package archmapper.main.conformance;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IProject;
import org.eclipse.jdt.core.dom.IAnnotationBinding;
import org.eclipse.jdt.core.dom.IMemberValuePairBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.springframework.util.AntPathMatcher;
import archmapper.main.annotations.ArtifactType;
import archmapper.main.annotations.BelongsToComponent;
import archmapper.main.annotations.BelongsToConnector;
import archmapper.main.annotations.ExposedByPort;
import archmapper.main.annotations.UsesPort;
import archmapper.main.exceptions.ArchMapperException;
import archmapper.main.model.ArchitectureMappingCache;
import archmapper.main.model.ArchitectureMappingModel;
import archmapper.main.model.architecture.ArchitectureElement;
import archmapper.main.model.architecture.Component;
import archmapper.main.model.architecture.ComponentToComponentConnection;
import archmapper.main.model.architecture.Configuration;
import archmapper.main.model.architecture.Connector;
import archmapper.main.model.architecture.ImplementableArchitectureElement;
import archmapper.main.model.architecture.Port;
import archmapper.main.model.architecture.Role;
import archmapper.main.model.architecture.Role.RoleDirection;
import archmapper.main.model.archmapping.ArchitectureMapping;
import archmapper.main.model.archmapping.ClassDefinition;
import archmapper.main.model.archmapping.ClassNamePattern;
import archmapper.main.model.archmapping.ComponentMapping;
import archmapper.main.model.archmapping.ConnectorMapping;
import archmapper.main.model.archmapping.FileDefinition;
import archmapper.main.model.archmapping.ImplementableArchitectureElementMapping;
import archmapper.main.model.archmapping.ImplementationArtifactDefinition;
import archmapper.main.model.archmapping.PortMapping;
import archmapper.main.model.archmapping.PortMapping.PortMappingOption;
import archmapper.main.model.stylemapping.ClassType;
import archmapper.main.model.stylemapping.ComponentTypeMapping;
import archmapper.main.model.stylemapping.ConnectorTypeMapping;
import archmapper.main.model.stylemapping.FileType;
import archmapper.main.model.stylemapping.ImplementableTypeMapping;
import archmapper.main.model.stylemapping.ImplementationArtifactType;
import archmapper.main.model.stylemapping.PortTypeMapping;
import archmapper.main.model.stylemapping.StyleMapping;
import archmapper.main.model.stylemapping.PortTypeMapping.PortTypeExportOption;
public class MappingHelper {
protected ArchitectureMappingModel model;
protected ArchitectureMapping archMapping;
protected Configuration arch;
protected StyleMapping styleMapping;
public MappingHelper(IProject project) {
this(ArchitectureMappingCache.getArchitectureMappingModel(project));
}
public MappingHelper(ArchitectureMappingModel model) {
this.model = model;
this.archMapping = model.getArchMapping();
this.arch = model.getArchitecture();
this.styleMapping = model.getStyleMapping();
}
/**
* Returns the value of the annotation of the given type, or null if no
* annotation of that type or no value was found.
*
* @param type
* @param annotationType
* @return
*/
public Object getAnnotationValue(ITypeBinding binding,
Class annotationType) {
for (IAnnotationBinding anno : binding.getAnnotations()) {
if (anno.getAnnotationType().getQualifiedName().equals(
annotationType.getCanonicalName())) {
for (IMemberValuePairBinding member : anno
.getAllMemberValuePairs()) {
if (member.getName().equals("value")) {
return member.getValue();
}
}
}
}
return null;
}
/**
* Returns an ImplemenationArtifactDefinition for a given type binding. The information
* includes the component or connector name, the artifact type and the artifact
* definition, if present. The information is taken from the architecture
* mapping file and from annotations at the type, if present.
* The order of evaluation is the following:
* 1. Annotations
* 2. ClassDefinitions in the architecture mapping
* 3. ClassNamePatterns in the architecture mapping
*
* @param type
* The type
* @return an ArchitectureClassInformation, or null, if no information could be found
*/
public ImplementationArtifactDefinition getClassInformation(ITypeBinding binding) {
String className = binding.getQualifiedName();
if (className == null) {
return null;
}
Object anno = getAnnotationValue(binding, BelongsToComponent.class);
if (anno == null) {
anno = getAnnotationValue(binding, BelongsToConnector.class);
}
if (anno != null) {
String compName = (String) anno;
ImplementableArchitectureElementMapping compMapping = getOrCreateComponentOrConnectorMapping(compName);
if (compMapping == null) {
return null;
}
ImplementationArtifactDefinition artifactDef = getImplementationArtifactDefinitionByClassname(compMapping, className);
if (artifactDef != null && !hasPortOrArtifactTypeAnnotations(binding)) {
return artifactDef;
}
if (artifactDef == null || artifactDef instanceof ClassNamePattern) {
artifactDef = createClassDefinitionFromAnnotationOrClassNamePattern(binding, compMapping, artifactDef);
}
addTypeInformationFromAnnotation(artifactDef, binding);
addPortOptionInformationFromAnnotation(artifactDef, binding, compMapping);
return artifactDef;
}
for (ImplementableArchitectureElementMapping implMapping : archMapping.getAllImplementableArchitectureElementMappings()) {
ImplementationArtifactDefinition artifactDef =
getImplementationArtifactDefinitionByClassname(implMapping, className);
if (artifactDef != null) {
if (hasPortOrArtifactTypeAnnotations(binding) && artifactDef instanceof ClassNamePattern) {
artifactDef = createClassDefinitionFromAnnotationOrClassNamePattern(binding, implMapping, artifactDef);
}
addPortOptionInformationFromAnnotation(artifactDef, binding, implMapping);
addTypeInformationFromAnnotation(artifactDef, binding);
return artifactDef;
}
}
return null;
}
private ClassDefinition createClassDefinitionFromAnnotationOrClassNamePattern(ITypeBinding binding,
ImplementableArchitectureElementMapping mapping, ImplementationArtifactDefinition classNamePattern) {
ClassDefinition classDef = new ClassDefinition();
classDef.setClassName(binding.getName());
classDef.setPackageName(binding.getPackage().getName());
classDef.setParent(mapping);
mapping.getClassDefinition().add(classDef);
if (classNamePattern != null) {
classDef.setType(classNamePattern.getType());
}
return classDef;
}
private void addTypeInformationFromAnnotation(ImplementationArtifactDefinition implDef,
ITypeBinding binding) {
Object type = getAnnotationValue(binding, ArtifactType.class);
if (type != null) {
implDef.setType((String) type);
}
}
private void addPortOptionInformationFromAnnotation(ImplementationArtifactDefinition implDef,
ITypeBinding binding, ImplementableArchitectureElementMapping mapping) {
if (!(mapping instanceof ComponentMapping)) {
// Only components can have ports
return;
}
ComponentMapping compMapping = (ComponentMapping) mapping;
Object usesPort = getAnnotationValue(binding, UsesPort.class);
Object exposedByPort = getAnnotationValue(binding, ExposedByPort.class);
if (usesPort != null) {
PortMapping portMapping = getOrCreatePortMapping(compMapping, (String) usesPort);
if (portMapping != null) {
if (!portMapping.getUsingClass().contains(implDef)) {
portMapping.getUsingClass().add(implDef);
}
}
}
if (exposedByPort != null) {
PortMapping portMapping = getOrCreatePortMapping(compMapping, (String) exposedByPort);
if (portMapping != null) {
if (!portMapping.getExposedClass().contains(implDef)) {
portMapping.getExposedClass().add(implDef);
}
}
}
}
public boolean hasPortOrArtifactTypeAnnotations(ITypeBinding binding) {
Class[] annotationTypes = {ArtifactType.class, ExposedByPort.class, UsesPort.class};
for (IAnnotationBinding anno : binding.getAnnotations()) {
for (Class annoClass : annotationTypes) {
if (anno.getAnnotationType().getQualifiedName().equals(
annoClass.getCanonicalName())) {
return true;
}
}
}
return false;
}
/**
* Returns the ImplementationArtifactDefinition for the given qualified class name
* under the given parent.
*
* @return the definition, or null, if no definition for that classname exists.
*/
public ImplementationArtifactDefinition getImplementationArtifactDefinitionByClassname(ImplementableArchitectureElementMapping parent, String className) {
List<ImplementationArtifactDefinition> artifacts = new ArrayList<ImplementationArtifactDefinition>();
artifacts.addAll(parent.getClassDefinition());
artifacts.addAll(parent.getInterfaceDefinition());
for (ImplementationArtifactDefinition artifact : artifacts) {
if (className.equals(getQualifiedName(artifact))) {
return artifact;
}
}
if (parent.getClassNamePattern().size() > 0) {
AntPathMatcher matcher = new AntPathMatcher();
matcher.setPathSeparator(".");
for (ClassNamePattern pattern : parent.getClassNamePattern()) {
if (matcher.match(pattern.getPattern(), className)) {
boolean ok = true;
for (String exclude : pattern.getExclude()) {
if (matcher.match(exclude, className)) {
ok = false;
}
}
if (ok) {
return pattern;
}
}
}
}
return null;
}
/**
* Returns the PortMapping for the given port name under the given
* component mapping. If no such mapping exists, creates a new mapping
* and adds it to the component mapping. If the port with the given
* name does not exist in the architecture, then null is returned and
* nothing is done.
*
* @param compMapping
* @param portName
* @return
*/
public PortMapping getOrCreatePortMapping(ComponentMapping compMapping, String portName) {
PortMapping portMapping = compMapping.getPortMapping(portName);
if (portMapping == null) {
// look if this port exists in the component
Component comp = arch.getComponentByName(compMapping.getComponentName());
if (comp != null) {
if (comp.getPortByName(portName) != null) {
// ok, the port exists. We can create a new PortMapping
portMapping = new PortMapping();
portMapping.setPortName(portName);
portMapping.setParent(compMapping);
compMapping.getPortMapping().add(portMapping);
}
}
}
return portMapping;
}
/**
* Returns a component or connector mapping for the given component or connector name.
* If the component or connector exists in the architecture, but a mapping does not
* exist, then one is created and added to the architecture mapping model.
* If no component or connector with the given name exists in the architecture,
* then null is returned.
*
* @param componentName
*/
public ImplementableArchitectureElementMapping getOrCreateComponentOrConnectorMapping(String componentOrConnectorName) {
ImplementableArchitectureElementMapping mapping = archMapping.getComponentOrConnectorMappingByName(componentOrConnectorName);
if (mapping != null) {
return mapping;
}
ArchitectureElement archElem = arch.getComponentOrConnectorByName(componentOrConnectorName);
if (archElem == null) {
return null;
}
// we have to create a new mapping
if (archElem instanceof Component) {
mapping = new ComponentMapping();
((ComponentMapping) mapping).setComponentName(componentOrConnectorName);
archMapping.getComponentMapping().add((ComponentMapping) mapping);
} else {
mapping = new ConnectorMapping();
((ConnectorMapping) mapping).setConnectorName(componentOrConnectorName);
archMapping.getConnectorMapping().add((ConnectorMapping) mapping);
}
mapping.setParent(archMapping);
return mapping;
}
/**
* Returns the name of the component or connector to which the given type belongs. If the
* name is given in an annotation, then that name is returned. Otherwise, the
* architecture mapping is searched.
*
* @param type
* The type to be searched for a component definition
* @return the component name, or null, if no mapping could be found.
*/
public String getComponentName(ITypeBinding binding) {
ImplementationArtifactDefinition def = getClassInformation(binding);
if (def == null) {
return null;
}
return def.getParent().getName();
}
public ComponentTypeMapping getComponentTypeMapping(String componentName) {
Component comp = arch.getComponentByName(componentName);
if (comp == null) {
return null;
}
return styleMapping.getComponentType(comp.getStyleType());
}
public boolean isExternalComponent(String componentName) {
Component comp = arch.getComponentByName(componentName);
if (comp != null) {
ComponentTypeMapping compTypeMapping = styleMapping.getComponentType(comp.getStyleType());
if (compTypeMapping != null) {
return compTypeMapping.isExternal();
}
}
return false;
}
/**
* Returns the name of the file without the package or directory
* information, but with the filename ending.
*
* @param fileDef
* @return
*/
public String getFilename(FileDefinition fileDef) {
String name = fileDef.getFilename();
if (fileDef.getType() != null && fileDef.getParent() instanceof ComponentMapping) {
String compType = getComponentTypeOf((ComponentMapping) fileDef.getParent());
ComponentTypeMapping typeMapping = styleMapping.getComponentType(compType);
if (typeMapping != null) {
FileType fileType = typeMapping.getFileType(fileDef.getType());
String ending = fileType.getFilenameEnding();
if (ending != null && !name.endsWith("." + ending)) {
name = name + "." + ending;
}
}
}
return name;
}
/**
* Returns the template that should be used for a new file.
*
* @return The template text or an empty string, if no template exists.
*
*/
public String getTemplateTextForFile(FileDefinition fileDef) {
FileType ft = getFileTypeForFileDefinition(fileDef);
if (ft != null && ft.getTemplateText() != null) {
return ft.getTemplateText();
}
return "";
}
/**
* Returns the file type for the given file definition, or null,
* if the file definition has no type or the type does not exist.
*
* @param fileDef
* @return
*/
public FileType getFileTypeForFileDefinition(FileDefinition fileDef) {
if (fileDef.getType() == null) {
return null;
}
for (ImplementableTypeMapping typeMapping : styleMapping.getAllImplementableTypeMappings()) {
FileType ft = typeMapping.getFileType(fileDef.getType());
if (ft != null) {
return ft;
}
}
return null;
}
public String getPackageOfImplementationArtifact(ImplementationArtifactDefinition implDef) {
if (implDef.getPackageName() != null) {
return implDef.getPackageName();
}
return getDefaultPackage(implDef.getParent());
}
/**
* Returns the type of the given component mapping, or null
* if that component does not exist in the architecture or has
* no type.
*
* @param mapping
* @return
*/
public String getComponentTypeOf(ComponentMapping mapping) {
Component comp = arch.getComponentByName(mapping.getComponentName());
if (comp == null) {
return null;
}
return comp.getStyleType();
}
/**
* Returns the connector type for the given connector mapping, or null,
* if the connector is not present in the architecture or has no type.
*
* @param mapping
* @return
*/
public String getConnectorTypeOf(ConnectorMapping mapping) {
Connector conn = arch.getConnectorByName(mapping.getConnectorName());
if (conn == null) {
return null;
}
return conn.getStyleType();
}
public String getDefaultPackage(ImplementableArchitectureElementMapping elem) {
if (elem.getDefaultPackage() != null) {
return elem.getDefaultPackage();
}
String styleType = "";
if (elem instanceof ComponentMapping) {
styleType = getComponentTypeOf((ComponentMapping) elem);
} else {
styleType = getConnectorTypeOf((ConnectorMapping) elem);
}
if (archMapping.getStyleTypeInformation(styleType) != null &&
archMapping.getStyleTypeInformation(styleType).getDefaultPackage() != null) {
return archMapping.getStyleTypeInformation(styleType).getDefaultPackage();
}
return "";
}
/**
* Returns the qualified class name of the given class definition.
* This includes the package name, which can be taken from
* default values defined in the component or type mapping.
*
* @param classDef
* @return
*/
public String getQualifiedClassname(ClassDefinition classDef) {
return getQualifiedName(classDef);
}
/**
* Returns the qualified name of the implementation artifact.
* This is the qualified class name for classes and interfaces,
* and the filename with a package path for files.
*
* @param implDef
* @return
*/
public String getQualifiedName(ImplementationArtifactDefinition implDef) {
String pkg = getPackageOfImplementationArtifact(implDef);
if (!pkg.equals("")) {
pkg = pkg + ".";
}
if (implDef instanceof FileDefinition) {
return pkg + getFilename((FileDefinition) implDef);
}
return pkg + implDef.getName();
}
/**
* Returns whether the given class or interface definition can be reached through the
* given port.
*
* @param classDef The class or interface definition of the class that should be tested. May
* also be null (e.g. when the class is defined by a ClassNamePattern).
* In that case, only the PortTypeMapping export option is relevant.
*
* @return
*/
public boolean isClassExposedByPort(ImplementationArtifactDefinition classDef, Port port, PortMapping portMapping) {
if (portMapping != null &&
portMapping.getExport() == PortMappingOption.all) {
return true;
}
PortTypeMapping portTypeMapping = styleMapping.getPortTypeMapping(port.getStyleType());
if (portTypeMapping != null) {
if (portTypeMapping.getExport() == PortTypeExportOption.all) {
return true;
} else if (portTypeMapping.getExport() == PortTypeExportOption.none) {
return false;
} else if (classDef != null) {
if (portTypeMapping.isExportedType(classDef.getType())) {
return true;
}
}
}
// only for the export option "some", we have to look at
// the port mapping
if (portMapping == null) {
return false;
}
return portMapping.isExposedClass(classDef);
}
/**
* Checks whether the first given class from the first given component or connector may have
* a reference to the second given class from the second given component or connector.
*
* @param className The qualified name of the class that has an outgoing connection
* @param componentOrConnectorName The name of the component or connector to which
* this class belongs
* @param otherClassName The name of the class that is referenced by the first class
* @param otherComponentOrConnectorName The name of the component or connector to which
* the referenced class belongs
* @return
*/
public boolean mayClassReferenceOtherClass(String className, String componentOrConnectorName,
String otherClassName, String otherComponentOrConnectorName) {
// If the classes are from the same component, they may reference each other
if (componentOrConnectorName.equals(otherComponentOrConnectorName)) {
return true;
}
ImplementableArchitectureElement comp1 = arch.getComponentOrConnectorByName(componentOrConnectorName);
ImplementableArchitectureElement comp2 = arch.getComponentOrConnectorByName(otherComponentOrConnectorName);
if (comp1 == null || comp2 == null) {
return false;
}
// If the components are not connected at all, the class may not know
// the other class
if (!comp1.isConnectedTo(comp2, RoleDirection.out)) {
return false;
}
// If they are connected, we have to look closer...
ImplementableArchitectureElementMapping comp1Mapping = archMapping.getComponentOrConnectorMappingByName(componentOrConnectorName);
ImplementableArchitectureElementMapping comp2Mapping = archMapping.getComponentOrConnectorMappingByName(otherComponentOrConnectorName);
ImplementationArtifactDefinition class1Def = getImplementationArtifactDefinitionByClassname(comp1Mapping, className);
ImplementationArtifactDefinition class2Def = getImplementationArtifactDefinitionByClassname(comp2Mapping, otherClassName);
// The procedure depends on the type of the ImplementableArtitectureElements
if (comp1 instanceof Component && comp2 instanceof Component) {
return mayClassInComponentReferenceClassInOtherComponent(class1Def, (Component) comp1, (ComponentMapping) comp1Mapping, class2Def,
(Component) comp2, (ComponentMapping) comp2Mapping);
} else if (comp1 instanceof Component && comp2 instanceof Connector) {
return mayClassInComponentReferenceClassInConnector(class1Def, (Component) comp1,
(ComponentMapping) comp1Mapping, class2Def,
(Connector) comp2, (ConnectorMapping) comp2Mapping);
} else if (comp1 instanceof Connector && comp2 instanceof Component) {
return mayClassInConnectorReferenceClassInComponent(class1Def, (Connector) comp1,
(ConnectorMapping) comp1Mapping, class2Def,
(Component) comp2, (ComponentMapping) comp2Mapping);
}
// A class in a connector may never reference a class
// in another connector. Connectors may only be connected
// to components.
return false;
}
/**
* Returns if the first given class may reference the other. The two classes must
* be in the given components and the components must be connected.
*
* @return
*/
public boolean mayClassInComponentReferenceClassInOtherComponent(ImplementationArtifactDefinition class1Def, Component comp1, ComponentMapping comp1Mapping,
ImplementationArtifactDefinition class2Def, Component comp2, ComponentMapping comp2Mapping) {
for (Port port : comp1.getPorts()) {
for (ComponentToComponentConnection connection : comp1.getConnectionsOverPort(RoleDirection.out, port)) {
if (connection.getTargetComponent() == comp2) {
if (isClassUsingPort(class1Def, port, comp1Mapping.getPortMapping(port.getName()))) {
// ok, this class uses this port
// now we have to look if the other class is exposed through
// the port of the other component
if (isClassExposedByPort(class2Def, connection.getTargetPort(),
comp2Mapping.getPortMapping(connection.getTargetPort().getName()))) {
return true;
}
}
}
}
}
return false;
}
/**
* Returns whether a class in a connector may reference a class in a
* component. Precondition: The first class must belong to the connector,
* the second class must belong to the component.
*
* @param class1Def
* @param connector
* @param connMapping
* @param class2Def
* @param comp
* @param compMapping
* @return
*/
public boolean mayClassInConnectorReferenceClassInComponent(ImplementationArtifactDefinition class1Def, Connector connector, ConnectorMapping connMapping,
ImplementationArtifactDefinition class2Def, Component comp, ComponentMapping compMapping) {
for (Role role : connector.getRoles()) {
if (role.getPort() != null && role.getPort().getParent() == comp) {
if (isClassExposedByPort(class2Def, role.getPort(),
compMapping.getPortMapping(role.getPort().getName()))) {
return true;
}
}
}
return false;
}
/**
* Returns whether a class in a component may reference a class in a connector.
* The first class must belong to the component, the second must belong to
* the connector (precondition!).
*
* @param class1Def
* @param comp
* @param compMapping
* @param class2Def
* @param connector
* @param connMapping
* @return
*/
public boolean mayClassInComponentReferenceClassInConnector(ImplementationArtifactDefinition class1Def, Component comp, ComponentMapping compMapping,
ImplementationArtifactDefinition class2Def, Connector connector, ConnectorMapping connMapping) {
for (Port port : comp.getPorts()) {
for (ComponentToComponentConnection connection : comp.getConnectionsOverPort(RoleDirection.out, port)) {
if (connection.getConnector() == connector) {
if (isClassUsingPort(class1Def, port, compMapping.getPortMapping(port.getName()))) {
return true;
}
}
}
}
return false;
}
/**
* Returns whether the given connector has an implementation.
* For this purpose, the attribute in the connector mapping, the
* existence of file definitions in the mapping and the style
* information is checked.
*
* @return
*/
public boolean hasConnectorImplementation(Connector connector) {
ConnectorMapping mapping = archMapping.getConnectorMapping(connector.getName());
ConnectorTypeMapping typeMapping = styleMapping.getConnectorTypeMapping(connector.getStyleType());
if (mapping != null) {
if (mapping.getHasImplementation() == Boolean.TRUE) {
return true;
}
// If it is false, and there are class or interface definitions,
// then set it to true nevertheless.
if (mapping.getClassDefinition().size() > 0 ||
mapping.getInterfaceDefinition().size() > 0 ||
mapping.getClassNamePattern().size() > 0) {
return true;
}
if (mapping.getHasImplementation() == Boolean.FALSE) {
return false;
}
}
if (typeMapping != null) {
return typeMapping.isHasImplementation();
}
return false;
}
/**
* Returns whether the given class or interface is using the given port.
*
* @param classDef The class or interface definition
* @param port The port
* @param portMapping may be null
* @return
*/
public boolean isClassUsingPort(ImplementationArtifactDefinition classDef, Port port, PortMapping portMapping) {
if (portMapping != null &&
portMapping.getUse() == PortMappingOption.all) {
return true;
}
PortTypeMapping portTypeMapping = styleMapping.getPortTypeMapping(port.getStyleType());
if (portTypeMapping != null) {
if (portTypeMapping.getUsingClasses() == PortTypeExportOption.all) {
return true;
} else if (portTypeMapping.getUsingClasses() == PortTypeExportOption.none) {
return false;
} else if (classDef != null) {
// look if the class type is a using class type...
if (portTypeMapping.isUsingType(classDef.getType())) {
return true;
}
}
}
if (portMapping != null) {
if (portMapping.getUsingClass().contains(classDef)) {
return true;
}
}
return false;
}
public boolean isClassExposedTowardsOtherComponent(ImplementationArtifactDefinition implArt, Component comp,
ComponentMapping compMapping, Component otherComponent) {
for (Port port : comp.getPorts()) {
if (comp.getConnectedComponentsOverPort(RoleDirection.in, port).contains(otherComponent)) {
return isClassExposedByPort(implArt, port,
compMapping.getPortMapping(port.getName()));
}
}
return false;
}
/**
* Returns whether the class with the given class definition is a singleton.
* Refers to the style type of this class first and, if that is not given,
* takes the information from the class definition itself.
*
* @param classDef
* @return
*/
public boolean isClassSingleton(ClassDefinition classDef) {
if (classDef.getType() == null) {
return (classDef.isSingleton() == Boolean.TRUE);
}
if (classDef.getParent() instanceof ComponentMapping) {
String compType = getComponentTypeOf((ComponentMapping) classDef.getParent());
ComponentTypeMapping compTypeMapping = styleMapping.getComponentType(compType);
if (compTypeMapping != null) {
ClassType type = compTypeMapping.getClassType(classDef.getType());
if (type == null) {
throw new ArchMapperException("The class type "+ classDef.getType() +
" of class "+ classDef.getClassName() + " is not defined!");
}
return (type.isSingleton() == Boolean.TRUE);
}
} else {
String connType = getConnectorTypeOf((ConnectorMapping) classDef.getParent());
ConnectorTypeMapping connTypeMapping = styleMapping.getConnectorTypeMapping(connType);
if (connTypeMapping != null) {
ClassType type = connTypeMapping.getClassType(classDef.getType());
if (type == null) {
throw new ArchMapperException("The class type "+ classDef.getType() +
" of class "+ classDef.getClassName() + " is not defined!");
}
return (type.isSingleton() == Boolean.TRUE);
}
}
return false;
}
/**
* Returns the qualified names of all super-interfaces of this ImplementationArtifactDefinitio.
*
* @param artifactDefinition the interfaces, or an empty list if there are no super-interfaces
* @return
*/
public List<String> getSuperInterfaces(ImplementationArtifactDefinition artifactDefinition) {
List<String> interfaces = new ArrayList<String>();
interfaces.addAll(artifactDefinition.getSuperInterfaces());
ImplementationArtifactType type = getTypeOf(artifactDefinition);
if (type != null) {
interfaces.addAll(type.getSuperInterfaces());
}
return interfaces;
}
/**
* Returns the ImplementationArtifactType of an artifact definition.
*
* @param artifactDefinition
* @return the type, or null, if the artifact definition has no type or
* an invalid type.
*/
public ImplementationArtifactType getTypeOf(ImplementationArtifactDefinition artifactDefinition) {
if (artifactDefinition.getType() != null) {
ArchitectureElement archElem = arch.getComponentOrConnectorByName(artifactDefinition.getParent().getName());
if (archElem != null) {
ImplementableTypeMapping typeMapping = styleMapping.getImplementableTypeMapping(archElem.getStyleType());
if (typeMapping != null) {
return typeMapping.getImplementationArtifactType(artifactDefinition.getType());
}
}
}
return null;
}
/**
* Returns the qualified name of the super class of the ImplementationArtifactDefinition.
*
* @param artifactDefinition A class, interface or file definition
* @return The qualified name of the super-class, or null, if the artifact does not
* have a superclass (always null for interfaces and files).
*/
public String getSuperClass(ImplementationArtifactDefinition artifactDefinition) {
if (artifactDefinition instanceof ClassDefinition) {
ClassDefinition classDef = (ClassDefinition) artifactDefinition;
if (classDef.getSuperClass() != null) {
return classDef.getSuperClass();
}
ImplementationArtifactType type = getTypeOf(artifactDefinition);
if (type != null && type instanceof ClassType) {
return ((ClassType) type).getSuperClass();
}
}
return null;
}
public ArchitectureMappingModel getModel() {
return model;
}
}