Package org.springframework.ide.eclipse.internal.bestpractices.quickfix

Source Code of org.springframework.ide.eclipse.internal.bestpractices.quickfix.MarkerResolutionGenerator

/*******************************************************************************
*  Copyright (c) 2012 VMware, Inc.
*  All rights reserved. This program and the accompanying materials
*  are made available under the terms of the Eclipse Public License v1.0
*  which accompanies this distribution, and is available at
*  http://www.eclipse.org/legal/epl-v10.html
*
*  Contributors:
*      VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.internal.bestpractices.quickfix;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IMarkerResolution;
import org.eclipse.ui.IMarkerResolutionGenerator2;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.xml.core.internal.document.AttrImpl;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.springframework.ide.eclipse.beans.ui.editor.contentassist.bean.FactoryMethodContentAssistCalculator;
import org.springframework.ide.eclipse.beans.ui.editor.contentassist.bean.InitDestroyMethodContentAssistCalculator;
import org.springframework.ide.eclipse.config.core.schemas.BeansSchemaConstants;
import org.springframework.ide.eclipse.quickfix.processors.BeanReferenceQuickAssistProcessor;
import org.springframework.ide.eclipse.quickfix.processors.ClassAttributeQuickAssistProcessor;
import org.springframework.ide.eclipse.quickfix.processors.ConstructorArgQuickAssistProcessor;
import org.springframework.ide.eclipse.quickfix.processors.MethodAttributeQuickAssistProcessor;
import org.springframework.ide.eclipse.quickfix.processors.PropertyAttributeQuickAssistProcessor;
import org.springframework.ide.eclipse.quickfix.processors.RequiredPropertyQuickAssistProcessor;
import org.springsource.ide.eclipse.commons.core.StatusHandler;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


/**
* Produces an IMarkerResolution instance for a given marker, if applicable.
* This Generator currently supports only one resolution per rule.
* @author Wesley Coelho
* @author Christian Dupuis
* @author Leo Dos Santos
* @author Terry Denney
*/
public class MarkerResolutionGenerator implements IMarkerResolutionGenerator2 {

  private class NodeInfo {
    private final IDOMNode node;

    private final int offset;

    private final int length;

    private NodeInfo(IDOMNode node, int offset, int length) {
      this.node = node;
      this.offset = offset;
      this.length = length;
    }
  }

  private static final String ERROR_ID_CLASS_NOT_FOUND = "CLASS_NOT_FOUND";

  private static final String ERROR_ID_UNDEFINED_REFERENCED_BEAN = "UNDEFINED_REFERENCED_BEAN";

  private static final String ERROR_ID_NO_SETTER = "NO_SETTER";

  private static final String ERROR_ID_NO_GETTER = "NO_GETTER";

  private static final String ERROR_ID_KEY = "errorId";

  private static final String ERROR_ID_UNDEFINED_INIT = "UNDEFINED_INIT_METHOD";

  private static final String ERROR_ID_UNDEFINED_DESTROY = "UNDEFINED_DESTROY_METHOD";

  private static final String ERROR_ID_REQUIRED_PROPERTY_MISSING = "REQUIRED_PROPERTY_MISSING";

  private static final String ERROR_ID_NO_CONSTRUCTOR = "NO_CONSTRUCTOR";

  private static final String ERROR_ID_UNDEFINED_FACTORY_BEAN_METHOD = "UNDEFINED_FACTORY_BEAN_METHOD";

  private IDOMNode findMatchedBean(NodeList nodes, String beanName) {
    if (nodes == null) {
      return null;
    }

    for (int i = 0; i < nodes.getLength(); i++) {
      Node item = nodes.item(i);
      if (BeansSchemaConstants.ELEM_BEAN.equals(item.getNodeName())) {
        if (item.getAttributes() != null) {
          AttrImpl attr = (AttrImpl) item.getAttributes().getNamedItem(BeansSchemaConstants.ATTR_NAME);
          if (attr != null) {
            if (beanName.equals(attr.getNodeValue())) {
              return (IDOMNode) item;
            }
          }

          attr = (AttrImpl) item.getAttributes().getNamedItem(BeansSchemaConstants.ATTR_ID);
          if (attr != null) {
            if (beanName.equals(attr.getNodeValue())) {
              return (IDOMNode) item;
            }
          }
        }
      }

      IDOMNode childNode = findMatchedBean(item.getChildNodes(), beanName);
      if (childNode != null) {
        return childNode;
      }
    }

    return null;
  }

