001/* Output a substring of the string provided at the input.
002
003 Copyright (c) 2003-2014 The Regents of the University of California.
004 All rights reserved.
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the above
008 copyright notice and the following two paragraphs appear in all copies
009 of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION_2
025 COPYRIGHTENDKEY
026
027 */
028package ptolemy.actor.lib.string;
029
030import ptolemy.actor.lib.Transformer;
031import ptolemy.actor.parameters.PortParameter;
032import ptolemy.data.BooleanToken;
033import ptolemy.data.IntToken;
034import ptolemy.data.StringToken;
035import ptolemy.data.expr.SingletonParameter;
036import ptolemy.data.type.BaseType;
037import ptolemy.kernel.CompositeEntity;
038import ptolemy.kernel.util.IllegalActionException;
039import ptolemy.kernel.util.NameDuplicationException;
040
041///////////////////////////////////////////////////////////////////
042//// StringSubstring
043
044/**
045 Output a substring of the string provided at the input.  The position of the
046 substring within the input string is determined by the <i>start</i> and
047 <i>stop</i> port parameters. Following Java convention, the character at
048 <i>start</i> is included, but the character at <i>stop</i> is not.
049 If the <i>stop</i> is less than <i>start</i>, then
050 the substring starts at <i>start</i> and extends to the end of the
051 string. The default values for <i>start</i> and <i>stop</i> are
052 both 0; this results in an empty string at the output.
053
054 @author Neil E. Turner and Edward A. Lee
055 @version $Id$
056 @since Ptolemy II 4.0
057 @Pt.ProposedRating Green (net)
058 @Pt.AcceptedRating Green (net)
059 */
060public class StringSubstring extends Transformer {
061    /** Construct an actor with the given container and name.
062     *  @param container The container.
063     *  @param name The name of this actor.
064     *  @exception IllegalActionException If the actor cannot be contained
065     *   by the proposed container.
066     *  @exception NameDuplicationException If the container already has an
067     *   actor with this name.
068     */
069    public StringSubstring(CompositeEntity container, String name)
070            throws NameDuplicationException, IllegalActionException {
071        super(container, name);
072
073        // Create new parameters and ports.
074        // Set default values of the parameters and type constraints.
075        start = new PortParameter(this, "start");
076        start.setExpression("0");
077        start.setTypeEquals(BaseType.INT);
078        new SingletonParameter(start.getPort(), "_showName")
079                .setToken(BooleanToken.TRUE);
080
081        stop = new PortParameter(this, "stop");
082        stop.setExpression("0");
083        stop.setTypeEquals(BaseType.INT);
084        new SingletonParameter(stop.getPort(), "_showName")
085                .setToken(BooleanToken.TRUE);
086
087        input.setTypeEquals(BaseType.STRING);
088        new SingletonParameter(input, "_showName").setToken(BooleanToken.TRUE);
089
090        output.setTypeEquals(BaseType.STRING);
091    }
092
093    ///////////////////////////////////////////////////////////////////
094    ////                     ports and parameters                  ////
095
096    /** The beginning index of the input string, which is the position of
097     *  first character of the desired substring.  Its default value is 0,
098     *  type int.
099     */
100    public PortParameter start;
101
102    /** The ending index of the input string, which is 1 greater than the
103     *  position of last letter of the desired substring.  Its default value
104     *  is 0, type int.
105     */
106    public PortParameter stop;
107
108    ///////////////////////////////////////////////////////////////////
109    ////                         public methods                    ////
110
111    /** If there is an input string, find a substring according to the indices
112     *  given by the port parameters <i>start</i> and <i>stop</i>
113     *  and produce the substring at the output.  If the <i>stop</i>
114     *  is -1 , then the substring starts at <i>start</i> and extends to
115     *  the end of the string.  In the event that the indices do not exist in
116     *  the input string, throw IndexOutOfBoundsException.
117     *  @exception IllegalActionException If the superclass throws it, or
118     *   if it is thrown reading the input port or writing to the output port.
119     */
120    @Override
121    public void fire() throws IllegalActionException {
122        super.fire();
123        start.update();
124        stop.update();
125
126        if (input.hasToken(0)) {
127            StringToken inputToken = (StringToken) input.get(0);
128            String value = inputToken.stringValue();
129            int startValue = ((IntToken) start.getToken()).intValue();
130            int stopValue = ((IntToken) stop.getToken()).intValue();
131            String substringValue;
132
133            if (stopValue < startValue) {
134                if (value.length() < startValue) {
135                    throw new IllegalActionException(this,
136                            "Cannot compute substring of " + "\"" + value + "\""
137                                    + " starting at " + startValue);
138                }
139                substringValue = value.substring(startValue);
140            } else {
141                if (value.length() < stopValue || startValue < 0) {
142                    throw new IllegalActionException(this,
143                            "Cannot compute substring of " + "\"" + value
144                                    + "\" between " + startValue + " and "
145                                    + stopValue);
146                }
147                substringValue = value.substring(startValue, stopValue);
148            }
149
150            output.send(0, new StringToken(substringValue));
151        }
152    }
153}