package org.modeldriven.fuml.io; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.modeldriven.fuml.FumlObject; import org.modeldriven.fuml.assembly.ElementAssemblerEvent; import org.modeldriven.fuml.assembly.ElementAssemblerEventListener; import org.modeldriven.fuml.assembly.ElementAssemblerResultsEvent; import org.modeldriven.fuml.repository.Repository; import org.modeldriven.fuml.repository.RepositoryArtifact; import org.modeldriven.fuml.repository.ext.Stereotype; import org.modeldriven.fuml.xmi.stream.StreamReader; import org.modeldriven.fuml.xmi.validation.ErrorSeverity; import org.modeldriven.fuml.xmi.validation.ValidationErrorEvent; import org.modeldriven.fuml.xmi.validation.ValidationEvent; import org.modeldriven.fuml.xmi.validation.ValidationEventListener; import fUML.Syntax.Activities.IntermediateActivities.Activity; import fUML.Syntax.Classes.Kernel.Class_; import fUML.Syntax.Classes.Kernel.EnumerationLiteral; import fUML.Syntax.Classes.Kernel.PrimitiveType; import fUML.Syntax.Classes.Kernel.Enumeration; import fUML.Syntax.Classes.Kernel.DataType; import fUML.Syntax.Classes.Kernel.Element; import fUML.Syntax.Classes.Kernel.NamedElement; import fUML.Syntax.Classes.Kernel.Property; import fUML.Syntax.Classes.Kernel.Package; import fUML.Syntax.CommonBehaviors.BasicBehaviors.OpaqueBehavior; public class ArtifactLoader implements ValidationEventListener, ElementAssemblerEventListener, ElementReaderEventListener { private static Log log = LogFactory.getLog(ArtifactLoader.class); protected List<Class_> classList = new ArrayList<Class_>(); protected RepositoryArtifact artifact; protected BasicElementReader modelElementReader; protected boolean validateExternalReferences = true; protected boolean assembleExternalReferences = true; public ArtifactLoader() { this.modelElementReader = new BasicElementReader(); } public ArtifactLoader(BasicElementReader modelElementReader) { this.modelElementReader = modelElementReader; } public boolean isValidateExternalReferences() { return this.modelElementReader.isValidateExternalReferences(); } public void setValidateExternalReferences(boolean validateExternalReferences) { this.modelElementReader.setValidateExternalReferences(validateExternalReferences); } public boolean isAssembleExternalReferences() { return this.modelElementReader.isAssembleExternalReferences(); } public void setAssembleExternalReferences(boolean assembleExternalReferences) { this.modelElementReader.setAssembleExternalReferences(assembleExternalReferences); } public void read(FileArtifact artifact) { log.debug("reading " + artifact.getURN()); this.artifact = artifact; StreamReader reader = new StreamReader(); reader.addStreamNodeListener(modelElementReader); modelElementReader.addValidationEventListener(this); modelElementReader.addElementAssemblerEventListener(this); modelElementReader.addElementReaderEventListener(this); try { reader.read(new FileInputStream(artifact.getFile())); } catch (FileNotFoundException e) { throw new IOException(e); } } public void read(ResourceArtifact artifact) { this.artifact = artifact; log.debug("reading " + artifact.getURN()); StreamReader reader = new StreamReader(); reader.addStreamNodeListener(modelElementReader); modelElementReader.addValidationEventListener(this); modelElementReader.addElementAssemblerEventListener(this); modelElementReader.addElementReaderEventListener(this); reader.read(artifact.getInputStream()); } public void validationCompleted(ValidationEvent event) { if (log.isDebugEnabled()) log.debug("validation completed"); } public void validationError(ValidationErrorEvent event) { if (event.getError().getSeverity().ordinal() == ErrorSeverity.FATAL.ordinal()) log.error("(" + this.artifact.getURN() + ") validation error " + event.getError().getText()); else if (event.getError().getSeverity().ordinal() == ErrorSeverity.WARN.ordinal()) log.warn("(" + this.artifact.getURN() + ") validation error " + event.getError().getText()); else if (event.getError().getSeverity().ordinal() == ErrorSeverity.INFO.ordinal()) log.info("(" + this.artifact.getURN() + ") validation error " + event.getError().getText()); else log.error("(" + this.artifact.getURN() + ") validation error " + event.getError().getText()); } public void validationStarted(ValidationEvent event) { if (log.isDebugEnabled()) log.debug("validation started"); } public void elementAssembled(ElementAssemblerEvent event) { try { if (log.isDebugEnabled()) log.debug("element assembled: (" + event.getSource().getClass().getName() + ") "+ event.getSource().getXmiId()); } catch (java.lang.NullPointerException e) { if (event == null) log.error("found null event"); if (event.getSource() == null) log.error("found null event source"); log.error(e); } } public void elementGraphAssembled(ElementAssemblerResultsEvent event) { if (log.isDebugEnabled()) log.debug("element graph assembled"); Iterator<String> ids = event.getSource().getResultsXmiIds().iterator(); while (ids.hasNext()) { String id = ids.next(); FumlObject fumlObject = event.getSource().lookupResult(id); if (fumlObject == null) { log.warn("could not lookup element from id '" + id + "'"); continue; } if (fumlObject instanceof NamedElement) if (log.isDebugEnabled()) log.debug("loading: (" + fumlObject.getClass().getName() + ") " + ((NamedElement)fumlObject).qualifiedName + " (" + id + ")"); else if (log.isDebugEnabled()) log.debug("loading: (" + fumlObject.getClass().getName() + ") " + "(" + id + ")"); if (fumlObject instanceof Activity) { NamedElement namedElement = (NamedElement)fumlObject; Repository.INSTANCE.getMapping().mapElementByName(namedElement, this.artifact); Repository.INSTANCE.getMapping().mapElementById(namedElement, this.artifact); } else if (fumlObject instanceof Class_ && !(fumlObject instanceof OpaqueBehavior)) { Class_ clss = (Class_)fumlObject; classList.add(clss); if (!(clss instanceof Stereotype)) { if (clss.package_ != null) { Repository.INSTANCE.getMapping().mapClass(clss, getQualifiedPackageName(clss.package_), artifact); } else Repository.INSTANCE.getMapping().mapClass(clss, null, artifact); } else { Stereotype stereotype = (Stereotype)clss; if (stereotype.package_ != null) Repository.INSTANCE.getMapping().mapStereotype(stereotype, getQualifiedPackageName(stereotype.package_), artifact); else Repository.INSTANCE.getMapping().mapStereotype(stereotype, null, artifact); } } else if (fumlObject instanceof Enumeration) { Enumeration enumeration = (Enumeration)fumlObject; if (enumeration.package_ != null) Repository.INSTANCE.getMapping().mapEnumerationExternal(enumeration, getQualifiedPackageName(enumeration.package_), artifact); else Repository.INSTANCE.getMapping().mapEnumerationExternal(enumeration, null, artifact); } else if (fumlObject instanceof DataType) { if (!(fumlObject instanceof PrimitiveType)) { // datatypes DataType datatype = (DataType)fumlObject; if (datatype.package_ != null) Repository.INSTANCE.getMapping().mapDataType(datatype, getQualifiedPackageName(datatype.package_), artifact); else Repository.INSTANCE.getMapping().mapDataType(datatype, null, artifact); } } else if (fumlObject instanceof Property) { Property property = (Property)fumlObject; Repository.INSTANCE.getMapping().mapProperty(property.class_, property, this.artifact); } else if (fumlObject instanceof EnumerationLiteral) { EnumerationLiteral literal = (EnumerationLiteral)fumlObject; Repository.INSTANCE.getMapping().mapEnumerationLiteral(literal, null, artifact); } else if (fumlObject instanceof Package) { Package pkg = (Package)fumlObject; Repository.INSTANCE.getMapping().mapPackage(pkg, null, artifact); //Repository.INSTANCE.getMapping().mapElementByName(namedElement, this.artifact); //Repository.INSTANCE.getMapping().mapElementById(namedElement, this.artifact); } else if (fumlObject instanceof NamedElement) { NamedElement namedElement = (NamedElement)fumlObject; Repository.INSTANCE.getMapping().mapElementByName(namedElement, this.artifact); Repository.INSTANCE.getMapping().mapElementById(namedElement, this.artifact); } else if (fumlObject instanceof Element) { Element element = (Element)fumlObject; Repository.INSTANCE.getMapping().mapElementById(element, this.artifact); } else // can be a Comment which is not an Element if (log.isDebugEnabled()) log.debug("ignoring class, " + fumlObject.getClass().getName()); } } public void elementStubAssembled(ElementAssemblerResultsEvent event) { if (log.isDebugEnabled()) log.debug("element stub assembled"); Iterator<String> ids = event.getSource().getResultsXmiIds().iterator(); while (ids.hasNext()) { String id = ids.next(); FumlObject fumlObject = event.getSource().lookupResult(id); if (fumlObject instanceof NamedElement) if (log.isDebugEnabled()) log.debug("loading: (" + fumlObject.getClass().getName() + ") " + ((NamedElement)fumlObject).qualifiedName + " (" + id + ")"); else if (log.isDebugEnabled()) log.debug("loading: (" + fumlObject.getClass().getName() + ") " + "(" + id + ")"); if (fumlObject instanceof NamedElement) { NamedElement namedElement = (NamedElement)fumlObject; Repository.INSTANCE.getMapping().mapElementByName(namedElement, this.artifact); Repository.INSTANCE.getMapping().mapElementById(namedElement, this.artifact); log.warn("imported invalid " + namedElement.getClass() + " (" + namedElement.getXmiId() + ") '" + namedElement.name + "' as non-executable \"stub\" element"); } else if (fumlObject instanceof Element) { Element element = (NamedElement)fumlObject; Repository.INSTANCE.getMapping().mapElementById(element, this.artifact); log.warn("imported invalid " + fumlObject.getClass() + " (" + fumlObject.getXmiId() + " as non-executable \"stub\" element"); } else // can be a Comment which is not an Element if (log.isDebugEnabled()) log.debug("ignoring class, " + fumlObject.getClass().getName()); } } public void streamCompleted(ElementReaderEvent event) { for (Class_ c: classList) { org.modeldriven.fuml.repository.Class_ clss = null; if (!(c instanceof Stereotype)) { clss = new org.modeldriven.fuml.repository.model.Class_(c, this.artifact); } else { clss = new org.modeldriven.fuml.repository.model.Stereotype((Stereotype)c, this.artifact); } Repository.INSTANCE.loadClass(clss); } } private String getQualifiedPackageName(fUML.Syntax.Classes.Kernel.Package pkg) { List<fUML.Syntax.Classes.Kernel.Package> list = new ArrayList<fUML.Syntax.Classes.Kernel.Package>(); fUML.Syntax.Classes.Kernel.Package p = pkg; while (p != null) { list.add(p); p = p.nestingPackage; } StringBuilder buf = new StringBuilder(); for (int i = list.size()-1; i >= 0; i--) { if (i < list.size()-1) buf.append("."); buf.append(list.get(i).name); } return buf.toString(); } }