/* Generate an index of actors. Copyright (c) 2006-2008 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.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import ptolemy.kernel.util.InternalErrorException; import ptolemy.moml.MoMLParser; import ptolemy.util.FileUtilities; import ptolemy.util.StringUtilities; ////////////////////////////////////////////////////////////////////////// //// ActorIndex /** Generate actor/demo index files. For each actor that is listed in a file, generate a html file that lists the models in which the actor appears. <p>For details, see $PTII/vergil/actor/docViewerHelp.htm @author Christopher Brooks @version $Id$ @since Ptolemy II 5.2 @Pt.ProposedRating Red (cxh) @Pt.AcceptedRating Red (cxh) */ public class ActorIndex { /** Generate the index files. * @param classesFileName The name of the file that contains the * dot separated class names - one class per line. * This file is usually called allActors.txt, which is generated by * running the $PTII/doc/doclets/PtDoc doclet. For example, see * $PTII/doc/codeDoc/allActors.txt * @param modelsFileName The name of the file that contains the * urls that point to the models to be parsed, one model * per line. This file is usually called models.txt and is generated by * running ptolemy.actor.gui.HTMLAbout. * @param outputDirectory Directory in which to write index files. * The files generated have the name <i>actorName<i>idx.htm, where * <i>actorName</i> is the name of the actor. Typically, the value * for this parameter is doc/codeDoc. * @exception Exception If there is a problem reading or writing * a file. */ public static void generateActorIndex(String classesFileName, String modelsFileName, String outputDirectory) throws Exception { // The class name is the key, a set of models is the value. HashMap classesToBeIndexed = new HashMap(); BufferedReader classesReader = null; BufferedReader modelReader = null; try { // Read classesFileName and populate the classes Set classesReader = new BufferedReader(new FileReader(classesFileName)); String className; while ((className = classesReader.readLine()) != null) { System.out.println("Going to index " + className); classesToBeIndexed.put(className, new HashSet()); } // Read modelsFileName and parse each model, looking // for classes in which we are interested. modelReader = new BufferedReader(new FileReader(modelsFileName)); String modelName; MoMLParser parser = new MoMLParser(); // Handle backward compatibility issues MoMLParser.setMoMLFilters(BackwardCompatibility.allFilters()); // Add a MoML filter that updates the values of classesToBeIndexed // with models that contain classes named by the key of // classesToBeIndexed NamedObjClassesSeen namedObjClassesSeen = new NamedObjClassesSeen( classesToBeIndexed); MoMLParser.addMoMLFilter(namedObjClassesSeen); // Add a filter to remove the graphical classes // This is safe to do because our NamedObjClassesSeen filter // runs before we then remove the graphical classes. RemoveGraphicalClasses removeGraphicalClasses = new RemoveGraphicalClasses(); removeGraphicalClasses.setRemoveGR(true); MoMLParser.addMoMLFilter(removeGraphicalClasses); while ((modelName = modelReader.readLine()) != null) { // Reset the list of classes seen, read the model // The filter updates the classesToBeIndexed hashMap namedObjClassesSeen.reset(modelName); //URL modelURL = new File(modelName).toURL(); try { URL modelURL = FileUtilities.nameToURL(modelName, null, null); System.out.println("Parsing: " + modelURL); parser.reset(); parser.parse(null, modelURL); } catch (Exception ex) { System.err.println("Warning, failed to parse " + modelName); ex.printStackTrace(); } } } finally { if (classesReader != null) { try { classesReader.close(); } catch (Exception ex) { // Ignore } } if (modelReader != null) { try { modelReader.close(); } catch (Exception ex) { // Ignore } } } // Write the output files. Iterator classes = classesToBeIndexed.entrySet().iterator(); while (classes.hasNext()) { Map.Entry entry = (Map.Entry) classes.next(); String actorClassName = (String) entry.getKey(); if (((Set) entry.getValue()).size() == 0) { // Skip classes that are not used in a demo // ptolemy.vergil.actor.DocManager checks to see if // the Idx.htm file exists before creating a link to it. continue; } BufferedWriter writer = null; try { String outputFileName = outputDirectory + File.separator + actorClassName.replace('.', File.separatorChar) + "Idx.htm"; // Determine the relative path to $PTII from this // file. We need this so that we can link to the models. String canonicalOutputFileName = new File(outputFileName) .getCanonicalPath().replace('\\', '/'); // Get PTII as C:/cxh/ptII String ptII = null; try { ptII = new URI(StringUtilities .getProperty("ptolemy.ptII.dirAsURL")).normalize() .getPath(); // Under Windows, convert /C:/foo/bar to C:/foo/bar ptII = new File(ptII).getCanonicalPath().replace('\\', '/'); } catch (URISyntaxException ex) { throw new InternalErrorException(null, ex, "Failed to process PTII " + ptII); } if (ptII.length() == 0) { throw new InternalErrorException("Failed to process " + "ptolemy.ptII.dirAsURL property, ptII = null?"); } String relativePath = ""; if (canonicalOutputFileName.startsWith(ptII)) { // If the canonical output file name starts with ptII // we then generate a relative path String relativeOutputFileName = StringUtilities.substitute( canonicalOutputFileName, ptII, ""); StringBuffer relativePathBuffer = new StringBuffer(); int index = 0; while (relativeOutputFileName.indexOf('/', index) != -1) { index = relativeOutputFileName.indexOf('/', index) + 1; relativePathBuffer.append("../"); } relativePath = relativePathBuffer.toString(); // Strip off the last ../ relativePath = relativePath.substring(0, relativePath .length() - 3); } // Make directories if necessary File outputDirectoryFile = new File(new File(outputFileName) .getParent()); if (!outputDirectoryFile.exists()) { System.out.println("Creating " + outputDirectoryFile); if (!outputDirectoryFile.mkdirs()) { throw new IOException("Directory \"" + outputDirectoryFile + "\" does not exist and cannot be created."); } } System.out.println("Writing " + outputFileName); writer = new BufferedWriter(new FileWriter(outputFileName)); writer.write("<html>\n<head>\n<title>Index for " + actorClassName + "</title>\n" + "<link href=\"" + relativePath + "doc/default.css\"" + "rel=\"stylesheet\" type=\"text/css\">\n" + "</head>\n<body>\n" + "<h2>" + actorClassName + "</h2>\n" + "Below are demonstration models that use " + actorClassName + "\n<ul>\n"); // Loop through all the models that use this actor Iterator models = ((Set) entry.getValue()).iterator(); while (models.hasNext()) { String model = (String) models.next(); if (model.startsWith("$CLASSPATH")) { model = model.substring(11); } writer.write("<li><a href=\"" + relativePath + model + "\">" + model + "</a>\n"); } writer.write("</ul>\n</body>\n</html>\n"); } finally { if (writer != null) { writer.close(); } } } } /** Generate index documentation. The three arguments are passed to * {@link #generateActorIndex(String, String, String)}. * <pre> * java -classpath "$PTII;$PTII/lib/diva.jar" ptolemy.moml.filter.ActorIndex allActors.txt models.txt doc/codeDoc * </pre> * @param args An array of three Strings * <br> The name of the file that lists all the actors in which we are * interested. * <br> The name of the file that lists all the models to be indexed. * <br> The directory in which to write the index files. * @exception Exception If there is a problem reading or writing * a file. */ public static void main(String[] args) throws Exception { ActorIndex.generateActorIndex(args[0], args[1], args[2]); } }