001/* A token that contains an array of tokens.
002
003 Copyright (c) 1997-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.data;
029
030import ptolemy.data.type.Type;
031import ptolemy.data.type.TypeLattice;
032import ptolemy.kernel.util.IllegalActionException;
033import ptolemy.kernel.util.InternalErrorException;
034
035///////////////////////////////////////////////////////////////////
036//// UpdatedArrayToken
037
038/**
039 A token that contains an array of tokens that is equal to another
040 specified ArrayToken except at one location, where it has a new
041 value. This implementation keeps a reference to the other specified
042 token and records only the diff between this modified array and the
043 original one.
044 <p>
045 This technique is inspired by a similar technique of storing diffs
046 described by Michael Isard in a talk at Berkeley in February, 2012.
047
048 @author Edward A. Lee
049 @version $Id$
050 @since Ptolemy II 10.0
051 @Pt.ProposedRating Yellow (cxh)
052 @Pt.AcceptedRating Red (cxh) nil token code
053 */
054public class UpdatedArrayToken extends ArrayToken {
055    /** Construct an UpdatedArrayToken that is equal to the specified
056     *  <i>baseToken</i>, except at <i>index</i>, where its value is
057     *  <i>newValue</i>.
058     *  The type of the resulting array type is the least upper bound
059     *  of the types of the elements, which is not necessarily the same
060     *  as the type of the base token.
061     *  @param baseToken The base array.
062     *  @param index The index of the new value.
063     *  @param newValue The updated value.
064     *  @exception IllegalActionException If the index is out of range
065     *   for the base token.
066     */
067    public UpdatedArrayToken(ArrayToken baseToken, int index, Token newValue)
068            throws IllegalActionException {
069        super(baseToken.getElementType());
070        if (index >= baseToken.length()) {
071            throw new IllegalActionException("Index " + index + " is out of "
072                    + "range for the array of length " + baseToken.length());
073
074        }
075        _baseToken = baseToken;
076        _index = index;
077        _newValue = newValue;
078
079        Type newValueType = newValue.getType();
080        Type baseType = baseToken.getElementType();
081        _elementType = TypeLattice.leastUpperBound(newValueType, baseType);
082        _newValue = _elementType.convert(_newValue);
083
084        _depth = _baseToken._depth + 1;
085    }
086
087    ///////////////////////////////////////////////////////////////////
088    ////                         public methods                    ////
089
090    // FindBugs says "Class doesn't override equals in superclass," but
091    // that's ok here.  See the tests in test/UpdatedArrayToken.tcl
092
093    /** Return the element at the specified index.
094     *  @param index The index of the desired element.
095     *  @return The token contained in this array token at the
096     *  specified index.
097     *  @exception ArrayIndexOutOfBoundsException If the specified index is
098     *   outside the range of the token array.
099     */
100    @Override
101    public Token getElement(int index) {
102        if (index == _index) {
103            return _newValue;
104        }
105        try {
106            return _elementType.convert(_baseToken.getElement(index));
107        } catch (IllegalActionException e) {
108            // This should not happen because _elementType is an upper bound.
109            throw new InternalErrorException(e);
110        }
111    }
112
113    /** Return the length of the contained token array.
114     *  @return The length of the contained token array.
115     */
116    @Override
117    public int length() {
118        return _baseToken.length();
119    }
120
121    ///////////////////////////////////////////////////////////////////
122    ////                         private variables                 ////
123
124    /** The base array. */
125    private ArrayToken _baseToken;
126
127    /** The index of the updated value. */
128    private int _index;
129
130    /** The one updated value. */
131    private Token _newValue;
132}