/* Filter for simple class name changes Copyright (c) 2002-2009 The Regents of the University of California. All rights reserved. Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute this software and its documentation for any purpose, provided that the above copyright notice and the following two paragraphs appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. PT_COPYRIGHT_VERSION_2 COPYRIGHTENDKEY */ package ptolemy.moml.filter; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import ptolemy.kernel.util.NamedObj; import ptolemy.moml.MoMLFilter; import ptolemy.moml.MoMLParser; ////////////////////////////////////////////////////////////////////////// //// ClassChanges /** When this class is registered with the MoMLParser.setMoMLFilter() method, it will cause MoMLParser to filter so that models from earlier releases will run in the current release. <p>This class will filter moml for simple class changes where the context of the class name to be changed does not matter - all occurrences of the class name will be changed. This class can be though of as a primitive form of sed. <p> If a class within an actor is what has changed, use (@see PropertyClassChanges) instead. @author Christopher Hylands @version $Id$ @since Ptolemy II 2.0 @Pt.ProposedRating Red (cxh) @Pt.AcceptedRating Red (cxh) */ public class ClassChanges implements MoMLFilter { /** Clear the map of class renames and the set of class removals. */ public static void clear() { _classChanges = new HashMap(); _classesToRemove = new HashSet(); } /** If the attributeName is "class" and attributeValue names a * class that needs to be renamed, then substitute in the new class * name. If the attributeValue names a class that needs to be removed, * then return null, which will cause the MoMLParser to skip the * rest of the element; * * @param container The container for this attribute. * @param element The XML element name. * @param attributeName The name of the attribute. * @param attributeValue The value of the attribute. * @param xmlFile The file currently being parsed. * @return the value of the attributeValue argument. */ public String filterAttributeValue(NamedObj container, String element, String attributeName, String attributeValue, String xmlFile) { // This method gets called many times by the MoMLParser, // so we try to be smart about the number of comparisons // and we try to group comparisons together so that we // are not making the same comparison more than once. if (attributeValue == null) { // attributeValue == null is fairly common, so we check for // that first return null; } // If you change this class, you should run before and after // timing tests on large moml files, a good command to run // is: // $PTII/bin/ptolemy -test $PTII/ptolemy/domains/ct/demo/CarTracking/CarTracking.xml // which will open up a large xml file and then close after 2 seconds. if (attributeName.equals("class")) { if (_classChanges.containsKey(attributeValue)) { // We found a class with a class change. MoMLParser.setModified(true); return (String) _classChanges.get(attributeValue); } else if (_classesToRemove.contains(attributeValue)) { // We found a class to remove. return null; } } return attributeValue; } /** In this class, do nothing. * @param container The object created by this element. * @param elementName The element name. * @param currentCharData The character data, which appears * only in the doc and configure elements * @param xmlFile The file currently being parsed. * @exception Exception Not thrown in this base class. */ public void filterEndElement(NamedObj container, String elementName, StringBuffer currentCharData, String xmlFile) throws Exception { } /** Add a class to be filtered. Note that if you add a class with this * method, then you must remove it with {@link #remove(String)}, * calling "new ClassChanges()" will not remove a class that was * added with this method. * @param oldName The old name of the class to be filtered. * @param newName The new name of the class to be filtered. If * the value is null, then the class in oldName will be removed. * @see #remove(String) */ public void put(String oldName, String newName) { if (newName == null) { _classesToRemove.add(oldName); } else { _classChanges.put(oldName, newName); } } /** Remove a class to be filtered. * @param className The name of the class to be filtered * out, for example "ptolemy.copernicus.kernel.GeneratorAttribute". * @see #put(String, String) */ public void remove(String className) { if (_classChanges.containsKey(className)) { _classChanges.remove(className); } else if (_classesToRemove.contains(className)) { _classesToRemove.remove(className); } } /** Return a string that describes what the filter does. * @return the description of the filter that ends with a newline. */ public String toString() { StringBuffer results = new StringBuffer(getClass().getName() + ": change any class names that have been " + "renamed and remove obsolete classes.\n" + "Below are original class names followed by " + "the new class names:\n"); Iterator classNames = _classChanges.keySet().iterator(); while (classNames.hasNext()) { String className = (String) classNames.next(); results.append("\t" + className + "\t -> " + _classChanges.get(className) + "\n"); } results.append("\nBelow are the classes to remove:\n"); Iterator classesToRemove = _classesToRemove.iterator(); while (classesToRemove.hasNext()) { String className = (String) classesToRemove.next(); results.append("\t" + className + "\n"); } return results.toString(); } /////////////////////////////////////////////////////////////////// //// private variables //// // Map of actor names a HashMap of property names to new classes. private static HashMap _classChanges; static { /////////////////////////////////////////////////////////// // Actors and attributes that have changed names. _classChanges = new HashMap(); // Location _classChanges.put("ptolemy.moml.Location", "ptolemy.kernel.util.Location"); // New in 2.1-devel-2 _classChanges.put("ptolemy.kernel.util.VersionAttribute", "ptolemy.kernel.attributes.VersionAttribute"); // New in 2.3-devel _classChanges.put("ptolemy.actor.lib.comm.SerialComm", "ptolemy.actor.lib.io.comm.SerialComm"); // New in 3.1-devel _classChanges.put("ptolemy.domains.fsm.lib.RelationList", "ptolemy.domains.fsm.kernel.RelationList"); // Renamed in 3.1-devel _classChanges.put("ptolemy.vergil.icon.ImageEditorIcon", "ptolemy.vergil.icon.ImageIcon"); // Replaced FileAttribute with FileParameter in 3.2-devel _classChanges.put("ptolemy.kernel.attributes.FileAttribute", "ptolemy.data.expr.FileParameter"); // SDFIOPort is obsolete as of 3.2-devel _classChanges.put("ptolemy.domains.sdf.kernel.SDFIOPort", "ptolemy.actor.TypedIOPort"); // Moved MultiInstanceComposite _classChanges.put("ptolemy.actor.hoc.MultiInstanceComposite", "ptolemy.actor.lib.hoc.MultiInstanceComposite"); // Moved ModalModel _classChanges.put("ptolemy.vergil.fsm.modal.ModalModel", "ptolemy.domains.fsm.modal.ModalModel"); // Moved InterfaceAutomatonTransition _classChanges.put( "ptolemy.domains.fsm.kernel.InterfaceAutomatonTransition", "ptolemy.domains.fsm.kernel.ia.InterfaceAutomatonTransition"); // Moved InterfaceAutomatonTransition _classChanges.put("ptolemy.domains.fsm.kernel.InterfaceAutomaton", "ptolemy.domains.fsm.kernel.ia.InterfaceAutomaton"); // Moved InterfaceAutomatonTransition _classChanges.put( "ptolemy.domains.modal.kernel.InterfaceAutomatonTransition", "ptolemy.domains.modal.kernel.ia.InterfaceAutomatonTransition"); // Moved InterfaceAutomatonTransition _classChanges.put("ptolemy.domains.modal.kernel.InterfaceAutomaton", "ptolemy.domains.modal.kernel.ia.InterfaceAutomaton"); // Moved ModalTableauFactory _classChanges.put( "ptolemy.vergil.fsm.modal.ModalModel$ModalTableauFactory", "ptolemy.vergil.fsm.modal.ModalTableauFactory"); // Moved ModalPort _classChanges.put("ptolemy.vergil.fsm.modal.ModalPort", "ptolemy.domains.fsm.modal.ModalPort"); // Moved ModalController _classChanges.put("ptolemy.vergil.fsm.modal.ModalController", "ptolemy.domains.fsm.modal.ModalController"); // Moved Refinement _classChanges.put("ptolemy.vergil.fsm.modal.Refinement", "ptolemy.domains.fsm.modal.Refinement"); // Moved RefinementPort _classChanges.put("ptolemy.vergil.fsm.modal.RefinementPort", "ptolemy.domains.fsm.modal.RefinementPort"); // Moved TransitionRefinement _classChanges.put("ptolemy.vergil.fsm.modal.TransitionRefinement", "ptolemy.domains.fsm.modal.TransitionRefinement"); // Moved TransitionRefinementPort _classChanges.put("ptolemy.vergil.fsm.modal.TransitionRefinementPort", "ptolemy.domains.fsm.modal.TransitionRefinementPort"); // Moved IDAttribute from ptolemy.kernel.attributes to // ptolemy.vergil.kernel.atttributes _classChanges.put("ptolemy.kernel.attributes.IDAttribute", "ptolemy.vergil.kernel.attributes.IDAttribute"); _classChanges.put("ptolemy.domains.gr.lib.ViewScreen", "ptolemy.domains.gr.lib.ViewScreen3D"); _classChanges.put("ptolemy.domains.sr.lib.Latch", "ptolemy.domains.sr.lib.Current"); // Renamed VergilPreferences _classChanges.put("ptolemy.vergil.VergilPreferences", "ptolemy.actor.gui.PtolemyPreferences"); // Use FPScheduler instead of SROptimizedScheduler _classChanges.put("ptolemy.domains.sr.kernel.SROptimizedScheduler", "ptolemy.actor.sched.FixedPointScheduler"); // Moved HSFSMDirector _classChanges.put("ptolemy.domains.fsm.kernel.HSFSMDirector", "ptolemy.domains.ct.kernel.HSFSMDirector"); // Moved ParameterSet _classChanges.put("ptolemy.data.expr.ParameterSet", "ptolemy.actor.parameters.ParameterSet"); // ColtSeedParameter is obsolete _classChanges.put("ptolemy.actor.lib.colt.ColtSeedParameter", "ptolemy.moml.SharedParameter"); // 1/08: Moved SingleTokenCommutator so that DDF can extend it _classChanges.put("ptolemy.domains.sr.lib.SingleTokenCommutator", "ptolemy.actor.lib.SingleTokenCommutator"); // DependencyHighlighter is really a vergil class _classChanges.put("ptolemy.actor.gui.DependencyHighlighter", "ptolemy.vergil.basic.DependencyHighlighter"); _classChanges.put("ptolemy.moml.SharedParameter", "ptolemy.actor.parameters.SharedParameter"); _classChanges.put("ptolemy.actor.lib.gui.LEDMatrix", "ptolemy.vergil.actor.lib.LEDMatrix"); _classChanges.put("ptolemy.actor.lib.gui.ModelDisplay", "ptolemy.vergil.actor.lib.ModelDisplay"); _classChanges.put("ptolemy.domains.sr.lib.ButtonTime", "ptolemy.domains.sr.lib.gui.ButtonTime"); _classChanges.put("ptolemy.domains.sr.lib.NonStrictDisplay", "ptolemy.domains.sr.lib.gui.NonStrictDisplay"); _classChanges.put("ptolemy.actor.lib.CodegenActor", "ptolemy.actor.lib.jni.CodegenActor"); _classChanges.put("ptolemy.codegen.c.actor.lib.CodegenActor", "ptolemy.codegen.c.actor.lib.jni.CodegenActor"); _classChanges.put("ptolemy.codegen.kernel.Director", "ptolemy.codegen.actor.Director"); // Look for Kepler's NamedObjId, and if we don't find it, then // add it to the filter. This makes it much easier to open // Kepler models in Ptolemy. try { Class.forName("org.kepler.moml.NamedObjId"); } catch (ClassNotFoundException ex) { _classChanges.put("org.kepler.moml.NamedObjId", "ptolemy.kernel.util.StringAttribute"); } _classChanges.put("ptolemy.data.unit.UnitAttribute", "ptolemy.moml.unit.UnitAttribute"); _classChanges.put("ptolemy.domains.properties.LatticeElement", "ptolemy.domains.properties.kernel.LatticeElement"); _classChanges.put("ptolemy.domains.properties.LatticeElementIcon", "ptolemy.vergil.properties.LatticeElementIcon"); _classChanges.put("ptolemy.domains.properties.PropertyLatticeComposite", "ptolemy.domains.properties.kernel.PropertyLatticeComposite"); } // Set of class names that are obsolete and should be simply // removed. private static HashSet _classesToRemove; static { //////////////////////////////////////////////////////////// // Classes that are obsolete and should be removed. _classesToRemove = new HashSet(); // NotEditableParameter _classesToRemove.add("ptolemy.data.expr.NotEditableParameter"); //DEIOPort _classesToRemove.add("ptolemy.domains.de.kernel.DEIOPort"); // SROptimizedScheduler _classesToRemove.add("ptolemy.domains.sr.kernel.SROptimizedScheduler"); // SRRandomizedScheduler _classesToRemove.add("ptolemy.domains.sr.kernel.SRRandomizedScheduler"); } }