| /******************************************************************************* |
| * Copyright (c) 2000, 2007 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.wst.wsdl.internal.generator; |
| |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javax.xml.namespace.QName; |
| |
| import org.eclipse.wst.wsdl.Binding; |
| import org.eclipse.wst.wsdl.BindingFault; |
| import org.eclipse.wst.wsdl.BindingInput; |
| import org.eclipse.wst.wsdl.BindingOperation; |
| import org.eclipse.wst.wsdl.BindingOutput; |
| import org.eclipse.wst.wsdl.Definition; |
| import org.eclipse.wst.wsdl.ExtensibilityElement; |
| import org.eclipse.wst.wsdl.ExtensibleElement; |
| import org.eclipse.wst.wsdl.Fault; |
| import org.eclipse.wst.wsdl.Input; |
| import org.eclipse.wst.wsdl.Operation; |
| import org.eclipse.wst.wsdl.Output; |
| import org.eclipse.wst.wsdl.Port; |
| import org.eclipse.wst.wsdl.PortType; |
| import org.eclipse.wst.wsdl.Service; |
| import org.eclipse.wst.wsdl.WSDLFactory; |
| import org.eclipse.wst.wsdl.internal.generator.extension.ContentGeneratorExtensionFactoryRegistry; |
| |
| |
| /* |
| * Class used to generate the Binding and it's content. We look in the registry for |
| * appropriate ContentGenerator classes based on the existing Binding Content's namespace. |
| * Alternatively, users can pass in a namespace through the constructor to specify which |
| * namespace to use when searching the registry. |
| * |
| * The ContentGenerator may also be set manually by calling |
| * setContentGenerator(ContentGenerator). |
| */ |
| public class BindingGenerator extends BaseGenerator |
| { |
| private WSDLFactory factory = WSDLFactory.eINSTANCE; |
| |
| private Binding binding; |
| |
| /* |
| * When the constructor is used, automatically attempt to retrieve a proper |
| * ContentGenerator based on the Binding given. The ContentGenerator may |
| * be replaced by calling setContentGenerator(ContentGenerator). |
| */ |
| public BindingGenerator(Definition definition, Binding binding) |
| { |
| this.definition = definition; |
| this.binding = binding; |
| contentGenerator = getContentGenerator(binding); |
| } |
| |
| /* |
| * When the constructor is used, automatically attempt to retrieve a proper |
| * ContentGenerator based on the namespace given. The ContentGenerator may |
| * be replaced by calling setContentGenerator(ContentGenerator). |
| */ |
| public BindingGenerator(Definition definition, Binding binding, String namespace) |
| { |
| this.definition = definition; |
| this.binding = binding; |
| contentGenerator = getContentGenerator(namespace); |
| } |
| |
| public static ContentGenerator getContentGenerator(Binding binding) |
| { |
| if (binding == null) |
| { |
| return null; |
| } |
| /****************************************************** |
| * Find the regeistered Content Generator for the Binding |
| ******************************************************/ |
| // Get BindingContent namespace |
| String namespace = null; |
| List eeList = binding.getEExtensibilityElements(); |
| if (eeList.size() > 0) |
| { |
| ExtensibilityElement ee = (ExtensibilityElement)eeList.get(0); |
| // TODO: QName qName = ee.getElementType(); go get the namespace instead? |
| namespace = ee.getElement().getNamespaceURI(); |
| return getContentGenerator(namespace); |
| } |
| |
| return null; |
| } |
| |
| public static ContentGenerator getContentGenerator(String namespace) |
| { |
| ContentGenerator contentGen = null; |
| if (namespace != null) |
| { |
| ContentGeneratorExtensionFactoryRegistry factoryRegistry = ContentGeneratorExtensionFactoryRegistry.getInstance(); |
| contentGen = factoryRegistry.getGeneratorClassFromNamespace(namespace); |
| } |
| |
| return contentGen; |
| } |
| |
| private Binding createEmptyBinding(String localName) |
| { |
| Binding newBinding = WSDLFactory.eINSTANCE.createBinding(); |
| newBinding.setQName(new QName(definition.getTargetNamespace(), localName)); |
| newBinding.setEnclosingDefinition(definition); |
| definition.addBinding(newBinding); |
| |
| return newBinding; |
| } |
| |
| /* |
| * TODO: Scenario: |
| * 1)overwrite == false |
| * 2)BindingOperation with 1 input |
| * 3)Corresponding Operation (with same name) with 1 input and 1 output |
| * If we generate with overwrite == false, nothing is done. Thus, an |
| * output is not generated on the BindingOperation. This is because we |
| * search for existing Elements only at the level of BindingOperations. |
| * For example, if there is a corresponding BindingOperation with the same |
| * name as our Operation, leave it alone.... but since there is already |
| * a BindingOperation with the same name, we don't create a new BindingOperation. |
| * |
| * The correct implementation is reduce this granularity to the MessageReference |
| * level. The code is almost there except for how we generate the Binding element |
| * content. Look at BindingGenrator.generateBindingOperation() and |
| * SOAPContentGenerator.java and it's content generation method |
| * for a good place to start. |
| * |
| * For wtp RC1, We shall only look at the Operation level (as we do in the previous |
| * version). |
| */ |
| public Binding generateBinding() |
| { |
| try |
| { |
| // If Binding is null (No Binding was passed into the constructor), we create an empty Binding first. |
| if (binding == null) |
| { |
| binding = createEmptyBinding(getName()); |
| } |
| if (getName() != null && !binding.getQName().getLocalPart().equals(getName())) |
| { |
| binding.setQName(new QName(binding.getQName().getNamespaceURI(), getName())); |
| } |
| if (getRefName() != null) |
| { |
| PortType portType = getPortType(); |
| binding.setEPortType(portType); |
| if (portType == null) |
| { |
| //The model doesn't reconile with it's Element properly when we're setting a null for it's PortType |
| binding.getElement().setAttribute("type", ""); |
| } |
| } |
| |
| List bindingOperations = binding.getEBindingOperations(); |
| PortType portType = binding.getEPortType(); |
| |
| if (!getOverwrite()) |
| { |
| // Don't Overwrite |
| if (portType == null) |
| { |
| return binding; |
| } |
| else |
| { |
| addRequiredNamespaces(binding); |
| List operations = portType.getOperations(); |
| |
| /******************************************************************************* |
| * Determine which Operations require new a new corresponding BindingOperations |
| *******************************************************************************/ |
| List newBindingOpsNeeded = new ArrayList(); |
| for (int index = 0; index < operations.size(); index++) |
| { |
| Operation operation = (Operation)operations.get(index); |
| |
| boolean foundMatch = false; |
| Iterator bindingOperationsIt = bindingOperations.iterator(); |
| while (bindingOperationsIt.hasNext()) |
| { |
| BindingOperation bindingOperation = (BindingOperation)bindingOperationsIt.next(); |
| |
| if (namesEqual(bindingOperation.getName(), operation.getName())) |
| { |
| foundMatch = true; |
| break; |
| } |
| } |
| |
| if (!foundMatch) |
| { |
| newBindingOpsNeeded.add(operation); |
| } |
| } |
| // newBindingOpsNeeded is the List of Operations needing new corresponding |
| // BindingOperation's |
| List newBindingOps = createNewBindingOperations(newBindingOpsNeeded); |
| |
| // Generate the contents of the new BindingOperation's |
| Iterator newBindingOpsIt = newBindingOps.iterator(); |
| while (newBindingOpsIt.hasNext()) |
| { |
| BindingOperation newBindingOp = (BindingOperation)newBindingOpsIt.next(); |
| generateBindingOperation(newBindingOp); |
| generateBindingOperationContent(newBindingOp); |
| } |
| } |
| |
| generateBindingContent(binding); |
| } |
| else |
| { |
| // Overwrite |
| if (portType == null) |
| { |
| // We need to blow away everything under the Binding. No PortType associated with this Binding |
| bindingOperations.clear(); |
| return binding; |
| } |
| else |
| { |
| addRequiredNamespaces(binding); |
| List operations = portType.getOperations(); |
| |
| /****************************************************** |
| * Compare the Operations |
| ******************************************************/ |
| // Remove any BindingOperations which are no longer used |
| for (int index = 0; index < bindingOperations.size(); index++) |
| { |
| BindingOperation bindingOperation = (BindingOperation)bindingOperations.get(index); |
| |
| boolean foundMatch = false; |
| Iterator operationsIt = operations.iterator(); |
| while (operationsIt.hasNext()) |
| { |
| Operation operation = (Operation)operationsIt.next(); |
| |
| if (namesEqual(bindingOperation.getName(), operation.getName())) |
| { |
| foundMatch = true; |
| break; |
| } |
| } |
| |
| if (!foundMatch) |
| { |
| // We need to remove this BindingFault from the bindingFaults List |
| bindingOperations.remove(index); |
| index--; |
| } |
| } |
| |
| // Remove any Operations which already exists in bindingOperations. What we |
| // have left are the Operations which needs newly created BindingOperations |
| List bindingOperationsNeeded = new ArrayList(); |
| for (int index = 0; index < operations.size(); index++) |
| { |
| Operation operation = (Operation)operations.get(index); |
| |
| boolean foundMatch = false; |
| Iterator bindingOperationsIt = bindingOperations.iterator(); |
| while (bindingOperationsIt.hasNext()) |
| { |
| BindingOperation bindingOperation = (BindingOperation)bindingOperationsIt.next(); |
| |
| if (namesEqual(bindingOperation.getName(), operation.getName())) |
| { |
| foundMatch = true; |
| break; |
| } |
| } |
| |
| if (!foundMatch) |
| { |
| // We need to remove this BindingFault from the bindingFaults List |
| bindingOperationsNeeded.add(operation); // Store the actual Operation |
| } |
| } |
| |
| // Create required BindingOperations |
| createNewBindingOperations(bindingOperationsNeeded); |
| |
| /****************************************************** |
| * Process the contents of the Operations |
| ******************************************************/ |
| Iterator bindingOperationsIt = binding.getEBindingOperations().iterator(); |
| while (bindingOperationsIt.hasNext()) |
| { |
| generateBindingOperation((BindingOperation)bindingOperationsIt.next()); |
| } |
| |
| generateBindingContent(binding); |
| |
| return binding; |
| } |
| } |
| } |
| catch (Exception e) |
| { |
| e.printStackTrace(); |
| } |
| return null; |
| } |
| |
| private List createNewBindingOperations(List operations) |
| { |
| List newBindingOps = new ArrayList(); |
| |
| Iterator neededBindingOperationsIt = operations.iterator(); |
| while (neededBindingOperationsIt.hasNext()) |
| { |
| Operation operation = (Operation)neededBindingOperationsIt.next(); |
| BindingOperation newBindingOperation = factory.createBindingOperation(); |
| newBindingOperation.setEOperation(operation); |
| newBindingOperation.setName(operation.getName()); |
| binding.addBindingOperation(newBindingOperation); |
| |
| newBindingOps.add(newBindingOperation); |
| } |
| |
| return newBindingOps; |
| } |
| |
| private void generateBindingOperation(BindingOperation bindingOperation) |
| { |
| BindingInput bindingInput = bindingOperation.getEBindingInput(); |
| BindingOutput bindingOutput = bindingOperation.getEBindingOutput(); |
| List bindingFaults = bindingOperation.getEBindingFaults(); |
| |
| Operation operation = bindingOperation.getEOperation(); |
| Input input = operation.getEInput(); |
| Output output = operation.getEOutput(); |
| List faults = operation.getEFaults(); |
| |
| /****************************************************** |
| * Compare the Operation names |
| ******************************************************/ |
| if (!namesEqual(bindingOperation.getName(), operation.getName())) |
| { |
| bindingOperation.setName(operation.getName()); |
| } |
| |
| /****************************************************** |
| * Compare the Output |
| ******************************************************/ |
| if (output == null) |
| { |
| bindingOperation.setBindingOutput(null); |
| } |
| else |
| { |
| // Create BindingOutput if necessary |
| if (bindingOutput == null) |
| { |
| BindingOutput newBindingOutput = factory.createBindingOutput(); |
| newBindingOutput.setEOutput(output); |
| newBindingOutput.setName(output.getName()); |
| bindingOperation.setBindingOutput(newBindingOutput); |
| } |
| else |
| { |
| // Compare the Output names |
| if (!namesEqual(bindingOutput.getName(), output.getName())) |
| { |
| bindingOutput.setName(output.getName()); |
| } |
| } |
| } |
| generateBindingOutputContent(bindingOperation.getEBindingOutput()); |
| |
| /****************************************************** |
| * Compare the Input |
| ******************************************************/ |
| if (input == null) |
| { |
| bindingOperation.setBindingInput(null); |
| } |
| else |
| { |
| // Create BindingInput if necessary |
| if (bindingInput == null) |
| { |
| BindingInput newBindingInput = factory.createBindingInput(); |
| newBindingInput.setEInput(input); |
| newBindingInput.setName(input.getName()); |
| bindingOperation.setBindingInput(newBindingInput); |
| } |
| else |
| { |
| // Compare the Input names |
| if (!namesEqual(bindingInput.getName(), input.getName())) |
| { |
| bindingInput.setName(input.getName()); |
| } |
| } |
| } |
| generateBindingInputContent(bindingOperation.getEBindingInput()); |
| |
| /****************************************************** |
| * Compare the Faults |
| ******************************************************/ |
| // Remove any BindingFaults which are no longer used |
| for (int index = 0; index < bindingFaults.size(); index++) |
| { |
| BindingFault bindingFault = (BindingFault)bindingFaults.get(index); |
| |
| boolean foundMatch = false; |
| Iterator faultsIt = faults.iterator(); |
| while (faultsIt.hasNext()) |
| { |
| Fault fault = (Fault)faultsIt.next(); |
| if (namesEqual(bindingFault.getName(), fault.getName())) |
| { |
| foundMatch = true; |
| break; |
| } |
| } |
| |
| if (!foundMatch) |
| { |
| // We need to remove this BindingFault from the bindingFaults List |
| bindingFaults.remove(index); |
| index--; |
| } |
| } |
| |
| // Remove any Faults which already exists in bindingFaults. What we |
| // have left are the Faults which needs newly created BindingFaults |
| List bindingFaultsNeeded = new ArrayList(); |
| for (int index = 0; index < faults.size(); index++) |
| { |
| Fault fault = (Fault)faults.get(index); |
| |
| boolean foundMatch = false; |
| Iterator bindingFaultsIt = bindingFaults.iterator(); |
| while (bindingFaultsIt.hasNext()) |
| { |
| BindingFault bindingFault = (BindingFault)bindingFaultsIt.next(); |
| if (namesEqual(bindingFault.getName(), fault.getName())) |
| { |
| foundMatch = true; |
| break; |
| } |
| } |
| |
| if (!foundMatch) |
| { |
| // We need to remove this BindingFault from the bindingFaults List |
| bindingFaultsNeeded.add(fault); |
| } |
| } |
| |
| // bindingFaultsNeeded contains the needed BindingFault's we need to create |
| Iterator neededBindingFaultsIt = bindingFaultsNeeded.iterator(); |
| while (neededBindingFaultsIt.hasNext()) |
| { |
| Fault fault = (Fault)neededBindingFaultsIt.next(); |
| BindingFault newBindingFault = factory.createBindingFault(); |
| newBindingFault.setEFault(fault); |
| newBindingFault.setName(fault.getName()); |
| bindingOperation.addBindingFault(newBindingFault); |
| } |
| |
| // Create the contents for each BindingFault |
| Iterator faultContentIt = bindingOperation.getEBindingFaults().iterator(); |
| while (faultContentIt.hasNext()) |
| { |
| BindingFault bindingFault = (BindingFault)faultContentIt.next(); |
| generateBindingFaultContent(bindingFault); |
| } |
| |
| generateBindingOperationContent(bindingOperation); |
| } |
| |
| private boolean namesEqual(String name1, String name2) |
| { |
| boolean match = false; |
| |
| if (name1 != null ^ name2 != null) |
| { |
| // one is null |
| match = false; |
| } |
| else if (name1 != null && name2 != null) |
| { |
| // neither is null |
| match = name1.equals(name2); |
| } |
| else |
| { |
| // both are null |
| match = true; |
| } |
| |
| return match; |
| } |
| |
| protected void generateBindingContent(Binding binding) |
| { |
| if (contentGenerator != null) |
| { |
| if (getOverwrite() || binding.getEExtensibilityElements().size() == 0) |
| { |
| contentGenerator.generateBindingContent(binding, (PortType)binding.getEPortType()); |
| } |
| } |
| else |
| { |
| removeExtensibilityElements(binding); |
| } |
| } |
| |
| protected void generateBindingOperationContent(BindingOperation bindingOperation) |
| { |
| if (bindingOperation != null && contentGenerator != null) |
| { |
| contentGenerator.generateBindingOperationContent(bindingOperation, bindingOperation.getEOperation()); |
| } |
| else |
| { |
| removeExtensibilityElements(bindingOperation); |
| } |
| } |
| |
| protected void generateBindingInputContent(BindingInput bindingInput) |
| { |
| if (bindingInput != null && contentGenerator != null) |
| { |
| contentGenerator.generateBindingInputContent(bindingInput, bindingInput.getEInput()); |
| } |
| else |
| { |
| removeExtensibilityElements(bindingInput); |
| } |
| } |
| |
| protected void generateBindingOutputContent(BindingOutput bindingOutput) |
| { |
| if (bindingOutput != null && contentGenerator != null) |
| { |
| contentGenerator.generateBindingOutputContent(bindingOutput, bindingOutput.getEOutput()); |
| } |
| else |
| { |
| removeExtensibilityElements(bindingOutput); |
| } |
| } |
| |
| protected void generateBindingFaultContent(BindingFault bindingFault) |
| { |
| if (bindingFault != null && contentGenerator != null) |
| { |
| contentGenerator.generateBindingFaultContent(bindingFault, bindingFault.getEFault()); |
| } |
| else |
| { |
| removeExtensibilityElements(bindingFault); |
| } |
| } |
| |
| private void removeExtensibilityElements(ExtensibleElement ee) |
| { |
| if (ee != null) |
| { |
| ee.getEExtensibilityElements().clear(); |
| } |
| } |
| |
| /* |
| * Generate Port Content for all Ports with a reference to the Binding |
| * which was passed in through the constructor (or a reference to the |
| * newly created Binding). |
| */ |
| public void generatePortContent() |
| { |
| if (binding != null && contentGenerator != null) |
| { |
| List portsToUpdate = new ArrayList(); |
| |
| Iterator servicesIt = binding.getEnclosingDefinition().getEServices().iterator(); |
| while (servicesIt.hasNext()) |
| { |
| Service service = (Service)servicesIt.next(); |
| Iterator portsIt = service.getEPorts().iterator(); |
| while (portsIt.hasNext()) |
| { |
| Port port = (Port)portsIt.next(); |
| if (binding.equals(port.getEBinding())) |
| { |
| // Found a match |
| portsToUpdate.add(port); |
| } |
| } |
| } |
| |
| Iterator portsToUpdateIt = portsToUpdate.iterator(); |
| while (portsToUpdateIt.hasNext()) |
| { |
| contentGenerator.generatePortContent((Port)portsToUpdateIt.next()); |
| } |
| } |
| } |
| |
| /* |
| * methods addRequiredNamespaces() and computeUniquePrefix() are used to add necessary |
| * namespaces |
| * |
| * TODO: |
| * Does this belong here? This is copied from wsdl.ui. Can we sync up in some way? |
| */ |
| protected void addRequiredNamespaces(Binding binding) |
| { |
| if (contentGenerator != null) |
| { |
| String[] namespaceNames = contentGenerator.getRequiredNamespaces(); |
| String[] preferredPrefixes = new String [namespaceNames.length]; |
| for (int index = 0; index < namespaceNames.length; index++) |
| { |
| preferredPrefixes[index] = contentGenerator.getPreferredNamespacePrefix(namespaceNames[index]); |
| } |
| |
| Map map = binding.getEnclosingDefinition().getNamespaces(); |
| |
| for (int i = 0; i < namespaceNames.length; i++) |
| { |
| String namespace = namespaceNames[i]; |
| if (!map.containsValue(namespace)) |
| { |
| String prefix = (i < preferredPrefixes.length) ? preferredPrefixes[i] : "p0"; |
| if (map.containsKey(prefix)) |
| { |
| prefix = computeUniquePrefix("p", map); |
| } |
| binding.getEnclosingDefinition().addNamespace(prefix, namespace); |
| } |
| } |
| } |
| } |
| |
| private String computeUniquePrefix(String base, Map table) |
| { |
| int i = 0; |
| String prefix = base; |
| while (true) |
| { |
| if (!table.containsKey(prefix)) |
| { |
| break; |
| } |
| else |
| { |
| prefix = base + i; |
| i++; |
| } |
| } |
| return prefix; |
| } |
| |
| private PortType getPortType() |
| { |
| if (getRefName().equals("")) |
| { |
| // Means we should set the PortType to Unspecified |
| return null; |
| } |
| |
| if (getRefName() != null) |
| { |
| Iterator portTypeIt = definition.getEPortTypes().iterator(); |
| |
| while (portTypeIt.hasNext()) |
| { |
| PortType pt = (PortType)portTypeIt.next(); |
| List prefixedNames = getPrefixedNames(pt); |
| if (prefixedNames.contains(getRefName())) |
| { |
| return pt; |
| } |
| } |
| } |
| |
| return binding.getEPortType(); |
| } |
| |
| private List getPrefixedNames(PortType portType) |
| { |
| List prefixedNames = new ArrayList(); |
| String currentPortTypeName = portType.getQName().getLocalPart(); |
| String currentNamespace = portType.getQName().getNamespaceURI(); |
| |
| Map namespaceMap = definition.getNamespaces(); |
| Iterator keys = namespaceMap.keySet().iterator(); |
| while (keys.hasNext()) |
| { |
| Object key = keys.next(); |
| Object value = namespaceMap.get(key); |
| |
| if (currentNamespace.equals(value)) |
| { |
| // Found a match. Add to our list |
| prefixedNames.add(key + ":" + currentPortTypeName); |
| } |
| } |
| |
| return prefixedNames; |
| |
| } |
| } |