View Javadoc

1   /*
2    PlantUMLDependencyOutputOptionExecution.java
3    Creation date : 9/06/2010
4    Copyright © Benjamin Croizet (graffity2199@yahoo.fr)
5   
6    This program is free software; you can redistribute it and/or
7    modify it under the terms of the GNU General Public License
8    or GNU Lesser General Public License as published by the
9    Free Software Foundation; either version 3 of the License,
10   or (at your option) any later version.
11  
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16  
17   You should have received copies of the GNU General Public License
18   and GNU Lesser General Public License along with this program;
19   if not, write to the Free Software Foundation, Inc.,
20   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21   http://www.fsf.org/licensing/licenses/gpl.html
22   http://www.gnu.org/licenses/lgpl.html
23   */
24  
25  package net.sourceforge.plantumldependency.cli.main.option.output;
26  
27  import static java.util.logging.Level.INFO;
28  import static java.util.logging.Level.SEVERE;
29  import static java.util.logging.Logger.getLogger;
30  import static net.sourceforge.plantumldependency.cli.constants.log.ErrorConstants.READING_SOURCE_FILE_ERROR;
31  import static net.sourceforge.plantumldependency.cli.constants.log.InfoConstants.TREATED_DEPENDENCY_INFO;
32  import static net.sourceforge.plantumldependency.common.utils.file.FileUtils.readFileIntoString;
33  import static net.sourceforge.plantumldependency.common.utils.file.FileUtils.writeIntoFile;
34  import static net.sourceforge.plantumldependency.common.utils.log.LogUtils.buildLogString;
35  
36  import java.io.File;
37  import java.util.Iterator;
38  import java.util.Set;
39  import java.util.TreeSet;
40  import java.util.logging.Logger;
41  import java.util.regex.Pattern;
42  
43  import net.sourceforge.plantumldependency.cli.exception.PlantUMLDependencyException;
44  import net.sourceforge.plantumldependency.cli.generic.GenericDependency;
45  import net.sourceforge.plantumldependency.cli.main.option.display.type.argument.DisplayType;
46  import net.sourceforge.plantumldependency.cli.main.option.programminglanguage.argument.ProgrammingLanguage;
47  import net.sourceforge.plantumldependency.cli.main.option.programminglanguage.context.ProgrammingLanguageContext;
48  import net.sourceforge.plantumldependency.cli.plantumldiagram.PlantUMLDiagram;
49  import net.sourceforge.plantumldependency.commoncli.exception.CommandLineException;
50  import net.sourceforge.plantumldependency.commoncli.option.execution.AbstractOptionExecution;
51  import net.sourceforge.plantumldependency.commoncli.option.execution.OptionExecution;
52  
53  import org.apache.tools.ant.types.FileSet;
54  import org.apache.tools.ant.types.resources.FileResource;
55  
56  /**
57   * The default option execution associated to the "-o" option, allowing to specify an output file,
58   * processing the input source files and generating the plantUML description.
59   *
60   * @author Benjamin Croizet (<a href="mailto:graffity2199@yahoo.fr>graffity2199@yahoo.fr</a>)
61   * @since 1.0.0
62   * @version 1.4.0
63   */
64  public class PlantUMLDependencyOutputOptionExecution extends AbstractOptionExecution {
65  
66      /** Serial version UID. */
67      private static final long serialVersionUID = 2237748681247499173L;
68  
69      /** The class logger. */
70      private static final transient Logger LOGGER = getLogger(PlantUMLDependencyOutputOptionExecution.class.getName());
71  
72      /**
73       * Creates a dependencies {@link ProgrammingLanguageContext} following a set of files in the
74       * passed programming language. This methods parses each source files of the set in order to add
75       * them in the context.
76       *
77       * @param language
78       *            the programming language of the source files to parse, mustn't be
79       *            <code>null</code>.
80       * @param includeExcludeFiles
81       *            the {@link FileSet} describing all files to include or exclude and also the base
82       *            directory where to look for, mustn't be <code>null</code>.
83       * @param displayTypesOpts
84       *            the {@link Set} of display types options which filter type to appear in the
85       *            plantUML description, mustn't be <code>null</code>.
86       * @param displayPackageNamePattern
87       *            the {@link Pattern} which filter package name to appear in the plantUML
88       *            description, mustn't be <code>null</code>.
89       * @param displayNamePattern
90       *            the {@link Pattern} which filter name to appear in the plantUML description,
91       *            mustn't be <code>null</code>.
92       * @return the {@link ProgrammingLanguageContext} instance containing all parsed
93       *         {@link GenericDependency}.
94       * @since 1.0.0
95       */
96      private static ProgrammingLanguageContext readDependenciesContextFromFiles(final ProgrammingLanguage language,
97              final FileSet includeExcludeFiles, final Set < DisplayType > displayTypesOpts,
98              final Pattern displayPackageNamePattern, final Pattern displayNamePattern) {
99          final ProgrammingLanguageContext programmingLanguageContext = language.createNewContext(displayTypesOpts,
100                 displayPackageNamePattern, displayNamePattern);
101 
102         final Iterator < FileResource > iter = includeExcludeFiles.iterator();
103         while (iter.hasNext()) {
104             final FileResource fileResource = iter.next();
105 
106             try {
107                 readDependencyFromFile(fileResource.getFile(), programmingLanguageContext, language);
108             } catch (final PlantUMLDependencyException e) {
109                 LOGGER.log(SEVERE, buildLogString(READING_SOURCE_FILE_ERROR, fileResource.getFile()));
110                 LOGGER.log(INFO, e.getMessage(), e);
111             }
112         }
113 
114         programmingLanguageContext.removeAllPotentialJavaLangSeenDependencyAndChangePackageToJavaLang();
115         return programmingLanguageContext;
116     }
117 
118     /**
119      * Creates a dependency following a single file in the passed programming language. Also updates
120      * the dependencies {@link java.util.Map} with other dependency seen in the source file.
121      *
122      * @param file
123      *            the source file to parse, mustn't be <code>null</code>.
124      * @param programmingLanguageContext
125      *            the context instance containing all dependencies which have already been seen in
126      *            previous treatment, and other information which can be shared when parsing several
127      *            source files, mustn't be <code>null</code>.
128      * @param language
129      *            the programming language of the source files to parse, mustn't be
130      *            <code>null</code>.
131      * @return the {@link GenericDependency} instance parsed in the source file, may be
132      *         <code>null</code> if the context display options doesn't manage the dependency type.
133      * @throws PlantUMLDependencyException
134      *             if any parsing exception occurs while reading the source file.
135      * @since 1.0.0
136      */
137     private static GenericDependency readDependencyFromFile(final File file,
138             final ProgrammingLanguageContext programmingLanguageContext, final ProgrammingLanguage language)
139             throws PlantUMLDependencyException {
140         final String sourceFileContent = readFileIntoString(file);
141         return language.readDependencyFromFile(sourceFileContent, programmingLanguageContext);
142     }
143 
144     /** The output file where to generate the plantUML description. */
145     private File outputFile;
146 
147     /**
148      * The {@link FileSet} describing all files to include or exclude and also the base directory
149      * where to look for.
150      */
151     // FIXME should have a serializable input file set
152     private transient FileSet inputFileSet;
153 
154     /** The programming language to parse. */
155     private ProgrammingLanguage programmingLanguage;
156 
157     /** The display types options which have to appear in the plantUML description. */
158     private Set < DisplayType > displayTypesOptions;
159 
160     /**
161      * The display package name pattern which have to appear in the plantUML description, mustn't be
162      * <code>null</code>.
163      */
164     private Pattern displayPackageNamePattern;
165 
166     /**
167      * The display name pattern which have to appear in the plantUML description, mustn't be
168      * <code>null</code>.
169      */
170     private Pattern displayNamePattern;
171 
172     /**
173      * Default constructor.
174      *
175      * @param file
176      *            the output file where to generate the plantUML description, mustn't be
177      *            <code>null</code>.
178      * @param language
179      *            The programming language to parse, mustn't be <code>null</code>.
180      * @param includeExcludeFiles
181      *            the {@link FileSet} describing all files to include or exclude and also the base
182      *            directory where to look for, mustn't be <code>null</code>.
183      * @param displayTypesOpts
184      *            the {@link Set} of display types options which filter type to appear in the
185      *            plantUML description, mustn't be <code>null</code>.
186      * @param displayPackageNamePatternOpt
187      *            the {@link Pattern} which filter package name to appear in the plantUML
188      *            description, mustn't be <code>null</code>.
189      * @param displayNamePatternOpt
190      *            the {@link Pattern} which filter name to appear in the plantUML description,
191      *            mustn't be <code>null</code>.
192      * @param optionPriority
193      *            the option priority as an integer. <i>Note : the priority must be unique amongst
194      *            all options</i>.
195      * @since 1.0.0
196      */
197     public PlantUMLDependencyOutputOptionExecution(final File file, final ProgrammingLanguage language,
198             final FileSet includeExcludeFiles, final Set < DisplayType > displayTypesOpts,
199             final Pattern displayPackageNamePatternOpt, final Pattern displayNamePatternOpt, final int optionPriority) {
200         super(optionPriority);
201         setOutputFile(file);
202         setInputFileSet(includeExcludeFiles);
203         setProgrammingLanguage(language);
204         setDisplayTypesOptions(displayTypesOpts);
205         setDisplayPackageNamePattern(displayPackageNamePatternOpt);
206         setDisplayNamePattern(displayNamePatternOpt);
207     }
208 
209     /**
210      * {@inheritDoc}
211      *
212      * @since 1.0.0
213      */
214     @Override
215     public OptionExecution deepClone() {
216         final PlantUMLDependencyOutputOptionExecution p = (PlantUMLDependencyOutputOptionExecution) super.deepClone();
217         p.outputFile = new File(outputFile.getAbsolutePath());
218         p.inputFileSet = (FileSet) inputFileSet.clone();
219         p.displayTypesOptions = new TreeSet < DisplayType >(displayTypesOptions);
220         p.displayPackageNamePattern = displayPackageNamePattern;
221         p.displayNamePattern = displayNamePattern;
222         return p;
223     }
224 
225     /**
226      * {@inheritDoc}
227      *
228      * @since 1.0.0
229      */
230     @Override
231     public void execute() throws CommandLineException {
232         final ProgrammingLanguageContext programmingLanguageContext = readDependenciesContextFromFiles(
233                 getProgrammingLanguage(), getInputFileSet(), getDisplayTypesOptions(), getDisplayPackageNamePattern(),
234                 getDisplayNamePattern());
235         final PlantUMLDiagram plantUMLDiagram = programmingLanguageContext.getPlantUMLClassesDiagram();
236         writeIntoFile(plantUMLDiagram.getPlantUMLTextDescription(), getOutputFile());
237         LOGGER.log(INFO,
238                 buildLogString(TREATED_DEPENDENCY_INFO, programmingLanguageContext.getParsedDependencies().size()));
239     }
240 
241     /**
242      * Gets the value of <code>displayNamePattern</code>.
243      *
244      * @return the value of <code>displayNamePattern</code>.
245      * @see #setDisplayNamePattern(Pattern)
246      * @since 1.4.0
247      */
248     private Pattern getDisplayNamePattern() {
249         return displayNamePattern;
250     }
251 
252     /**
253      * Gets the value of <code>displayPackageNamePattern</code>.
254      *
255      * @return the value of <code>displayPackageNamePattern</code>.
256      * @see #setDisplayPackageNamePattern(Pattern)
257      * @since 1.4.0
258      */
259     private Pattern getDisplayPackageNamePattern() {
260         return displayPackageNamePattern;
261     }
262 
263     /**
264      * Gets the value of <code>displayTypesOptions</code>.
265      *
266      * @return the value of <code>displayTypesOptions</code>.
267      * @see #setDisplayTypesOptions(Set)
268      * @since 1.0.0
269      */
270     private Set < DisplayType > getDisplayTypesOptions() {
271         return displayTypesOptions;
272     }
273 
274     /**
275      * Gets the value of <code>inputFileSet</code>.
276      *
277      * @return the value of <code>inputFileSet</code>.
278      * @see #setInputFileSet(FileSet)
279      * @since 1.0.0
280      */
281     private FileSet getInputFileSet() {
282         return inputFileSet;
283     }
284 
285     /**
286      * Gets the value of <code>outputFile</code>.
287      *
288      * @return the value of <code>outputFile</code>.
289      * @see #setOutputFile(File)
290      * @since 1.0.0
291      */
292     private File getOutputFile() {
293         return outputFile;
294     }
295 
296     /**
297      * Gets the value of <code>programmingLanguage</code>.
298      *
299      * @return the value of <code>programmingLanguage</code>.
300      * @see #setProgrammingLanguage(ProgrammingLanguage)
301      * @since 1.0.0
302      */
303     private ProgrammingLanguage getProgrammingLanguage() {
304         return programmingLanguage;
305     }
306 
307     /**
308      * Sets the value of <code>displayNamePattern</code>.
309      *
310      * @param value
311      *            the <code>displayNamePattern</code> to set, can be <code>null</code>.
312      * @see #getDisplayNamePattern()
313      * @since 1.4.0
314      */
315     private void setDisplayNamePattern(final Pattern value) {
316         displayNamePattern = value;
317     }
318 
319     /**
320      * Sets the value of <code>displayPackageNamePattern</code>.
321      *
322      * @param value
323      *            the <code>displayPackageNamePattern</code> to set, can be <code>null</code>.
324      * @see #getDisplayPackageNamePattern()
325      * @since 1.4.0
326      */
327     private void setDisplayPackageNamePattern(final Pattern value) {
328         displayPackageNamePattern = value;
329     }
330 
331     /**
332      * Sets the value of <code>displayTypesOptions</code>.
333      *
334      * @param value
335      *            the <code>displayTypesOptions</code> to set, can be <code>null</code>.
336      * @see #getDisplayTypesOptions()
337      * @since 1.0.0
338      */
339     private void setDisplayTypesOptions(final Set < DisplayType > value) {
340         displayTypesOptions = value;
341     }
342 
343     /**
344      * Sets the value of <code>inputFileSet</code>.
345      *
346      * @param value
347      *            the <code>inputFileSet</code> to set, can be <code>null</code>.
348      * @see #getInputFileSet()
349      * @since 1.0.0
350      */
351     private void setInputFileSet(final FileSet value) {
352         inputFileSet = value;
353     }
354 
355     /**
356      * Sets the value of <code>outputFile</code>.
357      *
358      * @param value
359      *            the <code>outputFile</code> to set, can be <code>null</code>.
360      * @see #getOutputFile()
361      * @since 1.0.0
362      */
363     private void setOutputFile(final File value) {
364         outputFile = value;
365     }
366 
367     /**
368      * Sets the value of <code>programmingLanguage</code>.
369      *
370      * @param value
371      *            the <code>programmingLanguage</code> to set, can be <code>null</code>.
372      * @see #getProgrammingLanguage()
373      * @since 1.0.0
374      */
375     private void setProgrammingLanguage(final ProgrammingLanguage value) {
376         programmingLanguage = value;
377     }
378 }