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