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.List;
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.*;
67
68
69
70
71
72
73
74
75
76 public class ToolsModelProvider implements ModelProvider
77 {
78
79
80 private static final QName SOURCE_FILES_QNAME = new ObjectFactory().createSourceFiles( null ).getName();
81
82
83
84
85
86
87 public static final String ENABLED_ATTRIBUTE_NAME = "org.jomc.tools.modlet.ToolsModelProvider.enabledAttribute";
88
89
90
91
92
93 private static final String DEFAULT_ENABLED_PROPERTY_NAME =
94 "org.jomc.tools.modlet.ToolsModelProvider.defaultEnabled";
95
96
97
98
99
100 private static final Boolean DEFAULT_ENABLED = Boolean.TRUE;
101
102
103 private static volatile Boolean defaultEnabled;
104
105
106 private Boolean enabled;
107
108
109
110
111
112
113
114
115 public static final String MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME =
116 "org.jomc.tools.modlet.ToolsModelProvider.modelObjectClasspathResolutionEnabledAttribute";
117
118
119
120
121
122
123 private static final String DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_PROPERTY_NAME =
124 "org.jomc.tools.modlet.ToolsModelProvider.defaultModelObjectClasspathResolutionEnabled";
125
126
127
128
129
130 private static final Boolean DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED = Boolean.TRUE;
131
132
133 private static volatile Boolean defaultModelObjectClasspathResolutionEnabled;
134
135
136 private Boolean modelObjectClasspathResolutionEnabled;
137
138
139 public ToolsModelProvider()
140 {
141 super();
142 }
143
144
145
146
147
148
149
150
151
152
153
154
155 public static boolean isDefaultEnabled()
156 {
157 if ( defaultEnabled == null )
158 {
159 defaultEnabled = Boolean.valueOf( System.getProperty( DEFAULT_ENABLED_PROPERTY_NAME,
160 Boolean.toString( DEFAULT_ENABLED ) ) );
161
162 }
163
164 return defaultEnabled;
165 }
166
167
168
169
170
171
172
173
174 public static void setDefaultEnabled( final Boolean value )
175 {
176 defaultEnabled = value;
177 }
178
179
180
181
182
183
184
185
186
187 public final boolean isEnabled()
188 {
189 if ( this.enabled == null )
190 {
191 this.enabled = isDefaultEnabled();
192 }
193
194 return this.enabled;
195 }
196
197
198
199
200
201
202
203
204 public final void setEnabled( final Boolean value )
205 {
206 this.enabled = value;
207 }
208
209
210
211
212
213
214
215
216
217
218
219
220
221 public static boolean isDefaultModelObjectClasspathResolutionEnabled()
222 {
223 if ( defaultModelObjectClasspathResolutionEnabled == null )
224 {
225 defaultModelObjectClasspathResolutionEnabled = Boolean.valueOf( System.getProperty(
226 DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_PROPERTY_NAME,
227 Boolean.toString( DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED ) ) );
228
229 }
230
231 return defaultModelObjectClasspathResolutionEnabled;
232 }
233
234
235
236
237
238
239
240
241
242 public static void setDefaultModelObjectClasspathResolutionEnabled( final Boolean value )
243 {
244 defaultModelObjectClasspathResolutionEnabled = value;
245 }
246
247
248
249
250
251
252
253
254
255
256 public final boolean isModelObjectClasspathResolutionEnabled()
257 {
258 if ( this.modelObjectClasspathResolutionEnabled == null )
259 {
260 this.modelObjectClasspathResolutionEnabled = isDefaultModelObjectClasspathResolutionEnabled();
261 }
262
263 return this.modelObjectClasspathResolutionEnabled;
264 }
265
266
267
268
269
270
271
272
273 public final void setModelObjectClasspathResolutionEnabled( final Boolean value )
274 {
275 this.modelObjectClasspathResolutionEnabled = value;
276 }
277
278
279
280
281
282
283
284
285
286 public Model findModel( final ModelContext context, final Model model ) throws ModelException
287 {
288 if ( context == null )
289 {
290 throw new NullPointerException( "context" );
291 }
292 if ( model == null )
293 {
294 throw new NullPointerException( "model" );
295 }
296
297 Model provided = null;
298
299 boolean contextEnabled = this.isEnabled();
300 if ( DEFAULT_ENABLED == contextEnabled && context.getAttribute( ENABLED_ATTRIBUTE_NAME ) instanceof Boolean )
301 {
302 contextEnabled = (Boolean) context.getAttribute( ENABLED_ATTRIBUTE_NAME );
303 }
304
305 boolean contextModelObjectClasspathResolutionEnabled = this.isModelObjectClasspathResolutionEnabled();
306 if ( contextModelObjectClasspathResolutionEnabled == DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED
307 && context.getAttribute( MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME ) instanceof Boolean )
308 {
309 contextModelObjectClasspathResolutionEnabled =
310 (Boolean) context.getAttribute( MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME );
311
312 }
313
314 if ( contextEnabled )
315 {
316 provided = model.clone();
317 final Modules modules = ModelHelper.getModules( provided );
318
319 if ( modules != null )
320 {
321 Module classpathModule = null;
322 if ( contextModelObjectClasspathResolutionEnabled )
323 {
324 classpathModule = modules.getClasspathModule( Modules.getDefaultClasspathModuleName(),
325 context.getClassLoader() );
326
327 if ( classpathModule != null
328 && modules.getModule( Modules.getDefaultClasspathModuleName() ) == null )
329 {
330 modules.getModule().add( classpathModule );
331 }
332 else
333 {
334 classpathModule = null;
335 }
336 }
337
338 if ( modules.getSpecifications() != null )
339 {
340 for ( int i = 0, s0 = modules.getSpecifications().getSpecification().size(); i < s0; i++ )
341 {
342 final Specification specification = modules.getSpecifications().getSpecification().get( i );
343 final SourceFileType sourceFileType = specification.getAnyObject( SourceFileType.class );
344 final SourceFilesType sourceFilesType = specification.getAnyObject( SourceFilesType.class );
345
346 if ( sourceFileType == null && specification.isClassDeclaration() )
347 {
348 final SourceFilesType defaultSourceFiles =
349 this.getDefaultSourceFilesType( context, modules, specification );
350
351 if ( sourceFilesType != null )
352 {
353 this.overwriteSourceFiles( sourceFilesType, defaultSourceFiles, true );
354 }
355 else
356 {
357 specification.getAny().add( new ObjectFactory().createSourceFiles(
358 this.getDefaultSourceFilesType( context, modules, specification ) ) );
359
360 }
361 }
362 }
363 }
364
365 if ( modules.getImplementations() != null )
366 {
367 final Map<Implementation, SourceFilesType> userSourceFiles =
368 new HashMap<Implementation, SourceFilesType>();
369
370 InheritanceModel imodel = new InheritanceModel( modules );
371
372 for ( int i = 0, s0 = modules.getImplementations().getImplementation().size(); i < s0; i++ )
373 {
374 final Implementation implementation = modules.getImplementations().getImplementation().get( i );
375 final SourceFileType sourceFileType = implementation.getAnyObject( SourceFileType.class );
376 final SourceFilesType sourceFilesType = implementation.getAnyObject( SourceFilesType.class );
377
378 if ( sourceFileType == null )
379 {
380 if ( sourceFilesType != null )
381 {
382 userSourceFiles.put( implementation, sourceFilesType );
383 }
384 else if ( implementation.isClassDeclaration() )
385 {
386 final SourceFilesType defaultSourceFiles =
387 this.getDefaultSourceFilesType( context, modules, implementation );
388
389 boolean finalAncestor = false;
390
391 final Set<InheritanceModel.Node<JAXBElement<?>>> sourceFilesNodes =
392 imodel.getJaxbElementNodes( implementation.getIdentifier(), SOURCE_FILES_QNAME );
393
394 for ( final InheritanceModel.Node<JAXBElement<?>> sourceFilesNode : sourceFilesNodes )
395 {
396 if ( sourceFilesNode.getModelObject().getValue() instanceof SourceFilesType )
397 {
398 final SourceFilesType ancestorSourceFiles =
399 (SourceFilesType) sourceFilesNode.getModelObject().getValue();
400
401 this.overwriteSourceFiles( defaultSourceFiles, ancestorSourceFiles, false );
402
403 if ( ancestorSourceFiles.isFinal() )
404 {
405 finalAncestor = true;
406 }
407 }
408 }
409
410 if ( !finalAncestor )
411 {
412 implementation.getAny().add(
413 new ObjectFactory().createSourceFiles( defaultSourceFiles ) );
414
415 }
416 }
417 }
418 }
419
420 for ( final Map.Entry<Implementation, SourceFilesType> e : userSourceFiles.entrySet() )
421 {
422 this.overwriteSourceFiles(
423 e.getValue(), this.getDefaultSourceFilesType( context, modules, e.getKey() ), true );
424
425 }
426
427 imodel = new InheritanceModel( modules );
428
429 for ( int i = 0, s0 = modules.getImplementations().getImplementation().size(); i < s0; i++ )
430 {
431 final Implementation implementation = modules.getImplementations().getImplementation().get( i );
432 final SourceFilesType sourceFilesType = implementation.getAnyObject( SourceFilesType.class );
433
434 if ( sourceFilesType != null && !userSourceFiles.containsKey( implementation ) )
435 {
436 boolean override = false;
437
438 final Set<InheritanceModel.Node<JAXBElement<?>>> sourceFilesNodes =
439 imodel.getJaxbElementNodes( implementation.getIdentifier(), SOURCE_FILES_QNAME );
440
441 for ( final InheritanceModel.Node<JAXBElement<?>> e : sourceFilesNodes )
442 {
443 if ( !e.getOverriddenNodes().isEmpty() )
444 {
445 override = true;
446 break;
447 }
448 }
449
450 if ( override )
451 {
452 sourceFilesType.setOverride( override );
453 }
454 }
455 }
456 }
457
458 if ( classpathModule != null )
459 {
460 modules.getModule().remove( classpathModule );
461 }
462 }
463 }
464 else if ( context.isLoggable( Level.FINER ) )
465 {
466 context.log( Level.FINER, getMessage( "disabled", this.getClass().getSimpleName(),
467 model.getIdentifier() ), null );
468
469 }
470
471 return provided;
472 }
473
474
475
476
477
478
479
480
481
482
483
484
485 private SourceFilesType getDefaultSourceFilesType( final ModelContext context, final Modules modules,
486 final Specification specification )
487 {
488 if ( context == null )
489 {
490 throw new NullPointerException( "context" );
491 }
492 if ( modules == null )
493 {
494 throw new NullPointerException( "modules" );
495 }
496 if ( specification == null )
497 {
498 throw new NullPointerException( "specification" );
499 }
500
501 final SourceFilesType sourceFilesType = new SourceFilesType();
502 final SourceFileType sourceFileType = new SourceFileType();
503 sourceFilesType.getSourceFile().add( sourceFileType );
504
505 sourceFileType.setIdentifier( "Default" );
506
507 try
508 {
509 if ( specification.getJavaTypeName() != null )
510 {
511 sourceFileType.setLocation(
512 specification.getJavaTypeName().getQualifiedName().replace( '.', '/' ) + ".java" );
513
514 }
515 }
516 catch ( final ModelObjectException e )
517 {
518 context.log( Level.WARNING, getMessage( e ), null );
519 }
520
521 sourceFileType.setTemplate( SPECIFICATION_TEMPLATE );
522 sourceFileType.setHeadComment( "//" );
523 sourceFileType.setSourceSections( new SourceSectionsType() );
524
525 SourceSectionType s = new SourceSectionType();
526 s.setName( LICENSE_SECTION_NAME );
527 s.setHeadTemplate( SPECIFICATION_LICENSE_TEMPLATE );
528 s.setOptional( true );
529 sourceFileType.getSourceSections().getSourceSection().add( s );
530
531 s = new SourceSectionType();
532 s.setName( ANNOTATIONS_SECTION_NAME );
533 s.setHeadTemplate( SPECIFICATION_ANNOTATIONS_TEMPLATE );
534 sourceFileType.getSourceSections().getSourceSection().add( s );
535
536 s = new SourceSectionType();
537 s.setName( DOCUMENTATION_SECTION_NAME );
538 s.setHeadTemplate( SPECIFICATION_DOCUMENTATION_TEMPLATE );
539 s.setOptional( true );
540 sourceFileType.getSourceSections().getSourceSection().add( s );
541
542 try
543 {
544 final JavaTypeName javaTypeName = specification.getJavaTypeName();
545
546 if ( javaTypeName != null )
547 {
548 s = new SourceSectionType();
549 s.setName( javaTypeName.getName( false ) );
550 s.setIndentationLevel( 1 );
551 s.setEditable( true );
552 sourceFileType.getSourceSections().getSourceSection().add( s );
553 }
554 }
555 catch ( final ModelObjectException e )
556 {
557 context.log( Level.WARNING, getMessage( e ), null );
558 }
559
560 return sourceFilesType;
561 }
562
563
564
565
566
567
568
569
570
571
572
573
574 private SourceFilesType getDefaultSourceFilesType( final ModelContext context, final Modules modules,
575 final Implementation implementation )
576 {
577 if ( context == null )
578 {
579 throw new NullPointerException( "context" );
580 }
581 if ( modules == null )
582 {
583 throw new NullPointerException( "modules" );
584 }
585 if ( implementation == null )
586 {
587 throw new NullPointerException( "implementation" );
588 }
589
590 final SourceFilesType sourceFilesType = new SourceFilesType();
591 final SourceFileType sourceFileType = new SourceFileType();
592 sourceFilesType.getSourceFile().add( sourceFileType );
593
594 final Specifications specifications = modules.getSpecifications( implementation.getIdentifier() );
595 final Dependencies dependencies = modules.getDependencies( implementation.getIdentifier() );
596 final Messages messages = modules.getMessages( implementation.getIdentifier() );
597 final Properties properties = modules.getProperties( implementation.getIdentifier() );
598
599 sourceFileType.setIdentifier( "Default" );
600
601 try
602 {
603 if ( implementation.getJavaTypeName() != null )
604 {
605 sourceFileType.setLocation(
606 implementation.getJavaTypeName().getQualifiedName().replace( '.', '/' ) + ".java" );
607
608 }
609 }
610 catch ( final ModelObjectException e )
611 {
612 context.log( Level.WARNING, getMessage( e ), null );
613 }
614
615 sourceFileType.setTemplate( IMPLEMENTATION_TEMPLATE );
616 sourceFileType.setHeadComment( "//" );
617 sourceFileType.setSourceSections( new SourceSectionsType() );
618
619 SourceSectionType s = new SourceSectionType();
620 s.setName( LICENSE_SECTION_NAME );
621 s.setHeadTemplate( IMPLEMENTATION_LICENSE_TEMPLATE );
622 s.setOptional( true );
623 sourceFileType.getSourceSections().getSourceSection().add( s );
624
625 s = new SourceSectionType();
626 s.setName( ANNOTATIONS_SECTION_NAME );
627 s.setHeadTemplate( IMPLEMENTATION_ANNOTATIONS_TEMPLATE );
628 sourceFileType.getSourceSections().getSourceSection().add( s );
629
630 s = new SourceSectionType();
631 s.setName( DOCUMENTATION_SECTION_NAME );
632 s.setHeadTemplate( IMPLEMENTATION_DOCUMENTATION_TEMPLATE );
633 s.setOptional( true );
634 sourceFileType.getSourceSections().getSourceSection().add( s );
635
636 List<JavaTypeName> javaTypeNames = null;
637
638 if ( specifications != null )
639 {
640 javaTypeNames = new ArrayList<JavaTypeName>( specifications.getSpecification().size() );
641
642 for ( final Specification specification : specifications.getSpecification() )
643 {
644 try
645 {
646 final JavaTypeName javaTypeName = specification.getJavaTypeName();
647
648 if ( javaTypeName != null && !javaTypeNames.contains( javaTypeName ) )
649 {
650 javaTypeNames.add( javaTypeName );
651 }
652 }
653 catch ( final ModelObjectException e )
654 {
655 context.log( Level.WARNING, getMessage( e ), null );
656 }
657 }
658
659 for ( int i = 0, s0 = javaTypeNames.size(); i < s0; i++ )
660 {
661 s = new SourceSectionType();
662 s.setName( javaTypeNames.get( i ).getName( false ) );
663 s.setIndentationLevel( 1 );
664 s.setEditable( true );
665 sourceFileType.getSourceSections().getSourceSection().add( s );
666 }
667 }
668
669 try
670 {
671 final JavaTypeName javaTypeName = implementation.getJavaTypeName();
672
673 if ( javaTypeName != null && ( javaTypeNames == null || !javaTypeNames.contains( javaTypeName ) ) )
674 {
675 s = new SourceSectionType();
676 s.setName( javaTypeName.getName( false ) );
677 s.setIndentationLevel( 1 );
678 s.setEditable( true );
679 sourceFileType.getSourceSections().getSourceSection().add( s );
680 }
681 }
682 catch ( final ModelObjectException e )
683 {
684 context.log( Level.WARNING, getMessage( e ), null );
685 }
686
687 s = new SourceSectionType();
688 s.setName( CONSTRUCTORS_SECTION_NAME );
689 s.setIndentationLevel( 1 );
690 s.setHeadTemplate( CONSTRUCTORS_HEAD_TEMPLATE );
691 s.setTailTemplate( CONSTRUCTORS_TAIL_TEMPLATE );
692 s.setOptional( specifications == null || ( specifications.getSpecification().isEmpty()
693 && specifications.getReference().isEmpty() ) );
694
695 s.setSourceSections( new SourceSectionsType() );
696 sourceFileType.getSourceSections().getSourceSection().add( s );
697
698 final SourceSectionType defaultCtor = new SourceSectionType();
699 defaultCtor.setName( DEFAULT_CONSTRUCTOR_SECTION_NAME );
700 defaultCtor.setIndentationLevel( 2 );
701 defaultCtor.setHeadTemplate( DEFAULT_CONSTRUCTOR_TEMPLATE );
702 defaultCtor.setEditable( true );
703 s.getSourceSections().getSourceSection().add( defaultCtor );
704
705 s = new SourceSectionType();
706 s.setName( DEPENDENCIES_SECTION_NAME );
707 s.setIndentationLevel( 1 );
708 s.setHeadTemplate( DEPENDENCIES_TEMPLATE );
709 s.setOptional( dependencies == null || dependencies.getDependency().isEmpty() );
710 sourceFileType.getSourceSections().getSourceSection().add( s );
711
712 s = new SourceSectionType();
713 s.setName( PROPERTIES_SECTION_NAME );
714 s.setIndentationLevel( 1 );
715 s.setHeadTemplate( PROPERTIES_TEMPLATE );
716 s.setOptional( properties == null || properties.getProperty().isEmpty() );
717 sourceFileType.getSourceSections().getSourceSection().add( s );
718
719 s = new SourceSectionType();
720 s.setName( MESSAGES_SECTION_NAME );
721 s.setIndentationLevel( 1 );
722 s.setHeadTemplate( MESSAGES_TEMPLATE );
723 s.setOptional( messages == null || messages.getMessage().isEmpty() );
724 sourceFileType.getSourceSections().getSourceSection().add( s );
725
726 return sourceFilesType;
727 }
728
729
730
731
732
733
734
735
736
737
738
739 private void overwriteSourceFiles( final SourceFilesType targetSourceFiles, final SourceFilesType sourceSourceFiles,
740 final boolean preserveExisting )
741 {
742 if ( targetSourceFiles == null )
743 {
744 throw new NullPointerException( "targetSourceFiles" );
745 }
746 if ( sourceSourceFiles == null )
747 {
748 throw new NullPointerException( "sourceSourceFiles" );
749 }
750
751 try
752 {
753 for ( final SourceFileType s : sourceSourceFiles.getSourceFile() )
754 {
755 final SourceFileType targetSourceFile = targetSourceFiles.getSourceFile( s.getIdentifier() );
756
757 if ( targetSourceFile != null )
758 {
759 this.overwriteSourceFile( targetSourceFile, s, preserveExisting );
760 }
761 }
762 }
763 catch ( final NoSuchFieldException e )
764 {
765 throw new AssertionError( e );
766 }
767 }
768
769
770
771
772
773
774
775
776
777
778
779 private void overwriteSourceFile( final SourceFileType targetSourceFile, final SourceFileType sourceSourceFile,
780 final boolean preserveExisting )
781 throws NoSuchFieldException
782 {
783 if ( targetSourceFile == null )
784 {
785 throw new NullPointerException( "targetSourceFile" );
786 }
787 if ( sourceSourceFile == null )
788 {
789 throw new NullPointerException( "sourceSourceFile" );
790 }
791
792 if ( !preserveExisting )
793 {
794 targetSourceFile.setIdentifier( sourceSourceFile.getIdentifier() );
795 targetSourceFile.setLocation( sourceSourceFile.getLocation() );
796 targetSourceFile.setTemplate( sourceSourceFile.getTemplate() );
797 targetSourceFile.setHeadComment( sourceSourceFile.getHeadComment() );
798 targetSourceFile.setTailComment( sourceSourceFile.getTailComment() );
799
800 if ( isFieldSet( sourceSourceFile, "_final" ) )
801 {
802 targetSourceFile.setFinal( sourceSourceFile.isFinal() );
803 }
804 if ( isFieldSet( sourceSourceFile, "modelVersion" ) )
805 {
806 targetSourceFile.setModelVersion( sourceSourceFile.getModelVersion() );
807 }
808 if ( isFieldSet( sourceSourceFile, "override" ) )
809 {
810 targetSourceFile.setOverride( sourceSourceFile.isOverride() );
811 }
812 }
813
814 if ( sourceSourceFile.getSourceSections() != null )
815 {
816 if ( targetSourceFile.getSourceSections() == null )
817 {
818 targetSourceFile.setSourceSections( new SourceSectionsType() );
819 }
820
821 this.overwriteSourceSections( targetSourceFile.getSourceSections(), sourceSourceFile.getSourceSections(),
822 preserveExisting );
823
824 }
825 }
826
827
828
829
830
831
832
833
834
835
836
837 private void overwriteSourceSections( final SourceSectionsType targetSourceSections,
838 final SourceSectionsType sourceSourceSections,
839 final boolean preserveExisting ) throws NoSuchFieldException
840 {
841 if ( targetSourceSections == null )
842 {
843 throw new NullPointerException( "targetSourceSections" );
844 }
845 if ( sourceSourceSections == null )
846 {
847 throw new NullPointerException( "sourceSourceSections" );
848 }
849
850 for ( final SourceSectionType sourceSection : sourceSourceSections.getSourceSection() )
851 {
852 SourceSectionType targetSection = null;
853
854 for ( final SourceSectionType t : targetSourceSections.getSourceSection() )
855 {
856 if ( sourceSection.getName().equals( t.getName() ) )
857 {
858 targetSection = t;
859 break;
860 }
861 }
862
863 if ( targetSection != null )
864 {
865 if ( !preserveExisting )
866 {
867 targetSection.setName( sourceSection.getName() );
868 targetSection.setHeadTemplate( sourceSection.getHeadTemplate() );
869 targetSection.setTailTemplate( sourceSection.getTailTemplate() );
870
871 if ( isFieldSet( sourceSection, "editable" ) )
872 {
873 targetSection.setEditable( sourceSection.isEditable() );
874 }
875 if ( isFieldSet( sourceSection, "indentationLevel" ) )
876 {
877 targetSection.setIndentationLevel( sourceSection.getIndentationLevel() );
878 }
879 if ( isFieldSet( sourceSection, "modelVersion" ) )
880 {
881 targetSection.setModelVersion( sourceSection.getModelVersion() );
882 }
883 if ( isFieldSet( sourceSection, "optional" ) )
884 {
885 targetSection.setOptional( sourceSection.isOptional() );
886 }
887 }
888 }
889 else
890 {
891 targetSection = sourceSection.clone();
892 targetSourceSections.getSourceSection().add( targetSection );
893 }
894
895 if ( sourceSection.getSourceSections() != null )
896 {
897 if ( targetSection.getSourceSections() == null )
898 {
899 targetSection.setSourceSections( new SourceSectionsType() );
900 }
901
902 this.overwriteSourceSections( targetSection.getSourceSections(), sourceSection.getSourceSections(),
903 preserveExisting );
904 }
905 }
906 }
907
908 private static boolean isFieldSet( final Object object, final String fieldName ) throws NoSuchFieldException
909 {
910 final Field field = getField( object.getClass(), fieldName );
911
912 if ( field == null )
913 {
914 throw new NoSuchFieldException( fieldName );
915 }
916
917 final boolean accessible = field.isAccessible();
918
919 try
920 {
921 field.setAccessible( true );
922 return field.get( object ) != null;
923 }
924 catch ( final IllegalAccessException e )
925 {
926 throw new AssertionError( e );
927 }
928 finally
929 {
930 field.setAccessible( accessible );
931 }
932 }
933
934 private static Field getField( final Class<?> clazz, final String name )
935 {
936 if ( clazz != null )
937 {
938 try
939 {
940 return clazz.getDeclaredField( name );
941 }
942 catch ( final NoSuchFieldException e )
943 {
944 return getField( clazz.getSuperclass(), name );
945 }
946 }
947
948 return null;
949 }
950
951 private static String getMessage( final Throwable t )
952 {
953 return t != null ? t.getMessage() != null ? t.getMessage() : getMessage( t.getCause() ) : null;
954 }
955
956 private static String getMessage( final String key, final Object... args )
957 {
958 return MessageFormat.format( ResourceBundle.getBundle(
959 ToolsModelProvider.class.getName().replace( '.', '/' ), Locale.getDefault() ).getString( key ), args );
960
961 }
962
963 }