001/* Filter for removing properties.
002
003 Copyright (c) 2004-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.moml.filter;
029
030import java.util.HashMap;
031import java.util.Iterator;
032import java.util.Map;
033
034import ptolemy.kernel.util.NamedObj;
035import ptolemy.moml.MoMLParser;
036
037///////////////////////////////////////////////////////////////////
038//// RemoveProperties
039
040/** When this class is registered with the MoMLParser.setMoMLFilter()
041 method, it will cause MoMLParser to filter out the properties included
042 in this classes.
043
044 <p>For example, after Ptolemy II 5.0, the <i>stopTime</i> parameter has a
045 default value as Infinity instead of MaxDouble (a macro with value of
046 Double.MAX_VALUE). What is more, stopTime is not supposed to be stored in
047 the MoML file. Therefore, this filter filters out those stopTime parameters
048 with the old default value, MaxDouble. The new default value for the
049 stopTime parameter will be created automatically by the Java classes and
050 the parameter will not be exported into the MoML file.
051 <p>
052 A typical usage looks like the following.
053 <pre>
054 // stopTime after Ptolemy II 5.0
055 // The stopTime used to have a default value as the Double.MAX_VALUE.
056 // Now the default value is Infinity.
057 HashMap removePropertyStopTime = new HashMap();
058
059 // Remove properties whose name is "stopTime" if their
060 // class and value properties are in the HashMap.
061 _propertiesToBeRemoved.put("stopTime", removePropertyStopTime);
062
063 // The class must be a Parameter for this to be removed.
064 removePropertyStopTime.put("ptolemy.data.expr.Parameter", null);
065
066 // The value must be one of the following representations of Double.MAX_VALUE.
067 removePropertyStopTime.put("1.7976931348623E308", null);
068 removePropertyStopTime.put("1.797693134862316E308", null);
069 removePropertyStopTime.put("MaxDouble", null);
070 removePropertyStopTime.put(""+Double.MAX_VALUE, null);
071
072 </pre>
073 The removePropertyStopTime HashMap stores all possible matches of the name
074 and class attributes of the MoML entry for this attribute. Given MoML with
075 both a class and a value, then both must match for the property to
076 be removed.
077
078 The _propertiesToBeRemoved HashMap contains all the properties
079 such as the stopTime parameter that will be removed.
080
081 <p> Note that this filter has a limitation. This filter assumes that the
082 property to be removed always has three attributes, name, class, and
083 value, and they are always in this order.
084
085 @author Haiyang Zheng
086 @version $Id$
087 @since Ptolemy II 4.1
088 @Pt.ProposedRating Red (hyzheng)
089 @Pt.AcceptedRating Red (hyzheng)
090 */
091public class RemoveProperties extends MoMLFilterSimple {
092    /** Return the old attribute value for properties that are not registered
093     *  to be removed. Otherwise, return null to remove the property.
094     *  @param container  The container for this attribute.
095     *  @param element The XML element name.
096     *  @param attributeName The name of the attribute.
097     *  @param attributeValue The value of the attribute.
098     *  @param xmlFile The file currently being parsed.
099     *  @return The value of the attributeValue argument.
100     */
101    @Override
102    public String filterAttributeValue(NamedObj container, String element,
103            String attributeName, String attributeValue, String xmlFile) {
104        //System.out.println("RemoveProperties.filterAttributeValue: " + container + "\t"
105        //   +  attributeName + "\t" + attributeValue);
106        if (attributeValue == null) {
107            // attributeValue == null is fairly common, so we check for
108            // that first.
109            return null;
110        }
111
112        if (attributeName.equals("name")) {
113            if (_propertiesToBeRemoved.containsKey(attributeValue)
114                    && element != null && element.equals("property")) {
115                _foundPropertyToBeRemoved = true;
116                _propertyMap = (HashMap) _propertiesToBeRemoved
117                        .get(attributeValue);
118            } else {
119                _foundPropertyToBeRemoved = false;
120            }
121        }
122
123        if (attributeName.equals("class") && _foundPropertyToBeRemoved) {
124            if (_propertyMap.containsKey(attributeValue)) {
125                _propertyToBeRemovedConfirmed = true;
126            } else {
127                _foundPropertyToBeRemoved = false;
128                _propertyToBeRemovedConfirmed = false;
129            }
130        }
131
132        if (attributeName.equals("value") && _propertyToBeRemovedConfirmed) {
133            if (_propertyMap.containsKey(attributeValue)) {
134                String newValue = (String) _propertyMap.get(attributeValue);
135
136                if (!attributeValue.equals(newValue)) {
137                    MoMLParser.setModified(true);
138                }
139
140                _foundPropertyToBeRemoved = false;
141                _propertyToBeRemovedConfirmed = false;
142                return newValue;
143            } else {
144                _foundPropertyToBeRemoved = false;
145                _propertyToBeRemovedConfirmed = false;
146            }
147        }
148
149        return attributeValue;
150    }
151
152    /** Reset private variables.
153     *  @param container The object created by this element.
154     *  @param elementName The element name.
155     *  @param currentCharData The character data, which appears
156     *   only in the doc and configure elements
157     *  @param xmlFile The file currently being parsed.
158     *  @exception Exception if there is a problem substituting
159     *  in the new value.
160     */
161    @Override
162    public void filterEndElement(NamedObj container, String elementName,
163            StringBuffer currentCharData, String xmlFile) throws Exception {
164        _foundPropertyToBeRemoved = false;
165        _propertyToBeRemovedConfirmed = false;
166    }
167
168    /** Return a string that describes what the filter does.
169     *  @return the description of the filter that ends with a newline.
170     */
171    @Override
172    public String toString() {
173        StringBuffer results = new StringBuffer(
174                getClass().getName() + ": Remove the properties listed below:");
175        Iterator propertiesToBeRemoved = _propertiesToBeRemoved.keySet()
176                .iterator();
177
178        while (propertiesToBeRemoved.hasNext()) {
179            String propertyToBeRemoved = (String) propertiesToBeRemoved.next();
180            results.append("\t" + propertyToBeRemoved + "\n");
181
182            HashMap propertyMap = (HashMap) _propertiesToBeRemoved
183                    .get(propertyToBeRemoved);
184            Iterator attributeMapEntries = propertyMap.entrySet().iterator();
185
186            while (attributeMapEntries.hasNext()) {
187                Map.Entry attributes = (Map.Entry) attributeMapEntries.next();
188                String oldAttribute = (String) attributes.getKey();
189                String newAttribute = (String) attributes.getValue();
190                results.append(
191                        "\t\t" + oldAttribute + "\t -> " + newAttribute + "\n");
192            }
193        }
194
195        return results.toString();
196    }
197
198    ///////////////////////////////////////////////////////////////////
199    ////                         private variables                 ////
200    // Map of the properties to be removed.
201    private static HashMap _propertiesToBeRemoved;
202
203    // Flag indicating whether a property to be removed is truly found.
204    private boolean _propertyToBeRemovedConfirmed = false;
205
206    // Flag indicating whether a potential property to be removed is found.
207    private boolean _foundPropertyToBeRemoved = false;
208
209    // Cache of map from the property to be removed to its detailed information.
210    private HashMap _propertyMap;
211
212    static {
213        ///////////////////////////////////////////////////////////
214        // The properties to be removed.
215        _propertiesToBeRemoved = new HashMap();
216
217        // For the stopTime parameter after Ptolemy II 5.0, if the stop time
218        // parameter has an old default value, remove it.
219        // The stopTime used to have a default value as the Double.MAX_VALUE.
220        // Now the default value is Infinity.
221        HashMap removePropertyStopTime = new HashMap();
222
223        // Key = attribute name, Value = attribute value
224        removePropertyStopTime.put("1.7976931348623E308", null);
225        removePropertyStopTime.put("1.797693134862316E308", null);
226        removePropertyStopTime.put("MaxDouble", null);
227        removePropertyStopTime.put("" + Double.MAX_VALUE, null);
228
229        removePropertyStopTime.put("ptolemy.data.expr.Parameter", null);
230
231        _propertiesToBeRemoved.put("stopTime", removePropertyStopTime);
232
233        // A property named "directorClass" that is a StringAttribute
234        // or StringParameter with value "ptolemy.domains.fsm.kernel.HSDirector"
235        // will be removed. HSDirector no longer exists, so we revert
236        // to the default.
237        HashMap removePropertyDirectorClass = new HashMap();
238
239        // Key = attribute name, Value = attribute value
240        removePropertyDirectorClass.put("ptolemy.domains.fsm.kernel.HSDirector",
241                null);
242        removePropertyDirectorClass.put("ptolemy.kernel.util.StringAttribute",
243                null);
244        removePropertyDirectorClass.put("ptolemy.data.expr.StringParameter",
245                null);
246
247        _propertiesToBeRemoved.put("directorClass",
248                removePropertyDirectorClass);
249    }
250}