View Javadoc
1   /*
2    *   Copyright (C) Christian Schulte <cs@schulte.it>, 2005-206
3    *   All rights reserved.
4    *
5    *   Redistribution and use in source and binary forms, with or without
6    *   modification, are permitted provided that the following conditions
7    *   are met:
8    *
9    *     o Redistributions of source code must retain the above copyright
10   *       notice, this list of conditions and the following disclaimer.
11   *
12   *     o Redistributions in binary form must reproduce the above copyright
13   *       notice, this list of conditions and the following disclaimer in
14   *       the documentation and/or other materials provided with the
15   *       distribution.
16   *
17   *   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
18   *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19   *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20   *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
21   *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22   *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23   *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24   *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25   *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26   *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27   *
28   *   $JOMC: DefaultModelValidator.java 5374 2016-09-05 12:24:12Z schulte $
29   *
30   */
31  package org.jomc.model.modlet;
32  
33  import java.lang.reflect.UndeclaredThrowableException;
34  import java.text.MessageFormat;
35  import java.util.Collection;
36  import java.util.Collections;
37  import java.util.HashMap;
38  import java.util.HashSet;
39  import java.util.Iterator;
40  import java.util.LinkedList;
41  import java.util.List;
42  import java.util.Locale;
43  import java.util.Map;
44  import java.util.ResourceBundle;
45  import java.util.Set;
46  import java.util.concurrent.Callable;
47  import java.util.concurrent.CancellationException;
48  import java.util.concurrent.ExecutionException;
49  import java.util.concurrent.Future;
50  import java.util.logging.Level;
51  import javax.xml.bind.JAXBElement;
52  import javax.xml.bind.JAXBException;
53  import javax.xml.bind.util.JAXBSource;
54  import javax.xml.namespace.QName;
55  import javax.xml.transform.Source;
56  import org.jomc.model.Argument;
57  import org.jomc.model.Dependency;
58  import org.jomc.model.Implementation;
59  import org.jomc.model.ImplementationReference;
60  import org.jomc.model.Implementations;
61  import org.jomc.model.Inheritable;
62  import org.jomc.model.InheritanceModel;
63  import org.jomc.model.JavaIdentifier;
64  import org.jomc.model.Message;
65  import org.jomc.model.MessageReference;
66  import org.jomc.model.ModelObject;
67  import org.jomc.model.ModelObjectException;
68  import org.jomc.model.Module;
69  import org.jomc.model.Modules;
70  import org.jomc.model.Multiplicity;
71  import org.jomc.model.ObjectFactory;
72  import org.jomc.model.Property;
73  import org.jomc.model.PropertyReference;
74  import org.jomc.model.Specification;
75  import org.jomc.model.SpecificationReference;
76  import org.jomc.model.Specifications;
77  import org.jomc.model.Text;
78  import org.jomc.modlet.Model;
79  import org.jomc.modlet.ModelContext;
80  import org.jomc.modlet.ModelException;
81  import org.jomc.modlet.ModelValidationReport;
82  import org.jomc.modlet.ModelValidator;
83  import org.jomc.util.ParseException;
84  import org.jomc.util.TokenMgrError;
85  import org.jomc.util.VersionParser;
86  import org.w3c.dom.Element;
87  
88  /**
89   * Default object management and configuration {@code ModelValidator} implementation.
90   *
91   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
92   * @version $JOMC: DefaultModelValidator.java 5374 2016-09-05 12:24:12Z schulte $
93   * @see ModelContext#validateModel(org.jomc.modlet.Model)
94   */
95  public class DefaultModelValidator implements ModelValidator
96  {
97  
98      /**
99       * Constant for the name of the model context attribute backing property {@code enabled}.
100      *
101      * @see #validateModel(org.jomc.modlet.ModelContext, org.jomc.modlet.Model)
102      * @see ModelContext#getAttribute(java.lang.String)
103      * @since 1.7
104      */
105     public static final String ENABLED_ATTRIBUTE_NAME = "org.jomc.model.modlet.DefaultModelValidator.enabledAttribute";
106 
107     /**
108      * Constant for the name of the system property controlling property {@code defaultEnabled}.
109      *
110      * @see #isDefaultEnabled()
111      * @since 1.7
112      */
113     private static final String DEFAULT_ENABLED_PROPERTY_NAME =
114         "org.jomc.model.modlet.DefaultModelValidator.defaultEnabled";
115 
116     /**
117      * Default value of the flag indicating the validator is enabled by default.
118      *
119      * @see #isDefaultEnabled()
120      * @since 1.7
121      */
122     private static final Boolean DEFAULT_ENABLED = Boolean.TRUE;
123 
124     /**
125      * Flag indicating the validator is enabled by default.
126      *
127      * @since 1.7
128      */
129     private static volatile Boolean defaultEnabled;
130 
131     /**
132      * Flag indicating the validator is enabled.
133      *
134      * @since 1.7
135      */
136     private Boolean enabled;
137 
138     /**
139      * Constant for the name of the model context attribute backing property {@code validateJava}.
140      *
141      * @see ModelContext#getAttribute(java.lang.String)
142      * @since 1.4
143      */
144     public static final String VALIDATE_JAVA_ATTRIBUTE_NAME =
145         "org.jomc.model.modlet.DefaultModelValidator.validateJavaAttribute";
146 
147     /**
148      * Constant for the name of the system property controlling property {@code defaultValidateJava}.
149      *
150      * @see #isDefaultValidateJava()
151      * @since 1.4
152      */
153     private static final String DEFAULT_VALIDATE_JAVA_PROPERTY_NAME =
154         "org.jomc.model.modlet.DefaultModelValidator.defaultValidateJava";
155 
156     /**
157      * Default value of the flag indicating the validator is performing Java related validation by default.
158      *
159      * @see #isDefaultValidateJava()
160      * @since 1.4
161      */
162     private static final Boolean DEFAULT_VALIDATE_JAVA = Boolean.TRUE;
163 
164     /**
165      * Flag indicating the validator is performing Java related validation by default.
166      *
167      * @since 1.4
168      */
169     private static volatile Boolean defaultValidateJava;
170 
171     /**
172      * Flag indicating the validator is performing Java related validation.
173      *
174      * @since 1.4
175      */
176     private Boolean validateJava;
177 
178     /**
179      * Creates a new {@code DefaultModelValidator} instance.
180      */
181     public DefaultModelValidator()
182     {
183         super();
184     }
185 
186     /**
187      * Gets a flag indicating the validator is enabled by default.
188      * <p>
189      * The default enabled flag is controlled by system property
190      * {@code org.jomc.model.modlet.DefaultModelValidator.defaultEnabled} holding a value indicating the validator is
191      * enabled by default. If that property is not set, the {@code true} default is returned.
192      * </p>
193      *
194      * @return {@code true}, if the validator is enabled by default; {@code false}, if the validator is disabled by
195      * default.
196      *
197      * @see #setDefaultEnabled(java.lang.Boolean)
198      * @since 1.7
199      */
200     public static boolean isDefaultEnabled()
201     {
202         if ( defaultEnabled == null )
203         {
204             defaultEnabled = Boolean.valueOf( System.getProperty( DEFAULT_ENABLED_PROPERTY_NAME,
205                                                                   Boolean.toString( DEFAULT_ENABLED ) ) );
206 
207         }
208 
209         return defaultEnabled;
210     }
211 
212     /**
213      * Sets the flag indicating the validator is enabled by default.
214      *
215      * @param value The new value of the flag indicating the validator is enabled by default or {@code null}.
216      *
217      * @see #isDefaultEnabled()
218      * @since 1.7
219      */
220     public static void setDefaultEnabled( final Boolean value )
221     {
222         defaultEnabled = value;
223     }
224 
225     /**
226      * Gets a flag indicating the validator is enabled.
227      *
228      * @return {@code true}, if the validator is enabled; {@code false}, if the validator is disabled.
229      *
230      * @see #isDefaultEnabled()
231      * @see #setEnabled(java.lang.Boolean)
232      * @since 1.7
233      */
234     public final boolean isEnabled()
235     {
236         if ( this.enabled == null )
237         {
238             this.enabled = isDefaultEnabled();
239         }
240 
241         return this.enabled;
242     }
243 
244     /**
245      * Sets the flag indicating the validator is enabled.
246      *
247      * @param value The new value of the flag indicating the validator is enabled or {@code null}.
248      *
249      * @see #isEnabled()
250      * @since 1.7
251      */
252     public final void setEnabled( final Boolean value )
253     {
254         this.enabled = value;
255     }
256 
257     /**
258      * Gets a flag indicating the validator is performing Java related validation by default.
259      * <p>
260      * The default validate Java flag is controlled by system property
261      * {@code org.jomc.model.modlet.DefaultModelValidator.defaultValidateJava} holding a value indicating the validator
262      * is performing Java related validation by default. If that property is not set, the {@code true} default is
263      * returned.
264      * </p>
265      *
266      * @return {@code true}, if the validator is performing Java related validation by default; {@code false}, if the
267      * validator is not performing Java related validation by default.
268      *
269      * @see #setDefaultValidateJava(java.lang.Boolean)
270      *
271      * @since 1.4
272      */
273     public static boolean isDefaultValidateJava()
274     {
275         if ( defaultValidateJava == null )
276         {
277             defaultValidateJava = Boolean.valueOf( System.getProperty( DEFAULT_VALIDATE_JAVA_PROPERTY_NAME,
278                                                                        Boolean.toString( DEFAULT_VALIDATE_JAVA ) ) );
279 
280         }
281 
282         return defaultValidateJava;
283     }
284 
285     /**
286      * Sets the flag indicating the validator is performing Java related validation by default.
287      *
288      * @param value The new value of the flag indicating the validator is performing Java related validation by default
289      * or {@code null}.
290      *
291      * @see #isDefaultValidateJava()
292      *
293      * @since 1.4
294      */
295     public static void setDefaultValidateJava( final Boolean value )
296     {
297         defaultValidateJava = value;
298     }
299 
300     /**
301      * Gets a flag indicating the validator is performing Java related validation.
302      *
303      * @return {@code true}, if the validator is performing Java related validation; {@code false}, if the the validator
304      * is not performing Java related validation.
305      *
306      * @see #isDefaultValidateJava()
307      * @see #setValidateJava(java.lang.Boolean)
308      *
309      * @since 1.4
310      */
311     public final boolean isValidateJava()
312     {
313         if ( this.validateJava == null )
314         {
315             this.validateJava = isDefaultValidateJava();
316         }
317 
318         return this.validateJava;
319     }
320 
321     /**
322      * Sets the flag indicating the validator is performing Java related validation.
323      *
324      * @param value The new value of the flag indicating the validator is performing Java related validation or
325      * {@code null}.
326      *
327      * @see #isValidateJava()
328      *
329      * @since 1.4
330      */
331     public final void setValidateJava( final Boolean value )
332     {
333         this.validateJava = value;
334     }
335 
336     public ModelValidationReport validateModel( final ModelContext context, final Model model ) throws ModelException
337     {
338         if ( context == null )
339         {
340             throw new NullPointerException( "context" );
341         }
342         if ( model == null )
343         {
344             throw new NullPointerException( "model" );
345         }
346 
347         boolean contextEnabled = this.isEnabled();
348         if ( DEFAULT_ENABLED == contextEnabled
349                  && context.getAttribute( ENABLED_ATTRIBUTE_NAME ) instanceof Boolean )
350         {
351             contextEnabled = (Boolean) context.getAttribute( ENABLED_ATTRIBUTE_NAME );
352         }
353 
354         boolean contextValidateJava = this.isValidateJava();
355         if ( DEFAULT_VALIDATE_JAVA == contextValidateJava
356                  && context.getAttribute( VALIDATE_JAVA_ATTRIBUTE_NAME ) instanceof Boolean )
357         {
358             contextValidateJava = (Boolean) context.getAttribute( VALIDATE_JAVA_ATTRIBUTE_NAME );
359         }
360 
361         try
362         {
363             ModelValidationReport report = new ModelValidationReport();
364 
365             if ( contextEnabled )
366             {
367                 final Source source = new JAXBSource( context.createContext( model.getIdentifier() ),
368                                                       new org.jomc.modlet.ObjectFactory().createModel( model ) );
369 
370                 report = context.validateModel( model.getIdentifier(), source );
371 
372                 final Modules modules = ModelHelper.getModules( model );
373 
374                 if ( modules != null )
375                 {
376                     final ValidationContext validationContext =
377                         new ValidationContext( context, modules, report, contextValidateJava );
378 
379                     assertModulesValid( validationContext );
380                     assertSpecificationsValid( validationContext );
381                     assertImplementationsValid( validationContext );
382                 }
383             }
384             else if ( context.isLoggable( Level.FINER ) )
385             {
386                 context.log( Level.FINER, getMessage( "disabled", this.getClass().getSimpleName(),
387                                                       model.getIdentifier() ), null );
388 
389             }
390 
391             return report;
392         }
393         catch ( final JAXBException e )
394         {
395             String message = getMessage( e );
396             if ( message == null && e.getLinkedException() != null )
397             {
398                 message = getMessage( e.getLinkedException() );
399             }
400 
401             if ( context.isLoggable( Level.FINE ) )
402             {
403                 context.log( Level.FINE, message, e );
404             }
405 
406             throw new ModelException( message, e );
407         }
408     }
409 
410     private static void assertModulesValid( final ValidationContext validationContext ) throws ModelException
411     {
412         try
413         {
414             class ValidateModuleTask implements Callable<Void>
415             {
416 
417                 private final Module module;
418 
419                 ValidateModuleTask( final Module module )
420                 {
421                     super();
422                     this.module = module;
423                 }
424 
425                 public Void call()
426                 {
427                     assertModuleValid( this.module, validationContext );
428                     return null;
429                 }
430 
431             }
432 
433             final List<ValidateModuleTask> tasks = new LinkedList<ValidateModuleTask>();
434 
435             for ( int i = 0, s0 = validationContext.getModules().getModule().size(); i < s0; i++ )
436             {
437                 tasks.add( new ValidateModuleTask( validationContext.getModules().getModule().get( i ) ) );
438             }
439 
440             if ( validationContext.getModelContext().getExecutorService() != null
441                      && tasks.size() > 1 )
442             {
443                 for ( final Future<Void> task
444                           : validationContext.getModelContext().getExecutorService().invokeAll( tasks ) )
445                 {
446                     task.get();
447                 }
448             }
449             else
450             {
451                 for ( final ValidateModuleTask task : tasks )
452                 {
453                     task.call();
454                 }
455             }
456         }
457         catch ( final CancellationException e )
458         {
459             throw new ModelException( getMessage( e ), e );
460         }
461         catch ( final InterruptedException e )
462         {
463             throw new ModelException( getMessage( e ), e );
464         }
465         catch ( final ExecutionException e )
466         {
467             if ( e.getCause() instanceof RuntimeException )
468             {
469                 // The fork-join framework breaks the exception handling contract of Callable by re-throwing any
470                 // exception caught using a runtime exception.
471                 if ( e.getCause().getCause() instanceof RuntimeException )
472                 {
473                     throw (RuntimeException) e.getCause().getCause();
474                 }
475                 else if ( e.getCause().getCause() instanceof Error )
476                 {
477                     throw (Error) e.getCause().getCause();
478                 }
479                 else if ( e.getCause().getCause() instanceof Exception )
480                 {
481                     // Checked exception not declared to be thrown by the Callable's 'call' method.
482                     throw new UndeclaredThrowableException( e.getCause().getCause() );
483                 }
484                 else
485                 {
486                     throw (RuntimeException) e.getCause();
487                 }
488             }
489             else if ( e.getCause() instanceof Error )
490             {
491                 throw (Error) e.getCause();
492             }
493             else
494             {
495                 // Checked exception not declared to be thrown by the Callable's 'call' method.
496                 throw new UndeclaredThrowableException( e.getCause() );
497             }
498         }
499     }
500 
501     private static void assertModuleValid( final Module m, final ValidationContext validationContext )
502     {
503 
504         if ( m.getImplementations() != null )
505         {
506             for ( int j = 0, s1 = m.getImplementations().getReference().size(); j < s1; j++ )
507             {
508                 final ImplementationReference r = m.getImplementations().getReference().get( j );
509                 addDetail( validationContext.getReport(), "MODULE_IMPLEMENTATION_REFERENCE_DECLARATION_CONSTRAINT",
510                            Level.SEVERE, new ObjectFactory().createModule( m ),
511                            "moduleImplementationReferenceDeclarationConstraint", m.getName(), r.getIdentifier() );
512 
513             }
514         }
515 
516         if ( m.getMessages() != null )
517         {
518             for ( int j = 0, s1 = m.getMessages().getMessage().size(); j < s1; j++ )
519             {
520                 final Message msg = m.getMessages().getMessage().get( j );
521 
522                 if ( msg.isFinal() )
523                 {
524                     addDetail( validationContext.getReport(), "MODULE_FINAL_MESSAGE_DECLARATION_CONSTRAINT",
525                                Level.SEVERE, new ObjectFactory().createModule( m ), "moduleFinalMessageConstraint",
526                                m.getName(), msg.getName() );
527 
528                 }
529 
530                 if ( msg.isOverride() )
531                 {
532                     addDetail( validationContext.getReport(), "MODULE_OVERRIDE_MESSAGE_DECLARATION_CONSTRAINT",
533                                Level.SEVERE, new ObjectFactory().createModule( m ),
534                                "moduleOverrideMessageConstraint", m.getName(), msg.getName() );
535 
536                 }
537 
538                 if ( validationContext.isValidateJava() )
539                 {
540                     try
541                     {
542                         msg.getJavaConstantName();
543                     }
544                     catch ( final ModelObjectException e )
545                     {
546                         final String message = getMessage( e );
547 
548                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
549                         {
550                             validationContext.getModelContext().log( Level.FINE, message, e );
551                         }
552 
553                         addDetail( validationContext.getReport(),
554                                    "MODULE_MESSAGE_JAVA_CONSTANT_NAME_CONSTRAINT",
555                                    Level.SEVERE, new ObjectFactory().createModule( m ),
556                                    "moduleMessageJavaConstantNameConstraint", m.getName(), msg.getName(),
557                                    message != null && message.length() > 0 ? " " + message : "" );
558 
559                     }
560 
561                     try
562                     {
563                         msg.getJavaGetterMethodName();
564                     }
565                     catch ( final ModelObjectException e )
566                     {
567                         final String message = getMessage( e );
568 
569                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
570                         {
571                             validationContext.getModelContext().log( Level.FINE, message, e );
572                         }
573 
574                         addDetail( validationContext.getReport(),
575                                    "MODULE_MESSAGE_JAVA_GETTER_METHOD_NAME_CONSTRAINT",
576                                    Level.SEVERE, new ObjectFactory().createModule( m ),
577                                    "moduleMessageJavaGetterMethodNameConstraint", m.getName(), msg.getName(),
578                                    message != null && message.length() > 0 ? " " + message : "" );
579 
580                     }
581 
582                     try
583                     {
584                         msg.getJavaSetterMethodName();
585                     }
586                     catch ( final ModelObjectException e )
587                     {
588                         final String message = getMessage( e );
589 
590                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
591                         {
592                             validationContext.getModelContext().log( Level.FINE, message, e );
593                         }
594 
595                         addDetail( validationContext.getReport(),
596                                    "MODULE_MESSAGE_JAVA_SETTER_METHOD_NAME_CONSTRAINT",
597                                    Level.SEVERE, new ObjectFactory().createModule( m ),
598                                    "moduleMessageJavaSetterMethodNameConstraint", m.getName(), msg.getName(),
599                                    message != null && message.length() > 0 ? " " + message : "" );
600 
601                     }
602 
603                     try
604                     {
605                         msg.getJavaVariableName();
606                     }
607                     catch ( final ModelObjectException e )
608                     {
609                         final String message = getMessage( e );
610 
611                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
612                         {
613                             validationContext.getModelContext().log( Level.FINE, message, e );
614                         }
615 
616                         addDetail( validationContext.getReport(),
617                                    "MODULE_MESSAGE_JAVA_VARIABLE_NAME_CONSTRAINT",
618                                    Level.SEVERE, new ObjectFactory().createModule( m ),
619                                    "moduleMessageJavaVariableNameConstraint", m.getName(), msg.getName(),
620                                    message != null && message.length() > 0 ? " " + message : "" );
621 
622                     }
623                 }
624 
625                 if ( msg.getTemplate() != null )
626                 {
627                     for ( int k = 0, s2 = msg.getTemplate().getText().size(); k < s2; k++ )
628                     {
629                         final Text t = msg.getTemplate().getText().get( k );
630 
631                         try
632                         {
633                             t.getMimeType();
634                         }
635                         catch ( final ModelObjectException e )
636                         {
637                             final String message = getMessage( e );
638 
639                             if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
640                             {
641                                 validationContext.getModelContext().log( Level.FINE, message, e );
642                             }
643 
644                             addDetail( validationContext.getReport(),
645                                        "MODULE_MESSAGE_TEMPLATE_MIME_TYPE_CONSTRAINT",
646                                        Level.SEVERE, new ObjectFactory().createModule( m ),
647                                        "moduleMessageTemplateMimeTypeConstraint", m.getName(), msg.getName(),
648                                        t.getLanguage(),
649                                        message != null && message.length() > 0 ? " " + message : "" );
650 
651                         }
652 
653                         if ( validationContext.isValidateJava() )
654                         {
655                             try
656                             {
657                                 new MessageFormat( t.getValue(), new Locale( t.getLanguage() ) );
658                             }
659                             catch ( final IllegalArgumentException e )
660                             {
661                                 final String message = getMessage( e );
662 
663                                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
664                                 {
665                                     validationContext.getModelContext().log( Level.FINE, message, e );
666                                 }
667 
668                                 addDetail( validationContext.getReport(), "MODULE_MESSAGE_TEMPLATE_CONSTRAINT",
669                                            Level.SEVERE, new ObjectFactory().createModule( m ),
670                                            "moduleMessageTemplateConstraint", m.getName(), msg.getName(),
671                                            t.getValue(),
672                                            message != null && message.length() > 0 ? " " + message : "" );
673 
674                             }
675                         }
676                     }
677                 }
678 
679                 if ( msg.getArguments() != null )
680                 {
681                     final Map<JavaIdentifier, Argument> javaVariableNames =
682                         new HashMap<JavaIdentifier, Argument>( msg.getArguments().getArgument().size() );
683 
684                     for ( int k = 0, s2 = msg.getArguments().getArgument().size(); k < s2; k++ )
685                     {
686                         final Argument a = msg.getArguments().getArgument( k );
687 
688                         if ( validationContext.isValidateJava() )
689                         {
690                             try
691                             {
692                                 a.getJavaTypeName();
693                             }
694                             catch ( final ModelObjectException e )
695                             {
696                                 final String message = getMessage( e );
697 
698                                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
699                                 {
700                                     validationContext.getModelContext().log( Level.FINE, message, e );
701                                 }
702 
703                                 addDetail( validationContext.getReport(),
704                                            "MODULE_MESSAGE_ARGUMENT_JAVA_TYPE_NAME_CONSTRAINT",
705                                            Level.SEVERE, new ObjectFactory().createModule( m ),
706                                            "moduleMessageArgumentJavaTypeNameConstraint", m.getName(),
707                                            msg.getName(), a.getIndex(),
708                                            message != null && message.length() > 0 ? " " + message : "" );
709 
710                             }
711 
712                             try
713                             {
714                                 final JavaIdentifier javaIdentifier = a.getJavaVariableName();
715 
716                                 if ( javaVariableNames.containsKey( javaIdentifier ) )
717                                 {
718                                     addDetail( validationContext.getReport(),
719                                                "MODULE_MESSAGE_ARGUMENT_JAVA_VARIABLE_NAME_UNIQUENESS_CONSTRAINT",
720                                                Level.SEVERE, new ObjectFactory().createModule( m ),
721                                                "moduleMessageArgumentJavaVariableNameUniquenessConstraint",
722                                                m.getName(), msg.getName(), a.getName(),
723                                                javaIdentifier, javaVariableNames.get( javaIdentifier ).getName() );
724 
725                                 }
726                                 else
727                                 {
728                                     javaVariableNames.put( javaIdentifier, a );
729                                 }
730                             }
731                             catch ( final ModelObjectException e )
732                             {
733                                 final String message = getMessage( e );
734 
735                                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
736                                 {
737                                     validationContext.getModelContext().log( Level.FINE, message, e );
738                                 }
739 
740                                 addDetail( validationContext.getReport(),
741                                            "MODULE_MESSAGE_ARGUMENT_JAVA_VARIABLE_NAME_CONSTRAINT",
742                                            Level.SEVERE, new ObjectFactory().createModule( m ),
743                                            "moduleMessageArgumentJavaVariableNameConstraint", m.getName(),
744                                            msg.getName(), a.getIndex(),
745                                            message != null && message.length() > 0 ? " " + message : "" );
746 
747                             }
748                         }
749                     }
750                 }
751             }
752 
753             for ( int j = 0, s1 = m.getMessages().getReference().size(); j < s1; j++ )
754             {
755                 final MessageReference r = m.getMessages().getReference().get( j );
756                 addDetail( validationContext.getReport(), "MODULE_MESSAGE_REFERENCE_DECLARATION_CONSTRAINT",
757                            Level.SEVERE, new ObjectFactory().createModule( m ),
758                            "moduleMessageReferenceDeclarationConstraint", m.getName(), r.getName() );
759 
760             }
761         }
762 
763         if ( m.getProperties() != null )
764         {
765             for ( int j = 0, s1 = m.getProperties().getProperty().size(); j < s1; j++ )
766             {
767                 final Property p = m.getProperties().getProperty().get( j );
768 
769                 if ( p.isFinal() )
770                 {
771                     addDetail( validationContext.getReport(), "MODULE_FINAL_PROPERTY_DECLARATION_CONSTRAINT",
772                                Level.SEVERE, new ObjectFactory().createModule( m ), "moduleFinalPropertyConstraint",
773                                m.getName(), p.getName() );
774 
775                 }
776 
777                 if ( p.isOverride() )
778                 {
779                     addDetail( validationContext.getReport(), "MODULE_OVERRIDE_PROPERTY_DECLARATION_CONSTRAINT",
780                                Level.SEVERE, new ObjectFactory().createModule( m ),
781                                "moduleOverridePropertyConstraint", m.getName(), p.getName() );
782 
783                 }
784 
785                 if ( p.getValue() != null && p.getAny() != null )
786                 {
787                     addDetail( validationContext.getReport(), "MODULE_PROPERTY_VALUE_CONSTRAINT", Level.SEVERE,
788                                new ObjectFactory().createModule( m ), "modulePropertyValueConstraint", m.getName(),
789                                p.getName() );
790 
791                 }
792 
793                 if ( p.getAny() != null && p.getType() == null )
794                 {
795                     addDetail( validationContext.getReport(), "MODULE_PROPERTY_TYPE_CONSTRAINT", Level.SEVERE,
796                                new ObjectFactory().createModule( m ), "modulePropertyTypeConstraint", m.getName(),
797                                p.getName() );
798 
799                 }
800 
801                 if ( validationContext.isValidateJava() )
802                 {
803                     try
804                     {
805                         p.getJavaConstantName();
806                     }
807                     catch ( final ModelObjectException e )
808                     {
809                         final String message = getMessage( e );
810 
811                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
812                         {
813                             validationContext.getModelContext().log( Level.FINE, message, e );
814                         }
815 
816                         addDetail( validationContext.getReport(),
817                                    "MODULE_PROPERTY_JAVA_CONSTANT_NAME_CONSTRAINT",
818                                    Level.SEVERE, new ObjectFactory().createModule( m ),
819                                    "modulePropertyJavaConstantNameConstraint", m.getName(), p.getName(),
820                                    message != null && message.length() > 0 ? " " + message : "" );
821 
822                     }
823 
824                     try
825                     {
826                         p.getJavaGetterMethodName();
827                     }
828                     catch ( final ModelObjectException e )
829                     {
830                         final String message = getMessage( e );
831 
832                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
833                         {
834                             validationContext.getModelContext().log( Level.FINE, message, e );
835                         }
836 
837                         addDetail( validationContext.getReport(),
838                                    "MODULE_PROPERTY_JAVA_GETTER_METHOD_NAME_CONSTRAINT",
839                                    Level.SEVERE, new ObjectFactory().createModule( m ),
840                                    "modulePropertyJavaGetterMethodNameConstraint", m.getName(), p.getName(),
841                                    message != null && message.length() > 0 ? " " + message : "" );
842 
843                     }
844 
845                     try
846                     {
847                         p.getJavaSetterMethodName();
848                     }
849                     catch ( final ModelObjectException e )
850                     {
851                         final String message = getMessage( e );
852 
853                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
854                         {
855                             validationContext.getModelContext().log( Level.FINE, message, e );
856                         }
857 
858                         addDetail( validationContext.getReport(),
859                                    "MODULE_PROPERTY_JAVA_SETTER_METHOD_NAME_CONSTRAINT",
860                                    Level.SEVERE, new ObjectFactory().createModule( m ),
861                                    "modulePropertyJavaSetterMethodNameConstraint", m.getName(), p.getName(),
862                                    message != null && message.length() > 0 ? " " + message : "" );
863 
864                     }
865 
866                     try
867                     {
868                         p.getJavaTypeName();
869                     }
870                     catch ( final ModelObjectException e )
871                     {
872                         final String message = getMessage( e );
873 
874                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
875                         {
876                             validationContext.getModelContext().log( Level.FINE, message, e );
877                         }
878 
879                         addDetail( validationContext.getReport(),
880                                    "MODULE_PROPERTY_JAVA_TYPE_NAME_CONSTRAINT",
881                                    Level.SEVERE, new ObjectFactory().createModule( m ),
882                                    "modulePropertyJavaTypeNameConstraint", m.getName(), p.getName(),
883                                    message != null && message.length() > 0 ? " " + message : "" );
884 
885                     }
886 
887                     try
888                     {
889                         p.getJavaVariableName();
890                     }
891                     catch ( final ModelObjectException e )
892                     {
893                         final String message = getMessage( e );
894 
895                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
896                         {
897                             validationContext.getModelContext().log( Level.FINE, message, e );
898                         }
899 
900                         addDetail( validationContext.getReport(),
901                                    "MODULE_PROPERTY_JAVA_VARIABLE_NAME_CONSTRAINT",
902                                    Level.SEVERE, new ObjectFactory().createModule( m ),
903                                    "modulePropertyJavaVariableNameConstraint", m.getName(), p.getName(),
904                                    message != null && message.length() > 0 ? " " + message : "" );
905 
906                     }
907 
908                     try
909                     {
910                         p.getJavaValue( validationContext.getModelContext().getClassLoader() );
911                     }
912                     catch ( final ModelObjectException e )
913                     {
914                         final String message = getMessage( e );
915 
916                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
917                         {
918                             validationContext.getModelContext().log( Level.FINE, message, e );
919                         }
920 
921                         addDetail( validationContext.getReport(), "MODULE_PROPERTY_JAVA_VALUE_CONSTRAINT",
922                                    Level.SEVERE, new ObjectFactory().createModule( m ),
923                                    "modulePropertyJavaValueConstraint", m.getName(), p.getName(),
924                                    message != null && message.length() > 0 ? " " + message : "" );
925 
926                     }
927                 }
928             }
929 
930             for ( int j = 0, s1 = m.getProperties().getReference().size(); j < s1; j++ )
931             {
932                 final PropertyReference r = m.getProperties().getReference().get( j );
933                 addDetail( validationContext.getReport(), "MODULE_PROPERTY_REFERENCE_DECLARATION_CONSTRAINT",
934                            Level.SEVERE, new ObjectFactory().createModule( m ),
935                            "modulePropertyReferenceDeclarationConstraint", m.getName(), r.getName() );
936 
937             }
938         }
939 
940         if ( m.getSpecifications() != null )
941         {
942             for ( int j = 0, s1 = m.getSpecifications().getReference().size(); j < s1; j++ )
943             {
944                 final SpecificationReference r = m.getSpecifications().getReference().get( j );
945                 addDetail( validationContext.getReport(), "MODULE_SPECIFICATION_REFERENCE_DECLARATION_CONSTRAINT",
946                            Level.SEVERE, new ObjectFactory().createModule( m ),
947                            "moduleSpecificationReferenceDeclarationConstraint", m.getName(), r.getIdentifier() );
948 
949             }
950         }
951     }
952 
953     private static void assertImplementationsValid( final ValidationContext validationContext ) throws ModelException
954     {
955         final Implementations implementations = validationContext.getAllImplementations();
956 
957         if ( implementations != null )
958         {
959             final List<Callable<Void>> tasks = new LinkedList<Callable<Void>>();
960             final Map<String, Implementation> implementationClassDeclarations = new HashMap<String, Implementation>();
961             final Map<String, Implementation> implementationJavaClassDeclarations =
962                 new HashMap<String, Implementation>();
963 
964             for ( int i = 0, s0 = implementations.getImplementation().size(); i < s0; i++ )
965             {
966                 final Implementation impl = implementations.getImplementation().get( i );
967                 final InheritanceModel imodel = validationContext.getInheritanceModel();
968                 final Module moduleOfImpl = validationContext.getModuleOfImplementation( impl.getIdentifier() );
969                 final Set<InheritanceModel.Node<ImplementationReference>> cyclicImplementationReferenceNodes =
970                     imodel.getCycleNodes( impl.getIdentifier() );
971 
972                 for ( final InheritanceModel.Node<ImplementationReference> node : cyclicImplementationReferenceNodes )
973                 {
974                     addDetail( validationContext.getReport(), "IMPLEMENTATION_INHERITANCE_CYCLE_CONSTRAINT",
975                                Level.SEVERE, new ObjectFactory().createImplementation( impl ),
976                                "implementationInheritanceCycleConstraint", impl.getIdentifier(),
977                                moduleOfImpl.getName(), getNodePathString( node ) );
978 
979                 }
980 
981                 if ( validationContext.isValidateJava() )
982                 {
983                     try
984                     {
985                         impl.getJavaTypeName();
986                     }
987                     catch ( final ModelObjectException e )
988                     {
989                         final String message = getMessage( e );
990 
991                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
992                         {
993                             validationContext.getModelContext().log( Level.FINE, message, e );
994                         }
995 
996                         addDetail( validationContext.getReport(),
997                                    "IMPLEMENTATION_JAVA_TYPE_NAME_CONSTRAINT",
998                                    Level.SEVERE, new ObjectFactory().createImplementation( impl ),
999                                    "implementationJavaTypeNameConstraint", impl.getIdentifier(),
1000                                    moduleOfImpl.getName(), impl.getClazz(),
1001                                    message != null && message.length() > 0 ? " " + message : "" );
1002 
1003                     }
1004                 }
1005 
1006                 if ( impl.isClassDeclaration() )
1007                 {
1008                     if ( impl.getClazz() == null )
1009                     {
1010                         addDetail( validationContext.getReport(), "IMPLEMENTATION_CLASS_CONSTRAINT", Level.SEVERE,
1011                                    new ObjectFactory().createImplementation( impl ), "implementationClassConstraint",
1012                                    impl.getIdentifier(), moduleOfImpl.getName() );
1013 
1014                     }
1015                     else
1016                     {
1017                         final Implementation prev = implementationClassDeclarations.get( impl.getClazz() );
1018 
1019                         if ( prev != null && !prev.getIdentifier().equals( impl.getIdentifier() ) )
1020                         {
1021                             final Module moduleOfPrev =
1022                                 validationContext.getModuleOfImplementation( prev.getIdentifier() );
1023 
1024                             addDetail( validationContext.getReport(), "IMPLEMENTATION_CLASS_DECLARATION_CONSTRAINT",
1025                                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1026                                        "implementationClassDeclarationConstraint", impl.getIdentifier(),
1027                                        moduleOfImpl.getName(), impl.getClazz(), prev.getIdentifier(),
1028                                        moduleOfPrev.getName() );
1029 
1030                         }
1031                         else
1032                         {
1033                             implementationClassDeclarations.put( impl.getClazz(), impl );
1034                         }
1035 
1036                         if ( validationContext.isValidateJava() )
1037                         {
1038                             try
1039                             {
1040                                 final Implementation java =
1041                                     implementationJavaClassDeclarations.get( impl.getJavaTypeName().getClassName() );
1042 
1043                                 if ( java != null && !java.getIdentifier().equals( impl.getIdentifier() ) )
1044                                 {
1045                                     final Module moduleOfJava =
1046                                         validationContext.getModuleOfImplementation( java.getIdentifier() );
1047 
1048                                     addDetail( validationContext.getReport(),
1049                                                "IMPLEMENTATION_JAVA_CLASS_DECLARATION_CONSTRAINT",
1050                                                Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1051                                                "implementationJavaClassDeclarationConstraint", impl.getIdentifier(),
1052                                                moduleOfImpl.getName(), impl.getJavaTypeName().getClassName(),
1053                                                java.getIdentifier(), moduleOfJava.getName() );
1054 
1055                                 }
1056                                 else
1057                                 {
1058                                     implementationJavaClassDeclarations.put( impl.getJavaTypeName().getClassName(),
1059                                                                              impl );
1060 
1061                                 }
1062                             }
1063                             catch ( final ModelObjectException e )
1064                             {
1065                                 // Already validated above.
1066                             }
1067                         }
1068                     }
1069                 }
1070 
1071                 if ( impl.isAbstract() && impl.getLocation() != null )
1072                 {
1073                     addDetail( validationContext.getReport(), "IMPLEMENTATION_ABSTRACT_LOCATION_DECLARATION_CONSTRAINT",
1074                                Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1075                                "implementationAbstractLocationDeclarationConstraint", impl.getIdentifier(),
1076                                moduleOfImpl.getName(), impl.getLocation() );
1077 
1078                 }
1079 
1080                 if ( impl.getDependencies() != null )
1081                 {
1082                     for ( int j = 0, s1 = impl.getDependencies().getDependency().size(); j < s1; j++ )
1083                     {
1084                         final Dependency d = impl.getDependencies().getDependency().get( j );
1085                         tasks.add( new Callable<Void>()
1086                         {
1087 
1088                             public Void call()
1089                             {
1090                                 assertValidDependency( validationContext, impl, d );
1091                                 return null;
1092                             }
1093 
1094                         } );
1095                     }
1096                 }
1097 
1098                 if ( impl.getImplementations() != null )
1099                 {
1100                     final Set<String> effImplementationReferences =
1101                         imodel.getImplementationReferenceIdentifiers( impl.getIdentifier() );
1102 
1103                     for ( final String effImplementationReference : effImplementationReferences )
1104                     {
1105                         final Implementation ancestorImplementation =
1106                             validationContext.getImplementation( effImplementationReference );
1107 
1108                         if ( ancestorImplementation != null && ancestorImplementation.isFinal() )
1109                         {
1110                             final Module moduleOfFinal =
1111                                 validationContext.getModuleOfImplementation( ancestorImplementation.getIdentifier() );
1112 
1113                             addDetail( validationContext.getReport(),
1114                                        "IMPLEMENTATION_IMPLEMENTATION_INHERITANCE_CONSTRAINT", Level.SEVERE,
1115                                        new ObjectFactory().createImplementation( impl ),
1116                                        "implementationFinalImplementationConstraint", impl.getIdentifier(),
1117                                        moduleOfImpl.getName(), ancestorImplementation.getIdentifier(),
1118                                        moduleOfFinal.getName() );
1119 
1120                         }
1121                     }
1122 
1123                     for ( int j = 0, s1 = impl.getImplementations().getImplementation().size(); j < s1; j++ )
1124                     {
1125                         final Implementation pi = impl.getImplementations().getImplementation().get( j );
1126 
1127                         addDetail( validationContext.getReport(),
1128                                    "IMPLEMENTATION_IMPLEMENTATION_DECLARATION_CONSTRAINT", Level.SEVERE,
1129                                    new ObjectFactory().createImplementation( impl ),
1130                                    "implementationImplementationDeclarationConstraint", impl.getIdentifier(),
1131                                    moduleOfImpl.getName(), pi.getIdentifier() );
1132 
1133                     }
1134 
1135                     for ( int j = 0, s1 = impl.getImplementations().getReference().size(); j < s1; j++ )
1136                     {
1137                         final ImplementationReference r = impl.getImplementations().getReference().get( j );
1138 
1139                         tasks.add( new Callable<Void>()
1140                         {
1141 
1142                             public Void call()
1143                             {
1144                                 assertValidImplementationReference( validationContext, impl, r );
1145                                 return null;
1146                             }
1147 
1148                         } );
1149                     }
1150                 }
1151 
1152                 if ( impl.getMessages() != null )
1153                 {
1154                     for ( int j = 0, s1 = impl.getMessages().getMessage().size(); j < s1; j++ )
1155                     {
1156                         final Message m = impl.getMessages().getMessage().get( j );
1157                         tasks.add( new Callable<Void>()
1158                         {
1159 
1160                             public Void call()
1161                             {
1162                                 assertValidMessage( validationContext, impl, m );
1163                                 return null;
1164                             }
1165 
1166                         } );
1167 
1168                     }
1169 
1170                     for ( int j = 0, s1 = impl.getMessages().getReference().size(); j < s1; j++ )
1171                     {
1172                         final MessageReference r = impl.getMessages().getReference().get( j );
1173 
1174                         tasks.add( new Callable<Void>()
1175                         {
1176 
1177                             public Void call()
1178                             {
1179                                 assertValidMessageReference( validationContext, impl, r );
1180                                 return null;
1181                             }
1182 
1183                         } );
1184                     }
1185                 }
1186 
1187                 if ( impl.getProperties() != null )
1188                 {
1189                     for ( int j = 0, s1 = impl.getProperties().getProperty().size(); j < s1; j++ )
1190                     {
1191                         final Property p = impl.getProperties().getProperty().get( j );
1192 
1193                         tasks.add( new Callable<Void>()
1194                         {
1195 
1196                             public Void call()
1197                             {
1198                                 assertValidProperty( validationContext, impl, p );
1199                                 return null;
1200                             }
1201 
1202                         } );
1203 
1204                     }
1205 
1206                     for ( int j = 0, s1 = impl.getProperties().getReference().size(); j < s1; j++ )
1207                     {
1208                         final PropertyReference r = impl.getProperties().getReference().get( j );
1209 
1210                         tasks.add( new Callable<Void>()
1211                         {
1212 
1213                             public Void call()
1214                             {
1215                                 assertValidPropertyReference( validationContext, impl, r );
1216                                 return null;
1217                             }
1218 
1219                         } );
1220 
1221                     }
1222                 }
1223 
1224                 if ( impl.getSpecifications() != null )
1225                 {
1226                     for ( int j = 0, s1 = impl.getSpecifications().getSpecification().size(); j < s1; j++ )
1227                     {
1228                         final Specification s = impl.getSpecifications().getSpecification().get( j );
1229 
1230                         addDetail( validationContext.getReport(), "IMPLEMENTATION_SPECIFICATION_DECLARATION_CONSTRAINT",
1231                                    Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1232                                    "implementationSpecificationDeclarationConstraint", impl.getIdentifier(),
1233                                    moduleOfImpl.getName(), s.getIdentifier() );
1234 
1235                     }
1236 
1237                     for ( int j = 0, s1 = impl.getSpecifications().getReference().size(); j < s1; j++ )
1238                     {
1239                         final SpecificationReference r = impl.getSpecifications().getReference().get( j );
1240 
1241                         tasks.add( new Callable<Void>()
1242                         {
1243 
1244                             public Void call()
1245                             {
1246                                 assertValidSpecificationReference( validationContext, impl, r );
1247                                 return null;
1248                             }
1249 
1250                         } );
1251 
1252                     }
1253                 }
1254 
1255                 if ( !impl.getAny().isEmpty() )
1256                 {
1257                     for ( int j = 0, s1 = impl.getAny().size(); j < s1; j++ )
1258                     {
1259                         final Object any = impl.getAny().get( j );
1260 
1261                         tasks.add( new Callable<Void>()
1262                         {
1263 
1264                             public Void call()
1265                             {
1266                                 assertValidAnyObject( validationContext, impl, any );
1267                                 return null;
1268                             }
1269 
1270                         } );
1271                     }
1272                 }
1273 
1274                 tasks.add( new Callable<Void>()
1275                 {
1276 
1277                     public Void call()
1278                     {
1279                         assertUniqueDependencies( validationContext, impl );
1280                         return null;
1281                     }
1282 
1283                 } );
1284 
1285                 tasks.add( new Callable<Void>()
1286                 {
1287 
1288                     public Void call()
1289                     {
1290                         assertUniqueMessages( validationContext, impl );
1291                         return null;
1292                     }
1293 
1294                 } );
1295 
1296                 tasks.add( new Callable<Void>()
1297                 {
1298 
1299                     public Void call()
1300                     {
1301                         assertUniqueProperties( validationContext, impl );
1302                         return null;
1303                     }
1304 
1305                 } );
1306 
1307                 final Set<String> specificationReferenceIdentifiers =
1308                     imodel.getSpecificationReferenceIdentifiers( impl.getIdentifier() );
1309 
1310                 for ( final String specificationRefereneIdentifier : specificationReferenceIdentifiers )
1311                 {
1312                     final Set<InheritanceModel.Node<SpecificationReference>> specificationReferenceNodes =
1313                         imodel.getSpecificationReferenceNodes( impl.getIdentifier(), specificationRefereneIdentifier );
1314 
1315                     if ( specificationReferenceNodes.size() > 1 )
1316                     {
1317                         addDetail( validationContext.getReport(),
1318                                    "IMPLEMENTATION_SPECIFICATION_MULTIPLE_INHERITANCE_CONSTRAINT",
1319                                    Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1320                                    "implementationMultipleInheritanceSpecificationConstraint",
1321                                    impl.getIdentifier(), moduleOfImpl.getName(), specificationRefereneIdentifier,
1322                                    getNodeListPathString( specificationReferenceNodes ) );
1323 
1324                     }
1325                 }
1326 
1327                 final Set<QName> xmlElementNames = imodel.getXmlElementNames( impl.getIdentifier() );
1328 
1329                 for ( final QName xmlElementName : xmlElementNames )
1330                 {
1331                     final Set<InheritanceModel.Node<Element>> xmlElementNodes =
1332                         imodel.getXmlElementNodes( impl.getIdentifier(), xmlElementName );
1333 
1334                     if ( xmlElementNodes.size() > 1 )
1335                     {
1336                         addDetail( validationContext.getReport(),
1337                                    "IMPLEMENTATION_XML_ELEMENT_MULTIPLE_INHERITANCE_CONSTRAINT",
1338                                    Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1339                                    "implementationMultipleInheritanceXmlElementConstraint",
1340                                    impl.getIdentifier(), moduleOfImpl.getName(), xmlElementName.toString(),
1341                                    getNodeListPathString( xmlElementNodes ) );
1342 
1343                     }
1344                 }
1345 
1346                 final Set<QName> jaxbElementNames = imodel.getJaxbElementNames( impl.getIdentifier() );
1347 
1348                 for ( final QName jaxbElementName : jaxbElementNames )
1349                 {
1350                     final Set<InheritanceModel.Node<JAXBElement<?>>> jaxbElementNodes =
1351                         imodel.getJaxbElementNodes( impl.getIdentifier(), jaxbElementName );
1352 
1353                     if ( jaxbElementNodes.size() > 1 )
1354                     {
1355                         addDetail( validationContext.getReport(),
1356                                    "IMPLEMENTATION_JAXB_ELEMENT_MULTIPLE_INHERITANCE_CONSTRAINT",
1357                                    Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1358                                    "implementationMultipleInheritanceJaxbElementConstraint",
1359                                    impl.getIdentifier(), moduleOfImpl.getName(), jaxbElementName.toString(),
1360                                    getNodeListPathString( jaxbElementNodes ) );
1361 
1362                     }
1363                 }
1364 
1365                 final Set<String> implementationReferenceIdentifiers =
1366                     imodel.getImplementationReferenceIdentifiers( impl.getIdentifier() );
1367 
1368                 for ( final String implementationReferenceIdentifier : implementationReferenceIdentifiers )
1369                 {
1370                     final Set<InheritanceModel.Node<ImplementationReference>> implementationReferenceNodes =
1371                         imodel.getImplementationReferenceNodes( impl.getIdentifier(),
1372                                                                 implementationReferenceIdentifier );
1373 
1374                     for ( final InheritanceModel.Node<ImplementationReference> node : implementationReferenceNodes )
1375                     {
1376                         final ImplementationReference r = node.getModelObject();
1377 
1378                         final Implementation referenced =
1379                             validationContext.getImplementation( r.getIdentifier() );
1380 
1381                         final Module moduleOfReferenced =
1382                             validationContext.getModuleOfImplementation( referenced.getIdentifier() );
1383 
1384                         if ( r.getVersion() != null && referenced != null )
1385                         {
1386                             if ( referenced.getVersion() == null )
1387                             {
1388                                 addDetail( validationContext.getReport(),
1389                                            "IMPLEMENTATION_IMPLEMENTATION_VERSIONING_CONSTRAINT", Level.SEVERE,
1390                                            new ObjectFactory().createImplementation( impl ),
1391                                            "implementationImplementationVersioningConstraint",
1392                                            impl.getIdentifier(), moduleOfImpl.getName(), r.getIdentifier(),
1393                                            moduleOfReferenced.getName() );
1394 
1395                             }
1396                             else
1397                             {
1398                                 try
1399                                 {
1400                                     if ( VersionParser.compare( r.getVersion(), referenced.getVersion() ) > 0 )
1401                                     {
1402                                         addDetail( validationContext.getReport(),
1403                                                    "IMPLEMENTATION_INHERITANCE_COMPATIBILITY_CONSTRAINT",
1404                                                    Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1405                                                    "implementationInheritanceCompatibilityConstraint",
1406                                                    impl.getIdentifier(), moduleOfImpl.getName(),
1407                                                    referenced.getIdentifier(), moduleOfReferenced.getName(),
1408                                                    r.getVersion(), referenced.getVersion() );
1409 
1410                                     }
1411                                 }
1412                                 catch ( final ParseException ex )
1413                                 {
1414                                     final String message = getMessage( ex );
1415 
1416                                     if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
1417                                     {
1418                                         validationContext.getModelContext().log( Level.FINE, message, ex );
1419                                     }
1420 
1421                                     addDetail(
1422                                         validationContext.getReport(),
1423                                         "IMPLEMENTATION_INHERITANCE_COMPATIBILITY_VERSIONING_PARSE_EXCEPTION",
1424                                         Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1425                                         "implementationInheritanceCompatibilityParseException",
1426                                         impl.getIdentifier(), moduleOfImpl.getName(), r.getIdentifier(),
1427                                         moduleOfReferenced.getName(), r.getVersion(),
1428                                         message != null && message.length() > 0 ? " " + message : "" );
1429 
1430                                 }
1431                                 catch ( final TokenMgrError ex )
1432                                 {
1433                                     final String message = getMessage( ex );
1434 
1435                                     if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
1436                                     {
1437                                         validationContext.getModelContext().log( Level.FINE, message, ex );
1438                                     }
1439 
1440                                     addDetail(
1441                                         validationContext.getReport(),
1442                                         "IMPLEMENTATION_INHERITANCE_COMPATIBILITY_VERSIONING_TOKEN_MANAGER_ERROR",
1443                                         Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1444                                         "implementationInheritanceCompatiblityVersioningTokenManagerError",
1445                                         impl.getIdentifier(), moduleOfImpl.getName(), r.getIdentifier(),
1446                                         moduleOfReferenced.getName(), r.getVersion(),
1447                                         message != null && message.length() > 0 ? " " + message : "" );
1448 
1449                                 }
1450                             }
1451                         }
1452                     }
1453                 }
1454 
1455                 tasks.add( new Callable<Void>()
1456                 {
1457 
1458                     public Void call()
1459                     {
1460                         assertImplementationSpecificationCompatibility( validationContext, impl );
1461                         return null;
1462                     }
1463 
1464                 } );
1465 
1466             }
1467 
1468             if ( validationContext.getModelContext().getExecutorService() != null && tasks.size() > 1 )
1469             {
1470                 try
1471                 {
1472                     for ( final Future<Void> task
1473                               : validationContext.getModelContext().getExecutorService().invokeAll( tasks ) )
1474                     {
1475                         try
1476                         {
1477                             task.get();
1478                         }
1479                         catch ( final ExecutionException e )
1480                         {
1481                             if ( e.getCause() instanceof RuntimeException )
1482                             {
1483                                 throw (RuntimeException) e.getCause();
1484                             }
1485                             else if ( e.getCause() instanceof Error )
1486                             {
1487                                 throw (Error) e.getCause();
1488                             }
1489                             else
1490                             {
1491                                 throw new UndeclaredThrowableException( e.getCause() );
1492                             }
1493                         }
1494                     }
1495                 }
1496                 catch ( final InterruptedException e )
1497                 {
1498                     throw new ModelException( getMessage( e ), e );
1499                 }
1500             }
1501             else
1502             {
1503                 for ( final Callable<Void> task : tasks )
1504                 {
1505                     try
1506                     {
1507                         task.call();
1508                     }
1509                     catch ( final Exception e )
1510                     {
1511                         // None of the callables has declared to throw an exception.
1512                         throw new UndeclaredThrowableException( e );
1513                     }
1514                 }
1515             }
1516         }
1517     }
1518 
1519     private static void assertValidDependency( final ValidationContext validationContext,
1520                                                final Implementation impl,
1521                                                final Dependency d )
1522     {
1523         final Set<InheritanceModel.Node<Dependency>> effDependencies =
1524             validationContext.getInheritanceModel().getDependencyNodes( impl.getIdentifier(), d.getName() );
1525 
1526         for ( final InheritanceModel.Node<Dependency> effDependency : effDependencies )
1527         {
1528             final Set<InheritanceModel.Node<Dependency>> overriddenDependencies =
1529                 modifiableSet( effDependency.getOverriddenNodes() );
1530 
1531             if ( d.isOverride() && effDependency.getOverriddenNodes().isEmpty() )
1532             {
1533                 addDetail( validationContext.getReport(),
1534                            "IMPLEMENTATION_DEPENDENCY_OVERRIDE_CONSTRAINT",
1535                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1536                            "implementationDependencyOverrideConstraint", impl.getIdentifier(),
1537                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), d.getName() );
1538 
1539             }
1540 
1541             if ( !( d.isOverride() || overriddenDependencies.isEmpty() ) )
1542             {
1543                 for ( final InheritanceModel.Node<Dependency> overriddenDependency
1544                           : overriddenDependencies )
1545                 {
1546                     Implementation overriddenImplementation = overriddenDependency.getImplementation();
1547                     if ( overriddenDependency.getClassDeclaration() != null )
1548                     {
1549                         overriddenImplementation = overriddenDependency.getClassDeclaration();
1550                     }
1551 
1552                     final Module moduleOfDependency =
1553                         validationContext.getModuleOfImplementation(
1554                             overriddenImplementation.getIdentifier() );
1555 
1556                     addDetail( validationContext.getReport(),
1557                                "IMPLEMENTATION_DEPENDENCY_OVERRIDE_WARNING",
1558                                Level.WARNING, new ObjectFactory().createImplementation( impl ),
1559                                "implementationDependencyOverrideWarning", impl.getIdentifier(),
1560                                validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
1561                                d.getName(), overriddenImplementation.getIdentifier(), moduleOfDependency.getName(),
1562                                getNodePathString( overriddenDependency ) );
1563 
1564                 }
1565             }
1566 
1567             retainFinalNodes( overriddenDependencies );
1568 
1569             for ( final InheritanceModel.Node<Dependency> overriddenDependency : overriddenDependencies )
1570             {
1571                 Implementation overriddenImplementation = overriddenDependency.getImplementation();
1572                 if ( overriddenDependency.getClassDeclaration() != null )
1573                 {
1574                     overriddenImplementation = overriddenDependency.getClassDeclaration();
1575                 }
1576 
1577                 final Module moduleOfDependency =
1578                     validationContext.getModuleOfImplementation(
1579                         overriddenImplementation.getIdentifier() );
1580 
1581                 addDetail( validationContext.getReport(),
1582                            "IMPLEMENTATION_DEPENDENCY_INHERITANCE_CONSTRAINT", Level.SEVERE,
1583                            new ObjectFactory().createImplementation( impl ),
1584                            "implementationDependencyFinalConstraint", impl.getIdentifier(),
1585                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), d.getName(),
1586                            overriddenImplementation.getIdentifier(),
1587                            moduleOfDependency.getName(),
1588                            getNodePathString( overriddenDependency ) );
1589 
1590             }
1591         }
1592 
1593         if ( validationContext.isValidateJava() )
1594         {
1595             try
1596             {
1597                 d.getJavaConstantName();
1598             }
1599             catch ( final ModelObjectException e )
1600             {
1601                 final String message = getMessage( e );
1602 
1603                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
1604                 {
1605                     validationContext.getModelContext().log( Level.FINE, message, e );
1606                 }
1607 
1608                 addDetail( validationContext.getReport(),
1609                            "IMPLEMENTATION_DEPENDENCY_JAVA_CONSTANT_NAME_CONSTRAINT",
1610                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1611                            "implementationDependencyJavaConstantNameConstraint", impl.getIdentifier(),
1612                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), d.getName(),
1613                            message != null && message.length() > 0 ? " " + message : "" );
1614 
1615             }
1616 
1617             try
1618             {
1619                 d.getJavaGetterMethodName();
1620             }
1621             catch ( final ModelObjectException e )
1622             {
1623                 final String message = getMessage( e );
1624 
1625                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
1626                 {
1627                     validationContext.getModelContext().log( Level.FINE, message, e );
1628                 }
1629 
1630                 addDetail( validationContext.getReport(),
1631                            "IMPLEMENTATION_DEPENDENCY_JAVA_GETTER_METHOD_NAME_CONSTRAINT",
1632                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1633                            "implementationDependencyJavaGetterMethodNameConstraint",
1634                            impl.getIdentifier(),
1635                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), d.getName(),
1636                            message != null && message.length() > 0 ? " " + message : "" );
1637 
1638             }
1639 
1640             try
1641             {
1642                 d.getJavaSetterMethodName();
1643             }
1644             catch ( final ModelObjectException e )
1645             {
1646                 final String message = getMessage( e );
1647 
1648                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
1649                 {
1650                     validationContext.getModelContext().log( Level.FINE, message, e );
1651                 }
1652 
1653                 addDetail( validationContext.getReport(),
1654                            "IMPLEMENTATION_DEPENDENCY_JAVA_SETTER_METHOD_NAME_CONSTRAINT",
1655                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1656                            "implementationDependencyJavaSetterMethodNameConstraint",
1657                            impl.getIdentifier(),
1658                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), d.getName(),
1659                            message != null && message.length() > 0 ? " " + message : "" );
1660 
1661             }
1662 
1663             try
1664             {
1665                 d.getJavaVariableName();
1666             }
1667             catch ( final ModelObjectException e )
1668             {
1669                 final String message = getMessage( e );
1670 
1671                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
1672                 {
1673                     validationContext.getModelContext().log( Level.FINE, message, e );
1674                 }
1675 
1676                 addDetail( validationContext.getReport(),
1677                            "IMPLEMENTATION_DEPENDENCY_JAVA_VARIABLE_NAME_CONSTRAINT",
1678                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1679                            "implementationDependencyJavaVariableNameConstraint",
1680                            impl.getIdentifier(),
1681                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), d.getName(),
1682                            message != null && message.length() > 0 ? " " + message : "" );
1683 
1684             }
1685         }
1686 
1687         assertDependencyValid( validationContext, impl, d );
1688     }
1689 
1690     private static void assertValidImplementationReference( final ValidationContext validationContext,
1691                                                             final Implementation impl,
1692                                                             final ImplementationReference r )
1693     {
1694         final Set<InheritanceModel.Node<ImplementationReference>> effReferences =
1695             validationContext.getInheritanceModel().getImplementationReferenceNodes( impl.getIdentifier(),
1696                                                                                      r.getIdentifier() );
1697 
1698         for ( final InheritanceModel.Node<ImplementationReference> effReference : effReferences )
1699         {
1700             final Set<InheritanceModel.Node<ImplementationReference>> overriddenReferences =
1701                 modifiableSet( effReference.getOverriddenNodes() );
1702 
1703             if ( r.isOverride() && overriddenReferences.isEmpty() )
1704             {
1705                 addDetail( validationContext.getReport(),
1706                            "IMPLEMENTATION_IMPLEMENTATION_OVERRIDE_CONSTRAINT", Level.SEVERE,
1707                            new ObjectFactory().createImplementation( impl ),
1708                            "implementationImplementationOverrideConstraint", impl.getIdentifier(),
1709                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
1710                            r.getIdentifier() );
1711 
1712             }
1713 
1714             if ( !( r.isOverride() || overriddenReferences.isEmpty() ) )
1715             {
1716                 for ( final InheritanceModel.Node<ImplementationReference> overriddenReference
1717                           : overriddenReferences )
1718                 {
1719                     Implementation overriddenImplementation = overriddenReference.getImplementation();
1720                     if ( overriddenReference.getClassDeclaration() != null )
1721                     {
1722                         overriddenImplementation = overriddenReference.getClassDeclaration();
1723                     }
1724 
1725                     final Module moduleOfReference =
1726                         validationContext.getModuleOfImplementation( overriddenImplementation.getIdentifier() );
1727 
1728                     addDetail( validationContext.getReport(),
1729                                "IMPLEMENTATION_IMPLEMENTATION_REFERENCE_OVERRIDE_WARNING",
1730                                Level.WARNING, new ObjectFactory().createImplementation( impl ),
1731                                "implementationImplementationOverrideWarning", impl.getIdentifier(),
1732                                validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
1733                                r.getIdentifier(), overriddenImplementation.getIdentifier(), moduleOfReference.getName(),
1734                                getNodePathString( overriddenReference ) );
1735 
1736                 }
1737             }
1738 
1739             retainFinalNodes( overriddenReferences );
1740 
1741             for ( final InheritanceModel.Node<ImplementationReference> overriddenReference
1742                       : overriddenReferences )
1743             {
1744                 Implementation overriddenImplementation = overriddenReference.getImplementation();
1745                 if ( overriddenReference.getClassDeclaration() != null )
1746                 {
1747                     overriddenImplementation = overriddenReference.getClassDeclaration();
1748                 }
1749 
1750                 final Module moduleOfReference =
1751                     validationContext.getModuleOfImplementation( overriddenImplementation.getIdentifier() );
1752 
1753                 addDetail( validationContext.getReport(),
1754                            "IMPLEMENTATION_IMPLEMENTATION_REFERENCE_INHERITANCE_CONSTRAINT",
1755                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1756                            "implementationFinalImplementatioReferenceConstraint", impl.getIdentifier(),
1757                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
1758                            r.getIdentifier(), overriddenImplementation.getIdentifier(), moduleOfReference.getName(),
1759                            getNodePathString( overriddenReference ) );
1760 
1761             }
1762         }
1763     }
1764 
1765     private static void assertValidMessage( final ValidationContext validationContext,
1766                                             final Implementation impl,
1767                                             final Message m )
1768     {
1769         if ( impl.getMessages().getReference( m.getName() ) != null )
1770         {
1771             addDetail( validationContext.getReport(), "IMPLEMENTATION_MESSAGES_UNIQUENESS_CONSTRAINT",
1772                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1773                        "implementationMessagesUniquenessConstraint", impl.getIdentifier(),
1774                        validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), m.getName() );
1775 
1776         }
1777 
1778         if ( validationContext.isValidateJava() )
1779         {
1780             try
1781             {
1782                 m.getJavaConstantName();
1783             }
1784             catch ( final ModelObjectException e )
1785             {
1786                 final String message = getMessage( e );
1787 
1788                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
1789                 {
1790                     validationContext.getModelContext().log( Level.FINE, message, e );
1791                 }
1792 
1793                 addDetail( validationContext.getReport(),
1794                            "IMPLEMENTATION_MESSAGE_JAVA_CONSTANT_NAME_CONSTRAINT", Level.SEVERE,
1795                            new ObjectFactory().createImplementation( impl ),
1796                            "implementationMessageJavaConstantNameConstraint", impl.getIdentifier(),
1797                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), m.getName(),
1798                            message != null && message.length() > 0 ? " " + message : "" );
1799 
1800             }
1801 
1802             try
1803             {
1804                 m.getJavaGetterMethodName();
1805             }
1806             catch ( final ModelObjectException e )
1807             {
1808                 final String message = getMessage( e );
1809 
1810                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
1811                 {
1812                     validationContext.getModelContext().log( Level.FINE, message, e );
1813                 }
1814 
1815                 addDetail( validationContext.getReport(),
1816                            "IMPLEMENTATION_MESSAGE_JAVA_GETTER_METHOD_NAME_CONSTRAINT", Level.SEVERE,
1817                            new ObjectFactory().createImplementation( impl ),
1818                            "implementationMessageJavaGetterMethodNameConstraint", impl.getIdentifier(),
1819                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), m.getName(),
1820                            message != null && message.length() > 0 ? " " + message : "" );
1821 
1822             }
1823 
1824             try
1825             {
1826                 m.getJavaSetterMethodName();
1827             }
1828             catch ( final ModelObjectException e )
1829             {
1830                 final String message = getMessage( e );
1831 
1832                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
1833                 {
1834                     validationContext.getModelContext().log( Level.FINE, message, e );
1835                 }
1836 
1837                 addDetail( validationContext.getReport(),
1838                            "IMPLEMENTATION_MESSAGE_JAVA_SETTER_METHOD_NAME_CONSTRAINT", Level.SEVERE,
1839                            new ObjectFactory().createImplementation( impl ),
1840                            "implementationMessageJavaSetterMethodNameConstraint", impl.getIdentifier(),
1841                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), m.getName(),
1842                            message != null && message.length() > 0 ? " " + message : "" );
1843 
1844             }
1845 
1846             try
1847             {
1848                 m.getJavaVariableName();
1849             }
1850             catch ( final ModelObjectException e )
1851             {
1852                 final String message = getMessage( e );
1853 
1854                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
1855                 {
1856                     validationContext.getModelContext().log( Level.FINE, message, e );
1857                 }
1858 
1859                 addDetail( validationContext.getReport(),
1860                            "IMPLEMENTATION_MESSAGE_JAVA_VARIABLE_NAME_CONSTRAINT", Level.SEVERE,
1861                            new ObjectFactory().createImplementation( impl ),
1862                            "implementationMessageJavaVariableNameConstraint", impl.getIdentifier(),
1863                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), m.getName(),
1864                            message != null && message.length() > 0 ? " " + message : "" );
1865 
1866             }
1867         }
1868 
1869         if ( m.getTemplate() != null )
1870         {
1871             for ( int k = 0, s2 = m.getTemplate().getText().size(); k < s2; k++ )
1872             {
1873                 final Text t = m.getTemplate().getText().get( k );
1874 
1875                 try
1876                 {
1877                     t.getMimeType();
1878                 }
1879                 catch ( final ModelObjectException e )
1880                 {
1881                     final String message = getMessage( e );
1882 
1883                     if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
1884                     {
1885                         validationContext.getModelContext().log( Level.FINE, message, e );
1886                     }
1887 
1888                     addDetail( validationContext.getReport(),
1889                                "IMPLEMENTATION_MESSAGE_TEMPLATE_MIME_TYPE_CONSTRAINT", Level.SEVERE,
1890                                new ObjectFactory().createImplementation( impl ),
1891                                "implementationMessageTemplateMimeTypeConstraint", impl.getIdentifier(),
1892                                validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
1893                                m.getName(), t.getLanguage(),
1894                                message != null && message.length() > 0 ? " " + message : "" );
1895 
1896                 }
1897 
1898                 if ( validationContext.isValidateJava() )
1899                 {
1900                     try
1901                     {
1902                         new MessageFormat( t.getValue(), new Locale( t.getLanguage() ) );
1903                     }
1904                     catch ( final IllegalArgumentException e )
1905                     {
1906                         final String message = getMessage( e );
1907 
1908                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
1909                         {
1910                             validationContext.getModelContext().log( Level.FINE, message, e );
1911                         }
1912 
1913                         addDetail( validationContext.getReport(),
1914                                    "IMPLEMENTATION_MESSAGE_TEMPLATE_CONSTRAINT", Level.SEVERE,
1915                                    new ObjectFactory().createImplementation( impl ),
1916                                    "implementationMessageTemplateConstraint", impl.getIdentifier(),
1917                                    validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
1918                                    m.getName(), t.getLanguage(),
1919                                    message != null && message.length() > 0 ? " " + message : "" );
1920 
1921                     }
1922                 }
1923             }
1924         }
1925 
1926         final Set<InheritanceModel.Node<Message>> effMessages =
1927             validationContext.getInheritanceModel().getMessageNodes( impl.getIdentifier(), m.getName() );
1928 
1929         for ( final InheritanceModel.Node<Message> effMessage : effMessages )
1930         {
1931             final Set<InheritanceModel.Node<Message>> overriddenMessages =
1932                 modifiableSet( effMessage.getOverriddenNodes() );
1933 
1934             if ( m.isOverride() && overriddenMessages.isEmpty() )
1935             {
1936                 addDetail( validationContext.getReport(), "IMPLEMENTATION_MESSAGE_OVERRIDE_CONSTRAINT",
1937                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1938                            "implementationMessageOverrideConstraint", impl.getIdentifier(),
1939                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), m.getName() );
1940 
1941             }
1942 
1943             if ( !( m.isOverride() || overriddenMessages.isEmpty() ) )
1944             {
1945                 for ( final InheritanceModel.Node<Message> overriddenMessage : overriddenMessages )
1946                 {
1947                     Implementation overriddenImplementation = overriddenMessage.getImplementation();
1948                     if ( overriddenMessage.getClassDeclaration() != null )
1949                     {
1950                         overriddenImplementation = overriddenMessage.getClassDeclaration();
1951                     }
1952 
1953                     final Module moduleOfMessage =
1954                         validationContext.getModuleOfImplementation( overriddenImplementation.getIdentifier() );
1955 
1956                     addDetail( validationContext.getReport(), "IMPLEMENTATION_MESSAGE_OVERRIDE_WARNING",
1957                                Level.WARNING, new ObjectFactory().createImplementation( impl ),
1958                                "implementationMessageOverrideWarning", impl.getIdentifier(),
1959                                validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
1960                                m.getName(), overriddenImplementation.getIdentifier(), moduleOfMessage.getName(),
1961                                getNodePathString( overriddenMessage ) );
1962 
1963                 }
1964             }
1965 
1966             retainFinalNodes( overriddenMessages );
1967 
1968             for ( final InheritanceModel.Node<Message> overriddenMessage : overriddenMessages )
1969             {
1970                 Implementation overriddenImplementation = overriddenMessage.getImplementation();
1971                 if ( overriddenMessage.getClassDeclaration() != null )
1972                 {
1973                     overriddenImplementation = overriddenMessage.getClassDeclaration();
1974                 }
1975 
1976                 final Module moduleOfMessage = validationContext.getModuleOfImplementation(
1977                     overriddenImplementation.getIdentifier() );
1978 
1979                 addDetail( validationContext.getReport(),
1980                            "IMPLEMENTATION_MESSAGE_INHERITANCE_CONSTRAINT",
1981                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1982                            "implementationMessageFinalConstraint", impl.getIdentifier(),
1983                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), m.getName(),
1984                            overriddenImplementation.getIdentifier(),
1985                            moduleOfMessage.getName(), getNodePathString( overriddenMessage ) );
1986 
1987             }
1988         }
1989 
1990         if ( m.getArguments() != null )
1991         {
1992             final Map<JavaIdentifier, Argument> javaVariableNames =
1993                 new HashMap<JavaIdentifier, Argument>( m.getArguments().getArgument().size() );
1994 
1995             for ( int k = 0, s2 = m.getArguments().getArgument().size(); k < s2; k++ )
1996             {
1997                 final Argument a = m.getArguments().getArgument().get( k );
1998 
1999                 if ( validationContext.isValidateJava() )
2000                 {
2001                     try
2002                     {
2003                         a.getJavaTypeName();
2004                     }
2005                     catch ( final ModelObjectException e )
2006                     {
2007                         final String message = getMessage( e );
2008 
2009                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
2010                         {
2011                             validationContext.getModelContext().log( Level.FINE, message, e );
2012                         }
2013 
2014                         addDetail( validationContext.getReport(),
2015                                    "IMPLEMENTATION_MESSAGE_ARGUMENT_JAVA_TYPE_NAME_CONSTRAINT",
2016                                    Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2017                                    "implementationMessageArgumentJavaTypeNameConstraint",
2018                                    impl.getIdentifier(),
2019                                    validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2020                                    m.getName(), a.getName(),
2021                                    message != null && message.length() > 0 ? " " + message : "" );
2022 
2023                     }
2024 
2025                     try
2026                     {
2027                         final JavaIdentifier javaIdentifier = a.getJavaVariableName();
2028 
2029                         if ( javaVariableNames.containsKey( javaIdentifier ) )
2030                         {
2031                             addDetail( validationContext.getReport(),
2032                                        "IMPLEMENTATION_MESSAGE_ARGUMENT_JAVA_VARIABLE_NAME_UNIQUENESS_CONSTRAINT",
2033                                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2034                                        "implementationMessageArgumentJavaVariableNameUniquenessConstraint",
2035                                        impl.getIdentifier(),
2036                                        validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2037                                        m.getName(), a.getName(), javaIdentifier,
2038                                        javaVariableNames.get( javaIdentifier ).getName() );
2039 
2040                         }
2041                         else
2042                         {
2043                             javaVariableNames.put( javaIdentifier, a );
2044                         }
2045                     }
2046                     catch ( final ModelObjectException e )
2047                     {
2048                         final String message = getMessage( e );
2049 
2050                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
2051                         {
2052                             validationContext.getModelContext().log( Level.FINE, message, e );
2053                         }
2054 
2055                         addDetail( validationContext.getReport(),
2056                                    "IMPLEMENTATION_MESSAGE_ARGUMENT_JAVA_VARIABLE_NAME_CONSTRAINT",
2057                                    Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2058                                    "implementationMessageArgumentJavaVariableNameConstraint",
2059                                    impl.getIdentifier(),
2060                                    validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2061                                    m.getName(), a.getIndex(),
2062                                    message != null && message.length() > 0 ? " " + message : "" );
2063 
2064                     }
2065                 }
2066             }
2067         }
2068     }
2069 
2070     private static void assertValidMessageReference( final ValidationContext validationContext,
2071                                                      final Implementation impl,
2072                                                      final MessageReference r )
2073     {
2074         final Set<InheritanceModel.Node<Message>> effMessages =
2075             validationContext.getInheritanceModel().getMessageNodes( impl.getIdentifier(), r.getName() );
2076 
2077         for ( final InheritanceModel.Node<Message> effMessage : effMessages )
2078         {
2079             final Set<InheritanceModel.Node<Message>> overriddenMessages =
2080                 modifiableSet( effMessage.getOverriddenNodes() );
2081 
2082             if ( r.isOverride() && overriddenMessages.isEmpty() )
2083             {
2084                 addDetail( validationContext.getReport(), "IMPLEMENTATION_MESSAGE_OVERRIDE_CONSTRAINT",
2085                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2086                            "implementationMessageOverrideConstraint", impl.getIdentifier(),
2087                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), r.getName() );
2088 
2089             }
2090 
2091             if ( !( r.isOverride() || overriddenMessages.isEmpty() ) )
2092             {
2093                 for ( final InheritanceModel.Node<Message> overriddenMessage : overriddenMessages )
2094                 {
2095                     Implementation overriddenImplementation = overriddenMessage.getImplementation();
2096                     if ( overriddenMessage.getClassDeclaration() != null )
2097                     {
2098                         overriddenImplementation = overriddenMessage.getClassDeclaration();
2099                     }
2100 
2101                     final Module moduleOfMessage =
2102                         validationContext.getModuleOfImplementation(
2103                             overriddenImplementation.getIdentifier() );
2104 
2105                     addDetail( validationContext.getReport(), "IMPLEMENTATION_MESSAGE_OVERRIDE_WARNING",
2106                                Level.WARNING, new ObjectFactory().createImplementation( impl ),
2107                                "implementationMessageOverrideWarning", impl.getIdentifier(),
2108                                validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2109                                r.getName(), overriddenImplementation.getIdentifier(),
2110                                moduleOfMessage.getName(), getNodePathString( overriddenMessage ) );
2111 
2112                 }
2113             }
2114 
2115             retainFinalNodes( overriddenMessages );
2116 
2117             for ( final InheritanceModel.Node<Message> overriddenMessage : overriddenMessages )
2118             {
2119                 Implementation overriddenImplementation = overriddenMessage.getImplementation();
2120                 if ( overriddenMessage.getClassDeclaration() != null )
2121                 {
2122                     overriddenImplementation = overriddenMessage.getClassDeclaration();
2123                 }
2124 
2125                 final Module moduleOfMessage =
2126                     validationContext.getModuleOfImplementation( overriddenImplementation.getIdentifier() );
2127 
2128                 addDetail( validationContext.getReport(),
2129                            "IMPLEMENTATION_MESSAGE_INHERITANCE_CONSTRAINT",
2130                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2131                            "implementationMessageFinalConstraint", impl.getIdentifier(),
2132                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), r.getName(),
2133                            overriddenImplementation.getIdentifier(),
2134                            moduleOfMessage.getName(), getNodePathString( overriddenMessage ) );
2135 
2136             }
2137         }
2138     }
2139 
2140     private static void assertValidProperty( final ValidationContext validationContext,
2141                                              final Implementation impl,
2142                                              final Property p )
2143     {
2144         if ( impl.getProperties().getReference( p.getName() ) != null )
2145         {
2146             addDetail( validationContext.getReport(), "IMPLEMENTATION_PROPERTIES_UNIQUENESS_CONSTRAINT",
2147                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2148                        "implementationPropertiesUniquenessConstraint", impl.getIdentifier(),
2149                        validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), p.getName() );
2150 
2151         }
2152 
2153         if ( p.getValue() != null && p.getAny() != null )
2154         {
2155             addDetail( validationContext.getReport(), "IMPLEMENTATION_PROPERTY_VALUE_CONSTRAINT",
2156                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2157                        "implementationPropertyValueConstraint", impl.getIdentifier(),
2158                        validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), p.getName() );
2159 
2160         }
2161 
2162         if ( p.getAny() != null && p.getType() == null )
2163         {
2164             addDetail( validationContext.getReport(), "IMPLEMENTATION_PROPERTY_TYPE_CONSTRAINT",
2165                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2166                        "implementationPropertyTypeConstraint", impl.getIdentifier(),
2167                        validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), p.getName() );
2168 
2169         }
2170 
2171         if ( validationContext.isValidateJava() )
2172         {
2173             try
2174             {
2175                 p.getJavaConstantName();
2176             }
2177             catch ( final ModelObjectException e )
2178             {
2179                 final String message = getMessage( e );
2180 
2181                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
2182                 {
2183                     validationContext.getModelContext().log( Level.FINE, message, e );
2184                 }
2185 
2186                 addDetail( validationContext.getReport(),
2187                            "IMPLEMENTATION_PROPERTY_JAVA_CONSTANT_NAME_CONSTRAINT",
2188                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2189                            "implementationPropertyJavaConstantNameConstraint", impl.getIdentifier(),
2190                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), p.getName(),
2191                            message != null && message.length() > 0 ? " " + message : "" );
2192 
2193             }
2194 
2195             try
2196             {
2197                 p.getJavaGetterMethodName();
2198             }
2199             catch ( final ModelObjectException e )
2200             {
2201                 final String message = getMessage( e );
2202 
2203                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
2204                 {
2205                     validationContext.getModelContext().log( Level.FINE, message, e );
2206                 }
2207 
2208                 addDetail( validationContext.getReport(),
2209                            "IMPLEMENTATION_PROPERTY_JAVA_GETTER_METHOD_NAME_CONSTRAINT",
2210                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2211                            "implementationPropertyJavaGetterMethodNameConstraint", impl.getIdentifier(),
2212                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), p.getName(),
2213                            message != null && message.length() > 0 ? " " + message : "" );
2214 
2215             }
2216 
2217             try
2218             {
2219                 p.getJavaSetterMethodName();
2220             }
2221             catch ( final ModelObjectException e )
2222             {
2223                 final String message = getMessage( e );
2224 
2225                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
2226                 {
2227                     validationContext.getModelContext().log( Level.FINE, message, e );
2228                 }
2229 
2230                 addDetail( validationContext.getReport(),
2231                            "IMPLEMENTATION_PROPERTY_JAVA_SETTER_METHOD_NAME_CONSTRAINT",
2232                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2233                            "implementationPropertyJavaSetterMethodNameConstraint", impl.getIdentifier(),
2234                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), p.getName(),
2235                            message != null && message.length() > 0 ? " " + message : "" );
2236 
2237             }
2238 
2239             try
2240             {
2241                 p.getJavaTypeName();
2242             }
2243             catch ( final ModelObjectException e )
2244             {
2245                 final String message = getMessage( e );
2246 
2247                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
2248                 {
2249                     validationContext.getModelContext().log( Level.FINE, message, e );
2250                 }
2251 
2252                 addDetail( validationContext.getReport(),
2253                            "IMPLEMENTATION_PROPERTY_JAVA_TYPE_NAME_CONSTRAINT",
2254                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2255                            "implementationPropertyJavaTypeNameConstraint", impl.getIdentifier(),
2256                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), p.getName(),
2257                            message != null && message.length() > 0 ? " " + message : "" );
2258 
2259             }
2260 
2261             try
2262             {
2263                 p.getJavaVariableName();
2264             }
2265             catch ( final ModelObjectException e )
2266             {
2267                 final String message = getMessage( e );
2268 
2269                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
2270                 {
2271                     validationContext.getModelContext().log( Level.FINE, message, e );
2272                 }
2273 
2274                 addDetail( validationContext.getReport(),
2275                            "IMPLEMENTATION_PROPERTY_JAVA_VARIABLE_NAME_CONSTRAINT",
2276                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2277                            "implementationPropertyJavaVariableNameConstraint", impl.getIdentifier(),
2278                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), p.getName(),
2279                            message != null && message.length() > 0 ? " " + message : "" );
2280 
2281             }
2282 
2283             try
2284             {
2285                 p.getJavaValue( validationContext.getModelContext().getClassLoader() );
2286             }
2287             catch ( final ModelObjectException e )
2288             {
2289                 final String message = getMessage( e );
2290 
2291                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
2292                 {
2293                     validationContext.getModelContext().log( Level.FINE, message, e );
2294                 }
2295 
2296                 addDetail( validationContext.getReport(),
2297                            "IMPLEMENTATION_PROPERTY_JAVA_VALUE_CONSTRAINT",
2298                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2299                            "implementationPropertyJavaValueConstraint", impl.getIdentifier(),
2300                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), p.getName(),
2301                            message != null && message.length() > 0 ? " " + message : "" );
2302 
2303             }
2304         }
2305 
2306         final Set<InheritanceModel.Node<Property>> effProperties =
2307             validationContext.getInheritanceModel().getPropertyNodes( impl.getIdentifier(), p.getName() );
2308 
2309         for ( final InheritanceModel.Node<Property> effProperty : effProperties )
2310         {
2311             final Set<InheritanceModel.Node<Property>> overriddenProperties =
2312                 modifiableSet( effProperty.getOverriddenNodes() );
2313 
2314             if ( p.isOverride() && overriddenProperties.isEmpty() )
2315             {
2316                 addDetail( validationContext.getReport(), "IMPLEMENTATION_PROPERTY_OVERRIDE_CONSTRAINT",
2317                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2318                            "implementationPropertyOverrideConstraint", impl.getIdentifier(),
2319                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), p.getName() );
2320 
2321             }
2322 
2323             if ( !( p.isOverride() || overriddenProperties.isEmpty() ) )
2324             {
2325                 for ( final InheritanceModel.Node<Property> overriddenProperty : overriddenProperties )
2326                 {
2327                     if ( overriddenProperty.getSpecification() != null )
2328                     {
2329                         final Module moduleOfProperty =
2330                             validationContext.getModuleOfSpecification(
2331                                 overriddenProperty.getSpecification().getIdentifier() );
2332 
2333                         addDetail( validationContext.getReport(),
2334                                    "IMPLEMENTATION_PROPERTY_OVERRIDE_WARNING", Level.WARNING,
2335                                    new ObjectFactory().createImplementation( impl ),
2336                                    "implementationSpecificationPropertyOverrideWarning",
2337                                    impl.getIdentifier(),
2338                                    validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2339                                    p.getName(), overriddenProperty.getSpecification().getIdentifier(),
2340                                    moduleOfProperty.getName(),
2341                                    getNodePathString( overriddenProperty ) );
2342 
2343                     }
2344                     else
2345                     {
2346                         Implementation overriddenImplementation =
2347                             overriddenProperty.getImplementation();
2348 
2349                         if ( overriddenProperty.getClassDeclaration() != null )
2350                         {
2351                             overriddenImplementation = overriddenProperty.getClassDeclaration();
2352                         }
2353 
2354                         final Module moduleOfProperty =
2355                             validationContext.getModuleOfImplementation( overriddenImplementation.getIdentifier() );
2356 
2357                         addDetail( validationContext.getReport(),
2358                                    "IMPLEMENTATION_PROPERTY_OVERRIDE_WARNING", Level.WARNING,
2359                                    new ObjectFactory().createImplementation( impl ),
2360                                    "implementationPropertyOverrideWarning", impl.getIdentifier(),
2361                                    validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2362                                    p.getName(), overriddenImplementation.getIdentifier(), moduleOfProperty.getName(),
2363                                    getNodePathString( overriddenProperty ) );
2364 
2365                     }
2366                 }
2367             }
2368 
2369             retainFinalNodes( overriddenProperties );
2370 
2371             for ( final InheritanceModel.Node<Property> overriddenProperty : overriddenProperties )
2372             {
2373                 Implementation overriddenImplementation = overriddenProperty.getImplementation();
2374                 if ( overriddenProperty.getClassDeclaration() != null )
2375                 {
2376                     overriddenImplementation = overriddenProperty.getClassDeclaration();
2377                 }
2378 
2379                 final Module moduleOfProperty =
2380                     validationContext.getModuleOfImplementation(
2381                         overriddenImplementation.getIdentifier() );
2382 
2383                 addDetail( validationContext.getReport(),
2384                            "IMPLEMENTATION_PROPERTY_INHERITANCE_CONSTRAINT",
2385                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2386                            "implementationPropertyFinalConstraint", impl.getIdentifier(),
2387                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), p.getName(),
2388                            overriddenImplementation.getIdentifier(),
2389                            moduleOfProperty.getName(), getNodePathString( overriddenProperty ) );
2390 
2391             }
2392         }
2393     }
2394 
2395     private static void assertValidPropertyReference( final ValidationContext validationContext,
2396                                                       final Implementation impl,
2397                                                       final PropertyReference r )
2398     {
2399         final Set<InheritanceModel.Node<Property>> effProperties =
2400             validationContext.getInheritanceModel().getPropertyNodes( impl.getIdentifier(), r.getName() );
2401 
2402         for ( final InheritanceModel.Node<Property> effProperty : effProperties )
2403         {
2404             final Set<InheritanceModel.Node<Property>> overriddenProperties =
2405                 modifiableSet( effProperty.getOverriddenNodes() );
2406 
2407             if ( r.isOverride() && overriddenProperties.isEmpty() )
2408             {
2409                 addDetail( validationContext.getReport(), "IMPLEMENTATION_PROPERTY_OVERRIDE_CONSTRAINT",
2410                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2411                            "implementationPropertyOverrideConstraint", impl.getIdentifier(),
2412                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), r.getName() );
2413 
2414             }
2415 
2416             if ( !( r.isOverride() || overriddenProperties.isEmpty() ) )
2417             {
2418                 for ( final InheritanceModel.Node<Property> overriddenProperty : overriddenProperties )
2419                 {
2420                     Implementation overriddenImplementation = overriddenProperty.getImplementation();
2421                     if ( overriddenProperty.getClassDeclaration() != null )
2422                     {
2423                         overriddenImplementation = overriddenProperty.getClassDeclaration();
2424                     }
2425 
2426                     final Module moduleOfProperty =
2427                         validationContext.getModuleOfImplementation(
2428                             overriddenImplementation.getIdentifier() );
2429 
2430                     addDetail( validationContext.getReport(),
2431                                "IMPLEMENTATION_PROPERTY_OVERRIDE_WARNING", Level.WARNING,
2432                                new ObjectFactory().createImplementation( impl ),
2433                                "implementationPropertyOverrideWarning", impl.getIdentifier(),
2434                                validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2435                                r.getName(), overriddenImplementation.getIdentifier(),
2436                                moduleOfProperty.getName(), getNodePathString( overriddenProperty ) );
2437 
2438                 }
2439             }
2440 
2441             retainFinalNodes( overriddenProperties );
2442 
2443             for ( final InheritanceModel.Node<Property> overriddenProperty : overriddenProperties )
2444             {
2445                 Implementation overriddenImplementation = overriddenProperty.getImplementation();
2446                 if ( overriddenProperty.getClassDeclaration() != null )
2447                 {
2448                     overriddenImplementation = overriddenProperty.getClassDeclaration();
2449                 }
2450 
2451                 final Module moduleOfProperty =
2452                     validationContext.getModuleOfImplementation(
2453                         overriddenImplementation.getIdentifier() );
2454 
2455                 addDetail( validationContext.getReport(),
2456                            "IMPLEMENTATION_PROPERTY_INHERITANCE_CONSTRAINT",
2457                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2458                            "implementationPropertyFinalConstraint", impl.getIdentifier(),
2459                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), r.getName(),
2460                            overriddenImplementation.getIdentifier(),
2461                            moduleOfProperty.getName(), getNodePathString( overriddenProperty ) );
2462 
2463             }
2464         }
2465     }
2466 
2467     private static void assertValidSpecificationReference( final ValidationContext validationContext,
2468                                                            final Implementation impl,
2469                                                            final SpecificationReference r )
2470     {
2471         final Set<InheritanceModel.Node<SpecificationReference>> effReferences =
2472             validationContext.getInheritanceModel().getSpecificationReferenceNodes( impl.getIdentifier(),
2473                                                                                     r.getIdentifier() );
2474 
2475         for ( final InheritanceModel.Node<SpecificationReference> effReference : effReferences )
2476         {
2477             final Set<InheritanceModel.Node<SpecificationReference>> overriddenReferences =
2478                 modifiableSet( effReference.getOverriddenNodes() );
2479 
2480             if ( r.isOverride() && overriddenReferences.isEmpty() )
2481             {
2482                 addDetail( validationContext.getReport(),
2483                            "IMPLEMENTATION_SPECIFICATION_OVERRIDE_CONSTRAINT", Level.SEVERE,
2484                            new ObjectFactory().createImplementation( impl ),
2485                            "implementationSpecificationOverrideConstraint", impl.getIdentifier(),
2486                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2487                            r.getIdentifier() );
2488 
2489             }
2490 
2491             if ( !( r.isOverride() || overriddenReferences.isEmpty() ) )
2492             {
2493                 for ( final InheritanceModel.Node<SpecificationReference> overriddenReference : overriddenReferences )
2494                 {
2495                     Implementation overriddenImplementation = overriddenReference.getImplementation();
2496                     if ( overriddenReference.getClassDeclaration() != null )
2497                     {
2498                         overriddenImplementation = overriddenReference.getClassDeclaration();
2499                     }
2500 
2501                     final Module moduleOfReference =
2502                         validationContext.getModuleOfImplementation( overriddenImplementation.getIdentifier() );
2503 
2504                     addDetail( validationContext.getReport(),
2505                                "IMPLEMENTATION_SPECIFICATION_REFERENCE_OVERRIDE_WARNING",
2506                                Level.WARNING, new ObjectFactory().createImplementation( impl ),
2507                                "implementationSpecificationOverrideWarning", impl.getIdentifier(),
2508                                validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2509                                r.getIdentifier(), overriddenImplementation.getIdentifier(),
2510                                moduleOfReference.getName(), getNodePathString( overriddenReference ) );
2511 
2512                 }
2513             }
2514 
2515             retainFinalNodes( overriddenReferences );
2516 
2517             for ( final InheritanceModel.Node<SpecificationReference> overriddenReference
2518                       : overriddenReferences )
2519             {
2520                 Implementation overriddenImplementation = overriddenReference.getImplementation();
2521                 if ( overriddenReference.getClassDeclaration() != null )
2522                 {
2523                     overriddenImplementation = overriddenReference.getClassDeclaration();
2524                 }
2525 
2526                 final Module moduleOfReference =
2527                     validationContext.getModuleOfImplementation( overriddenImplementation.getIdentifier() );
2528 
2529                 addDetail( validationContext.getReport(),
2530                            "IMPLEMENTATION_SPECIFICATION_INHERITANCE_CONSTRAINT", Level.SEVERE,
2531                            new ObjectFactory().createImplementation( impl ),
2532                            "implementationSpecificationFinalConstraint", impl.getIdentifier(),
2533                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2534                            r.getIdentifier(), overriddenImplementation.getIdentifier(),
2535                            moduleOfReference.getName(), getNodePathString( overriddenReference ) );
2536 
2537             }
2538         }
2539     }
2540 
2541     private static void assertValidAnyObject( final ValidationContext validationContext,
2542                                               final Implementation impl,
2543                                               final Object any )
2544     {
2545 
2546         if ( any instanceof JAXBElement<?> )
2547         {
2548             final JAXBElement<?> jaxbElement = (JAXBElement<?>) any;
2549             boolean overrideNode = false;
2550 
2551             if ( jaxbElement.getValue() instanceof Inheritable )
2552             {
2553                 overrideNode = ( (Inheritable) jaxbElement.getValue() ).isOverride();
2554             }
2555 
2556             final Set<InheritanceModel.Node<JAXBElement<?>>> effElements =
2557                 validationContext.getInheritanceModel().getJaxbElementNodes( impl.getIdentifier(),
2558                                                                              jaxbElement.getName() );
2559 
2560             for ( final InheritanceModel.Node<JAXBElement<?>> effElement : effElements )
2561             {
2562                 final Set<InheritanceModel.Node<JAXBElement<?>>> overriddenElements =
2563                     modifiableSet( effElement.getOverriddenNodes() );
2564 
2565                 if ( overrideNode && overriddenElements.isEmpty() )
2566                 {
2567                     addDetail( validationContext.getReport(),
2568                                "IMPLEMENTATION_JAXB_ELEMENT_OVERRIDE_CONSTRAINT",
2569                                Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2570                                "implementationJaxbElementOverrideConstraint", impl.getIdentifier(),
2571                                validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2572                                jaxbElement.getName().toString() );
2573 
2574                 }
2575 
2576                 if ( !( overrideNode || overriddenElements.isEmpty() ) )
2577                 {
2578                     for ( final InheritanceModel.Node<JAXBElement<?>> overriddenElement : overriddenElements )
2579                     {
2580                         Implementation overriddenImplementation = overriddenElement.getImplementation();
2581                         if ( overriddenElement.getClassDeclaration() != null )
2582                         {
2583                             overriddenImplementation = overriddenElement.getClassDeclaration();
2584                         }
2585 
2586                         final Module moduleOfElement =
2587                             validationContext.getModuleOfImplementation(
2588                                 overriddenElement.getImplementation().getIdentifier() );
2589 
2590                         addDetail( validationContext.getReport(),
2591                                    "IMPLEMENTATION_JAXB_ELEMENT_OVERRIDE_WARNING",
2592                                    Level.WARNING, new ObjectFactory().createImplementation( impl ),
2593                                    "implementationJaxbElementOverrideWarning", impl.getIdentifier(),
2594                                    validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2595                                    jaxbElement.getName().toString(), overriddenImplementation.getIdentifier(),
2596                                    moduleOfElement.getName(), getNodePathString( overriddenElement ) );
2597 
2598                     }
2599                 }
2600 
2601                 retainFinalNodes( overriddenElements );
2602 
2603                 for ( final InheritanceModel.Node<JAXBElement<?>> overriddenElement : overriddenElements )
2604                 {
2605                     Implementation overriddenImplementation = overriddenElement.getImplementation();
2606                     if ( overriddenElement.getClassDeclaration() != null )
2607                     {
2608                         overriddenImplementation = overriddenElement.getClassDeclaration();
2609                     }
2610 
2611                     final Module moduleOfElement =
2612                         validationContext.getModuleOfImplementation( overriddenImplementation.getIdentifier() );
2613 
2614                     addDetail( validationContext.getReport(),
2615                                "IMPLEMENTATION_JAXB_ELEMENT_INHERITANCE_CONSTRAINT",
2616                                Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2617                                "implementationJaxbElementFinalConstraint", impl.getIdentifier(),
2618                                validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2619                                jaxbElement.getName().toString(), overriddenImplementation.getIdentifier(),
2620                                moduleOfElement.getName(), getNodePathString( overriddenElement ) );
2621 
2622                 }
2623             }
2624         }
2625     }
2626 
2627     private static void assertUniqueDependencies( final ValidationContext validationContext,
2628                                                   final Implementation impl )
2629     {
2630         final Set<String> dependencyNames =
2631             validationContext.getInheritanceModel().getDependencyNames( impl.getIdentifier() );
2632 
2633         final Map<JavaIdentifier, InheritanceModel.Node<Dependency>> dependencyJavaConstantNames =
2634             new HashMap<JavaIdentifier, InheritanceModel.Node<Dependency>>( dependencyNames.size() );
2635 
2636         final Map<JavaIdentifier, InheritanceModel.Node<Dependency>> dependencyJavaGetterMethodNames =
2637             new HashMap<JavaIdentifier, InheritanceModel.Node<Dependency>>( dependencyNames.size() );
2638 
2639         final Map<JavaIdentifier, InheritanceModel.Node<Dependency>> dependencyJavaSetterMethodNames =
2640             new HashMap<JavaIdentifier, InheritanceModel.Node<Dependency>>( dependencyNames.size() );
2641 
2642         final Map<JavaIdentifier, InheritanceModel.Node<Dependency>> dependencyJavaVariableNames =
2643             new HashMap<JavaIdentifier, InheritanceModel.Node<Dependency>>( dependencyNames.size() );
2644 
2645         for ( final String dependencyName : dependencyNames )
2646         {
2647             final Set<InheritanceModel.Node<Dependency>> dependencyNodes =
2648                 validationContext.getInheritanceModel().getDependencyNodes( impl.getIdentifier(), dependencyName );
2649 
2650             if ( dependencyNodes.size() > 1 )
2651             {
2652                 addDetail( validationContext.getReport(),
2653                            "IMPLEMENTATION_DEPENDENCY_MULTIPLE_INHERITANCE_CONSTRAINT",
2654                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2655                            "implementationMultipleInheritanceDependencyConstraint", impl.getIdentifier(),
2656                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2657                            dependencyName, getNodeListPathString( dependencyNodes ) );
2658 
2659             }
2660 
2661             if ( validationContext.isValidateJava() )
2662             {
2663                 for ( final InheritanceModel.Node<Dependency> node : dependencyNodes )
2664                 {
2665                     try
2666                     {
2667                         final JavaIdentifier javaIdentifier = node.getModelObject().getJavaConstantName();
2668                         final InheritanceModel.Node<Dependency> existingNode =
2669                             dependencyJavaConstantNames.get( javaIdentifier );
2670 
2671                         if ( existingNode != null )
2672                         {
2673                             addDetail( validationContext.getReport(),
2674                                        "IMPLEMENTATION_DEPENDENCY_JAVA_CONSTANT_NAME_UNIQUENESS_CONSTRAINT",
2675                                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2676                                        "implementationDependencyJavaConstantNameUniquenessConstraint",
2677                                        impl.getIdentifier(),
2678                                        validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2679                                        dependencyName, getNodePathString( node ),
2680                                        existingNode.getModelObject().getName(),
2681                                        getNodePathString( existingNode ), javaIdentifier );
2682 
2683                         }
2684                         else
2685                         {
2686                             dependencyJavaConstantNames.put( javaIdentifier, node );
2687                         }
2688                     }
2689                     catch ( final ModelObjectException e )
2690                     {
2691                         // Validated elsewhere.
2692                     }
2693 
2694                     try
2695                     {
2696                         final JavaIdentifier javaIdentifier = node.getModelObject().getJavaGetterMethodName();
2697                         final InheritanceModel.Node<Dependency> existingNode =
2698                             dependencyJavaGetterMethodNames.get( javaIdentifier );
2699 
2700                         if ( existingNode != null )
2701                         {
2702                             addDetail( validationContext.getReport(),
2703                                        "IMPLEMENTATION_DEPENDENCY_JAVA_GETTER_METHOD_NAME_UNIQUENESS_CONSTRAINT",
2704                                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2705                                        "implementationDependencyJavaGetterMethodNameUniquenessConstraint",
2706                                        impl.getIdentifier(),
2707                                        validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2708                                        dependencyName, getNodePathString( node ),
2709                                        existingNode.getModelObject().getName(),
2710                                        getNodePathString( existingNode ), javaIdentifier );
2711 
2712                         }
2713                         else
2714                         {
2715                             dependencyJavaGetterMethodNames.put( javaIdentifier, node );
2716                         }
2717                     }
2718                     catch ( final ModelObjectException e )
2719                     {
2720                         // Validated elsewhere.
2721                     }
2722 
2723                     try
2724                     {
2725                         final JavaIdentifier javaIdentifier = node.getModelObject().getJavaSetterMethodName();
2726                         final InheritanceModel.Node<Dependency> existingNode =
2727                             dependencyJavaSetterMethodNames.get( javaIdentifier );
2728 
2729                         if ( existingNode != null )
2730                         {
2731                             addDetail( validationContext.getReport(),
2732                                        "IMPLEMENTATION_DEPENDENCY_JAVA_SETTER_METHOD_NAME_UNIQUENESS_CONSTRAINT",
2733                                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2734                                        "implementationDependencyJavaSetterMethodNameUniquenessConstraint",
2735                                        impl.getIdentifier(),
2736                                        validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2737                                        dependencyName, getNodePathString( node ),
2738                                        existingNode.getModelObject().getName(),
2739                                        getNodePathString( existingNode ), javaIdentifier );
2740 
2741                         }
2742                         else
2743                         {
2744                             dependencyJavaSetterMethodNames.put( javaIdentifier, node );
2745                         }
2746                     }
2747                     catch ( final ModelObjectException e )
2748                     {
2749                         // Validated elsewhere.
2750                     }
2751 
2752                     try
2753                     {
2754                         final JavaIdentifier javaIdentifier = node.getModelObject().getJavaSetterMethodName();
2755                         final InheritanceModel.Node<Dependency> existingNode =
2756                             dependencyJavaVariableNames.get( javaIdentifier );
2757 
2758                         if ( existingNode != null )
2759                         {
2760                             addDetail( validationContext.getReport(),
2761                                        "IMPLEMENTATION_DEPENDENCY_JAVA_VARIABLE_NAME_UNIQUENESS_CONSTRAINT",
2762                                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2763                                        "implementationDependencyJavaVariableNameUniquenessConstraint",
2764                                        impl.getIdentifier(),
2765                                        validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2766                                        dependencyName,
2767                                        getNodePathString( node ), existingNode.getModelObject().getName(),
2768                                        getNodePathString( existingNode ), javaIdentifier );
2769 
2770                         }
2771                         else
2772                         {
2773                             dependencyJavaVariableNames.put( javaIdentifier, node );
2774                         }
2775                     }
2776                     catch ( final ModelObjectException e )
2777                     {
2778                         // Validated elsewhere.
2779                     }
2780                 }
2781             }
2782         }
2783     }
2784 
2785     private static void assertUniqueMessages( final ValidationContext validationContext,
2786                                               final Implementation impl )
2787     {
2788         final Set<String> messageNames =
2789             validationContext.getInheritanceModel().getMessageNames( impl.getIdentifier() );
2790 
2791         final Map<JavaIdentifier, InheritanceModel.Node<Message>> messageJavaConstantNames =
2792             new HashMap<JavaIdentifier, InheritanceModel.Node<Message>>( messageNames.size() );
2793 
2794         final Map<JavaIdentifier, InheritanceModel.Node<Message>> messageJavaGetterMethodNames =
2795             new HashMap<JavaIdentifier, InheritanceModel.Node<Message>>( messageNames.size() );
2796 
2797         final Map<JavaIdentifier, InheritanceModel.Node<Message>> messageJavaSetterMethodNames =
2798             new HashMap<JavaIdentifier, InheritanceModel.Node<Message>>( messageNames.size() );
2799 
2800         final Map<JavaIdentifier, InheritanceModel.Node<Message>> messageJavaVariableNames =
2801             new HashMap<JavaIdentifier, InheritanceModel.Node<Message>>( messageNames.size() );
2802 
2803         for ( final String messageName : messageNames )
2804         {
2805             final Set<InheritanceModel.Node<Message>> messageNodes =
2806                 validationContext.getInheritanceModel().getMessageNodes( impl.getIdentifier(), messageName );
2807 
2808             if ( messageNodes.size() > 1 )
2809             {
2810                 addDetail( validationContext.getReport(),
2811                            "IMPLEMENTATION_MESSAGE_MULTIPLE_INHERITANCE_CONSTRAINT", Level.SEVERE,
2812                            new ObjectFactory().createImplementation( impl ),
2813                            "implementationMultipleInheritanceMessageConstraint", impl.getIdentifier(),
2814                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(), messageName,
2815                            getNodeListPathString( messageNodes ) );
2816 
2817             }
2818 
2819             if ( validationContext.isValidateJava() )
2820             {
2821                 for ( final InheritanceModel.Node<Message> node : messageNodes )
2822                 {
2823                     try
2824                     {
2825                         final JavaIdentifier javaIdentifier = node.getModelObject().getJavaConstantName();
2826                         final InheritanceModel.Node<Message> existingNode =
2827                             messageJavaConstantNames.get( javaIdentifier );
2828 
2829                         if ( existingNode != null )
2830                         {
2831                             addDetail( validationContext.getReport(),
2832                                        "IMPLEMENTATION_MESSAGE_JAVA_CONSTANT_NAME_UNIQUENESS_CONSTRAINT",
2833                                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2834                                        "implementationMessageJavaConstantNameUniquenessConstraint",
2835                                        impl.getIdentifier(),
2836                                        validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2837                                        messageName, getNodePathString( node ), existingNode.getModelObject().getName(),
2838                                        getNodePathString( existingNode ), javaIdentifier );
2839 
2840                         }
2841                         else
2842                         {
2843                             messageJavaConstantNames.put( javaIdentifier, node );
2844                         }
2845                     }
2846                     catch ( final ModelObjectException e )
2847                     {
2848                         // Validated elsewhere.
2849                     }
2850 
2851                     try
2852                     {
2853                         final JavaIdentifier javaIdentifier = node.getModelObject().getJavaGetterMethodName();
2854                         final InheritanceModel.Node<Message> existingNode =
2855                             messageJavaGetterMethodNames.get( javaIdentifier );
2856 
2857                         if ( existingNode != null )
2858                         {
2859                             addDetail( validationContext.getReport(),
2860                                        "IMPLEMENTATION_MESSAGE_JAVA_GETTER_METHOD_NAME_UNIQUENESS_CONSTRAINT",
2861                                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2862                                        "implementationMessageJavaGetterMethodNameUniquenessConstraint",
2863                                        impl.getIdentifier(),
2864                                        validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2865                                        messageName, getNodePathString( node ), existingNode.getModelObject().getName(),
2866                                        getNodePathString( existingNode ), javaIdentifier );
2867 
2868                         }
2869                         else
2870                         {
2871                             messageJavaGetterMethodNames.put( javaIdentifier, node );
2872                         }
2873                     }
2874                     catch ( final ModelObjectException e )
2875                     {
2876                         // Validated elsewhere.
2877                     }
2878 
2879                     try
2880                     {
2881                         final JavaIdentifier javaIdentifier = node.getModelObject().getJavaSetterMethodName();
2882                         final InheritanceModel.Node<Message> existingNode =
2883                             messageJavaSetterMethodNames.get( javaIdentifier );
2884 
2885                         if ( existingNode != null )
2886                         {
2887                             addDetail( validationContext.getReport(),
2888                                        "IMPLEMENTATION_MESSAGE_JAVA_SETTER_METHOD_NAME_UNIQUENESS_CONSTRAINT",
2889                                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2890                                        "implementationMessageJavaSetterMethodNameUniquenessConstraint",
2891                                        impl.getIdentifier(),
2892                                        validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2893                                        messageName, getNodePathString( node ), existingNode.getModelObject().getName(),
2894                                        getNodePathString( existingNode ), javaIdentifier );
2895 
2896                         }
2897                         else
2898                         {
2899                             messageJavaSetterMethodNames.put( javaIdentifier, node );
2900                         }
2901                     }
2902                     catch ( final ModelObjectException e )
2903                     {
2904                         // Validated elsewhere.
2905                     }
2906 
2907                     try
2908                     {
2909                         final JavaIdentifier javaIdentifier = node.getModelObject().getJavaSetterMethodName();
2910                         final InheritanceModel.Node<Message> existingNode =
2911                             messageJavaVariableNames.get( javaIdentifier );
2912 
2913                         if ( existingNode != null )
2914                         {
2915                             addDetail( validationContext.getReport(),
2916                                        "IMPLEMENTATION_MESSAGE_JAVA_VARIABLE_NAME_UNIQUENESS_CONSTRAINT",
2917                                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2918                                        "implementationMessageJavaVariableNameUniquenessConstraint",
2919                                        impl.getIdentifier(),
2920                                        validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2921                                        messageName, getNodePathString( node ), existingNode.getModelObject().getName(),
2922                                        getNodePathString( existingNode ), javaIdentifier );
2923 
2924                         }
2925                         else
2926                         {
2927                             messageJavaVariableNames.put( javaIdentifier, node );
2928                         }
2929                     }
2930                     catch ( final ModelObjectException e )
2931                     {
2932                         // Validated elsewhere.
2933                     }
2934                 }
2935             }
2936         }
2937     }
2938 
2939     private static void assertUniqueProperties( final ValidationContext validationContext,
2940                                                 final Implementation impl )
2941     {
2942         final Set<String> propertyNames =
2943             validationContext.getInheritanceModel().getPropertyNames( impl.getIdentifier() );
2944 
2945         final Map<JavaIdentifier, InheritanceModel.Node<Property>> propertyJavaConstantNames =
2946             new HashMap<JavaIdentifier, InheritanceModel.Node<Property>>( propertyNames.size() );
2947 
2948         final Map<JavaIdentifier, InheritanceModel.Node<Property>> propertyJavaGetterMethodNames =
2949             new HashMap<JavaIdentifier, InheritanceModel.Node<Property>>( propertyNames.size() );
2950 
2951         final Map<JavaIdentifier, InheritanceModel.Node<Property>> propertyJavaSetterMethodNames =
2952             new HashMap<JavaIdentifier, InheritanceModel.Node<Property>>( propertyNames.size() );
2953 
2954         final Map<JavaIdentifier, InheritanceModel.Node<Property>> propertyJavaVariableNames =
2955             new HashMap<JavaIdentifier, InheritanceModel.Node<Property>>( propertyNames.size() );
2956 
2957         for ( final String propertyName : propertyNames )
2958         {
2959             final Set<InheritanceModel.Node<Property>> propertyNodes =
2960                 validationContext.getInheritanceModel().getPropertyNodes( impl.getIdentifier(), propertyName );
2961 
2962             if ( propertyNodes.size() > 1 )
2963             {
2964                 addDetail( validationContext.getReport(),
2965                            "IMPLEMENTATION_PROPERTY_MULTIPLE_INHERITANCE_CONSTRAINT", Level.SEVERE,
2966                            new ObjectFactory().createImplementation( impl ),
2967                            "implementationMultipleInheritancePropertyConstraint", impl.getIdentifier(),
2968                            validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2969                            propertyName, getNodeListPathString( propertyNodes ) );
2970 
2971             }
2972 
2973             if ( validationContext.isValidateJava() )
2974             {
2975                 for ( final InheritanceModel.Node<Property> node : propertyNodes )
2976                 {
2977                     try
2978                     {
2979                         final JavaIdentifier javaIdentifier = node.getModelObject().getJavaConstantName();
2980                         final InheritanceModel.Node<Property> existingNode =
2981                             propertyJavaConstantNames.get( javaIdentifier );
2982 
2983                         if ( existingNode != null )
2984                         {
2985                             addDetail( validationContext.getReport(),
2986                                        "IMPLEMENTATION_PROPERTY_JAVA_CONSTANT_NAME_UNIQUENESS_CONSTRAINT",
2987                                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
2988                                        "implementationPropertyJavaConstantNameUniquenessConstraint",
2989                                        impl.getIdentifier(),
2990                                        validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
2991                                        propertyName, getNodePathString( node ), existingNode.getModelObject().getName(),
2992                                        getNodePathString( existingNode ), javaIdentifier );
2993 
2994                         }
2995                         else
2996                         {
2997                             propertyJavaConstantNames.put( javaIdentifier, node );
2998                         }
2999                     }
3000                     catch ( final ModelObjectException e )
3001                     {
3002                         // Validated elsewhere.
3003                     }
3004 
3005                     try
3006                     {
3007                         final JavaIdentifier javaIdentifier = node.getModelObject().getJavaGetterMethodName();
3008                         final InheritanceModel.Node<Property> existingNode =
3009                             propertyJavaGetterMethodNames.get( javaIdentifier );
3010 
3011                         if ( existingNode != null )
3012                         {
3013                             addDetail( validationContext.getReport(),
3014                                        "IMPLEMENTATION_PROPERTY_JAVA_GETTER_METHOD_NAME_UNIQUENESS_CONSTRAINT",
3015                                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
3016                                        "implementationPropertyJavaGetterMethodNameUniquenessConstraint",
3017                                        impl.getIdentifier(),
3018                                        validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
3019                                        propertyName, getNodePathString( node ), existingNode.getModelObject().getName(),
3020                                        getNodePathString( existingNode ), javaIdentifier );
3021 
3022                         }
3023                         else
3024                         {
3025                             propertyJavaGetterMethodNames.put( javaIdentifier, node );
3026                         }
3027                     }
3028                     catch ( final ModelObjectException e )
3029                     {
3030                         // Validated elsewhere.
3031                     }
3032 
3033                     try
3034                     {
3035                         final JavaIdentifier javaIdentifier = node.getModelObject().getJavaSetterMethodName();
3036                         final InheritanceModel.Node<Property> existingNode =
3037                             propertyJavaSetterMethodNames.get( javaIdentifier );
3038 
3039                         if ( existingNode != null )
3040                         {
3041                             addDetail( validationContext.getReport(),
3042                                        "IMPLEMENTATION_PROPERTY_JAVA_SETTER_METHOD_NAME_UNIQUENESS_CONSTRAINT",
3043                                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
3044                                        "implementationPropertyJavaSetterMethodNameUniquenessConstraint",
3045                                        impl.getIdentifier(),
3046                                        validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
3047                                        propertyName, getNodePathString( node ), existingNode.getModelObject().getName(),
3048                                        getNodePathString( existingNode ), javaIdentifier );
3049 
3050                         }
3051                         else
3052                         {
3053                             propertyJavaSetterMethodNames.put( javaIdentifier, node );
3054                         }
3055                     }
3056                     catch ( final ModelObjectException e )
3057                     {
3058                         // Validated elsewhere.
3059                     }
3060 
3061                     try
3062                     {
3063                         final JavaIdentifier javaIdentifier = node.getModelObject().getJavaSetterMethodName();
3064                         final InheritanceModel.Node<Property> existingNode =
3065                             propertyJavaVariableNames.get( javaIdentifier );
3066 
3067                         if ( existingNode != null )
3068                         {
3069                             addDetail( validationContext.getReport(),
3070                                        "IMPLEMENTATION_PROPERTY_JAVA_VARIABLE_NAME_UNIQUENESS_CONSTRAINT",
3071                                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
3072                                        "implementationPropertyJavaVariableNameUniquenessConstraint",
3073                                        impl.getIdentifier(),
3074                                        validationContext.getModuleOfImplementation( impl.getIdentifier() ).getName(),
3075                                        propertyName, getNodePathString( node ), existingNode.getModelObject().getName(),
3076                                        getNodePathString( existingNode ), javaIdentifier );
3077 
3078                         }
3079                         else
3080                         {
3081                             propertyJavaVariableNames.put( javaIdentifier, node );
3082                         }
3083                     }
3084                     catch ( final ModelObjectException e )
3085                     {
3086                         // Validated elsewhere.
3087                     }
3088                 }
3089             }
3090         }
3091     }
3092 
3093     private static void assertSpecificationsValid( final ValidationContext validationContext )
3094     {
3095         final Specifications specifications = validationContext.getAllSpecifications();
3096         final Map<String, Specification> specificationClassDeclarations = new HashMap<String, Specification>();
3097         final Map<String, Specification> specificationJavaClassDeclarations =
3098             new HashMap<String, Specification>();
3099 
3100         if ( specifications != null )
3101         {
3102             for ( int i = 0, s0 = specifications.getSpecification().size(); i < s0; i++ )
3103             {
3104                 final Specification s = specifications.getSpecification().get( i );
3105                 final Implementations impls = validationContext.getImplementations( s.getIdentifier() );
3106                 final Module moduleOfS = validationContext.getModuleOfSpecification( s.getIdentifier() );
3107 
3108                 if ( validationContext.isValidateJava() )
3109                 {
3110                     try
3111                     {
3112                         s.getJavaTypeName();
3113                     }
3114                     catch ( final ModelObjectException e )
3115                     {
3116                         final String message = getMessage( e );
3117 
3118                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3119                         {
3120                             validationContext.getModelContext().log( Level.FINE, message, e );
3121                         }
3122 
3123                         addDetail( validationContext.getReport(),
3124                                    "SPECIFICATION_JAVA_TYPE_NAME_CONSTRAINT",
3125                                    Level.SEVERE, new ObjectFactory().createSpecification( s ),
3126                                    "specificationJavaTypeNameConstraint", s.getIdentifier(),
3127                                    moduleOfS.getName(), s.getClazz(),
3128                                    message != null && message.length() > 0 ? " " + message : "" );
3129 
3130                     }
3131                 }
3132 
3133                 if ( s.isClassDeclaration() )
3134                 {
3135                     if ( s.getClazz() == null )
3136                     {
3137                         addDetail( validationContext.getReport(), "SPECIFICATION_CLASS_CONSTRAINT", Level.SEVERE,
3138                                    new ObjectFactory().createSpecification( s ), "specificationClassConstraint",
3139                                    s.getIdentifier(), moduleOfS.getName() );
3140 
3141                     }
3142                     else
3143                     {
3144                         final Specification prev = specificationClassDeclarations.get( s.getClazz() );
3145 
3146                         if ( prev != null && !prev.getIdentifier().equals( s.getIdentifier() ) )
3147                         {
3148                             final Module moduleOfPrev =
3149                                 validationContext.getModuleOfSpecification( prev.getIdentifier() );
3150 
3151                             addDetail( validationContext.getReport(), "SPECIFICATION_CLASS_DECLARATION_CONSTRAINT",
3152                                        Level.SEVERE, new ObjectFactory().createSpecification( s ),
3153                                        "specificationClassDeclarationConstraint", s.getIdentifier(),
3154                                        moduleOfS.getName(), s.getClazz(), prev.getIdentifier(),
3155                                        moduleOfPrev.getName() );
3156 
3157                         }
3158                         else
3159                         {
3160                             specificationClassDeclarations.put( s.getClazz(), s );
3161                         }
3162 
3163                         if ( validationContext.isValidateJava() )
3164                         {
3165                             try
3166                             {
3167                                 final Specification java =
3168                                     specificationJavaClassDeclarations.get( s.getJavaTypeName().getClassName() );
3169 
3170                                 if ( java != null && !java.getIdentifier().equals( s.getIdentifier() ) )
3171                                 {
3172                                     final Module moduleOfJava =
3173                                         validationContext.getModuleOfSpecification( java.getIdentifier() );
3174 
3175                                     addDetail( validationContext.getReport(),
3176                                                "SPECIFICATION_JAVA_CLASS_DECLARATION_CONSTRAINT",
3177                                                Level.SEVERE, new ObjectFactory().createSpecification( s ),
3178                                                "specificationJavaClassDeclarationConstraint", s.getIdentifier(),
3179                                                moduleOfS.getName(), s.getJavaTypeName().getClassName(),
3180                                                java.getIdentifier(), moduleOfJava.getName() );
3181 
3182                                 }
3183                                 else
3184                                 {
3185                                     specificationJavaClassDeclarations.put( s.getJavaTypeName().getClassName(), s );
3186                                 }
3187                             }
3188                             catch ( final ModelObjectException e )
3189                             {
3190                                 // Already validated above.
3191                             }
3192                         }
3193                     }
3194                 }
3195 
3196                 if ( impls != null )
3197                 {
3198                     final Map<String, Implementations> map = new HashMap<String, Implementations>();
3199 
3200                     for ( int j = 0, s1 = impls.getImplementation().size(); j < s1; j++ )
3201                     {
3202                         final Implementation impl = impls.getImplementation().get( j );
3203                         Implementations implementations = map.get( impl.getName() );
3204 
3205                         if ( implementations == null )
3206                         {
3207                             implementations = new Implementations();
3208                             map.put( impl.getName(), implementations );
3209                         }
3210 
3211                         implementations.getImplementation().add( impl );
3212                     }
3213 
3214                     for ( final Map.Entry<String, Implementations> e : map.entrySet() )
3215                     {
3216                         if ( e.getValue().getImplementation().size() > 1 )
3217                         {
3218                             for ( int j = 0, s1 = e.getValue().getImplementation().size(); j < s1; j++ )
3219                             {
3220                                 final Implementation impl = e.getValue().getImplementation().get( j );
3221                                 final Module moduleOfImpl =
3222                                     validationContext.getModuleOfImplementation( impl.getIdentifier() );
3223 
3224                                 addDetail( validationContext.getReport(),
3225                                            "SPECIFICATION_IMPLEMENTATION_NAME_UNIQUENESS_CONSTRAINT",
3226                                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
3227                                            "specificationImplementationNameConstraint", impl.getIdentifier(),
3228                                            moduleOfImpl.getName(), s.getIdentifier(), moduleOfS.getName(),
3229                                            impl.getName() );
3230 
3231                             }
3232                         }
3233                     }
3234 
3235                     if ( s.getMultiplicity() == Multiplicity.ONE && impls.getImplementation().size() > 1 )
3236                     {
3237                         for ( int j = 0, s1 = impls.getImplementation().size(); j < s1; j++ )
3238                         {
3239                             final Implementation impl = impls.getImplementation().get( j );
3240                             final Module moduleOfImpl =
3241                                 validationContext.getModuleOfImplementation( impl.getIdentifier() );
3242 
3243                             addDetail( validationContext.getReport(),
3244                                        "SPECIFICATION_IMPLEMENTATION_MULTIPLICITY_CONSTRAINT", Level.SEVERE,
3245                                        new ObjectFactory().createImplementation( impl ),
3246                                        "specificationMultiplicityConstraint", impl.getIdentifier(),
3247                                        moduleOfImpl.getName(), s.getIdentifier(), moduleOfS.getName(),
3248                                        s.getMultiplicity() );
3249 
3250                         }
3251                     }
3252                 }
3253 
3254                 if ( s.getProperties() != null )
3255                 {
3256                     for ( int j = 0, s1 = s.getProperties().getProperty().size(); j < s1; j++ )
3257                     {
3258                         final Property p = s.getProperties().getProperty().get( j );
3259 
3260                         if ( p.getValue() != null && p.getAny() != null )
3261                         {
3262                             addDetail( validationContext.getReport(), "SPECIFICATION_PROPERTY_VALUE_CONSTRAINT",
3263                                        Level.SEVERE, new ObjectFactory().createSpecification( s ),
3264                                        "specificationPropertyValueConstraint", s.getIdentifier(),
3265                                        moduleOfS.getName(), p.getName() );
3266 
3267                         }
3268 
3269                         if ( p.getAny() != null && p.getType() == null )
3270                         {
3271                             addDetail( validationContext.getReport(), "SPECIFICATION_PROPERTY_TYPE_CONSTRAINT",
3272                                        Level.SEVERE, new ObjectFactory().createSpecification( s ),
3273                                        "specificationPropertyTypeConstraint", s.getIdentifier(),
3274                                        moduleOfS.getName(), p.getName() );
3275 
3276                         }
3277 
3278                         if ( validationContext.isValidateJava() )
3279                         {
3280                             try
3281                             {
3282                                 p.getJavaConstantName();
3283                             }
3284                             catch ( final ModelObjectException e )
3285                             {
3286                                 final String message = getMessage( e );
3287 
3288                                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3289                                 {
3290                                     validationContext.getModelContext().log( Level.FINE, message, e );
3291                                 }
3292 
3293                                 addDetail( validationContext.getReport(),
3294                                            "SPECIFICATION_PROPERTY_JAVA_CONSTANT_NAME_CONSTRAINT",
3295                                            Level.SEVERE, new ObjectFactory().createSpecification( s ),
3296                                            "specificationPropertyJavaConstantNameConstraint", s.getIdentifier(),
3297                                            moduleOfS.getName(), p.getName(),
3298                                            message != null && message.length() > 0 ? " " + message : "" );
3299 
3300                             }
3301 
3302                             try
3303                             {
3304                                 p.getJavaGetterMethodName();
3305                             }
3306                             catch ( final ModelObjectException e )
3307                             {
3308                                 final String message = getMessage( e );
3309 
3310                                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3311                                 {
3312                                     validationContext.getModelContext().log( Level.FINE, message, e );
3313                                 }
3314 
3315                                 addDetail( validationContext.getReport(),
3316                                            "SPECIFICATION_PROPERTY_JAVA_GETTER_METHOD_NAME_CONSTRAINT",
3317                                            Level.SEVERE, new ObjectFactory().createSpecification( s ),
3318                                            "specificationPropertyJavaGetterMethodNameConstraint", s.getIdentifier(),
3319                                            moduleOfS.getName(), p.getName(),
3320                                            message != null && message.length() > 0 ? " " + message : "" );
3321 
3322                             }
3323 
3324                             try
3325                             {
3326                                 p.getJavaSetterMethodName();
3327                             }
3328                             catch ( final ModelObjectException e )
3329                             {
3330                                 final String message = getMessage( e );
3331 
3332                                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3333                                 {
3334                                     validationContext.getModelContext().log( Level.FINE, message, e );
3335                                 }
3336 
3337                                 addDetail( validationContext.getReport(),
3338                                            "SPECIFICATION_PROPERTY_JAVA_SETTER_METHOD_NAME_CONSTRAINT",
3339                                            Level.SEVERE, new ObjectFactory().createSpecification( s ),
3340                                            "specificationPropertyJavaSetterMethodNameConstraint", s.getIdentifier(),
3341                                            moduleOfS.getName(), p.getName(),
3342                                            message != null && message.length() > 0 ? " " + message : "" );
3343 
3344                             }
3345 
3346                             try
3347                             {
3348                                 p.getJavaTypeName();
3349                             }
3350                             catch ( final ModelObjectException e )
3351                             {
3352                                 final String message = getMessage( e );
3353 
3354                                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3355                                 {
3356                                     validationContext.getModelContext().log( Level.FINE, message, e );
3357                                 }
3358 
3359                                 addDetail( validationContext.getReport(),
3360                                            "SPECIFICATION_PROPERTY_JAVA_TYPE_NAME_CONSTRAINT",
3361                                            Level.SEVERE, new ObjectFactory().createSpecification( s ),
3362                                            "specificationPropertyJavaTypeNameConstraint", s.getIdentifier(),
3363                                            moduleOfS.getName(), p.getName(),
3364                                            message != null && message.length() > 0 ? " " + message : "" );
3365 
3366                             }
3367 
3368                             try
3369                             {
3370                                 p.getJavaVariableName();
3371                             }
3372                             catch ( final ModelObjectException e )
3373                             {
3374                                 final String message = getMessage( e );
3375 
3376                                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3377                                 {
3378                                     validationContext.getModelContext().log( Level.FINE, message, e );
3379                                 }
3380 
3381                                 addDetail( validationContext.getReport(),
3382                                            "SPECIFICATION_PROPERTY_JAVA_VARIABLE_NAME_CONSTRAINT",
3383                                            Level.SEVERE, new ObjectFactory().createSpecification( s ),
3384                                            "specificationPropertyJavaVariableNameConstraint", s.getIdentifier(),
3385                                            moduleOfS.getName(), p.getName(),
3386                                            message != null && message.length() > 0 ? " " + message : "" );
3387 
3388                             }
3389 
3390                             try
3391                             {
3392                                 p.getJavaValue( validationContext.getModelContext().getClassLoader() );
3393                             }
3394                             catch ( final ModelObjectException e )
3395                             {
3396                                 final String message = getMessage( e );
3397 
3398                                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3399                                 {
3400                                     validationContext.getModelContext().log( Level.FINE, message, e );
3401                                 }
3402 
3403                                 addDetail( validationContext.getReport(),
3404                                            "SPECIFICATION_PROPERTY_JAVA_VALUE_CONSTRAINT",
3405                                            Level.SEVERE, new ObjectFactory().createSpecification( s ),
3406                                            "specificationPropertyJavaValueConstraint", s.getIdentifier(),
3407                                            moduleOfS.getName(), p.getName(),
3408                                            message != null && message.length() > 0 ? " " + message : "" );
3409 
3410                             }
3411                         }
3412                     }
3413 
3414                     for ( int j = 0, s1 = s.getProperties().getReference().size(); j < s1; j++ )
3415                     {
3416                         final PropertyReference r = s.getProperties().getReference().get( j );
3417 
3418                         addDetail( validationContext.getReport(),
3419                                    "SPECIFICATION_PROPERTY_REFERENCE_DECLARATION_CONSTRAINT", Level.SEVERE,
3420                                    new ObjectFactory().createSpecification( s ),
3421                                    "specificationPropertyReferenceDeclarationConstraint", s.getIdentifier(),
3422                                    moduleOfS.getName(), r.getName() );
3423 
3424                     }
3425                 }
3426             }
3427         }
3428     }
3429 
3430     private static void assertDependencyValid( final ValidationContext validationContext,
3431                                                final Implementation implementation, final Dependency dependency )
3432     {
3433         final Specification s = validationContext.getSpecification( dependency.getIdentifier() );
3434         final Implementations available = validationContext.getImplementations( dependency.getIdentifier() );
3435         final Module moduleOfImpl =
3436             validationContext.getModuleOfImplementation( implementation.getIdentifier() );
3437 
3438         if ( !dependency.isOptional()
3439                  && ( available == null || available.getImplementation().isEmpty()
3440                       || ( dependency.getImplementationName() != null
3441                            && available.getImplementationByName( dependency.getImplementationName() ) == null ) ) )
3442         {
3443             addDetail( validationContext.getReport(), "IMPLEMENTATION_MANDATORY_DEPENDENCY_CONSTRAINT", Level.SEVERE,
3444                        new ObjectFactory().createImplementation( implementation ),
3445                        "implementationMandatoryDependencyConstraint", implementation.getIdentifier(),
3446                        moduleOfImpl.getName(), dependency.getName() );
3447 
3448         }
3449 
3450         if ( s != null )
3451         {
3452             final Module moduleOfS = validationContext.getModuleOfSpecification( s.getIdentifier() );
3453 
3454             if ( s.getClazz() == null )
3455             {
3456                 addDetail( validationContext.getReport(), "IMPLEMENTATION_DEPENDENCY_SPECIFICATION_CLASS_CONSTRAINT",
3457                            Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
3458                            "implementationDependencySpecificationClassConstraint", implementation.getIdentifier(),
3459                            moduleOfImpl.getName(), dependency.getName(), dependency.getIdentifier(),
3460                            moduleOfS.getName() );
3461 
3462             }
3463 
3464             if ( dependency.getVersion() != null )
3465             {
3466                 if ( s.getVersion() == null )
3467                 {
3468                     addDetail( validationContext.getReport(),
3469                                "IMPLEMENTATION_DEPENDENCY_SPECIFICATION_VERSIONING_CONSTRAINT", Level.SEVERE,
3470                                new ObjectFactory().createImplementation( implementation ),
3471                                "implementationDependencySpecificationVersioningConstraint",
3472                                implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
3473                                s.getIdentifier(), moduleOfS.getName() );
3474 
3475                 }
3476                 else
3477                 {
3478                     try
3479                     {
3480                         if ( VersionParser.compare( dependency.getVersion(), s.getVersion() ) > 0 )
3481                         {
3482                             addDetail( validationContext.getReport(),
3483                                        "IMPLEMENTATION_DEPENDENCY_SPECIFICATION_COMPATIBILITY_CONSTRAINT",
3484                                        Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
3485                                        "implementationDependencySpecificationCompatibilityConstraint",
3486                                        implementation.getIdentifier(), moduleOfImpl.getName(), s.getIdentifier(),
3487                                        moduleOfS.getName(), dependency.getVersion(), s.getVersion() );
3488 
3489                         }
3490                     }
3491                     catch ( final ParseException e )
3492                     {
3493                         final String message = getMessage( e );
3494 
3495                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3496                         {
3497                             validationContext.getModelContext().log( Level.FINE, message, e );
3498                         }
3499 
3500                         addDetail( validationContext.getReport(),
3501                                    "IMPLEMENTATION_DEPENDENCY_SPECIFICATION_COMPATIBILITY_VERSIONING_PARSE_EXCEPTION",
3502                                    Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
3503                                    "implementationDependencySpecificationCompatibilityParseException",
3504                                    implementation.getIdentifier(), moduleOfImpl.getName(), s.getIdentifier(),
3505                                    moduleOfS.getName(), dependency.getVersion(),
3506                                    message != null && message.length() > 0 ? " " + message : "" );
3507 
3508                     }
3509                     catch ( final TokenMgrError e )
3510                     {
3511                         final String message = getMessage( e );
3512 
3513                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3514                         {
3515                             validationContext.getModelContext().log( Level.FINE, message, e );
3516                         }
3517 
3518                         addDetail( validationContext.getReport(),
3519                                    "IMPLEMENTATION_DEPENDENCY_SPECIFICATION_COMPATIBILITY_VERSIONING_TOKEN_MANAGER_ERROR",
3520                                    Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
3521                                    "implementationDependencySpecificationCompatibilityTokenMgrError",
3522                                    implementation.getIdentifier(), moduleOfImpl.getName(), s.getIdentifier(),
3523                                    moduleOfS.getName(), dependency.getVersion(),
3524                                    message != null && message.length() > 0 ? " " + message : "" );
3525 
3526                     }
3527                 }
3528             }
3529 
3530             if ( s.getScope() != null )
3531             {
3532                 if ( dependency.getDependencies() != null )
3533                 {
3534                     for ( int i = 0, s0 = dependency.getDependencies().getDependency().size(); i < s0; i++ )
3535                     {
3536                         final Dependency d = dependency.getDependencies().getDependency().get( i );
3537 
3538                         addDetail( validationContext.getReport(),
3539                                    "IMPLEMENTATION_DEPENDENCY_DEPENDENCIES_OVERRIDE_CONSTRAINT", Level.SEVERE,
3540                                    new ObjectFactory().createImplementation( implementation ),
3541                                    "implementationDependencyDependenciesOverrideConstraint",
3542                                    implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
3543                                    d.getName(), s.getIdentifier(), moduleOfS.getName(), s.getScope() );
3544 
3545                     }
3546                 }
3547 
3548                 if ( dependency.getMessages() != null )
3549                 {
3550                     for ( int i = 0, s0 = dependency.getMessages().getMessage().size(); i < s0; i++ )
3551                     {
3552                         final Message m = dependency.getMessages().getMessage().get( i );
3553 
3554                         addDetail( validationContext.getReport(),
3555                                    "IMPLEMENTATION_DEPENDENCY_MESSAGES_OVERRIDE_CONSTRAINT", Level.SEVERE,
3556                                    new ObjectFactory().createImplementation( implementation ),
3557                                    "implementationDependencyMessagesOverrideConstraint", implementation.getIdentifier(),
3558                                    moduleOfImpl.getName(), dependency.getName(), m.getName(), s.getIdentifier(),
3559                                    moduleOfS.getName(), s.getScope() );
3560 
3561                     }
3562                 }
3563 
3564                 if ( dependency.getProperties() != null )
3565                 {
3566                     for ( int i = 0, s0 = dependency.getProperties().getProperty().size(); i < s0; i++ )
3567                     {
3568                         final Property p = dependency.getProperties().getProperty().get( i );
3569                         addDetail( validationContext.getReport(),
3570                                    "IMPLEMENTATION_DEPENDENCY_PROPERTIES_OVERRIDE_CONSTRAINT", Level.SEVERE,
3571                                    new ObjectFactory().createImplementation( implementation ),
3572                                    "implementationDependencyPropertiesOverrideConstraint",
3573                                    implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
3574                                    p.getName(), s.getIdentifier(), moduleOfS.getName(), s.getScope() );
3575 
3576                     }
3577                 }
3578             }
3579         }
3580 
3581         if ( dependency.getMessages() != null )
3582         {
3583             for ( int i = 0, s0 = dependency.getMessages().getMessage().size(); i < s0; i++ )
3584             {
3585                 final Message m = dependency.getMessages().getMessage().get( i );
3586 
3587                 if ( validationContext.isValidateJava() )
3588                 {
3589                     try
3590                     {
3591                         m.getJavaConstantName();
3592                     }
3593                     catch ( final ModelObjectException e )
3594                     {
3595                         final String message = getMessage( e );
3596 
3597                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3598                         {
3599                             validationContext.getModelContext().log( Level.FINE, message, e );
3600                         }
3601 
3602                         addDetail( validationContext.getReport(),
3603                                    "IMPLEMENTATION_DEPENDENCY_MESSAGE_JAVA_CONSTANT_NAME_CONSTRAINT", Level.SEVERE,
3604                                    new ObjectFactory().createImplementation( implementation ),
3605                                    "implementationDependencyMessageJavaConstantNameConstraint",
3606                                    implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
3607                                    m.getName(), message != null && message.length() > 0 ? " " + message : "" );
3608                     }
3609 
3610                     try
3611                     {
3612                         m.getJavaGetterMethodName();
3613                     }
3614                     catch ( final ModelObjectException e )
3615                     {
3616                         final String message = getMessage( e );
3617 
3618                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3619                         {
3620                             validationContext.getModelContext().log( Level.FINE, message, e );
3621                         }
3622 
3623                         addDetail( validationContext.getReport(),
3624                                    "IMPLEMENTATION_DEPENDENCY_MESSAGE_JAVA_GETTER_METHOD_NAME_CONSTRAINT", Level.SEVERE,
3625                                    new ObjectFactory().createImplementation( implementation ),
3626                                    "implementationDependencyMessageJavaGetterMethodNameConstraint",
3627                                    implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
3628                                    m.getName(), message != null && message.length() > 0 ? " " + message : "" );
3629                     }
3630 
3631                     try
3632                     {
3633                         m.getJavaSetterMethodName();
3634                     }
3635                     catch ( final ModelObjectException e )
3636                     {
3637                         final String message = getMessage( e );
3638 
3639                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3640                         {
3641                             validationContext.getModelContext().log( Level.FINE, message, e );
3642                         }
3643 
3644                         addDetail( validationContext.getReport(),
3645                                    "IMPLEMENTATION_DEPENDENCY_MESSAGE_JAVA_SETTER_METHOD_NAME_CONSTRAINT", Level.SEVERE,
3646                                    new ObjectFactory().createImplementation( implementation ),
3647                                    "implementationDependencyMessageJavaSetterMethodNameConstraint",
3648                                    implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
3649                                    m.getName(), message != null && message.length() > 0 ? " " + message : "" );
3650                     }
3651 
3652                     try
3653                     {
3654                         m.getJavaVariableName();
3655                     }
3656                     catch ( final ModelObjectException e )
3657                     {
3658                         final String message = getMessage( e );
3659 
3660                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3661                         {
3662                             validationContext.getModelContext().log( Level.FINE, message, e );
3663                         }
3664 
3665                         addDetail( validationContext.getReport(),
3666                                    "IMPLEMENTATION_DEPENDENCY_MESSAGE_JAVA_VARIABLE_NAME_CONSTRAINT", Level.SEVERE,
3667                                    new ObjectFactory().createImplementation( implementation ),
3668                                    "implementationDependencyMessageJavaVariableNameConstraint",
3669                                    implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
3670                                    m.getName(), message != null && message.length() > 0 ? " " + message : "" );
3671                     }
3672                 }
3673 
3674                 if ( m.getTemplate() != null )
3675                 {
3676                     for ( int j = 0, s1 = m.getTemplate().getText().size(); j < s1; j++ )
3677                     {
3678                         final Text t = m.getTemplate().getText().get( j );
3679 
3680                         try
3681                         {
3682                             t.getMimeType();
3683                         }
3684                         catch ( final ModelObjectException e )
3685                         {
3686                             final String message = getMessage( e );
3687 
3688                             if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3689                             {
3690                                 validationContext.getModelContext().log( Level.FINE, message, e );
3691                             }
3692 
3693                             addDetail( validationContext.getReport(),
3694                                        "IMPLEMENTATION_DEPENDENCY_MESSAGE_TEMPLATE_MIME_TYPE_CONSTRAINT", Level.SEVERE,
3695                                        new ObjectFactory().createImplementation( implementation ),
3696                                        "implementationDependencyMessageTemplateMimeTypeConstraint",
3697                                        implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
3698                                        m.getName(), t.getLanguage(),
3699                                        message != null && message.length() > 0 ? " " + message : "" );
3700 
3701                         }
3702 
3703                         if ( validationContext.isValidateJava() )
3704                         {
3705                             try
3706                             {
3707                                 new MessageFormat( t.getValue(), new Locale( t.getLanguage() ) );
3708                             }
3709                             catch ( final IllegalArgumentException e )
3710                             {
3711                                 final String message = getMessage( e );
3712 
3713                                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3714                                 {
3715                                     validationContext.getModelContext().log( Level.FINE, message, e );
3716                                 }
3717 
3718                                 addDetail( validationContext.getReport(),
3719                                            "IMPLEMENTATION_DEPENDENCY_MESSAGE_TEMPLATE_CONSTRAINT", Level.SEVERE,
3720                                            new ObjectFactory().createImplementation( implementation ),
3721                                            "implementationDependencyMessageTemplateConstraint",
3722                                            implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
3723                                            m.getName(), t.getLanguage(),
3724                                            message != null && message.length() > 0 ? " " + message : "" );
3725 
3726                             }
3727                         }
3728                     }
3729                 }
3730 
3731                 if ( m.getArguments() != null )
3732                 {
3733                     final Map<JavaIdentifier, Argument> javaVariableNames =
3734                         new HashMap<JavaIdentifier, Argument>( m.getArguments().getArgument().size() );
3735 
3736                     for ( int j = 0, s1 = m.getArguments().getArgument().size(); j < s1; j++ )
3737                     {
3738                         final Argument a = m.getArguments().getArgument().get( j );
3739 
3740                         if ( validationContext.isValidateJava() )
3741                         {
3742                             try
3743                             {
3744                                 a.getJavaTypeName();
3745                             }
3746                             catch ( final ModelObjectException e )
3747                             {
3748                                 final String message = getMessage( e );
3749 
3750                                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3751                                 {
3752                                     validationContext.getModelContext().log( Level.FINE, message, e );
3753                                 }
3754 
3755                                 addDetail( validationContext.getReport(),
3756                                            "IMPLEMENTATION_DEPENDENCY_MESSAGE_ARGUMENT_JAVA_TYPE_NAME_CONSTRAINT",
3757                                            Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
3758                                            "implementationDependencyMessageArgumentJavaTypeNameConstraint",
3759                                            implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
3760                                            m.getName(), a.getName(),
3761                                            message != null && message.length() > 0 ? " " + message : "" );
3762 
3763                             }
3764 
3765                             try
3766                             {
3767                                 final JavaIdentifier javaIdentifier = a.getJavaVariableName();
3768 
3769                                 if ( javaVariableNames.containsKey( javaIdentifier ) )
3770                                 {
3771                                     addDetail( validationContext.getReport(),
3772                                                "IMPLEMENTATION_DEPENDENCY_MESSAGE_ARGUMENT_JAVA_VARIABLE_NAME_UNIQUENESS_CONSTRAINT",
3773                                                Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
3774                                                "implementationDependencyMessageArgumentJavaVariableNameUniquenessConstraint",
3775                                                implementation.getIdentifier(), moduleOfImpl.getName(),
3776                                                dependency.getName(), m.getName(), a.getName(), javaIdentifier,
3777                                                javaVariableNames.get( javaIdentifier ).getName() );
3778 
3779                                 }
3780                                 else
3781                                 {
3782                                     javaVariableNames.put( javaIdentifier, a );
3783                                 }
3784                             }
3785                             catch ( final ModelObjectException e )
3786                             {
3787                                 final String message = getMessage( e );
3788 
3789                                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3790                                 {
3791                                     validationContext.getModelContext().log( Level.FINE, message, e );
3792                                 }
3793 
3794                                 addDetail( validationContext.getReport(),
3795                                            "IMPLEMENTATION_DEPENDENCY_MESSAGE_ARGUMENT_JAVA_VARIABLE_NAME_CONSTRAINT",
3796                                            Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
3797                                            "implementationDependencyMessageArgumentJavaVariableNameConstraint",
3798                                            implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
3799                                            m.getName(), a.getIndex(),
3800                                            message != null && message.length() > 0 ? " " + message : "" );
3801 
3802                             }
3803                         }
3804                     }
3805                 }
3806             }
3807 
3808             for ( int i = 0, s0 = dependency.getMessages().getReference().size(); i < s0; i++ )
3809             {
3810                 final MessageReference r = dependency.getMessages().getReference().get( i );
3811 
3812                 addDetail( validationContext.getReport(),
3813                            "IMPLEMENTATION_DEPENDENCY_MESSAGE_REFERENCE_DECLARATION_CONSTRAINT", Level.SEVERE,
3814                            new ObjectFactory().createImplementation( implementation ),
3815                            "implementationDependencyMessageReferenceDeclarationConstraint",
3816                            implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(), r.getName() );
3817 
3818             }
3819         }
3820 
3821         if ( dependency.getProperties() != null )
3822         {
3823             for ( int i = 0, s0 = dependency.getProperties().getProperty().size(); i < s0; i++ )
3824             {
3825                 final Property p = dependency.getProperties().getProperty().get( i );
3826 
3827                 if ( p.getValue() != null && p.getAny() != null )
3828                 {
3829                     addDetail( validationContext.getReport(), "IMPLEMENTATION_DEPENDENCY_PROPERTY_VALUE_CONSTRAINT",
3830                                Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
3831                                "implementationDependencyPropertyValueConstraint", implementation.getIdentifier(),
3832                                moduleOfImpl.getName(), dependency.getName(), p.getName() );
3833 
3834                 }
3835 
3836                 if ( p.getAny() != null && p.getType() == null )
3837                 {
3838                     addDetail( validationContext.getReport(), "IMPLEMENTATION_DEPENDENCY_PROPERTY_TYPE_CONSTRAINT",
3839                                Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
3840                                "implementationDependencyPropertyTypeConstraint", implementation.getIdentifier(),
3841                                moduleOfImpl.getName(), dependency.getName(), p.getName() );
3842 
3843                 }
3844 
3845                 if ( validationContext.isValidateJava() )
3846                 {
3847                     try
3848                     {
3849                         p.getJavaConstantName();
3850                     }
3851                     catch ( final ModelObjectException e )
3852                     {
3853                         final String message = getMessage( e );
3854 
3855                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3856                         {
3857                             validationContext.getModelContext().log( Level.FINE, message, e );
3858                         }
3859 
3860                         addDetail( validationContext.getReport(),
3861                                    "IMPLEMENTATION_DEPENDENCY_PROPERTY_JAVA_CONSTANT_NAME_CONSTRAINT", Level.SEVERE,
3862                                    new ObjectFactory().createImplementation( implementation ),
3863                                    "implementationDependencyPropertyJavaConstantNameConstraint",
3864                                    implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
3865                                    p.getName(), message != null && message.length() > 0 ? " " + message : "" );
3866 
3867                     }
3868 
3869                     try
3870                     {
3871                         p.getJavaGetterMethodName();
3872                     }
3873                     catch ( final ModelObjectException e )
3874                     {
3875                         final String message = getMessage( e );
3876 
3877                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3878                         {
3879                             validationContext.getModelContext().log( Level.FINE, message, e );
3880                         }
3881 
3882                         addDetail( validationContext.getReport(),
3883                                    "IMPLEMENTATION_DEPENDENCY_PROPERTY_JAVA_GETTER_METHOD_NAME_CONSTRAINT",
3884                                    Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
3885                                    "implementationDependencyPropertyJavaGetterMethodNameConstraint",
3886                                    implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
3887                                    p.getName(), message != null && message.length() > 0 ? " " + message : "" );
3888 
3889                     }
3890 
3891                     try
3892                     {
3893                         p.getJavaSetterMethodName();
3894                     }
3895                     catch ( final ModelObjectException e )
3896                     {
3897                         final String message = getMessage( e );
3898 
3899                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3900                         {
3901                             validationContext.getModelContext().log( Level.FINE, message, e );
3902                         }
3903 
3904                         addDetail( validationContext.getReport(),
3905                                    "IMPLEMENTATION_DEPENDENCY_PROPERTY_JAVA_SETTER_METHOD_NAME_CONSTRAINT",
3906                                    Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
3907                                    "implementationDependencyPropertyJavaSetterMethodNameConstraint",
3908                                    implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
3909                                    p.getName(), message != null && message.length() > 0 ? " " + message : "" );
3910 
3911                     }
3912 
3913                     try
3914                     {
3915                         p.getJavaTypeName();
3916                     }
3917                     catch ( final ModelObjectException e )
3918                     {
3919                         final String message = getMessage( e );
3920 
3921                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3922                         {
3923                             validationContext.getModelContext().log( Level.FINE, message, e );
3924                         }
3925 
3926                         addDetail( validationContext.getReport(),
3927                                    "IMPLEMENTATION_DEPENDENCY_PROPERTY_JAVA_TYPE_NAME_CONSTRAINT",
3928                                    Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
3929                                    "implementationDependencyPropertyJavaTypeNameConstraint",
3930                                    implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
3931                                    p.getName(), message != null && message.length() > 0 ? " " + message : "" );
3932 
3933                     }
3934 
3935                     try
3936                     {
3937                         p.getJavaVariableName();
3938                     }
3939                     catch ( final ModelObjectException e )
3940                     {
3941                         final String message = getMessage( e );
3942 
3943                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3944                         {
3945                             validationContext.getModelContext().log( Level.FINE, message, e );
3946                         }
3947 
3948                         addDetail( validationContext.getReport(),
3949                                    "IMPLEMENTATION_DEPENDENCY_PROPERTY_JAVA_VARIABLE_NAME_CONSTRAINT",
3950                                    Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
3951                                    "implementationDependencyPropertyJavaVariableNameConstraint",
3952                                    implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
3953                                    p.getName(), message != null && message.length() > 0 ? " " + message : "" );
3954 
3955                     }
3956 
3957                     try
3958                     {
3959                         p.getJavaValue( validationContext.getModelContext().getClassLoader() );
3960                     }
3961                     catch ( final ModelObjectException e )
3962                     {
3963                         final String message = getMessage( e );
3964 
3965                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
3966                         {
3967                             validationContext.getModelContext().log( Level.FINE, message, e );
3968                         }
3969 
3970                         addDetail( validationContext.getReport(),
3971                                    "IMPLEMENTATION_DEPENDENCY_PROPERTY_JAVA_VALUE_CONSTRAINT", Level.SEVERE,
3972                                    new ObjectFactory().createImplementation( implementation ),
3973                                    "implementationDependencyPropertyJavaValueConstraint",
3974                                    implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
3975                                    p.getName(), message != null && message.length() > 0 ? " " + message : "" );
3976 
3977                     }
3978                 }
3979             }
3980 
3981             for ( int i = 0, s0 = dependency.getProperties().getReference().size(); i < s0; i++ )
3982             {
3983                 final PropertyReference r = dependency.getProperties().getReference().get( i );
3984 
3985                 addDetail( validationContext.getReport(),
3986                            "IMPLEMENTATION_DEPENDENCY_PROPERTY_REFERENCE_DECLARATION_CONSTRAINT", Level.SEVERE,
3987                            new ObjectFactory().createImplementation( implementation ),
3988                            "implementationDependencyPropertyReferenceDeclarationConstraint",
3989                            implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(), r.getName() );
3990 
3991             }
3992         }
3993 
3994         if ( available != null )
3995         {
3996             for ( int i = 0, s0 = available.getImplementation().size(); i < s0; i++ )
3997             {
3998                 final Implementation a = available.getImplementation().get( i );
3999 
4000                 if ( dependency.getImplementationName() != null
4001                          && !dependency.getImplementationName().equals( a.getName() ) )
4002                 {
4003                     continue;
4004                 }
4005 
4006                 final InheritanceModel imodel = validationContext.getInheritanceModel();
4007                 final Module moduleOfA = validationContext.getModuleOfImplementation( a.getIdentifier() );
4008 
4009                 if ( dependency.getDependencies() != null )
4010                 {
4011                     for ( int j = 0, s1 = dependency.getDependencies().getDependency().size(); j < s1; j++ )
4012                     {
4013                         final Dependency override = dependency.getDependencies().getDependency().get( j );
4014 
4015                         final Set<InheritanceModel.Node<Dependency>> effDependencies =
4016                             imodel.getDependencyNodes( a.getIdentifier(), override.getName() );
4017 
4018                         final Set<InheritanceModel.Node<Dependency>> overriddenDependencies =
4019                             modifiableSet( effDependencies );
4020 
4021                         final boolean effectiveDependencyOverridden = !overriddenDependencies.isEmpty();
4022 
4023                         if ( override.isOverride() && overriddenDependencies.isEmpty() )
4024                         {
4025                             addDetail( validationContext.getReport(),
4026                                        "IMPLEMENTATION_DEPENDENCY_OVERRIDE_DEPENDENCY_CONSTRAINT",
4027                                        Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
4028                                        "implementationDependencyOverrideDependencyConstraint",
4029                                        implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
4030                                        override.getName(), a.getIdentifier(), moduleOfA.getName() );
4031 
4032                         }
4033 
4034                         if ( !( override.isOverride() || overriddenDependencies.isEmpty() ) )
4035                         {
4036                             for ( final InheritanceModel.Node<Dependency> overriddenDependency : overriddenDependencies )
4037                             {
4038                                 addDetail( validationContext.getReport(),
4039                                            "IMPLEMENTATION_DEPENDENCY_OVERRIDE_DEPENDENCY_WARNING",
4040                                            Level.WARNING, new ObjectFactory().createImplementation( implementation ),
4041                                            "implementationDependencyOverrideDependencyWarning",
4042                                            implementation.getIdentifier(), moduleOfImpl.getName(),
4043                                            dependency.getName(), override.getName(), a.getIdentifier(),
4044                                            moduleOfA.getName(), getNodePathString( overriddenDependency ) );
4045 
4046                             }
4047                         }
4048 
4049                         retainFinalNodes( overriddenDependencies );
4050 
4051                         for ( final InheritanceModel.Node<Dependency> overriddenDependency : overriddenDependencies )
4052                         {
4053                             addDetail( validationContext.getReport(),
4054                                        "IMPLEMENTATION_DEPENDENCY_FINAL_DEPENDENCY_CONSTRAINT",
4055                                        Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
4056                                        "implementationDependencyFinalDependencyConstraint",
4057                                        implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
4058                                        override.getName(), a.getIdentifier(), moduleOfA.getName(),
4059                                        getNodePathString( overriddenDependency ) );
4060 
4061                         }
4062 
4063                         if ( effectiveDependencyOverridden )
4064                         {
4065                             for ( final InheritanceModel.Node<Dependency> node : effDependencies )
4066                             {
4067                                 final Dependency overridden = node.getModelObject();
4068 
4069                                 final Specification overrideSpecification =
4070                                     validationContext.getSpecification( override.getIdentifier() );
4071 
4072                                 final Specification overriddenSpecification =
4073                                     validationContext.getSpecification( overridden.getIdentifier() );
4074 
4075                                 if ( overrideSpecification != null && overriddenSpecification != null )
4076                                 {
4077                                     if ( overrideSpecification.getMultiplicity()
4078                                              != overriddenSpecification.getMultiplicity() )
4079                                     {
4080                                         addDetail( validationContext.getReport(),
4081                                                    "IMPLEMENTATION_DEPENDENCY_MULTIPLICITY_CONSTRAINT",
4082                                                    Level.SEVERE,
4083                                                    new ObjectFactory().createImplementation( implementation ),
4084                                                    "implementationDependencyMultiplicityConstraint",
4085                                                    implementation.getIdentifier(), moduleOfImpl.getName(),
4086                                                    dependency.getName(), overridden.getName(),
4087                                                    a.getIdentifier(), moduleOfA.getName(),
4088                                                    overrideSpecification.getMultiplicity().value(),
4089                                                    overriddenSpecification.getMultiplicity().value() );
4090 
4091                                     }
4092 
4093                                     if ( overrideSpecification.getScope() != null
4094                                              ? !overrideSpecification.getScope().equals(
4095                                             overriddenSpecification.getScope() )
4096                                              : overriddenSpecification.getScope() != null )
4097                                     {
4098                                         addDetail( validationContext.getReport(),
4099                                                    "IMPLEMENTATION_DEPENDENCY_SCOPE_CONSTRAINT", Level.SEVERE,
4100                                                    new ObjectFactory().createImplementation( implementation ),
4101                                                    "implementationDependencyScopeConstraint",
4102                                                    implementation.getIdentifier(), moduleOfImpl.getName(),
4103                                                    dependency.getName(), override.getName(),
4104                                                    a.getIdentifier(), moduleOfA.getName(),
4105                                                    overrideSpecification.getScope() == null
4106                                                        ? "Multiton" : overrideSpecification.getScope(),
4107                                                    overriddenSpecification.getScope() == null
4108                                                        ? "Multiton" : overriddenSpecification.getScope() );
4109 
4110                                     }
4111 
4112                                     if ( overriddenSpecification.getMultiplicity() == Multiplicity.MANY )
4113                                     {
4114                                         if ( override.getImplementationName() == null
4115                                                  && overridden.getImplementationName() != null )
4116                                         {
4117                                             addDetail( validationContext.getReport(),
4118                                                        "IMPLEMENTATION_DEPENDENCY_NO_IMPLEMENTATION_NAME_CONSTRAINT",
4119                                                        Level.SEVERE,
4120                                                        new ObjectFactory().createImplementation( implementation ),
4121                                                        "implementationDependencyNoImplementationNameConstraint",
4122                                                        implementation.getIdentifier(), moduleOfImpl.getName(),
4123                                                        dependency.getName(), override.getName(),
4124                                                        a.getIdentifier(), moduleOfA.getName() );
4125 
4126                                         }
4127 
4128                                         if ( override.getImplementationName() != null
4129                                                  && overridden.getImplementationName() == null )
4130                                         {
4131                                             addDetail( validationContext.getReport(),
4132                                                        "IMPLEMENTATION_DEPENDENCY_IMPLEMENTATION_NAME_CONSTRAINT",
4133                                                        Level.SEVERE,
4134                                                        new ObjectFactory().createImplementation( implementation ),
4135                                                        "implementationDependencyImplementationNameConstraint",
4136                                                        implementation.getIdentifier(), moduleOfImpl.getName(),
4137                                                        dependency.getName(), overridden.getName(),
4138                                                        a.getIdentifier(), moduleOfA.getName(),
4139                                                        override.getImplementationName() );
4140 
4141                                         }
4142                                     }
4143                                 }
4144 
4145                                 if ( override.isOptional() != overridden.isOptional() )
4146                                 {
4147                                     addDetail( validationContext.getReport(),
4148                                                "IMPLEMENTATION_DEPENDENCY_OPTIONALITY_CONSTRAINT", Level.SEVERE,
4149                                                new ObjectFactory().createImplementation( implementation ),
4150                                                "implementationDependencyOptonalityConstraint",
4151                                                implementation.getIdentifier(), moduleOfImpl.getName(),
4152                                                dependency.getName(), overridden.getName(),
4153                                                a.getIdentifier(), moduleOfA.getName() );
4154 
4155                                 }
4156                             }
4157                         }
4158                     }
4159                 }
4160 
4161                 if ( dependency.getMessages() != null )
4162                 {
4163                     for ( int j = 0, s1 = dependency.getMessages().getMessage().size(); j < s1; j++ )
4164                     {
4165                         final Message override = dependency.getMessages().getMessage().get( j );
4166 
4167                         final Set<InheritanceModel.Node<Message>> overriddenMessages =
4168                             modifiableSet( imodel.getMessageNodes( a.getIdentifier(), override.getName() ) );
4169 
4170                         if ( override.isOverride() && overriddenMessages.isEmpty() )
4171                         {
4172                             addDetail( validationContext.getReport(),
4173                                        "IMPLEMENTATION_DEPENDENCY_OVERRIDE_MESSAGE_CONSTRAINT", Level.SEVERE,
4174                                        new ObjectFactory().createImplementation( implementation ),
4175                                        "implementationDependencyOverrideMessageConstraint",
4176                                        implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
4177                                        override.getName(), a.getIdentifier(), moduleOfA.getName() );
4178 
4179                         }
4180 
4181                         if ( !( override.isOverride() || overriddenMessages.isEmpty() ) )
4182                         {
4183                             for ( final InheritanceModel.Node<Message> overriddenMessage : overriddenMessages )
4184                             {
4185                                 addDetail( validationContext.getReport(),
4186                                            "IMPLEMENTATION_DEPENDENCY_OVERRIDE_MESSAGE_WARNING", Level.WARNING,
4187                                            new ObjectFactory().createImplementation( implementation ),
4188                                            "implementationDependencyOverrideMessageWarning",
4189                                            implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
4190                                            override.getName(), a.getIdentifier(), moduleOfA.getName(),
4191                                            getNodePathString( overriddenMessage ) );
4192 
4193                             }
4194                         }
4195 
4196                         retainFinalNodes( overriddenMessages );
4197 
4198                         for ( final InheritanceModel.Node<Message> overriddenMessage : overriddenMessages )
4199                         {
4200                             addDetail( validationContext.getReport(),
4201                                        "IMPLEMENTATION_DEPENDENCY_FINAL_MESSAGE_CONSTRAINT", Level.SEVERE,
4202                                        new ObjectFactory().createImplementation( implementation ),
4203                                        "implementationDependencyFinalMessageConstraint",
4204                                        implementation.getIdentifier(), moduleOfImpl.getName(),
4205                                        dependency.getName(), override.getName(), a.getIdentifier(),
4206                                        moduleOfA.getName(), getNodePathString( overriddenMessage ) );
4207 
4208                         }
4209                     }
4210                 }
4211 
4212                 if ( dependency.getProperties() != null )
4213                 {
4214                     for ( int j = 0, s1 = dependency.getProperties().getProperty().size(); j < s1; j++ )
4215                     {
4216                         final Property override = dependency.getProperties().getProperty().get( j );
4217 
4218                         final Set<InheritanceModel.Node<Property>> overriddenProperties =
4219                             modifiableSet( imodel.getPropertyNodes( a.getIdentifier(), override.getName() ) );
4220 
4221                         if ( override.isOverride() && overriddenProperties.isEmpty() )
4222                         {
4223                             addDetail( validationContext.getReport(),
4224                                        "IMPLEMENTATION_DEPENDENCY_OVERRIDE_PROPERTY_CONSTRAINT", Level.SEVERE,
4225                                        new ObjectFactory().createImplementation( implementation ),
4226                                        "implementationDependencyOverridePropertyConstraint",
4227                                        implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
4228                                        override.getName(), a.getIdentifier(), moduleOfA.getName() );
4229 
4230                         }
4231 
4232                         if ( !( override.isOverride() || overriddenProperties.isEmpty() ) )
4233                         {
4234                             for ( final InheritanceModel.Node<Property> overriddenProperty : overriddenProperties )
4235                             {
4236                                 addDetail( validationContext.getReport(),
4237                                            "IMPLEMENTATION_DEPENDENCY_OVERRIDE_PROPERTY_WARNING", Level.WARNING,
4238                                            new ObjectFactory().createImplementation( implementation ),
4239                                            "implementationDependencyOverridePropertyWarning",
4240                                            implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
4241                                            override.getName(), a.getIdentifier(), moduleOfA.getName(),
4242                                            getNodePathString( overriddenProperty ) );
4243 
4244                             }
4245                         }
4246 
4247                         retainFinalNodes( overriddenProperties );
4248 
4249                         for ( final InheritanceModel.Node<Property> overriddenProperty : overriddenProperties )
4250                         {
4251                             addDetail( validationContext.getReport(),
4252                                        "IMPLEMENTATION_DEPENDENCY_FINAL_PROPERTY_CONSTRAINT", Level.SEVERE,
4253                                        new ObjectFactory().createImplementation( implementation ),
4254                                        "implementationDependencyFinalPropertyConstraint",
4255                                        implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
4256                                        override.getName(), a.getIdentifier(), moduleOfA.getName(),
4257                                        getNodePathString( overriddenProperty ) );
4258 
4259                         }
4260                     }
4261                 }
4262             }
4263         }
4264 
4265         if ( dependency.getDependencies() != null )
4266         {
4267             for ( int i = 0, s0 = dependency.getDependencies().getDependency().size(); i < s0; i++ )
4268             {
4269                 final Dependency d = dependency.getDependencies().getDependency().get( i );
4270 
4271                 if ( validationContext.isValidateJava() )
4272                 {
4273                     try
4274                     {
4275                         d.getJavaConstantName();
4276                     }
4277                     catch ( final ModelObjectException e )
4278                     {
4279                         final String message = getMessage( e );
4280 
4281                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
4282                         {
4283                             validationContext.getModelContext().log( Level.FINE, message, e );
4284                         }
4285 
4286                         addDetail( validationContext.getReport(),
4287                                    "IMPLEMENTATION_DEPENDENCY_DEPENDENCY_JAVA_CONSTANT_NAME_CONSTRAINT", Level.SEVERE,
4288                                    new ObjectFactory().createImplementation( implementation ),
4289                                    "implementationDependencyDependencyJavaConstantNameConstraint",
4290                                    implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
4291                                    d.getName(), message != null && message.length() > 0 ? " " + message : "" );
4292 
4293                     }
4294 
4295                     try
4296                     {
4297                         d.getJavaGetterMethodName();
4298                     }
4299                     catch ( final ModelObjectException e )
4300                     {
4301                         final String message = getMessage( e );
4302 
4303                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
4304                         {
4305                             validationContext.getModelContext().log( Level.FINE, message, e );
4306                         }
4307 
4308                         addDetail( validationContext.getReport(),
4309                                    "IMPLEMENTATION_DEPENDENCY_DEPENDENCY_JAVA_GETTER_METHOD_NAME_CONSTRAINT",
4310                                    Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
4311                                    "implementationDependencyDependencyJavaGetterMethodNameConstraint",
4312                                    implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
4313                                    d.getName(), message != null && message.length() > 0 ? " " + message : "" );
4314 
4315                     }
4316 
4317                     try
4318                     {
4319                         d.getJavaSetterMethodName();
4320                     }
4321                     catch ( final ModelObjectException e )
4322                     {
4323                         final String message = getMessage( e );
4324 
4325                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
4326                         {
4327                             validationContext.getModelContext().log( Level.FINE, message, e );
4328                         }
4329 
4330                         addDetail( validationContext.getReport(),
4331                                    "IMPLEMENTATION_DEPENDENCY_DEPENDENCY_JAVA_SETTER_METHOD_NAME_CONSTRAINT",
4332                                    Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
4333                                    "implementationDependencyDependencyJavaSetterMethodNameConstraint",
4334                                    implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
4335                                    d.getName(), message != null && message.length() > 0 ? " " + message : "" );
4336 
4337                     }
4338 
4339                     try
4340                     {
4341                         d.getJavaVariableName();
4342                     }
4343                     catch ( final ModelObjectException e )
4344                     {
4345                         final String message = getMessage( e );
4346 
4347                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
4348                         {
4349                             validationContext.getModelContext().log( Level.FINE, message, e );
4350                         }
4351 
4352                         addDetail( validationContext.getReport(),
4353                                    "IMPLEMENTATION_DEPENDENCY_DEPENDENCY_JAVA_VARIABLE_NAME_CONSTRAINT",
4354                                    Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
4355                                    "implementationDependencyDependencyJavaVariableNameConstraint",
4356                                    implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
4357                                    d.getName(), message != null && message.length() > 0 ? " " + message : "" );
4358 
4359                     }
4360                 }
4361 
4362                 assertDependencyValid( validationContext, implementation, d );
4363             }
4364         }
4365     }
4366 
4367     private static void assertImplementationSpecificationCompatibility(
4368         final ValidationContext validationContext, final Implementation implementation )
4369     {
4370         final Specifications specs = validationContext.getSpecifications( implementation.getIdentifier() );
4371         final Module moduleOfImpl =
4372             validationContext.getModuleOfImplementation( implementation.getIdentifier() );
4373 
4374         if ( specs != null )
4375         {
4376             for ( int i = 0, s0 = specs.getReference().size(); i < s0; i++ )
4377             {
4378                 final SpecificationReference r = specs.getReference().get( i );
4379                 final Specification s = specs.getSpecification( r.getIdentifier() );
4380 
4381                 if ( s != null && r.getVersion() != null )
4382                 {
4383                     final Module moduleOfS =
4384                         validationContext.getModuleOfSpecification( s.getIdentifier() );
4385 
4386                     if ( s.getVersion() == null )
4387                     {
4388                         addDetail( validationContext.getReport(),
4389                                    "IMPLEMENTATION_SPECIFICATION_VERSIONING_CONSTRAINT", Level.SEVERE,
4390                                    new ObjectFactory().createImplementation( implementation ),
4391                                    "implementationSpecificationVersioningConstraint", implementation.getIdentifier(),
4392                                    moduleOfImpl.getName(), s.getIdentifier(), moduleOfS.getName() );
4393 
4394                     }
4395                     else
4396                     {
4397                         try
4398                         {
4399                             if ( VersionParser.compare( r.getVersion(), s.getVersion() ) != 0 )
4400                             {
4401                                 addDetail( validationContext.getReport(),
4402                                            "IMPLEMENTATION_SPECIFICATION_COMPATIBILITY_CONSTRAINT", Level.SEVERE,
4403                                            new ObjectFactory().createImplementation( implementation ),
4404                                            "implementationSpecificationCompatibilityConstraint",
4405                                            implementation.getIdentifier(), moduleOfImpl.getName(), s.getIdentifier(),
4406                                            moduleOfS.getName(), r.getVersion(), s.getVersion() );
4407 
4408                             }
4409                         }
4410                         catch ( final ParseException e )
4411                         {
4412                             final String message = getMessage( e );
4413 
4414                             if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
4415                             {
4416                                 validationContext.getModelContext().log( Level.FINE, message, e );
4417                             }
4418 
4419                             addDetail( validationContext.getReport(),
4420                                        "IMPLEMENTATION_SPECIFICATION_COMPATIBILITY_VERSIONING_PARSE_EXCEPTION",
4421                                        Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
4422                                        "implementationSpecificationCompatibilityVersioningParseException",
4423                                        implementation.getIdentifier(), moduleOfImpl.getName(), s.getIdentifier(),
4424                                        moduleOfS.getName(), r.getVersion(),
4425                                        message != null && message.length() > 0 ? " " + message : "" );
4426 
4427                         }
4428                         catch ( final TokenMgrError e )
4429                         {
4430                             final String message = getMessage( e );
4431 
4432                             if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
4433                             {
4434                                 validationContext.getModelContext().log( Level.FINE, message, e );
4435                             }
4436 
4437                             addDetail( validationContext.getReport(),
4438                                        "IMPLEMENTATION_SPECIFICATION_COMPATIBILITY_VERSIONING_TOKEN_MANAGER_ERROR",
4439                                        Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
4440                                        "implementationSpecificationCompatibilityVersioningTokenManagerError",
4441                                        implementation.getIdentifier(), moduleOfImpl.getName(), s.getIdentifier(),
4442                                        moduleOfS.getName(), r.getVersion(),
4443                                        message != null && message.length() > 0 ? " " + message : "" );
4444 
4445                         }
4446                     }
4447                 }
4448             }
4449         }
4450     }
4451 
4452     private static <T> String getNodePathString( final InheritanceModel.Node<T> node )
4453     {
4454         final StringBuilder b = new StringBuilder( node.getPath().size() * 50 );
4455 
4456         for ( int i = 0, s0 = node.getPath().size(); i < s0; i++ )
4457         {
4458             final InheritanceModel.Node<Implementation> pathNode = node.getPath().get( i );
4459 
4460             if ( pathNode.getClassDeclaration() != null )
4461             {
4462                 b.append( " -> [" ).append( pathNode.getClassDeclaration().getClazz() ).append( "] @ '" ).
4463                     append( pathNode.getImplementation().getIdentifier() ).append( "'" );
4464 
4465             }
4466             if ( pathNode.getSpecification() != null )
4467             {
4468                 b.append( " -> <" ).append( pathNode.getSpecification().getIdentifier() ).append( "> @ '" ).
4469                     append( pathNode.getImplementation().getIdentifier() ).append( "'" );
4470 
4471             }
4472             else
4473             {
4474                 b.append( " -> '" ).append( pathNode.getImplementation().getIdentifier() ).append( "'" );
4475             }
4476         }
4477 
4478         if ( node.getClassDeclaration() != null )
4479         {
4480             b.append( " -> [" ).append( node.getClassDeclaration().getClazz() ).append( "] @ '" ).
4481                 append( node.getImplementation().getIdentifier() ).append( "'" );
4482 
4483         }
4484         if ( node.getSpecification() != null )
4485         {
4486             b.append( " -> <" ).append( node.getSpecification().getIdentifier() ).append( "> @ '" ).
4487                 append( node.getImplementation().getIdentifier() ).append( "'" );
4488 
4489         }
4490 
4491         return b.length() > 0 ? b.substring( " -> ".length() ) : b.toString();
4492     }
4493 
4494     private static <T> String getNodeListPathString( final Collection<? extends InheritanceModel.Node<T>> nodes )
4495     {
4496         final StringBuilder path = new StringBuilder( nodes.size() * 255 );
4497 
4498         for ( final InheritanceModel.Node<T> node : nodes )
4499         {
4500             path.append( ", " ).append( getNodePathString( node ) );
4501         }
4502 
4503         return path.length() > 1 ? path.substring( 2 ) : path.toString();
4504     }
4505 
4506     private static <T> Set<InheritanceModel.Node<T>> retainFinalNodes( final Set<InheritanceModel.Node<T>> set )
4507     {
4508         if ( set != null )
4509         {
4510             for ( final Iterator<InheritanceModel.Node<T>> it = set.iterator(); it.hasNext(); )
4511             {
4512                 if ( !it.next().isFinal() )
4513                 {
4514                     it.remove();
4515                 }
4516             }
4517         }
4518 
4519         return set;
4520     }
4521 
4522     private static void addDetail(
4523         final ModelValidationReport report, final String identifier, final Level level,
4524         final JAXBElement<? extends ModelObject> element, final String messageKey, final Object... messageArguments )
4525     {
4526         report.getDetails().add( new ModelValidationReport.Detail(
4527             identifier, level, getMessage( messageKey, messageArguments ), element ) );
4528 
4529     }
4530 
4531     private static <T> Set<T> modifiableSet( final Collection<? extends T> col )
4532     {
4533         Set<T> set = Collections.emptySet();
4534 
4535         if ( col != null )
4536         {
4537             set = new HashSet<T>( col );
4538         }
4539 
4540         return set;
4541     }
4542 
4543     private static String getMessage( final String key, final Object... messageArguments )
4544     {
4545         return MessageFormat.format( ResourceBundle.getBundle(
4546             DefaultModelValidator.class.getName(), Locale.getDefault() ).getString( key ), messageArguments );
4547 
4548     }
4549 
4550     private static String getMessage( final Throwable t )
4551     {
4552         return t != null
4553                    ? t.getMessage() != null && t.getMessage().trim().length() > 0
4554                          ? t.getMessage()
4555                          : getMessage( t.getCause() )
4556                    : null;
4557 
4558     }
4559 
4560     /**
4561      * @since 1.2
4562      */
4563     private static final class ValidationContext
4564     {
4565 
4566         private final ModelContext modelContext;
4567 
4568         private final Modules modules;
4569 
4570         private final ModelValidationReport report;
4571 
4572         private final InheritanceModel inheritanceModel;
4573 
4574         private final boolean validateJava;
4575 
4576         private final Specifications allSpecifications;
4577 
4578         private final Implementations allImplementations;
4579 
4580         private final Map<String, Specification> specifications = new HashMap<String, Specification>( 128 );
4581 
4582         private final Map<String, Specifications> specificationsByImplementation =
4583             new HashMap<String, Specifications>( 128 );
4584 
4585         private final Map<String, Module> modulesOfSpecifications = new HashMap<String, Module>( 128 );
4586 
4587         private final Map<String, Implementation> implementations = new HashMap<String, Implementation>();
4588 
4589         private final Map<String, Implementations> implementationsBySpecification =
4590             new HashMap<String, Implementations>( 128 );
4591 
4592         private final Map<String, Module> modulesOfImplementations = new HashMap<String, Module>( 128 );
4593 
4594         private ValidationContext( final ModelContext modelContext, final Modules modules,
4595                                    final ModelValidationReport report, final boolean validateJava )
4596         {
4597             super();
4598             this.modelContext = modelContext;
4599             this.modules = modules;
4600             this.report = report;
4601             this.inheritanceModel = new InheritanceModel( modules );
4602             this.validateJava = validateJava;
4603             this.allImplementations = modules.getImplementations();
4604             this.allSpecifications = modules.getSpecifications();
4605 
4606             if ( this.allSpecifications != null )
4607             {
4608                 for ( final Specification s : this.allSpecifications.getSpecification() )
4609                 {
4610                     this.specifications.put( s.getIdentifier(), s );
4611                     this.implementationsBySpecification.put(
4612                         s.getIdentifier(), modules.getImplementations( s.getIdentifier() ) );
4613 
4614                     this.modulesOfSpecifications.put(
4615                         s.getIdentifier(), modules.getModuleOfSpecification( s.getIdentifier() ) );
4616 
4617                 }
4618             }
4619 
4620             if ( this.allImplementations != null )
4621             {
4622                 for ( final Implementation i : this.allImplementations.getImplementation() )
4623                 {
4624                     this.implementations.put( i.getIdentifier(), i );
4625                     this.specificationsByImplementation.put(
4626                         i.getIdentifier(), modules.getSpecifications( i.getIdentifier() ) );
4627 
4628                     this.modulesOfImplementations.put(
4629                         i.getIdentifier(), modules.getModuleOfImplementation( i.getIdentifier() ) );
4630                 }
4631             }
4632         }
4633 
4634         private ModelContext getModelContext()
4635         {
4636             return modelContext;
4637         }
4638 
4639         private Modules getModules()
4640         {
4641             return modules;
4642         }
4643 
4644         private ModelValidationReport getReport()
4645         {
4646             return report;
4647         }
4648 
4649         private InheritanceModel getInheritanceModel()
4650         {
4651             return this.inheritanceModel;
4652         }
4653 
4654         private boolean isValidateJava()
4655         {
4656             return this.validateJava;
4657         }
4658 
4659         private Specifications getAllSpecifications()
4660         {
4661             return this.allSpecifications;
4662         }
4663 
4664         private Implementations getAllImplementations()
4665         {
4666             return this.allImplementations;
4667         }
4668 
4669         private Specification getSpecification( final String identifier )
4670         {
4671             return this.specifications.get( identifier );
4672         }
4673 
4674         private Specifications getSpecifications( final String implementation )
4675         {
4676             return this.specificationsByImplementation.get( implementation );
4677         }
4678 
4679         private Implementation getImplementation( final String identifier )
4680         {
4681             return this.implementations.get( identifier );
4682         }
4683 
4684         private Implementations getImplementations( final String specification )
4685         {
4686             return this.implementationsBySpecification.get( specification );
4687         }
4688 
4689         private Module getModuleOfSpecification( final String identifier )
4690         {
4691             return this.modulesOfSpecifications.get( identifier );
4692         }
4693 
4694         private Module getModuleOfImplementation( final String identifier )
4695         {
4696             return this.modulesOfImplementations.get( identifier );
4697         }
4698 
4699     }
4700 
4701 }