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: ToolsModelProvider.java 4852 2014-01-26 05:42:11Z schulte $ |
29 | * |
30 | */ |
31 | package org.jomc.tools.modlet; |
32 | |
33 | import java.lang.reflect.Field; |
34 | import java.text.MessageFormat; |
35 | import java.util.ArrayList; |
36 | import java.util.HashMap; |
37 | import java.util.HashSet; |
38 | import java.util.Locale; |
39 | import java.util.Map; |
40 | import java.util.ResourceBundle; |
41 | import java.util.Set; |
42 | import java.util.logging.Level; |
43 | import javax.xml.bind.JAXBElement; |
44 | import javax.xml.namespace.QName; |
45 | import org.jomc.model.Dependencies; |
46 | import org.jomc.model.Implementation; |
47 | import org.jomc.model.InheritanceModel; |
48 | import org.jomc.model.JavaTypeName; |
49 | import org.jomc.model.Messages; |
50 | import org.jomc.model.ModelObjectException; |
51 | import org.jomc.model.Module; |
52 | import org.jomc.model.Modules; |
53 | import org.jomc.model.Properties; |
54 | import org.jomc.model.Specification; |
55 | import org.jomc.model.Specifications; |
56 | import org.jomc.model.modlet.ModelHelper; |
57 | import org.jomc.modlet.Model; |
58 | import org.jomc.modlet.ModelContext; |
59 | import org.jomc.modlet.ModelException; |
60 | import org.jomc.modlet.ModelProvider; |
61 | import org.jomc.tools.model.ObjectFactory; |
62 | import org.jomc.tools.model.SourceFileType; |
63 | import org.jomc.tools.model.SourceFilesType; |
64 | import org.jomc.tools.model.SourceSectionType; |
65 | import org.jomc.tools.model.SourceSectionsType; |
66 | import static org.jomc.tools.modlet.ToolsModletConstants.ANNOTATIONS_SECTION_NAME; |
67 | import static org.jomc.tools.modlet.ToolsModletConstants.CONSTRUCTORS_HEAD_TEMPLATE; |
68 | import static org.jomc.tools.modlet.ToolsModletConstants.CONSTRUCTORS_SECTION_NAME; |
69 | import static org.jomc.tools.modlet.ToolsModletConstants.CONSTRUCTORS_TAIL_TEMPLATE; |
70 | import static org.jomc.tools.modlet.ToolsModletConstants.DEFAULT_CONSTRUCTOR_SECTION_NAME; |
71 | import static org.jomc.tools.modlet.ToolsModletConstants.DEFAULT_CONSTRUCTOR_TEMPLATE; |
72 | import static org.jomc.tools.modlet.ToolsModletConstants.DEPENDENCIES_SECTION_NAME; |
73 | import static org.jomc.tools.modlet.ToolsModletConstants.DEPENDENCIES_TEMPLATE; |
74 | import static org.jomc.tools.modlet.ToolsModletConstants.DOCUMENTATION_SECTION_NAME; |
75 | import static org.jomc.tools.modlet.ToolsModletConstants.IMPLEMENTATION_ANNOTATIONS_TEMPLATE; |
76 | import static org.jomc.tools.modlet.ToolsModletConstants.IMPLEMENTATION_DOCUMENTATION_TEMPLATE; |
77 | import static org.jomc.tools.modlet.ToolsModletConstants.IMPLEMENTATION_LICENSE_TEMPLATE; |
78 | import static org.jomc.tools.modlet.ToolsModletConstants.IMPLEMENTATION_TEMPLATE; |
79 | import static org.jomc.tools.modlet.ToolsModletConstants.LICENSE_SECTION_NAME; |
80 | import static org.jomc.tools.modlet.ToolsModletConstants.MESSAGES_SECTION_NAME; |
81 | import static org.jomc.tools.modlet.ToolsModletConstants.MESSAGES_TEMPLATE; |
82 | import static org.jomc.tools.modlet.ToolsModletConstants.PROPERTIES_SECTION_NAME; |
83 | import static org.jomc.tools.modlet.ToolsModletConstants.PROPERTIES_TEMPLATE; |
84 | import static org.jomc.tools.modlet.ToolsModletConstants.SPECIFICATION_ANNOTATIONS_TEMPLATE; |
85 | import static org.jomc.tools.modlet.ToolsModletConstants.SPECIFICATION_DOCUMENTATION_TEMPLATE; |
86 | import static org.jomc.tools.modlet.ToolsModletConstants.SPECIFICATION_LICENSE_TEMPLATE; |
87 | import static org.jomc.tools.modlet.ToolsModletConstants.SPECIFICATION_TEMPLATE; |
88 | |
89 | /** |
90 | * Object management and configuration tools {@code ModelProvider} implementation. |
91 | * |
92 | * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> |
93 | * @version $JOMC: ToolsModelProvider.java 4852 2014-01-26 05:42:11Z schulte $ |
94 | * @see ModelContext#findModel(java.lang.String) |
95 | * @since 1.2 |
96 | */ |
97 | public class ToolsModelProvider implements ModelProvider |
98 | { |
99 | |
100 | /** Constant for the qualified name of {@code source-files} elements. */ |
101 | private static final QName SOURCE_FILES_QNAME = new ObjectFactory().createSourceFiles( null ).getName(); |
102 | |
103 | /** |
104 | * Constant for the name of the model context attribute backing property {@code enabled}. |
105 | * @see #findModel(org.jomc.modlet.ModelContext, org.jomc.modlet.Model) |
106 | * @see ModelContext#getAttribute(java.lang.String) |
107 | */ |
108 | public static final String ENABLED_ATTRIBUTE_NAME = "org.jomc.tools.modlet.ToolsModelProvider.enabledAttribute"; |
109 | |
110 | /** |
111 | * Constant for the name of the system property controlling property {@code defaultEnabled}. |
112 | * @see #isDefaultEnabled() |
113 | */ |
114 | private static final String DEFAULT_ENABLED_PROPERTY_NAME = |
115 | "org.jomc.tools.modlet.ToolsModelProvider.defaultEnabled"; |
116 | |
117 | /** |
118 | * Default value of the flag indicating the provider is enabled by default. |
119 | * @see #isDefaultEnabled() |
120 | */ |
121 | private static final Boolean DEFAULT_ENABLED = Boolean.TRUE; |
122 | |
123 | /** Flag indicating the provider is enabled by default. */ |
124 | private static volatile Boolean defaultEnabled; |
125 | |
126 | /** Flag indicating the provider is enabled. */ |
127 | private Boolean enabled; |
128 | |
129 | /** |
130 | * Constant for the name of the model context attribute backing property |
131 | * {@code modelObjectClasspathResolutionEnabled}. |
132 | * |
133 | * @see #findModel(org.jomc.modlet.ModelContext, org.jomc.modlet.Model) |
134 | * @see ModelContext#getAttribute(java.lang.String) |
135 | */ |
136 | public static final String MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME = |
137 | "org.jomc.tools.modlet.ToolsModelProvider.modelObjectClasspathResolutionEnabledAttribute"; |
138 | |
139 | /** |
140 | * Constant for the name of the system property controlling property |
141 | * {@code defaultModelObjectClasspathResolutionEnabled}. |
142 | * @see #isDefaultModelObjectClasspathResolutionEnabled() |
143 | */ |
144 | private static final String DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_PROPERTY_NAME = |
145 | "org.jomc.tools.modlet.ToolsModelProvider.defaultModelObjectClasspathResolutionEnabled"; |
146 | |
147 | /** |
148 | * Default value of the flag indicating model object class path resolution is enabled by default. |
149 | * @see #isDefaultModelObjectClasspathResolutionEnabled() |
150 | */ |
151 | private static final Boolean DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED = Boolean.TRUE; |
152 | |
153 | /** Flag indicating model object class path resolution is enabled by default. */ |
154 | private static volatile Boolean defaultModelObjectClasspathResolutionEnabled; |
155 | |
156 | /** Flag indicating model object class path resolution is enabled. */ |
157 | private Boolean modelObjectClasspathResolutionEnabled; |
158 | |
159 | /** |
160 | * Constant for the name of the model context attribute backing property {@code headComment}. |
161 | * @see #findModel(org.jomc.modlet.ModelContext, org.jomc.modlet.Model) |
162 | * @see ModelContext#getAttribute(java.lang.String) |
163 | * @since 1.6 |
164 | */ |
165 | public static final String HEAD_COMMENT_ATTRIBUTE_NAME = |
166 | "org.jomc.tools.modlet.ToolsModelProvider.headCommentAttribute"; |
167 | |
168 | /** |
169 | * Constant for the name of the system property controlling property {@code defaultHeadComment}. |
170 | * @see #getDefaultHeadComment() |
171 | * @since 1.6 |
172 | */ |
173 | private static final String DEFAULT_HEAD_COMMENT_PROPERTY_NAME = |
174 | "org.jomc.tools.modlet.ToolsModelProvider.defaultHeadComment"; |
175 | |
176 | /** |
177 | * Default head comment the provider is providing by default. |
178 | * @see #getDefaultHeadComment() |
179 | * @since 1.6 |
180 | */ |
181 | private static final String DEFAULT_HEAD_COMMENT = "//"; |
182 | |
183 | /** |
184 | * Head comment the provider is providing by default. |
185 | * @since 1.6 |
186 | */ |
187 | private static volatile String defaultHeadComment; |
188 | |
189 | /** |
190 | * Head comment the provider is providing. |
191 | * @since 1.6 |
192 | */ |
193 | private String headComment; |
194 | |
195 | /** |
196 | * Constant for the name of the model context attribute backing property {@code tailComment}. |
197 | * @see #findModel(org.jomc.modlet.ModelContext, org.jomc.modlet.Model) |
198 | * @see ModelContext#getAttribute(java.lang.String) |
199 | * @since 1.6 |
200 | */ |
201 | public static final String TAIL_COMMENT_ATTRIBUTE_NAME = |
202 | "org.jomc.tools.modlet.ToolsModelProvider.tailCommentAttribute"; |
203 | |
204 | /** |
205 | * Constant for the name of the system property controlling property {@code defaultTailComment}. |
206 | * @see #getDefaultTailComment() |
207 | * @since 1.6 |
208 | */ |
209 | private static final String DEFAULT_TAIL_COMMENT_PROPERTY_NAME = |
210 | "org.jomc.tools.modlet.ToolsModelProvider.defaultTailComment"; |
211 | |
212 | /** |
213 | * Default tail comment the provider is providing by default. |
214 | * @see #getDefaultTailComment() |
215 | * @since 1.6 |
216 | */ |
217 | private static final String DEFAULT_TAIL_COMMENT = null; |
218 | |
219 | /** |
220 | * Tail comment the provider is providing by default. |
221 | * @since 1.6 |
222 | */ |
223 | private static volatile String defaultTailComment; |
224 | |
225 | /** |
226 | * Tail comment the provider is providing. |
227 | * @since 1.6 |
228 | */ |
229 | private String tailComment; |
230 | |
231 | /** Creates a new {@code ToolsModelProvider} instance. */ |
232 | public ToolsModelProvider() |
233 | { |
234 | super(); |
235 | } |
236 | |
237 | /** |
238 | * Gets a flag indicating the provider is enabled by default. |
239 | * <p>The default enabled flag is controlled by system property |
240 | * {@code org.jomc.tools.modlet.ToolsModelProvider.defaultEnabled} holding a value indicating the provider is |
241 | * enabled by default. If that property is not set, the {@code true} default is returned.</p> |
242 | * |
243 | * @return {@code true}, if the provider is enabled by default; {@code false}, if the provider is disabled by |
244 | * default. |
245 | * |
246 | * @see #setDefaultEnabled(java.lang.Boolean) |
247 | */ |
248 | public static boolean isDefaultEnabled() |
249 | { |
250 | if ( defaultEnabled == null ) |
251 | { |
252 | defaultEnabled = Boolean.valueOf( System.getProperty( DEFAULT_ENABLED_PROPERTY_NAME, |
253 | Boolean.toString( DEFAULT_ENABLED ) ) ); |
254 | |
255 | } |
256 | |
257 | return defaultEnabled; |
258 | } |
259 | |
260 | /** |
261 | * Sets the flag indicating the provider is enabled by default. |
262 | * |
263 | * @param value The new value of the flag indicating the provider is enabled by default or {@code null}. |
264 | * |
265 | * @see #isDefaultEnabled() |
266 | */ |
267 | public static void setDefaultEnabled( final Boolean value ) |
268 | { |
269 | defaultEnabled = value; |
270 | } |
271 | |
272 | /** |
273 | * Gets a flag indicating the provider is enabled. |
274 | * |
275 | * @return {@code true}, if the provider is enabled; {@code false}, if the provider is disabled. |
276 | * |
277 | * @see #isDefaultEnabled() |
278 | * @see #setEnabled(java.lang.Boolean) |
279 | */ |
280 | public final boolean isEnabled() |
281 | { |
282 | if ( this.enabled == null ) |
283 | { |
284 | this.enabled = isDefaultEnabled(); |
285 | } |
286 | |
287 | return this.enabled; |
288 | } |
289 | |
290 | /** |
291 | * Sets the flag indicating the provider is enabled. |
292 | * |
293 | * @param value The new value of the flag indicating the provider is enabled or {@code null}. |
294 | * |
295 | * @see #isEnabled() |
296 | */ |
297 | public final void setEnabled( final Boolean value ) |
298 | { |
299 | this.enabled = value; |
300 | } |
301 | |
302 | /** |
303 | * Gets a flag indicating model object class path resolution is enabled by default. |
304 | * <p>The model object class path resolution default enabled flag is controlled by system property |
305 | * {@code org.jomc.tools.modlet.ToolsModelProvider.defaultModelObjectClasspathResolutionEnabled} holding a value |
306 | * indicating model object class path resolution is enabled by default. If that property is not set, the |
307 | * {@code true} default is returned.</p> |
308 | * |
309 | * @return {@code true}, if model object class path resolution is enabled by default; {@code false}, if model object |
310 | * class path resolution is disabled by default. |
311 | * |
312 | * @see #setDefaultModelObjectClasspathResolutionEnabled(java.lang.Boolean) |
313 | */ |
314 | public static boolean isDefaultModelObjectClasspathResolutionEnabled() |
315 | { |
316 | if ( defaultModelObjectClasspathResolutionEnabled == null ) |
317 | { |
318 | defaultModelObjectClasspathResolutionEnabled = Boolean.valueOf( System.getProperty( |
319 | DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_PROPERTY_NAME, |
320 | Boolean.toString( DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED ) ) ); |
321 | |
322 | } |
323 | |
324 | return defaultModelObjectClasspathResolutionEnabled; |
325 | } |
326 | |
327 | /** |
328 | * Sets the flag indicating model object class path resolution is enabled by default. |
329 | * |
330 | * @param value The new value of the flag indicating model object class path resolution is enabled by default or |
331 | * {@code null}. |
332 | * |
333 | * @see #isDefaultModelObjectClasspathResolutionEnabled() |
334 | */ |
335 | public static void setDefaultModelObjectClasspathResolutionEnabled( final Boolean value ) |
336 | { |
337 | defaultModelObjectClasspathResolutionEnabled = value; |
338 | } |
339 | |
340 | /** |
341 | * Gets a flag indicating model object class path resolution is enabled. |
342 | * |
343 | * @return {@code true}, if model object class path resolution is enabled; {@code false}, if model object class path |
344 | * resolution is disabled. |
345 | * |
346 | * @see #isDefaultModelObjectClasspathResolutionEnabled() |
347 | * @see #setModelObjectClasspathResolutionEnabled(java.lang.Boolean) |
348 | */ |
349 | public final boolean isModelObjectClasspathResolutionEnabled() |
350 | { |
351 | if ( this.modelObjectClasspathResolutionEnabled == null ) |
352 | { |
353 | this.modelObjectClasspathResolutionEnabled = isDefaultModelObjectClasspathResolutionEnabled(); |
354 | } |
355 | |
356 | return this.modelObjectClasspathResolutionEnabled; |
357 | } |
358 | |
359 | /** |
360 | * Sets the flag indicating model object class path resolution is is enabled. |
361 | * |
362 | * @param value The new value of the flag indicating model object class path resolution is enabled or {@code null}. |
363 | * |
364 | * @see #isModelObjectClasspathResolutionEnabled() |
365 | */ |
366 | public final void setModelObjectClasspathResolutionEnabled( final Boolean value ) |
367 | { |
368 | this.modelObjectClasspathResolutionEnabled = value; |
369 | } |
370 | |
371 | /** |
372 | * Gets the head comment the provider is providing by default. |
373 | * <p>The default head comment is controlled by system property |
374 | * {@code org.jomc.tools.modlet.ToolsModelProvider.defaultHeadComment} holding the head comment the provider is |
375 | * providing by default. If that property is not set, the {@code //} default is returned.</p> |
376 | * |
377 | * @return The head comment the provider is providing by default or {@code null}. |
378 | * |
379 | * @see #setDefaultHeadComment(java.lang.String) |
380 | * @since 1.6 |
381 | */ |
382 | public static String getDefaultHeadComment() |
383 | { |
384 | if ( defaultHeadComment == null ) |
385 | { |
386 | defaultHeadComment = System.getProperty( DEFAULT_HEAD_COMMENT_PROPERTY_NAME, DEFAULT_HEAD_COMMENT ); |
387 | } |
388 | |
389 | return defaultHeadComment; |
390 | } |
391 | |
392 | /** |
393 | * Sets the head comment the provider is providing by default. |
394 | * |
395 | * @param value The new head comment the provider is providing by default or {@code null}. |
396 | * |
397 | * @see #getDefaultHeadComment() |
398 | * @since 1.6 |
399 | */ |
400 | public static void setDefaultHeadComment( final String value ) |
401 | { |
402 | defaultHeadComment = value; |
403 | } |
404 | |
405 | /** |
406 | * Gets the head comment the provider is providing. |
407 | * |
408 | * @return The head comment the provider is providing or {@code null}. |
409 | * |
410 | * @see #getDefaultHeadComment() |
411 | * @see #setDefaultHeadComment(java.lang.String) |
412 | * @since 1.6 |
413 | */ |
414 | public final String getHeadComment() |
415 | { |
416 | if ( this.headComment == null ) |
417 | { |
418 | this.headComment = getDefaultHeadComment(); |
419 | } |
420 | |
421 | return this.headComment; |
422 | } |
423 | |
424 | /** |
425 | * Sets the head comment the provider is providing. |
426 | * |
427 | * @param value The new head comment the provider is providing or {@code null}. |
428 | * |
429 | * @see #getHeadComment() |
430 | * @since 1.6 |
431 | */ |
432 | public final void setHeadComment( final String value ) |
433 | { |
434 | this.headComment = value; |
435 | } |
436 | |
437 | /** |
438 | * Gets the tail comment the provider is providing by default. |
439 | * <p>The default tail comment is controlled by system property |
440 | * {@code org.jomc.tools.modlet.ToolsModelProvider.defaultTailComment} holding the tail comment the provider is |
441 | * providing by default. If that property is not set, the {@code null} default is returned.</p> |
442 | * |
443 | * @return The tail comment the provider is providing by default or {@code null}. |
444 | * |
445 | * @see #setDefaultTailComment(java.lang.String) |
446 | * @since 1.6 |
447 | */ |
448 | public static String getDefaultTailComment() |
449 | { |
450 | if ( defaultTailComment == null ) |
451 | { |
452 | defaultTailComment = System.getProperty( DEFAULT_TAIL_COMMENT_PROPERTY_NAME, DEFAULT_TAIL_COMMENT ); |
453 | } |
454 | |
455 | return defaultTailComment; |
456 | } |
457 | |
458 | /** |
459 | * Sets the tail comment the provider is providing by default. |
460 | * |
461 | * @param value The new tail comment the provider is providing by default or {@code null}. |
462 | * |
463 | * @see #getDefaultTailComment() |
464 | * @since 1.6 |
465 | */ |
466 | public static void setDefaultTailComment( final String value ) |
467 | { |
468 | defaultTailComment = value; |
469 | } |
470 | |
471 | /** |
472 | * Gets the tail comment the provider is providing. |
473 | * |
474 | * @return The tail comment the provider is providing or {@code null}. |
475 | * |
476 | * @see #getDefaultTailComment() |
477 | * @see #setDefaultTailComment(java.lang.String) |
478 | * @since 1.6 |
479 | */ |
480 | public final String getTailComment() |
481 | { |
482 | if ( this.tailComment == null ) |
483 | { |
484 | this.tailComment = getDefaultTailComment(); |
485 | } |
486 | |
487 | return this.tailComment; |
488 | } |
489 | |
490 | /** |
491 | * Sets the tail comment the provider is providing. |
492 | * |
493 | * @param value The new tail comment the provider is providing or {@code null}. |
494 | * |
495 | * @see #getTailComment() |
496 | * @since 1.6 |
497 | */ |
498 | public final void setTailComment( final String value ) |
499 | { |
500 | this.tailComment = value; |
501 | } |
502 | |
503 | /** |
504 | * {@inheritDoc} |
505 | * |
506 | * @see #isEnabled() |
507 | * @see #isModelObjectClasspathResolutionEnabled() |
508 | * @see #getHeadComment() |
509 | * @see #getTailComment() |
510 | * @see #ENABLED_ATTRIBUTE_NAME |
511 | * @see #MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME |
512 | * @see #HEAD_COMMENT_ATTRIBUTE_NAME |
513 | * @see #TAIL_COMMENT_ATTRIBUTE_NAME |
514 | */ |
515 | public Model findModel( final ModelContext context, final Model model ) throws ModelException |
516 | { |
517 | if ( context == null ) |
518 | { |
519 | throw new NullPointerException( "context" ); |
520 | } |
521 | if ( model == null ) |
522 | { |
523 | throw new NullPointerException( "model" ); |
524 | } |
525 | |
526 | Model provided = null; |
527 | |
528 | boolean contextEnabled = this.isEnabled(); |
529 | if ( DEFAULT_ENABLED == contextEnabled && context.getAttribute( ENABLED_ATTRIBUTE_NAME ) instanceof Boolean ) |
530 | { |
531 | contextEnabled = (Boolean) context.getAttribute( ENABLED_ATTRIBUTE_NAME ); |
532 | } |
533 | |
534 | boolean contextModelObjectClasspathResolutionEnabled = this.isModelObjectClasspathResolutionEnabled(); |
535 | if ( contextModelObjectClasspathResolutionEnabled == DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED |
536 | && context.getAttribute( MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME ) instanceof Boolean ) |
537 | { |
538 | contextModelObjectClasspathResolutionEnabled = |
539 | (Boolean) context.getAttribute( MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME ); |
540 | |
541 | } |
542 | |
543 | if ( contextEnabled ) |
544 | { |
545 | provided = model.clone(); |
546 | final Modules modules = ModelHelper.getModules( provided ); |
547 | |
548 | if ( modules != null ) |
549 | { |
550 | Module classpathModule = null; |
551 | if ( contextModelObjectClasspathResolutionEnabled ) |
552 | { |
553 | classpathModule = modules.getClasspathModule( Modules.getDefaultClasspathModuleName(), |
554 | context.getClassLoader() ); |
555 | |
556 | if ( classpathModule != null |
557 | && modules.getModule( Modules.getDefaultClasspathModuleName() ) == null ) |
558 | { |
559 | modules.getModule().add( classpathModule ); |
560 | } |
561 | else |
562 | { |
563 | classpathModule = null; |
564 | } |
565 | } |
566 | |
567 | if ( modules.getSpecifications() != null ) |
568 | { |
569 | for ( int i = 0, s0 = modules.getSpecifications().getSpecification().size(); i < s0; i++ ) |
570 | { |
571 | final Specification specification = modules.getSpecifications().getSpecification().get( i ); |
572 | final SourceFileType sourceFileType = specification.getAnyObject( SourceFileType.class ); |
573 | final SourceFilesType sourceFilesType = specification.getAnyObject( SourceFilesType.class ); |
574 | |
575 | if ( sourceFileType == null && specification.isClassDeclaration() ) |
576 | { |
577 | final SourceFilesType defaultSourceFiles = |
578 | this.getDefaultSourceFilesType( context, modules, specification ); |
579 | |
580 | if ( sourceFilesType != null ) |
581 | { |
582 | this.overwriteSourceFiles( sourceFilesType, defaultSourceFiles, true ); |
583 | } |
584 | else |
585 | { |
586 | specification.getAny().add( |
587 | new ObjectFactory().createSourceFiles( defaultSourceFiles ) ); |
588 | |
589 | } |
590 | } |
591 | } |
592 | } |
593 | |
594 | if ( modules.getImplementations() != null ) |
595 | { |
596 | final Map<Implementation, SourceFilesType> userSourceFiles = |
597 | new HashMap<Implementation, SourceFilesType>( |
598 | modules.getImplementations().getImplementation().size() ); |
599 | |
600 | InheritanceModel imodel = new InheritanceModel( modules ); |
601 | |
602 | for ( int i = 0, s0 = modules.getImplementations().getImplementation().size(); i < s0; i++ ) |
603 | { |
604 | final Implementation implementation = modules.getImplementations().getImplementation().get( i ); |
605 | final SourceFileType sourceFileType = implementation.getAnyObject( SourceFileType.class ); |
606 | final SourceFilesType sourceFilesType = implementation.getAnyObject( SourceFilesType.class ); |
607 | |
608 | if ( sourceFileType == null ) |
609 | { |
610 | if ( sourceFilesType != null ) |
611 | { |
612 | userSourceFiles.put( implementation, sourceFilesType ); |
613 | } |
614 | else if ( implementation.isClassDeclaration() ) |
615 | { |
616 | final SourceFilesType defaultSourceFiles = |
617 | this.getDefaultSourceFilesType( context, modules, implementation ); |
618 | |
619 | boolean finalAncestor = false; |
620 | |
621 | final Set<InheritanceModel.Node<JAXBElement<?>>> sourceFilesNodes = |
622 | imodel.getJaxbElementNodes( implementation.getIdentifier(), SOURCE_FILES_QNAME ); |
623 | |
624 | for ( final InheritanceModel.Node<JAXBElement<?>> sourceFilesNode : sourceFilesNodes ) |
625 | { |
626 | if ( sourceFilesNode.getModelObject().getValue() instanceof SourceFilesType ) |
627 | { |
628 | final SourceFilesType ancestorSourceFiles = |
629 | (SourceFilesType) sourceFilesNode.getModelObject().getValue(); |
630 | |
631 | this.overwriteSourceFiles( defaultSourceFiles, ancestorSourceFiles, false ); |
632 | |
633 | if ( ancestorSourceFiles.isFinal() ) |
634 | { |
635 | finalAncestor = true; |
636 | } |
637 | } |
638 | } |
639 | |
640 | if ( !finalAncestor ) |
641 | { |
642 | implementation.getAny().add( |
643 | new ObjectFactory().createSourceFiles( defaultSourceFiles ) ); |
644 | |
645 | } |
646 | } |
647 | } |
648 | } |
649 | |
650 | for ( final Map.Entry<Implementation, SourceFilesType> e : userSourceFiles.entrySet() ) |
651 | { |
652 | this.overwriteSourceFiles( |
653 | e.getValue(), this.getDefaultSourceFilesType( context, modules, e.getKey() ), true ); |
654 | |
655 | } |
656 | |
657 | imodel = new InheritanceModel( modules ); |
658 | |
659 | for ( int i = 0, s0 = modules.getImplementations().getImplementation().size(); i < s0; i++ ) |
660 | { |
661 | final Implementation implementation = modules.getImplementations().getImplementation().get( i ); |
662 | final SourceFilesType sourceFilesType = implementation.getAnyObject( SourceFilesType.class ); |
663 | |
664 | if ( sourceFilesType != null && !userSourceFiles.containsKey( implementation ) ) |
665 | { |
666 | boolean override = false; |
667 | |
668 | final Set<InheritanceModel.Node<JAXBElement<?>>> sourceFilesNodes = |
669 | imodel.getJaxbElementNodes( implementation.getIdentifier(), SOURCE_FILES_QNAME ); |
670 | |
671 | for ( final InheritanceModel.Node<JAXBElement<?>> e : sourceFilesNodes ) |
672 | { |
673 | if ( !e.getOverriddenNodes().isEmpty() ) |
674 | { |
675 | override = true; |
676 | break; |
677 | } |
678 | } |
679 | |
680 | if ( override ) |
681 | { |
682 | sourceFilesType.setOverride( override ); |
683 | } |
684 | } |
685 | } |
686 | } |
687 | |
688 | if ( classpathModule != null ) |
689 | { |
690 | modules.getModule().remove( classpathModule ); |
691 | } |
692 | } |
693 | } |
694 | else if ( context.isLoggable( Level.FINER ) ) |
695 | { |
696 | context.log( Level.FINER, getMessage( "disabled", this.getClass().getSimpleName(), |
697 | model.getIdentifier() ), null ); |
698 | |
699 | } |
700 | |
701 | return provided; |
702 | } |
703 | |
704 | /** |
705 | * Gets the default source code file location for a given specification. |
706 | * <p>If the specification provides a Java type name, this method returns a Java source code file location based on |
707 | * that Java type name.</p> |
708 | * |
709 | * @param context The context to get the default location with. |
710 | * @param modules The model to get the default location with. |
711 | * @param specification The specification to get the default location for. |
712 | * |
713 | * @return The default location for {@code specification} or {@code null}. |
714 | * |
715 | * @throws NullPointerExeption if {@code context}, {@code modules} or {@code specification} is {@code null}. |
716 | * |
717 | * @see #getDefaultSourceFilesType(org.jomc.modlet.ModelContext, org.jomc.model.Modules, org.jomc.model.Specification) |
718 | * @see SourceFileType#getLocation() |
719 | * @see Specification#getJavaTypeName() |
720 | * @since 1.6 |
721 | */ |
722 | protected String getDefaultSourceFileLocation( final ModelContext context, final Modules modules, |
723 | final Specification specification ) |
724 | { |
725 | if ( context == null ) |
726 | { |
727 | throw new NullPointerException( "context" ); |
728 | } |
729 | if ( modules == null ) |
730 | { |
731 | throw new NullPointerException( "modules" ); |
732 | } |
733 | if ( specification == null ) |
734 | { |
735 | throw new NullPointerException( "specification" ); |
736 | } |
737 | |
738 | String location = null; |
739 | |
740 | try |
741 | { |
742 | if ( specification.getJavaTypeName() != null ) |
743 | { |
744 | location = specification.getJavaTypeName().getQualifiedName().replace( '.', '/' ) + ".java"; |
745 | } |
746 | } |
747 | catch ( final ModelObjectException e ) |
748 | { |
749 | context.log( Level.WARNING, getMessage( e ), null ); |
750 | } |
751 | |
752 | return location; |
753 | } |
754 | |
755 | /** |
756 | * Gets the default source code file location for a given implementation. |
757 | * <p>If the implementation provides a Java type name, this method returns a Java source code file location based on |
758 | * that Java type name.</p> |
759 | * |
760 | * @param context The context to get the default location with. |
761 | * @param modules The model to get the default location with. |
762 | * @param implementation The implementation to get the default location for. |
763 | * |
764 | * @return The default location for {@code implementation} or {@code null}. |
765 | * |
766 | * @throws NullPointerExeption if {@code context}, {@code modules} or {@code implementation} is {@code null}. |
767 | * |
768 | * @see #getDefaultSourceFilesType(org.jomc.modlet.ModelContext, org.jomc.model.Modules, org.jomc.model.Implementation) |
769 | * @see SourceFileType#getLocation() |
770 | * @see Implementation#getJavaTypeName() |
771 | * @since 1.6 |
772 | */ |
773 | protected String getDefaultSourceFileLocation( final ModelContext context, final Modules modules, |
774 | final Implementation implementation ) |
775 | { |
776 | if ( context == null ) |
777 | { |
778 | throw new NullPointerException( "context" ); |
779 | } |
780 | if ( modules == null ) |
781 | { |
782 | throw new NullPointerException( "modules" ); |
783 | } |
784 | if ( implementation == null ) |
785 | { |
786 | throw new NullPointerException( "implementation" ); |
787 | } |
788 | |
789 | String location = null; |
790 | |
791 | try |
792 | { |
793 | if ( implementation.getJavaTypeName() != null ) |
794 | { |
795 | location = implementation.getJavaTypeName().getQualifiedName().replace( '.', '/' ) + ".java"; |
796 | } |
797 | } |
798 | catch ( final ModelObjectException e ) |
799 | { |
800 | context.log( Level.WARNING, getMessage( e ), null ); |
801 | } |
802 | |
803 | return location; |
804 | } |
805 | |
806 | /** |
807 | * Gets the default source section name for a given specification. |
808 | * <p>If the specification provides a Java type name, this method returns a section name based on that Java type |
809 | * name.</p> |
810 | * |
811 | * @param context The context to get the default section name with. |
812 | * @param modules The model to get the default section name with. |
813 | * @param specification The specification to get the default section name for. |
814 | * |
815 | * @return The default source section name for {@code specification} or {@code null}. |
816 | * |
817 | * @throws NullPointerExeption if {@code context}, {@code modules} or {@code specification} is {@code null}. |
818 | * |
819 | * @see #getDefaultSourceFilesType(org.jomc.modlet.ModelContext, org.jomc.model.Modules, org.jomc.model.Specification) |
820 | * @see SourceSectionType#getName() |
821 | * @see Specification#getJavaTypeName() |
822 | * @since 1.6 |
823 | */ |
824 | protected String getDefaultSourceSectionName( final ModelContext context, final Modules modules, |
825 | final Specification specification ) |
826 | { |
827 | if ( context == null ) |
828 | { |
829 | throw new NullPointerException( "context" ); |
830 | } |
831 | if ( modules == null ) |
832 | { |
833 | throw new NullPointerException( "modules" ); |
834 | } |
835 | if ( specification == null ) |
836 | { |
837 | throw new NullPointerException( "specification" ); |
838 | } |
839 | |
840 | String sectionName = null; |
841 | |
842 | try |
843 | { |
844 | final JavaTypeName javaTypeName = specification.getJavaTypeName(); |
845 | |
846 | if ( javaTypeName != null ) |
847 | { |
848 | sectionName = javaTypeName.getName( false ); |
849 | } |
850 | } |
851 | catch ( final ModelObjectException e ) |
852 | { |
853 | context.log( Level.WARNING, getMessage( e ), null ); |
854 | } |
855 | |
856 | return sectionName; |
857 | } |
858 | |
859 | /** |
860 | * Gets the default source section name for a given implementation. |
861 | * <p>If the implementation provides a Java type name, this method returns a section name based that Java type |
862 | * name.</p> |
863 | * |
864 | * @param context The context to get the default section name with. |
865 | * @param modules The model to get the default section name with. |
866 | * @param implementation The implementation to get the default section name for. |
867 | * |
868 | * @return The default source section name for {@code implementation} or {@code null}. |
869 | * |
870 | * @throws NullPointerExeption if {@code context}, {@code modules} or {@code implementation} is {@code null}. |
871 | * |
872 | * @see #getDefaultSourceFilesType(org.jomc.modlet.ModelContext, org.jomc.model.Modules, org.jomc.model.Implementation) |
873 | * @see SourceSectionType#getName() |
874 | * @see Implementation#getJavaTypeName() |
875 | * @since 1.6 |
876 | */ |
877 | protected String getDefaultSourceSectionName( final ModelContext context, final Modules modules, |
878 | final Implementation implementation ) |
879 | { |
880 | if ( context == null ) |
881 | { |
882 | throw new NullPointerException( "context" ); |
883 | } |
884 | if ( modules == null ) |
885 | { |
886 | throw new NullPointerException( "modules" ); |
887 | } |
888 | if ( implementation == null ) |
889 | { |
890 | throw new NullPointerException( "implementation" ); |
891 | } |
892 | |
893 | String sectionName = null; |
894 | |
895 | try |
896 | { |
897 | final JavaTypeName javaTypeName = implementation.getJavaTypeName(); |
898 | |
899 | if ( javaTypeName != null ) |
900 | { |
901 | sectionName = javaTypeName.getName( false ); |
902 | } |
903 | } |
904 | catch ( final ModelObjectException e ) |
905 | { |
906 | context.log( Level.WARNING, getMessage( e ), null ); |
907 | } |
908 | |
909 | return sectionName; |
910 | } |
911 | |
912 | /** |
913 | * Creates a new default source files model for a given specification. |
914 | * |
915 | * @param context The context to create a new default source files model with. |
916 | * @param modules The model to create a new default source files model with. |
917 | * @param specification The specification to create a new default source files model for. |
918 | * |
919 | * @return A new default source files model for {@code specification}. |
920 | * |
921 | * @throws NullPointerExeption if {@code context}, {@code modules} or {@code specification} is {@code null}. |
922 | * |
923 | * @see #getDefaultSourceFileLocation(org.jomc.modlet.ModelContext, org.jomc.model.Modules, org.jomc.model.Specification) |
924 | * @see #getDefaultSourceSectionName(org.jomc.modlet.ModelContext, org.jomc.model.Modules, org.jomc.model.Specification) |
925 | * @since 1.6 |
926 | */ |
927 | protected SourceFilesType getDefaultSourceFilesType( final ModelContext context, final Modules modules, |
928 | final Specification specification ) |
929 | { |
930 | if ( context == null ) |
931 | { |
932 | throw new NullPointerException( "context" ); |
933 | } |
934 | if ( modules == null ) |
935 | { |
936 | throw new NullPointerException( "modules" ); |
937 | } |
938 | if ( specification == null ) |
939 | { |
940 | throw new NullPointerException( "specification" ); |
941 | } |
942 | |
943 | String contextHeadComment = this.getHeadComment(); |
944 | if ( ( DEFAULT_HEAD_COMMENT != null |
945 | ? DEFAULT_HEAD_COMMENT.equals( contextHeadComment ) |
946 | : contextHeadComment == null ) |
947 | && context.getAttribute( HEAD_COMMENT_ATTRIBUTE_NAME ) instanceof String ) |
948 | { |
949 | contextHeadComment = (String) context.getAttribute( HEAD_COMMENT_ATTRIBUTE_NAME ); |
950 | } |
951 | |
952 | if ( contextHeadComment != null && contextHeadComment.length() == 0 ) |
953 | { |
954 | contextHeadComment = null; |
955 | } |
956 | |
957 | String contextTailComment = this.getTailComment(); |
958 | if ( ( DEFAULT_TAIL_COMMENT != null |
959 | ? DEFAULT_TAIL_COMMENT.equals( contextTailComment ) |
960 | : contextTailComment == null ) |
961 | && context.getAttribute( TAIL_COMMENT_ATTRIBUTE_NAME ) instanceof String ) |
962 | { |
963 | contextTailComment = (String) context.getAttribute( TAIL_COMMENT_ATTRIBUTE_NAME ); |
964 | } |
965 | |
966 | if ( contextTailComment != null && contextTailComment.length() == 0 ) |
967 | { |
968 | contextTailComment = null; |
969 | } |
970 | |
971 | final Set<String> uniqueSectionNames = new HashSet<String>( 16 ); |
972 | final Set<String> sectionNames = new HashSet<String>( 16 ); |
973 | sectionNames.add( LICENSE_SECTION_NAME ); |
974 | sectionNames.add( ANNOTATIONS_SECTION_NAME ); |
975 | sectionNames.add( DOCUMENTATION_SECTION_NAME ); |
976 | |
977 | final SourceFilesType sourceFilesType = new SourceFilesType(); |
978 | final SourceFileType sourceFileType = new SourceFileType(); |
979 | sourceFilesType.getSourceFile().add( sourceFileType ); |
980 | |
981 | sourceFileType.setIdentifier( "Default" ); |
982 | sourceFileType.setLocation( this.getDefaultSourceFileLocation( context, modules, specification ) ); |
983 | |
984 | sourceFileType.setTemplate( SPECIFICATION_TEMPLATE ); |
985 | sourceFileType.setHeadComment( contextHeadComment ); |
986 | sourceFileType.setTailComment( contextTailComment ); |
987 | sourceFileType.setSourceSections( new SourceSectionsType() ); |
988 | |
989 | SourceSectionType s = new SourceSectionType(); |
990 | s.setName( LICENSE_SECTION_NAME ); |
991 | s.setHeadTemplate( SPECIFICATION_LICENSE_TEMPLATE ); |
992 | s.setOptional( true ); |
993 | sourceFileType.getSourceSections().getSourceSection().add( s ); |
994 | |
995 | s = new SourceSectionType(); |
996 | s.setName( ANNOTATIONS_SECTION_NAME ); |
997 | s.setHeadTemplate( SPECIFICATION_ANNOTATIONS_TEMPLATE ); |
998 | sourceFileType.getSourceSections().getSourceSection().add( s ); |
999 | |
1000 | s = new SourceSectionType(); |
1001 | s.setName( DOCUMENTATION_SECTION_NAME ); |
1002 | s.setHeadTemplate( SPECIFICATION_DOCUMENTATION_TEMPLATE ); |
1003 | s.setOptional( true ); |
1004 | sourceFileType.getSourceSections().getSourceSection().add( s ); |
1005 | |
1006 | final String sectionName = this.getDefaultSourceSectionName( context, modules, specification ); |
1007 | |
1008 | if ( sectionName != null ) |
1009 | { |
1010 | if ( sectionNames.add( sectionName ) ) |
1011 | { |
1012 | s = new SourceSectionType(); |
1013 | s.setName( sectionName ); |
1014 | s.setIndentationLevel( 1 ); |
1015 | s.setEditable( true ); |
1016 | sourceFileType.getSourceSections().getSourceSection().add( s ); |
1017 | } |
1018 | else if ( uniqueSectionNames.add( sectionName ) ) |
1019 | { |
1020 | final Module module = modules.getModuleOfSpecification( specification.getIdentifier() ); |
1021 | context.log( Level.WARNING, getMessage( "specificationSectionNameUniqueness", |
1022 | specification.getIdentifier(), |
1023 | module.getName(), |
1024 | sourceFileType.getIdentifier(), |
1025 | sectionName ), |
1026 | null ); |
1027 | |
1028 | } |
1029 | } |
1030 | |
1031 | return sourceFilesType; |
1032 | } |
1033 | |
1034 | /** |
1035 | * Creates a new default source files model for a given implementation. |
1036 | * |
1037 | * @param context The context to create a new default source files model with. |
1038 | * @param modules The model to create a new default source files model with. |
1039 | * @param implementation The implementation to create a new default source files model for. |
1040 | * |
1041 | * @return A new default source files model for {@code implementation}. |
1042 | * |
1043 | * @throws NullPointerExeption if {@code context}, {@code modules} or {@code implementation} is {@code null}. |
1044 | * |
1045 | * @see #getDefaultSourceFileLocation(org.jomc.modlet.ModelContext, org.jomc.model.Modules, org.jomc.model.Implementation) |
1046 | * @see #getDefaultSourceSectionName(org.jomc.modlet.ModelContext, org.jomc.model.Modules, org.jomc.model.Implementation) |
1047 | * @since 1.6 |
1048 | */ |
1049 | protected SourceFilesType getDefaultSourceFilesType( final ModelContext context, final Modules modules, |
1050 | final Implementation implementation ) |
1051 | { |
1052 | if ( context == null ) |
1053 | { |
1054 | throw new NullPointerException( "context" ); |
1055 | } |
1056 | if ( modules == null ) |
1057 | { |
1058 | throw new NullPointerException( "modules" ); |
1059 | } |
1060 | if ( implementation == null ) |
1061 | { |
1062 | throw new NullPointerException( "implementation" ); |
1063 | } |
1064 | |
1065 | String contextHeadComment = this.getHeadComment(); |
1066 | if ( ( DEFAULT_HEAD_COMMENT != null |
1067 | ? DEFAULT_HEAD_COMMENT.equals( contextHeadComment ) |
1068 | : contextHeadComment == null ) |
1069 | && context.getAttribute( HEAD_COMMENT_ATTRIBUTE_NAME ) instanceof String ) |
1070 | { |
1071 | contextHeadComment = (String) context.getAttribute( HEAD_COMMENT_ATTRIBUTE_NAME ); |
1072 | } |
1073 | |
1074 | if ( contextHeadComment != null && contextHeadComment.length() == 0 ) |
1075 | { |
1076 | contextHeadComment = null; |
1077 | } |
1078 | |
1079 | String contextTailComment = this.getTailComment(); |
1080 | if ( ( DEFAULT_TAIL_COMMENT != null |
1081 | ? DEFAULT_TAIL_COMMENT.equals( contextTailComment ) |
1082 | : contextTailComment == null ) |
1083 | && context.getAttribute( TAIL_COMMENT_ATTRIBUTE_NAME ) instanceof String ) |
1084 | { |
1085 | contextTailComment = (String) context.getAttribute( TAIL_COMMENT_ATTRIBUTE_NAME ); |
1086 | } |
1087 | |
1088 | if ( contextTailComment != null && contextTailComment.length() == 0 ) |
1089 | { |
1090 | contextTailComment = null; |
1091 | } |
1092 | |
1093 | final Set<String> uniqueSectionNames = new HashSet<String>( 16 ); |
1094 | final ArrayList<String> sectionNames = new ArrayList<String>( 16 ); |
1095 | sectionNames.add( LICENSE_SECTION_NAME ); |
1096 | sectionNames.add( ANNOTATIONS_SECTION_NAME ); |
1097 | sectionNames.add( DOCUMENTATION_SECTION_NAME ); |
1098 | sectionNames.add( CONSTRUCTORS_SECTION_NAME ); |
1099 | sectionNames.add( DEFAULT_CONSTRUCTOR_SECTION_NAME ); |
1100 | sectionNames.add( DEPENDENCIES_SECTION_NAME ); |
1101 | sectionNames.add( PROPERTIES_SECTION_NAME ); |
1102 | sectionNames.add( MESSAGES_SECTION_NAME ); |
1103 | |
1104 | final SourceFilesType sourceFilesType = new SourceFilesType(); |
1105 | final SourceFileType sourceFileType = new SourceFileType(); |
1106 | sourceFilesType.getSourceFile().add( sourceFileType ); |
1107 | |
1108 | final Specifications specifications = modules.getSpecifications( implementation.getIdentifier() ); |
1109 | final Dependencies dependencies = modules.getDependencies( implementation.getIdentifier() ); |
1110 | final Messages messages = modules.getMessages( implementation.getIdentifier() ); |
1111 | final Properties properties = modules.getProperties( implementation.getIdentifier() ); |
1112 | |
1113 | sourceFileType.setIdentifier( "Default" ); |
1114 | sourceFileType.setLocation( this.getDefaultSourceFileLocation( context, modules, implementation ) ); |
1115 | |
1116 | sourceFileType.setTemplate( IMPLEMENTATION_TEMPLATE ); |
1117 | sourceFileType.setHeadComment( contextHeadComment ); |
1118 | sourceFileType.setTailComment( contextTailComment ); |
1119 | sourceFileType.setSourceSections( new SourceSectionsType() ); |
1120 | |
1121 | SourceSectionType s = new SourceSectionType(); |
1122 | s.setName( LICENSE_SECTION_NAME ); |
1123 | s.setHeadTemplate( IMPLEMENTATION_LICENSE_TEMPLATE ); |
1124 | s.setOptional( true ); |
1125 | sourceFileType.getSourceSections().getSourceSection().add( s ); |
1126 | |
1127 | s = new SourceSectionType(); |
1128 | s.setName( ANNOTATIONS_SECTION_NAME ); |
1129 | s.setHeadTemplate( IMPLEMENTATION_ANNOTATIONS_TEMPLATE ); |
1130 | sourceFileType.getSourceSections().getSourceSection().add( s ); |
1131 | |
1132 | s = new SourceSectionType(); |
1133 | s.setName( DOCUMENTATION_SECTION_NAME ); |
1134 | s.setHeadTemplate( IMPLEMENTATION_DOCUMENTATION_TEMPLATE ); |
1135 | s.setOptional( true ); |
1136 | sourceFileType.getSourceSections().getSourceSection().add( s ); |
1137 | |
1138 | if ( specifications != null ) |
1139 | { |
1140 | sectionNames.ensureCapacity( sectionNames.size() + specifications.getSpecification().size() ); |
1141 | |
1142 | for ( final Specification specification : specifications.getSpecification() ) |
1143 | { |
1144 | final String sectionName = this.getDefaultSourceSectionName( context, modules, specification ); |
1145 | |
1146 | if ( sectionName != null ) |
1147 | { |
1148 | if ( !sectionNames.contains( sectionName ) ) |
1149 | { |
1150 | sectionNames.add( sectionName ); |
1151 | |
1152 | s = new SourceSectionType(); |
1153 | s.setName( sectionName ); |
1154 | s.setIndentationLevel( 1 ); |
1155 | s.setEditable( true ); |
1156 | sourceFileType.getSourceSections().getSourceSection().add( s ); |
1157 | } |
1158 | else if ( uniqueSectionNames.add( sectionName ) ) |
1159 | { |
1160 | final Module module = modules.getModuleOfImplementation( implementation.getIdentifier() ); |
1161 | context.log( Level.WARNING, getMessage( "implementationSectionNameUniqueness", |
1162 | implementation.getIdentifier(), |
1163 | module.getName(), |
1164 | sourceFileType.getIdentifier(), |
1165 | sectionName ), |
1166 | null ); |
1167 | |
1168 | } |
1169 | } |
1170 | } |
1171 | } |
1172 | |
1173 | final String sectionName = this.getDefaultSourceSectionName( context, modules, implementation ); |
1174 | |
1175 | if ( sectionName != null ) |
1176 | { |
1177 | if ( !sectionNames.contains( sectionName ) ) |
1178 | { |
1179 | sectionNames.add( sectionName ); |
1180 | |
1181 | s = new SourceSectionType(); |
1182 | s.setName( sectionName ); |
1183 | s.setIndentationLevel( 1 ); |
1184 | s.setEditable( true ); |
1185 | sourceFileType.getSourceSections().getSourceSection().add( s ); |
1186 | } |
1187 | else if ( uniqueSectionNames.add( sectionName ) ) |
1188 | { |
1189 | final Module module = modules.getModuleOfImplementation( implementation.getIdentifier() ); |
1190 | context.log( Level.WARNING, getMessage( "implementationSectionNameUniqueness", |
1191 | implementation.getIdentifier(), |
1192 | module.getName(), |
1193 | sourceFileType.getIdentifier(), |
1194 | sectionName ), |
1195 | null ); |
1196 | |
1197 | } |
1198 | } |
1199 | |
1200 | s = new SourceSectionType(); |
1201 | s.setName( CONSTRUCTORS_SECTION_NAME ); |
1202 | s.setIndentationLevel( 1 ); |
1203 | s.setHeadTemplate( CONSTRUCTORS_HEAD_TEMPLATE ); |
1204 | s.setTailTemplate( CONSTRUCTORS_TAIL_TEMPLATE ); |
1205 | s.setOptional( specifications == null || ( specifications.getSpecification().isEmpty() |
1206 | && specifications.getReference().isEmpty() ) ); |
1207 | |
1208 | s.setSourceSections( new SourceSectionsType() ); |
1209 | sourceFileType.getSourceSections().getSourceSection().add( s ); |
1210 | |
1211 | final SourceSectionType defaultCtor = new SourceSectionType(); |
1212 | defaultCtor.setName( DEFAULT_CONSTRUCTOR_SECTION_NAME ); |
1213 | defaultCtor.setIndentationLevel( 2 ); |
1214 | defaultCtor.setHeadTemplate( DEFAULT_CONSTRUCTOR_TEMPLATE ); |
1215 | defaultCtor.setEditable( true ); |
1216 | s.getSourceSections().getSourceSection().add( defaultCtor ); |
1217 | |
1218 | s = new SourceSectionType(); |
1219 | s.setName( DEPENDENCIES_SECTION_NAME ); |
1220 | s.setIndentationLevel( 1 ); |
1221 | s.setHeadTemplate( DEPENDENCIES_TEMPLATE ); |
1222 | s.setOptional( dependencies == null || dependencies.getDependency().isEmpty() ); |
1223 | sourceFileType.getSourceSections().getSourceSection().add( s ); |
1224 | |
1225 | s = new SourceSectionType(); |
1226 | s.setName( PROPERTIES_SECTION_NAME ); |
1227 | s.setIndentationLevel( 1 ); |
1228 | s.setHeadTemplate( PROPERTIES_TEMPLATE ); |
1229 | s.setOptional( properties == null || properties.getProperty().isEmpty() ); |
1230 | sourceFileType.getSourceSections().getSourceSection().add( s ); |
1231 | |
1232 | s = new SourceSectionType(); |
1233 | s.setName( MESSAGES_SECTION_NAME ); |
1234 | s.setIndentationLevel( 1 ); |
1235 | s.setHeadTemplate( MESSAGES_TEMPLATE ); |
1236 | s.setOptional( messages == null || messages.getMessage().isEmpty() ); |
1237 | sourceFileType.getSourceSections().getSourceSection().add( s ); |
1238 | |
1239 | return sourceFilesType; |
1240 | } |
1241 | |
1242 | /** |
1243 | * Overwrites a list of source code files with another list of source code files. |
1244 | * |
1245 | * @param targetSourceFiles The list to overwrite. |
1246 | * @param sourceSourceFiles The list to overwrite with. |
1247 | * @param preserveExisting {@code true}, to preserve existing attributes of source code files and sections; |
1248 | * {@code false}, to overwrite existing attributes of source code files and sections. |
1249 | * |
1250 | * @throws NullPointerException if {@code targetSourceFiles} or {@code sourceSourceFiles} is {@code null}. |
1251 | */ |
1252 | private void overwriteSourceFiles( final SourceFilesType targetSourceFiles, final SourceFilesType sourceSourceFiles, |
1253 | final boolean preserveExisting ) |
1254 | { |
1255 | if ( targetSourceFiles == null ) |
1256 | { |
1257 | throw new NullPointerException( "targetSourceFiles" ); |
1258 | } |
1259 | if ( sourceSourceFiles == null ) |
1260 | { |
1261 | throw new NullPointerException( "sourceSourceFiles" ); |
1262 | } |
1263 | |
1264 | try |
1265 | { |
1266 | for ( final SourceFileType s : sourceSourceFiles.getSourceFile() ) |
1267 | { |
1268 | final SourceFileType targetSourceFile = targetSourceFiles.getSourceFile( s.getIdentifier() ); |
1269 | |
1270 | if ( targetSourceFile != null ) |
1271 | { |
1272 | this.overwriteSourceFile( targetSourceFile, s, preserveExisting ); |
1273 | } |
1274 | } |
1275 | } |
1276 | catch ( final NoSuchFieldException e ) |
1277 | { |
1278 | throw new AssertionError( e ); |
1279 | } |
1280 | } |
1281 | |
1282 | /** |
1283 | * Overwrites a source code file with another source code file. |
1284 | * |
1285 | * @param targetSourceFile The source code file to overwrite. |
1286 | * @param sourceSourceFile The source code file to overwrite with. |
1287 | * @param preserveExisting {@code true}, to preserve existing attributes of the given source code file and sections; |
1288 | * {@code false}, to overwrite existing attributes of the given source code file and sections. |
1289 | * |
1290 | * @throws NullPointerException if {@code targetSourceFile} or {@code sourceSourceFile} is {@code null}. |
1291 | */ |
1292 | private void overwriteSourceFile( final SourceFileType targetSourceFile, final SourceFileType sourceSourceFile, |
1293 | final boolean preserveExisting ) |
1294 | throws NoSuchFieldException |
1295 | { |
1296 | if ( targetSourceFile == null ) |
1297 | { |
1298 | throw new NullPointerException( "targetSourceFile" ); |
1299 | } |
1300 | if ( sourceSourceFile == null ) |
1301 | { |
1302 | throw new NullPointerException( "sourceSourceFile" ); |
1303 | } |
1304 | |
1305 | if ( !preserveExisting ) |
1306 | { |
1307 | targetSourceFile.setIdentifier( sourceSourceFile.getIdentifier() ); |
1308 | targetSourceFile.setLocation( sourceSourceFile.getLocation() ); |
1309 | targetSourceFile.setTemplate( sourceSourceFile.getTemplate() ); |
1310 | targetSourceFile.setHeadComment( sourceSourceFile.getHeadComment() ); |
1311 | targetSourceFile.setTailComment( sourceSourceFile.getTailComment() ); |
1312 | |
1313 | if ( isFieldSet( sourceSourceFile, "_final" ) ) |
1314 | { |
1315 | targetSourceFile.setFinal( sourceSourceFile.isFinal() ); |
1316 | } |
1317 | if ( isFieldSet( sourceSourceFile, "modelVersion" ) ) |
1318 | { |
1319 | targetSourceFile.setModelVersion( sourceSourceFile.getModelVersion() ); |
1320 | } |
1321 | if ( isFieldSet( sourceSourceFile, "override" ) ) |
1322 | { |
1323 | targetSourceFile.setOverride( sourceSourceFile.isOverride() ); |
1324 | } |
1325 | } |
1326 | |
1327 | if ( sourceSourceFile.getSourceSections() != null ) |
1328 | { |
1329 | if ( targetSourceFile.getSourceSections() == null ) |
1330 | { |
1331 | targetSourceFile.setSourceSections( new SourceSectionsType() ); |
1332 | } |
1333 | |
1334 | this.overwriteSourceSections( targetSourceFile.getSourceSections(), sourceSourceFile.getSourceSections(), |
1335 | preserveExisting ); |
1336 | |
1337 | } |
1338 | } |
1339 | |
1340 | /** |
1341 | * Overwrites source code file sections with other source code file sections. |
1342 | * |
1343 | * @param targetSourceSections The source code file sections to overwrite. |
1344 | * @param sourceSourceSections The source code file sections to overwrite with. |
1345 | * @param preserveExisting {@code true}, to preserve existing attributes of the given source code file sections; |
1346 | * {@code false}, to overwrite existing attributes of the given source code file sections. |
1347 | * |
1348 | * @throws NullPointerException if {@code targetSourceSections} or {@code sourceSourceSections} is {@code null}. |
1349 | */ |
1350 | private void overwriteSourceSections( final SourceSectionsType targetSourceSections, |
1351 | final SourceSectionsType sourceSourceSections, |
1352 | final boolean preserveExisting ) throws NoSuchFieldException |
1353 | { |
1354 | if ( targetSourceSections == null ) |
1355 | { |
1356 | throw new NullPointerException( "targetSourceSections" ); |
1357 | } |
1358 | if ( sourceSourceSections == null ) |
1359 | { |
1360 | throw new NullPointerException( "sourceSourceSections" ); |
1361 | } |
1362 | |
1363 | for ( final SourceSectionType sourceSection : sourceSourceSections.getSourceSection() ) |
1364 | { |
1365 | SourceSectionType targetSection = null; |
1366 | |
1367 | for ( final SourceSectionType t : targetSourceSections.getSourceSection() ) |
1368 | { |
1369 | if ( sourceSection.getName().equals( t.getName() ) ) |
1370 | { |
1371 | targetSection = t; |
1372 | break; |
1373 | } |
1374 | } |
1375 | |
1376 | if ( targetSection != null ) |
1377 | { |
1378 | if ( !preserveExisting ) |
1379 | { |
1380 | targetSection.setName( sourceSection.getName() ); |
1381 | targetSection.setHeadTemplate( sourceSection.getHeadTemplate() ); |
1382 | targetSection.setTailTemplate( sourceSection.getTailTemplate() ); |
1383 | |
1384 | if ( isFieldSet( sourceSection, "editable" ) ) |
1385 | { |
1386 | targetSection.setEditable( sourceSection.isEditable() ); |
1387 | } |
1388 | if ( isFieldSet( sourceSection, "indentationLevel" ) ) |
1389 | { |
1390 | targetSection.setIndentationLevel( sourceSection.getIndentationLevel() ); |
1391 | } |
1392 | if ( isFieldSet( sourceSection, "modelVersion" ) ) |
1393 | { |
1394 | targetSection.setModelVersion( sourceSection.getModelVersion() ); |
1395 | } |
1396 | if ( isFieldSet( sourceSection, "optional" ) ) |
1397 | { |
1398 | targetSection.setOptional( sourceSection.isOptional() ); |
1399 | } |
1400 | } |
1401 | } |
1402 | else |
1403 | { |
1404 | targetSection = sourceSection.clone(); |
1405 | targetSourceSections.getSourceSection().add( targetSection ); |
1406 | } |
1407 | |
1408 | if ( sourceSection.getSourceSections() != null ) |
1409 | { |
1410 | if ( targetSection.getSourceSections() == null ) |
1411 | { |
1412 | targetSection.setSourceSections( new SourceSectionsType() ); |
1413 | } |
1414 | |
1415 | this.overwriteSourceSections( targetSection.getSourceSections(), sourceSection.getSourceSections(), |
1416 | preserveExisting ); |
1417 | } |
1418 | } |
1419 | } |
1420 | |
1421 | private static boolean isFieldSet( final Object object, final String fieldName ) throws NoSuchFieldException |
1422 | { |
1423 | final Field field = getField( object.getClass(), fieldName ); |
1424 | |
1425 | if ( field == null ) |
1426 | { |
1427 | throw new NoSuchFieldException( fieldName ); |
1428 | } |
1429 | |
1430 | final boolean accessible = field.isAccessible(); |
1431 | |
1432 | try |
1433 | { |
1434 | field.setAccessible( true ); |
1435 | return field.get( object ) != null; |
1436 | } |
1437 | catch ( final IllegalAccessException e ) |
1438 | { |
1439 | throw new AssertionError( e ); |
1440 | } |
1441 | finally |
1442 | { |
1443 | field.setAccessible( accessible ); |
1444 | } |
1445 | } |
1446 | |
1447 | private static Field getField( final Class<?> clazz, final String name ) |
1448 | { |
1449 | if ( clazz != null ) |
1450 | { |
1451 | try |
1452 | { |
1453 | return clazz.getDeclaredField( name ); |
1454 | } |
1455 | catch ( final NoSuchFieldException e ) |
1456 | { |
1457 | return getField( clazz.getSuperclass(), name ); |
1458 | } |
1459 | } |
1460 | |
1461 | return null; |
1462 | } |
1463 | |
1464 | private static String getMessage( final Throwable t ) |
1465 | { |
1466 | return t != null |
1467 | ? t.getMessage() != null && t.getMessage().trim().length() > 0 |
1468 | ? t.getMessage() |
1469 | : getMessage( t.getCause() ) |
1470 | : null; |
1471 | |
1472 | } |
1473 | |
1474 | private static String getMessage( final String key, final Object... args ) |
1475 | { |
1476 | return MessageFormat.format( ResourceBundle.getBundle( |
1477 | ToolsModelProvider.class.getName().replace( '.', '/' ), Locale.getDefault() ).getString( key ), args ); |
1478 | |
1479 | } |
1480 | |
1481 | } |