  private NodeInfo findNodeInfo(IDOMNode node, String attrName, String attrValue) {
    if (node != null) {
      NamedNodeMap attributes = node.getAttributes();
      if (attributes != null) {
        for (int i = 0; i < attributes.getLength(); i++) {
          AttrImpl attribute = (AttrImpl) attributes.item(i);
          if (attrName == null || attrName.equals(attribute.getNodeName())) {
            if (attrValue != null && attrValue.equals(attribute.getNodeValue())) {
              int offset = attribute.getValueRegionStartOffset();

              // increase offset if value starts with
              // "
              if (attribute.getValueRegion().getLength() > attrValue.length()) {
                offset++;
              }
              int length = attribute.getNodeValue() == null ? 0 : attribute.getNodeValue().length();
              return new NodeInfo(node, offset, length);
            }
          }
        }
      }

      NodeList children = node.getChildNodes();
      for (int i = 0; i < children.getLength(); i++) {
        NodeInfo info = findNodeInfo((IDOMNode) children.item(i), attrName, attrValue);
        if (info != null) {
          return info;
        }
      }
    }

    return null;
  }

  protected NodeInfo findNodeInfo(IMarker marker, String attrName, String attrValue) {
    IDOMModel model = null;
    try {
      String beanName = (String) marker.getAttribute("BEAN_NAME");

      if (beanName == null) {
        return null;
      }

      IFile file = (IFile) marker.getResource();
      model = (IDOMModel) StructuredModelManager.getModelManager().getModelForRead(file);
      if (model != null) {
        IDOMDocument document = model.getDocument();
        if (document != null) {
          NodeList nodes = document.getChildNodes();
          IDOMNode node = findMatchedBean(nodes, beanName);
          return findNodeInfo(node, attrName, attrValue);
        }
      }
    }
    catch (CoreException e) {

    }
    catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    finally {
      if (model != null) {
        model.releaseFromRead();
      }
    }
    return null;
  }

