Package archmapper.acmeconverter

Source Code of archmapper.acmeconverter.AcmeConverter

package archmapper.acmeconverter;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.acmestudio.acme.core.exception.AcmeVisitorException;
import org.acmestudio.acme.core.resource.IAcmeResource;
import org.acmestudio.acme.core.type.IAcmeBooleanValue;
import org.acmestudio.acme.core.type.IAcmeEnumValue;
import org.acmestudio.acme.core.type.IAcmeFloatValue;
import org.acmestudio.acme.core.type.IAcmeIntValue;
import org.acmestudio.acme.core.type.IAcmeRecordField;
import org.acmestudio.acme.core.type.IAcmeRecordValue;
import org.acmestudio.acme.core.type.IAcmeSequenceValue;
import org.acmestudio.acme.core.type.IAcmeSetValue;
import org.acmestudio.acme.core.type.IAcmeStringValue;
import org.acmestudio.acme.element.AbstractAcmeElementVisitor;
import org.acmestudio.acme.element.IAcmeAttachment;
import org.acmestudio.acme.element.IAcmeComponent;
import org.acmestudio.acme.element.IAcmeComponentType;
import org.acmestudio.acme.element.IAcmeConnector;
import org.acmestudio.acme.element.IAcmeConnectorType;
import org.acmestudio.acme.element.IAcmeDesignRule;
import org.acmestudio.acme.element.IAcmeElement;
import org.acmestudio.acme.element.IAcmeElementTypeRef;
import org.acmestudio.acme.element.IAcmePort;
import org.acmestudio.acme.element.IAcmePortType;
import org.acmestudio.acme.element.IAcmeRole;
import org.acmestudio.acme.element.IAcmeRoleType;
import org.acmestudio.acme.element.IAcmeSystem;
import org.acmestudio.acme.element.IAcmeSystemType;
import org.acmestudio.acme.element.property.IAcmeProperty;
import org.acmestudio.acme.element.property.IAcmePropertyValue;
import org.acmestudio.acme.element.representation.IAcmeRepresentation;
import org.acmestudio.acme.element.representation.IAcmeRepresentationBinding;
import org.acmestudio.acme.environment.error.AcmeError;
import org.acmestudio.acme.model.IAcmeModel;
import org.acmestudio.acme.type.IAcmeSynchronousTypeChecker;
import org.acmestudio.acme.type.IAcmeTypeChecker;
import org.acmestudio.standalone.environment.StandaloneEnvironment;
import org.acmestudio.standalone.environment.StandaloneEnvironment.TypeCheckerType;
import org.acmestudio.standalone.resource.StandaloneResourceProvider;
import org.eclipse.core.resources.IFile;

import archmapper.main.exceptions.ArchMapperException;
import archmapper.main.model.IAdlConverter;
import archmapper.main.model.architecture.Component;
import archmapper.main.model.architecture.Configuration;
import archmapper.main.model.architecture.Connector;
import archmapper.main.model.architecture.IPropertiesHolder;
import archmapper.main.model.architecture.Port;
import archmapper.main.model.architecture.Role;

/**
* Converts an Acme architecture description into the internal model
* used by ArchMapper.
*
* @author mg
*
*/
public class AcmeConverter implements IAdlConverter {
  private Configuration conf;
 
  public Configuration convertFromAdl(IFile adlFile) {
    return convertFromAdl(adlFile.getLocation().removeLastSegments(1)
        .toString() + "/families",
        adlFile.getLocation().toOSString());
  }

  public Configuration convertFromAdl(String familyPath, String adlFilename) {
    StandaloneEnvironment.instance().useTypeChecker(
        TypeCheckerType.SYNCHRONOUS);
   
    System.setProperty("ACME_FAMILY_SEARCH_PATH", familyPath);

    IAcmeResource resource;
    File tmp = null;
   
    try {
      // There is a problem with AcmeLib: If does not
      // reload a file if it was loaded before, even if
      // it has changed after the first load.
      // The workaround is copying the file to a new
      // location everytime, loading it from there
      // and then deleting the copy.
      tmp = File.createTempFile("acmeTemp", ".acme");
      FileInputStream fis  = new FileInputStream(adlFilename);
        FileOutputStream fos = new FileOutputStream(tmp);
        byte[] buf = new byte[1024];
        int i = 0;
        while((i=fis.read(buf))!=-1) {
          fos.write(buf, 0, i);
          }
        fis.close();
        fos.close();
     
      resource = StandaloneResourceProvider.instance()
          .acmeResourceForString(tmp.getPath());
    } catch (Exception e) {
      throw new ArchMapperException(e);
    } finally {
      if (tmp != null) {
        tmp.delete();
      }
    }
   
    IAcmeModel model = resource.getModel();
    IAcmeSystem sys = model.getSystems().iterator().next();
   
    conf = new Configuration();
    conf.setName(sys.getName());
    if (sys.getDeclaredTypes().size() > 0) {
      IAcmeElementTypeRef<IAcmeSystemType> type = sys.getDeclaredTypes()
          .iterator().next();
      conf.setArchitecturalStyle(type.getReferencedName());
    }
    addProperties(conf, sys.getProperties());
    createConnectors(sys);

    for (IAcmeComponent acmeComp : sys.getComponents()) {
      createComponents(acmeComp, false, null, sys, null);
    }
   
    checkViolations(conf, resource, model);

    return conf;
  }
 
