Project Report: fawkez

Packagesummary org.jcoderz.commons.taskdefs

org.jcoderz.commons.taskdefs.DiagramTask

LineHitsNoteSource
1  /*
2   * $Id: DiagramTask.java 1011 2008-06-16 17:57:36Z amandel $
3   *
4   * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5   *
6   * Redistribution and use in source and binary forms, with or without
7   * modification, are permitted provided that the following conditions are
8   * met:
9   *
10   *    * Redistributions of source code must retain the above copyright
11   *      notice, this list of conditions and the following disclaimer.
12   *    * Redistributions in binary form must reproduce the above
13   *      copyright notice, this list of conditions and the following
14   *      disclaimer in the documentation and/or other materials
15   *      provided with the distribution.
16   *    * Neither the name of the jCoderZ.org Project nor the names of
17   *      its contributors may be used to endorse or promote products
18   *      derived from this software without specific prior written
19   *      permission.
20   *
21   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24   * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25   * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28   * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32   */
33  package org.jcoderz.commons.taskdefs;
34  
35  import java.io.File;
36  import java.io.FileInputStream;
37  import java.io.IOException;
38  import java.util.ArrayList;
39  import java.util.Collections;
40  import java.util.Iterator;
41  import java.util.List;
42  
43  import javax.xml.parsers.SAXParser;
44  import javax.xml.parsers.SAXParserFactory;
45  
46  import org.apache.tools.ant.BuildException;
47  import org.apache.tools.ant.Project;
48  import org.apache.tools.ant.Task;
49  import org.apache.tools.ant.taskdefs.Javadoc;
50  import org.apache.tools.ant.taskdefs.Javadoc.DocletInfo;
51  import org.apache.tools.ant.taskdefs.Javadoc.DocletParam;
52  import org.apache.tools.ant.types.FileSet;
53  import org.apache.tools.ant.types.Path;
54  import org.apache.tools.ant.types.PatternSet.NameEntry;
55  import org.jcoderz.phoenix.sqlparser.SqlToXml;
56  import org.xml.sax.Attributes;
57  import org.xml.sax.InputSource;
58  import org.xml.sax.helpers.DefaultHandler;
59  
60  /**
61   * Generates UML diagrams.
62   *
63   * @author Michael Griffel
64   */
650 public class DiagramTask
66        extends Task
67  {
68     /** Task name. */
69     public static final String NAME = "diagram";
70     /** File name extension of graphviz dot files. */
71     private static final String DOTTY_EXTENSION = ".dot";
72     /** File name extension of Java files. */
73     private static final String JAVA_EXTENSION = ".java";
74     /** Font name for graphviz. */
75     private static final String DEFAULT_FONTNAME = "verdana";
76     /** Font size for graphviz. */
77     private static final String DEFAULT_FONTSIZE = "7";
78  
79     /** The output directory. */
80     private File mOutDir;
81     /** The input file. */
82     private File mInFile;
83     /** terminate ant build on error. */
84     private boolean mFailOnError;
85     /** Doclet path. */
86     private Path mDocletPath;
87     /** Source path - list of SourceDirectory. */
880    private final List mSources = new ArrayList();
89  
90     /**
91      * Sets the XML input file that contains the document.
92      * @param f the XML input file (log message info).
93      */
94     public void setIn (File f)
95     {
960       mInFile = f;
970    }
98  
99     /**
100      * Set the destination directory into which the result
101      * files should be copied to. This parameter is required.
102      * @param dir the name of the destination directory.
103      **/
104     public void setOut (File dir)
105     {
1060        mOutDir = dir;
1070    }
108  
109     /**
110      * Set the document type.
111      * @param type the document type.
112      */
113     public void setType (String type)
114     {
115 (1)      // TODO:
1160    }
117  
118     /**
119      * Set whether we should fail on an error.
120      * @param b Whether we should fail on an error.
121      */
122     public void setFailonerror (boolean b)
123     {
1240       mFailOnError = b;
1250    }
126  
127     /**
128      * Set the source path to be used for this task run.
129      * @param src an Ant FileSet object containing the compilation
130      *        source path.
131      */
132     public void addSrc (SourceDirectory src)
133     {
1340       mSources.add(src);
1350    }
136  
137     /**
138      * Set the doclet path to be used for this task run.
139      * @param path an Ant Path object containing the compilation
140      *        source path.
141      */
142     public void setDocletPath (Path path)
143     {
1440       if (mDocletPath == null)
145        {
1460          mDocletPath = path;
147        }
148        else
149        {
1500          mDocletPath.add(path);
151        }
1520    }
153  
154     /**
155      * Execute this task.
156      *
157      * @throws BuildException An building exception occurred.
158      */
159     public void execute ()
160           throws BuildException
161     {
162        try
163        {
1640          checkAttributes();
165  
1660          final DiagramSaxHandler handler = parse();
1670          log("Diagrams: " + handler.diagrams().toString(), Project.MSG_DEBUG);
168  
1690          final Iterator iterator = handler.diagrams().iterator();
1700          while (iterator.hasNext())
171           {
1720             final Diagram diagram = (Diagram) iterator.next();
1730             if ("class".equals(diagram.getType()))
174              {
1750                generateUmlDiagram(diagram);
176              }
1770             else if ("ER".equals(diagram.getType()))
178              {
1790                generateEntityRelationshipDiagram(diagram);
180              }
1810          }
1820          generateStateDiagram();
1830          AntTaskUtil.renderDotFiles(this, mOutDir, mFailOnError);
184        }
1850       catch (BuildException e)
186        {
1870          if (mFailOnError)
188           {
1890             throw e;
190           }
1910          log(e.getMessage(), Project.MSG_ERR);
1920       }
1930    }
194  
195  
196     private void generateEntityRelationshipDiagram (Diagram diagram)
197     {
1980       final File inFile = new File(
199              getProject().getBaseDir(), diagram.getFile());
200        final File tmpFile;
201        try
202        {
2030          tmpFile = File.createTempFile("xdoc", ".tmp");
204        }
2050       catch (IOException e)
206        {
2070          throw new BuildException("Failed to create temp file: " + e, e);
2080       }
2090       final SqlToXml sqlToXml
210              = new SqlToXml(inFile.getAbsolutePath(), tmpFile.getAbsolutePath());
211        try
212        {
2130          sqlToXml.transformSqlToXml();
214        }
2150       catch (Exception e)
216        {
2170          throw new BuildException("Failed to transform SQL '" + inFile
218                 + "' file to XML: " + e, e);
2190       }
220  
2210       final File outFile = new File(mOutDir, diagram.getName() + ".dot");
2220       final XsltBasedTask t = new XsltBasedTask()
2230(2)      {
224           String getDefaultStyleSheet ()
225           {
2260             return "generate-er-diagram.xsl";
227           }
228        };
2290       t.setProject(getProject());
2300       t.setTaskName("xml2dot");
2310       t.setFailonerror(mFailOnError);
2320       t.setIn(tmpFile);
2330       t.setForce(true);
2340       t.setDestdir(mOutDir);
2350       t.setOut(outFile);
2360       log("Generating ER diagram " + outFile, Project.MSG_VERBOSE);
2370       t.execute();
2380    }
239  
240     private void generateStateDiagram ()
241     {
2420       final XsltBasedTask t = new XsltBasedTask()
2430(3)      {
244           String getDefaultStyleSheet ()
245           {
2460             return "generate-state-diagram.xsl";
247           }
248        };
2490       t.setProject(getProject());
2500       t.setTaskName("xml2dot");
2510       t.setFailonerror(mFailOnError);
2520       t.setIn(mInFile);
2530       t.setForce(true);
2540       t.setDestdir(mOutDir);
255        try
256        {
2570          t.setOut(File.createTempFile("xdoc", ".tmp"));
258        }
2590       catch (IOException e)
260        {
2610          throw new BuildException("Cannot create temp file: " + e, e);
2620       }
2630       log("Generating state diagrams from file "
264              + mInFile, Project.MSG_VERBOSE);
2650       t.execute();
2660    }
267  /*
268     private void generateUmlDiagram (final Diagram diagram)
269     {
270        final Javadoc javadocTask = new Javadoc();
271        javadocTask.setProject(getProject());
272        javadocTask.setFailonerror(mFailOnError);
273        javadocTask.setTaskName("umlgraph");
274        javadocTask.setPackage(true);
275        javadocTask.setClasspath(mDocletPath);
276        javadocTask.setClasspath(Path.systemClasspath);
277        for (final Iterator i = mSources.iterator(); i.hasNext();)
278        {
279           final SourceDirectory fs = (SourceDirectory) i.next();
280           javadocTask.addFileset(addClasses(diagram, fs.getDir()));
281        }
282        final DocletInfo info = javadocTask.createDoclet();
283        info.setProject(getProject());
284        info.setName("gr.spinellis.umlgraph.doclet.UmlGraph");
285        info.setPath(mDocletPath);
286        addDocletParam(info, "-operations");
287        addDocletParam(info, "-visibility");
288        addDocletParam(info, "-types");
289  //      addDocletParam(info, "-noguillemot");
290        addDocletParam(info, "-nodefontname", DEFAULT_FONTNAME);
291        addDocletParam(info, "-nodefontsize", DEFAULT_FONTSIZE);
292        addDocletParam(info, "-nodefontabstractname", DEFAULT_FONTNAME);
293        addDocletParam(info, "-edgefontname", DEFAULT_FONTNAME);
294        addDocletParam(info, "-edgefontsize", DEFAULT_FONTSIZE);
295  //      final File dotFile
296  //            = new File(mOutDir, diagram.getName() + DOTTY_EXTENSION);
297  //      dotFile.getParentFile().mkdirs();
298  //      addDocletParam(info, "-output", dotFile.getAbsolutePath());
299      addDocletParam(info, "-d", mOutDir.getAbsolutePath());
300      addDocletParam(info, "-output", diagram.getName() + DOTTY_EXTENSION);
301      mOutDir.mkdirs();
302        javadocTask.execute();
303     }
304  */
305  
306     private void generateUmlDiagram (final Diagram diagram)
307     {
3080       final Javadoc javadocTask = new Javadoc();
3090       javadocTask.setProject(getProject());
3100       javadocTask.setFailonerror(mFailOnError);
3110       javadocTask.setTaskName("umlgraph");
3120       javadocTask.setPackage(true);
3130       javadocTask.setClasspath(mDocletPath);
3140       javadocTask.setClasspath(Path.systemClasspath);
3150       for (final Iterator i = mSources.iterator(); i.hasNext();)
316        {
3170          final SourceDirectory fs = (SourceDirectory) i.next();
3180          javadocTask.addFileset(addClasses(diagram, fs.getDir()));
3190       }
3200       final DocletInfo info = javadocTask.createDoclet();
3210       info.setProject(getProject());
3220       info.setName("UmlGraph");
3230       info.setPath(mDocletPath);
3240       addDocletParam(info, "-operations");
3250       addDocletParam(info, "-visibility");
3260       addDocletParam(info, "-types");
3270       addDocletParam(info, "-noguillemot");
3280       addDocletParam(info, "-nodefontname", DEFAULT_FONTNAME);
3290       addDocletParam(info, "-nodefontsize", DEFAULT_FONTSIZE);
3300       addDocletParam(info, "-nodefontabstractname", DEFAULT_FONTNAME);
3310       addDocletParam(info, "-edgefontname", DEFAULT_FONTNAME);
3320       addDocletParam(info, "-edgefontsize", DEFAULT_FONTSIZE);
3330       final File dotFile
334              = new File(mOutDir, diagram.getName() + DOTTY_EXTENSION);
3350(4)      dotFile.getParentFile().mkdirs();
3360       addDocletParam(info, "-output", dotFile.getAbsolutePath());
3370       javadocTask.execute();
3380    }
339  
340     
341     private FileSet addClasses (final Diagram diagram, File path)
342     {
3430       final FileSet filez = new FileSet();
3440       filez.setProject(getProject());
3450       filez.setDir(path);
3460       final Iterator i = diagram.classList().iterator();
3470       while (i.hasNext())
348        {
3490          final String name = (String) i.next();
3500          final NameEntry entry = filez.createInclude();
3510          final String pathName = name.replaceAll("\\.", "/") + JAVA_EXTENSION;
3520          log("Adding Source file " + pathName, Project.MSG_VERBOSE);
3530          entry.setName(pathName);
3540       }
3550       return filez;
356     }
357  
358     private void addDocletParam (DocletInfo info, String key)
359     {
3600       final DocletParam param = info.createParam();
3610       param.setName(key);
3620    }
363  
364     private void addDocletParam (DocletInfo info, String key, String value)
365     {
3660       final DocletParam param = info.createParam();
3670       param.setName(key);
3680       param.setValue(value);
3690    }
370  
371     private DiagramSaxHandler parse ()
372     {
3730(5)      final DiagramSaxHandler handler = new DiagramSaxHandler();
374        try
375        {
376           // create a new XML parser
3770          final SAXParserFactory factory = SAXParserFactory.newInstance();
3780          factory.setNamespaceAware(true);
3790          factory.setValidating(true);
3800          final SAXParser parser = factory.newSAXParser();
381           /*
382           parser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
383           parser.setProperty(JAXP_SCHEMA_SOURCE,
384                 AppInfoTask.class.getResource(APP_INFO_SCHEMA).toExternalForm());
385                 */
3860          parser.parse(new InputSource(new FileInputStream(mInFile)), handler);
3870          log(mInFile + " parsed successfully.", Project.MSG_INFO);
388        }
3890       catch (Exception e)
390        {
3910          throw new BuildException("Failed to parse " + mInFile + ": " + e, e);
3920       }
3930       return handler;
394     }
395  
396     /**
397      * Checks the attributes provided by this class.
398      * @throws BuildException
399    */
400     private void checkAttributes ()
401           throws BuildException
402     {
4030       checkAttributeInFile();
4040    }
405  
406     private void checkAttributeInFile ()
407     {
4080       if (mInFile == null)
409        {
4100          throw new BuildException(
411                 "Missing mandatory attribute 'in'.", getLocation());
412        }
4130       if (!mInFile.exists())
414        {
4150          throw new BuildException(
416                 "Input file '" + mInFile + "' not found.", getLocation());
417        }
4180    }
419  
420  
4210    private static class DiagramSaxHandler
422           extends DefaultHandler
423     {
4240       private final StringBuffer mBuffer = new StringBuffer();
4250       private boolean mCaptureCharacters = false;
426  
4270       private final List mDiagrams = new ArrayList();
4280       private Diagram mCurrentDiagram = null;
429  
430        /** {@inheritDoc} */
431        public void startElement (String uri, String localName, String qName,
432              Attributes attributes)
433        {
4340          if ("diagram".equals(localName))
435           {
4360             mCurrentDiagram = new Diagram(
437                    attributes.getValue("name"), attributes.getValue("type"));
4380             if (attributes.getValue("file") != null)
439              {
4400                mCurrentDiagram.setFile(attributes.getValue("file"));
441              }
4420             mDiagrams.add(mCurrentDiagram);
443           }
4440          else if ("class".equals(localName) && mCurrentDiagram != null)
445           {
4460             mCurrentDiagram.add(attributes.getValue("name"));
447           }
4480          else if ("description".equals(localName) && mCurrentDiagram != null)
449           {
4500             captureCharacters();
451           }
4520       }
453  
454        /** {@inheritDoc} */
455        public void endElement (String uri, String localName, String qName)
456        {
4570          if ("diagram".equals(localName))
458           {
4590             mCurrentDiagram = null;
460           }
4610          else if ("description".equals(localName) && mCurrentDiagram != null)
462           {
4630             mCurrentDiagram.setDescription(characters().trim());
464           }
465  
4660       }
467  
468        /** {@inheritDoc} */
469        public void characters (char[] ch, int start, int length)
470        {
4710          if (mCaptureCharacters)
472           {
4730             mBuffer.append(ch, start, length);
474           }
4750       }
476  
477  
478        void captureCharacters ()
479        {
4800          mCaptureCharacters = true;
4810       }
482  
483        /**
484         * Returns the captured characters and <b>clears</b> the internal
485         * buffer.
486         * @return the captured characters.
487         */
488        String characters ()
489        {
4900          final String result = mBuffer.toString();
4910          mBuffer.setLength(0);
4920          mCaptureCharacters = false;
4930          return result;
494        }
495  
496  
497        /**
498         * Returns a list of {@link Diagram}.
499         * @return a list of {@link Diagram}.
500         */
501        public List diagrams ()
502        {
5030          return Collections.unmodifiableList(mDiagrams);
504        }
505  
506     }
507  
5080    private static class Diagram
509     {
510        private final String mName;
511        private final String mType;
5120       private final List mClasses = new ArrayList();
5130       private String mDescription = "";
514        private String mFile;
515  
516        Diagram (String name, String type)
5170       {
5180          mName = name;
5190          mType = type;
5200       }
521  
522        void add (String clazz)
523        {
5240          mClasses.add(clazz);
5250       }
526  
527        List classList ()
528        {
5290          return Collections.unmodifiableList(mClasses);
530        }
531  
532        String getName ()
533        {
5340          return mName;
535        }
536  
537        String getType ()
538        {
5390          return mType;
540        }
541  
542        String getDescription ()
543        {
5440          return mDescription;
545        }
546  
547        void setDescription (String description)
548        {
5490          mDescription = description;
5500       }
551  
552        String getFile ()
553        {
5540          return mFile;
555        }
556  
557        void setFile (String file)
558        {
5590          mFile = file;
5600       }
561  
562        /** {@inheritDoc} */
563        public String toString ()
564        {
5650(6)         final StringBuffer sb = new StringBuffer();
5660          sb.append("diagram ");
5670          sb.append(mName);
5680          sb.append(" (");
5690          sb.append(mType);
5700          sb.append(") = ");
5710          sb.append(mClasses);
5720          sb.append(" description: '");
5730          sb.append(mDescription);
5740          sb.append('\'');
5750          return sb.toString();
576        }
577     }
578  }

Findings in this File

c (7) Got an exception - java.lang.RuntimeException: Unable to get class information for @throws tag 'BuildException'.
i (1) 115 : 0 Comment matches to-do format '(TODO|FIXME|CHECKME)'.
i (2) 223 : 0 The class org.jcoderz.commons.taskdefs.DiagramTask$1 could be refactored into a named _static_ inner class
i (3) 243 : 0 The class org.jcoderz.commons.taskdefs.DiagramTask$2 could be refactored into a named _static_ inner class
w (4) 335 : 0 org.jcoderz.commons.taskdefs.DiagramTask.generateUmlDiagram(DiagramTask$Diagram) ignores exceptional return value of java.io.File.mkdirs()
c (5) 373 : 0 Copied and pasted code. 150 equal tokens (49 lines) found in 2 locations. See also: org.jcoderz.commons.taskdefs.ApiDocTask:254
i (6) 565 : 29 StringBuffer constructor is initialized with size 16, but has at least 31 characters appended.