  /**
   * Return the resolution(s) for the given marker. Currently supports only
   * one resolution per marker.
   */
  public IMarkerResolution[] getResolutions(IMarker marker) {
    ICompletionProposal[] proposals = null;

    // Do not offer resolutions if the editor is dirty because the marker
    // position may be incorrect
    IEditorPart editor = XmlQuickFixUtil.getMarkedEditor(marker);
    if (editor != null && editor.isDirty()) {
      return new IMarkerResolution[0];
    }

    try {
      String errorId = (String) marker.getAttribute(ERROR_ID_KEY);
      String className = marker.getAttribute("CLASS", null);
      IFile file = marker.getResource() instanceof IFile ? (IFile) marker.getResource() : null;

      if (ERROR_ID_NO_CONSTRUCTOR.equals(errorId)) {
        int numArgument = marker.getAttribute("NUM_ARGUMENT", 0);
        if (className != null) {
          NodeInfo nodeInfo = findNodeInfo(marker, BeansSchemaConstants.ATTR_CLASS, className);
          if (nodeInfo != null && file != null) {

            List<String> argClassNames = new ArrayList<String>();
            for (int i = 0; i < numArgument; i++) {
              // TODO: narrow this down to a type
              argClassNames.add("Object");
            }
            proposals = new ConstructorArgQuickAssistProcessor(nodeInfo.offset, nodeInfo.length, className,
                file.getProject(), false, argClassNames, nodeInfo.node)
                .computeQuickAssistProposals(null);
          }
        }
      }
      else if (ERROR_ID_REQUIRED_PROPERTY_MISSING.equals(errorId)) {
        List<String> requiredProperties = new ArrayList<String>();
        String requiredProperty = null;
        int counter = 1;
        do {
          requiredProperty = marker.getAttribute("MISSING_PROPERTIES" + counter, null);
          if (requiredProperty != null) {
            requiredProperties.add(requiredProperty);
          }
          counter++;
        } while (requiredProperty != null);

        if (requiredProperties.size() > 0 && className != null) {
          NodeInfo nodeInfo = findNodeInfo(marker, BeansSchemaConstants.ATTR_CLASS, className);
          if (nodeInfo != null) {
            proposals = new RequiredPropertyQuickAssistProcessor(nodeInfo.offset, nodeInfo.length,
                className, false, requiredProperties, nodeInfo.node).computeQuickAssistProposals(null);
          }
        }
      }
      else if (ERROR_ID_UNDEFINED_DESTROY.equals(errorId)) {
        String methodName = marker.getAttribute("METHOD", null);
        if (methodName != null && className != null) {
          NodeInfo nodeInfo = findNodeInfo(marker, BeansSchemaConstants.ATTR_DESTROY_METHOD, methodName);
          if (nodeInfo != null && file != null) {
            proposals = new MethodAttributeQuickAssistProcessor(nodeInfo.offset, nodeInfo.length,
                className, methodName, true, nodeInfo.node, BeansSchemaConstants.ATTR_DESTROY_METHOD,
                file.getProject(), false, new InitDestroyMethodContentAssistCalculator(), file)
                .computeQuickAssistProposals(null);
          }
        }
      }
      else if (ERROR_ID_UNDEFINED_INIT.equals(errorId)) {
        String methodName = marker.getAttribute("METHOD", null);
        if (methodName != null && className != null) {
          NodeInfo nodeInfo = findNodeInfo(marker, BeansSchemaConstants.ATTR_INIT_METHOD, methodName);
          if (nodeInfo != null && file != null) {
            proposals = new MethodAttributeQuickAssistProcessor(nodeInfo.offset, nodeInfo.length,
                className, methodName, true, nodeInfo.node, BeansSchemaConstants.ATTR_INIT_METHOD,
                file.getProject(), false, new InitDestroyMethodContentAssistCalculator(), file)
                .computeQuickAssistProposals(null);
          }
        }
      }
      else if (ERROR_ID_UNDEFINED_FACTORY_BEAN_METHOD.equals(errorId)) {
        String methodName = marker.getAttribute("METHOD", null);
        if (methodName != null && className != null) {
          NodeInfo nodeInfo = findNodeInfo(marker, BeansSchemaConstants.ATTR_FACTORY_METHOD, methodName);
          if (nodeInfo != null && file != null) {
            proposals = new MethodAttributeQuickAssistProcessor(nodeInfo.offset, nodeInfo.length,
                className, methodName, true, nodeInfo.node, BeansSchemaConstants.ATTR_FACTORY_METHOD,
                file.getProject(), false, new FactoryMethodContentAssistCalculator(), file)
                .computeQuickAssistProposals(null);
          }
        }
      }
      else if (ERROR_ID_NO_SETTER.equals(errorId)) {
        String propertyName = marker.getAttribute("PROPERTY", null);
        if (className != null && propertyName != null && file != null) {
          NodeInfo nodeInfo = findNodeInfo(marker, BeansSchemaConstants.ATTR_NAME, propertyName);
          if (nodeInfo != null) {
            proposals = new PropertyAttributeQuickAssistProcessor(nodeInfo.offset, nodeInfo.length,
                className, propertyName, file.getProject(), false,
                PropertyAttributeQuickAssistProcessor.Type.SETTER).computeQuickAssistProposals(null);
          }
        }
      }
      else if (ERROR_ID_NO_GETTER.equals(errorId)) {
        String propertyName = marker.getAttribute("PROPERTY", null);
        if (className != null && propertyName != null && file != null) {
          NodeInfo nodeInfo = findNodeInfo(marker, BeansSchemaConstants.ATTR_NAME, propertyName);
          if (nodeInfo != null) {
            proposals = new PropertyAttributeQuickAssistProcessor(nodeInfo.offset, nodeInfo.length,
                className, propertyName, file.getProject(), false,
                PropertyAttributeQuickAssistProcessor.Type.GETTER).computeQuickAssistProposals(null);
          }
        }
      }
      else if (ERROR_ID_CLASS_NOT_FOUND.equals(errorId)) {
        if (className != null) {
          NodeInfo nodeInfo = findNodeInfo(marker, BeansSchemaConstants.ATTR_CLASS, className);
          if (nodeInfo != null && file != null) {
            proposals = new ClassAttributeQuickAssistProcessor(nodeInfo.offset, nodeInfo.length, className,
                file.getProject(), false, new HashSet<String>(), 0).computeQuickAssistProposals(null);
          }
        }
      }
      else if (ERROR_ID_UNDEFINED_REFERENCED_BEAN.equals(errorId)) {
        String beanName = marker.getAttribute("BEAN", null);
        if (beanName != null) {
          NodeInfo nodeInfo = findNodeInfo(marker, BeansSchemaConstants.ATTR_REF, beanName);
          if (nodeInfo == null) {
            nodeInfo = findNodeInfo(marker, BeansSchemaConstants.ATTR_PARENT, beanName);
          }
          if (nodeInfo == null) {
            nodeInfo = findNodeInfo(marker, BeansSchemaConstants.ATTR_FACTORY_BEAN, beanName);
          }
          if (nodeInfo != null && file != null) {
            proposals = new BeanReferenceQuickAssistProcessor(nodeInfo.offset, nodeInfo.length, beanName,
                false, nodeInfo.node, BeansSchemaConstants.ATTR_REF, beanName, file)
                .computeQuickAssistProposals(null);
          }
        }
      }
    }
    catch (CoreException e) {
      StatusHandler.log(e.getStatus());
    }

    if (proposals != null) {
      List<IMarkerResolution> resolutions = new ArrayList<IMarkerResolution>();
      for (ICompletionProposal proposal : proposals) {
        if (proposal instanceof IMarkerResolution) {
          resolutions.add((IMarkerResolution) proposal);
        }
      }
      return resolutions.toArray(new IMarkerResolution[resolutions.size()]);
    }
    return new IMarkerResolution[0];
  }

