001/* A RelationList object contains the information of the relations of a
002 guard expression.
003
004 Copyright (c) 2003-2013 The Regents of the University of California.
005 All rights reserved.
006 Permission is hereby granted, without written agreement and without
007 license or royalty fees, to use, copy, modify, and distribute this
008 software and its documentation for any purpose, provided that the above
009 copyright notice and the following two paragraphs appear in all copies
010 of this software.
011
012 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
013 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
014 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
015 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
016 SUCH DAMAGE.
017
018 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
020 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
021 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
022 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
023 ENHANCEMENTS, OR MODIFICATIONS.
024
025 PT_COPYRIGHT_VERSION_2
026 COPYRIGHTENDKEY
027 */
028package ptolemy.domains.modal.kernel;
029
030import java.util.LinkedList;
031import java.util.ListIterator;
032
033///////////////////////////////////////////////////////////////////
034//// RelationList
035
036/**
037 A RelationList object contains a list of relations of a guard expression.
038 Relations are comparison operations, for example "x ≥ 10", where x is
039 a variable.  This class provides facilities for measuring how far the
040 expression is from the threshold; for example, if x = 7, then the
041 distance to the threshold is 3.  Moreover, it provides a mechanism
042 for recording the current distance (via a "commit") and then later
043 accessing that distance and comparing it against the current distance.
044 The information
045 includes relation type and the difference information. (See
046 {@link ParseTreeEvaluatorForGuardExpression} for the detailed explanation
047 of relation type and difference.) This attribute is non-persistent and will
048 not be exported into MoML.
049 <p>
050 This class is designed to be used with ParseTreeEvaluatorForGuardExpression.
051 The common usage would be like:
052 <p>
053 <i>Construct a relation list for a transition with the first argument of the
054 constructor as that transition.</i>
055 <pre>
056 _relationList = new RelationList();
057 </pre>
058 <p>
059 <i>Associate the relation list with the an object of
060 ParseTreeEvaluatorForGuardExpression</i>
061 <pre>
062 _parseTreeEvaluator =
063 new ParseTreeEvaluatorForGuardExpression(_relationList, getErrorTolerance());
064 </pre>
065 <p>
066 See {@link Transition} for the detailed usage.
067
068 @author Haiyang Zheng
069 @version $Id$
070 @since Ptolemy II 8.0
071 @Pt.ProposedRating Yellow (hyzheng)
072 @Pt.AcceptedRating Red (hyzheng)
073 */
074public class RelationList {
075    /** Construct a relation list.
076     */
077    public RelationList() {
078        _relationList = new LinkedList();
079    }
080
081    ///////////////////////////////////////////////////////////////////
082    ////                         public methods                    ////
083
084    /** Construct a relation node with the given type and difference
085     *  information of a relation, and add it to the end of the relation
086     *  list.
087     *  @param type The relation type of the relation.
088     *  @param difference The difference of the relation.
089     */
090    public void addRelation(int type, double difference) {
091        _relationList.add(new RelationNode(type, difference));
092    }
093
094    /** Reset the relation list by resetting each relation node.
095     */
096    public void resetRelationList() {
097        ListIterator relations = _relationList.listIterator();
098        while (relations.hasNext()) {
099            ((RelationNode) relations.next()).reset();
100        }
101    }
102
103    /** Record the current relation values so that when getPreviousMaximumDistance()
104     *  is called, these recorded values are used.
105     *  @see #getPreviousMaximumDistance()
106     */
107    public void commitRelationValues() {
108        ListIterator relations = _relationList.listIterator();
109        while (relations.hasNext()) {
110            ((RelationNode) relations.next()).commit();
111        }
112    }
113
114    /** Destroy the relation list by deleting all the contained elements.
115     */
116    public void destroy() {
117        _relationList.clear();
118    }
119
120    /** Return the previous difference of the relation that has the
121     *  maximum current difference.  This is the value as of the last
122     *  call to commitRelationValues().
123     *  @see #commitRelationValues()
124     *  @return The previous distance of a relation.
125     */
126    public double getPreviousMaximumDistance() {
127        return ((RelationNode) _relationList.get(_maximumDifferenceIndex))
128                .getPreviousDifference();
129    }
130
131    /** Return true if there exists an event caused by the type change of
132     *  any relation.
133     *  @return True If there exits an event.
134     */
135    public boolean hasEvent() {
136        boolean result = false;
137        ListIterator relations = _relationList.listIterator();
138        while (relations.hasNext() && !result) {
139            result = result || ((RelationNode) relations.next()).hasEvent();
140        }
141        return result;
142    }
143
144    /** Return true if the relation list is empty.
145     *  @return True If the relation list is empty.
146     */
147    public boolean isEmpty() {
148        return _relationList.size() == 0;
149    }
150
151    /** Return the number of relations in the relation list.
152     *  @return the number of relations in the relation list.
153     */
154    public int length() {
155        return _relationList.size();
156    }
157
158    /** Return the maximum current difference of all the relations by iterating
159     *  the relation list.
160     *  @return maximumDistance The maximum current distance.
161     */
162    public double getMaximumDifference() {
163        double maxDifference = 0.0;
164        double difference = 0.0;
165        int index = 0;
166        _maximumDifferenceIndex = 0;
167        ListIterator relations = _relationList.listIterator();
168        while (relations.hasNext()) {
169            RelationNode relation = (RelationNode) relations.next();
170            difference = Math.abs(relation.getDifference());
171            if (relation.typeChanged() && difference > maxDifference) {
172                maxDifference = difference;
173                _maximumDifferenceIndex = index;
174            }
175            index++;
176        }
177        return maxDifference;
178    }
179
180    /** Update the relation in the relation list referred by the
181     *  relation index argument with the given type and difference
182     *  information.
183     *  @param relationIndex The position of the relation in the
184     *  relation list.
185     *  @param type The current type of the relation.
186     *  @param difference The current difference of the relation.
187     */
188    public void setRelation(int relationIndex, int type, double difference) {
189        RelationNode relationNode = (RelationNode) _relationList
190                .get(relationIndex);
191        relationNode.setType(type);
192        relationNode.setDifference(difference);
193    }
194
195    ///////////////////////////////////////////////////////////////////
196    ////                         private fields                    ////
197    // The index for the relation with the maximum current difference.
198    private int _maximumDifferenceIndex;
199
200    // The relation list.
201    private LinkedList _relationList;
202}