/*******************************************************************************
* Copyright (c) 2010 SAP AG.
* 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:
* Emil Simeonov - initial API and implementation.
* Dimitar Donchev - initial API and implementation.
* Dimitar Tenev - initial API and implementation.
* Nevena Manova - initial API and implementation.
* Georgi Konstantinov - initial API and implementation.
* Stanislav Nichev - initial API and implementation.
*******************************************************************************/
package org.eclipse.wst.sse.sieditor.command.emf.common.utils;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.query.conditions.eobjects.EObjectCondition;
import org.eclipse.emf.query.conditions.eobjects.structuralfeatures.EObjectReferencerCondition;
import org.eclipse.emf.query.statements.FROM;
import org.eclipse.emf.query.statements.IQueryResult;
import org.eclipse.emf.query.statements.SELECT;
import org.eclipse.emf.query.statements.WHERE;
import org.eclipse.wst.wsdl.Definition;
import org.eclipse.wst.wsdl.WSDLElement;
import org.eclipse.wst.wsdl.util.WSDLConstants;
import org.eclipse.xsd.XSDComplexTypeDefinition;
import org.eclipse.xsd.XSDConcreteComponent;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDNamedComponent;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.util.XSDConstants;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.eclipse.wst.sse.sieditor.model.utils.ElementAttributeUtils;
/**
* Utility class handling the refactor rename functionality for types, elements,
* parameters, etc...
*
*/
public class RefactorRenameUtils {
private static final String SOAP_HEADER_PART = "part"; //$NON-NLS-1$
private static final String SOAP_BODY_PARTS = "parts"; //$NON-NLS-1$
private static final RefactorRenameUtils INSTANCE = new RefactorRenameUtils();
private RefactorRenameUtils() {
}
public static RefactorRenameUtils instance() {
return INSTANCE;
}
public void refactorRenameComponent(final EObject baseComponent, final XSDNamedComponent componentToRename,
final String newName) {
final EObjectCondition refCondition = new EObjectReferencerCondition(componentToRename);
final IQueryResult result = new SELECT(new FROM(baseComponent), new WHERE(refCondition)).execute();
processQueryResult(componentToRename.getName(), newName, componentToRename, result);
componentToRename.setName(newName);
}
public void refactorRenameComponent(final EObject baseComponent, final WSDLElement wsdlElement, final String newName) {
final EObjectCondition refCondition = new EObjectReferencerCondition(wsdlElement);
final IQueryResult result = new SELECT(new FROM(baseComponent), new WHERE(refCondition)).execute();
processQueryResult(getWsdlElementName(wsdlElement), newName, wsdlElement, result);
setWsdlElementName(wsdlElement, newName);
}
private void processQueryResult(final String oldName, final String newName, final XSDNamedComponent component,
final IQueryResult result) {
for (final Object next : result) {
if (next instanceof XSDSchema || next instanceof Definition) {
continue; // we do not need to check root elements
}
if (next == component) {
continue;
}
if (next instanceof XSDConcreteComponent) {
refactorRenameConcreteComponent(oldName, newName, (XSDConcreteComponent) next);
} else if (next instanceof WSDLElement) {
refactorRenameWsdlElements(oldName, newName, (WSDLElement) next);
}
}
}
private void processQueryResult(final String oldName, final String newName, final WSDLElement wsdlElement,
final IQueryResult result) {
for (final Object next : result) {
if (next instanceof XSDSchema || next instanceof Definition) {
continue;
}
if (!(next instanceof WSDLElement)) {
continue;
}
refactorRenameWsdlElements(oldName, newName, (WSDLElement) next);
}
}
private void refactorRenameConcreteComponent(final String oldName, final String newName,
final XSDConcreteComponent concreteComponent) {
processContentElement(oldName, newName, concreteComponent.getElement(), XSDConstants.TYPE_ATTRIBUTE);
processContentElement(oldName, newName, concreteComponent.getElement(), XSDConstants.REF_ATTRIBUTE);
processContentElement(oldName, newName, concreteComponent.getElement(), XSDConstants.BASE_ATTRIBUTE);
processComplexTypeContent(oldName, newName, concreteComponent);
processElementDeclarationComplexType(oldName, newName, concreteComponent);
processRestrictedElement(oldName, newName, concreteComponent);
}
private void processComplexTypeContent(final String oldName, final String newName,
final XSDConcreteComponent concreteComponent) {
if (concreteComponent instanceof XSDComplexTypeDefinition) {
final Element contentElement = RemapReferencesUtils.instance().getComplexTypeContentElement(
concreteComponent.getElement());
if (contentElement != null) {
processDerivationElement(oldName, newName, contentElement, XSDConstants.EXTENSION_ELEMENT_TAG);
processDerivationElement(oldName, newName, contentElement, XSDConstants.REDEFINE_ELEMENT_TAG);
}
}
}
private void processElementDeclarationComplexType(final String oldName, final String newName,
final XSDConcreteComponent concreteComponent) {
if (concreteComponent instanceof XSDElementDeclaration) {
final XSDElementDeclaration xsdElementDeclaration = (XSDElementDeclaration) concreteComponent;
if (!xsdElementDeclaration.isElementDeclarationReference() && xsdElementDeclaration.getTypeDefinition() != null
&& xsdElementDeclaration.getTypeDefinition().getComplexType() != null) {
processDerivationElement(oldName, newName, xsdElementDeclaration.getElement(), XSDConstants.EXTENSION_ELEMENT_TAG);
processDerivationElement(oldName, newName, xsdElementDeclaration.getElement(), XSDConstants.REDEFINE_ELEMENT_TAG);
}
}
}
private void processRestrictedElement(final String oldName, final String newName, final XSDConcreteComponent concreteComponent) {
final Element componentElement = concreteComponent.getElement();
Element elementToCheckForRestrictionTag = getChildElementWithTag(componentElement, XSDConstants.SIMPLETYPE_ELEMENT_TAG);
if (elementToCheckForRestrictionTag == null) {
elementToCheckForRestrictionTag = componentElement;
}
final Element restrictionElement = getChildElementWithTag(elementToCheckForRestrictionTag,
XSDConstants.RESTRICTION_ELEMENT_TAG);
if (restrictionElement == null) {
return;
}
processContentElement(oldName, newName, restrictionElement, XSDConstants.BASE_ATTRIBUTE);
}
private Element getChildElementWithTag(final Element element, final String childElementTag) {
if (element == null) {
return null;
}
final NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
if (childElementTag.equals(childNodes.item(i).getNodeName())) {
return (Element) childNodes.item(i);
}
}
return null;
}
private void refactorRenameWsdlElements(final String oldName, final String newName, final WSDLElement wsdlElement) {
processContentElement(oldName, newName, wsdlElement.getElement(), WSDLConstants.NAME_ATTRIBUTE);
processContentElement(oldName, newName, wsdlElement.getElement(), WSDLConstants.MESSAGE_ATTRIBUTE);
processContentElement(oldName, newName, wsdlElement.getElement(), WSDLConstants.ELEMENT_ATTRIBUTE);
processContentElement(oldName, newName, wsdlElement.getElement(), WSDLConstants.TYPE_ATTRIBUTE);
processContentElement(oldName, newName, wsdlElement.getElement(), SOAP_HEADER_PART);
processContentElement(oldName, newName, wsdlElement.getElement(), SOAP_BODY_PARTS);
}
private void processDerivationElement(final String oldName, final String newName, final Element contentElement,
final String derivationTag) {
final Element derivationMethodElement = RemapReferencesUtils.instance().getComplexTypeContainingElement(contentElement,
derivationTag);
if (derivationMethodElement == null) {
return;
}
processContentElement(oldName, newName, derivationMethodElement, XSDConstants.BASE_ATTRIBUTE);
}
// =========================================================
// wsdl elements helpers
// =========================================================
private void setWsdlElementName(final WSDLElement wsdlElement, final String name) {
if (ElementAttributeUtils.hasAttributeValue(wsdlElement.getElement(), WSDLConstants.NAME_ATTRIBUTE)) {
wsdlElement.getElement().setAttribute(WSDLConstants.NAME_ATTRIBUTE, name);
}
}
private String getWsdlElementName(final WSDLElement wsdlElement) {
if (ElementAttributeUtils.hasAttributeValue(wsdlElement.getElement(), WSDLConstants.NAME_ATTRIBUTE)) {
return wsdlElement.getElement().getAttribute(WSDLConstants.NAME_ATTRIBUTE);
}
return null;
}
// =========================================================
// DOM update helpers
// =========================================================
private void processContentElement(final String oldName, final String newName, final Element contentElement,
final String attributeName) {
if (contentElement == null) {
return;
}
if (ElementAttributeUtils.hasAttributeValue(contentElement, attributeName)) {
final String qName = contentElement.getAttribute(attributeName);
final String simpleName = qName.substring(qName.indexOf(':') + 1);
if (simpleName.equals(oldName)) {
updateElementName(contentElement, newName, attributeName);
}
}
}
private void updateElementName(final Element componentElement, final String newName, final String attributeName) {
final String oldQName = componentElement.getAttribute(attributeName);
String nsPrefix = UpdateNSPrefixUtils.instance().extractPrefixFromQName(oldQName);
if (nsPrefix == null) {
nsPrefix = ""; //$NON-NLS-1$
} else {
nsPrefix += ":"; //$NON-NLS-1$
}
componentElement.setAttribute(attributeName, nsPrefix + newName);
}
}