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 }