package org.modeldriven.fuml.repository.model;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.modeldriven.fuml.FumlObject;
import org.modeldriven.fuml.common.reflect.ReflectionUtils;
import org.modeldriven.fuml.config.FumlConfiguration;
import org.modeldriven.fuml.config.NamespaceDomain;
import org.modeldriven.fuml.repository.RepositoryArtifact;
import org.modeldriven.fuml.repository.RepositoryMapping;
import org.modeldriven.fuml.repository.RepositorylException;
import org.modeldriven.fuml.repository.ext.Extension;
import org.modeldriven.fuml.repository.ext.Stereotype;
import org.modeldriven.fuml.repository.merge.PackageGraphNode;
import UMLPrimitiveTypes.UnlimitedNatural;
import fUML.Syntax.Classes.Kernel.Association;
import fUML.Syntax.Classes.Kernel.Class_;
import fUML.Syntax.Classes.Kernel.Classifier;
import fUML.Syntax.Classes.Kernel.DataType;
import fUML.Syntax.Classes.Kernel.Element;
import fUML.Syntax.Classes.Kernel.Enumeration;
import fUML.Syntax.Classes.Kernel.EnumerationLiteral;
import fUML.Syntax.Classes.Kernel.Generalization;
import fUML.Syntax.Classes.Kernel.InstanceValue;
import fUML.Syntax.Classes.Kernel.LiteralBoolean;
import fUML.Syntax.Classes.Kernel.LiteralInteger;
import fUML.Syntax.Classes.Kernel.LiteralNull;
import fUML.Syntax.Classes.Kernel.LiteralString;
import fUML.Syntax.Classes.Kernel.LiteralUnlimitedNatural;
import fUML.Syntax.Classes.Kernel.NamedElement;
import fUML.Syntax.Classes.Kernel.Package;
import fUML.Syntax.Classes.Kernel.PackageableElement;
import fUML.Syntax.Classes.Kernel.PrimitiveType;
import fUML.Syntax.Classes.Kernel.Property;
import fUML.Syntax.Classes.Kernel.ValueSpecification;
public class InMemoryMapping implements RepositoryMapping
{
private Log log = LogFactory.getLog(InMemoryMapping.class);
// generic maps
protected Map<String, org.modeldriven.fuml.repository.Element> elementIdToElementMap = new HashMap<String, org.modeldriven.fuml.repository.Element>();
protected Map<String, org.modeldriven.fuml.repository.NamedElement> elementNameToElementMap = new HashMap<String, org.modeldriven.fuml.repository.NamedElement>();
protected Map<String, org.modeldriven.fuml.repository.NamedElement> qualifiedElementNameToElementMap = new HashMap<String, org.modeldriven.fuml.repository.NamedElement>();
// unqualified classifier specific maps
protected Map<String, org.modeldriven.fuml.repository.Classifier> classifierNameToClassifierMap = new HashMap<String, org.modeldriven.fuml.repository.Classifier>();
protected Map<String, String> classifierNameToPackageNameMap = new HashMap<String, String>();
// qualified classifier specific maps
protected Map<String, org.modeldriven.fuml.repository.Classifier> qualifiedClassifierNameToClassifierMap = new HashMap<String, org.modeldriven.fuml.repository.Classifier>();
protected Map<String, String> qualifiedClassifierNameToPackageNameMap = new HashMap<String, String>();
// maps qualifier XMI ID rather than qualified name, as target classifier
// may not have yet been unmarshalled, to specializations
protected Map<String, List<org.modeldriven.fuml.repository.Classifier>> classifierIdToSpecializationClassifierMap = new HashMap<String, List<org.modeldriven.fuml.repository.Classifier>>();
// package specific maps
protected Map<String, org.modeldriven.fuml.repository.Package> qualifiedPackageNameToPackageMap = new HashMap<String, org.modeldriven.fuml.repository.Package>();
// package merge maps
protected Map<String, PackageGraphNode> packageIdToPackageMergeMap = new HashMap<String, PackageGraphNode>();
protected Map<String, List<org.modeldriven.fuml.repository.Package>> artifactURIToPackagesMap = new HashMap<String, List<org.modeldriven.fuml.repository.Package>>();
// Stereotype and extension maps
protected Map<String, List<org.modeldriven.fuml.repository.Extension>> elementToExtensionListMap = new HashMap<String, List<org.modeldriven.fuml.repository.Extension>>();
protected Map<String, List<org.modeldriven.fuml.repository.Stereotype>> elementToStereotypeListMap = new HashMap<String, List<org.modeldriven.fuml.repository.Stereotype>>();
protected Map<Class<?>, List<org.modeldriven.fuml.repository.Stereotype>> classToStereotypeListMap = new HashMap<Class<?>, List<org.modeldriven.fuml.repository.Stereotype>>();
protected InMemoryMapping() {}
public org.modeldriven.fuml.repository.Element getElementById(String id)
{
org.modeldriven.fuml.repository.Element result = elementIdToElementMap.get(id);
if (result != null)
return result;
else
throw new RepositorylException("could not get element from XMI ID, '"
+ id + "'");
}
public org.modeldriven.fuml.repository.Element findElementById(String id)
{
return elementIdToElementMap.get(id);
}
public org.modeldriven.fuml.repository.Element getElementByName(String name)
{
org.modeldriven.fuml.repository.Element result = elementNameToElementMap.get(name);
if (result != null)
return result;
else
throw new RepositorylException("could not get element from name, '"
+ name + "'");
}
public org.modeldriven.fuml.repository.Element findElementByName(String name)
{
return elementNameToElementMap.get(name);
}
public org.modeldriven.fuml.repository.Element getElementByQualifiedName(String qualifiedName)
{
org.modeldriven.fuml.repository.Element result = qualifiedElementNameToElementMap.get(qualifiedName);
if (result != null)
return result;
else
throw new RepositorylException("could not get element from qualified name, '"
+ qualifiedName + "'");
}
public org.modeldriven.fuml.repository.Element findElementByQualifiedName(String qualifiedName)
{
return qualifiedElementNameToElementMap.get(qualifiedName);
}
public int getElementCount(Class<? extends Element> clss) {
int result = 0;
Iterator<String> keys = elementNameToElementMap.keySet().iterator();
while (keys.hasNext())
{
org.modeldriven.fuml.repository.Element element = elementNameToElementMap.get(keys.next());
if (clss.isAssignableFrom(element.getDelegate().getClass()))
result++;
}
return result;
}
public String[] getElementNames(Class<? extends Element> clss) {
List<String> list = new ArrayList<String>();
Iterator<String> keys = elementNameToElementMap.keySet().iterator();
while (keys.hasNext())
{
org.modeldriven.fuml.repository.Element element = elementNameToElementMap.get(keys.next());
if (clss.isAssignableFrom(element.getDelegate().getClass()))
list.add(((NamedElement)element.getDelegate()).name);
}
String[] result = new String[list.size()];
list.toArray(result);
return result;
}
public org.modeldriven.fuml.repository.Classifier getClassifierByName(String name) {
return classifierNameToClassifierMap.get(name);
}
public org.modeldriven.fuml.repository.Classifier getClassifierByQualifiedName(String qualifiedName) {
return qualifiedClassifierNameToClassifierMap.get(qualifiedName);
}
public org.modeldriven.fuml.repository.Package getPackageByQualifiedName(String qualifiedName) {
org.modeldriven.fuml.repository.Package result = qualifiedPackageNameToPackageMap.get(qualifiedName);
if (result != null)
return result;
else
throw new RepositorylException("could not get package from qualified name, '"
+ qualifiedName + "'");
}
public void mapElementById(Element element, RepositoryArtifact artifact) {
org.modeldriven.fuml.repository.Element elem =
new org.modeldriven.fuml.repository.model.Element(element, artifact);
elementIdToElementMap.put(element.getXmiId(), elem);
String globalId = artifact.getURN() + "#" + element.getXmiId();
if (elementIdToElementMap.get(globalId) != null)
throw new RepositorylException("found existing reference, '"
+ globalId + "'");
elementIdToElementMap.put(globalId, elem);
}
public void mapElementByName(NamedElement element, RepositoryArtifact artifact) {
if (element instanceof Class_) {
org.modeldriven.fuml.repository.Class_ clss =
new org.modeldriven.fuml.repository.model.Class_((Class_)element, artifact);
elementNameToElementMap.put(element.name, clss);
classifierNameToClassifierMap.put(element.name, clss);
if (element.qualifiedName != null) {
qualifiedElementNameToElementMap.put(element.qualifiedName, clss);
qualifiedClassifierNameToClassifierMap.put(element.qualifiedName, clss);
}
}
else if (element instanceof Classifier) {
org.modeldriven.fuml.repository.Classifier classifier =
new org.modeldriven.fuml.repository.model.Classifier((Classifier)element, artifact);
elementNameToElementMap.put(element.name, classifier);
classifierNameToClassifierMap.put(element.name, classifier);
if (element.qualifiedName != null) {
qualifiedElementNameToElementMap.put(element.qualifiedName, classifier);
qualifiedClassifierNameToClassifierMap.put(element.qualifiedName, classifier);
}
}
else {
org.modeldriven.fuml.repository.NamedElement elem =
new org.modeldriven.fuml.repository.model.NamedElement(element, artifact);
elementNameToElementMap.put(element.name, elem);
if (element.qualifiedName != null)
qualifiedElementNameToElementMap.put(element.qualifiedName, elem);
}
}
public void mapPackage(Package p, String currentPackageName, RepositoryArtifact artifact) {
String qualifiedName = null;
if (currentPackageName != null)
qualifiedName = currentPackageName + "." + p.name;
if (log.isDebugEnabled())
log.debug("mapping package, " + artifact.getURN() + "#" + p.name + "(" + currentPackageName + ")");
org.modeldriven.fuml.repository.Package pkg = new org.modeldriven.fuml.repository.model.Package(p, artifact);
// NOTE: This is to provide a consistent way to resolve library element
// names, for add-on functionality.
if (qualifiedName != null) {
if (log.isDebugEnabled())
log.debug("mapping package, " + artifact.getURN() + "#" + p.name + " by package qualified name: " + qualifiedName);
if (qualifiedPackageNameToPackageMap.get(qualifiedName) != null)
throw new RepositorylException("found existing package, '"
+ qualifiedName + ".");
qualifiedPackageNameToPackageMap.put(qualifiedName, pkg);
}
List<org.modeldriven.fuml.repository.Package> artifactPackages = artifactURIToPackagesMap.get(artifact.getURN());
if (artifactPackages == null)
{
artifactPackages = new ArrayList<org.modeldriven.fuml.repository.Package>();
artifactURIToPackagesMap.put(artifact.getURN(), artifactPackages);
}
artifactPackages.add(pkg);
if (elementIdToElementMap.get(p.getXmiId()) != null)
throw new RepositorylException("found existing package reference, '"
+ p.getXmiId() + ".");
elementIdToElementMap.put(p.getXmiId(), pkg);
String globalId = artifact.getURN() + "#" + p.getXmiId();
if (elementIdToElementMap.get(globalId) != null)
throw new RepositorylException("found existing package reference, '"
+ globalId + "'");
elementIdToElementMap.put(globalId, pkg);
}
public void mapPackageMerge(Package p, String sourcePackageXmiId) {
if (log.isDebugEnabled())
log.debug("mapping package merge, " + p.qualifiedName + "->" + sourcePackageXmiId);
PackageGraphNode target = packageIdToPackageMergeMap.get(p.getXmiId());
if (target == null)
{
target = new PackageGraphNode(p.getXmiId());
packageIdToPackageMergeMap.put(p.getXmiId(), target);
}
PackageGraphNode source = packageIdToPackageMergeMap.get(sourcePackageXmiId);
if (source == null) {
source = new PackageGraphNode(sourcePackageXmiId);
packageIdToPackageMergeMap.put(sourcePackageXmiId, source);
}
if (target.contains(source))
throw new RepositorylException("found existing merge node (" + sourcePackageXmiId
+ ") in target, " + p.qualifiedName + " ("
+ p.getXmiId() + ")");
target.addNode(source);
}
public void mapClass(Class_ clss, String currentPackageName, RepositoryArtifact artifact) {
org.modeldriven.fuml.repository.Class_ repositoryClass =
new org.modeldriven.fuml.repository.model.Class_(clss, artifact);
mapClassifier(clss, repositoryClass, currentPackageName,
artifact);
}
public void mapClassifier(Classifier classifier, String currentPackageName, RepositoryArtifact artifact) {
org.modeldriven.fuml.repository.Classifier repositoryClassifier =
new org.modeldriven.fuml.repository.model.Classifier(classifier, artifact);
mapClassifier(classifier, repositoryClassifier, currentPackageName,
artifact);
}
private void mapClassifier(Classifier classifier,
org.modeldriven.fuml.repository.Classifier repositoryClassifier,
String currentPackageName, RepositoryArtifact artifact) {
String packageQualifiedName = null;
if (currentPackageName != null)
packageQualifiedName = currentPackageName + "." + classifier.name;
else
packageQualifiedName = classifier.name; // is a qualified name as it may not have a package
if (log.isDebugEnabled())
log.debug("mapping class, " + artifact.getURN() + "#" + packageQualifiedName);
if (qualifiedClassifierNameToClassifierMap.get(packageQualifiedName) != null)
throw new RepositorylException("found existing classifier by package qualified name, '"
+ packageQualifiedName + "' while mapping artifact, "
+ artifact.getURN());
qualifiedClassifierNameToClassifierMap.put(packageQualifiedName, repositoryClassifier);
qualifiedClassifierNameToPackageNameMap.put(packageQualifiedName,
currentPackageName);
qualifiedElementNameToElementMap.put(packageQualifiedName, repositoryClassifier);
if (artifact.getNamespaceURI() != null) {
String artifactNamespaceQualifiedName = artifact.getNamespaceURI()
+ "#" + classifier.name;
if (qualifiedClassifierNameToClassifierMap.get(artifactNamespaceQualifiedName) != null)
if (log.isDebugEnabled())
log.debug("found existing classifier by artifact qualified name, '"
+ artifactNamespaceQualifiedName + "' while mapping artifact, "
+ artifact.getURN());
qualifiedClassifierNameToClassifierMap.put(artifactNamespaceQualifiedName, repositoryClassifier);
}
else
log.warn("missing artifact URI - could not map classifier '"
+ classifier.name + "' as externally referencable by artifact URI");
if (elementIdToElementMap.get(classifier.getXmiId()) != null)
throw new RepositorylException("found existing classifier reference, '"
+ classifier.getXmiId() + "' while mapping artifact, "
+ artifact.getURN());
elementIdToElementMap.put(classifier.getXmiId(), repositoryClassifier);
String globalId = artifact.getURN() + "#" + classifier.getXmiId();
if (elementIdToElementMap.get(globalId) != null)
throw new RepositorylException("found existing classifier reference, '"
+ globalId + "' while mapping artifact, "
+ artifact.getURN());
elementIdToElementMap.put(globalId, repositoryClassifier);
// so all classifiers can be externally referenced (i.e. external XMI references)using a "generic"
// namespace assigned currently in the model artifact config entry
// FIXME: note mapping artifact qualified datatypes to qualifiedClassifierNameToClassifierMap below !!!
if (artifact.getNamespaceURI() != null) {
String artifactNamespaceQualifiedName = artifact.getNamespaceURI()
+ "#" + classifier.name;
if (elementIdToElementMap.get(artifactNamespaceQualifiedName) != null)
if (log.isDebugEnabled())
log.debug("found existing classifier, '"
+ artifactNamespaceQualifiedName + "' while mapping artifact, "
+ artifact.getURN());
elementIdToElementMap.put(artifactNamespaceQualifiedName, repositoryClassifier);
}
else
log.warn("missing artifact URI - could not map element '"
+ classifier.name + "' as externally referencable by artifact URI");
Iterator<Generalization> sourceIter = classifier.generalization.iterator();
while (sourceIter.hasNext()) {
Generalization generalization = sourceIter.next();
List<org.modeldriven.fuml.repository.Classifier> list =
this.classifierIdToSpecializationClassifierMap.get(generalization.general.getXmiId());
if (list == null) {
list = new ArrayList<org.modeldriven.fuml.repository.Classifier>();
this.classifierIdToSpecializationClassifierMap.put(generalization.general.getXmiId(), list);
}
list.add(repositoryClassifier);
}
}
public void mapStereotype(Stereotype stereotype, String currentPackageName, RepositoryArtifact artifact) {
String packageQualifiedName = null;
if (currentPackageName != null)
packageQualifiedName = currentPackageName + "." + stereotype.name;
else
packageQualifiedName = stereotype.name; // is a qualified name as it may not have a package
if (log.isDebugEnabled())
log.debug("mapping stereotype, " + artifact.getURN() + "#" + packageQualifiedName);
// try and find the classifier for this stereotype to determine
// how to map it
if (stereotype.getXmiNamespace() != null) {
// use our actual Java class instance name to find our classifier if exists
String xmiNamespaceQualifiedClassifierName = stereotype.getXmiNamespace()
+ "#" + stereotype.getClass().getSimpleName();
//org.modeldriven.fuml.repository.Stereotype stereotypeClassifier = (org.modeldriven.fuml.repository.Stereotype)qualifiedClassifierNameToClassifierMap.get(xmiNamespaceQualifiedClassifierName);
//if this is the stereotype definition in an instance model, not the profile model
org.modeldriven.fuml.repository.Class_ stereotypeClassifier = (org.modeldriven.fuml.repository.Class_)qualifiedClassifierNameToClassifierMap.get(xmiNamespaceQualifiedClassifierName);
if (stereotypeClassifier != null && stereotypeClassifier instanceof org.modeldriven.fuml.repository.Stereotype) {
boolean foundExtension = false;
for (fUML.Syntax.Classes.Kernel.Property prop : stereotypeClassifier.getDelegate().ownedAttribute)
{
if (prop.name == null || !prop.name.startsWith("base_"))
continue;
if (prop.association == null)
continue;
org.modeldriven.fuml.repository.Element assocElement = null;
if ((assocElement = elementIdToElementMap.get(prop.association.getXmiId())) == null)
throw new RepositorylException("could not find association reference, '"
+ prop.association.getXmiId() + "' while mapping artifact, "
+ artifact.getURN());
fUML.Syntax.Classes.Kernel.Element delegateElement = assocElement.getDelegate();
if (!(delegateElement instanceof Extension))
continue;
foundExtension = true;
Extension extension = (Extension)assocElement.getDelegate();
String targetClassAttributeName = prop.name;
try {
FumlObject targetElement = null;
try {
targetElement = (FumlObject)ReflectionUtils.invokePublicGetterOrField(
stereotype, targetClassAttributeName);
} catch (InvocationTargetException e) {
}
//Field targetClassField = stereotype.getClass().getField(targetClassAttributeName);
//Element targetElement = (Element)targetClassField.get(stereotype);
if (targetElement == null)
throw new RepositorylException("no target element found linked to Stereotype instance, '"
+ stereotype.getXmiId() + "' by field '"
+ targetClassAttributeName
+ "' while mapping artifact, "
+ artifact.getURN());
List<org.modeldriven.fuml.repository.Extension> list = elementToExtensionListMap.get(targetElement.getXmiId());
if (list == null) {
list = new ArrayList<org.modeldriven.fuml.repository.Extension>();
elementToExtensionListMap.put(targetElement.getXmiId(), list);
}
list.add(new org.modeldriven.fuml.repository.model.Extension(extension, artifact));
List<org.modeldriven.fuml.repository.Stereotype> elementStereotypeList = elementToStereotypeListMap.get(targetElement.getXmiId());
if (elementStereotypeList == null) {
elementStereotypeList = new ArrayList<org.modeldriven.fuml.repository.Stereotype>();
elementToStereotypeListMap.put(targetElement.getXmiId(), elementStereotypeList);
}
org.modeldriven.fuml.repository.model.Stereotype repoStereotype = new org.modeldriven.fuml.repository.model.Stereotype(stereotype, artifact);
elementStereotypeList.add(repoStereotype);
List<org.modeldriven.fuml.repository.Stereotype> classStereotypeList = classToStereotypeListMap.get(repoStereotype.getDelegate().getClass());
if (classStereotypeList == null) {
classStereotypeList = new ArrayList<org.modeldriven.fuml.repository.Stereotype>();
classToStereotypeListMap.put(repoStereotype.getDelegate().getClass(), classStereotypeList);
}
classStereotypeList.add(repoStereotype);
} catch (SecurityException e) {
throw new RepositorylException(e);
} catch (IllegalArgumentException e) {
throw new RepositorylException(e);
} catch (IllegalAccessException e) {
throw new RepositorylException(e);
}
}
if (!foundExtension)
throw new RepositorylException("could not find extension property for Stereotype, '"
+ stereotype.getXmiId() + "' while mapping artifact, "
+ artifact.getURN());
}
else {
if (qualifiedClassifierNameToClassifierMap.get(packageQualifiedName) != null)
throw new RepositorylException("found existing classifier, '"
+ packageQualifiedName + "' while mapping artifact, "
+ artifact.getURN());
stereotypeClassifier = new org.modeldriven.fuml.repository.model.Stereotype(stereotype, artifact);
qualifiedClassifierNameToClassifierMap.put(packageQualifiedName, stereotypeClassifier);
qualifiedClassifierNameToPackageNameMap.put(packageQualifiedName,
currentPackageName);
qualifiedElementNameToElementMap.put(packageQualifiedName, stereotypeClassifier);
if (artifact.getNamespaceURI() != null) {
String artifactNamespaceQualifiedName = artifact.getNamespaceURI()
+ "#" + stereotype.name;
if (qualifiedClassifierNameToClassifierMap.get(artifactNamespaceQualifiedName) != null)
if (log.isDebugEnabled())
log.debug("found existing classifier, '"
+ artifactNamespaceQualifiedName + "' while mapping artifact, "
+ artifact.getURN());
qualifiedClassifierNameToClassifierMap.put(artifactNamespaceQualifiedName, stereotypeClassifier);
}
else
log.warn("missing artifact URI - could not map classifier '"
+ stereotype.name + "' as externally referencable by artifact URI");
}
}
if (elementIdToElementMap.get(stereotype.getXmiId()) != null)
throw new RepositorylException("found existing classifier reference, '"
+ stereotype.getXmiId() + "' while mapping artifact, "
+ artifact.getURN());
org.modeldriven.fuml.repository.Stereotype strtpe = new org.modeldriven.fuml.repository.model.Stereotype(stereotype, artifact);
elementIdToElementMap.put(stereotype.getXmiId(), strtpe);
String globalId = artifact.getURN() + "#" + stereotype.getXmiId();
if (elementIdToElementMap.get(globalId) != null)
throw new RepositorylException("found existing classifier reference, '"
+ globalId + "' while mapping artifact, "
+ artifact.getURN());
elementIdToElementMap.put(globalId, strtpe);
// so all classifiers can be externally referenced (i.e. external XMI references)using a "generic"
// namespace assigned currently in the model artifact config entry
if (artifact.getNamespaceURI() != null) {
String artifactNamespaceQualifiedName = artifact.getNamespaceURI()
+ "#" + stereotype.name;
if (elementIdToElementMap.get(artifactNamespaceQualifiedName) != null)
if (log.isDebugEnabled())
log.debug("found existing classifier, '"
+ artifactNamespaceQualifiedName + "' while mapping artifact, "
+ artifact.getURN());
elementIdToElementMap.put(artifactNamespaceQualifiedName, strtpe);
}
else
log.warn("missing artifact URI - could not map element '"
+ stereotype.name + "' as externally referencable by artifact URI");
}
public void mapProperty(Classifier c, Property p, RepositoryArtifact artifact) {
if (log.isDebugEnabled())
if (c != null) // FIXME - why after assembly this could happen
log.debug("mapping property, " + artifact.getURN() + "#" + c.name + "." + p.name);
else
log.debug("mapping property, " + artifact.getURN() + "#" + p.name);
if (elementIdToElementMap.get(p.getXmiId()) != null)
throw new RepositorylException("found existing property reference, '"
+ p.getXmiId() + ".");
org.modeldriven.fuml.repository.Property property = new org.modeldriven.fuml.repository.model.Property(p, artifact);
elementIdToElementMap.put(p.getXmiId(), property);
String globalId = artifact.getURN() + "#" + p.getXmiId();
if (elementIdToElementMap.get(globalId) != null)
throw new RepositorylException("found existing property reference, '"
+ globalId + ".");
elementIdToElementMap.put(globalId, property);
}
public void mapPrimitiveType(PrimitiveType t, String currentPackageName, RepositoryArtifact artifact) {
if (log.isDebugEnabled())
log.debug("mapping type, " + artifact.getURN() + "#" + currentPackageName + "." + t.getClass().getSimpleName());
org.modeldriven.fuml.repository.Classifier classifier = new org.modeldriven.fuml.repository.model.Classifier(t, artifact);
classifierNameToClassifierMap.put(t.name, classifier);
qualifiedClassifierNameToClassifierMap.put(currentPackageName + "." + t.name, classifier);
classifierNameToPackageNameMap.put(t.name, currentPackageName);
qualifiedClassifierNameToPackageNameMap.put(currentPackageName + "." + t.name,
currentPackageName);
if (elementIdToElementMap.get(t.getXmiId()) != null)
throw new RepositorylException("found existing primitive type, '"
+ t.getXmiId() + ".");
elementIdToElementMap.put(t.getXmiId(), classifier);
String globalId = artifact.getURN() + "#" + t.getXmiId();
if (elementIdToElementMap.get(globalId) != null)
throw new RepositorylException("found existing primitive type, '"
+ globalId + ".");
elementIdToElementMap.put(globalId, classifier);
// FIXME: Path map variables allow for portability of URIs. The actual location
// indicated by a URI depends on the run-time binding of the path variable. Thus, different
// environments can work with the same resource URIs even though the
// resources are stored in different physical locations.
elementIdToElementMap.put("pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml"
+ "#" + t.name, classifier);
// FIXME: map primitive types to all configured UML
// namespaces using all known URL fragment suffixes
String[] uris = FumlConfiguration.getInstance().getSupportedNamespaceURIsForDomain(NamespaceDomain.UML);
for (String uri : uris) {
elementIdToElementMap.put(uri + "/" + "PrimitiveTypes.xmi"
+ "#" + t.name, classifier);
elementIdToElementMap.put(uri + "/" + "uml.xml"
+ "#" + t.name, classifier);
}
}
public void mapDataType(DataType t, String currentPackageName, RepositoryArtifact artifact) {
if (log.isDebugEnabled())
log.debug("mapping datatype, " + artifact.getURN() + "#" + currentPackageName + "." + t.getClass().getSimpleName());
org.modeldriven.fuml.repository.Classifier classifier = new org.modeldriven.fuml.repository.model.Classifier(t, artifact);
if (t.name != null && currentPackageName != null) {
qualifiedClassifierNameToClassifierMap.put(currentPackageName + "." + t.name, classifier);
classifierNameToPackageNameMap.put(t.name, currentPackageName);
qualifiedClassifierNameToPackageNameMap.put(currentPackageName + "." + t.name,
currentPackageName);
}
if (elementIdToElementMap.get(t.getXmiId()) != null)
throw new RepositorylException("found existing datatype, '"
+ t.getXmiId() + ".");
elementIdToElementMap.put(t.getXmiId(), classifier);
String globalId = artifact.getURN() + "#" + t.getXmiId();
if (elementIdToElementMap.get(globalId) != null)
throw new RepositorylException("found existing datatype, '"
+ globalId + ".");
elementIdToElementMap.put(globalId, classifier);
if (t.name != null) {
if (artifact.getNamespaceURI() != null) {
String artifactNamespaceQualifiedName = artifact.getNamespaceURI()
+ "#" + t.name;
if (log.isDebugEnabled())
log.debug("mapping datatype to artifact qualified name, " + artifactNamespaceQualifiedName);
if (qualifiedClassifierNameToClassifierMap.get(artifactNamespaceQualifiedName) != null)
if (log.isDebugEnabled())
log.debug("found existing datatype by artifact qualified name, '"
+ artifactNamespaceQualifiedName + "' while mapping artifact, "
+ artifact.getURN());
qualifiedClassifierNameToClassifierMap.put(artifactNamespaceQualifiedName, classifier);
//FIXME: artifact qualified classifiers only mapped to this map above !!
if (elementIdToElementMap.get(artifactNamespaceQualifiedName) != null)
if (log.isDebugEnabled())
log.debug("found existing classifier, '"
+ artifactNamespaceQualifiedName + "' while mapping artifact, "
+ artifact.getURN());
elementIdToElementMap.put(artifactNamespaceQualifiedName, classifier);
String artifactNamespaceQualifiedUUID = artifact.getNamespaceURI()
+ "#" + t.getXmiId();
if (elementIdToElementMap.get(artifactNamespaceQualifiedUUID) != null)
if (log.isDebugEnabled())
log.debug("found existing classifier, '"
+ artifactNamespaceQualifiedUUID + "' while mapping artifact, "
+ artifact.getURN());
elementIdToElementMap.put(artifactNamespaceQualifiedUUID, classifier);
}
else
log.warn("missing artifact URI - could not map datatype '"
+ t.name + "' as externally referencable by artifact URI");
}
}
public void mapEnumeration(Enumeration e, String currentPackageName, RepositoryArtifact artifact) {
if (log.isDebugEnabled())
log.debug("mapping enumeration, " + currentPackageName + "." + e.name);
org.modeldriven.fuml.repository.Classifier classifier = new org.modeldriven.fuml.repository.model.Enumeration(e, artifact);
//classifierNameToClassifierMap.put(e.name, classifier); // FIXME: flat name mapping
qualifiedClassifierNameToClassifierMap.put(currentPackageName + "." + e.name, classifier);
classifierNameToPackageNameMap.put(e.name, currentPackageName); // FIXME: flat name mapping
qualifiedClassifierNameToPackageNameMap.put(currentPackageName + "." + e.name,
currentPackageName);
if (elementIdToElementMap.get(e.getXmiId()) != null)
throw new RepositorylException("found existing enumeration, '"
+ e.getXmiId() + ".");
elementIdToElementMap.put(e.getXmiId(), classifier);
}
public void mapEnumerationExternal(Enumeration e, String currentPackageName, RepositoryArtifact artifact) {
if (log.isDebugEnabled())
log.debug("mapping enumeration, " + currentPackageName + "." + e.name);
org.modeldriven.fuml.repository.Classifier classifier = new org.modeldriven.fuml.repository.model.Enumeration(e, artifact);
//classifierNameToClassifierMap.put(e.name, classifier); // FIXME: flat name mapping
qualifiedClassifierNameToClassifierMap.put(currentPackageName + "." + e.name, classifier);
//classifierNameToPackageNameMap.put(e.name, currentPackageName); // FIXME: flat name mapping
qualifiedClassifierNameToPackageNameMap.put(currentPackageName + "." + e.name,
currentPackageName);
if (elementIdToElementMap.get(e.getXmiId()) != null)
throw new RepositorylException("found existing enumeration, '"
+ e.getXmiId() + ".");
elementIdToElementMap.put(e.getXmiId(), classifier);
}
public void mapEnumerationLiteral(EnumerationLiteral literal, String currentPackageName, RepositoryArtifact artifact) {
if (log.isDebugEnabled())
log.debug("mapping enumeration literal, " + currentPackageName + "." + literal.name);
if (elementIdToElementMap.get(literal.getXmiId()) != null)
throw new RepositorylException("found existing enumeration literal, '"
+ literal.getXmiId() + ".");
org.modeldriven.fuml.repository.NamedElement namedElement = new org.modeldriven.fuml.repository.model.EnumerationLiteral(literal, artifact);
elementIdToElementMap.put(literal.getXmiId(), namedElement);
}
public void mapAssociation(Association assoc, String currentPackageName, RepositoryArtifact artifact) {
if (log.isDebugEnabled())
log.debug("mapping association, " + currentPackageName + "." + assoc.name);
if (elementIdToElementMap.get(assoc.getXmiId()) != null)
throw new RepositorylException("found existing association, '"
+ assoc.getXmiId() + ".");
org.modeldriven.fuml.repository.Classifier classifier = new org.modeldriven.fuml.repository.model.Classifier(assoc, artifact);
elementIdToElementMap.put(assoc.getXmiId(), classifier);
}
public void mergePackage(Package target, Package source) {
if (log.isDebugEnabled())
log.debug("merging package " + target.getHref() + " with "
+ source.getHref());
Iterator<PackageableElement> sourceIter = source.packagedElement.iterator();
while (sourceIter.hasNext())
{
PackageableElement sourceElement = sourceIter.next();
if (sourceElement instanceof Class_)
{
Class_ sourceClass = (Class_)sourceElement;
Class_ targetClass = findClass(target, sourceClass.name);
if (targetClass != null)
{
if (log.isDebugEnabled())
log.debug("merging class (" + target.qualifiedName + ") " + targetClass.name + " with "
+ "(" + source.qualifiedName + ") " + sourceClass.name);
mergeClass(targetClass, sourceClass);
}
else
{
if (log.isDebugEnabled())
log.debug("adding class (" + source.qualifiedName + ") " + sourceClass.name
+ " to package " + target.qualifiedName);
target.packagedElement.add(sourceClass);
}
}
}
}
private Class_ findClass(Package p, String name)
{
Iterator<PackageableElement> targetIter = p.packagedElement.iterator();
while (targetIter.hasNext())
{
PackageableElement element = targetIter.next();
if (element instanceof Class_)
{
Class_ c = (Class_)element;
if (name.equals(c.name))
return c;
}
}
return null;
}
@SuppressWarnings("unchecked")
private Property findProperty(Class_ c, String name)
{
Iterator<fUML.Syntax.Classes.Kernel.Property> iter = c.ownedAttribute.iterator();
while (iter.hasNext()) {
Property p = (Property)iter.next();
if (p.name.equals(name))
return p;
}
return null;
}
public void mergeClass(Class_ target, Class_ source) {
mergeProperties(target, source);
mergeGeneralizations(target, source);
target.general.clear(); // HACK
//mergeGenerals(target, source);
target.isAbstract = source.isAbstract;
target.setIsAbstract(target.isAbstract);
}
public void mergeProperties(Class_ target, Class_ source) {
// merge existing properties and add new properties
Iterator<fUML.Syntax.Classes.Kernel.Property> sourceIter = source.ownedAttribute.iterator();
while (sourceIter.hasNext()) {
Property sourceProp = (Property)sourceIter.next();
Property targetProp = findProperty(target, sourceProp.name);
if (targetProp != null)
{
if (log.isDebugEnabled())
log.debug("merging property " + target.qualifiedName + "." + targetProp.name + " with "
+ source.qualifiedName + "." + sourceProp.name);
mergeProperty(targetProp, sourceProp);
}
else
{
if (log.isDebugEnabled())
log.debug("adding property " + source.qualifiedName + "." + sourceProp.name + " to "
+ target.name);
target.ownedAttribute.add(sourceProp);
}
}
// remove obsolete properties
/*
List<Property> toRemove = new ArrayList<Property>();
Iterator<Property> targetIter = target.ownedAttribute.iterator();
while (targetIter.hasNext()) {
Property targetProp = targetIter.next();
sourceIter = source.ownedAttribute.iterator();
boolean found = false;
while (sourceIter.hasNext()) {
Property sourceProp = sourceIter.next();
if (!targetProp.name.equals(sourceProp.name))
continue;
found = true;
}
if (!found) // target no longer in source
toRemove.add(targetProp);
}
Iterator<Property> toRemoveTargetIter = toRemove.iterator();
while (toRemoveTargetIter.hasNext())
{
Property targetProp = toRemoveTargetIter.next();
if (!target.ownedAttribute.remove(targetProp))
log.warn("could not remove property "
+ target.name + "." + targetProp.name);
}
*/
}
private void mergeGeneralizations(Class_ target, Class_ source) {
Iterator<Generalization> sourceIter = source.generalization.iterator();
while (sourceIter.hasNext()) {
Generalization sourceGeneralization = sourceIter.next();
boolean found = false;
Iterator<Generalization> targetIter = target.generalization.iterator();
while (targetIter.hasNext()) {
Generalization targetGeneralization = targetIter.next();
if (!targetGeneralization.general.name.equals(sourceGeneralization.general.name))
continue;
targetGeneralization.setXmiId(sourceGeneralization.getXmiId());
found = true;
break;
}
if (!found)
target.generalization.add(sourceGeneralization);
}
}
private void mergeGenerals(Class_ target, Class_ source) {
Iterator<Classifier> sourceIter = source.general.iterator();
while (sourceIter.hasNext()) {
Classifier sourceGeneral = sourceIter.next();
boolean found = false;
Iterator<Classifier> targetIter = target.general.iterator();
while (targetIter.hasNext()) {
Classifier targetGeneral = targetIter.next();
if (!targetGeneral.name.equals(sourceGeneral.name))
continue;
found = true;
break;
}
if (!found)
target.general.add(sourceGeneral);
}
}
protected void mergeProperty(Property target, Property source) {
// type
target.typedElement = source.typedElement;
// merge defaults
ValueSpecification sourceDefault = source.defaultValue;
if (sourceDefault != null) {
ValueSpecification targetDefault = target.defaultValue;
if (targetDefault == null) {
target.defaultValue = source.defaultValue;
} else
mergeValueSpecification(targetDefault, sourceDefault);
}
// merge upper/lower value (constraints)
ValueSpecification sourceLower = source.multiplicityElement.lowerValue;
if (sourceLower != null)
{
ValueSpecification targetLower = target.multiplicityElement.lowerValue;
if (targetLower == null)
target.setLowerValue(sourceLower);
else
mergeValueSpecification(targetLower, sourceLower);
}
ValueSpecification sourceUpper = source.multiplicityElement.lowerValue;
if (sourceUpper != null)
{
ValueSpecification targetUpper = target.multiplicityElement.lowerValue;
if (targetUpper == null)
target.setUpperValue(sourceUpper);
else
mergeValueSpecification(targetUpper, sourceUpper);
}
}
private void mergeValueSpecification(ValueSpecification target, ValueSpecification source) {
// NOTE; this is scary.
if (!target.getClass().equals(source.getClass()))
if (log.isDebugEnabled())
log.warn("merging unequal value specification classes, "
+ source.getClass().getSimpleName() + " to "
+ target.getClass().getSimpleName());
String sourceValue = getValue(source);
if (sourceValue != null && sourceValue.trim().length() > 0)
setValue(target, sourceValue);
}
private String getValue(ValueSpecification valueSpec) {
if (LiteralString.class.isAssignableFrom(valueSpec.getClass()))
return ((LiteralString)valueSpec).value;
else if (LiteralInteger.class.isAssignableFrom(valueSpec.getClass()))
return String.valueOf(((LiteralInteger)valueSpec).value);
else if (LiteralBoolean.class.isAssignableFrom(valueSpec.getClass()))
return String.valueOf(((LiteralBoolean)valueSpec).value);
else if (LiteralNull.class.isAssignableFrom(valueSpec.getClass()))
return null; //((LiteralNull)valueSpec).;
else if (LiteralUnlimitedNatural.class.isAssignableFrom(valueSpec.getClass())) {
int naturalValue = ((LiteralUnlimitedNatural)valueSpec).value.naturalValue;
return naturalValue == -1? "*": String.valueOf(naturalValue);
} else if (InstanceValue.class.isAssignableFrom(valueSpec.getClass())) {
return valueSpec.name;
} else {
// return ((OpaqueExpression)valueSpec).getBody();
throw new IllegalArgumentException("expected literal or instance value");
}
}
private void setValue(ValueSpecification valueSpec, String value) {
if (LiteralString.class.isAssignableFrom(valueSpec.getClass()))
((LiteralString)valueSpec).value = value;
else if (LiteralInteger.class.isAssignableFrom(valueSpec.getClass()))
((LiteralInteger)valueSpec).value = Integer.parseInt(value);
else if (LiteralBoolean.class.isAssignableFrom(valueSpec.getClass()))
((LiteralBoolean)valueSpec).value = Boolean.parseBoolean(value);
//else if (LiteralNull.class.isAssignableFrom(valueSpec.getClass()))
else if (LiteralUnlimitedNatural.class.isAssignableFrom(valueSpec.getClass())) {
UnlimitedNatural un = new UnlimitedNatural();
un.naturalValue = value.equals("*")? -1: Integer.parseInt(value);
((LiteralUnlimitedNatural)valueSpec).value = un;
} else if (InstanceValue.class.isAssignableFrom(valueSpec.getClass())) {
valueSpec.setName(value);
} else {
// ((OpaqueExpression)valueSpec).setBody(value);
throw new IllegalArgumentException("expected literal or instance value");
}
}
}