001/* Remove classes not compatible with Ptiny
002
003 Copyright (c) 2009-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;
032
033import ptolemy.kernel.util.NamedObj;
034import ptolemy.moml.MoMLParser;
035import ptolemy.util.StringUtilities;
036
037///////////////////////////////////////////////////////////////////
038//// RemoveNonPtinyClasses
039
040/**
041 Remove classes such as code generators that are not present in Ptiny.
042
043 <p> When this class is registered with the MoMLParser.setMoMLFilter()
044 method, it will cause MoMLParser to filter out classes that are
045 not present in the Ptiny configuration.
046
047 @author  Christopher Hylands
048 @version $Id$
049 @since Ptolemy II 8.0
050 @Pt.ProposedRating Red (cxh)
051 @Pt.AcceptedRating Red (cxh)
052 */
053public class RemoveNonPtinyClasses extends MoMLFilterSimple {
054    /** Clear the map of graphical classes to be removed.
055     */
056    public static void clear() {
057        _nonPtinyClasses = new HashMap();
058    }
059
060    /** Filter for graphical classes and return new values if
061     *  a graphical class is found.
062     *  An internal HashMap maps names of graphical entities to
063     *  new names.  The HashMap can also map a graphical entity
064     *  to null, which means the entity is removed from the model.
065     *  All class attributeValues that start with "ptolemy.domains.gr"
066     *  are deemed to be graphical elements and null is always returned.
067     *  For example, if the attributeValue is "ptolemy.vergil.icon.ValueIcon",
068     *  or "ptolemy.vergil.basic.NodeControllerFactory"
069     *  then return "ptolemy.kernel.util.Attribute"; if the attributeValue
070     *  is "ptolemy.vergil.icon.AttributeValueIcon" or
071     *  "ptolemy.vergil.icon.BoxedValueIcon" then return null, which
072     *  will cause the MoMLParser to skip the rest of the element;
073     *  otherwise return the original value of the attributeValue.
074     *
075     *  @param container  The container for this attribute, ignored
076     *  in this method.
077     *  @param element The XML element name.
078     *  @param attributeName The name of the attribute, ignored
079     *   in this method.
080     *  @param attributeValue The value of the attribute.
081     *  @param xmlFile The file currently being parsed.
082     *  @return the filtered attributeValue.
083     */
084    @Override
085    public String filterAttributeValue(NamedObj container, String element,
086            String attributeName, String attributeValue, String xmlFile) {
087        // If the nightly build is failing with messages like:
088        // " X connection to foo:0 broken (explicit kill or server shutdown)."
089        // Try uncommenting the next lines to see what is being
090        // expanding before the error:
091        //System.out.println("filterAttributeValue: " + container + "\t"
092        //       +  attributeName + "\t" + attributeValue);
093        if (attributeValue == null) {
094            return null;
095        } else if (_nonPtinyClasses.containsKey(attributeValue)) {
096            return (String) _nonPtinyClasses.get(attributeValue);
097        }
098
099        return attributeValue;
100    }
101
102    /** In this class, do nothing.
103     *  @param container The object created by this element.
104     *  @param elementName The element name.
105     *  @param currentCharData The character data, which appears
106     *   only in the doc and configure elements
107     *  @param xmlFile The file currently being parsed.
108     *  @exception Exception Not thrown in this base class.
109     */
110    @Override
111    public void filterEndElement(NamedObj container, String elementName,
112            StringBuffer currentCharData, String xmlFile) throws Exception {
113    }
114
115    /** Read in a MoML file, remove graphical classes and
116     *  write the results to standard out.
117     *  <p> For example, to remove the graphical classes from
118     *  a file called <code>RemoveGraphicalClasses.xml</code>
119     *  <pre>
120     *  java -classpath "$PTII" ptolemy.moml.filter.RemoveGraphicalClasses test/RemoveGraphicalClasses.xml &gt; output.xml
121     *  </pre>
122     *  @param args An array of one string
123     *  <br> The name of the MoML file to be cleaned.
124     *  @exception Exception If there is a problem reading or writing
125     *  a file.
126     */
127    public static void main(String[] args) throws Exception {
128        try {
129            MoMLParser parser = new MoMLParser();
130
131            // The list of filters is static, so we reset it in case there
132            // filters were already added.
133            MoMLParser.setMoMLFilters(null);
134
135            // Add the backward compatibility filters.
136            MoMLParser.setMoMLFilters(BackwardCompatibility.allFilters());
137
138            MoMLParser.addMoMLFilter(new RemoveGraphicalClasses());
139            MoMLParser.addMoMLFilter(new HideAnnotationNames());
140            MoMLParser.addMoMLFilter(new RemoveNonPtinyClasses());
141            NamedObj topLevel = parser.parseFile(args[0]);
142            System.out.println(topLevel.exportMoML());
143        } catch (Throwable throwable) {
144            System.err.println("Failed to filter \"" + args[0] + "\"");
145            throwable.printStackTrace();
146            StringUtilities.exit(1);
147        }
148    }
149
150    /** Remove a class to be filtered.
151     *  @param className The name of the class to be filtered
152     *  out, for example "ptolemy.copernicus.kernel.GeneratorAttribute".
153     *  @see #put(String, String)
154     */
155    public void remove(String className) {
156        // ptolemy.copernicus.kernel.MakefileGenerator
157        // so as to filter out the GeneratorAttribute
158        _nonPtinyClasses.remove(className);
159    }
160
161    /** Add a class to be filtered for and its replacement if the class
162     *  is found.  If the replacement is null, then the rest of the
163     *  attribute is skipped.  Note that if you add a class with
164     *  this method, then you must remove it with {@link #remove(String)},
165     *  calling 'new RemoveNonPtinyClasses' will not remove a class
166     *  that was added with this method.
167     *  @param className The name of the class to be filtered
168     *  out, for example "ptolemy.copernicus.kernel.GeneratorAttribute".
169     *  @param replacement The name of the class to be used if
170     *  className is found.  If this argument is null then the
171     *  rest of the attribute is skipped.
172     *  @see #remove(String)
173     */
174    public void put(String className, String replacement) {
175        // ptolemy.copernicus.kernel.KernelMain call this method
176        // so as to filter out the GeneratorAttribute
177        _nonPtinyClasses.put(className, replacement);
178    }
179
180    /** Return a string that describes what the filter does.
181     *  @return the description of the filter that ends with a newline.
182     */
183    @Override
184    public String toString() {
185        StringBuffer results = new StringBuffer(getClass().getName()
186                + ": Remove classes such as code generators that are "
187                + "not present in Ptiny.");
188        Iterator classNames = _nonPtinyClasses.keySet().iterator();
189
190        while (classNames.hasNext()) {
191            String oldClassName = (String) classNames.next();
192            String newClassName = (String) _nonPtinyClasses.get(oldClassName);
193
194            if (newClassName == null) {
195                results.append(oldClassName + " will be removed\n");
196            } else {
197                results.append(oldClassName + " will be replaced by "
198                        + newClassName + "\n");
199            }
200        }
201
202        return results.toString();
203    }
204
205    ///////////////////////////////////////////////////////////////////
206    ////                         private variables                 ////
207
208    /** Map of actor names a HashMap of non-ptiny classes to their
209     *  counterparts, usually either ptolemy.kernel.util.Attribute or
210     *  null.
211     */
212    private static HashMap _nonPtinyClasses;
213
214    static {
215        _nonPtinyClasses = new HashMap();
216
217        // Alphabetical by key class
218        // We can convert any graphical classes that have a port named "input" to
219        // a Discard actor.  However, classes like XYPlot have ports named "X" and Y",
220        // so XYPlot cannot be converted.
221        _nonPtinyClasses.put(
222                "ptolemy.codegen.kernel.StaticSchedulingCodeGenerator", null);
223    }
224}