Package archmapper.main.ui

Source Code of archmapper.main.ui.ArchMappingContentAssistProcessor

package archmapper.main.ui;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import archmapper.main.Preferences;
import archmapper.main.model.ArchitectureMappingModel;
import archmapper.main.model.architecture.ArchitectureElement;
import archmapper.main.model.architecture.Component;
import archmapper.main.model.architecture.Configuration;
import archmapper.main.model.architecture.Connector;
import archmapper.main.model.architecture.Port;
import archmapper.main.model.stylemapping.ImplementableTypeMapping;
import archmapper.main.model.stylemapping.ImplementationArtifactType;
import archmapper.main.model.stylemapping.StyleMapping;

/**
* This class adds content assist to archmapping XML files in
* the Eclipse WST XML-editor. It gets information about the
* architecture and the style mapping from other files and displays
* this information as content assists.
*
* @author mg
*
*/
@SuppressWarnings("restriction")
public class ArchMappingContentAssistProcessor extends
    ContentAssistProcessorBase {
  private static Configuration lastLoadedArchitecture = null;
  private static long loadedArchModificationStamp = 0;
 
  private static StyleMapping lastLoadedStyleMapping = null;
  private static long lastStyleMappingLoadTime = 0;
 
  private static IProject lastUsedProject = null;
 

  @Override
  protected void addPCDATAProposal(String elementName, ContentAssistRequest request) {
    if (elementName == null) {
      return;
    }
   
    if (elementName.equals("usingClass") || elementName.equals("exposedClass")) {
      addProposalForUsingAndExposedClassesOfPort(request);
    }
   
  }

  @Override
  protected void addAttributeValueProposals(ContentAssistRequest request) {
    Node node = request.getNode();
    String attribute = getAttributeName(node, request);
    String nodename = node.getLocalName();
    if (nodename == null) {
      return;
    }
   
    if (nodename.equals("componentMapping") &&
        attribute.equals("componentName")) {
      addProposalForComponentNames(request);
    } else if (nodename.equals("connectorMapping") &&
        attribute.equals("connectorName")) {
      addProposalForConnectorNames(request);
    } else if (nodename.equals("portMapping") &&
        attribute.equals("portName")) {
      addProposalForPortNames(request);
    } else if (nodename.equals("typeInformation") &&
        attribute.equals("type")) {
      addProposalForTypeInformation(request);
    } else if ((nodename.equals("classDefinition")
        ||  nodename.equals("interfaceDefinition")
        ||  nodename.equals("fileDefinition")
           ) && attribute.equals("type")) {
      addProposalForImplementationArtifactType(nodename, request);
    }
       
    super.addAttributeValueProposals(request);
  }
 
  private void addProposalForComponentNames(ContentAssistRequest request) {
    Configuration conf = getArchitecture(request);
    if (conf == null) {
      return;
    }
   
    // propose all components from the architecture, but
    // not those that are already used in the file
    List<String> presentNames = getPresentNamesInDocument((Element) request.getNode(),
        (Element) request.getNode().getParentNode(), "componentMapping", "componentName");
   
    for (Component comp : conf.getComponents()) {
      if (!presentNames.contains(comp.getName())) {
        addAttributeProposal(comp.getName(), request);
      }
    }
  }
 
  private void addProposalForConnectorNames(ContentAssistRequest request) {
    Configuration conf = getArchitecture(request);
    if (conf == null) {
      return;
    }
   
    List<String> presentNames = getPresentNamesInDocument((Element) request.getNode(),
        (Element) request.getNode().getParentNode(), "connectorMapping", "connectorName");
 
    for (Connector conn : conf.getConnectors()) {
      if (!presentNames.contains(conn.getName())) {
        addAttributeProposal(conn.getName(), request);
      }
    }
  }
 
  private void addProposalForPortNames(ContentAssistRequest request) {
    Configuration conf = getArchitecture(request);
    if (conf == null) {
      return;
    }
   
    List<String> presentNames = getPresentNamesInDocument((Element) request.getNode(),
        (Element) request.getNode().getParentNode(), "portMapping", "portName");
   
    String compName = ((Element) request.getNode().getParentNode()).getAttribute("componentName");
    Component comp = conf.getComponentByName(compName);
    if (comp == null) {
      return;
    }
   
    for (Port port : comp.getPorts()) {
      if (!presentNames.contains(port.getName())) {
        addAttributeProposal(port.getName(), request);
      }
    }
  }
 
  private void addProposalForTypeInformation(ContentAssistRequest request) {
    Configuration conf = getArchitecture(request);
    if (conf == null) {
      return;
    }
   
    List<String> presentNames = getPresentNamesInDocument((Element) request.getNode(),
        (Element) request.getNode().getParentNode(), "typeInformation", "type");
   
    for (ArchitectureElement elem : conf.getComponentsAndConnectors()) {
      String type = elem.getStyleType();
     
      if (!presentNames.contains(type)) {
        // don't add types more than once
        presentNames.add(type);
        addAttributeProposal(type, request);
      }
    }
  }
 
  private List<String> getPresentNamesInDocument(Element currentNode, Element parentNode,
      String nodeName, String attributeName) {
    List<String> presentNames = new ArrayList<String>();
    NodeList nodes = parentNode.getElementsByTagName(nodeName);   
   
    for (int i=0; i<nodes.getLength(); i++) {
      Element node = (Element) nodes.item(i);
      if (node != currentNode) {
        String compName = node.getAttribute(attributeName);
        if (compName != null && !compName.equals("")) {
          presentNames.add(compName);
        }
      }
    }
   
    return presentNames;
  }
 
  private void addProposalForImplementationArtifactType(String artifactType, ContentAssistRequest request) {
    StyleMapping styleMapping = getStyleMapping(request);
    Configuration conf = getArchitecture(request);
    if (styleMapping == null || conf == null) {
      return;
    }
   
    ArchitectureElement archElem = getParentComponentOrConnector(request.getNode(), conf);
    if (archElem != null) {
      ImplementableTypeMapping typeMapping = styleMapping.getImplementableTypeMapping(archElem.getStyleType());
     
      if (typeMapping != null) {
        List<? extends ImplementationArtifactType> types = typeMapping.getClassTypes();
       
        if (artifactType.equals("interfaceDefinition")) {
          types = typeMapping.getInterfaceTypes();
        } else if (artifactType.equals("fileDefinition")) {
          types = typeMapping.getFileTypes();
        }
       
        for (ImplementationArtifactType type : types) {
          addAttributeProposal(type.getTypeName(), request);
        }
      }
    }
  }
 
  private void addProposalForUsingAndExposedClassesOfPort(ContentAssistRequest request) {
    Node parentNode = request.getNode().getParentNode().getParentNode();
    if (parentNode == null) {
      return;
    }
   
    // The parent nodes differ depending whether there is
    // already text in the node or not...
    if (!parentNode.getLocalName().equals("componentMapping")) {
      parentNode = parentNode.getParentNode();
    }
       
    List<String> ids = getPresentNamesInDocument(null, (Element) parentNode,
        "classDefinition", "id");
    ids.addAll(getPresentNamesInDocument(null, (Element) parentNode, "interfaceDefinition",
        "id"));
   
    for (String id : ids) {
      addElementValueProposal(id, request);
    }
  }
 
  /**
   * Returns the component or connector that belongs to the parent element
   * of the given node in the xml document. Returns null, if no corresponding
   * element can be found.
   *
   * @param node
   * @return
   */
  private ArchitectureElement getParentComponentOrConnector(Node node, Configuration conf)  {
    String compName = ((Element) node.getParentNode()).getAttribute("componentName");
    if (compName == null) {
      compName = ((Element) node.getParentNode()).getAttribute("connectorName");
    }
   
    return conf.getComponentOrConnectorByName(compName);
  }
 
 
  /**
   * Returns the architecture model for the project of the currently edited
   * file, or null, if the architecture preferences for the project are not set.
   * The architecture is cached internally, but will be reloaded if the
   * architecture file changes.
   *
   * @param request
   * @return
   */
  public Configuration getArchitecture(ContentAssistRequest request) {
    IFile file = getResource(request);
    IProject project = file.getProject();
    Preferences pref = new Preferences(project);
   
    Configuration conf = null;
    IFile archFile = pref.getArchitectureFile();
   
    if (archFile != null) {
      try {
        long thisfileModStamp = getModificationStamp(archFile);
       
        if (lastUsedProject == project &&
            lastLoadedArchitecture != null &&
              loadedArchModificationStamp == thisfileModStamp) {
          // even if both files don't have a modification stamp
          // (e.g. because they are not saved in a real file, but
          // come from a stream), don't reload. Content assist must
          // be fast...
         
          conf = lastLoadedArchitecture;
        } else {
          conf = ArchitectureMappingModel.getArchitectureFromExtensionPoint(
            pref.getArchitectureFile());
                 
          lastUsedProject = project;
          loadedArchModificationStamp = thisfileModStamp;
          lastLoadedArchitecture = conf;
        }
      } catch (Exception e) {
        // don't do anything. It is more important that the user
        // doesn't see an error message than having
        // a correct content assist.
      }
    }
   
    return conf;
  }
 
  /**
   * Returns the style mapping that belongs to the currently edited
   * Architecture mapping file, or null, if no style mapping could
   * be found. The style mapping is cached internally: it is reloaded
   * every 20 seconds, since it is difficult to track if it really
   * changed.
   *
   * @param request
   * @return
   */
  public StyleMapping getStyleMapping(ContentAssistRequest request) {
    Configuration arch = getArchitecture(request);
    if (arch == null) {
      return null;
    }
   
    IFile archMappingFile = getResource(request);
   
    Element rootElem = request.getNode().getOwnerDocument().getDocumentElement();
   
    long currentTime = Calendar.getInstance().getTimeInMillis();
    long secondsSinceLastLoad = (currentTime - lastStyleMappingLoadTime) / 1000;
   
    if (lastLoadedStyleMapping != null && secondsSinceLastLoad < 20) {
      return lastLoadedStyleMapping;
    } else {
      String styleMappingFilename = rootElem.getAttribute("styleMappingFile");
      String styleMappingName = rootElem.getAttribute("styleMappingName");
     
      StyleMapping styleMapping = ArchitectureMappingModel.loadStyleMapping(archMappingFile,
          styleMappingFilename, arch.getArchitecturalStyle(),
          styleMappingName);
     
      lastLoadedStyleMapping = styleMapping;
      lastStyleMappingLoadTime = Calendar.getInstance().getTimeInMillis();
     
      return styleMapping;
    }
  }
 

 
}
TOP

Related Classes of archmapper.main.ui.ArchMappingContentAssistProcessor

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.