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 4426 2012-03-14 09:11:54Z schulte2005 $
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.Dependency;
52  import org.jomc.model.Implementation;
53  import org.jomc.model.ImplementationReference;
54  import org.jomc.model.Implementations;
55  import org.jomc.model.Inheritable;
56  import org.jomc.model.InheritanceModel;
57  import org.jomc.model.Message;
58  import org.jomc.model.MessageReference;
59  import org.jomc.model.ModelObject;
60  import org.jomc.model.Module;
61  import org.jomc.model.Modules;
62  import org.jomc.model.Multiplicity;
63  import org.jomc.model.ObjectFactory;
64  import org.jomc.model.Property;
65  import org.jomc.model.PropertyException;
66  import org.jomc.model.PropertyReference;
67  import org.jomc.model.Specification;
68  import org.jomc.model.SpecificationReference;
69  import org.jomc.model.Specifications;
70  import org.jomc.model.Text;
71  import org.jomc.modlet.Model;
72  import org.jomc.modlet.ModelContext;
73  import org.jomc.modlet.ModelException;
74  import org.jomc.modlet.ModelValidationReport;
75  import org.jomc.modlet.ModelValidator;
76  import org.jomc.util.ParseException;
77  import org.jomc.util.TokenMgrError;
78  import org.jomc.util.VersionParser;
79  import org.w3c.dom.Element;
80  
81  /**
82   * Default object management and configuration {@code ModelValidator} implementation.
83   *
84   * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a>
85   * @version $JOMC: DefaultModelValidator.java 4426 2012-03-14 09:11:54Z schulte2005 $
86   * @see ModelContext#validateModel(org.jomc.modlet.Model)
87   */
88  public class DefaultModelValidator implements ModelValidator
89  {
90  
91      /** Creates a new {@code DefaultModelValidator} instance. */
92      public DefaultModelValidator()
93      {
94          super();
95      }
96  
97      public ModelValidationReport validateModel( final ModelContext context, final Model model ) throws ModelException
98      {
99          if ( context == null )
100         {
101             throw new NullPointerException( "context" );
102         }
103         if ( model == null )
104         {
105             throw new NullPointerException( "model" );
106         }
107 
108         try
109         {
110             final Source source = new JAXBSource( context.createContext( model.getIdentifier() ),
111                                                   new org.jomc.modlet.ObjectFactory().createModel( model ) );
112 
113             final ModelValidationReport report = context.validateModel( model.getIdentifier(), source );
114             final Modules modules = ModelHelper.getModules( model );
115 
116             if ( modules != null )
117             {
118                 final ValidationContext validationContext = new ValidationContext( context, modules, report );
119                 assertModulesValid( validationContext );
120                 assertSpecificationsValid( validationContext );
121                 assertImplementationsValid( validationContext );
122             }
123 
124             return report;
125         }
126         catch ( final JAXBException e )
127         {
128             String message = getMessage( e );
129             if ( message == null && e.getLinkedException() != null )
130             {
131                 message = getMessage( e.getLinkedException() );
132             }
133 
134             if ( context.isLoggable( Level.FINE ) )
135             {
136                 context.log( Level.FINE, message, e );
137             }
138 
139             throw new ModelException( message, e );
140         }
141     }
142 
143     private static void assertModulesValid( final ValidationContext validationContext )
144     {
145         for ( int i = 0, s0 = validationContext.getModules().getModule().size(); i < s0; i++ )
146         {
147             final Module m = validationContext.getModules().getModule().get( i );
148 
149             if ( m.getImplementations() != null )
150             {
151                 for ( int j = 0, s1 = m.getImplementations().getReference().size(); j < s1; j++ )
152                 {
153                     final ImplementationReference r = m.getImplementations().getReference().get( j );
154                     addDetail( validationContext.getReport(), "MODULE_IMPLEMENTATION_REFERENCE_DECLARATION_CONSTRAINT",
155                                Level.SEVERE, new ObjectFactory().createModule( m ),
156                                "moduleImplementationReferenceDeclarationConstraint", m.getName(), r.getIdentifier() );
157 
158                 }
159             }
160 
161             if ( m.getMessages() != null )
162             {
163                 for ( int j = 0, s1 = m.getMessages().getMessage().size(); j < s1; j++ )
164                 {
165                     final Message msg = m.getMessages().getMessage().get( j );
166 
167                     if ( msg.isFinal() )
168                     {
169                         addDetail( validationContext.getReport(), "MODULE_FINAL_MESSAGE_DECLARATION_CONSTRAINT",
170                                    Level.SEVERE, new ObjectFactory().createModule( m ), "moduleFinalMessageConstraint",
171                                    m.getName(), msg.getName() );
172 
173                     }
174 
175                     if ( msg.isOverride() )
176                     {
177                         addDetail( validationContext.getReport(), "MODULE_OVERRIDE_MESSAGE_DECLARATION_CONSTRAINT",
178                                    Level.SEVERE, new ObjectFactory().createModule( m ),
179                                    "moduleOverrideMessageConstraint", m.getName(), msg.getName() );
180 
181                     }
182 
183                     if ( msg.getTemplate() != null )
184                     {
185                         for ( int k = 0, s2 = msg.getTemplate().getText().size(); k < s2; k++ )
186                         {
187                             final Text t = msg.getTemplate().getText().get( k );
188 
189                             try
190                             {
191                                 new MessageFormat( t.getValue(), new Locale( t.getLanguage() ) );
192                             }
193                             catch ( final IllegalArgumentException e )
194                             {
195                                 final String message = getMessage( e );
196 
197                                 if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
198                                 {
199                                     validationContext.getModelContext().log( Level.FINE, message, e );
200                                 }
201 
202                                 addDetail( validationContext.getReport(), "MODULE_MESSAGE_TEMPLATE_CONSTRAINT",
203                                            Level.SEVERE, new ObjectFactory().createModule( m ),
204                                            "moduleMessageTemplateConstraint", m.getName(), msg.getName(), t.getValue(),
205                                            message );
206 
207                             }
208                         }
209                     }
210                 }
211 
212                 for ( int j = 0, s1 = m.getMessages().getReference().size(); j < s1; j++ )
213                 {
214                     final MessageReference r = m.getMessages().getReference().get( j );
215                     addDetail( validationContext.getReport(), "MODULE_MESSAGE_REFERENCE_DECLARATION_CONSTRAINT",
216                                Level.SEVERE, new ObjectFactory().createModule( m ),
217                                "moduleMessageReferenceDeclarationConstraint", m.getName(), r.getName() );
218 
219                 }
220             }
221 
222             if ( m.getProperties() != null )
223             {
224                 for ( int j = 0, s1 = m.getProperties().getProperty().size(); j < s1; j++ )
225                 {
226                     final Property p = m.getProperties().getProperty().get( j );
227 
228                     if ( p.isFinal() )
229                     {
230                         addDetail( validationContext.getReport(), "MODULE_FINAL_PROPERTY_DECLARATION_CONSTRAINT",
231                                    Level.SEVERE, new ObjectFactory().createModule( m ), "moduleFinalPropertyConstraint",
232                                    m.getName(), p.getName() );
233 
234                     }
235 
236                     if ( p.isOverride() )
237                     {
238                         addDetail( validationContext.getReport(), "MODULE_OVERRIDE_PROPERTY_DECLARATION_CONSTRAINT",
239                                    Level.SEVERE, new ObjectFactory().createModule( m ),
240                                    "moduleOverridePropertyConstraint", m.getName(), p.getName() );
241 
242                     }
243 
244                     if ( p.getValue() != null && p.getAny() != null )
245                     {
246                         addDetail( validationContext.getReport(), "MODULE_PROPERTY_VALUE_CONSTRAINT", Level.SEVERE,
247                                    new ObjectFactory().createModule( m ), "modulePropertyValueConstraint", m.getName(),
248                                    p.getName() );
249 
250                     }
251 
252                     if ( p.getAny() != null && p.getType() == null )
253                     {
254                         addDetail( validationContext.getReport(), "MODULE_PROPERTY_TYPE_CONSTRAINT", Level.SEVERE,
255                                    new ObjectFactory().createModule( m ), "modulePropertyTypeConstraint", m.getName(),
256                                    p.getName() );
257 
258                     }
259 
260                     try
261                     {
262                         p.getJavaValue( validationContext.getModelContext().getClassLoader() );
263                     }
264                     catch ( final PropertyException e )
265                     {
266                         final String message = getMessage( e );
267 
268                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
269                         {
270                             validationContext.getModelContext().log( Level.FINE, message, e );
271                         }
272 
273                         addDetail( validationContext.getReport(), "MODULE_PROPERTY_JAVA_VALUE_CONSTRAINT", Level.SEVERE,
274                                    new ObjectFactory().createModule( m ), "modulePropertyJavaValueConstraint",
275                                    m.getName(), p.getName(), message );
276 
277                     }
278                 }
279 
280                 for ( int j = 0, s1 = m.getProperties().getReference().size(); j < s1; j++ )
281                 {
282                     final PropertyReference r = m.getProperties().getReference().get( j );
283                     addDetail( validationContext.getReport(), "MODULE_PROPERTY_REFERENCE_DECLARATION_CONSTRAINT",
284                                Level.SEVERE, new ObjectFactory().createModule( m ),
285                                "modulePropertyReferenceDeclarationConstraint", m.getName(), r.getName() );
286 
287                 }
288             }
289 
290             if ( m.getSpecifications() != null )
291             {
292                 for ( int j = 0, s1 = m.getSpecifications().getReference().size(); j < s1; j++ )
293                 {
294                     final SpecificationReference r = m.getSpecifications().getReference().get( j );
295                     addDetail( validationContext.getReport(), "MODULE_SPECIFICATION_REFERENCE_DECLARATION_CONSTRAINT",
296                                Level.SEVERE, new ObjectFactory().createModule( m ),
297                                "moduleSpecificationReferenceDeclarationConstraint", m.getName(), r.getIdentifier() );
298 
299                 }
300             }
301         }
302     }
303 
304     private static void assertImplementationsValid( final ValidationContext validationContext )
305     {
306         final Implementations implementations = validationContext.getModules().getImplementations();
307 
308         if ( implementations != null )
309         {
310             final Map<String, Implementation> implementationClassDeclarations = new HashMap<String, Implementation>();
311 
312             for ( int i = 0, s0 = implementations.getImplementation().size(); i < s0; i++ )
313             {
314                 final Implementation impl = implementations.getImplementation().get( i );
315                 final InheritanceModel imodel = validationContext.getInheritanceModel();
316                 final List<String> cyclePath = new LinkedList<String>();
317                 final Module moduleOfImpl =
318                     validationContext.getModules().getModuleOfImplementation( impl.getIdentifier() );
319 
320                 if ( isInheritanceCycle( validationContext, impl, null, cyclePath ) )
321                 {
322                     final StringBuilder b = new StringBuilder( cyclePath.size() * 50 );
323 
324                     for ( int j = 0, s1 = cyclePath.size(); j < s1; j++ )
325                     {
326                         b.append( " -> " ).append( "'" ).append( cyclePath.get( j ) ).append( "'" );
327                     }
328 
329                     addDetail( validationContext.getReport(), "IMPLEMENTATION_INHERITANCE_CYCLE_CONSTRAINT",
330                                Level.SEVERE, new ObjectFactory().createImplementation( impl ),
331                                "implementationInheritanceCycleConstraint", impl.getIdentifier(),
332                                moduleOfImpl.getName(), b.substring( " -> ".length() ) );
333 
334                 }
335 
336                 if ( impl.isClassDeclaration() )
337                 {
338                     if ( impl.getClazz() == null )
339                     {
340                         addDetail( validationContext.getReport(), "IMPLEMENTATION_CLASS_CONSTRAINT", Level.SEVERE,
341                                    new ObjectFactory().createImplementation( impl ), "implementationClassConstraint",
342                                    impl.getIdentifier(), moduleOfImpl.getName() );
343 
344                     }
345                     else
346                     {
347                         final Implementation prev = implementationClassDeclarations.get( impl.getClazz() );
348 
349                         if ( prev != null && !prev.getIdentifier().equals( impl.getIdentifier() ) )
350                         {
351                             final Module moduleOfPrev =
352                                 validationContext.getModules().getModuleOfImplementation( prev.getIdentifier() );
353 
354                             addDetail( validationContext.getReport(), "IMPLEMENTATION_CLASS_DECLARATION_CONSTRAINT",
355                                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
356                                        "implementationClassDeclarationConstraint", impl.getIdentifier(),
357                                        moduleOfImpl.getName(), impl.getClazz(), prev.getIdentifier(),
358                                        moduleOfPrev.getName() );
359 
360                         }
361                         else
362                         {
363                             implementationClassDeclarations.put( impl.getClazz(), impl );
364                         }
365                     }
366                 }
367 
368                 if ( impl.isAbstract() && impl.getLocation() != null )
369                 {
370                     addDetail( validationContext.getReport(), "IMPLEMENTATION_ABSTRACT_LOCATION_DECLARATION_CONSTRAINT",
371                                Level.SEVERE, new ObjectFactory().createImplementation( impl ),
372                                "implementationAbstractLocationDeclarationConstraint", impl.getIdentifier(),
373                                moduleOfImpl.getName(), impl.getLocation() );
374 
375                 }
376 
377                 if ( impl.getDependencies() != null )
378                 {
379                     for ( int j = 0, s1 = impl.getDependencies().getDependency().size(); j < s1; j++ )
380                     {
381                         final Dependency d = impl.getDependencies().getDependency().get( j );
382 
383                         final Set<InheritanceModel.Node<Dependency>> effDependencies =
384                             imodel.getDependencyNodes( impl.getIdentifier(), d.getName() );
385 
386                         for ( final InheritanceModel.Node<Dependency> effDependency : effDependencies )
387                         {
388                             final Set<InheritanceModel.Node<Dependency>> overriddenDependencies =
389                                 modifiableSet( effDependency.getOverriddenNodes() );
390 
391                             if ( d.isOverride() && effDependency.getOverriddenNodes().isEmpty() )
392                             {
393                                 addDetail( validationContext.getReport(),
394                                            "IMPLEMENTATION_DEPENDENCY_OVERRIDE_CONSTRAINT",
395                                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
396                                            "implementationDependencyOverrideConstraint", impl.getIdentifier(),
397                                            moduleOfImpl.getName(), d.getName() );
398 
399                             }
400 
401                             if ( !( d.isOverride() || overriddenDependencies.isEmpty() ) )
402                             {
403                                 for ( final InheritanceModel.Node<Dependency> overriddenDependency :
404                                       overriddenDependencies )
405                                 {
406                                     Implementation overriddenImplementation = overriddenDependency.getImplementation();
407                                     if ( overriddenDependency.getClassDeclaration() != null )
408                                     {
409                                         overriddenImplementation = overriddenDependency.getClassDeclaration();
410                                     }
411 
412                                     final Module moduleOfDependency =
413                                         validationContext.getModules().getModuleOfImplementation(
414                                         overriddenImplementation.getIdentifier() );
415 
416                                     addDetail( validationContext.getReport(),
417                                                "IMPLEMENTATION_DEPENDENCY_OVERRIDE_WARNING",
418                                                Level.WARNING, new ObjectFactory().createImplementation( impl ),
419                                                "implementationDependencyOverrideWarning", impl.getIdentifier(),
420                                                moduleOfImpl.getName(), d.getName(),
421                                                overriddenImplementation.getIdentifier(),
422                                                moduleOfDependency.getName(),
423                                                getNodePathString( overriddenDependency ) );
424 
425                                 }
426                             }
427 
428                             retainFinalNodes( overriddenDependencies );
429 
430                             for ( final InheritanceModel.Node<Dependency> overriddenDependency :
431                                   overriddenDependencies )
432                             {
433                                 Implementation overriddenImplementation = overriddenDependency.getImplementation();
434                                 if ( overriddenDependency.getClassDeclaration() != null )
435                                 {
436                                     overriddenImplementation = overriddenDependency.getClassDeclaration();
437                                 }
438 
439                                 final Module moduleOfDependency =
440                                     validationContext.getModules().getModuleOfImplementation(
441                                     overriddenImplementation.getIdentifier() );
442 
443                                 addDetail( validationContext.getReport(),
444                                            "IMPLEMENTATION_DEPENDENCY_INHERITANCE_CONSTRAINT", Level.SEVERE,
445                                            new ObjectFactory().createImplementation( impl ),
446                                            "implementationDependencyFinalConstraint", impl.getIdentifier(),
447                                            moduleOfImpl.getName(), d.getName(),
448                                            overriddenImplementation.getIdentifier(),
449                                            moduleOfDependency.getName(),
450                                            getNodePathString( overriddenDependency ) );
451 
452                             }
453                         }
454 
455                         assertDependencyValid( validationContext, impl, d );
456                     }
457                 }
458 
459                 if ( impl.getImplementations() != null )
460                 {
461                     final Set<String> effImplementationReferences =
462                         imodel.getImplementationReferenceIdentifiers( impl.getIdentifier() );
463 
464                     for ( final String effImplementationReference : effImplementationReferences )
465                     {
466                         final Implementation ancestorImplementation =
467                             validationContext.getModules().getImplementation( effImplementationReference );
468 
469                         if ( ancestorImplementation != null && ancestorImplementation.isFinal() )
470                         {
471                             final Module moduleOfFinal = validationContext.getModules().getModuleOfImplementation(
472                                 ancestorImplementation.getIdentifier() );
473 
474                             addDetail( validationContext.getReport(),
475                                        "IMPLEMENTATION_IMPLEMENTATION_INHERITANCE_CONSTRAINT", Level.SEVERE,
476                                        new ObjectFactory().createImplementation( impl ),
477                                        "implementationFinalImplementationConstraint", impl.getIdentifier(),
478                                        moduleOfImpl.getName(), ancestorImplementation.getIdentifier(),
479                                        moduleOfFinal.getName() );
480 
481                         }
482                     }
483 
484                     for ( int j = 0, s1 = impl.getImplementations().getImplementation().size(); j < s1; j++ )
485                     {
486                         final Implementation pi = impl.getImplementations().getImplementation().get( j );
487 
488                         addDetail( validationContext.getReport(),
489                                    "IMPLEMENTATION_IMPLEMENTATION_DECLARATION_CONSTRAINT", Level.SEVERE,
490                                    new ObjectFactory().createImplementation( impl ),
491                                    "implementationImplementationDeclarationConstraint", impl.getIdentifier(),
492                                    moduleOfImpl.getName(), pi.getIdentifier() );
493 
494                     }
495 
496                     for ( int j = 0, s1 = impl.getImplementations().getReference().size(); j < s1; j++ )
497                     {
498                         final ImplementationReference r = impl.getImplementations().getReference().get( j );
499 
500                         final Set<InheritanceModel.Node<ImplementationReference>> effReferences =
501                             imodel.getImplementationReferenceNodes( impl.getIdentifier(), r.getIdentifier() );
502 
503                         for ( final InheritanceModel.Node<ImplementationReference> effReference : effReferences )
504                         {
505                             final Set<InheritanceModel.Node<ImplementationReference>> overriddenReferences =
506                                 modifiableSet( effReference.getOverriddenNodes() );
507 
508                             if ( r.isOverride() && overriddenReferences.isEmpty() )
509                             {
510                                 addDetail( validationContext.getReport(),
511                                            "IMPLEMENTATION_IMPLEMENTATION_OVERRIDE_CONSTRAINT", Level.SEVERE,
512                                            new ObjectFactory().createImplementation( impl ),
513                                            "implementationImplementationOverrideConstraint", impl.getIdentifier(),
514                                            moduleOfImpl.getName(), r.getIdentifier() );
515 
516                             }
517 
518                             if ( !( r.isOverride() || overriddenReferences.isEmpty() ) )
519                             {
520                                 for ( final InheritanceModel.Node<ImplementationReference> overriddenReference :
521                                       overriddenReferences )
522                                 {
523                                     Implementation overriddenImplementation = overriddenReference.getImplementation();
524                                     if ( overriddenReference.getClassDeclaration() != null )
525                                     {
526                                         overriddenImplementation = overriddenReference.getClassDeclaration();
527                                     }
528 
529                                     final Module moduleOfReference =
530                                         validationContext.getModules().getModuleOfImplementation(
531                                         overriddenImplementation.getIdentifier() );
532 
533                                     addDetail( validationContext.getReport(),
534                                                "IMPLEMENTATION_IMPLEMENTATION_REFERENCE_OVERRIDE_WARNING",
535                                                Level.WARNING, new ObjectFactory().createImplementation( impl ),
536                                                "implementationImplementationOverrideWarning", impl.getIdentifier(),
537                                                moduleOfImpl.getName(), r.getIdentifier(),
538                                                overriddenImplementation.getIdentifier(),
539                                                moduleOfReference.getName(),
540                                                getNodePathString( overriddenReference ) );
541 
542                                 }
543                             }
544 
545                             retainFinalNodes( overriddenReferences );
546 
547                             for ( final InheritanceModel.Node<ImplementationReference> overriddenReference :
548                                   overriddenReferences )
549                             {
550                                 Implementation overriddenImplementation = overriddenReference.getImplementation();
551                                 if ( overriddenReference.getClassDeclaration() != null )
552                                 {
553                                     overriddenImplementation = overriddenReference.getClassDeclaration();
554                                 }
555 
556                                 final Module moduleOfReference =
557                                     validationContext.getModules().getModuleOfImplementation(
558                                     overriddenImplementation.getIdentifier() );
559 
560                                 addDetail( validationContext.getReport(),
561                                            "IMPLEMENTATION_IMPLEMENTATION_REFERENCE_INHERITANCE_CONSTRAINT",
562                                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
563                                            "implementationFinalImplementatioReferenceConstraint", impl.getIdentifier(),
564                                            moduleOfImpl.getName(), r.getIdentifier(),
565                                            overriddenImplementation.getIdentifier(),
566                                            moduleOfReference.getName(), getNodePathString( overriddenReference ) );
567 
568                             }
569                         }
570                     }
571                 }
572 
573                 if ( impl.getMessages() != null )
574                 {
575                     for ( int j = 0, s1 = impl.getMessages().getMessage().size(); j < s1; j++ )
576                     {
577                         final Message m = impl.getMessages().getMessage().get( j );
578 
579                         if ( impl.getMessages().getReference( m.getName() ) != null )
580                         {
581                             addDetail( validationContext.getReport(), "IMPLEMENTATION_MESSAGES_UNIQUENESS_CONSTRAINT",
582                                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
583                                        "implementationMessagesUniquenessConstraint", impl.getIdentifier(),
584                                        moduleOfImpl.getName(), m.getName() );
585 
586                         }
587 
588                         if ( m.getTemplate() != null )
589                         {
590                             for ( int k = 0, s2 = m.getTemplate().getText().size(); k < s2; k++ )
591                             {
592                                 final Text t = m.getTemplate().getText().get( k );
593 
594                                 try
595                                 {
596                                     new MessageFormat( t.getValue(), new Locale( t.getLanguage() ) );
597                                 }
598                                 catch ( final IllegalArgumentException e )
599                                 {
600                                     final String message = getMessage( e );
601 
602                                     if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
603                                     {
604                                         validationContext.getModelContext().log( Level.FINE, message, e );
605                                     }
606 
607                                     addDetail( validationContext.getReport(),
608                                                "IMPLEMENTATION_MESSAGE_TEMPLATE_CONSTRAINT", Level.SEVERE,
609                                                new ObjectFactory().createImplementation( impl ),
610                                                "implementationMessageTemplateConstraint", impl.getIdentifier(),
611                                                moduleOfImpl.getName(), m.getName(), t.getValue(),
612                                                message != null && message.length() > 0 ? " " + message : "" );
613 
614                                 }
615                             }
616                         }
617 
618                         final Set<InheritanceModel.Node<Message>> effMessages =
619                             imodel.getMessageNodes( impl.getIdentifier(), m.getName() );
620 
621                         for ( final InheritanceModel.Node<Message> effMessage : effMessages )
622                         {
623                             final Set<InheritanceModel.Node<Message>> overriddenMessages =
624                                 modifiableSet( effMessage.getOverriddenNodes() );
625 
626                             if ( m.isOverride() && overriddenMessages.isEmpty() )
627                             {
628                                 addDetail( validationContext.getReport(), "IMPLEMENTATION_MESSAGE_OVERRIDE_CONSTRAINT",
629                                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
630                                            "implementationMessageOverrideConstraint", impl.getIdentifier(),
631                                            moduleOfImpl.getName(), m.getName() );
632 
633                             }
634 
635                             if ( !( m.isOverride() || overriddenMessages.isEmpty() ) )
636                             {
637                                 for ( final InheritanceModel.Node<Message> overriddenMessage : overriddenMessages )
638                                 {
639                                     Implementation overriddenImplementation = overriddenMessage.getImplementation();
640                                     if ( overriddenMessage.getClassDeclaration() != null )
641                                     {
642                                         overriddenImplementation = overriddenMessage.getClassDeclaration();
643                                     }
644 
645                                     final Module moduleOfMessage =
646                                         validationContext.getModules().getModuleOfImplementation(
647                                         overriddenImplementation.getIdentifier() );
648 
649                                     addDetail( validationContext.getReport(), "IMPLEMENTATION_MESSAGE_OVERRIDE_WARNING",
650                                                Level.WARNING, new ObjectFactory().createImplementation( impl ),
651                                                "implementationMessageOverrideWarning", impl.getIdentifier(),
652                                                moduleOfImpl.getName(), m.getName(),
653                                                overriddenImplementation.getIdentifier(),
654                                                moduleOfMessage.getName(), getNodePathString( overriddenMessage ) );
655 
656                                 }
657                             }
658 
659                             retainFinalNodes( overriddenMessages );
660 
661                             for ( final InheritanceModel.Node<Message> overriddenMessage : overriddenMessages )
662                             {
663                                 Implementation overriddenImplementation = overriddenMessage.getImplementation();
664                                 if ( overriddenMessage.getClassDeclaration() != null )
665                                 {
666                                     overriddenImplementation = overriddenMessage.getClassDeclaration();
667                                 }
668 
669                                 final Module moduleOfMessage = validationContext.getModules().getModuleOfImplementation(
670                                     overriddenImplementation.getIdentifier() );
671 
672                                 addDetail( validationContext.getReport(),
673                                            "IMPLEMENTATION_MESSAGE_INHERITANCE_CONSTRAINT",
674                                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
675                                            "implementationMessageFinalConstraint", impl.getIdentifier(),
676                                            moduleOfImpl.getName(), m.getName(),
677                                            overriddenImplementation.getIdentifier(),
678                                            moduleOfMessage.getName(), getNodePathString( overriddenMessage ) );
679 
680                             }
681                         }
682                     }
683 
684                     for ( int j = 0, s1 = impl.getMessages().getReference().size(); j < s1; j++ )
685                     {
686                         final MessageReference r = impl.getMessages().getReference().get( j );
687 
688                         final Set<InheritanceModel.Node<Message>> effMessages =
689                             imodel.getMessageNodes( impl.getIdentifier(), r.getName() );
690 
691                         for ( final InheritanceModel.Node<Message> effMessage : effMessages )
692                         {
693                             final Set<InheritanceModel.Node<Message>> overriddenMessages =
694                                 modifiableSet( effMessage.getOverriddenNodes() );
695 
696                             if ( r.isOverride() && overriddenMessages.isEmpty() )
697                             {
698                                 addDetail( validationContext.getReport(), "IMPLEMENTATION_MESSAGE_OVERRIDE_CONSTRAINT",
699                                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
700                                            "implementationMessageOverrideConstraint", impl.getIdentifier(),
701                                            moduleOfImpl.getName(), r.getName() );
702 
703                             }
704 
705                             if ( !( r.isOverride() || overriddenMessages.isEmpty() ) )
706                             {
707                                 for ( final InheritanceModel.Node<Message> overriddenMessage : overriddenMessages )
708                                 {
709                                     Implementation overriddenImplementation = overriddenMessage.getImplementation();
710                                     if ( overriddenMessage.getClassDeclaration() != null )
711                                     {
712                                         overriddenImplementation = overriddenMessage.getClassDeclaration();
713                                     }
714 
715                                     final Module moduleOfMessage =
716                                         validationContext.getModules().getModuleOfImplementation(
717                                         overriddenImplementation.getIdentifier() );
718 
719                                     addDetail( validationContext.getReport(), "IMPLEMENTATION_MESSAGE_OVERRIDE_WARNING",
720                                                Level.WARNING, new ObjectFactory().createImplementation( impl ),
721                                                "implementationMessageOverrideWarning", impl.getIdentifier(),
722                                                moduleOfImpl.getName(), r.getName(),
723                                                overriddenImplementation.getIdentifier(),
724                                                moduleOfMessage.getName(), getNodePathString( overriddenMessage ) );
725 
726                                 }
727                             }
728 
729                             retainFinalNodes( overriddenMessages );
730 
731                             for ( final InheritanceModel.Node<Message> overriddenMessage : overriddenMessages )
732                             {
733                                 Implementation overriddenImplementation = overriddenMessage.getImplementation();
734                                 if ( overriddenMessage.getClassDeclaration() != null )
735                                 {
736                                     overriddenImplementation = overriddenMessage.getClassDeclaration();
737                                 }
738 
739                                 final Module moduleOfMessage =
740                                     validationContext.getModules().getModuleOfImplementation(
741                                     overriddenImplementation.getIdentifier() );
742 
743                                 addDetail( validationContext.getReport(),
744                                            "IMPLEMENTATION_MESSAGE_INHERITANCE_CONSTRAINT",
745                                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
746                                            "implementationMessageFinalConstraint", impl.getIdentifier(),
747                                            moduleOfImpl.getName(), r.getName(),
748                                            overriddenImplementation.getIdentifier(),
749                                            moduleOfMessage.getName(), getNodePathString( overriddenMessage ) );
750 
751                             }
752                         }
753                     }
754                 }
755 
756                 if ( impl.getProperties() != null )
757                 {
758                     for ( int j = 0, s1 = impl.getProperties().getProperty().size(); j < s1; j++ )
759                     {
760                         final Property p = impl.getProperties().getProperty().get( j );
761 
762                         if ( impl.getProperties().getReference( p.getName() ) != null )
763                         {
764                             addDetail( validationContext.getReport(), "IMPLEMENTATION_PROPERTIES_UNIQUENESS_CONSTRAINT",
765                                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
766                                        "implementationPropertiesUniquenessConstraint", impl.getIdentifier(),
767                                        moduleOfImpl.getName(), p.getName() );
768 
769                         }
770 
771                         if ( p.getValue() != null && p.getAny() != null )
772                         {
773                             addDetail( validationContext.getReport(), "IMPLEMENTATION_PROPERTY_VALUE_CONSTRAINT",
774                                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
775                                        "implementationPropertyValueConstraint", impl.getIdentifier(),
776                                        moduleOfImpl.getName(), p.getName() );
777 
778                         }
779 
780                         if ( p.getAny() != null && p.getType() == null )
781                         {
782                             addDetail( validationContext.getReport(), "IMPLEMENTATION_PROPERTY_TYPE_CONSTRAINT",
783                                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
784                                        "implementationPropertyTypeConstraint", impl.getIdentifier(),
785                                        moduleOfImpl.getName(), p.getName() );
786 
787                         }
788 
789                         try
790                         {
791                             p.getJavaValue( validationContext.getModelContext().getClassLoader() );
792                         }
793                         catch ( final PropertyException e )
794                         {
795                             final String message = getMessage( e );
796 
797                             if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
798                             {
799                                 validationContext.getModelContext().log( Level.FINE, message, e );
800                             }
801 
802                             addDetail( validationContext.getReport(), "IMPLEMENTATION_PROPERTY_JAVA_VALUE_CONSTRAINT",
803                                        Level.SEVERE, new ObjectFactory().createImplementation( impl ),
804                                        "implementationPropertyJavaValueConstraint", impl.getIdentifier(),
805                                        moduleOfImpl.getName(), p.getName(),
806                                        message != null && message.length() > 0 ? " " + message : "" );
807 
808                         }
809 
810                         final Set<InheritanceModel.Node<Property>> effProperties =
811                             imodel.getPropertyNodes( impl.getIdentifier(), p.getName() );
812 
813                         for ( final InheritanceModel.Node<Property> effProperty : effProperties )
814                         {
815                             final Set<InheritanceModel.Node<Property>> overriddenProperties =
816                                 modifiableSet( effProperty.getOverriddenNodes() );
817 
818                             if ( p.isOverride() && overriddenProperties.isEmpty() )
819                             {
820                                 addDetail( validationContext.getReport(), "IMPLEMENTATION_PROPERTY_OVERRIDE_CONSTRAINT",
821                                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
822                                            "implementationPropertyOverrideConstraint", impl.getIdentifier(),
823                                            moduleOfImpl.getName(), p.getName() );
824 
825                             }
826 
827                             if ( !( p.isOverride() || overriddenProperties.isEmpty() ) )
828                             {
829                                 for ( final InheritanceModel.Node<Property> overriddenProperty : overriddenProperties )
830                                 {
831                                     if ( overriddenProperty.getSpecification() != null )
832                                     {
833                                         final Module moduleOfProperty =
834                                             validationContext.getModules().getModuleOfSpecification(
835                                             overriddenProperty.getSpecification().getIdentifier() );
836 
837                                         addDetail( validationContext.getReport(),
838                                                    "IMPLEMENTATION_PROPERTY_OVERRIDE_WARNING", Level.WARNING,
839                                                    new ObjectFactory().createImplementation( impl ),
840                                                    "implementationSpecificationPropertyOverrideWarning",
841                                                    impl.getIdentifier(), moduleOfImpl.getName(), p.getName(),
842                                                    overriddenProperty.getSpecification().getIdentifier(),
843                                                    moduleOfProperty.getName(),
844                                                    getNodePathString( overriddenProperty ) );
845 
846                                     }
847                                     else
848                                     {
849                                         Implementation overriddenImplementation =
850                                             overriddenProperty.getImplementation();
851 
852                                         if ( overriddenProperty.getClassDeclaration() != null )
853                                         {
854                                             overriddenImplementation = overriddenProperty.getClassDeclaration();
855                                         }
856 
857                                         final Module moduleOfProperty =
858                                             validationContext.getModules().getModuleOfImplementation(
859                                             overriddenImplementation.getIdentifier() );
860 
861                                         addDetail( validationContext.getReport(),
862                                                    "IMPLEMENTATION_PROPERTY_OVERRIDE_WARNING", Level.WARNING,
863                                                    new ObjectFactory().createImplementation( impl ),
864                                                    "implementationPropertyOverrideWarning", impl.getIdentifier(),
865                                                    moduleOfImpl.getName(), p.getName(),
866                                                    overriddenImplementation.getIdentifier(),
867                                                    moduleOfProperty.getName(),
868                                                    getNodePathString( overriddenProperty ) );
869 
870                                     }
871                                 }
872                             }
873 
874                             retainFinalNodes( overriddenProperties );
875 
876                             for ( final InheritanceModel.Node<Property> overriddenProperty : overriddenProperties )
877                             {
878                                 Implementation overriddenImplementation = overriddenProperty.getImplementation();
879                                 if ( overriddenProperty.getClassDeclaration() != null )
880                                 {
881                                     overriddenImplementation = overriddenProperty.getClassDeclaration();
882                                 }
883 
884                                 final Module moduleOfProperty =
885                                     validationContext.getModules().getModuleOfImplementation(
886                                     overriddenImplementation.getIdentifier() );
887 
888                                 addDetail( validationContext.getReport(),
889                                            "IMPLEMENTATION_PROPERTY_INHERITANCE_CONSTRAINT",
890                                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
891                                            "implementationPropertyFinalConstraint", impl.getIdentifier(),
892                                            moduleOfImpl.getName(), p.getName(),
893                                            overriddenImplementation.getIdentifier(),
894                                            moduleOfProperty.getName(), getNodePathString( overriddenProperty ) );
895 
896                             }
897                         }
898                     }
899 
900                     for ( int j = 0, s1 = impl.getProperties().getReference().size(); j < s1; j++ )
901                     {
902                         final PropertyReference r = impl.getProperties().getReference().get( j );
903 
904                         final Set<InheritanceModel.Node<Property>> effProperties =
905                             imodel.getPropertyNodes( impl.getIdentifier(), r.getName() );
906 
907                         for ( final InheritanceModel.Node<Property> effProperty : effProperties )
908                         {
909                             final Set<InheritanceModel.Node<Property>> overriddenProperties =
910                                 modifiableSet( effProperty.getOverriddenNodes() );
911 
912                             if ( r.isOverride() && overriddenProperties.isEmpty() )
913                             {
914                                 addDetail( validationContext.getReport(), "IMPLEMENTATION_PROPERTY_OVERRIDE_CONSTRAINT",
915                                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
916                                            "implementationPropertyOverrideConstraint", impl.getIdentifier(),
917                                            moduleOfImpl.getName(), r.getName() );
918 
919                             }
920 
921                             if ( !( r.isOverride() || overriddenProperties.isEmpty() ) )
922                             {
923                                 for ( final InheritanceModel.Node<Property> overriddenProperty : overriddenProperties )
924                                 {
925                                     Implementation overriddenImplementation = overriddenProperty.getImplementation();
926                                     if ( overriddenProperty.getClassDeclaration() != null )
927                                     {
928                                         overriddenImplementation = overriddenProperty.getClassDeclaration();
929                                     }
930 
931                                     final Module moduleOfProperty =
932                                         validationContext.getModules().getModuleOfImplementation(
933                                         overriddenImplementation.getIdentifier() );
934 
935                                     addDetail( validationContext.getReport(),
936                                                "IMPLEMENTATION_PROPERTY_OVERRIDE_WARNING", Level.WARNING,
937                                                new ObjectFactory().createImplementation( impl ),
938                                                "implementationPropertyOverrideWarning", impl.getIdentifier(),
939                                                moduleOfImpl.getName(), r.getName(),
940                                                overriddenImplementation.getIdentifier(),
941                                                moduleOfProperty.getName(), getNodePathString( overriddenProperty ) );
942 
943                                 }
944                             }
945 
946                             retainFinalNodes( overriddenProperties );
947 
948                             for ( final InheritanceModel.Node<Property> overriddenProperty : overriddenProperties )
949                             {
950                                 Implementation overriddenImplementation = overriddenProperty.getImplementation();
951                                 if ( overriddenProperty.getClassDeclaration() != null )
952                                 {
953                                     overriddenImplementation = overriddenProperty.getClassDeclaration();
954                                 }
955 
956                                 final Module moduleOfProperty =
957                                     validationContext.getModules().getModuleOfImplementation(
958                                     overriddenImplementation.getIdentifier() );
959 
960                                 addDetail( validationContext.getReport(),
961                                            "IMPLEMENTATION_PROPERTY_INHERITANCE_CONSTRAINT",
962                                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
963                                            "implementationPropertyFinalConstraint", impl.getIdentifier(),
964                                            moduleOfImpl.getName(), r.getName(),
965                                            overriddenImplementation.getIdentifier(),
966                                            moduleOfProperty.getName(), getNodePathString( overriddenProperty ) );
967 
968                             }
969                         }
970                     }
971                 }
972 
973                 if ( impl.getSpecifications() != null )
974                 {
975                     for ( int j = 0, s1 = impl.getSpecifications().getSpecification().size(); j < s1; j++ )
976                     {
977                         final Specification s = impl.getSpecifications().getSpecification().get( j );
978 
979                         addDetail( validationContext.getReport(), "IMPLEMENTATION_SPECIFICATION_DECLARATION_CONSTRAINT",
980                                    Level.SEVERE, new ObjectFactory().createImplementation( impl ),
981                                    "implementationSpecificationDeclarationConstraint", impl.getIdentifier(),
982                                    moduleOfImpl.getName(), s.getIdentifier() );
983 
984                     }
985 
986                     for ( int j = 0, s1 = impl.getSpecifications().getReference().size(); j < s1; j++ )
987                     {
988                         final SpecificationReference r = impl.getSpecifications().getReference().get( j );
989 
990                         final Set<InheritanceModel.Node<SpecificationReference>> effReferences =
991                             imodel.getSpecificationReferenceNodes( impl.getIdentifier(), r.getIdentifier() );
992 
993                         for ( final InheritanceModel.Node<SpecificationReference> effReference : effReferences )
994                         {
995                             final Set<InheritanceModel.Node<SpecificationReference>> overriddenReferences =
996                                 modifiableSet( effReference.getOverriddenNodes() );
997 
998                             if ( r.isOverride() && overriddenReferences.isEmpty() )
999                             {
1000                                 addDetail( validationContext.getReport(),
1001                                            "IMPLEMENTATION_SPECIFICATION_OVERRIDE_CONSTRAINT", Level.SEVERE,
1002                                            new ObjectFactory().createImplementation( impl ),
1003                                            "implementationSpecificationOverrideConstraint", impl.getIdentifier(),
1004                                            moduleOfImpl.getName(), r.getIdentifier() );
1005 
1006                             }
1007 
1008                             if ( !( r.isOverride() || overriddenReferences.isEmpty() ) )
1009                             {
1010                                 for ( final InheritanceModel.Node<SpecificationReference> overriddenReference :
1011                                       overriddenReferences )
1012                                 {
1013                                     Implementation overriddenImplementation = overriddenReference.getImplementation();
1014                                     if ( overriddenReference.getClassDeclaration() != null )
1015                                     {
1016                                         overriddenImplementation = overriddenReference.getClassDeclaration();
1017                                     }
1018 
1019                                     final Module moduleOfReference =
1020                                         validationContext.getModules().getModuleOfImplementation(
1021                                         overriddenImplementation.getIdentifier() );
1022 
1023                                     addDetail( validationContext.getReport(),
1024                                                "IMPLEMENTATION_SPECIFICATION_REFERENCE_OVERRIDE_WARNING",
1025                                                Level.WARNING, new ObjectFactory().createImplementation( impl ),
1026                                                "implementationSpecificationOverrideWarning", impl.getIdentifier(),
1027                                                moduleOfImpl.getName(), r.getIdentifier(),
1028                                                overriddenImplementation.getIdentifier(),
1029                                                moduleOfReference.getName(), getNodePathString( overriddenReference ) );
1030 
1031                                 }
1032                             }
1033 
1034                             retainFinalNodes( overriddenReferences );
1035 
1036                             for ( final InheritanceModel.Node<SpecificationReference> overriddenReference :
1037                                   overriddenReferences )
1038                             {
1039                                 Implementation overriddenImplementation = overriddenReference.getImplementation();
1040                                 if ( overriddenReference.getClassDeclaration() != null )
1041                                 {
1042                                     overriddenImplementation = overriddenReference.getClassDeclaration();
1043                                 }
1044 
1045                                 final Module moduleOfReference =
1046                                     validationContext.getModules().getModuleOfImplementation(
1047                                     overriddenImplementation.getIdentifier() );
1048 
1049                                 addDetail( validationContext.getReport(),
1050                                            "IMPLEMENTATION_SPECIFICATION_INHERITANCE_CONSTRAINT", Level.SEVERE,
1051                                            new ObjectFactory().createImplementation( impl ),
1052                                            "implementationSpecificationFinalConstraint", impl.getIdentifier(),
1053                                            moduleOfImpl.getName(), r.getIdentifier(),
1054                                            overriddenImplementation.getIdentifier(),
1055                                            moduleOfReference.getName(), getNodePathString( overriddenReference ) );
1056 
1057                             }
1058                         }
1059                     }
1060                 }
1061 
1062                 if ( !impl.getAny().isEmpty() )
1063                 {
1064                     for ( int j = 0, s1 = impl.getAny().size(); j < s1; j++ )
1065                     {
1066                         final Object any = impl.getAny().get( j );
1067 
1068                         if ( any instanceof JAXBElement<?> )
1069                         {
1070                             final JAXBElement<?> jaxbElement = (JAXBElement<?>) any;
1071                             boolean overrideNode = false;
1072 
1073                             if ( jaxbElement.getValue() instanceof Inheritable )
1074                             {
1075                                 overrideNode = ( (Inheritable) jaxbElement.getValue() ).isOverride();
1076                             }
1077 
1078                             final Set<InheritanceModel.Node<JAXBElement<?>>> effElements =
1079                                 imodel.getJaxbElementNodes( impl.getIdentifier(), jaxbElement.getName() );
1080 
1081                             for ( final InheritanceModel.Node<JAXBElement<?>> effElement : effElements )
1082                             {
1083                                 final Set<InheritanceModel.Node<JAXBElement<?>>> overriddenElements =
1084                                     modifiableSet( effElement.getOverriddenNodes() );
1085 
1086                                 if ( overrideNode && overriddenElements.isEmpty() )
1087                                 {
1088                                     addDetail( validationContext.getReport(),
1089                                                "IMPLEMENTATION_JAXB_ELEMENT_OVERRIDE_CONSTRAINT",
1090                                                Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1091                                                "implementationJaxbElementOverrideConstraint", impl.getIdentifier(),
1092                                                moduleOfImpl.getName(), jaxbElement.getName().toString() );
1093 
1094                                 }
1095 
1096                                 if ( !( overrideNode || overriddenElements.isEmpty() ) )
1097                                 {
1098                                     for ( final InheritanceModel.Node<JAXBElement<?>> overriddenElement :
1099                                           overriddenElements )
1100                                     {
1101                                         Implementation overriddenImplementation = overriddenElement.getImplementation();
1102                                         if ( overriddenElement.getClassDeclaration() != null )
1103                                         {
1104                                             overriddenImplementation = overriddenElement.getClassDeclaration();
1105                                         }
1106 
1107                                         final Module moduleOfElement =
1108                                             validationContext.getModules().getModuleOfImplementation(
1109                                             overriddenElement.getImplementation().getIdentifier() );
1110 
1111                                         addDetail( validationContext.getReport(),
1112                                                    "IMPLEMENTATION_JAXB_ELEMENT_OVERRIDE_WARNING",
1113                                                    Level.WARNING, new ObjectFactory().createImplementation( impl ),
1114                                                    "implementationJaxbElementOverrideWarning", impl.getIdentifier(),
1115                                                    moduleOfImpl.getName(), jaxbElement.getName().toString(),
1116                                                    overriddenImplementation.getIdentifier(),
1117                                                    moduleOfElement.getName(), getNodePathString( overriddenElement ) );
1118 
1119                                     }
1120                                 }
1121 
1122                                 retainFinalNodes( overriddenElements );
1123 
1124                                 for ( final InheritanceModel.Node<JAXBElement<?>> overriddenElement :
1125                                       overriddenElements )
1126                                 {
1127                                     Implementation overriddenImplementation = overriddenElement.getImplementation();
1128                                     if ( overriddenElement.getClassDeclaration() != null )
1129                                     {
1130                                         overriddenImplementation = overriddenElement.getClassDeclaration();
1131                                     }
1132 
1133                                     final Module moduleOfElement =
1134                                         validationContext.getModules().getModuleOfImplementation(
1135                                         overriddenImplementation.getIdentifier() );
1136 
1137                                     addDetail( validationContext.getReport(),
1138                                                "IMPLEMENTATION_JAXB_ELEMENT_INHERITANCE_CONSTRAINT",
1139                                                Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1140                                                "implementationJaxbElementFinalConstraint", impl.getIdentifier(),
1141                                                moduleOfImpl.getName(), jaxbElement.getName().toString(),
1142                                                overriddenImplementation.getIdentifier(),
1143                                                moduleOfElement.getName(), getNodePathString( overriddenElement ) );
1144 
1145                                 }
1146                             }
1147                         }
1148                     }
1149                 }
1150 
1151                 final Set<String> dependencyNames = imodel.getDependencyNames( impl.getIdentifier() );
1152 
1153                 for ( String dependencyName : dependencyNames )
1154                 {
1155                     final Set<InheritanceModel.Node<Dependency>> dependencyNodes =
1156                         imodel.getDependencyNodes( impl.getIdentifier(), dependencyName );
1157 
1158                     if ( dependencyNodes.size() > 1 )
1159                     {
1160                         addDetail( validationContext.getReport(),
1161                                    "IMPLEMENTATION_DEPENDENCY_MULTIPLE_INHERITANCE_CONSTRAINT",
1162                                    Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1163                                    "implementationMultipleInheritanceDependencyConstraint", impl.getIdentifier(),
1164                                    moduleOfImpl.getName(), dependencyName, getNodeListPathString( dependencyNodes ) );
1165 
1166                     }
1167                 }
1168 
1169                 final Set<String> messageNames = imodel.getMessageNames( impl.getIdentifier() );
1170 
1171                 for ( String messageName : messageNames )
1172                 {
1173                     final Set<InheritanceModel.Node<Message>> messageNodes =
1174                         imodel.getMessageNodes( impl.getIdentifier(), messageName );
1175 
1176                     if ( messageNodes.size() > 1 )
1177                     {
1178                         addDetail( validationContext.getReport(),
1179                                    "IMPLEMENTATION_MESSAGE_MULTIPLE_INHERITANCE_CONSTRAINT", Level.SEVERE,
1180                                    new ObjectFactory().createImplementation( impl ),
1181                                    "implementationMultipleInheritanceMessageConstraint", impl.getIdentifier(),
1182                                    moduleOfImpl.getName(), messageName, getNodeListPathString( messageNodes ) );
1183 
1184                     }
1185                 }
1186 
1187                 final Set<String> propertyNames = imodel.getPropertyNames( impl.getIdentifier() );
1188 
1189                 for ( String propertyName : propertyNames )
1190                 {
1191                     final Set<InheritanceModel.Node<Property>> propertyNodes =
1192                         imodel.getPropertyNodes( impl.getIdentifier(), propertyName );
1193 
1194                     if ( propertyNodes.size() > 1 )
1195                     {
1196                         addDetail( validationContext.getReport(),
1197                                    "IMPLEMENTATION_PROPERTY_MULTIPLE_INHERITANCE_CONSTRAINT", Level.SEVERE,
1198                                    new ObjectFactory().createImplementation( impl ),
1199                                    "implementationMultipleInheritancePropertyConstraint", impl.getIdentifier(),
1200                                    moduleOfImpl.getName(), propertyName, getNodeListPathString( propertyNodes ) );
1201 
1202                     }
1203                 }
1204 
1205                 final Set<String> specificationReferenceIdentifiers =
1206                     imodel.getSpecificationReferenceIdentifiers( impl.getIdentifier() );
1207 
1208                 for ( String specificationRefereneIdentifier : specificationReferenceIdentifiers )
1209                 {
1210                     final Set<InheritanceModel.Node<SpecificationReference>> specificationReferenceNodes =
1211                         imodel.getSpecificationReferenceNodes( impl.getIdentifier(), specificationRefereneIdentifier );
1212 
1213                     if ( specificationReferenceNodes.size() > 1 )
1214                     {
1215                         addDetail( validationContext.getReport(),
1216                                    "IMPLEMENTATION_SPECIFICATION_MULTIPLE_INHERITANCE_CONSTRAINT",
1217                                    Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1218                                    "implementationMultipleInheritanceSpecificationConstraint",
1219                                    impl.getIdentifier(), moduleOfImpl.getName(), specificationRefereneIdentifier,
1220                                    getNodeListPathString( specificationReferenceNodes ) );
1221 
1222                     }
1223                 }
1224 
1225                 final Set<QName> xmlElementNames = imodel.getXmlElementNames( impl.getIdentifier() );
1226 
1227                 for ( QName xmlElementName : xmlElementNames )
1228                 {
1229                     final Set<InheritanceModel.Node<Element>> xmlElementNodes =
1230                         imodel.getXmlElementNodes( impl.getIdentifier(), xmlElementName );
1231 
1232                     if ( xmlElementNodes.size() > 1 )
1233                     {
1234                         addDetail( validationContext.getReport(),
1235                                    "IMPLEMENTATION_XML_ELEMENT_MULTIPLE_INHERITANCE_CONSTRAINT",
1236                                    Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1237                                    "implementationMultipleInheritanceXmlElementConstraint",
1238                                    impl.getIdentifier(), moduleOfImpl.getName(), xmlElementName.toString(),
1239                                    getNodeListPathString( xmlElementNodes ) );
1240 
1241                     }
1242                 }
1243 
1244                 final Set<QName> jaxbElementNames = imodel.getJaxbElementNames( impl.getIdentifier() );
1245 
1246                 for ( QName jaxbElementName : jaxbElementNames )
1247                 {
1248                     final Set<InheritanceModel.Node<JAXBElement<?>>> jaxbElementNodes =
1249                         imodel.getJaxbElementNodes( impl.getIdentifier(), jaxbElementName );
1250 
1251                     if ( jaxbElementNodes.size() > 1 )
1252                     {
1253                         addDetail( validationContext.getReport(),
1254                                    "IMPLEMENTATION_JAXB_ELEMENT_MULTIPLE_INHERITANCE_CONSTRAINT",
1255                                    Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1256                                    "implementationMultipleInheritanceJaxbElementConstraint",
1257                                    impl.getIdentifier(), moduleOfImpl.getName(), jaxbElementName.toString(),
1258                                    getNodeListPathString( jaxbElementNodes ) );
1259 
1260                     }
1261                 }
1262 
1263                 final Set<String> implementationReferenceIdentifiers =
1264                     imodel.getImplementationReferenceIdentifiers( impl.getIdentifier() );
1265 
1266                 for ( String implementationReferenceIdentifier : implementationReferenceIdentifiers )
1267                 {
1268                     final Set<InheritanceModel.Node<ImplementationReference>> implementationReferenceNodes =
1269                         imodel.getImplementationReferenceNodes( impl.getIdentifier(),
1270                                                                 implementationReferenceIdentifier );
1271 
1272                     for ( final InheritanceModel.Node<ImplementationReference> node : implementationReferenceNodes )
1273                     {
1274                         final ImplementationReference r = node.getModelObject();
1275 
1276                         final Implementation referenced =
1277                             validationContext.getModules().getImplementation( r.getIdentifier() );
1278 
1279                         final Module moduleOfReferenced =
1280                             validationContext.getModules().getModuleOfImplementation( referenced.getIdentifier() );
1281 
1282                         if ( r.getVersion() != null && referenced != null )
1283                         {
1284                             if ( referenced.getVersion() == null )
1285                             {
1286                                 addDetail( validationContext.getReport(),
1287                                            "IMPLEMENTATION_IMPLEMENTATION_VERSIONING_CONSTRAINT", Level.SEVERE,
1288                                            new ObjectFactory().createImplementation( impl ),
1289                                            "implementationImplementationVersioningConstraint",
1290                                            impl.getIdentifier(), moduleOfImpl.getName(), r.getIdentifier(),
1291                                            moduleOfReferenced.getName() );
1292 
1293                             }
1294                             else
1295                             {
1296                                 try
1297                                 {
1298                                     if ( VersionParser.compare( r.getVersion(), referenced.getVersion() ) > 0 )
1299                                     {
1300                                         addDetail( validationContext.getReport(),
1301                                                    "IMPLEMENTATION_INHERITANCE_COMPATIBILITY_CONSTRAINT",
1302                                                    Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1303                                                    "implementationInheritanceCompatibilityConstraint",
1304                                                    impl.getIdentifier(), moduleOfImpl.getName(),
1305                                                    referenced.getIdentifier(), moduleOfReferenced.getName(),
1306                                                    r.getVersion(), referenced.getVersion() );
1307 
1308                                     }
1309                                 }
1310                                 catch ( final ParseException ex )
1311                                 {
1312                                     final String message = getMessage( ex );
1313 
1314                                     if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
1315                                     {
1316                                         validationContext.getModelContext().log( Level.FINE, message, ex );
1317                                     }
1318 
1319                                     addDetail(
1320                                         validationContext.getReport(),
1321                                         "IMPLEMENTATION_INHERITANCE_COMPATIBILITY_VERSIONING_PARSE_EXCEPTION",
1322                                         Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1323                                         "implementationInheritanceCompatibilityParseException",
1324                                         impl.getIdentifier(), moduleOfImpl.getName(), r.getIdentifier(),
1325                                         moduleOfReferenced.getName(), r.getVersion(),
1326                                         message != null && message.length() > 0 ? " " + message : "" );
1327 
1328                                 }
1329                                 catch ( final TokenMgrError ex )
1330                                 {
1331                                     final String message = getMessage( ex );
1332 
1333                                     if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
1334                                     {
1335                                         validationContext.getModelContext().log( Level.FINE, message, ex );
1336                                     }
1337 
1338                                     addDetail(
1339                                         validationContext.getReport(),
1340                                         "IMPLEMENTATION_INHERITANCE_COMPATIBILITY_VERSIONING_TOKEN_MANAGER_ERROR",
1341                                         Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1342                                         "implementationInheritanceCompatiblityVersioningTokenManagerError",
1343                                         impl.getIdentifier(), moduleOfImpl.getName(), r.getIdentifier(),
1344                                         moduleOfReferenced.getName(), r.getVersion(),
1345                                         message != null && message.length() > 0 ? " " + message : "" );
1346 
1347                                 }
1348                             }
1349                         }
1350                     }
1351                 }
1352 
1353                 assertImplementationSpecificationCompatibility( validationContext, impl );
1354             }
1355         }
1356     }
1357 
1358     private static void assertSpecificationsValid( final ValidationContext validationContext )
1359     {
1360         final Specifications specifications = validationContext.getModules().getSpecifications();
1361         final Map<String, Specification> specificationClassDeclarations = new HashMap<String, Specification>();
1362 
1363         if ( specifications != null )
1364         {
1365             for ( int i = 0, s0 = specifications.getSpecification().size(); i < s0; i++ )
1366             {
1367                 final Specification s = specifications.getSpecification().get( i );
1368                 final Implementations impls = validationContext.getModules().getImplementations( s.getIdentifier() );
1369                 final Module moduleOfS = validationContext.getModules().getModuleOfSpecification( s.getIdentifier() );
1370 
1371                 if ( s.isClassDeclaration() )
1372                 {
1373                     if ( s.getClazz() == null )
1374                     {
1375                         addDetail( validationContext.getReport(), "SPECIFICATION_CLASS_CONSTRAINT", Level.SEVERE,
1376                                    new ObjectFactory().createSpecification( s ), "specificationClassConstraint",
1377                                    s.getIdentifier(), moduleOfS.getName() );
1378 
1379                     }
1380                     else
1381                     {
1382                         final Specification prev = specificationClassDeclarations.get( s.getClazz() );
1383 
1384                         if ( prev != null && !prev.getIdentifier().equals( s.getIdentifier() ) )
1385                         {
1386                             final Module moduleOfPrev = validationContext.getModules().getModuleOfSpecification(
1387                                 prev.getIdentifier() );
1388 
1389                             addDetail( validationContext.getReport(), "SPECIFICATION_CLASS_DECLARATION_CONSTRAINT",
1390                                        Level.SEVERE, new ObjectFactory().createSpecification( s ),
1391                                        "specificationClassDeclarationConstraint", s.getIdentifier(),
1392                                        moduleOfS.getName(), s.getClazz(), prev.getIdentifier(),
1393                                        moduleOfPrev.getName() );
1394 
1395                         }
1396                         else
1397                         {
1398                             specificationClassDeclarations.put( s.getClazz(), s );
1399                         }
1400                     }
1401                 }
1402 
1403                 if ( impls != null )
1404                 {
1405                     final Map<String, Implementations> map = new HashMap<String, Implementations>();
1406 
1407                     for ( int j = 0, s1 = impls.getImplementation().size(); j < s1; j++ )
1408                     {
1409                         final Implementation impl = impls.getImplementation().get( j );
1410                         Implementations implementations = map.get( impl.getName() );
1411 
1412                         if ( implementations == null )
1413                         {
1414                             implementations = new Implementations();
1415                             map.put( impl.getName(), implementations );
1416                         }
1417 
1418                         implementations.getImplementation().add( impl );
1419                     }
1420 
1421                     for ( Map.Entry<String, Implementations> e : map.entrySet() )
1422                     {
1423                         if ( e.getValue().getImplementation().size() > 1 )
1424                         {
1425                             for ( int j = 0, s1 = e.getValue().getImplementation().size(); j < s1; j++ )
1426                             {
1427                                 final Implementation impl = e.getValue().getImplementation().get( j );
1428                                 final Module moduleOfImpl = validationContext.getModules().getModuleOfImplementation(
1429                                     impl.getIdentifier() );
1430 
1431                                 addDetail( validationContext.getReport(),
1432                                            "SPECIFICATION_IMPLEMENTATION_NAME_UNIQUENESS_CONSTRAINT",
1433                                            Level.SEVERE, new ObjectFactory().createImplementation( impl ),
1434                                            "specificationImplementationNameConstraint", impl.getIdentifier(),
1435                                            moduleOfImpl.getName(), s.getIdentifier(), moduleOfS.getName(),
1436                                            impl.getName() );
1437 
1438                             }
1439                         }
1440                     }
1441 
1442                     if ( s.getMultiplicity() == Multiplicity.ONE && impls.getImplementation().size() > 1 )
1443                     {
1444                         for ( int j = 0, s1 = impls.getImplementation().size(); j < s1; j++ )
1445                         {
1446                             final Implementation impl = impls.getImplementation().get( j );
1447                             final Module moduleOfImpl = validationContext.getModules().getModuleOfImplementation(
1448                                 impl.getIdentifier() );
1449 
1450                             addDetail( validationContext.getReport(),
1451                                        "SPECIFICATION_IMPLEMENTATION_MULTIPLICITY_CONSTRAINT", Level.SEVERE,
1452                                        new ObjectFactory().createImplementation( impl ),
1453                                        "specificationMultiplicityConstraint", impl.getIdentifier(),
1454                                        moduleOfImpl.getName(), s.getIdentifier(), moduleOfS.getName(),
1455                                        s.getMultiplicity() );
1456 
1457                         }
1458                     }
1459                 }
1460 
1461                 if ( s.getProperties() != null )
1462                 {
1463                     for ( int j = 0, s1 = s.getProperties().getProperty().size(); j < s1; j++ )
1464                     {
1465                         final Property p = s.getProperties().getProperty().get( j );
1466 
1467                         if ( p.getValue() != null && p.getAny() != null )
1468                         {
1469                             addDetail( validationContext.getReport(), "SPECIFICATION_PROPERTY_VALUE_CONSTRAINT",
1470                                        Level.SEVERE, new ObjectFactory().createSpecification( s ),
1471                                        "specificationPropertyValueConstraint", s.getIdentifier(),
1472                                        moduleOfS.getName(), p.getName() );
1473 
1474                         }
1475 
1476                         if ( p.getAny() != null && p.getType() == null )
1477                         {
1478                             addDetail( validationContext.getReport(), "SPECIFICATION_PROPERTY_TYPE_CONSTRAINT",
1479                                        Level.SEVERE, new ObjectFactory().createSpecification( s ),
1480                                        "specificationPropertyTypeConstraint", s.getIdentifier(),
1481                                        moduleOfS.getName(), p.getName() );
1482 
1483                         }
1484 
1485                         try
1486                         {
1487                             p.getJavaValue( validationContext.getModelContext().getClassLoader() );
1488                         }
1489                         catch ( final PropertyException e )
1490                         {
1491                             final String message = getMessage( e );
1492 
1493                             if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
1494                             {
1495                                 validationContext.getModelContext().log( Level.FINE, message, e );
1496                             }
1497 
1498                             addDetail( validationContext.getReport(), "SPECIFICATION_PROPERTY_JAVA_VALUE_CONSTRAINT",
1499                                        Level.SEVERE, new ObjectFactory().createSpecification( s ),
1500                                        "specificationPropertyJavaValueConstraint", s.getIdentifier(),
1501                                        moduleOfS.getName(), p.getName(),
1502                                        message != null && message.length() > 0 ? " " + message : "" );
1503 
1504                         }
1505                     }
1506 
1507                     for ( int j = 0, s1 = s.getProperties().getReference().size(); j < s1; j++ )
1508                     {
1509                         final PropertyReference r = s.getProperties().getReference().get( j );
1510 
1511                         addDetail( validationContext.getReport(),
1512                                    "SPECIFICATION_PROPERTY_REFERENCE_DECLARATION_CONSTRAINT", Level.SEVERE,
1513                                    new ObjectFactory().createSpecification( s ),
1514                                    "specificationPropertyReferenceDeclarationConstraint", s.getIdentifier(),
1515                                    moduleOfS.getName(), r.getName() );
1516 
1517                     }
1518                 }
1519             }
1520         }
1521     }
1522 
1523     private static void assertDependencyValid( final ValidationContext validationContext,
1524                                                final Implementation implementation, final Dependency dependency )
1525     {
1526         final Specification s = validationContext.getModules().getSpecification( dependency.getIdentifier() );
1527         final Implementations available =
1528             validationContext.getModules().getImplementations( dependency.getIdentifier() );
1529 
1530         final Module moduleOfImpl =
1531             validationContext.getModules().getModuleOfImplementation( implementation.getIdentifier() );
1532 
1533         if ( !dependency.isOptional()
1534              && ( available == null || available.getImplementation().isEmpty()
1535                   || ( dependency.getImplementationName() != null
1536                        && available.getImplementationByName( dependency.getImplementationName() ) == null ) ) )
1537         {
1538             addDetail( validationContext.getReport(), "IMPLEMENTATION_MANDATORY_DEPENDENCY_CONSTRAINT", Level.SEVERE,
1539                        new ObjectFactory().createImplementation( implementation ),
1540                        "implementationMandatoryDependencyConstraint", implementation.getIdentifier(),
1541                        moduleOfImpl.getName(), dependency.getName() );
1542 
1543         }
1544 
1545         if ( s != null )
1546         {
1547             final Module moduleOfS = validationContext.getModules().getModuleOfSpecification( s.getIdentifier() );
1548 
1549             if ( s.getClazz() == null )
1550             {
1551                 addDetail( validationContext.getReport(), "IMPLEMENTATION_DEPENDENCY_SPECIFICATION_CLASS_CONSTRAINT",
1552                            Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
1553                            "implementationDependencySpecificationClassConstraint", implementation.getIdentifier(),
1554                            moduleOfImpl.getName(), dependency.getName(), dependency.getIdentifier(),
1555                            moduleOfS.getName() );
1556 
1557             }
1558 
1559             if ( dependency.getVersion() != null )
1560             {
1561                 if ( s.getVersion() == null )
1562                 {
1563                     addDetail( validationContext.getReport(),
1564                                "IMPLEMENTATION_DEPENDENCY_SPECIFICATION_VERSIONING_CONSTRAINT", Level.SEVERE,
1565                                new ObjectFactory().createImplementation( implementation ),
1566                                "implementationDependencySpecificationVersioningConstraint",
1567                                implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
1568                                s.getIdentifier(), moduleOfS.getName() );
1569 
1570                 }
1571                 else
1572                 {
1573 
1574                     try
1575                     {
1576                         if ( VersionParser.compare( dependency.getVersion(), s.getVersion() ) > 0 )
1577                         {
1578                             addDetail( validationContext.getReport(),
1579                                        "IMPLEMENTATION_DEPENDENCY_SPECIFICATION_COMPATIBILITY_CONSTRAINT",
1580                                        Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
1581                                        "implementationDependencySpecificationCompatibilityConstraint",
1582                                        implementation.getIdentifier(), moduleOfImpl.getName(), s.getIdentifier(),
1583                                        moduleOfS.getName(), dependency.getVersion(), s.getVersion() );
1584 
1585                         }
1586                     }
1587                     catch ( final ParseException e )
1588                     {
1589                         final String message = getMessage( e );
1590 
1591                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
1592                         {
1593                             validationContext.getModelContext().log( Level.FINE, message, e );
1594                         }
1595 
1596                         addDetail( validationContext.getReport(),
1597                                    "IMPLEMENTATION_DEPENDENCY_SPECIFICATION_COMPATIBILITY_VERSIONING_PARSE_EXCEPTION",
1598                                    Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
1599                                    "implementationDependencySpecificationCompatibilityParseException",
1600                                    implementation.getIdentifier(), moduleOfImpl.getName(), s.getIdentifier(),
1601                                    moduleOfS.getName(), dependency.getVersion(),
1602                                    message != null && message.length() > 0 ? " " + message : "" );
1603 
1604                     }
1605                     catch ( final TokenMgrError e )
1606                     {
1607                         final String message = getMessage( e );
1608 
1609                         if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
1610                         {
1611                             validationContext.getModelContext().log( Level.FINE, message, e );
1612                         }
1613 
1614                         addDetail( validationContext.getReport(),
1615                                    "IMPLEMENTATION_DEPENDENCY_SPECIFICATION_COMPATIBILITY_VERSIONING_TOKEN_MANAGER_ERROR",
1616                                    Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
1617                                    "implementationDependencySpecificationCompatibilityTokenMgrError",
1618                                    implementation.getIdentifier(), moduleOfImpl.getName(), s.getIdentifier(),
1619                                    moduleOfS.getName(), dependency.getVersion(),
1620                                    message != null && message.length() > 0 ? " " + message : "" );
1621 
1622                     }
1623                 }
1624             }
1625 
1626             if ( s.getScope() != null )
1627             {
1628                 if ( dependency.getDependencies() != null )
1629                 {
1630                     for ( int i = 0, s0 = dependency.getDependencies().getDependency().size(); i < s0; i++ )
1631                     {
1632                         final Dependency d = dependency.getDependencies().getDependency().get( i );
1633 
1634                         addDetail( validationContext.getReport(),
1635                                    "IMPLEMENTATION_DEPENDENCY_DEPENDENCIES_OVERRIDE_CONSTRAINT", Level.SEVERE,
1636                                    new ObjectFactory().createImplementation( implementation ),
1637                                    "implementationDependencyDependenciesOverrideConstraint",
1638                                    implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
1639                                    d.getName(), s.getIdentifier(), moduleOfS.getName(), s.getScope() );
1640 
1641                     }
1642                 }
1643 
1644                 if ( dependency.getMessages() != null )
1645                 {
1646                     for ( int i = 0, s0 = dependency.getMessages().getMessage().size(); i < s0; i++ )
1647                     {
1648                         final Message m = dependency.getMessages().getMessage().get( i );
1649 
1650                         addDetail( validationContext.getReport(),
1651                                    "IMPLEMENTATION_DEPENDENCY_MESSAGES_OVERRIDE_CONSTRAINT", Level.SEVERE,
1652                                    new ObjectFactory().createImplementation( implementation ),
1653                                    "implementationDependencyMessagesOverrideConstraint", implementation.getIdentifier(),
1654                                    moduleOfImpl.getName(), dependency.getName(), m.getName(), s.getIdentifier(),
1655                                    moduleOfS.getName(), s.getScope() );
1656 
1657                     }
1658                 }
1659 
1660                 if ( dependency.getProperties() != null )
1661                 {
1662                     for ( int i = 0, s0 = dependency.getProperties().getProperty().size(); i < s0; i++ )
1663                     {
1664                         final Property p = dependency.getProperties().getProperty().get( i );
1665                         addDetail( validationContext.getReport(),
1666                                    "IMPLEMENTATION_DEPENDENCY_PROPERTIES_OVERRIDE_CONSTRAINT", Level.SEVERE,
1667                                    new ObjectFactory().createImplementation( implementation ),
1668                                    "implementationDependencyPropertiesOverrideConstraint",
1669                                    implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
1670                                    p.getName(), s.getIdentifier(), moduleOfS.getName(), s.getScope() );
1671 
1672                     }
1673                 }
1674             }
1675         }
1676 
1677         if ( dependency.getMessages() != null )
1678         {
1679             for ( int i = 0, s0 = dependency.getMessages().getReference().size(); i < s0; i++ )
1680             {
1681                 final MessageReference r = dependency.getMessages().getReference().get( i );
1682 
1683                 addDetail( validationContext.getReport(),
1684                            "IMPLEMENTATION_DEPENDENCY_MESSAGE_REFERENCE_DECLARATION_CONSTRAINT", Level.SEVERE,
1685                            new ObjectFactory().createImplementation( implementation ),
1686                            "implementationDependencyMessageReferenceDeclarationConstraint",
1687                            implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(), r.getName() );
1688 
1689             }
1690         }
1691 
1692         if ( dependency.getProperties() != null )
1693         {
1694             for ( int i = 0, s0 = dependency.getProperties().getProperty().size(); i < s0; i++ )
1695             {
1696                 final Property p = dependency.getProperties().getProperty().get( i );
1697 
1698                 if ( p.getValue() != null && p.getAny() != null )
1699                 {
1700                     addDetail( validationContext.getReport(), "IMPLEMENTATION_DEPENDENCY_PROPERTY_VALUE_CONSTRAINT",
1701                                Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
1702                                "implementationDependencyPropertyValueConstraint", implementation.getIdentifier(),
1703                                moduleOfImpl.getName(), dependency.getName(), p.getName() );
1704 
1705                 }
1706 
1707                 if ( p.getAny() != null && p.getType() == null )
1708                 {
1709                     addDetail( validationContext.getReport(), "IMPLEMENTATION_DEPENDENCY_PROPERTY_TYPE_CONSTRAINT",
1710                                Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
1711                                "implementationDependencyPropertyTypeConstraint", implementation.getIdentifier(),
1712                                moduleOfImpl.getName(), dependency.getName(), p.getName() );
1713 
1714                 }
1715 
1716                 try
1717                 {
1718                     p.getJavaValue( validationContext.getModelContext().getClassLoader() );
1719                 }
1720                 catch ( final PropertyException e )
1721                 {
1722                     final String message = getMessage( e );
1723 
1724                     if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
1725                     {
1726                         validationContext.getModelContext().log( Level.FINE, message, e );
1727                     }
1728 
1729                     addDetail( validationContext.getReport(),
1730                                "IMPLEMENTATION_DEPENDENCY_PROPERTY_JAVA_VALUE_CONSTRAINT", Level.SEVERE,
1731                                new ObjectFactory().createImplementation( implementation ),
1732                                "implementationDependencyPropertyJavaValueConstraint", implementation.getIdentifier(),
1733                                moduleOfImpl.getName(), dependency.getName(), p.getName(),
1734                                message != null && message.length() > 0 ? " " + message : "" );
1735 
1736                 }
1737             }
1738 
1739             for ( int i = 0, s0 = dependency.getProperties().getReference().size(); i < s0; i++ )
1740             {
1741                 final PropertyReference r = dependency.getProperties().getReference().get( i );
1742 
1743                 addDetail( validationContext.getReport(),
1744                            "IMPLEMENTATION_DEPENDENCY_PROPERTY_REFERENCE_DECLARATION_CONSTRAINT", Level.SEVERE,
1745                            new ObjectFactory().createImplementation( implementation ),
1746                            "implementationDependencyPropertyReferenceDeclarationConstraint",
1747                            implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(), r.getName() );
1748 
1749             }
1750         }
1751 
1752         if ( available != null )
1753         {
1754             for ( int i = 0, s0 = available.getImplementation().size(); i < s0; i++ )
1755             {
1756                 final Implementation a = available.getImplementation().get( i );
1757 
1758                 if ( dependency.getImplementationName() != null
1759                      && !dependency.getImplementationName().equals( a.getName() ) )
1760                 {
1761                     continue;
1762                 }
1763 
1764                 final InheritanceModel imodel = validationContext.getInheritanceModel();
1765                 final Module moduleOfA = validationContext.getModules().getModuleOfImplementation( a.getIdentifier() );
1766 
1767                 if ( dependency.getDependencies() != null )
1768                 {
1769                     for ( int j = 0, s1 = dependency.getDependencies().getDependency().size(); j < s1; j++ )
1770                     {
1771                         final Dependency override = dependency.getDependencies().getDependency().get( j );
1772 
1773                         final Set<InheritanceModel.Node<Dependency>> effDependencies =
1774                             imodel.getDependencyNodes( a.getIdentifier(), override.getName() );
1775 
1776                         final Set<InheritanceModel.Node<Dependency>> overriddenDependencies =
1777                             modifiableSet( effDependencies );
1778 
1779                         final boolean effectiveDependencyOverridden = !overriddenDependencies.isEmpty();
1780 
1781                         if ( override.isOverride() && overriddenDependencies.isEmpty() )
1782                         {
1783                             addDetail( validationContext.getReport(),
1784                                        "IMPLEMENTATION_DEPENDENCY_OVERRIDE_DEPENDENCY_CONSTRAINT",
1785                                        Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
1786                                        "implementationDependencyOverrideDependencyConstraint",
1787                                        implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
1788                                        override.getName(), a.getIdentifier(), moduleOfA.getName() );
1789 
1790                         }
1791 
1792                         if ( !( override.isOverride() || overriddenDependencies.isEmpty() ) )
1793                         {
1794                             for ( final InheritanceModel.Node<Dependency> overriddenDependency :
1795                                   overriddenDependencies )
1796                             {
1797                                 addDetail( validationContext.getReport(),
1798                                            "IMPLEMENTATION_DEPENDENCY_OVERRIDE_DEPENDENCY_WARNING",
1799                                            Level.WARNING, new ObjectFactory().createImplementation( implementation ),
1800                                            "implementationDependencyOverrideDependencyWarning",
1801                                            implementation.getIdentifier(), moduleOfImpl.getName(),
1802                                            dependency.getName(), override.getName(), a.getIdentifier(),
1803                                            moduleOfA.getName(), getNodePathString( overriddenDependency ) );
1804 
1805                             }
1806                         }
1807 
1808                         retainFinalNodes( overriddenDependencies );
1809 
1810                         for ( final InheritanceModel.Node<Dependency> overriddenDependency :
1811                               overriddenDependencies )
1812                         {
1813                             addDetail( validationContext.getReport(),
1814                                        "IMPLEMENTATION_DEPENDENCY_FINAL_DEPENDENCY_CONSTRAINT",
1815                                        Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
1816                                        "implementationDependencyFinalDependencyConstraint",
1817                                        implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
1818                                        override.getName(), a.getIdentifier(), moduleOfA.getName(),
1819                                        getNodePathString( overriddenDependency ) );
1820 
1821                         }
1822 
1823                         if ( effectiveDependencyOverridden )
1824                         {
1825                             for ( InheritanceModel.Node<Dependency> node : effDependencies )
1826                             {
1827                                 final Dependency overridden = node.getModelObject();
1828 
1829                                 final Specification overrideSpecification =
1830                                     validationContext.getModules().getSpecification( override.getIdentifier() );
1831 
1832                                 final Specification overriddenSpecification =
1833                                     validationContext.getModules().getSpecification( overridden.getIdentifier() );
1834 
1835                                 if ( overrideSpecification != null && overriddenSpecification != null )
1836                                 {
1837                                     if ( overrideSpecification.getMultiplicity()
1838                                          != overriddenSpecification.getMultiplicity() )
1839                                     {
1840                                         addDetail( validationContext.getReport(),
1841                                                    "IMPLEMENTATION_DEPENDENCY_MULTIPLICITY_CONSTRAINT",
1842                                                    Level.SEVERE,
1843                                                    new ObjectFactory().createImplementation( implementation ),
1844                                                    "implementationDependencyMultiplicityConstraint",
1845                                                    implementation.getIdentifier(), moduleOfImpl.getName(),
1846                                                    dependency.getName(), overridden.getName(),
1847                                                    a.getIdentifier(), moduleOfA.getName(),
1848                                                    overrideSpecification.getMultiplicity().value(),
1849                                                    overriddenSpecification.getMultiplicity().value() );
1850 
1851                                     }
1852 
1853                                     if ( overrideSpecification.getScope() != null
1854                                          ? !overrideSpecification.getScope().equals(
1855                                         overriddenSpecification.getScope() )
1856                                          : overriddenSpecification.getScope() != null )
1857                                     {
1858                                         addDetail( validationContext.getReport(),
1859                                                    "IMPLEMENTATION_DEPENDENCY_SCOPE_CONSTRAINT", Level.SEVERE,
1860                                                    new ObjectFactory().createImplementation( implementation ),
1861                                                    "implementationDependencyScopeConstraint",
1862                                                    implementation.getIdentifier(), moduleOfImpl.getName(),
1863                                                    dependency.getName(), override.getName(),
1864                                                    a.getIdentifier(), moduleOfA.getName(),
1865                                                    overrideSpecification.getScope() == null
1866                                                    ? "Multiton" : overrideSpecification.getScope(),
1867                                                    overriddenSpecification.getScope() == null
1868                                                    ? "Multiton" : overriddenSpecification.getScope() );
1869 
1870                                     }
1871 
1872                                     if ( overriddenSpecification.getMultiplicity() == Multiplicity.MANY )
1873                                     {
1874                                         if ( override.getImplementationName() == null
1875                                              && overridden.getImplementationName() != null )
1876                                         {
1877                                             addDetail( validationContext.getReport(),
1878                                                        "IMPLEMENTATION_DEPENDENCY_NO_IMPLEMENTATION_NAME_CONSTRAINT",
1879                                                        Level.SEVERE,
1880                                                        new ObjectFactory().createImplementation( implementation ),
1881                                                        "implementationDependencyNoImplementationNameConstraint",
1882                                                        implementation.getIdentifier(), moduleOfImpl.getName(),
1883                                                        dependency.getName(), override.getName(),
1884                                                        a.getIdentifier(), moduleOfA.getName() );
1885 
1886                                         }
1887 
1888                                         if ( override.getImplementationName() != null
1889                                              && overridden.getImplementationName() == null )
1890                                         {
1891                                             addDetail( validationContext.getReport(),
1892                                                        "IMPLEMENTATION_DEPENDENCY_IMPLEMENTATION_NAME_CONSTRAINT",
1893                                                        Level.SEVERE,
1894                                                        new ObjectFactory().createImplementation( implementation ),
1895                                                        "implementationDependencyImplementationNameConstraint",
1896                                                        implementation.getIdentifier(), moduleOfImpl.getName(),
1897                                                        dependency.getName(), overridden.getName(),
1898                                                        a.getIdentifier(), moduleOfA.getName(),
1899                                                        override.getImplementationName() );
1900 
1901                                         }
1902                                     }
1903                                 }
1904 
1905                                 if ( override.isOptional() != overridden.isOptional() )
1906                                 {
1907                                     addDetail( validationContext.getReport(),
1908                                                "IMPLEMENTATION_DEPENDENCY_OPTIONALITY_CONSTRAINT", Level.SEVERE,
1909                                                new ObjectFactory().createImplementation( implementation ),
1910                                                "implementationDependencyOptonalityConstraint",
1911                                                implementation.getIdentifier(), moduleOfImpl.getName(),
1912                                                dependency.getName(), overridden.getName(),
1913                                                a.getIdentifier(), moduleOfA.getName() );
1914 
1915                                 }
1916                             }
1917                         }
1918                     }
1919                 }
1920 
1921                 if ( dependency.getMessages() != null )
1922                 {
1923                     for ( int j = 0, s1 = dependency.getMessages().getMessage().size(); j < s1; j++ )
1924                     {
1925                         final Message override = dependency.getMessages().getMessage().get( j );
1926 
1927                         final Set<InheritanceModel.Node<Message>> overriddenMessages =
1928                             modifiableSet( imodel.getMessageNodes( a.getIdentifier(), override.getName() ) );
1929 
1930                         if ( override.isOverride() && overriddenMessages.isEmpty() )
1931                         {
1932                             addDetail( validationContext.getReport(),
1933                                        "IMPLEMENTATION_DEPENDENCY_OVERRIDE_MESSAGE_CONSTRAINT", Level.SEVERE,
1934                                        new ObjectFactory().createImplementation( implementation ),
1935                                        "implementationDependencyOverrideMessageConstraint",
1936                                        implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
1937                                        override.getName(), a.getIdentifier(), moduleOfA.getName() );
1938 
1939                         }
1940 
1941                         if ( !( override.isOverride() || overriddenMessages.isEmpty() ) )
1942                         {
1943                             for ( final InheritanceModel.Node<Message> overriddenMessage : overriddenMessages )
1944                             {
1945                                 addDetail( validationContext.getReport(),
1946                                            "IMPLEMENTATION_DEPENDENCY_OVERRIDE_MESSAGE_WARNING", Level.WARNING,
1947                                            new ObjectFactory().createImplementation( implementation ),
1948                                            "implementationDependencyOverrideMessageWarning",
1949                                            implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
1950                                            override.getName(), a.getIdentifier(), moduleOfA.getName(),
1951                                            getNodePathString( overriddenMessage ) );
1952 
1953                             }
1954                         }
1955 
1956                         retainFinalNodes( overriddenMessages );
1957 
1958                         for ( final InheritanceModel.Node<Message> overriddenMessage : overriddenMessages )
1959                         {
1960                             addDetail( validationContext.getReport(),
1961                                        "IMPLEMENTATION_DEPENDENCY_FINAL_MESSAGE_CONSTRAINT", Level.SEVERE,
1962                                        new ObjectFactory().createImplementation( implementation ),
1963                                        "implementationDependencyFinalMessageConstraint",
1964                                        implementation.getIdentifier(), moduleOfImpl.getName(),
1965                                        dependency.getName(), override.getName(), a.getIdentifier(),
1966                                        moduleOfA.getName(), getNodePathString( overriddenMessage ) );
1967 
1968                         }
1969                     }
1970                 }
1971 
1972                 if ( dependency.getProperties() != null )
1973                 {
1974                     for ( int j = 0, s1 = dependency.getProperties().getProperty().size(); j < s1; j++ )
1975                     {
1976                         final Property override = dependency.getProperties().getProperty().get( j );
1977 
1978                         final Set<InheritanceModel.Node<Property>> overriddenProperties =
1979                             modifiableSet( imodel.getPropertyNodes( a.getIdentifier(), override.getName() ) );
1980 
1981                         if ( override.isOverride() && overriddenProperties.isEmpty() )
1982                         {
1983                             addDetail( validationContext.getReport(),
1984                                        "IMPLEMENTATION_DEPENDENCY_OVERRIDE_PROPERTY_CONSTRAINT", Level.SEVERE,
1985                                        new ObjectFactory().createImplementation( implementation ),
1986                                        "implementationDependencyOverridePropertyConstraint",
1987                                        implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
1988                                        override.getName(), a.getIdentifier(), moduleOfA.getName() );
1989 
1990                         }
1991 
1992                         if ( !( override.isOverride() || overriddenProperties.isEmpty() ) )
1993                         {
1994                             for ( final InheritanceModel.Node<Property> overriddenProperty : overriddenProperties )
1995                             {
1996                                 addDetail( validationContext.getReport(),
1997                                            "IMPLEMENTATION_DEPENDENCY_OVERRIDE_PROPERTY_WARNING", Level.WARNING,
1998                                            new ObjectFactory().createImplementation( implementation ),
1999                                            "implementationDependencyOverridePropertyWarning",
2000                                            implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
2001                                            override.getName(), a.getIdentifier(), moduleOfA.getName(),
2002                                            getNodePathString( overriddenProperty ) );
2003 
2004                             }
2005                         }
2006 
2007                         retainFinalNodes( overriddenProperties );
2008 
2009                         for ( final InheritanceModel.Node<Property> overriddenProperty : overriddenProperties )
2010                         {
2011                             addDetail( validationContext.getReport(),
2012                                        "IMPLEMENTATION_DEPENDENCY_FINAL_PROPERTY_CONSTRAINT", Level.SEVERE,
2013                                        new ObjectFactory().createImplementation( implementation ),
2014                                        "implementationDependencyFinalPropertyConstraint",
2015                                        implementation.getIdentifier(), moduleOfImpl.getName(), dependency.getName(),
2016                                        override.getName(), a.getIdentifier(), moduleOfA.getName(),
2017                                        getNodePathString( overriddenProperty ) );
2018 
2019                         }
2020                     }
2021                 }
2022             }
2023         }
2024 
2025         if ( dependency.getDependencies() != null )
2026         {
2027             for ( int i = 0, s0 = dependency.getDependencies().getDependency().size(); i < s0; i++ )
2028             {
2029                 final Dependency d = dependency.getDependencies().getDependency().get( i );
2030                 assertDependencyValid( validationContext, implementation, d );
2031             }
2032         }
2033     }
2034 
2035     private static void assertImplementationSpecificationCompatibility(
2036         final ValidationContext validationContext, final Implementation implementation )
2037     {
2038         final Specifications specs = validationContext.getModules().getSpecifications( implementation.getIdentifier() );
2039         final Module moduleOfImpl =
2040             validationContext.getModules().getModuleOfImplementation( implementation.getIdentifier() );
2041 
2042         if ( specs != null )
2043         {
2044             for ( int i = 0, s0 = specs.getReference().size(); i < s0; i++ )
2045             {
2046                 final SpecificationReference r = specs.getReference().get( i );
2047                 final Specification s = specs.getSpecification( r.getIdentifier() );
2048 
2049                 if ( s != null && r.getVersion() != null )
2050                 {
2051                     final Module moduleOfS =
2052                         validationContext.getModules().getModuleOfSpecification( s.getIdentifier() );
2053 
2054                     if ( s.getVersion() == null )
2055                     {
2056                         addDetail( validationContext.getReport(),
2057                                    "IMPLEMENTATION_SPECIFICATION_VERSIONING_CONSTRAINT", Level.SEVERE,
2058                                    new ObjectFactory().createImplementation( implementation ),
2059                                    "implementationSpecificationVersioningConstraint", implementation.getIdentifier(),
2060                                    moduleOfImpl.getName(), s.getIdentifier(), moduleOfS.getName() );
2061 
2062                     }
2063                     else
2064                     {
2065                         try
2066                         {
2067                             if ( VersionParser.compare( r.getVersion(), s.getVersion() ) != 0 )
2068                             {
2069                                 addDetail( validationContext.getReport(),
2070                                            "IMPLEMENTATION_SPECIFICATION_COMPATIBILITY_CONSTRAINT", Level.SEVERE,
2071                                            new ObjectFactory().createImplementation( implementation ),
2072                                            "implementationSpecificationCompatibilityConstraint",
2073                                            implementation.getIdentifier(), moduleOfImpl.getName(), s.getIdentifier(),
2074                                            moduleOfS.getName(), r.getVersion(), s.getVersion() );
2075 
2076                             }
2077                         }
2078                         catch ( final ParseException e )
2079                         {
2080                             final String message = getMessage( e );
2081 
2082                             if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
2083                             {
2084                                 validationContext.getModelContext().log( Level.FINE, message, e );
2085                             }
2086 
2087                             addDetail( validationContext.getReport(),
2088                                        "IMPLEMENTATION_SPECIFICATION_COMPATIBILITY_VERSIONING_PARSE_EXCEPTION",
2089                                        Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
2090                                        "implementationSpecificationCompatibilityVersioningParseException",
2091                                        implementation.getIdentifier(), moduleOfImpl.getName(), s.getIdentifier(),
2092                                        moduleOfS.getName(), r.getVersion(),
2093                                        message != null && message.length() > 0 ? " " + message : "" );
2094 
2095                         }
2096                         catch ( final TokenMgrError e )
2097                         {
2098                             final String message = getMessage( e );
2099 
2100                             if ( validationContext.getModelContext().isLoggable( Level.FINE ) )
2101                             {
2102                                 validationContext.getModelContext().log( Level.FINE, message, e );
2103                             }
2104 
2105                             addDetail( validationContext.getReport(),
2106                                        "IMPLEMENTATION_SPECIFICATION_COMPATIBILITY_VERSIONING_TOKEN_MANAGER_ERROR",
2107                                        Level.SEVERE, new ObjectFactory().createImplementation( implementation ),
2108                                        "implementationSpecificationCompatibilityVersioningTokenManagerError",
2109                                        implementation.getIdentifier(), moduleOfImpl.getName(), s.getIdentifier(),
2110                                        moduleOfS.getName(), r.getVersion(),
2111                                        message != null && message.length() > 0 ? " " + message : "" );
2112 
2113                         }
2114                     }
2115                 }
2116             }
2117         }
2118     }
2119 
2120     private static boolean isInheritanceCycle( final ValidationContext validationContext, final Implementation current,
2121                                                Map<String, Implementation> implementations, final List<String> path )
2122     {
2123         if ( implementations == null )
2124         {
2125             implementations = new HashMap<String, Implementation>();
2126         }
2127 
2128         if ( current != null )
2129         {
2130             path.add( current.getIdentifier() );
2131 
2132             if ( implementations.containsKey( current.getIdentifier() ) )
2133             {
2134                 return true;
2135             }
2136 
2137             implementations.put( current.getIdentifier(), current );
2138 
2139             if ( current.getImplementations() != null )
2140             {
2141                 for ( int i = 0, s0 = current.getImplementations().getReference().size(); i < s0; i++ )
2142                 {
2143                     final ImplementationReference r = current.getImplementations().getReference().get( i );
2144                     return isInheritanceCycle(
2145                         validationContext, validationContext.getModules().getImplementation( r.getIdentifier() ),
2146                         implementations, path );
2147 
2148                 }
2149             }
2150 
2151             path.remove( current.getIdentifier() );
2152         }
2153 
2154         return false;
2155     }
2156 
2157     private static <T> String getNodePathString( final InheritanceModel.Node<T> node )
2158     {
2159         final StringBuilder b = new StringBuilder( node.getPath().size() * 50 );
2160 
2161         for ( int i = 0, s0 = node.getPath().size(); i < s0; i++ )
2162         {
2163             final InheritanceModel.Node<Implementation> pathNode = node.getPath().get( i );
2164 
2165             if ( pathNode.getClassDeclaration() != null )
2166             {
2167                 b.append( " -> [" ).append( pathNode.getClassDeclaration().getClazz() ).append( "] @ '" ).
2168                     append( pathNode.getImplementation().getIdentifier() ).append( "'" );
2169 
2170             }
2171             if ( pathNode.getSpecification() != null )
2172             {
2173                 b.append( " -> <" ).append( pathNode.getSpecification().getIdentifier() ).append( "> @ '" ).
2174                     append( pathNode.getImplementation().getIdentifier() ).append( "'" );
2175 
2176             }
2177             else
2178             {
2179                 b.append( " -> '" ).append( pathNode.getImplementation().getIdentifier() ).append( "'" );
2180             }
2181         }
2182 
2183         if ( node.getClassDeclaration() != null )
2184         {
2185             b.append( " -> [" ).append( node.getClassDeclaration().getClazz() ).append( "] @ '" ).
2186                 append( node.getImplementation().getIdentifier() ).append( "'" );
2187 
2188         }
2189         if ( node.getSpecification() != null )
2190         {
2191             b.append( " -> <" ).append( node.getSpecification().getIdentifier() ).append( "> @ '" ).
2192                 append( node.getImplementation().getIdentifier() ).append( "'" );
2193 
2194         }
2195 
2196         return b.length() > 0 ? b.substring( " -> ".length() ) : b.toString();
2197     }
2198 
2199     private static <T> String getNodeListPathString( final Collection<? extends InheritanceModel.Node<T>> nodes )
2200     {
2201         final StringBuilder path = new StringBuilder( nodes.size() * 255 );
2202 
2203         for ( final InheritanceModel.Node<T> node : nodes )
2204         {
2205             path.append( ", " ).append( getNodePathString( node ) );
2206         }
2207 
2208         return path.length() > 1 ? path.substring( 2 ) : path.toString();
2209     }
2210 
2211     private static <T> Set<InheritanceModel.Node<T>> retainFinalNodes( final Set<InheritanceModel.Node<T>> set )
2212     {
2213         if ( set != null )
2214         {
2215             for ( final Iterator<InheritanceModel.Node<T>> it = set.iterator(); it.hasNext(); )
2216             {
2217                 if ( !it.next().isFinal() )
2218                 {
2219                     it.remove();
2220                 }
2221             }
2222         }
2223 
2224         return set;
2225     }
2226 
2227     private static void addDetail(
2228         final ModelValidationReport report, final String identifier, final Level level,
2229         final JAXBElement<? extends ModelObject> element, final String messageKey, final Object... messageArguments )
2230     {
2231         report.getDetails().add( new ModelValidationReport.Detail(
2232             identifier, level, getMessage( messageKey, messageArguments ), element ) );
2233 
2234     }
2235 
2236     private static <T> Set<T> modifiableSet( final Collection<? extends T> col )
2237     {
2238         Set<T> set = Collections.emptySet();
2239 
2240         if ( col != null )
2241         {
2242             set = new HashSet<T>( col );
2243         }
2244 
2245         return set;
2246     }
2247 
2248     private static String getMessage( final String key, final Object... messageArguments )
2249     {
2250         return MessageFormat.format( ResourceBundle.getBundle(
2251             DefaultModelValidator.class.getName().replace( '.', '/' ),
2252             Locale.getDefault() ).getString( key ), messageArguments );
2253 
2254     }
2255 
2256     private static String getMessage( final Throwable t )
2257     {
2258         return t != null ? t.getMessage() != null ? t.getMessage() : getMessage( t.getCause() ) : null;
2259     }
2260 
2261     /** @since 1.2 */
2262     private static final class ValidationContext
2263     {
2264 
2265         private final ModelContext modelContext;
2266 
2267         private final Modules modules;
2268 
2269         private final ModelValidationReport report;
2270 
2271         private final InheritanceModel inheritanceModel;
2272 
2273         private ValidationContext( final ModelContext modelContext, final Modules modules,
2274                                    final ModelValidationReport report )
2275         {
2276             super();
2277             this.modelContext = modelContext;
2278             this.modules = modules;
2279             this.report = report;
2280             this.inheritanceModel = new InheritanceModel( modules );
2281         }
2282 
2283         private ModelContext getModelContext()
2284         {
2285             return modelContext;
2286         }
2287 
2288         private Modules getModules()
2289         {
2290             return modules;
2291         }
2292 
2293         private ModelValidationReport getReport()
2294         {
2295             return report;
2296         }
2297 
2298         private InheritanceModel getInheritanceModel()
2299         {
2300             return this.inheritanceModel;
2301         }
2302 
2303     }
2304 
2305 }