1 | /* |
2 | * Copyright (C) Christian Schulte, 2005-206 |
3 | * All rights reserved. |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions |
7 | * are met: |
8 | * |
9 | * o Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. |
11 | * |
12 | * o Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in |
14 | * the documentation and/or other materials provided with the |
15 | * distribution. |
16 | * |
17 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
18 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
19 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL |
20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, |
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | * |
28 | * $JOMC: ToolsModelProcessor.java 4201 2012-01-25 09:47:12Z schulte2005 $ |
29 | * |
30 | */ |
31 | package org.jomc.tools.modlet; |
32 | |
33 | import java.lang.reflect.Field; |
34 | import java.text.MessageFormat; |
35 | import java.util.List; |
36 | import java.util.Locale; |
37 | import java.util.ResourceBundle; |
38 | import java.util.logging.Level; |
39 | import org.jomc.model.Dependencies; |
40 | import org.jomc.model.Implementation; |
41 | import org.jomc.model.Messages; |
42 | import org.jomc.model.Module; |
43 | import org.jomc.model.Modules; |
44 | import org.jomc.model.Properties; |
45 | import org.jomc.model.Specification; |
46 | import org.jomc.model.Specifications; |
47 | import org.jomc.model.modlet.ModelHelper; |
48 | import org.jomc.modlet.Model; |
49 | import org.jomc.modlet.ModelContext; |
50 | import org.jomc.modlet.ModelException; |
51 | import org.jomc.modlet.ModelProcessor; |
52 | import org.jomc.tools.JomcTool; |
53 | import org.jomc.tools.model.SourceFileType; |
54 | import org.jomc.tools.model.SourceFilesType; |
55 | import org.jomc.tools.model.SourceSectionType; |
56 | import org.jomc.tools.model.SourceSectionsType; |
57 | import static org.jomc.tools.modlet.ToolsModletConstants.*; |
58 | |
59 | /** |
60 | * Object management and configuration tools {@code ModelProcessor} implementation. |
61 | * |
62 | * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a> |
63 | * @version $JOMC: ToolsModelProcessor.java 4201 2012-01-25 09:47:12Z schulte2005 $ |
64 | * @see ModelContext#processModel(org.jomc.modlet.Model) |
65 | * @since 1.2 |
66 | */ |
67 | public class ToolsModelProcessor implements ModelProcessor |
68 | { |
69 | |
70 | /** |
71 | * Constant for the name of the model context attribute backing property {@code enabled}. |
72 | * @see #processModel(org.jomc.modlet.ModelContext, org.jomc.modlet.Model) |
73 | * @see ModelContext#getAttribute(java.lang.String) |
74 | */ |
75 | public static final String ENABLED_ATTRIBUTE_NAME = "org.jomc.tools.modlet.ToolsModelProcessor.enabledAttribute"; |
76 | |
77 | /** |
78 | * Constant for the name of the system property controlling property {@code defaultEnabled}. |
79 | * @see #isDefaultEnabled() |
80 | */ |
81 | private static final String DEFAULT_ENABLED_PROPERTY_NAME = |
82 | "org.jomc.tools.modlet.ToolsModelProcessor.defaultEnabled"; |
83 | |
84 | /** |
85 | * Default value of the flag indicating the processor is enabled by default. |
86 | * @see #isDefaultEnabled() |
87 | */ |
88 | private static final Boolean DEFAULT_ENABLED = Boolean.TRUE; |
89 | |
90 | /** Flag indicating the processor is enabled by default. */ |
91 | private static volatile Boolean defaultEnabled; |
92 | |
93 | /** Flag indicating the processor is enabled. */ |
94 | private Boolean enabled; |
95 | |
96 | /** |
97 | * Constant for the name of the model context attribute backing property |
98 | * {@code modelObjectClasspathResolutionEnabled}. |
99 | * |
100 | * @see #processModel(org.jomc.modlet.ModelContext, org.jomc.modlet.Model) |
101 | * @see ModelContext#getAttribute(java.lang.String) |
102 | */ |
103 | public static final String MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME = |
104 | "org.jomc.tools.modlet.ToolsModelProcessor.modelObjectClasspathResolutionEnabledAttribute"; |
105 | |
106 | /** |
107 | * Constant for the name of the system property controlling property |
108 | * {@code defaultModelObjectClasspathResolutionEnabled}. |
109 | * @see #isDefaultModelObjectClasspathResolutionEnabled() |
110 | */ |
111 | private static final String DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_PROPERTY_NAME = |
112 | "org.jomc.tools.modlet.ToolsModelProcessor.defaultModelObjectClasspathResolutionEnabled"; |
113 | |
114 | /** |
115 | * Default value of the flag indicating model object class path resolution is enabled by default. |
116 | * @see #isDefaultModelObjectClasspathResolutionEnabled() |
117 | */ |
118 | private static final Boolean DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED = Boolean.TRUE; |
119 | |
120 | /** Flag indicating model object class path resolution is enabled by default. */ |
121 | private static volatile Boolean defaultModelObjectClasspathResolutionEnabled; |
122 | |
123 | /** Flag indicating model object class path resolution is enabled. */ |
124 | private Boolean modelObjectClasspathResolutionEnabled; |
125 | |
126 | /** Creates a new {@code ToolsModelProcessor} instance. */ |
127 | public ToolsModelProcessor() |
128 | { |
129 | super(); |
130 | } |
131 | |
132 | /** |
133 | * Gets a flag indicating the processor is enabled by default. |
134 | * <p>The default enabled flag is controlled by system property |
135 | * {@code org.jomc.tools.modlet.ToolsModelProcessor.defaultEnabled} holding a value indicating the processor is |
136 | * enabled by default. If that property is not set, the {@code true} default is returned.</p> |
137 | * |
138 | * @return {@code true}, if the processor is enabled by default; {@code false}, if the processor is disabled by |
139 | * default. |
140 | * |
141 | * @see #setDefaultEnabled(java.lang.Boolean) |
142 | */ |
143 | public static boolean isDefaultEnabled() |
144 | { |
145 | if ( defaultEnabled == null ) |
146 | { |
147 | defaultEnabled = Boolean.valueOf( System.getProperty( DEFAULT_ENABLED_PROPERTY_NAME, |
148 | Boolean.toString( DEFAULT_ENABLED ) ) ); |
149 | |
150 | } |
151 | |
152 | return defaultEnabled; |
153 | } |
154 | |
155 | /** |
156 | * Sets the flag indicating the processor is enabled by default. |
157 | * |
158 | * @param value The new value of the flag indicating the processor is enabled by default or {@code null}. |
159 | * |
160 | * @see #isDefaultEnabled() |
161 | */ |
162 | public static void setDefaultEnabled( final Boolean value ) |
163 | { |
164 | defaultEnabled = value; |
165 | } |
166 | |
167 | /** |
168 | * Gets a flag indicating the processor is enabled. |
169 | * |
170 | * @return {@code true}, if the processor is enabled; {@code false}, if the processor is disabled. |
171 | * |
172 | * @see #isDefaultEnabled() |
173 | * @see #setEnabled(java.lang.Boolean) |
174 | */ |
175 | public final boolean isEnabled() |
176 | { |
177 | if ( this.enabled == null ) |
178 | { |
179 | this.enabled = isDefaultEnabled(); |
180 | } |
181 | |
182 | return this.enabled; |
183 | } |
184 | |
185 | /** |
186 | * Sets the flag indicating the processor is enabled. |
187 | * |
188 | * @param value The new value of the flag indicating the processor is enabled or {@code null}. |
189 | * |
190 | * @see #isEnabled() |
191 | */ |
192 | public final void setEnabled( final Boolean value ) |
193 | { |
194 | this.enabled = value; |
195 | } |
196 | |
197 | /** |
198 | * Gets a flag indicating model object class path resolution is enabled by default. |
199 | * <p>The model object class path resolution default enabled flag is controlled by system property |
200 | * {@code org.jomc.tools.modlet.ToolsModelProcessor.defaultModelObjectClasspathResolutionEnabled} holding a value |
201 | * indicating model object class path resolution is enabled by default. If that property is not set, the |
202 | * {@code true} default is returned.</p> |
203 | * |
204 | * @return {@code true}, if model object class path resolution is enabled by default; {@code false}, if model object |
205 | * class path resolution is disabled by default. |
206 | * |
207 | * @see #setDefaultModelObjectClasspathResolutionEnabled(java.lang.Boolean) |
208 | */ |
209 | public static boolean isDefaultModelObjectClasspathResolutionEnabled() |
210 | { |
211 | if ( defaultModelObjectClasspathResolutionEnabled == null ) |
212 | { |
213 | defaultModelObjectClasspathResolutionEnabled = Boolean.valueOf( System.getProperty( |
214 | DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_PROPERTY_NAME, |
215 | Boolean.toString( DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED ) ) ); |
216 | |
217 | } |
218 | |
219 | return defaultModelObjectClasspathResolutionEnabled; |
220 | } |
221 | |
222 | /** |
223 | * Sets the flag indicating model object class path resolution is enabled by default. |
224 | * |
225 | * @param value The new value of the flag indicating model object class path resolution is enabled by default or |
226 | * {@code null}. |
227 | * |
228 | * @see #isDefaultModelObjectClasspathResolutionEnabled() |
229 | */ |
230 | public static void setDefaultModelObjectClasspathResolutionEnabled( final Boolean value ) |
231 | { |
232 | defaultModelObjectClasspathResolutionEnabled = value; |
233 | } |
234 | |
235 | /** |
236 | * Gets a flag indicating model object class path resolution is enabled. |
237 | * |
238 | * @return {@code true}, if model object class path resolution is enabled; {@code false}, if model object class path |
239 | * resolution is disabled. |
240 | * |
241 | * @see #isDefaultModelObjectClasspathResolutionEnabled() |
242 | * @see #setModelObjectClasspathResolutionEnabled(java.lang.Boolean) |
243 | */ |
244 | public final boolean isModelObjectClasspathResolutionEnabled() |
245 | { |
246 | if ( this.modelObjectClasspathResolutionEnabled == null ) |
247 | { |
248 | this.modelObjectClasspathResolutionEnabled = isDefaultModelObjectClasspathResolutionEnabled(); |
249 | } |
250 | |
251 | return this.modelObjectClasspathResolutionEnabled; |
252 | } |
253 | |
254 | /** |
255 | * Sets the flag indicating model object class path resolution is is enabled. |
256 | * |
257 | * @param value The new value of the flag indicating model object class path resolution is enabled or {@code null}. |
258 | * |
259 | * @see #isModelObjectClasspathResolutionEnabled() |
260 | */ |
261 | public final void setModelObjectClasspathResolutionEnabled( final Boolean value ) |
262 | { |
263 | this.modelObjectClasspathResolutionEnabled = value; |
264 | } |
265 | |
266 | /** |
267 | * {@inheritDoc} |
268 | * |
269 | * @see #isEnabled() |
270 | * @see #isModelObjectClasspathResolutionEnabled() |
271 | * @see #ENABLED_ATTRIBUTE_NAME |
272 | * @see #MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME |
273 | */ |
274 | public Model processModel( final ModelContext context, final Model model ) throws ModelException |
275 | { |
276 | if ( context == null ) |
277 | { |
278 | throw new NullPointerException( "context" ); |
279 | } |
280 | if ( model == null ) |
281 | { |
282 | throw new NullPointerException( "model" ); |
283 | } |
284 | |
285 | Model processed = model; |
286 | |
287 | boolean contextEnabled = this.isEnabled(); |
288 | if ( DEFAULT_ENABLED == contextEnabled && context.getAttribute( ENABLED_ATTRIBUTE_NAME ) instanceof Boolean ) |
289 | { |
290 | contextEnabled = (Boolean) context.getAttribute( ENABLED_ATTRIBUTE_NAME ); |
291 | } |
292 | |
293 | boolean contextModelObjectClasspathResolutionEnabled = this.isModelObjectClasspathResolutionEnabled(); |
294 | if ( contextModelObjectClasspathResolutionEnabled == DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED |
295 | && context.getAttribute( MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME ) instanceof Boolean ) |
296 | { |
297 | contextModelObjectClasspathResolutionEnabled = |
298 | (Boolean) context.getAttribute( MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME ); |
299 | |
300 | } |
301 | |
302 | if ( contextEnabled ) |
303 | { |
304 | processed = model.clone(); |
305 | final Modules modules = ModelHelper.getModules( processed ); |
306 | |
307 | if ( modules != null ) |
308 | { |
309 | Module classpathModule = null; |
310 | if ( contextModelObjectClasspathResolutionEnabled ) |
311 | { |
312 | classpathModule = modules.getClasspathModule( Modules.getDefaultClasspathModuleName(), |
313 | context.getClassLoader() ); |
314 | |
315 | if ( classpathModule != null |
316 | && modules.getModule( Modules.getDefaultClasspathModuleName() ) == null ) |
317 | { |
318 | modules.getModule().add( classpathModule ); |
319 | } |
320 | else |
321 | { |
322 | classpathModule = null; |
323 | } |
324 | } |
325 | |
326 | final JomcTool tool = new JomcTool(); |
327 | tool.setModel( processed ); |
328 | |
329 | if ( modules.getSpecifications() != null ) |
330 | { |
331 | for ( int i = 0, s0 = modules.getSpecifications().getSpecification().size(); i < s0; i++ ) |
332 | { |
333 | final Specification specification = modules.getSpecifications().getSpecification().get( i ); |
334 | final SourceFileType sourceFileType = specification.getAnyObject( SourceFileType.class ); |
335 | final SourceFilesType sourceFilesType = specification.getAnyObject( SourceFilesType.class ); |
336 | |
337 | if ( sourceFileType != null ) |
338 | { |
339 | if ( sourceFileType.getLocation() == null && specification.getClazz() != null ) |
340 | { |
341 | // As of 1.2, the 'location' attribute got updated from 'required' to 'optional'. |
342 | sourceFileType.setLocation( new StringBuilder( specification.getClazz().length() + 5 ). |
343 | append( specification.getClazz().replace( '.', '/' ) ).append( ".java" ). |
344 | toString() ); |
345 | |
346 | } |
347 | |
348 | if ( sourceFileType.getHeadComment() == null ) |
349 | { |
350 | // As of 1.2, the 'head-comment' and 'tail-comment' attributes got introduced. |
351 | sourceFileType.setHeadComment( "//" ); |
352 | } |
353 | } |
354 | |
355 | if ( sourceFilesType != null ) |
356 | { |
357 | this.applyDefaults( tool, specification, sourceFilesType ); |
358 | } |
359 | } |
360 | } |
361 | |
362 | if ( modules.getImplementations() != null ) |
363 | { |
364 | for ( int i = 0, s0 = modules.getImplementations().getImplementation().size(); i < s0; i++ ) |
365 | { |
366 | final Implementation implementation = modules.getImplementations().getImplementation().get( i ); |
367 | final SourceFileType sourceFileType = implementation.getAnyObject( SourceFileType.class ); |
368 | final SourceFilesType sourceFilesType = implementation.getAnyObject( SourceFilesType.class ); |
369 | |
370 | if ( sourceFileType != null ) |
371 | { |
372 | if ( sourceFileType.getLocation() == null && implementation.getClazz() != null ) |
373 | { |
374 | // As of 1.2, the 'location' attribute got updated from 'required' to 'optional'. |
375 | sourceFileType.setLocation( new StringBuilder( implementation.getClazz().length() + 5 ). |
376 | append( implementation.getClazz().replace( '.', '/' ) ).append( ".java" ). |
377 | toString() ); |
378 | |
379 | } |
380 | |
381 | if ( sourceFileType.getHeadComment() == null ) |
382 | { |
383 | // As of 1.2, the 'head-comment' and 'tail-comment' attributes got introduced. |
384 | sourceFileType.setHeadComment( "//" ); |
385 | } |
386 | } |
387 | |
388 | if ( sourceFilesType != null ) |
389 | { |
390 | this.applyDefaults( tool, implementation, sourceFilesType ); |
391 | } |
392 | } |
393 | } |
394 | |
395 | if ( classpathModule != null ) |
396 | { |
397 | modules.getModule().remove( classpathModule ); |
398 | } |
399 | } |
400 | } |
401 | else if ( context.isLoggable( Level.FINER ) ) |
402 | { |
403 | context.log( Level.FINER, getMessage( "disabled", this.getClass().getSimpleName(), |
404 | model.getIdentifier() ), null ); |
405 | |
406 | } |
407 | |
408 | return processed; |
409 | } |
410 | |
411 | /** |
412 | * Updates any optional attributes to default values. |
413 | * |
414 | * @param tool The tool to use for creating type names. |
415 | * @param specification The specification corresponding to {@code sourceFilesType}. |
416 | * @param sourceFilesType The model to update. |
417 | * |
418 | * @throws NullPointerException if {@code tool}, {@code specification} or {@code sourceFilesType} is {@code null}. |
419 | */ |
420 | private void applyDefaults( final JomcTool tool, final Specification specification, |
421 | final SourceFilesType sourceFilesType ) |
422 | { |
423 | if ( tool == null ) |
424 | { |
425 | throw new NullPointerException( "tool" ); |
426 | } |
427 | if ( specification == null ) |
428 | { |
429 | throw new NullPointerException( "specification" ); |
430 | } |
431 | if ( sourceFilesType == null ) |
432 | { |
433 | throw new NullPointerException( "sourceFilesType" ); |
434 | } |
435 | |
436 | for ( int i = 0, s0 = sourceFilesType.getSourceFile().size(); i < s0; i++ ) |
437 | { |
438 | final SourceFileType s = sourceFilesType.getSourceFile().get( i ); |
439 | |
440 | if ( s.getTemplate() == null ) |
441 | { |
442 | s.setTemplate( SPECIFICATION_TEMPLATE ); |
443 | } |
444 | if ( s.getLocation() == null && specification.getClazz() != null ) |
445 | { |
446 | s.setLocation( new StringBuilder( specification.getClazz().length() + 5 ).append( |
447 | specification.getClazz().replace( '.', '/' ) ).append( ".java" ).toString() ); |
448 | |
449 | } |
450 | if ( s.getHeadComment() == null ) |
451 | { |
452 | s.setHeadComment( "//" ); |
453 | } |
454 | |
455 | this.applyDefaults( tool, specification, s.getSourceSections() ); |
456 | } |
457 | } |
458 | |
459 | /** |
460 | * Updates any optional attributes to default values. |
461 | * |
462 | * @param tool The tool to use for creating type names. |
463 | * @param specification The specification corresponding to {@code sourceSectionsType}. |
464 | * @param sourceSectionsType The model to update or {@code null}. |
465 | * |
466 | * @throws NullPointerException if {@code tool} or {@code specification} is {@code null}. |
467 | */ |
468 | private void applyDefaults( final JomcTool tool, final Specification specification, |
469 | final SourceSectionsType sourceSectionsType ) |
470 | { |
471 | if ( tool == null ) |
472 | { |
473 | throw new NullPointerException( "tool" ); |
474 | } |
475 | if ( specification == null ) |
476 | { |
477 | throw new NullPointerException( "specification" ); |
478 | } |
479 | |
480 | try |
481 | { |
482 | if ( sourceSectionsType != null ) |
483 | { |
484 | for ( int i = 0, s0 = sourceSectionsType.getSourceSection().size(); i < s0; i++ ) |
485 | { |
486 | final SourceSectionType s = sourceSectionsType.getSourceSection().get( i ); |
487 | |
488 | if ( LICENSE_SECTION_NAME.equals( s.getName() ) ) |
489 | { |
490 | if ( !isFieldSet( s, "optional" ) ) |
491 | { |
492 | s.setOptional( true ); |
493 | } |
494 | if ( s.getHeadTemplate() == null ) |
495 | { |
496 | s.setHeadTemplate( SPECIFICATION_LICENSE_TEMPLATE ); |
497 | } |
498 | } |
499 | |
500 | if ( ANNOTATIONS_SECTION_NAME.equals( s.getName() ) ) |
501 | { |
502 | if ( s.getHeadTemplate() == null ) |
503 | { |
504 | s.setHeadTemplate( SPECIFICATION_ANNOTATIONS_TEMPLATE ); |
505 | } |
506 | } |
507 | |
508 | if ( DOCUMENTATION_SECTION_NAME.equals( s.getName() ) ) |
509 | { |
510 | if ( !isFieldSet( s, "optional" ) ) |
511 | { |
512 | s.setOptional( true ); |
513 | } |
514 | if ( s.getHeadTemplate() == null ) |
515 | { |
516 | s.setHeadTemplate( SPECIFICATION_DOCUMENTATION_TEMPLATE ); |
517 | } |
518 | } |
519 | |
520 | final String javaTypeName = tool.getJavaTypeName( specification, false ); |
521 | if ( javaTypeName != null ) |
522 | { |
523 | if ( javaTypeName.equals( s.getName() ) ) |
524 | { |
525 | if ( !isFieldSet( s, "editable" ) ) |
526 | { |
527 | s.setEditable( true ); |
528 | } |
529 | if ( !isFieldSet( s, "indentationLevel" ) ) |
530 | { |
531 | s.setIndentationLevel( 1 ); |
532 | } |
533 | } |
534 | } |
535 | |
536 | this.applyDefaults( tool, specification, s.getSourceSections() ); |
537 | } |
538 | } |
539 | } |
540 | catch ( final NoSuchFieldException e ) |
541 | { |
542 | throw new AssertionError( e ); |
543 | } |
544 | } |
545 | |
546 | /** |
547 | * Updates any optional attributes to default values. |
548 | * |
549 | * @param tool The tool to use for creating type names. |
550 | * @param implementation The implementation corresponding to {@code sourceFilesType}. |
551 | * @param sourceFilesType The model to update. |
552 | * |
553 | * @throws NullPointerException if {@code tool}, {@code implementation} or {@code sourceFilesType} is {@code null}. |
554 | */ |
555 | private void applyDefaults( final JomcTool tool, final Implementation implementation, |
556 | final SourceFilesType sourceFilesType ) |
557 | { |
558 | if ( tool == null ) |
559 | { |
560 | throw new NullPointerException( "tool" ); |
561 | } |
562 | if ( implementation == null ) |
563 | { |
564 | throw new NullPointerException( "implementation" ); |
565 | } |
566 | if ( sourceFilesType == null ) |
567 | { |
568 | throw new NullPointerException( "sourceFilesType" ); |
569 | } |
570 | |
571 | for ( int i = 0, s0 = sourceFilesType.getSourceFile().size(); i < s0; i++ ) |
572 | { |
573 | final SourceFileType s = sourceFilesType.getSourceFile().get( i ); |
574 | |
575 | if ( s.getTemplate() == null ) |
576 | { |
577 | s.setTemplate( IMPLEMENTATION_TEMPLATE ); |
578 | } |
579 | if ( s.getLocation() == null && implementation.getClazz() != null ) |
580 | { |
581 | s.setLocation( new StringBuilder( implementation.getClazz().length() + 5 ).append( |
582 | implementation.getClazz().replace( '.', '/' ) ).append( ".java" ).toString() ); |
583 | |
584 | } |
585 | if ( s.getHeadComment() == null ) |
586 | { |
587 | s.setHeadComment( "//" ); |
588 | } |
589 | |
590 | this.applyDefaults( tool, implementation, s.getSourceSections() ); |
591 | } |
592 | } |
593 | |
594 | /** |
595 | * Updates any optional attributes to default values. |
596 | * |
597 | * @param tool The tool to use for creating type names. |
598 | * @param implementation The implementation corresponding to {@code sourceSectionsType}. |
599 | * @param sourceSectionsType The model to update or {@code null}. |
600 | * |
601 | * @throws NullPointerException if {@code tool} or {@code implementation} is {@code null}. |
602 | */ |
603 | private void applyDefaults( final JomcTool tool, final Implementation implementation, |
604 | final SourceSectionsType sourceSectionsType ) |
605 | { |
606 | if ( tool == null ) |
607 | { |
608 | throw new NullPointerException( "tool" ); |
609 | } |
610 | if ( implementation == null ) |
611 | { |
612 | throw new NullPointerException( "implementation" ); |
613 | } |
614 | |
615 | try |
616 | { |
617 | if ( sourceSectionsType != null ) |
618 | { |
619 | final Modules modules = ModelHelper.getModules( tool.getModel() ); |
620 | |
621 | for ( int i = 0, s0 = sourceSectionsType.getSourceSection().size(); i < s0; i++ ) |
622 | { |
623 | final SourceSectionType s = sourceSectionsType.getSourceSection().get( i ); |
624 | |
625 | if ( LICENSE_SECTION_NAME.equals( s.getName() ) ) |
626 | { |
627 | if ( !isFieldSet( s, "optional" ) ) |
628 | { |
629 | s.setOptional( true ); |
630 | } |
631 | if ( s.getHeadTemplate() == null ) |
632 | { |
633 | s.setHeadTemplate( IMPLEMENTATION_LICENSE_TEMPLATE ); |
634 | } |
635 | } |
636 | |
637 | if ( ANNOTATIONS_SECTION_NAME.equals( s.getName() ) ) |
638 | { |
639 | if ( s.getHeadTemplate() == null ) |
640 | { |
641 | s.setHeadTemplate( IMPLEMENTATION_ANNOTATIONS_TEMPLATE ); |
642 | } |
643 | } |
644 | |
645 | if ( DOCUMENTATION_SECTION_NAME.equals( s.getName() ) ) |
646 | { |
647 | if ( !isFieldSet( s, "optional" ) ) |
648 | { |
649 | s.setOptional( true ); |
650 | } |
651 | if ( s.getHeadTemplate() == null ) |
652 | { |
653 | s.setHeadTemplate( IMPLEMENTATION_DOCUMENTATION_TEMPLATE ); |
654 | } |
655 | } |
656 | |
657 | if ( CONSTRUCTORS_SECTION_NAME.equals( s.getName() ) ) |
658 | { |
659 | if ( !isFieldSet( s, "indentationLevel" ) ) |
660 | { |
661 | s.setIndentationLevel( 1 ); |
662 | } |
663 | if ( s.getHeadTemplate() == null ) |
664 | { |
665 | s.setHeadTemplate( CONSTRUCTORS_HEAD_TEMPLATE ); |
666 | } |
667 | if ( s.getTailTemplate() == null ) |
668 | { |
669 | s.setTailTemplate( CONSTRUCTORS_TAIL_TEMPLATE ); |
670 | } |
671 | if ( !isFieldSet( s, "optional" ) ) |
672 | { |
673 | final Specifications specifications = |
674 | modules != null ? modules.getSpecifications( implementation.getIdentifier() ) : null; |
675 | |
676 | s.setOptional( specifications == null || ( specifications.getSpecification().isEmpty() |
677 | && specifications.getReference().isEmpty() ) ); |
678 | |
679 | } |
680 | } |
681 | |
682 | if ( DEFAULT_CONSTRUCTOR_SECTION_NAME.equals( s.getName() ) ) |
683 | { |
684 | if ( !isFieldSet( s, "editable" ) ) |
685 | { |
686 | s.setEditable( true ); |
687 | } |
688 | if ( !isFieldSet( s, "indentationLevel" ) ) |
689 | { |
690 | s.setIndentationLevel( 2 ); |
691 | } |
692 | if ( s.getHeadTemplate() == null ) |
693 | { |
694 | s.setHeadTemplate( DEFAULT_CONSTRUCTOR_TEMPLATE ); |
695 | } |
696 | } |
697 | |
698 | if ( DEPENDENCIES_SECTION_NAME.equals( s.getName() ) ) |
699 | { |
700 | if ( !isFieldSet( s, "optional" ) ) |
701 | { |
702 | final Dependencies dependencies = |
703 | modules != null ? modules.getDependencies( implementation.getIdentifier() ) : null; |
704 | |
705 | s.setOptional( dependencies == null || dependencies.getDependency().isEmpty() ); |
706 | } |
707 | if ( !isFieldSet( s, "indentationLevel" ) ) |
708 | { |
709 | s.setIndentationLevel( 1 ); |
710 | } |
711 | if ( s.getHeadTemplate() == null ) |
712 | { |
713 | s.setHeadTemplate( DEPENDENCIES_TEMPLATE ); |
714 | } |
715 | } |
716 | |
717 | if ( PROPERTIES_SECTION_NAME.equals( s.getName() ) ) |
718 | { |
719 | if ( !isFieldSet( s, "optional" ) ) |
720 | { |
721 | final Properties properties = |
722 | modules != null ? modules.getProperties( implementation.getIdentifier() ) : null; |
723 | |
724 | s.setOptional( properties == null || properties.getProperty().isEmpty() ); |
725 | } |
726 | if ( !isFieldSet( s, "indentationLevel" ) ) |
727 | { |
728 | s.setIndentationLevel( 1 ); |
729 | } |
730 | if ( s.getHeadTemplate() == null ) |
731 | { |
732 | s.setHeadTemplate( PROPERTIES_TEMPLATE ); |
733 | } |
734 | } |
735 | |
736 | if ( MESSAGES_SECTION_NAME.equals( s.getName() ) ) |
737 | { |
738 | if ( !isFieldSet( s, "optional" ) ) |
739 | { |
740 | final Messages messages = |
741 | modules != null ? modules.getMessages( implementation.getIdentifier() ) : null; |
742 | |
743 | s.setOptional( messages == null || messages.getMessage().isEmpty() ); |
744 | } |
745 | if ( !isFieldSet( s, "indentationLevel" ) ) |
746 | { |
747 | s.setIndentationLevel( 1 ); |
748 | } |
749 | if ( s.getHeadTemplate() == null ) |
750 | { |
751 | s.setHeadTemplate( MESSAGES_TEMPLATE ); |
752 | } |
753 | } |
754 | |
755 | final List<String> implementedJavaTypeNames = |
756 | tool.getImplementedJavaTypeNames( implementation, false ); |
757 | |
758 | for ( int j = 0, s1 = implementedJavaTypeNames.size(); j < s1; j++ ) |
759 | { |
760 | final String interfaceName = implementedJavaTypeNames.get( j ); |
761 | |
762 | if ( interfaceName.equals( s.getName() ) ) |
763 | { |
764 | if ( !isFieldSet( s, "editable" ) ) |
765 | { |
766 | s.setEditable( true ); |
767 | } |
768 | if ( !isFieldSet( s, "indentationLevel" ) ) |
769 | { |
770 | s.setIndentationLevel( 1 ); |
771 | } |
772 | } |
773 | } |
774 | |
775 | final String javaTypeName = tool.getJavaTypeName( implementation, false ); |
776 | if ( javaTypeName != null ) |
777 | { |
778 | if ( javaTypeName.equals( s.getName() ) ) |
779 | { |
780 | if ( !isFieldSet( s, "editable" ) ) |
781 | { |
782 | s.setEditable( true ); |
783 | } |
784 | if ( !isFieldSet( s, "indentationLevel" ) ) |
785 | { |
786 | s.setIndentationLevel( 1 ); |
787 | } |
788 | } |
789 | } |
790 | |
791 | this.applyDefaults( tool, implementation, s.getSourceSections() ); |
792 | } |
793 | } |
794 | } |
795 | catch ( final NoSuchFieldException e ) |
796 | { |
797 | throw new AssertionError( e ); |
798 | } |
799 | } |
800 | |
801 | private static boolean isFieldSet( final Object object, final String fieldName ) throws NoSuchFieldException |
802 | { |
803 | final Field field = object.getClass().getDeclaredField( fieldName ); |
804 | final boolean accessible = field.isAccessible(); |
805 | |
806 | try |
807 | { |
808 | field.setAccessible( true ); |
809 | return field.get( object ) != null; |
810 | } |
811 | catch ( final IllegalAccessException e ) |
812 | { |
813 | throw new AssertionError( e ); |
814 | } |
815 | finally |
816 | { |
817 | field.setAccessible( accessible ); |
818 | } |
819 | } |
820 | |
821 | private static String getMessage( final String key, final Object... args ) |
822 | { |
823 | return MessageFormat.format( ResourceBundle.getBundle( |
824 | ToolsModelProcessor.class.getName().replace( '.', '/' ), Locale.getDefault() ).getString( key ), args ); |
825 | |
826 | } |
827 | |
828 | } |