001/* Remove graphical classes
002
003 Copyright (c) 1998-2016 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;
035
036///////////////////////////////////////////////////////////////////
037//// RemoveGraphicalClasses
038
039/** When this class is registered with the MoMLParser.setMoMLFilter()
040 method, it will cause MoMLParser to filter out graphical classes.
041
042 <p>This is very useful for running applets with out requiring files
043 like diva.jar to be downloaded.  It is also used by the nightly build to
044 run tests when there is no graphical display present.</p>
045
046 <p> See ptolemy.moml.filter.RemoveGraphicalClassesApplication for
047 an application that will remove graphical classes from a file.</p>
048
049 @author  Edward A. Lee, Christopher Hylands
050 @version $Id$
051 @since Ptolemy II 2.0
052 @Pt.ProposedRating Red (cxh)
053 @Pt.AcceptedRating Red (cxh)
054 */
055public class RemoveGraphicalClasses extends MoMLFilterSimple {
056    /** Construct a filter that removes graphical classes.
057     */
058    public RemoveGraphicalClasses() {
059        if (_graphicalClasses == null) {
060            initialize();
061        }
062    }
063
064    /** Clear the map of graphical classes to be removed.
065     */
066    public static void clear() {
067        _graphicalClasses = new HashMap();
068    }
069
070    /** Filter for graphical classes and return new values if
071     *  a graphical class is found.
072     *  An internal HashMap maps names of graphical entities to
073     *  new names.  The HashMap can also map a graphical entity
074     *  to null, which means the entity is removed from the model.
075     *  All class attributeValues that start with "ptolemy.domains.gr"
076     *  are deemed to be graphical elements and null is always returned.
077     *  For example, if the attributeValue is "ptolemy.vergil.icon.ValueIcon",
078     *  or "ptolemy.vergil.basic.NodeControllerFactory"
079     *  then return "ptolemy.kernel.util.Attribute"; if the attributeValue
080     *  is "ptolemy.vergil.icon.AttributeValueIcon" or
081     *  "ptolemy.vergil.icon.BoxedValueIcon" then return null, which
082     *  will cause the MoMLParser to skip the rest of the element;
083     *  otherwise return the original value of the attributeValue.
084     *
085     *  @param container  The container for this attribute, ignored
086     *  in this method.
087     *  @param element The XML element name.
088     *  @param attributeName The name of the attribute, ignored
089     *   in this method.
090     *  @param attributeValue The value of the attribute.
091     *  @param xmlFile The file currently being parsed.
092     *  @return the filtered attributeValue.
093     */
094    @Override
095    public String filterAttributeValue(NamedObj container, String element,
096            String attributeName, String attributeValue, String xmlFile) {
097        if (_graphicalClasses == null) {
098            initialize();
099        }
100        // If the nightly build is failing with messages like:
101        // " X connection to foo:0 broken (explicit kill or server shutdown)."
102        // Try uncommenting the next lines to see what is being
103        // expanding before the error:
104        //System.out.println("filterAttributeValue: " + container + "\t"
105        //       +  attributeName + "\t" + attributeValue);
106        if (attributeValue == null) {
107            return null;
108        } else if (_graphicalClasses.containsKey(attributeValue)) {
109            MoMLParser.setModified(true);
110            return (String) _graphicalClasses.get(attributeValue);
111        } else if (_removeGR
112                && attributeValue.startsWith("ptolemy.domains.gr")) {
113            MoMLParser.setModified(true);
114            return null;
115        }
116
117        return attributeValue;
118    }
119
120    /** In this class, do nothing.
121     *  @param container The object created by this element.
122     *  @param elementName The element name.
123     *  @param currentCharData The character data, which appears
124     *   only in the doc and configure elements
125     *  @param xmlFile The file currently being parsed.
126     *  @exception Exception Not thrown in this base class.
127     */
128    @Override
129    public void filterEndElement(NamedObj container, String elementName,
130            StringBuffer currentCharData, String xmlFile) throws Exception {
131    }
132
133    /** Initialize the set of classes to remove. */
134    public static void initialize() {
135        _graphicalClasses = new HashMap();
136
137        // Alphabetical by key class
138        // We can convert any graphical classes that have a port named "input" to
139        // a DiscardDoubles actor.  However, classes like XYPlot have ports named "X" and Y",
140        // so XYPlot cannot be converted.
141
142        // We use DiscardDoublesArray here so that the types are preserved
143        // in case enableBackwardTypeInference is set.
144        _graphicalClasses.put("ptolemy.actor.lib.gui.ArrayPlotter",
145                "ptolemy.moml.filter.DiscardDoublesArray");
146        _graphicalClasses.put("ptolemy.actor.lib.gui.BarGraph",
147                "ptolemy.moml.filter.DiscardDoublesArray");
148
149        // Display's input port is of type General.
150        _graphicalClasses.put("ptolemy.actor.lib.gui.Display",
151                "ptolemy.actor.lib.Discard");
152        // Classes that extend Display
153        _graphicalClasses.put("ptolemy.actor.lib.gui.TimedDisplay",
154                "ptolemy.actor.lib.Discard");
155        _graphicalClasses.put("ptolemy.domains.taskpt.lib.gui.DisplayAll",
156                "ptolemy.actor.lib.Discard");
157
158        // We use DiscardDoubles here so that the types are preserved
159        // in case enableBackwardTypeInference is set.
160        _graphicalClasses.put("ptolemy.actor.lib.gui.HistogramPlotter",
161                "ptolemy.moml.filter.DiscardDoubles");
162        _graphicalClasses.put("ptolemy.actor.lib.gui.RealTimePlotter",
163                "ptolemy.moml.filter.DiscardDoubles");
164        _graphicalClasses.put("ptolemy.actor.lib.gui.TimedPlotter",
165                "ptolemy.moml.filter.DiscardDoubles");
166        _graphicalClasses.put("ptolemy.actor.lib.gui.SequencePlotter",
167                "ptolemy.moml.filter.DiscardDoubles");
168        _graphicalClasses.put("ptolemy.vergil.actor.lib.LEDMatrix",
169                "ptolemy.moml.filter.DiscardDoubles");
170
171        _graphicalClasses.put("ptolemy.data.properties.gui.PropertyHighlighter",
172                null);
173
174        _graphicalClasses.put("ptolemy.domains.sr.lib.gui.NonStrictDisplay",
175                "ptolemy.actor.lib.Discard");
176
177        // Generated applet from moml/demo/modulation.xml
178        // fails to run if substitute Attribute for NodeControllerFactory
179        // so we set it to null instead.
180        _graphicalClasses.put("ptolemy.vergil.toolbox.AnnotationEditorFactory",
181                "ptolemy.kernel.util.Attribute");
182        _graphicalClasses.put(
183                "ptolemy.vergil.toolbox.VisibleParameterEditorFactory",
184                "ptolemy.kernel.util.Attribute");
185        _graphicalClasses.put(
186                "ptolemy.vergil.fsm.modal.HierarchicalStateControllerFactory",
187                "ptolemy.kernel.util.Attribute");
188        _graphicalClasses.put(
189                "ptolemy.vergil.modal.modal.HierarchicalStateControllerFactory",
190                "ptolemy.kernel.util.Attribute");
191        _graphicalClasses.put("ptolemy.vergil.fsm.modal.ModalTableauFactory",
192                "ptolemy.kernel.util.Attribute");
193        _graphicalClasses.put("ptolemy.vergil.modal.modal.ModalTableauFactory",
194                "ptolemy.kernel.util.Attribute");
195        _graphicalClasses.put("ptolemy.vergil.ptera.PteraGraphTableau$Factory",
196                "ptolemy.kernel.util.Attribute");
197        _graphicalClasses.put(
198                "ptolemy.vergil.gt.TransformationAttributeEditorFactory",
199                "ptolemy.kernel.util.Attribute");
200        _graphicalClasses.put("ptolemy.vergil.gt.MatchResultTableau$Factory",
201                "ptolemy.kernel.util.Attribute");
202        _graphicalClasses.put("ptolemy.vergil.gt.GTTableau$Factory",
203                "ptolemy.kernel.util.Attribute");
204        _graphicalClasses.put("ptolemy.vergil.gt.GTTableau$ModalTableauFactory",
205                "ptolemy.kernel.util.Attribute");
206
207        // 4/04 BooleanSwitch uses EditorIcon
208        _graphicalClasses.put("ptolemy.vergil.icon.EditorIcon", null);
209
210        // 11/06 FSM uses StateIcon
211        _graphicalClasses.put("ptolemy.vergil.fsm.StateIcon", null);
212
213        _graphicalClasses.put("ptolemy.vergil.modal.StateIcon", null);
214
215        _graphicalClasses.put("ptolemy.vergil.fsm.fmv.FmvStateIcon", null);
216
217        _graphicalClasses.put("ptolemy.vergil.modal.fmv.FmvStateIcon", null);
218
219        _graphicalClasses.put("ptolemy.ontologies.ConceptIcon", null);
220
221        _graphicalClasses.put("ptolemy.vergil.kernel.attributes.ArcAttribute",
222                null);
223
224        _graphicalClasses
225                .put("ptolemy.vergil.kernel.attributes.EllipseAttribute", null);
226
227        _graphicalClasses.put(
228                "ptolemy.vergil.kernel.attributes.FilledShapeAttribute", null);
229
230        _graphicalClasses.put("ptolemy.vergil.kernel.attributes.IDAttribute",
231                null);
232
233        _graphicalClasses.put("ptolemy.vergil.kernel.attributes.ImageAttribute",
234                null);
235
236        _graphicalClasses.put("ptolemy.vergil.kernel.attributes.ArrowAttribute",
237                null);
238
239        _graphicalClasses.put("ptolemy.vergil.kernel.attributes.LineAttribute",
240                null);
241
242        _graphicalClasses.put("ptolemy.vergil.kernel.attributes.ShapeAttribute",
243                null);
244
245        _graphicalClasses.put(
246                "ptolemy.vergil.kernel.attributes.ResizablePolygonAttribute",
247                null);
248
249        _graphicalClasses.put(
250                "ptolemy.vergil.kernel.attributes.RectangleAttribute", null);
251
252        _graphicalClasses.put("ptolemy.vergil.kernel.attributes.TextAttribute",
253                null);
254
255        _graphicalClasses.put("ptolemy.vergil.basic.export.web.BasicJSPlotter",
256                null);
257        _graphicalClasses
258                .put("ptolemy.vergil.basic.export.web.DygraphsJSPlotter", null);
259        // Classes that import ptolemy.vergil.icon.ValueIcon
260        _graphicalClasses.put("ptolemy.vergil.basic.export.web.DefaultIconLink",
261                null);
262        _graphicalClasses
263                .put("ptolemy.vergil.basic.export.web.DefaultIconScript", null);
264        _graphicalClasses.put("ptolemy.vergil.basic.export.web.DefaultTitle",
265                null);
266        _graphicalClasses.put("ptolemy.vergil.basic.export.web.HTMLImage",
267                null);
268        // HTMLText extends WebContent which imports ValueIcon
269        _graphicalClasses.put("ptolemy.vergil.basic.export.web.HTMLText", null);
270        _graphicalClasses.put("ptolemy.vergil.basic.export.web.IconLink", null);
271        _graphicalClasses.put("ptolemy.vergil.basic.export.web.IconScript",
272                null);
273        _graphicalClasses.put(
274                "ptolemy.vergil.basic.export.web.LinkToOpenTableaux", null);
275        _graphicalClasses.put(
276                "ptolemy.vergil.basic.export.web.ParameterDisplayIconScript",
277                null);
278        _graphicalClasses.put("ptolemy.vergil.basic.export.web.Title", null);
279        _graphicalClasses.put("ptolemy.vergil.basic.export.web.WebContent",
280                null);
281        _graphicalClasses.put("ptolemy.vergil.basic.export.web.WebExportable",
282                null);
283
284        _graphicalClasses.put("ptolemy.vergil.basic.NodeControllerFactory",
285                null);
286
287        _graphicalClasses.put("ptolemy.vergil.ptera.EventIcon", null);
288        _graphicalClasses.put("ptolemy.vergil.ptera.OctagonEventIcon", null);
289        _graphicalClasses.put("ptolemy.vergil.ptera.TestIcon", null);
290        _graphicalClasses.put("ptolemy.vergil.ptera.TimeAdvanceEventIcon",
291                null);
292
293        _graphicalClasses.put("ptolemy.vergil.gt.IterativeParameterIcon", null);
294        _graphicalClasses.put("ptolemy.vergil.gt.StateMatcherIcon", null);
295        _graphicalClasses.put("ptolemy.vergil.gt.TransformationAttributeIcon",
296                null);
297
298        _graphicalClasses.put("ptolemy.vergil.ptera.TimeAdvanceEventIcon",
299                null);
300
301        _graphicalClasses.put("ptolemy.vergil.icon.AttributeValueIcon", null);
302        _graphicalClasses.put("ptolemy.vergil.icon.BoxedValueIcon", null);
303        _graphicalClasses.put("ptolemy.vergil.icon.DesignPatternIcon", null);
304        _graphicalClasses.put("ptolemy.vergil.icon.CopyCatIcon", null);
305        _graphicalClasses.put("ptolemy.vergil.icon.EditorIcon", null);
306        _graphicalClasses.put("ptolemy.vergil.icon.ShapeIcon", null);
307        _graphicalClasses.put("ptolemy.vergil.icon.XMLIcon", null);
308
309        // ptolemy/actor/lib/test/auto/StopSDF.xml has a MonitorValue actor,
310        // so remove the UpdatedValueIcon.
311        _graphicalClasses.put("ptolemy.vergil.icon.UpdatedValueIcon", null);
312        _graphicalClasses.put("ptolemy.vergil.icon.ValueIcon",
313                "ptolemy.kernel.util.Attribute");
314
315        // Generated applet from moml/demo/modulation.xml
316        // fails to run if substitute Attribute for AnnotationEditorFactory
317        // so we set it to null instead.
318        //_graphicalClasses.put("ptolemy.vergil.toolbox.AnnotationEditorFactory",
319        //        "ptolemy.kernel.util.Attribute");
320        _graphicalClasses.put("ptolemy.vergil.toolbox.AnnotationEditorFactory",
321                null);
322        _graphicalClasses.put(
323                "ptolemy.vergil.toolbox" + ".VisibleParameterEditorFactory",
324                "ptolemy.kernel.util.Attribute");
325
326        // Shallow CG of actor/lib/test/auto/URLDirectoryReader3.xml fails
327        // unless we remove CheckBoxStyle
328        _graphicalClasses.put("ptolemy.actor.gui.style.CheckBoxStyle", null);
329        _graphicalClasses.put("ptolemy.actor.gui.style.ChoiceStyle", null);
330
331        _graphicalClasses.put("ptolemy.actor.gui.LocationAttribute", null);
332        _graphicalClasses.put("ptolemy.actor.gui.SizeAttribute", null);
333        _graphicalClasses.put("ptolemy.actor.gui.PtolemyPreferences",
334                "ptolemy.data.expr.ScopeExtendingAttribute");
335        _graphicalClasses.put("ptolemy.actor.gui.WindowPropertiesAttribute",
336                null);
337
338        // Sinewave has a DocViewerFactory, which we need to remove
339        _graphicalClasses.put("ptolemy.vergil.basic.DocViewerFactory",
340                "ptolemy.kernel.util.Attribute");
341        // Sinewave has a DocAttribute, which we need to remove
342        _graphicalClasses.put("ptolemy.vergil.basic.DocAttribute",
343                "ptolemy.kernel.util.Attribute");
344
345        _graphicalClasses.put("ptolemy.domains.wireless.lib.GraphicalLocator",
346                "ptolemy.domains.wireless.lib.Locator");
347
348        _graphicalClasses.put("ptolemy.domains.wireless.lib.TerrainProperty",
349                null);
350
351        _graphicalClasses.put(
352                "ptolemy.domains.wireless.demo.EvaderAndPursuer.Sensor", null);
353
354        // Remove various graphical classes from curriculum
355        _graphicalClasses
356                .put("ptolemy.domains.curriculum.DependencyHighlighter", null);
357        _graphicalClasses.put("ptolemy.vergil.basic.DependencyHighlighter",
358                null);
359        _graphicalClasses.put("ptolemy.domains.curriculum.HighlightEntities",
360                "ptolemy.kernel.util.Attribute");
361        _graphicalClasses.put("ptolemy.vergil.icon.NameIcon", null);
362
363        // Needed modal/demo/SystemLevelTypes/*.xml
364        _graphicalClasses.put("ptolemy.vergil.modal.StateIcon", null);
365
366        // Exclude DependencyHighlighter
367        _graphicalClasses.put("ptolemy.actor.gui.DependencyHighlighter", null);
368
369        // properties classes
370        _graphicalClasses.put(
371                "ptolemy.vergil.properties.ModelAttributeController", null);
372
373        _graphicalClasses.put("ptolemy.vergil.properties.LatticeElementIcon",
374                null);
375
376        _graphicalClasses
377                .put("ptolemy.vergil.actor.lib.MonitorReceiverContents", null);
378
379        _graphicalClasses.put("ptolemy.vergil.ontologies.ConceptIcon", null);
380        _graphicalClasses.put("ptolemy.vergil.ontologies.MultipleConceptIcon",
381                null);
382
383        _graphicalClasses.put(
384                "ptolemy.domains.petrinet.lib.gui.PetriNetDisplay",
385                "ptolemy.domains.petrinet.lib.PetriNetRecorder");
386
387        _graphicalClasses.put(
388                "ptolemy.domains.ptides.demo.PtidesAirplaneFuelControl.Tank",
389                "ptolemy.domains.wireless.kernel.WirelessComposite");
390
391        _graphicalClasses.put("ptolemy.actor.lib.image.ImageDisplay",
392                "ptolemy.moml.filter.DiscardGenerals");
393        // Classes that extend ImageDisplay
394        _graphicalClasses.put("ptolemy.domains.sdf.lib.vq.ImageDisplay",
395                "ptolemy.moml.filter.DiscardGenerals");
396
397        // FIXME: If this actors are used when enabledBackwardTypeInference
398        // is set, then the type of Discard is not the same as the type
399        // of MatrixViewer.
400        _graphicalClasses.put("ptolemy.actor.lib.gui.MatrixViewer",
401                "ptolemy.actor.lib.Discard");
402
403        // org/ptolemy/qss/test/auto/RLC.xml
404        _graphicalClasses.put("ptolemy.vergil.pdfrenderer.PDFAttribute", null);
405
406        //note: kepler display related actors should not be added here.
407        //if the actor supports '-redirectgui', it should be put into file: $Kepler/common/configs/ptolemy/configs/kepler/KeplerDisplayActorWithRedirect.xml.
408        //if the actor does not support '-redirectgui', it should be put into file: $Kepler/common/configs/ptolemy/configs/kepler/KeplerDisplayActorNoRedirect.xml.
409
410        _graphicalClasses.put("ptolemy.vergil.actor.LayoutHint", null);
411
412    }
413
414    /** Remove a class to be filtered.
415     *  @param className The name of the class to be filtered
416     *  out, for example "ptolemy.copernicus.kernel.GeneratorAttribute".
417     *  @see #put(String, String)
418     */
419    public void remove(String className) {
420        // ptolemy.copernicus.kernel.MakefileGenerator
421        // so as to filter out the GeneratorAttribute
422        _graphicalClasses.remove(className);
423    }
424
425    /** Add a class to be filtered for and its replacement if the class
426     *  is found.  If the replacement is null, then the rest of the
427     *  attribute is skipped.  Note that if you add a class with
428     *  this method, then you must remove it with {@link #remove(String)},
429     *  calling 'new RemoveGraphicalClasses' will not remove a class
430     *  that was added with this method.
431     *  @param className The name of the class to be filtered
432     *  out, for example "ptolemy.copernicus.kernel.GeneratorAttribute".
433     *  @param replacement The name of the class to be used if
434     *  className is found.  If this argument is null then the
435     *  rest of the attribute is skipped.
436     *  @see #remove(String)
437     */
438    public void put(String className, String replacement) {
439        // ptolemy.copernicus.kernel.KernelMain call this method
440        // so as to filter out the GeneratorAttribute
441        _graphicalClasses.put(className, replacement);
442    }
443
444    /** Set to true if we should removed classes that start with
445     *  ptolemy.domains.gr.
446     *  @param removeGR True if we should remove classes that start
447     *  with ptolemy.domains.gr.
448     */
449    public void setRemoveGR(boolean removeGR) {
450        _removeGR = removeGR;
451    }
452
453    /** Return a string that describes what the filter does.
454     *  @return the description of the filter that ends with a newline.
455     */
456    @Override
457    public String toString() {
458        StringBuffer results = new StringBuffer(getClass().getName()
459                + ": Remove or replace classes that are graphical.\n"
460                + "This filter is used by the nightly build, and\n"
461                + "can be used to run applets so that files like\n"
462                + "diva.jar do not need to be downloaded.\n"
463                + "The following actors are affected:\n");
464        Iterator classNames = _graphicalClasses.keySet().iterator();
465
466        while (classNames.hasNext()) {
467            String oldClassName = (String) classNames.next();
468            String newClassName = (String) _graphicalClasses.get(oldClassName);
469
470            if (newClassName == null) {
471                results.append(oldClassName + " will be removed\n");
472            } else {
473                results.append(oldClassName + " will be replaced by "
474                        + newClassName + "\n");
475            }
476        }
477
478        return results.toString();
479    }
480
481    ///////////////////////////////////////////////////////////////////
482    ////                         private variables                 ////
483
484    /** Map of actor names a HashMap of graphical classes to their
485     *  non-graphical counterparts, usually either
486     *  ptolemy.kernel.util.Attribute or null.
487     */
488    private static HashMap _graphicalClasses;
489
490    /** True if we should remove the GR domain. */
491    private boolean _removeGR = false;
492}