001/* Create a list of actors parsed thus far.
002
003 Copyright (c) 2006-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.HashSet;
032import java.util.Set;
033
034import ptolemy.actor.TypedCompositeActor;
035import ptolemy.kernel.util.NamedObj;
036
037///////////////////////////////////////////////////////////////////
038//// NamedObjClassesSeen
039
040/** Create a Set of classes that extend NamedObj that are in the MoML
041 parsed thus far.  This filter does not modify the model.
042
043 @author Christopher Brooks, Edward A. Lee
044 @version $Id$
045 @since Ptolemy II 5.2
046 @Pt.ProposedRating Red (cxh)
047 @Pt.AcceptedRating Red (cxh)
048 */
049public class NamedObjClassesSeen extends MoMLFilterSimple {
050    /** Create a filter that looks for classes that extend NamedObj.
051     *  @param classesToBeIndexed A HashMap, where the key is a fully
052     *  qualified dot separated String naming the class; and the key
053     *  is a Set where each element is a String that is a relative
054     *  path that refresh to the model.
055     */
056
057    public NamedObjClassesSeen(HashMap classesToBeIndexed) {
058        reset(null);
059        _classesToBeIndexed = classesToBeIndexed;
060    }
061
062    /** If the attributeName is "class" and the attributeValue extends
063     *  NamedObj, then add the attributeValue to the set of classes
064     *  we are interested in.
065     *  @param container  The container for this attribute.
066     *   in this method.
067     *  @param element The XML element name.
068     *  @param attributeName The name of the attribute.
069     *  @param attributeValue The value of the attribute.
070     *  @param xmlFile The file currently being parsed.
071     *  @return the value of the attributeValue argument.
072     */
073    @Override
074    public String filterAttributeValue(NamedObj container, String element,
075            String attributeName, String attributeValue, String xmlFile) {
076        // This method gets called many times by the MoMLParser,
077        // so we try to be smart about the number of comparisons
078        // and we try to group comparisons together so that we
079        // are not making the same comparison more than once.
080        if (attributeValue == null) {
081            // attributeValue == null is fairly common, so we check for
082            // that first
083            return null;
084        }
085
086        if (attributeName.equals("class")) {
087            // If we have not yet seen this class, check it
088            if (!_classesSeen.contains(attributeValue)) {
089                _classesSeen.add(attributeValue);
090                Set models = null;
091                if ((models = (Set) _classesToBeIndexed
092                        .get(attributeValue)) != null) {
093                    Class theClass = null;
094                    try {
095                        theClass = Class.forName(attributeValue);
096                    } catch (Throwable ex) {
097                        // Print a message and move on.
098                        // FIXME: Use the doclet error handling mechanism
099                        System.err.println("Failed to process " + attributeValue
100                                + "\n" + ex);
101                    }
102                    if (theClass != null
103                            && _namedObjClass.isAssignableFrom(theClass)) {
104                        if (container != null
105                                && container instanceof TypedCompositeActor
106                                && container.getFullName().indexOf(".",
107                                        1) != -1) {
108                            // If the container is not a top level, then
109                            // link to the inner part
110                            String compositePath = _modelPath + "#"
111                                    + container.getFullName()
112                                            .substring(container.getFullName()
113                                                    .indexOf(".", 1) + 1);
114                            //                             System.out.println("NamedObjClasssesSeen: ("
115                            //                                                + compositePath
116                            //                                                + ") container: " + container
117                            //                                                + " element: " + element
118                            //                                                + " attributeName: " + attributeName
119                            //                                                + " attributeValue: " + attributeValue);
120                            models.add(compositePath);
121                        } else {
122                            models.add(_modelPath);
123                        }
124                    }
125                }
126            }
127        }
128        return attributeValue;
129    }
130
131    /** In this class, do nothing.
132     *  @param container The object created by this element.
133     *  @param elementName The element name.
134     *  @param currentCharData The character data, which appears
135     *   only in the doc and configure elements
136     *  @param xmlFile The file currently being parsed.
137     *  @exception Exception Not thrown in this base class.
138     */
139    @Override
140    public void filterEndElement(NamedObj container, String elementName,
141            StringBuffer currentCharData, String xmlFile) throws Exception {
142    }
143
144    /** Return the Set of classes we have seen that extend NamedObj.
145     *  @return Classes seen that extend NamedObj
146     */
147    //    public Set getNamedObjClassesSeen() {
148    //        return _namedObjClassesSeen;
149    //    }
150    /** Reset the filter.
151     *  @param modelPath The new model path.
152     */
153    public void reset(String modelPath) {
154        _modelPath = modelPath;
155        _classesSeen = new HashSet();
156        //_namedObjClassesSeen = new HashSet();
157    }
158
159    /** Return a string that describes what the filter does.
160     *  @return the description of the filter that ends with a newline.
161     */
162    @Override
163    public String toString() {
164        return getClass().getName()
165                + ": Create a Set of classes that have been parsed thus far. "
166                + "The classes extend NamedObj. "
167                + "This filter does not modify the model. ";
168    }
169
170    ///////////////////////////////////////////////////////////////////
171    ////                         private variables                 ////
172
173    /** Set of classes seen the far.  Each element is a String that
174     *  is a dot separated fully qualified class name.
175     */
176    private Set _classesSeen;
177
178    /**  A HashMap, where the key is a fully
179     *  qualified dot separated String naming the class; and the key
180     *  is a Set where each element is a String that is a relative
181     *  path that refresh to the model.
182     */
183    private HashMap _classesToBeIndexed;
184
185    /** The relative path to the model we are parsing.
186     */
187    String _modelPath;
188
189    private static Class _namedObjClass;
190    static {
191        try {
192            _namedObjClass = Class.forName("ptolemy.kernel.util.NamedObj");
193        } catch (ClassNotFoundException ex) {
194            throw new RuntimeException(ex);
195        }
196    }
197}