  private void checkViolations(Configuration conf, IAcmeResource resource,
      IAcmeModel model) {
    IAcmeTypeChecker checker = resource.getEnvironment().getTypeChecker();
       
      if(checker instanceof IAcmeSynchronousTypeChecker) {
        IAcmeSynchronousTypeChecker tc = (IAcmeSynchronousTypeChecker)checker;
        tc.typecheckAllModelsNow();
      }
      try {
        AcmeViolationsVisitor visitor = new AcmeViolationsVisitor();
      model.visit(visitor, null);
      for (IAcmeDesignRule rule : visitor.getViolatedRules()) {
        String violation = "In "+
            getElementType(rule.getParent() )+" "+
            getQualifiedName(rule.getParent()) + ": "+ rule.getName();
        System.out.println(violation);
        conf.getArchitectureRuleViolations().add(violation);
      }
    } catch (Exception e) {
      throw new ArchMapperException(e);
    }
  }
 
  /**
   * Returns the type of the element, e.g. "Component", "Port" or "Connector". If
   * it is an unknown type, returns "Element"
   *
   * @param elem The acme element
   * @return The type of the element as a String
   */
  public String getElementType(IAcmeElement elem) {
    if (elem instanceof IAcmeComponent) {
      return "Component";
    }
    if (elem instanceof IAcmeConnector) {
      return "Connector";
    }
    if (elem instanceof IAcmePort) {
      return "Port";
    }
    if (elem instanceof IAcmeRole) {
      return "Role";
    }
    if (elem instanceof IAcmeSystem) {
      return "System";
    }
     
    return "Element";
  }
 
  /**
   * This class collects all violations of design rules and stores
   * them in the attribute violatedRules. Every violated design rule
   * is reported only once.
   *
   * @author mg
   *
   */
  class AcmeViolationsVisitor extends AbstractAcmeElementVisitor {
    List<IAcmeDesignRule> violatedRules = new ArrayList<IAcmeDesignRule>();
   
      @Override
    public void postVisit(IAcmeElement element, Object data) throws AcmeVisitorException {
        boolean typechecked = element.getContext().getEnvironment().getTypeChecker().typechecks(element);
       
        if(!typechecked) { 
          Set<? extends AcmeError> errs = element.getContext().getEnvironment().errorsByAffiliatedObject(element);
          for(AcmeError err : errs) {
            IAcmeDesignRule rootCause = getRootCause(err);
           
            if (rootCause != null &&
                !violatedRules.contains(rootCause)) {
              violatedRules.add(rootCause);
            }
          }
         
        }
    }

    public List<IAcmeDesignRule> getViolatedRules() {
      return violatedRules;
    }
     
   
  }
 
  private IAcmeDesignRule getRootCause(AcmeError error) {
    if (error.getCausedByList() != null &&
        error.getCausedByList().size() > 0) {
      return getRootCause(error.getCausedByList().get(0));
    }
   
    else if (error.getSource() instanceof IAcmeDesignRule) {
      return (IAcmeDesignRule) error.getSource();
    }
   
    return null;
  }

  private void createConnectors(IAcmeSystem system) {
    for (IAcmeConnector acmeConn : system.getConnectors()) {
      Connector conn = new Connector();
      conf.getConnectors().add(conn);
      conn.setParent(conf);
      conn.setName(getQualifiedName(acmeConn));

      if (acmeConn.getDeclaredTypes().size() > 0) {
        IAcmeElementTypeRef<IAcmeConnectorType> type = acmeConn
            .getDeclaredTypes().iterator().next();
        conn.setStyleType(type.getReferencedName());
      }

      addProperties(conn, acmeConn.getProperties());
    }
  }

