001/* Filter for Property class changes
002
003 Copyright (c) 2002-2015 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//// PropertyClassChanges
039
040/** When this class is registered with the MoMLParser.setMoMLFilter()
041 method, it will cause MoMLParser to filter so that models from
042 earlier releases will run in the current release.
043
044 <p>This class will filter for classes with properties where the class
045 name has changed.
046
047 <p>For example, after Ptolemy II 2.0.1, the Expression actor
048 changed in such a way that the expression property changed from
049 being a Parameter to being a StringAttribute.  To add this
050 change to this filter, we add a code to the static section at
051 the bottom of the file.
052 <pre>
053 // Expression: After 2.0.1, expression
054 // property is now a StringAttribute
055 HashMap expressionClassChanges = new HashMap();
056 // Key = property name, Value = new class name
057 expressionClassChanges.put("expression",
058 "ptolemy.kernel.util.StringAttribute");
059 </pre>
060 The expressionClassChange HashMap maps property names to the new
061 classname
062
063 <pre>
064
065 _actorsWithPropertyClassChanges
066 .put("ptolemy.actor.lib.Expression",
067 expressionClassChanges);
068 </pre>
069 The _actorsWithPropertyClassChanges HashMap contains all the classes
070 such as Expression that have changes and each class has a map
071 of the property changes that are to be made.
072
073 <p> Conceptually, how the code works is that when we see a class while
074 parsing, we check to see if the class is in _actorsWithPropertyClassChanges.
075 If the class was present in the HashMap, then as we go through the
076 code, we look for property names that need to have their classes changed.
077
078
079 @author Christopher Hylands, Edward A. Lee
080 @version $Id$
081 @since Ptolemy II 2.0
082 @Pt.ProposedRating Red (cxh)
083 @Pt.AcceptedRating Red (cxh)
084 */
085public class PropertyClassChanges extends MoMLFilterSimple {
086    /** Clear the map of actors with property class changes.
087     */
088    public static void clear() {
089        _actorsWithPropertyClassChanges = new HashMap();
090    }
091
092    /** Return new class names for properties that have been
093     *  registered as having changed classes. This filter
094     *  may also return null to remove the element.
095     *  @param container  The container for this attribute.
096     *  in this method.
097     *  @param element The XML element name.
098     *  @param attributeName The name of the attribute.
099     *  @param attributeValue The value of the attribute.
100     *  @param xmlFile The file currently being parsed.
101     *  @return The value of the attributeValue argument or
102     *   a new value if the value has changed.
103     */
104    @Override
105    public String filterAttributeValue(NamedObj container, String element,
106            String attributeName, String attributeValue, String xmlFile) {
107        // If you change this class, you should run before and after
108        // timing tests on large moml files, a good command to run
109        // is:
110        // $PTII/bin/ptolemy -test $PTII/ptolemy/domains/ct/demo/CarTracking/CarTracking.xml
111        // which will open up a large xml file and then close after 2 seconds.
112        //System.out.println("<---filterAttributeValue: " + container + "\t"
113        //           +  attributeName + "\t" + attributeValue);
114        // This method gets called many times by the MoMLParser,
115        // so we try to be smart about the number of comparisons
116        // and we try to group comparisons together so that we
117        // are not making the same comparison more than once.
118        if (attributeValue == null) {
119            // attributeValue == null is fairly common, so we check for
120            // that first
121            return null;
122        }
123
124        if (attributeName.equals("name")) {
125            // Save the name of the attribute for later use if we see a "class"
126            _lastNameSeen = attributeValue;
127
128            //             System.out.println("<---filterAttributeValue: " + container + "\t"
129            //                     +  attributeName + "\t" + attributeValue
130            //                     + "fav0.5: lastNameSeen: " + _lastNameSeen);
131            if (_currentlyProcessingActorWithPropertyClassChanges
132                    && element != null && element.equals("property")) {
133                if (_propertyMap.containsKey(attributeValue)) {
134                    // We will do the above checks only if we found a
135                    // class that had property class changes.
136                    //                     System.out.println("<---filterAttributeValue: " + container + "\t"
137                    //                             +  attributeName + "\t" + attributeValue
138                    //                             + "fav1: foundChange");
139                    _newClass = (String) _propertyMap.get(attributeValue);
140                    _foundChange = true;
141                } else {
142                    // Saw a name that did not match.
143                    // However, we might have other names that
144                    // did match, so keep looking
145                    //_currentlyProcessingActorWithPropertyClassChanges = false;
146                    //                     System.out.println("<---filterAttributeValue: " + container + "\t"
147                    //                             +  attributeName + "\t" + attributeValue
148                    //                             + "fav2: non-matching name");
149
150                    _newClass = null;
151                    _foundChange = false;
152                }
153            }
154        }
155
156        if (attributeName.equals("class")) {
157            if (_currentlyProcessingActorWithPropertyClassChanges
158                    && _foundChange) {
159                if (container != null
160                        && !container.getFullName()
161                                .equals(_currentActorFullName)
162                        && !container.getFullName()
163                                .substring(0,
164                                        container.getFullName()
165                                                .lastIndexOf("."))
166                                .equals(_currentActorFullName)
167
168                ) {
169                    // This is fix for an unusual bug involving
170                    // space.Occupant.
171                    // See test 1.1 in test/PropertyClassChanges.tcl
172                    _currentlyProcessingActorWithPropertyClassChanges = false;
173                    _newClass = null;
174                    _foundChange = false;
175                    //                     System.out.println("<---filterAttributeValue: " + container + "\t"
176                    //                             +  attributeName + "\t" + attributeValue
177                    //                             + "fav3: Did not match, returning " + attributeValue);
178
179                    return attributeValue;
180                }
181
182                // This if clause needs to be first so that we handle
183                // the PropertyClassChanges case where we have a
184                // _tableauFactory in a ModalModel that is not
185                // a ModalTableauFactory, but should be.  An example
186                // of this is ct/demo/Pendulum3D/Pendulum3D.xml.
187                String temporaryNewClass = _newClass;
188
189                if (!attributeValue.equals(_newClass)) {
190                    MoMLParser.setModified(true);
191                }
192
193                _newClass = null;
194                _foundChange = false;
195                //                     System.out.println("<---filterAttributeValue: " + container + "\t"
196                //                             +  attributeName + "\t" + attributeValue
197                //                             + "fav4, returning temporaryNewClass" + temporaryNewClass);
198
199                return temporaryNewClass;
200            } else if (_actorsWithPropertyClassChanges
201                    .containsKey(attributeValue)) {
202                //                     System.out.println("<---filterAttributeValue: " + container + "\t"
203                //                             +  attributeName + "\t" + attributeValue
204                //                             + "fav4.5, found a class with a property class change");
205
206                // We found a class with a property class change.
207                _currentlyProcessingActorWithPropertyClassChanges = true;
208
209                if (container != null) {
210                    _currentActorFullName = container.getFullName() + "."
211                            + _lastNameSeen;
212                } else {
213                    _currentActorFullName = "." + _lastNameSeen;
214                }
215
216                //                     System.out.println("<---filterAttributeValue: " + container + "\t"
217                //                             +  attributeName + "\t" + attributeValue
218                //                             + "fav5: found a class with a prop class change");
219
220                _propertyMap = (HashMap) _actorsWithPropertyClassChanges
221                        .get(attributeValue);
222            } else if (_currentlyProcessingActorWithPropertyClassChanges
223                    && container != null
224                    && !container.getFullName().equals(_currentActorFullName)
225                    /*&& !container.getFullName().substring(0,
226                      container.getFullName().lastIndexOf(".")).equals(_currentActorFullName)*/
227                    && !container.getFullName()
228                            .startsWith(_currentActorFullName)) {
229                // We found another class in a different container
230                // while handling a class with port name changes
231                //                     System.out.println("<---filterAttributeValue: " + container + "\t"
232                //                             +  attributeName + "\t" + attributeValue
233                //                             + "fav6: found another class in diff container");
234
235                _currentlyProcessingActorWithPropertyClassChanges = false;
236            }
237        }
238
239        return attributeValue;
240    }
241
242    /** Reset private variables.
243     *  @param container The object created by this element.
244     *  @param elementName The element name.
245     *  @param currentCharData The character data, which appears
246     *   only in the doc and configure elements
247     *  @param xmlFile The file currently being parsed.
248     *  @exception Exception if there is a problem substituting
249     *  in the new value.
250     */
251    @Override
252    public void filterEndElement(NamedObj container, String elementName,
253            StringBuffer currentCharData, String xmlFile) throws Exception {
254        //            System.out.println("<---filterEndElement: "
255        //                    + ((container == null) ? "null" : container.getFullName())
256        //                    +  "\t" + elementName + "\t" + currentCharData);
257        _foundChange = false;
258    }
259
260    /** Add a class to be filtered and the old and new property class
261     *  types. Note that if you add a class with this method, then you
262     *  must remove it with {@link #remove(String)}, calling
263     *  "new PropertyClassChanges()" will not remove a class that was
264     *  added with this method.
265     *  @param className The name of the class to be filtered
266     *  out, for example "ptolemy.copernicus.kernel.GeneratorAttribute".
267     *  @param propertyClassMap The HashMap that has the property
268     *  name as a key and the new class name as a value. If the value
269     *  of the HashMap is null then the rest of the attribute is skipped.
270     *  @see #remove(String)
271     */
272    public void put(String className, HashMap propertyClassMap) {
273        _actorsWithPropertyClassChanges.put(className, propertyClassMap);
274    }
275
276    /** Remove a class to be filtered.
277     *  @param className The name of the class to be filtered
278     *  out, for example "ptolemy.copernicus.kernel.GeneratorAttribute".
279     *  @see #put(String, HashMap)
280     */
281    public void remove(String className) {
282        _actorsWithPropertyClassChanges.remove(className);
283    }
284
285    /** Return a string that describes what the filter does.
286     *  @return the description of the filter that ends with a newline.
287     */
288    @Override
289    public String toString() {
290        StringBuffer results = new StringBuffer(
291                getClass().getName() + ": Update any actor port class names\n"
292                        + "that have been renamed.\n"
293                        + "Below are the actors that are affected, along "
294                        + "with the port name\nand the new classname:");
295        Iterator actors = _actorsWithPropertyClassChanges.keySet().iterator();
296
297        while (actors.hasNext()) {
298            String actor = (String) actors.next();
299            results.append("\t" + actor + "\n");
300
301            HashMap propertyMap = (HashMap) _actorsWithPropertyClassChanges
302                    .get(actor);
303            if (propertyMap != null) {
304                Iterator propertyMapEntries = propertyMap.entrySet().iterator();
305
306                while (propertyMapEntries.hasNext()) {
307                    Map.Entry properties = (Map.Entry) propertyMapEntries
308                            .next();
309                    String oldProperty = (String) properties.getKey();
310                    String newProperty = (String) properties.getValue();
311                    results.append("\t\t" + oldProperty + "\t -> " + newProperty
312                            + "\n");
313                }
314            }
315        }
316
317        return results.toString();
318    }
319
320    ///////////////////////////////////////////////////////////////////
321    ////                         private variables                 ////
322    // Map of actor names a HashMap of property names to new classes.
323    private static HashMap _actorsWithPropertyClassChanges;
324
325    // The the full name of the actor we are currently processing
326    private String _currentActorFullName;
327
328    // Set to true if we are currently processing an actor with parameter
329    // class changes, set to false when we are done.
330    private boolean _currentlyProcessingActorWithPropertyClassChanges = false;
331
332    // Last "name" value seen, for use if we see a "class" for this actor
333    private String _lastNameSeen;
334
335    // The new class name for the property we are working on.
336    private String _newClass;
337
338    // Keep track of whether a change was found.
339    private boolean _foundChange;
340
341    // Cache of map from old property names to new class names for
342    // the actor we are working on.
343    private static HashMap _propertyMap;
344
345    static {
346        ///////////////////////////////////////////////////////////
347        // Actors that have properties that have changed class.
348        _actorsWithPropertyClassChanges = new HashMap();
349
350        // Display
351        HashMap displayClassChanges = new HashMap();
352
353        // Key = property name, Value = new class name
354        displayClassChanges.put("title", "ptolemy.data.expr.StringParameter");
355
356        _actorsWithPropertyClassChanges.put("ptolemy.actor.lib.gui.Display",
357                displayClassChanges);
358
359        _actorsWithPropertyClassChanges.put(
360                "ptolemy.domains.sr.lib.gui.NonStrictDisplay",
361                displayClassChanges);
362
363        _actorsWithPropertyClassChanges.put(
364                "ptolemy.domains.dt.kernel.text.TimedDisplay",
365                displayClassChanges);
366
367        // Expression
368        // This is a second generation change.
369        // Used to change it to a StringAttribute
370        HashMap expressionClassChanges = new HashMap();
371
372        // Key = property name, Value = new class name
373        expressionClassChanges.put("expression",
374                "ptolemy.kernel.util.StringAttribute");
375
376        _actorsWithPropertyClassChanges.put("ptolemy.actor.lib.Expression",
377                expressionClassChanges);
378
379        // _hideName in visible attributes.
380        HashMap hideNameClassChanges = new HashMap();
381
382        // Key = property name, Value = new class name
383        // NOTE: Ideally, we would create a
384        // ptolemy.data.expr.SingletonParameter with value
385        // true, but we have no mechanism to set the value,
386        // so we use an attribute.
387        hideNameClassChanges.put("_hideName",
388                "ptolemy.kernel.util.SingletonAttribute");
389
390        _actorsWithPropertyClassChanges.put("ptolemy.kernel.util.Attribute",
391                hideNameClassChanges);
392
393        // MathFunction
394        HashMap mathFunctionClassChanges = new HashMap();
395
396        // Key = property name, Value = new class name
397        mathFunctionClassChanges.put("function",
398                "ptolemy.data.expr.StringParameter");
399
400        _actorsWithPropertyClassChanges.put("ptolemy.actor.lib.MathFunction",
401                mathFunctionClassChanges);
402
403        // TrigFunction
404        HashMap trigFunctionClassChanges = new HashMap();
405
406        // Key = property name, Value = new class name
407        trigFunctionClassChanges.put("function",
408                "ptolemy.data.expr.StringParameter");
409
410        _actorsWithPropertyClassChanges.put("ptolemy.actor.lib.TrigFunction",
411                trigFunctionClassChanges);
412
413        // MatlabExpression
414        HashMap matlabClassChanges = new HashMap();
415
416        // Key = property name, Value = new class name
417        matlabClassChanges.put("expression",
418                "ptolemy.data.expr.StringParameter");
419
420        _actorsWithPropertyClassChanges.put("ptolemy.matlab.Expression",
421                matlabClassChanges);
422
423        // DirectoryListing
424        HashMap directoryListingClassChanges = new HashMap();
425
426        // Key = property name, Value = new class name
427        directoryListingClassChanges.put("directoryOrURL",
428                "ptolemy.actor.parameters.FilePortParameter");
429
430        _actorsWithPropertyClassChanges.put(
431                "ptolemy.actor.lib.io.DirectoryListing",
432                directoryListingClassChanges);
433
434        // LineReader
435        HashMap lineReaderClassChanges = new HashMap();
436
437        // Key = property name, Value = new class name
438        lineReaderClassChanges.put("fileOrURL",
439                "ptolemy.actor.parameters.FilePortParameter");
440
441        _actorsWithPropertyClassChanges.put("ptolemy.actor.lib.io.LineReader",
442                lineReaderClassChanges);
443
444        // CSVReader
445        HashMap csvReaderClassChanges = new HashMap();
446
447        // Key = property name, Value = new class name
448        csvReaderClassChanges.put("fileOrURL",
449                "ptolemy.actor.parameters.FilePortParameter");
450
451        _actorsWithPropertyClassChanges.put("ptolemy.actor.lib.io.CSVReader",
452                csvReaderClassChanges);
453
454        // ExpressionReader
455        HashMap expressionReaderClassChanges = new HashMap();
456
457        // Key = property name, Value = new class name
458        expressionReaderClassChanges.put("fileOrURL",
459                "ptolemy.actor.parameters.FilePortParameter");
460
461        _actorsWithPropertyClassChanges.put(
462                "ptolemy.actor.lib.io.ExpressionReader",
463                expressionReaderClassChanges);
464
465        // LineWriter
466        HashMap lineWriterClassChanges = new HashMap();
467
468        // Key = property name, Value = new class name
469        lineWriterClassChanges.put("fileName",
470                "ptolemy.actor.parameters.FilePortParameter");
471
472        _actorsWithPropertyClassChanges.put("ptolemy.actor.lib.io.LineWriter",
473                lineWriterClassChanges);
474
475        // ModelReference
476        HashMap modelReferenceClassChanges = new HashMap();
477
478        // Key = property name, Value = new class name
479        modelReferenceClassChanges.put("modelFileOrURL",
480                "ptolemy.actor.parameters.FilePortParameter");
481
482        _actorsWithPropertyClassChanges.put(
483                "ptolemy.actor.lib.hoc.ModelReference",
484                modelReferenceClassChanges);
485        _actorsWithPropertyClassChanges.put(
486                "ptolemy.vergil.actor.lib.VisualModelReference",
487                modelReferenceClassChanges);
488
489        // SRDirector
490        HashMap srDirectorClassChanges = new HashMap();
491
492        // Key = property name, Value = new class name
493        srDirectorClassChanges.put("scheduler",
494                "ptolemy.data.expr.StringParameter");
495
496        _actorsWithPropertyClassChanges.put(
497                "ptolemy.domains.sr.kernel.Director", srDirectorClassChanges);
498
499        // There is only one BreakpointODESolver. Some old models have the
500        // wrong choices of break point ODE solvers. The following filters
501        // remove them.
502        // CTEmbeddedDirector
503        HashMap CTEmbeddedDirectorClassChanges = new HashMap();
504
505        // Key = property name, Value = new class name
506        CTEmbeddedDirectorClassChanges.put("breakpointODESolver", null);
507
508        _actorsWithPropertyClassChanges.put(
509                "ptolemy.domains.ct.kernel.CTEmbeddedDirector",
510                CTEmbeddedDirectorClassChanges);
511
512        // CTMixedSignalDirector
513        HashMap ctMixedSignalDirectorClassChanges = new HashMap();
514
515        // Key = property name, Value = new class name
516        ctMixedSignalDirectorClassChanges.put("breakpointODESolver", null);
517
518        _actorsWithPropertyClassChanges.put(
519                "ptolemy.domains.ct.kernel.CTMixedSignalDirector",
520                ctMixedSignalDirectorClassChanges);
521
522        // CTMultiSolverDirector
523        HashMap CTMultiSolverDirectorClassChanges = new HashMap();
524
525        // Key = property name, Value = new class name
526        CTMultiSolverDirectorClassChanges.put("breakpointODESolver", null);
527
528        _actorsWithPropertyClassChanges.put(
529                "ptolemy.domains.ct.kernel.CTMultiSolverDirector",
530                CTMultiSolverDirectorClassChanges);
531
532        // ModalModel
533        HashMap modalModelClassChanges = new HashMap();
534
535        // Key = property name, Value = new class name
536        modalModelClassChanges.put("directorClass",
537                "ptolemy.data.expr.StringParameter");
538
539        // Remove the _Director attribute, which does not help the modal model
540        // to decide which director to choose. This attribugte will be
541        // automatically created. This attribute will not appear in the MoML
542        // output any more.
543        // NOTE: Remove a property by setting the new class to null.
544        modalModelClassChanges.put("_Director", null);
545
546        modalModelClassChanges.put("_tableauFactory",
547                "ptolemy.vergil.fsm.modal.ModalTableauFactory");
548
549        // Note that we add ModalModel here then sometimes remove it
550        // in RemoveGraphical classes.
551        _actorsWithPropertyClassChanges.put(
552                "ptolemy.domains.fsm.modal.ModalModel", modalModelClassChanges);
553
554        // ModalModel changes for the new model model
555        HashMap modalModelClassChanges2 = new HashMap();
556
557        // Key = property name, Value = new class name
558        modalModelClassChanges2.put("directorClass",
559                "ptolemy.data.expr.StringParameter");
560
561        // Remove the _Director attribute, which does not help the modal model
562        // to decide which director to choose. This attribugte will be
563        // automatically created. This attribute will not appear in the MoML
564        // output any more.
565        // NOTE: Remove a property by setting the new class to null.
566        modalModelClassChanges2.put("_Director", null);
567
568        // Here is the only difference between the filter for the old code
569        // and the new filter.
570        modalModelClassChanges2.put("_tableauFactory",
571                "ptolemy.vergil.modal.modal.ModalTableauFactory");
572
573        _actorsWithPropertyClassChanges.put(
574                "ptolemy.domains.modal.modal.ModalModel",
575                modalModelClassChanges2);
576
577        // HashMap hdfClassChanges = new HashMap();
578        //         hdfClassChanges.put("_Director", null);
579        //         _actorsWithPropertyClassChanges.put(
580        //                 "ptolemy.domains.hdf.kernel.HDFFSMDirector", hdfClassChanges);
581
582        // LevelCrossingDetector
583        HashMap levelCrossingDetectorClassChanges = new HashMap();
584        levelCrossingDetectorClassChanges.put("useEventValue", null);
585        _actorsWithPropertyClassChanges.put(
586                "ptolemy.domains.ct.lib.LevelCrossingDetector",
587                levelCrossingDetectorClassChanges);
588
589        // ZeroCrossingDetector
590        HashMap zeroCrossingDetectorClassChanges = new HashMap();
591        zeroCrossingDetectorClassChanges.put("useEventValue", null);
592        _actorsWithPropertyClassChanges.put(
593                "ptolemy.domains.ct.lib.ZeroCrossingDetector",
594                zeroCrossingDetectorClassChanges);
595
596        // SDF actors don't record rates.
597        HashMap rateParameterChanges = new HashMap();
598        rateParameterChanges.put("tokenProductionRate", null);
599        rateParameterChanges.put("tokenConsumptionRate", null);
600        rateParameterChanges.put("tokenInitProduction", null);
601        rateParameterChanges.put("tokenInitConsumption", null);
602        _actorsWithPropertyClassChanges.put(
603                "ptolemy.domains.sdf.lib.Autocorrelation",
604                rateParameterChanges);
605        _actorsWithPropertyClassChanges.put(
606                "ptolemy.domains.sdf.lib.ArrayToSequence",
607                rateParameterChanges);
608        _actorsWithPropertyClassChanges.put("ptolemy.domains.sdf.lib.BitsToInt",
609                rateParameterChanges);
610        _actorsWithPropertyClassChanges.put("ptolemy.domains.sdf.lib.Chop",
611                rateParameterChanges);
612        _actorsWithPropertyClassChanges.put(
613                "ptolemy.domains.sdf.lib.CountTrues", rateParameterChanges);
614        _actorsWithPropertyClassChanges.put(
615                "ptolemy.domains.sdf.lib.DownSample", rateParameterChanges);
616        _actorsWithPropertyClassChanges.put(
617                "ptolemy.domains.sdf.lib.DoubleToMatrix", rateParameterChanges);
618        _actorsWithPropertyClassChanges.put("ptolemy.domains.sdf.lib.FIR",
619                rateParameterChanges);
620        _actorsWithPropertyClassChanges.put("ptolemy.domains.sdf.lib.FFT",
621                rateParameterChanges);
622        _actorsWithPropertyClassChanges.put("ptolemy.domains.sdf.lib.IFFT",
623                rateParameterChanges);
624        _actorsWithPropertyClassChanges.put("ptolemy.domains.sdf.lib.IntToBits",
625                rateParameterChanges);
626        _actorsWithPropertyClassChanges.put("ptolemy.domains.sdf.lib.LineCoder",
627                rateParameterChanges);
628        _actorsWithPropertyClassChanges.put(
629                "ptolemy.domains.sdf.lib.MatrixToDouble", rateParameterChanges);
630        _actorsWithPropertyClassChanges.put(
631                "ptolemy.domains.sdf.lib.MatrixToSequence",
632                rateParameterChanges);
633        _actorsWithPropertyClassChanges.put("ptolemy.domains.sdf.lib.Repeat",
634                rateParameterChanges);
635        _actorsWithPropertyClassChanges.put(
636                "ptolemy.domains.sdf.lib.SampleDelay", rateParameterChanges);
637        _actorsWithPropertyClassChanges.put(
638                "ptolemy.domains.sdf.lib.SequenceToArray",
639                rateParameterChanges);
640        _actorsWithPropertyClassChanges.put(
641                "ptolemy.domains.sdf.lib.SequenceToMatrix",
642                rateParameterChanges);
643        _actorsWithPropertyClassChanges.put("ptolemy.domains.sdf.lib.UpSample",
644                rateParameterChanges);
645        _actorsWithPropertyClassChanges.put(
646                "ptolemy.domains.sdf.lib.VariableFIR", rateParameterChanges);
647
648        // Transition
649        HashMap TransitionClassChanges = new HashMap();
650        TransitionClassChanges.put("relationList", null);
651        _actorsWithPropertyClassChanges.put(
652                "ptolemy.domains.fsm.kernel.Transition",
653                TransitionClassChanges);
654
655        _actorsWithPropertyClassChanges.put(
656                "ptolemy.domains.modal.kernel.Transition",
657                TransitionClassChanges);
658
659        // DocAttribute
660        HashMap DocAttributeClassChanges = new HashMap();
661        DocAttributeClassChanges.put("description",
662                "ptolemy.kernel.util.StringAttribute");
663        _actorsWithPropertyClassChanges.put("ptolemy.vergil.basic.DocAttribute",
664                DocAttributeClassChanges);
665
666        // Repeat actor
667        // Change its numberOfTimes from Parameter to be PortParameter.
668        HashMap RepeatAttributeClassChanges = new HashMap();
669        RepeatAttributeClassChanges.put("numberOfTimes",
670                "ptolemy.actor.parameters.PortParameter");
671        _actorsWithPropertyClassChanges.put("ptolemy.domains.sdf.lib.Repeat",
672                RepeatAttributeClassChanges);
673
674        // PythonActor
675        // Change its _tableauFactory to a ptolemy.vergil.toolbox.TextEditorConfigureFactory
676        // Hmm.  Actually, there are two versions of PythonScript, see python.xml
677        // 'PythonActor' has a _tableauFactory that is a TextEditorTableauFactory
678        // 'PythonScript' has an _editoryFactory that is a TextEditorConfigureFactory.
679        // Both are actor.lib.PythonScript instances.  So, we can't filter here.
680        //         HashMap PythonActorAttributeClassChanges = new HashMap();
681        //         PythonActorAttributeClassChanges.put("_tableauFactory",
682        //                 "ptolemy.vergil.toolbox.TextEditorConfigureFactory");
683
684        //         _actorsWithPropertyClassChanges.put("ptolemy.actor.lib.python.PythonScript",
685        //                 PythonActorAttributeClassChanges);
686
687        // JSAccessor
688        HashMap jsAccessorClassChanges = new HashMap();
689
690        // Key = property name, Value = new class name
691
692        // Needed by:
693        // ptolemy/actor/lib/jjs/modules/vertxEventBus/demo/VertxBus/ReadFromVertxBus.xml
694        jsAccessorClassChanges.put("accessorSource",
695                "org.terraswarm.accessor.JSAccessor$ActionableAttribute");
696
697        jsAccessorClassChanges.put("script",
698                "ptolemy.actor.parameters.PortParameter");
699
700        _actorsWithPropertyClassChanges.put(
701                "org.terraswarm.accessor.JSAccessor", jsAccessorClassChanges);
702
703        // Rhino JavaScript
704        HashMap jsJavaScriptClassChanges = new HashMap();
705
706        // Key = property name, Value = new class name
707
708        // Needed by: org/ptolemy/ptango/demo/Exception/Exception.xml
709
710        jsJavaScriptClassChanges.put("script",
711                "ptolemy.actor.parameters.PortParameter");
712
713        _actorsWithPropertyClassChanges.put("ptolemy.actor.lib.jjs.JavaScript",
714                jsJavaScriptClassChanges);
715
716    }
717}