View Javadoc

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