  private void createComponents(IAcmeComponent acmeComp,
      boolean isSubComponent, IAcmeRepresentation representation,
      IAcmeSystem system, IAcmeSystem parentSystem) {

    // pull subcomponents in representations out
    if (acmeComp.getRepresentations() != null
        && acmeComp.getRepresentations().size() > 0) {
      IAcmeRepresentation rep = acmeComp.getRepresentations().iterator()
          .next();
      Set<? extends IAcmeComponent> subComponents = rep.getSystem()
          .getComponents();
      if (subComponents != null && subComponents.size() > 0) {
        // The connectors from the subsystem
        // must be created in the super-system, too
        createConnectors(rep.getSystem());

        for (IAcmeComponent acmeSubComp : subComponents) {
          createComponents(acmeSubComp, true, rep, rep.getSystem(),
              system);
        }
        return;
      }
    }

    Component component = new Component();
    component.setParent(conf);
    conf.getComponents().add(component);

    component.setName(getQualifiedName(acmeComp));

    if (acmeComp.getDeclaredTypes().size() > 0) {
      IAcmeElementTypeRef<IAcmeComponentType> type = acmeComp
          .getDeclaredTypes().iterator().next();
      component.setStyleType(type.getReferencedName());
    }

    addProperties(component, acmeComp.getProperties());

    for (IAcmePort acmePort : acmeComp.getPorts()) {
      Port port = new Port();
      port.setParent(component);
      component.getPorts().add(port);

      port.setName(acmePort.getName());

      if (acmePort.getDeclaredTypes().size() > 0) {
        IAcmeElementTypeRef<IAcmePortType> type = acmePort
            .getDeclaredTypes().iterator().next();
        port.setStyleType(type.getReferencedName());
      }

      addProperties(port, acmePort.getProperties());
      addPortAttachments(acmePort, port, system);

      // If the component is a subcomponent, we
      // also have to respect rep-maps that connect
      // the Ports to ports of the super-component
      if (isSubComponent) {
        for (IAcmeRepresentationBinding binding : representation
            .getBindings()) {
          if (binding.getInnerReference().getTarget() == acmePort) {
            IAcmePort dest = (IAcmePort) binding
                .getOuterReference().getTarget();
            addPortAttachments(dest, port, parentSystem);
          }
        }
      }
    }
  }

  private void addPortAttachments(IAcmePort acmePort, Port port,
      IAcmeSystem system) {
    for (IAcmeAttachment att : system.getAttachments(acmePort)) {
      IAcmeRole acmeRole = att.getRole();

      Role role = new Role();
      port.getRoles().add(role);
      role.setPort(port);

      if (acmeRole.getDeclaredTypes().size() > 0) {
        IAcmeElementTypeRef<IAcmeRoleType> type = acmeRole
            .getDeclaredTypes().iterator().next();
        role.setStyleType(type.getReferencedName());
      }

      addProperties(role, acmeRole.getProperties());

      IAcmeConnector acmeConn = (IAcmeConnector) acmeRole.getParent();
      Connector conn = conf
          .getConnectorByName(getQualifiedName(acmeConn));
      role.setConnector(conn);
      conn.getRoles().add(role);
    }
  }

  /**
   * Returns the qualified name of the given element. This is a simpler name
   * than the one used in acme since this includes only super-components and
   * no systems or representations.
   *
   * @param elem
   * @return
   */
  private String getQualifiedName(IAcmeElement elem) {
    String s = elem.getName();

    while (elem.getParent() != null) {
      elem = elem.getParent();
      if (elem instanceof IAcmeComponent) {
        s = elem.getName() + "." + s;
      }
    }

    return s;
  }

  private void addProperties(IPropertiesHolder holder,
      Set<? extends IAcmeProperty> properties) {
    for (IAcmeProperty prop : properties) {
      Object value = getObjectFromAcmePropertyValue(prop.getValue());
      holder.getProperties().put(prop.getName(), value);
    }
  }

  /**
   * Transforms an Acme property value into a normal java object, i.e.
   * transforms IAcmeIntValue to Integer, IAcmeSequenceValue to List,
   * IAcmeSetValue to Set and IAcmeRecordValue to Map.
   *
   * @param propValue
   * @return
   */
  private Object getObjectFromAcmePropertyValue(IAcmePropertyValue propValue) {
    Object value = null;

    if (propValue instanceof IAcmeStringValue) {
      value = ((IAcmeStringValue) propValue).getValue();
    } else if (propValue instanceof IAcmeIntValue) {
      value = new Integer(((IAcmeIntValue) propValue).getValue());
    } else if (propValue instanceof IAcmeBooleanValue) {
      value = new Boolean(((IAcmeBooleanValue) propValue).getValue());
    } else if (propValue instanceof IAcmeFloatValue) {
      value = new Float(((IAcmeFloatValue) propValue).getValue());
    } else if (propValue instanceof IAcmeEnumValue) {
      value = ((IAcmeEnumValue) propValue).getValue();
    } else if (propValue instanceof IAcmeRecordValue) {
      Map<String, Object> map = new HashMap<String, Object>();
      for (IAcmeRecordField field : ((IAcmeRecordValue) propValue)
          .getFields()) {
        map.put(field.getName(), getObjectFromAcmePropertyValue(field
            .getValue()));
      }

      value = map;
    } else if (propValue instanceof IAcmeSetValue) {
      Set<Object> set = new HashSet<Object>();

      for (IAcmePropertyValue pv : ((IAcmeSetValue) propValue)
          .getValues()) {
        set.add(getObjectFromAcmePropertyValue(pv));
      }

      value = set;
    } else if (propValue instanceof IAcmeSequenceValue) {
      List<Object> list = new ArrayList<Object>();

      for (IAcmePropertyValue pv : ((IAcmeSequenceValue) propValue)
          .getValues()) {
        list.add(getObjectFromAcmePropertyValue(pv));
      }

      value = list;
    }

    return value;
  }

}
TOP

Related Classes of archmapper.acmeconverter.AcmeConverter

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.