blob: 22dc5fa3c246d0e46eb25e866044966878d91380 [file] [log] [blame]
/*******************************************************************************
* 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.model.reconcile;
import java.util.List;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.xml.type.internal.QName;
import org.eclipse.wst.wsdl.Binding;
import org.eclipse.wst.wsdl.Definition;
import org.eclipse.wst.wsdl.Fault;
import org.eclipse.wst.wsdl.Message;
import org.eclipse.wst.wsdl.MessageReference;
import org.eclipse.wst.wsdl.Operation;
import org.eclipse.wst.wsdl.Part;
import org.eclipse.wst.wsdl.Port;
import org.eclipse.wst.wsdl.Service;
import org.eclipse.wst.wsdl.util.WSDLConstants;
import org.eclipse.xsd.XSDAttributeDeclaration;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.XSDTypeDefinition;
import org.eclipse.xsd.util.XSDConstants;
import org.w3c.dom.Element;
import org.eclipse.wst.sse.sieditor.command.emf.common.namespace.UpdateNSPrefixUtils;
import org.eclipse.wst.sse.sieditor.model.utils.EmfXsdUtils;
/**
* This is the default implementation of the {@link IReconcileUtils} interface.
*
*
*
*/
public class ReconcileUtils implements IReconcileUtils {
private static final IReconcileUtils INSTANCE = new ReconcileUtils();
private ReconcileUtils() {
}
public static IReconcileUtils instance() {
return INSTANCE;
}
// =========================================================
// reconcile schema elements references
// =========================================================
@Override
public void reconcileSchemaContents(final XSDSchema schema, final List<XSDElementDeclaration> elementsForReferenceResolve,
final List<XSDElementDeclaration> elementsForTypeResolve, final List<XSDAttributeDeclaration> attributesForResolve) {
this.reconcileElementsReferences(schema, elementsForReferenceResolve);
this.reconcileElementsTypes(schema, elementsForTypeResolve);
this.reconcileAttributesReferences(schema, attributesForResolve);
}
private void reconcileElementsTypes(final XSDSchema changedSchema,
final java.util.List<XSDElementDeclaration> elementsForTypeResolve) {
for (final XSDElementDeclaration xsdElementDeclaration : elementsForTypeResolve) {
if (xsdElementDeclaration.getTypeDefinition() == null) {
continue;
}
final XSDTypeDefinition resolvedTypeDefinition = resolveUtils().resolveTypeDefinition(changedSchema,
changedSchema.getTargetNamespace(),
xsdElementDeclaration.getTypeDefinition().getName());
if (resolvedTypeDefinition != null) {
xsdElementDeclaration.setTypeDefinition(resolvedTypeDefinition);
}
}
};
private void reconcileElementsReferences(final XSDSchema changedSchema, final List<XSDElementDeclaration> elementsForResolve) {
for (final XSDElementDeclaration xsdElementDeclaration : elementsForResolve) {
final XSDElementDeclaration newResolveElementDeclaration = resolveUtils().resolveElementDeclaration(changedSchema,
changedSchema.getTargetNamespace(), xsdElementDeclaration.getResolvedElementDeclaration().getName());
if (newResolveElementDeclaration != null) {
// the element declaration was resolved, so we proceed with
// the reference update
final String prefix = prefixUtils().extractPrefixFromQName(
xsdElementDeclaration.getElement().getAttribute(XSDConstants.REF_ATTRIBUTE));
final String tnsForPrefix = changedSchema.getQNamePrefixToNamespaceMap().get(prefix);
if (isElementCorrectlyResolved(changedSchema, changedSchema.getElement(), newResolveElementDeclaration
.getTargetNamespace(), prefix, tnsForPrefix)) {
xsdElementDeclaration.setResolvedElementDeclaration(newResolveElementDeclaration);
}
}
}
}
private void reconcileAttributesReferences(final XSDSchema changedSchema,
final List<XSDAttributeDeclaration> attributesForResolve) {
for (final XSDAttributeDeclaration xsdAttributeDeclaration : attributesForResolve) {
final XSDAttributeDeclaration newResolveAttributeDeclaration = resolveUtils().resolveAttributeDeclaration(
changedSchema, changedSchema.getTargetNamespace(),
xsdAttributeDeclaration.getResolvedAttributeDeclaration().getName());
if (newResolveAttributeDeclaration != null) {
final String prefix = prefixUtils().extractPrefixFromQName(
xsdAttributeDeclaration.getElement().getAttribute(XSDConstants.REF_ATTRIBUTE));
final String tnsForPrefix = changedSchema.getQNamePrefixToNamespaceMap().get(prefix);
if (isElementCorrectlyResolved(changedSchema, changedSchema.getElement(), newResolveAttributeDeclaration
.getTargetNamespace(), prefix, tnsForPrefix)) {
xsdAttributeDeclaration.setResolvedAttributeDeclaration(newResolveAttributeDeclaration);
}
}
}
}
// =========================================================
// reconcile WSDL element references
// =========================================================
@Override
public void reconcileMessages(final List<Message> messagesForResolve, final Definition definition) {
for (final Message message : messagesForResolve) {
String namespaceURI = definition.getNamespace(message.getQName().getPrefix());
if ("".equals(message.getQName().getPrefix())) { //$NON-NLS-1$
namespaceURI = definition.getTargetNamespace();
}
message.setQName(new QName(namespaceURI, message.getQName().getLocalPart(), message.getQName().getPrefix()));
}
}
@Override
public void reconcileMessagePartsReferences(final XSDSchema changedSchema, final List<Part> messagePartsForResolve,
final Definition definition) {
for (final Part part : messagePartsForResolve) {
if (part.getElementDeclaration() != null) {
reconcileMessagePartReference(changedSchema, definition, part);
}
}
}
private void reconcileMessagePartReference(final XSDSchema changedSchema, final Definition definition, final Part part) {
// try and resolve the message using the current resolverScheam
final XSDElementDeclaration newResolvedElementDeclaration = resolveUtils().resolveElementDeclaration(changedSchema, null,
part.getElementName().getLocalPart());
if (newResolvedElementDeclaration == null) {
// the attribute declaration was not resolved. the message must be
// in another schema
return;
}
final String prefix = prefixUtils().extractPrefixFromQName(
part.getElement().getAttribute(WSDLConstants.ELEMENT_ATTRIBUTE));
final String tnsForPrefix = changedSchema.getQNamePrefixToNamespaceMap().get(prefix);
if (isElementCorrectlyResolved(changedSchema, definition.getElement(),
newResolvedElementDeclaration.getTargetNamespace(), prefix, tnsForPrefix)) {
part.setElementName(new QName(tnsForPrefix, part.getElementName().getLocalPart(), part.getElementName().getPrefix()));
part.setElementDeclaration(newResolvedElementDeclaration);
}
}
@Override
public void reconcileOperationsMessagesReferences(final List<Operation> operationsForResolve,
final Definition editedDefinition, final EList<Message> eMessages, final String prefix) {
for (final Operation operation : operationsForResolve) {
for (final Message currentMessage : eMessages) {
processMessageReference(operation.getEInput(), currentMessage, prefix);
processMessageReference(operation.getEOutput(), currentMessage, prefix);
processFaults(operation, currentMessage, prefix);
}
}
}
@SuppressWarnings("unchecked")
private void processFaults(final Operation operation, final Message message, final String prefix) {
final EList<Fault> eFaults = operation.getEFaults();
for (final Fault fault : eFaults) {
if (fault.getMessage() == null) {
processMessageReference(fault, message, prefix);
}
}
}
private void processMessageReference(final MessageReference messageReference, final Message message, String prefix) {
if (messageReference != null && (messageReference.getEMessage() == null
/*
* || ( messageReference . getEMessage ( ) . getEnclosingDefinition ( )
* . getTargetNamespace ( ) != null && ! messageReference . getEMessage
* ( ) . getEnclosingDefinition ( ) . getTargetNamespace ( ) . equals (
* message . getQName ( ) . getNamespaceURI ( ) ) )
*/)) {
final String messageQName = messageReference.getElement().getAttribute(WSDLConstants.MESSAGE_ATTRIBUTE);
if (messageQName == null) {
return;
}
final String messageName = messageQName.substring(messageQName.indexOf(':') + 1);
if (prefix == null) {
prefix = prefixUtils().extractPrefixFromQName(messageQName);
}
// check if this is the correct message to be resolved
if (message.getQName().getLocalPart().equals(messageName)
&& (message.getQName().getPrefix().equals(prefix == null ? "" : prefix) || message.getQName().getPrefix() //$NON-NLS-1$
.equals(""))) { //$NON-NLS-1$
messageReference.setEMessage(message);
}
}
}
@Override
@SuppressWarnings("unchecked")
public void reconcileBindingsQNames(final Definition definition) {
final EList<Binding> eBindings = definition.getEBindings();
if (eBindings != null) {
for (final Binding binding : eBindings) {
if (binding.getEnclosingDefinition() != definition) {
continue;
}
binding.setQName(new QName(definition.getTargetNamespace(), binding.getQName().getLocalPart(), binding.getQName()
.getPrefix().equals(EmfXsdUtils.XMLNS_PREFIX) ? "" : binding.getQName().getPrefix())); //$NON-NLS-1$
}
}
}
// @Override
// public void reconcileBindingsQNames(final EList<Binding> eBindings, final
// String targetNamespace,
// final EList<PortType> ePortTypesToCheck) {
// if (eBindings != null) {
// for (final Binding binding : eBindings) {
// if (binding.getEPortType() == null) {
// final String portTypeQName =
// binding.getElement().getAttribute(WSDLConstants.TYPE_ATTRIBUTE);
// final String portTypeName =
// portTypeQName.substring(portTypeQName.indexOf(':') + 1);
// final String prefix =
// prefixUtils().extractPrefixFromQName(portTypeQName);
//
// for (final PortType portType : ePortTypesToCheck) {
// if (portTypeName.equals(portType.getQName().getLocalPart())) {
// portType.setQName(new QName(portType.getQName().getNamespaceURI(),
// portType.getQName().getLocalPart(), prefix));
// binding.setEPortType(portType);
// binding.setQName(new QName(targetNamespace,
// binding.getQName().getLocalPart(), binding.getQName()
// .getPrefix().equals(EmfXsdUtils.XMLNS_PREFIX) ? "" : binding.getQName().getPrefix())); //$NON-NLS-1$
// }
// }
// }
// }
// }
// }
@Override
@SuppressWarnings("unchecked")
public void reconcileServicePortBindings(final Definition definition, final EList<Binding> eBindings) {
final EList<Service> eServices = definition.getEServices();
if (eServices != null) {
for (final Service service : eServices) {
final EList<Port> ePorts = service.getEPorts();
if (ePorts == null) {
continue;
}
resolvePorts(definition, ePorts, eBindings);
}
}
}
/**
* Utility method for resolving the port bindings. For each port it searches
* all the bindings in the given definition and determines which one is the
* correct one to be set to the port binding.
*/
private void resolvePorts(final Definition definition, final EList<Port> ePorts, final EList<Binding> eBindings) {
for (final Port port : ePorts) {
if (port.getEBinding() != null || port.getEnclosingDefinition() != definition) {
continue;
}
final String portBindingQName = port.getElement().getAttribute(WSDLConstants.BINDING_ATTRIBUTE);
final String portBindingName = portBindingQName.substring(portBindingQName.indexOf(':') + 1);
String prefix = prefixUtils().extractPrefixFromQName(portBindingQName);
if (prefix == null) {
prefix = ""; //$NON-NLS-1$
}
// we need to search all the bindings in the definition, so that we
// can find the correct binding to set to the portBinding
for (final Binding binding : eBindings) {
if (binding.getQName().getLocalPart().equals(portBindingName)
&& binding.getQName().getNamespaceURI().equals(definition.getNamespaces().get(prefix))) {
port.setEBinding(binding);
break;
}
}
}
}
// =========================================================
// resolve helpers
// =========================================================
protected IResolveUtils resolveUtils() {
return ResolveUtils.instance();
}
// =========================================================
// helpers
// =========================================================
/**
* Utility method. Checks if the prefix is an actual and valid one, so that
* we can safely set the new reference.
*/
private boolean isElementCorrectlyResolved(final XSDSchema schema, final Element element,
final String resolvedTargetNamespace, final String prefix, final String tnsForPrefix) {
final boolean targetNamespacesAreTheSame = (tnsForPrefix != null && tnsForPrefix.equals(resolvedTargetNamespace));
// this is used to resolve referred elements from importing schemas
final boolean prefixValueMatchesResolvedTargetNamespace = (schema.getQNamePrefixToNamespaceMap().get(prefix) != null && schema
.getQNamePrefixToNamespaceMap().get(prefix).equals(resolvedTargetNamespace));
return targetNamespacesAreTheSame
&& (element.getAttribute(tnsPrefixAttribute(prefix)) != null || prefixValueMatchesResolvedTargetNamespace);
}
/**
* Utility method. It builds the tns prefix attribute for the given prefix.
* If the prefix is some custom prefix (for e.g. "ns1"), it returns "xmlns:"
* + "ns1". <br>
* <br>
* If the prefix is the default one, it simply returns it.
*/
private String tnsPrefixAttribute(final String prefix) {
String prefixAttribute = null;
if (EmfXsdUtils.XMLNS_PREFIX.equals(prefix)) {
prefixAttribute = EmfXsdUtils.XMLNS_PREFIX;
} else {
prefixAttribute = EmfXsdUtils.XMLNS_PREFIX + ':' + prefix;
}
return prefixAttribute;
}
private UpdateNSPrefixUtils prefixUtils() {
return UpdateNSPrefixUtils.instance();
}
}