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.Locale;
36 import java.util.ResourceBundle;
37 import java.util.logging.Level;
38 import org.jomc.model.Dependencies;
39 import org.jomc.model.Implementation;
40 import org.jomc.model.JavaTypeName;
41 import org.jomc.model.Messages;
42 import org.jomc.model.ModelObjectException;
43 import org.jomc.model.Module;
44 import org.jomc.model.Modules;
45 import org.jomc.model.Properties;
46 import org.jomc.model.Specification;
47 import org.jomc.model.Specifications;
48 import org.jomc.model.modlet.ModelHelper;
49 import org.jomc.modlet.Model;
50 import org.jomc.modlet.ModelContext;
51 import org.jomc.modlet.ModelException;
52 import org.jomc.modlet.ModelProcessor;
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 if ( modules.getSpecifications() != null )
327 {
328 for ( int i = 0, s0 = modules.getSpecifications().getSpecification().size(); i < s0; i++ )
329 {
330 final Specification specification = modules.getSpecifications().getSpecification().get( i );
331 final SourceFileType sourceFileType = specification.getAnyObject( SourceFileType.class );
332 final SourceFilesType sourceFilesType = specification.getAnyObject( SourceFilesType.class );
333
334 if ( sourceFileType != null )
335 {
336 if ( sourceFileType.getLocation() == null && specification.getClazz() != null )
337 {
338
339 sourceFileType.setLocation( new StringBuilder( specification.getClazz().length() + 5 ).
340 append( specification.getClazz().replace( '.', '/' ) ).append( ".java" ).
341 toString() );
342
343 }
344
345 if ( sourceFileType.getHeadComment() == null )
346 {
347
348 sourceFileType.setHeadComment( "//" );
349 }
350 }
351
352 if ( sourceFilesType != null )
353 {
354 this.applyDefaults( context, modules, specification, sourceFilesType );
355 }
356 }
357 }
358
359 if ( modules.getImplementations() != null )
360 {
361 for ( int i = 0, s0 = modules.getImplementations().getImplementation().size(); i < s0; i++ )
362 {
363 final Implementation implementation = modules.getImplementations().getImplementation().get( i );
364 final SourceFileType sourceFileType = implementation.getAnyObject( SourceFileType.class );
365 final SourceFilesType sourceFilesType = implementation.getAnyObject( SourceFilesType.class );
366
367 if ( sourceFileType != null )
368 {
369 if ( sourceFileType.getLocation() == null && implementation.getClazz() != null )
370 {
371
372 sourceFileType.setLocation( new StringBuilder( implementation.getClazz().length() + 5 ).
373 append( implementation.getClazz().replace( '.', '/' ) ).append( ".java" ).
374 toString() );
375
376 }
377
378 if ( sourceFileType.getHeadComment() == null )
379 {
380
381 sourceFileType.setHeadComment( "//" );
382 }
383 }
384
385 if ( sourceFilesType != null )
386 {
387 this.applyDefaults( context, modules, implementation, sourceFilesType );
388 }
389 }
390 }
391
392 if ( classpathModule != null )
393 {
394 modules.getModule().remove( classpathModule );
395 }
396 }
397 }
398 else if ( context.isLoggable( Level.FINER ) )
399 {
400 context.log( Level.FINER, getMessage( "disabled", this.getClass().getSimpleName(),
401 model.getIdentifier() ), null );
402
403 }
404
405 return processed;
406 }
407
408
409
410
411
412
413
414
415
416
417
418
419 private void applyDefaults( final ModelContext context, final Modules modules, final Specification specification,
420 final SourceFilesType sourceFilesType )
421 {
422 if ( context == null )
423 {
424 throw new NullPointerException( "context" );
425 }
426 if ( modules == null )
427 {
428 throw new NullPointerException( "modules" );
429 }
430 if ( specification == null )
431 {
432 throw new NullPointerException( "specification" );
433 }
434 if ( sourceFilesType == null )
435 {
436 throw new NullPointerException( "sourceFilesType" );
437 }
438
439 for ( int i = 0, s0 = sourceFilesType.getSourceFile().size(); i < s0; i++ )
440 {
441 final SourceFileType s = sourceFilesType.getSourceFile().get( i );
442
443 if ( s.getTemplate() == null )
444 {
445 s.setTemplate( SPECIFICATION_TEMPLATE );
446 }
447 if ( s.getLocation() == null )
448 {
449 try
450 {
451 final JavaTypeName javaTypeName = specification.getJavaTypeName();
452
453 if ( javaTypeName != null )
454 {
455 s.setLocation( javaTypeName.getQualifiedName().replace( '.', '/' ) + ".java" );
456 }
457 }
458 catch ( final ModelObjectException e )
459 {
460 context.log( Level.WARNING, getMessage( e ), null );
461 }
462 }
463 if ( s.getHeadComment() == null )
464 {
465 s.setHeadComment( "//" );
466 }
467
468 this.applyDefaults( context, modules, specification, s.getSourceSections() );
469 }
470 }
471
472
473
474
475
476
477
478
479
480
481
482 private void applyDefaults( final ModelContext context, final Modules modules, final Specification specification,
483 final SourceSectionsType sourceSectionsType )
484 {
485 if ( context == null )
486 {
487 throw new NullPointerException( "context" );
488 }
489 if ( modules == null )
490 {
491 throw new NullPointerException( "modules" );
492 }
493 if ( specification == null )
494 {
495 throw new NullPointerException( "specification" );
496 }
497
498 try
499 {
500 if ( sourceSectionsType != null )
501 {
502 for ( int i = 0, s0 = sourceSectionsType.getSourceSection().size(); i < s0; i++ )
503 {
504 final SourceSectionType s = sourceSectionsType.getSourceSection().get( i );
505
506 if ( LICENSE_SECTION_NAME.equals( s.getName() ) )
507 {
508 if ( !isFieldSet( s, "optional" ) )
509 {
510 s.setOptional( true );
511 }
512 if ( s.getHeadTemplate() == null )
513 {
514 s.setHeadTemplate( SPECIFICATION_LICENSE_TEMPLATE );
515 }
516 }
517
518 if ( ANNOTATIONS_SECTION_NAME.equals( s.getName() ) )
519 {
520 if ( s.getHeadTemplate() == null )
521 {
522 s.setHeadTemplate( SPECIFICATION_ANNOTATIONS_TEMPLATE );
523 }
524 }
525
526 if ( DOCUMENTATION_SECTION_NAME.equals( s.getName() ) )
527 {
528 if ( !isFieldSet( s, "optional" ) )
529 {
530 s.setOptional( true );
531 }
532 if ( s.getHeadTemplate() == null )
533 {
534 s.setHeadTemplate( SPECIFICATION_DOCUMENTATION_TEMPLATE );
535 }
536 }
537
538 try
539 {
540 final JavaTypeName javaTypeName = specification.getJavaTypeName();
541
542 if ( javaTypeName != null )
543 {
544 if ( javaTypeName.getName( false ).equals( s.getName() ) )
545 {
546 if ( !isFieldSet( s, "editable" ) )
547 {
548 s.setEditable( true );
549 }
550 if ( !isFieldSet( s, "indentationLevel" ) )
551 {
552 s.setIndentationLevel( 1 );
553 }
554 }
555 }
556 }
557 catch ( final ModelObjectException e )
558 {
559 context.log( Level.WARNING, getMessage( e ), null );
560 }
561
562 this.applyDefaults( context, modules, specification, s.getSourceSections() );
563 }
564 }
565 }
566 catch ( final NoSuchFieldException e )
567 {
568 throw new AssertionError( e );
569 }
570 }
571
572
573
574
575
576
577
578
579
580
581
582
583 private void applyDefaults( final ModelContext context, final Modules modules, final Implementation implementation,
584 final SourceFilesType sourceFilesType )
585 {
586 if ( context == null )
587 {
588 throw new NullPointerException( "context" );
589 }
590 if ( modules == null )
591 {
592 throw new NullPointerException( "modules" );
593 }
594 if ( implementation == null )
595 {
596 throw new NullPointerException( "implementation" );
597 }
598 if ( sourceFilesType == null )
599 {
600 throw new NullPointerException( "sourceFilesType" );
601 }
602
603 for ( int i = 0, s0 = sourceFilesType.getSourceFile().size(); i < s0; i++ )
604 {
605 final SourceFileType s = sourceFilesType.getSourceFile().get( i );
606
607 if ( s.getTemplate() == null )
608 {
609 s.setTemplate( IMPLEMENTATION_TEMPLATE );
610 }
611 if ( s.getLocation() == null )
612 {
613 try
614 {
615 final JavaTypeName javaTypeName = implementation.getJavaTypeName();
616
617 if ( javaTypeName != null )
618 {
619 s.setLocation( javaTypeName.getQualifiedName().replace( '.', '/' ) + ".java" );
620 }
621 }
622 catch ( final ModelObjectException e )
623 {
624 context.log( Level.WARNING, getMessage( e ), null );
625 }
626 }
627 if ( s.getHeadComment() == null )
628 {
629 s.setHeadComment( "//" );
630 }
631
632 this.applyDefaults( context, modules, implementation, s.getSourceSections() );
633 }
634 }
635
636
637
638
639
640
641
642
643
644
645
646 private void applyDefaults( final ModelContext context, final Modules modules, final Implementation implementation,
647 final SourceSectionsType sourceSectionsType )
648 {
649 if ( context == null )
650 {
651 throw new NullPointerException( "context" );
652 }
653 if ( modules == null )
654 {
655 throw new NullPointerException( "modules" );
656 }
657 if ( implementation == null )
658 {
659 throw new NullPointerException( "implementation" );
660 }
661
662 final Specifications specifications = modules.getSpecifications( implementation.getIdentifier() );
663 final Dependencies dependencies = modules.getDependencies( implementation.getIdentifier() );
664 final Messages messages = modules.getMessages( implementation.getIdentifier() );
665 final Properties properties = modules.getProperties( implementation.getIdentifier() );
666
667 try
668 {
669 if ( sourceSectionsType != null )
670 {
671 for ( int i = 0, s0 = sourceSectionsType.getSourceSection().size(); i < s0; i++ )
672 {
673 final SourceSectionType s = sourceSectionsType.getSourceSection().get( i );
674
675 if ( LICENSE_SECTION_NAME.equals( s.getName() ) )
676 {
677 if ( !isFieldSet( s, "optional" ) )
678 {
679 s.setOptional( true );
680 }
681 if ( s.getHeadTemplate() == null )
682 {
683 s.setHeadTemplate( IMPLEMENTATION_LICENSE_TEMPLATE );
684 }
685 }
686
687 if ( ANNOTATIONS_SECTION_NAME.equals( s.getName() ) )
688 {
689 if ( s.getHeadTemplate() == null )
690 {
691 s.setHeadTemplate( IMPLEMENTATION_ANNOTATIONS_TEMPLATE );
692 }
693 }
694
695 if ( DOCUMENTATION_SECTION_NAME.equals( s.getName() ) )
696 {
697 if ( !isFieldSet( s, "optional" ) )
698 {
699 s.setOptional( true );
700 }
701 if ( s.getHeadTemplate() == null )
702 {
703 s.setHeadTemplate( IMPLEMENTATION_DOCUMENTATION_TEMPLATE );
704 }
705 }
706
707 if ( CONSTRUCTORS_SECTION_NAME.equals( s.getName() ) )
708 {
709 if ( !isFieldSet( s, "indentationLevel" ) )
710 {
711 s.setIndentationLevel( 1 );
712 }
713 if ( s.getHeadTemplate() == null )
714 {
715 s.setHeadTemplate( CONSTRUCTORS_HEAD_TEMPLATE );
716 }
717 if ( s.getTailTemplate() == null )
718 {
719 s.setTailTemplate( CONSTRUCTORS_TAIL_TEMPLATE );
720 }
721 if ( !isFieldSet( s, "optional" ) )
722 {
723 s.setOptional( specifications == null || ( specifications.getSpecification().isEmpty()
724 && specifications.getReference().isEmpty() ) );
725
726 }
727 }
728
729 if ( DEFAULT_CONSTRUCTOR_SECTION_NAME.equals( s.getName() ) )
730 {
731 if ( !isFieldSet( s, "editable" ) )
732 {
733 s.setEditable( true );
734 }
735 if ( !isFieldSet( s, "indentationLevel" ) )
736 {
737 s.setIndentationLevel( 2 );
738 }
739 if ( s.getHeadTemplate() == null )
740 {
741 s.setHeadTemplate( DEFAULT_CONSTRUCTOR_TEMPLATE );
742 }
743 }
744
745 if ( DEPENDENCIES_SECTION_NAME.equals( s.getName() ) )
746 {
747 if ( !isFieldSet( s, "optional" ) )
748 {
749 s.setOptional( dependencies == null || dependencies.getDependency().isEmpty() );
750 }
751 if ( !isFieldSet( s, "indentationLevel" ) )
752 {
753 s.setIndentationLevel( 1 );
754 }
755 if ( s.getHeadTemplate() == null )
756 {
757 s.setHeadTemplate( DEPENDENCIES_TEMPLATE );
758 }
759 }
760
761 if ( PROPERTIES_SECTION_NAME.equals( s.getName() ) )
762 {
763 if ( !isFieldSet( s, "optional" ) )
764 {
765 s.setOptional( properties == null || properties.getProperty().isEmpty() );
766 }
767 if ( !isFieldSet( s, "indentationLevel" ) )
768 {
769 s.setIndentationLevel( 1 );
770 }
771 if ( s.getHeadTemplate() == null )
772 {
773 s.setHeadTemplate( PROPERTIES_TEMPLATE );
774 }
775 }
776
777 if ( MESSAGES_SECTION_NAME.equals( s.getName() ) )
778 {
779 if ( !isFieldSet( s, "optional" ) )
780 {
781 s.setOptional( messages == null || messages.getMessage().isEmpty() );
782 }
783 if ( !isFieldSet( s, "indentationLevel" ) )
784 {
785 s.setIndentationLevel( 1 );
786 }
787 if ( s.getHeadTemplate() == null )
788 {
789 s.setHeadTemplate( MESSAGES_TEMPLATE );
790 }
791 }
792
793 if ( specifications != null )
794 {
795 for ( final Specification specification : specifications.getSpecification() )
796 {
797 try
798 {
799 final JavaTypeName javaTypeName = specification.getJavaTypeName();
800
801 if ( javaTypeName != null )
802 {
803 if ( javaTypeName.getName( false ).equals( s.getName() ) )
804 {
805 if ( !isFieldSet( s, "editable" ) )
806 {
807 s.setEditable( true );
808 }
809 if ( !isFieldSet( s, "indentationLevel" ) )
810 {
811 s.setIndentationLevel( 1 );
812 }
813 }
814 }
815 }
816 catch ( final ModelObjectException e )
817 {
818 context.log( Level.WARNING, getMessage( e ), null );
819 }
820 }
821 }
822
823 try
824 {
825 final JavaTypeName javaTypeName = implementation.getJavaTypeName();
826
827 if ( javaTypeName != null )
828 {
829 if ( javaTypeName.getName( false ).equals( s.getName() ) )
830 {
831 if ( !isFieldSet( s, "editable" ) )
832 {
833 s.setEditable( true );
834 }
835 if ( !isFieldSet( s, "indentationLevel" ) )
836 {
837 s.setIndentationLevel( 1 );
838 }
839 }
840 }
841 }
842 catch ( final ModelObjectException e )
843 {
844 context.log( Level.WARNING, getMessage( e ), null );
845 }
846
847 this.applyDefaults( context, modules, implementation, s.getSourceSections() );
848 }
849 }
850 }
851 catch ( final NoSuchFieldException e )
852 {
853 throw new AssertionError( e );
854 }
855 }
856
857 private static boolean isFieldSet( final Object object, final String fieldName ) throws NoSuchFieldException
858 {
859 final Field field = object.getClass().getDeclaredField( fieldName );
860 final boolean accessible = field.isAccessible();
861
862 try
863 {
864 field.setAccessible( true );
865 return field.get( object ) != null;
866 }
867 catch ( final IllegalAccessException e )
868 {
869 throw new AssertionError( e );
870 }
871 finally
872 {
873 field.setAccessible( accessible );
874 }
875 }
876
877 private static String getMessage( final Throwable t )
878 {
879 return t != null ? t.getMessage() != null ? t.getMessage() : getMessage( t.getCause() ) : null;
880 }
881
882 private static String getMessage( final String key, final Object... args )
883 {
884 return MessageFormat.format( ResourceBundle.getBundle(
885 ToolsModelProcessor.class.getName().replace( '.', '/' ), Locale.getDefault() ).getString( key ), args );
886
887 }
888
889 }