1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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
61
62
63
64
65
66
67 public class ToolsModelProcessor implements ModelProcessor
68 {
69
70
71
72
73
74
75 public static final String ENABLED_ATTRIBUTE_NAME = "org.jomc.tools.modlet.ToolsModelProcessor.enabledAttribute";
76
77
78
79
80
81 private static final String DEFAULT_ENABLED_PROPERTY_NAME =
82 "org.jomc.tools.modlet.ToolsModelProcessor.defaultEnabled";
83
84
85
86
87
88 private static final Boolean DEFAULT_ENABLED = Boolean.TRUE;
89
90
91 private static volatile Boolean defaultEnabled;
92
93
94 private Boolean enabled;
95
96
97
98
99
100
101
102
103 public static final String MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME =
104 "org.jomc.tools.modlet.ToolsModelProcessor.modelObjectClasspathResolutionEnabledAttribute";
105
106
107
108
109
110
111 private static final String DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_PROPERTY_NAME =
112 "org.jomc.tools.modlet.ToolsModelProcessor.defaultModelObjectClasspathResolutionEnabled";
113
114
115
116
117
118 private static final Boolean DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED = Boolean.TRUE;
119
120
121 private static volatile Boolean defaultModelObjectClasspathResolutionEnabled;
122
123
124 private Boolean modelObjectClasspathResolutionEnabled;
125
126
127 public ToolsModelProcessor()
128 {
129 super();
130 }
131
132
133
134
135
136
137
138
139
140
141
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
157
158
159
160
161
162 public static void setDefaultEnabled( final Boolean value )
163 {
164 defaultEnabled = value;
165 }
166
167
168
169
170
171
172
173
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
187
188
189
190
191
192 public final void setEnabled( final Boolean value )
193 {
194 this.enabled = value;
195 }
196
197
198
199
200
201
202
203
204
205
206
207
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
224
225
226
227
228
229
230 public static void setDefaultModelObjectClasspathResolutionEnabled( final Boolean value )
231 {
232 defaultModelObjectClasspathResolutionEnabled = value;
233 }
234
235
236
237
238
239
240
241
242
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
256
257
258
259
260
261 public final void setModelObjectClasspathResolutionEnabled( final Boolean value )
262 {
263 this.modelObjectClasspathResolutionEnabled = value;
264 }
265
266
267
268
269
270
271
272
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
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
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
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
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
413
414
415
416
417
418
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
461
462
463
464
465
466
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
548
549
550
551
552
553
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
596
597
598
599
600
601
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 }