001/**
002 *  '$Author: crawl $'
003 *  '$Date: 2015-08-24 22:45:41 +0000 (Mon, 24 Aug 2015) $'
004 *  '$Revision: 33631 $'
005 *
006 *  For Details:
007 *  http://www.kepler-project.org
008 *
009 *  Copyright (c) 2010 The Regents of the
010 *  University of California. All rights reserved. Permission is hereby granted,
011 *  without written agreement and without license or royalty fees, to use, copy,
012 *  modify, and distribute this software and its documentation for any purpose,
013 *  provided that the above copyright notice and the following two paragraphs
014 *  appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF
015 *  CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
016 *  OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
017 *  DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
018 *  POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY
019 *  DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
020 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
021 *  SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
022 *  CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
023 *  ENHANCEMENTS, OR MODIFICATIONS.
024 */
025package org.kepler.kar;
026
027import java.io.IOException;
028import java.net.URL;
029import java.util.HashSet;
030import java.util.Set;
031
032import com.sun.javadoc.ClassDoc;
033import com.sun.javadoc.RootDoc;
034
035import ptolemy.util.ClassUtilities;
036
037/** A doclet to find the paths of all super classes for an object.
038 * 
039 *  @author Daniel Crawl
040 *  @version $Id: SuperClassPathFinderDoclet.java 33631 2015-08-24 22:45:41Z crawl $
041 */
042
043public class SuperClassPathFinderDoclet {
044    
045    /** The entry point called from javadoc. */
046    public static boolean start(RootDoc root) {
047
048        _classFiles.clear();
049        
050        try {
051            ClassDoc[] classes = root.classes();
052            _className = classes[0].qualifiedName();
053            for (int i = 0; i < classes.length; i++) {
054                String name = classes[i].qualifiedName();
055                // skip nested classes
056                if(i > 0 && name.startsWith(_className)) {
057                    //System.out.println("skipping nested class " + name);
058                    continue;
059                }
060                String filename = getFileNameForClassName(name);
061                if (filename != null && !_classFiles.contains(filename)) {
062                    _classFiles.add(filename);
063                    _addSuperClasses(classes[i]);
064                }
065            }
066        } catch (Exception e) {
067            System.out.println("ERROR " + e.getClass() + ": " + e.getMessage());
068            e.printStackTrace();
069        }
070        return true;
071    }
072    
073    /** Get the collection of path names. */
074    public static Set<String> getClassFiles() {
075        return new HashSet<String>(_classFiles);
076    }
077    
078    /** Get the class name of the primary object. */
079    public static String getClassName() {
080        return _className;
081    }
082
083    /** Recursively add the super classes of the object. */
084    private static void _addSuperClasses(ClassDoc classDoc) throws ClassNotFoundException {
085        ClassDoc superClassDoc = classDoc.superclass();
086        if (superClassDoc != null) {
087            String name = superClassDoc.qualifiedName();
088            String filename = getFileNameForClassName(name);
089            //System.out.println("name = " + name);
090            if (superClassDoc != null && filename != null && !_classFiles.contains(filename)
091                    // for actors, stop at TypedAtomicActor and TypedCompositeActor
092                    && !name.equals("ptolemy.actor.TypedAtomicActor")
093                    && !name.equals("ptolemy.actor.TypedCompositeActor")
094                    // for parameters stop at Variable
095                    && !name.equals("ptolemy.data.expr.Variable")
096                    // for directors stop at Attribute
097                    && !name.equals("ptolemy.kernel.util.Attribute")) {
098                _classFiles.add(filename);
099                _addSuperClasses(superClassDoc);
100            }
101        }
102    }
103    
104    /** Return the path for a fully-qualified class name. */
105    public static String getFileNameForClassName(String className) throws ClassNotFoundException {
106        String filename = className.replace('.', '/');
107
108        // Inner classes: Get rid of everything past the first $
109        if (filename.indexOf("$") != -1) {
110            filename = filename.substring(0, filename.indexOf("$"));
111        }
112
113        filename += ".java";
114        //System.out.println("filename = " + filename);
115        URL url = ClassLoader.getSystemResource(filename);
116        //System.out.println("url = " + url);        
117        
118        if(url == null) {
119
120            try {
121                url = ClassUtilities.sourceResource(filename);
122            } catch (IOException e) {
123                System.out.println("ERROR trying to find file for class " + className + ": " + e.getMessage());
124            }
125            
126            if(url == null) {
127                // see if class is a nested class
128                Class<?> clazz = null;
129                try {
130                     clazz = Class.forName(className);
131                } catch(ClassNotFoundException e) {
132                   System.out.println("WARNING: could not instiante class " + className +
133                           " (Maybe it's a customized composite actor?)");
134                   return null;
135                }
136                if(clazz.getEnclosingClass() == null) {
137                    System.out.println("WARNING: could not find path for class " + className);
138                }// else { System.out.println("ignoring nested class " + className); }
139            }
140        }
141        
142        if(url != null) {
143            return url.getPath();
144        }
145        return null;
146        
147    }
148
149    /** A collection of path names. */
150    private static final Set<String> _classFiles = new HashSet<String>();
151    
152    /** The class name of the primary object. */
153    private static String _className;
154}