/*******************************************************************************
* 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.quickfix.processors;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.jdt.core.IMethod;
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.beans.ui.editor.util.BeansEditorUtils;
import org.springframework.ide.eclipse.config.core.schemas.BeansSchemaConstants;
import org.springframework.ide.eclipse.core.model.validation.ValidationProblemAttribute;
import org.springframework.ide.eclipse.quickfix.BeansEditorValidator;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Factory class for creating quickfix processors.
* @author Terry Denney
* @since 2.0
*/
public enum QuickfixProcessorFactory {
CLASS, PROPERTY, REF, FACTORY_METHOD, INIT_DESTROY_METHOD, CONSTRUCTOR_ARG, RENAME_PROPERTY, RENAME_METHOD, DEPRECATED, BEAN_DEFINITION, REQUIRED_PROPERTY, NAMESPACE, NAMESPACE_ELEMENTS, FACTORY_BEAN, ALIAS;
@SuppressWarnings("unchecked")
public BeanQuickAssistProcessor create(int offset, int length, String text, boolean missingEndQuote,
IDOMNode parentNode, BeansEditorValidator validator, String problemId,
ValidationProblemAttribute... problemAttributes) {
boolean isStatic = true;
IProject project = validator.getProject();
IFile file = validator.getFile();
Set<String> properties = new HashSet<String>();
List<String> refClassNames = new ArrayList<String>();
Map<String, Node> referenceableNodes = BeansEditorUtils.getReferenceableNodes(parentNode.getOwnerDocument(),
file);
NodeList childNodes = parentNode.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node child = childNodes.item(i);
String localName = child.getLocalName();
if (localName != null) {
if (localName.equals(BeansSchemaConstants.ELEM_PROPERTY)) {
properties.add(getPropertyName(child));
}
else if (localName.equals(BeansSchemaConstants.ELEM_CONSTRUCTOR_ARG)) {
NamedNodeMap attributes = child.getAttributes();
Node refAttr = attributes.getNamedItem(BeansSchemaConstants.ATTR_REF);
String refClassName = "Object";
if (refAttr != null) {
String ref = refAttr.getNodeValue();
if (ref != null) {
Node refNode = referenceableNodes.get(ref);
refClassName = BeansEditorUtils.getClassNameForBean(refNode);
}
}
refClassNames.add(refClassName);
}
}
}
String className = null, beanName = null;
IMethod method = null;
int numConstructorArgs = -1;
List<String> missingProperties = null;
for (ValidationProblemAttribute problemAttribute : problemAttributes) {
String attributeKey = problemAttribute.getKey();
if ("CLASS".equals(attributeKey)) {
className = (String) problemAttribute.getValue();
}
else if ("BEAN".equals(attributeKey)) {
beanName = (String) problemAttribute.getValue();
}
else if ("MISSING_PROPERTIES".equals(attributeKey)) {
missingProperties = (List<String>) problemAttribute.getValue();
}
else if ("METHOD_OBJ".equals(attributeKey)) {
method = (IMethod) problemAttribute.getValue();
}
else if ("NUM_CONSTRUCTOR_ARGS".equals(attributeKey)) {
numConstructorArgs = (Integer) problemAttribute.getValue();
}
}
if (numConstructorArgs < 0) {
numConstructorArgs = refClassNames.size();
}
switch (this) {
case CLASS:
if ("CLASS_NOT_FOUND".equals(problemId)) {
return new ClassAttributeQuickAssistProcessor(offset, length, text, project, missingEndQuote,
properties, numConstructorArgs);
}
case PROPERTY:
if (className != null) {
if ("NO_GETTER".equals(problemId)) {
return new PropertyAttributeQuickAssistProcessor(offset, length, className, text, project,
missingEndQuote, PropertyAttributeQuickAssistProcessor.Type.GETTER);
}
if ("NO_SETTER".equals(problemId)) {
return new PropertyAttributeQuickAssistProcessor(offset, length, className, text, project,
missingEndQuote, PropertyAttributeQuickAssistProcessor.Type.SETTER);
}
}
break;
case REF:
if ("UNDEFINED_PARENT_BEAN".equals(problemId) || "UNDEFINED_DEPENDS_ON_BEAN".equals(problemId)
|| "UNDEFINED_FACTORY_BEAN".equals(problemId) || "UNDEFINED_REFERENCED_BEAN".equals(problemId)) {
return new BeanReferenceQuickAssistProcessor(offset, length, text, missingEndQuote, parentNode,
BeansSchemaConstants.ATTR_REF, beanName, file);
}
break;
case FACTORY_METHOD:
if ("NO_FACTORY_METHOD".equals(problemId) || "UNDEFINED_FACTORY_BEAN_METHOD".equals(problemId)) {
return new MethodAttributeQuickAssistProcessor(offset, length, className, text, missingEndQuote,
parentNode, BeansSchemaConstants.ATTR_FACTORY_METHOD, project, isStatic,
new FactoryMethodContentAssistCalculator(), file);
}
break;
case FACTORY_BEAN:
if ("UNDEFINED_FACTORY_BEAN".equals(problemId)) {
return new BeanReferenceQuickAssistProcessor(offset, length, text, missingEndQuote, parentNode,
BeansSchemaConstants.ATTR_FACTORY_BEAN, beanName, file);
}
if ("NO_FACTORY_METHOD".equals(problemId) || "UNDEFINED_FACTORY_BEAN_METHOD".equals(problemId)) {
return new MissingFactoryMethodAttributeQuickAssistProcessor(offset, length, text, missingEndQuote,
parentNode);
}
case INIT_DESTROY_METHOD:
if ("UNDEFINED_INIT_METHOD".equals(problemId)) {
return new MethodAttributeQuickAssistProcessor(offset, length, className, text, missingEndQuote,
parentNode, BeansSchemaConstants.ATTR_INIT_METHOD, project, isStatic,
new InitDestroyMethodContentAssistCalculator(), file);
}
else if ("UNDEFINED_DESTROY_METHOD".equals(problemId)) {
return new MethodAttributeQuickAssistProcessor(offset, length, className, text, missingEndQuote,
parentNode, BeansSchemaConstants.ATTR_DESTROY_METHOD, project, isStatic,
new InitDestroyMethodContentAssistCalculator(), file);
}
case CONSTRUCTOR_ARG:
if ("NO_CONSTRUCTOR".equals(problemId)) {
return new ConstructorArgQuickAssistProcessor(offset, length, text, project, missingEndQuote,
refClassNames, parentNode);
}
if ("MISSING_CONSTRUCTOR_ARG_NAME".equals(problemId)) {
return new ConstructorArgNameQuickAssistProcessor(offset, length, text, className, project,
missingEndQuote, numConstructorArgs, parentNode);
}
break;
case RENAME_PROPERTY:
return new RenamePropertyQuickAssistProcessor(offset, length, className, text, project, missingEndQuote,
validator.getFile());
case RENAME_METHOD:
return new RenameMethodQuickAssistProcessor(offset, length, className, text, project, missingEndQuote,
validator.getFile());
case NAMESPACE_ELEMENTS:
return new NameSpaceElementsQuickAssistProcessor(problemId, offset, length, text, missingEndQuote, project,
parentNode, file, problemAttributes);
// TODO: processor for bean definition?
// TODO: processor for required property missing?
// TODO: processor for namespace element
case REQUIRED_PROPERTY:
if (missingProperties != null) {
return new RequiredPropertyQuickAssistProcessor(offset, length, text, missingEndQuote,
missingProperties, parentNode);
}
break;
case DEPRECATED:
if ("CLASS_IS_DEPRECATED".equals(problemId) && className != null) {
return new ClassDeprecatedQuickAssistProcessor(offset, length, text, missingEndQuote, className,
project);
}
if ("METHOD_IS_DEPRECATED".equals(problemId) && method != null && className != null) {
return new MethodDeprecatedQuickAssistProcessor(offset, length, text, missingEndQuote, className,
method.getElementName(), method);
}
break;
}
return null;
}
private String getPropertyName(Node child) {
NamedNodeMap attributes = child.getAttributes();
Node attribute = attributes.getNamedItem(BeansSchemaConstants.ATTR_NAME);
return attribute.getNodeValue();
}
}