/******************************************************************************* * 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.utils; import java.util.LinkedList; import java.util.List; import java.util.Map; 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.XSDElementDeclaration; import org.eclipse.xsd.XSDSchema; import org.w3c.dom.Element; import org.eclipse.wst.sse.sieditor.command.emf.common.utils.UpdateNSPrefixUtils; import org.eclipse.wst.sse.sieditor.model.reconcile.IResolveUtils; import org.eclipse.wst.sse.sieditor.model.reconcile.ResolveUtils; import org.eclipse.wst.sse.sieditor.model.reconcile.utils.IXsdReconcileUtils.NamespaceResolverType; import org.eclipse.wst.sse.sieditor.model.utils.EmfXsdUtils; /** * This is the default implementation of the {@link IWsdlReconcileUtils} * interface. * */ public class WsdlReconcileUtils implements IWsdlReconcileUtils { private static final IWsdlReconcileUtils INSTANCE = new WsdlReconcileUtils(); private WsdlReconcileUtils() { } public static IWsdlReconcileUtils instance() { return INSTANCE; } @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) { reconcileMessagePartsInternal(changedSchema, messagePartsForResolve, definition, NamespaceResolverType.ELEMENT); reconcileMessagePartsInternal(changedSchema, messagePartsForResolve, definition, NamespaceResolverType.SCHEMA); } private void reconcileMessagePartsInternal(final XSDSchema changedSchema, final List<Part> messagePartsForResolve, final Definition definition, final NamespaceResolverType namespaceResolverType) { final List<Part> reconciledMessageParts = new LinkedList<Part>(); for (final Part part : messagePartsForResolve) { if (part.getElementDeclaration() != null) { final String targetNamespace = namespaceResolverType == NamespaceResolverType.ELEMENT ? part.getElementName() .getNamespaceURI() : changedSchema.getTargetNamespace(); final boolean messagePartReconciled = reconcileMessagePartReference(changedSchema, changedSchema .getQNamePrefixToNamespaceMap(), definition, part, targetNamespace); if (messagePartReconciled) { reconciledMessageParts.add(part); } } } messagePartsForResolve.removeAll(reconciledMessageParts); } private boolean reconcileMessagePartReference(final XSDSchema changedSchema, final Map<String, String> prefixesMap, final Definition definition, final Part part, final String targetNamespaceForResolve) { final XSDElementDeclaration newResolvedElementDeclaration = resolveUtils().resolveElementDeclaration(changedSchema, targetNamespaceForResolve, part.getElementName().getLocalPart()); if (newResolvedElementDeclaration == null) { // the attribute declaration was not resolved. the message must be // in another schema return false; } final String prefix = prefixUtils().extractPrefixFromQName( part.getElement().getAttribute(WSDLConstants.ELEMENT_ATTRIBUTE)); final String tnsForPrefix = changedSchema.getQNamePrefixToNamespaceMap().get(prefix); if (isElementCorrectlyResolved(changedSchema, prefixesMap, definition.getElement(), newResolvedElementDeclaration .getTargetNamespace(), prefix, tnsForPrefix)) { part.setElementName(new QName(tnsForPrefix, part.getElementName().getLocalPart(), part.getElementName().getPrefix())); part.setElementDeclaration(newResolvedElementDeclaration); return true; } return false; } @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, final String prefix) { if (messageReference == null || messageReference.getEMessage() != null) { return; } final String messageDOMqName = messageReference.getElement().getAttribute(WSDLConstants.MESSAGE_ATTRIBUTE); if (messageDOMqName == null || messageDOMqName.isEmpty()) { return; } final String expectedPrefix = prefix != null ? prefix : getPrefixForDefinition(messageDOMqName); final String prefixNamespace = message.getEnclosingDefinition().getNamespace(expectedPrefix); final javax.xml.namespace.QName messageEMFqName = message.getQName(); if (prefixNamespace != null && !prefixNamespace.equals(messageEMFqName.getNamespaceURI())) { return; } final String messageDOMname = messageDOMqName.substring(messageDOMqName.indexOf(':') + 1); if (messageDOMname.equals(messageEMFqName.getLocalPart()) && (messageEMFqName.getPrefix().equals(expectedPrefix) || messageEMFqName.getPrefix().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); final String prefix = getPrefixForDefinition(portBindingQName); // 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.getNamespace(prefix))) { port.setEBinding(binding); break; } } } } // ========================================================= // helpers // ========================================================= protected IResolveUtils resolveUtils() { return ResolveUtils.instance(); } private String getPrefixForDefinition(final String qName) { String prefix = prefixUtils().extractPrefixFromQName(qName); if (prefix == null) { prefix = ""; //$NON-NLS-1$ } return prefix; } /** * 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 Map<String, String> prefixesMap, 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 = (prefixesMap.get(prefix) != null && prefixesMap.get(prefix) .equals(resolvedTargetNamespace)); return targetNamespacesAreTheSame && (/* * element.getAttribute(tnsPrefixAttribute * (prefix)) != null || */prefixValueMatchesResolvedTargetNamespace); } private UpdateNSPrefixUtils prefixUtils() { return UpdateNSPrefixUtils.instance(); } }