Package archmapper.main.conformance

Source Code of archmapper.main.conformance.MappingHelper

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;
  }
}
TOP

Related Classes of archmapper.main.conformance.MappingHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.