3535import org .modeldriven .fuml .config .ImportAdapter ;
3636import org .modeldriven .fuml .config .ImportAdapterType ;
3737import org .modeldriven .fuml .config .NamespaceDomain ;
38+ import org .modeldriven .fuml .config .NamespaceMapping ;
3839import org .modeldriven .fuml .config .ReferenceMappingType ;
3940import org .modeldriven .fuml .config .ValidationExemption ;
4041import org .modeldriven .fuml .config .ValidationExemptionType ;
@@ -740,28 +741,15 @@ private void assembleReferenceFeature(XmiReference reference) throws ClassNotFou
740741
741742 if (reference instanceof XmiExternalReferenceElement ) {
742743 if (assembleExternalReferences ) {
743- // FIXME: resolve these references inside/outside of lib(s)
744- if (id == null || !id .startsWith ("pathmap:" ))
745- {
746- Element referent = Library .getInstance ().lookup (id );
747- if (referent == null ) {
748- if (domain == null )
749- domain = FumlConfiguration .getInstance ().findNamespaceDomain (eventNode .getNamespaceURI ());
750-
751- ValidationExemption exemption = FumlConfiguration .getInstance ().findValidationExemptionByReference (ValidationExemptionType .EXTERNAL_REFERENCE ,
752- reference .getClassifier (), id , eventNode .getNamespaceURI (), domain );
753- if (exemption == null ) {
754- throw new ValidationException (new ValidationError (reference , id ,
755- ErrorCode .INVALID_EXTERNAL_REFERENCE , ErrorSeverity .FATAL ));
756- }
757- // otherwise don't attempt to assemble
758- }
759- else
760- this .assembleSingularReferenceFeature (referent , property , type );
761- }
744+ if (log .isDebugEnabled ())
745+ log .debug ("assembling singular external reference feature <" + type .getName () + "> "
746+ + this .getPrototype ().getName () + "." + property .getName ());
747+ Element referent = this .resolveExternalReference (eventNode , reference , id );
748+ if (referent != null )
749+ this .assembleSingularReferenceFeature (referent , property , type );
762750 }
763751 } else {
764- Element target = null ;
752+ FumlObject target = null ;
765753
766754 ElementAssembler referencedAssembler = this .assemblerMap .get (id );
767755 if (referencedAssembler != null )
@@ -785,44 +773,74 @@ private void assembleReferenceFeature(XmiReference reference) throws ClassNotFou
785773 String id = iter .next ();
786774 if (reference instanceof XmiExternalReferenceElement ) {
787775 if (assembleExternalReferences ) {
788- // FIXME: resolve these references inside/outside of lib(s)
789- if (id == null || !id .startsWith ("pathmap:" ))
790- {
791- Element referent = Library .getInstance ().lookup (id );
792- if (referent == null ) {
793- if (domain == null )
794- domain = FumlConfiguration .getInstance ().findNamespaceDomain (eventNode .getNamespaceURI ());
795-
796- ValidationExemption exemption = FumlConfiguration .getInstance ().findValidationExemptionByReference (ValidationExemptionType .EXTERNAL_REFERENCE ,
797- reference .getClassifier (), id , eventNode .getNamespaceURI (), domain );
798- if (exemption == null ) {
799- throw new ValidationException (new ValidationError (reference , id ,
800- ErrorCode .INVALID_EXTERNAL_REFERENCE , ErrorSeverity .FATAL ));
801- }
802- // otherwise don't attempt to assemble
803- }
804- else
805- this .assembleCollectionReferenceFeature (referent , property , type );
806- }
776+ Element referent = this .resolveExternalReference (eventNode , reference , id );
777+ if (referent != null )
778+ this .assembleCollectionReferenceFeature (referent , property , type );
807779 }
808780 } else {
809- FumlObject target = null ;
810-
811781 ElementAssembler referencedAssembler = this .assemblerMap .get (id );
812- if (referencedAssembler != null )
813- target = referencedAssembler .getTargetObject ();
814- else
815- target = Environment .getInstance ().findElementById (id );
816-
817- if (target != null )
818- this .assembleCollectionReferenceFeature (target , property , type );
819- else
782+ if (referencedAssembler == null )
820783 throw new ValidationException (new ValidationError (reference , id ,
821784 ErrorCode .INVALID_REFERENCE , ErrorSeverity .FATAL ));
785+ this .assembleCollectionReferenceFeature (referencedAssembler .getTargetObject (),
786+ property , type );
822787 }
823788 }
824789 }
825790 }
791+
792+ /**
793+ * Resolves a single external reference id by first resolving the pathmap if exists, then checking for
794+ * a valid library reference, then a valid qualified element reference. If neither a library or
795+ * element reference are found, a validation error is thrown.
796+ * @param eventNode the stream event node
797+ * @param reference the Xmi reference
798+ * @param id the id
799+ * @throws ValidationException when no mapping is found for a pathmap or when no library or qualified element
800+ * is found for the given id.
801+ * @return the resolved element
802+ */
803+ private Element resolveExternalReference (StreamNode eventNode , XmiReference reference , String id ) {
804+ NamespaceDomain domain = null ; // only lookup as needed
805+ if (id == null ) {
806+ throw new ValidationException (new ValidationError (reference , "" ,
807+ ErrorCode .INVALID_EXTERNAL_REFERENCE , ErrorSeverity .FATAL ));
808+ }
809+ String mappedId = id ;
810+ if (mappedId .toUpperCase ().startsWith ("PATHMAP:" )) {
811+ int idx = id .lastIndexOf ("#" );
812+ String pathmap = id .substring (0 , idx );
813+ NamespaceMapping mapping = FumlConfiguration .getInstance ().findPathmap (pathmap );
814+ if (mapping == null )
815+ throw new ValidationException (new ValidationError (reference , mappedId ,
816+ ErrorCode .INVALID_EXTERNAL_REFERENCE , ErrorSeverity .FATAL ));
817+ mappedId = mapping .getTarget () + id .substring (idx );
818+ if (log .isDebugEnabled ())
819+ log .debug ("resolved external pathmap reference '" + id + "' to '" + mappedId + "'" );
820+ }
821+ Element referent = Library .getInstance ().lookup (mappedId );
822+ if (referent == null ) {
823+ org .modeldriven .fuml .repository .Element elem = Repository .INSTANCE .findElementByQualifiedName (mappedId );
824+ if (elem != null )
825+ referent = elem .getDelegate ();
826+ }
827+ if (referent == null ) {
828+ if (domain == null )
829+ domain = FumlConfiguration .getInstance ().findNamespaceDomain (eventNode .getNamespaceURI ());
830+
831+ ValidationExemption exemption = FumlConfiguration .getInstance ().findValidationExemptionByReference (ValidationExemptionType .EXTERNAL_REFERENCE ,
832+ reference .getClassifier (), id , eventNode .getNamespaceURI (), domain );
833+ if (exemption == null )
834+ exemption = FumlConfiguration .getInstance ().findValidationExemptionByReference (ValidationExemptionType .EXTERNAL_REFERENCE ,
835+ reference .getClassifier (), mappedId , eventNode .getNamespaceURI (), domain );
836+ // if external reference not specifically exempted from validation
837+ if (exemption == null ) {
838+ throw new ValidationException (new ValidationError (reference , mappedId ,
839+ ErrorCode .INVALID_EXTERNAL_REFERENCE , ErrorSeverity .FATAL ));
840+ }
841+ }
842+ return referent ;
843+ }
826844
827845 @ SuppressWarnings ("rawtypes" )
828846 private void assembleEnumerationFeature (Property property , Object value , Classifier type )
0 commit comments