  public boolean hasResolutions(IMarker marker) {
    String errorId = marker.getAttribute(ERROR_ID_KEY, null);
    String className = marker.getAttribute("CLASS", null);

    if (errorId == null) {
      return false;
    }

    if (ERROR_ID_NO_CONSTRUCTOR.equals(errorId)) {
      return className != null;
    }
    else if (ERROR_ID_REQUIRED_PROPERTY_MISSING.equals(errorId)) {
      return true;
    }
    else if (ERROR_ID_UNDEFINED_DESTROY.equals(errorId)) {
      String methodName = marker.getAttribute("METHOD", null);
      return methodName != null && className != null;
    }
    else if (ERROR_ID_UNDEFINED_INIT.equals(errorId)) {
      String methodName = marker.getAttribute("METHOD", null);
      return methodName != null && className != null;
    }
    else if (ERROR_ID_UNDEFINED_FACTORY_BEAN_METHOD.equals(errorId)) {
      String methodName = marker.getAttribute("METHOD", null);
      return methodName != null && className != null;
    }
    else if (ERROR_ID_NO_SETTER.equals(errorId)) {
      String propertyName = marker.getAttribute("PROPERTY", null);
      return propertyName != null && className != null;
    }
    else if (ERROR_ID_NO_GETTER.equals(errorId)) {
      String propertyName = marker.getAttribute("PROPERTY", null);
      return propertyName != null && className != null;
    }
    else if (ERROR_ID_CLASS_NOT_FOUND.equals(errorId)) {
      return className != null;
    }
    else if (ERROR_ID_UNDEFINED_REFERENCED_BEAN.equals(errorId)) {
      String beanName = marker.getAttribute("BEAN", null);
      return beanName != null;
    }

    return false;
  }

}
TOP

Related Classes of org.springframework.ide.eclipse.internal.bestpractices.quickfix.MarkerResolutionGenerator

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.