blob: cd587c1796594b3f9fccd4e63cbba69e575f8416 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2007 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.wsdl.ui.internal.commands;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.wst.sse.core.internal.format.IStructuredFormatProcessor;
import org.eclipse.wst.wsdl.Definition;
import org.eclipse.wst.wsdl.Fault;
import org.eclipse.wst.wsdl.Input;
import org.eclipse.wst.wsdl.Message;
import org.eclipse.wst.wsdl.MessageReference;
import org.eclipse.wst.wsdl.Operation;
import org.eclipse.wst.wsdl.Output;
import org.eclipse.wst.wsdl.Part;
import org.eclipse.wst.wsdl.PortType;
import org.eclipse.wst.wsdl.WSDLElement;
import org.eclipse.wst.wsdl.ui.internal.util.ComponentReferenceUtil;
import org.eclipse.wst.wsdl.ui.internal.util.NameUtil;
import org.eclipse.wst.wsdl.ui.internal.util.XSDComponentHelper;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.eclipse.wst.xml.core.internal.provisional.format.FormatProcessorXML;
import org.eclipse.xsd.XSDComplexTypeDefinition;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDModelGroup;
import org.eclipse.xsd.XSDNamedComponent;
import org.eclipse.xsd.XSDParticle;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.XSDSimpleTypeDefinition;
import org.eclipse.xsd.XSDTypeDefinition;
import org.w3c.dom.Element;
public abstract class AddBaseParameterCommand {
public static int PART_ELEMENT_SEQ_ELEMENT = 0;
public static int PART_ELEMENT = 1;
public static int PART_COMPLEXTYPE_SEQ_ELEMENT = 2;
public static int PART_COMPLEXTYPE = 3;
public static int PART_SIMPLETYPE = 4;
protected int style = 0;
protected Operation operation;
protected XSDElementDeclaration newXSDElement;
protected Part newPart;
protected String newAnonymousXSDElementName;
protected String newXSDElementName;
protected String newWSDLMessageName;
protected String newWSDLPartName;
public abstract void run();
public abstract MessageReference getMessageReference();
public AddBaseParameterCommand(Operation operation, int style) {
this.operation = operation;
this.style = style;
}
public void setStyle(int style) {
this.style = style;
}
public XSDElementDeclaration getXSDElementDeclaration() {
return newXSDElement;
}
protected boolean isPartElementReference() {
if (style == PART_ELEMENT || style == PART_ELEMENT_SEQ_ELEMENT) {
return true;
}
return false;
}
protected XSDElementDeclaration createPartElementSeqElementPattern(Part part, XSDElementDeclaration partElement) {
XSDElementDeclaration returnedXSDElement = null;
XSDElementDeclaration originalElement = null;
XSDElementDeclaration anonXSDElement = null;
// Create the XSDElement (anonymous) referenced by the Part if necessary
if (partElement == null || partElement.getAnonymousTypeDefinition() == null || partElement.getSchema() == null) {
anonXSDElement = XSDComponentHelper.createAnonymousXSDElementDefinition(getAnonymousXSDElementBaseName(), part);
// part.setElementDeclaration(anonXSDElement);
String prefixedName = getPrefixedComponentName(part.getEnclosingDefinition(), anonXSDElement);
ComponentReferenceUtil.setComponentReference(part, false, prefixedName);
part.setTypeDefinition(null);
if (partElement != null && partElement.getSchema() != null) {
originalElement = partElement;
// Remove the 'original' XSDElement as a Global Element
partElement.getSchema().getContents().remove(partElement);
}
}
else {
anonXSDElement = partElement;
}
// Add the 'original' XSDElement if it's type wasn't anonymous
if (originalElement != null) {
XSDComponentHelper.addXSDElementToModelGroup(anonXSDElement, originalElement);
}
// Create a new XSDElement
XSDModelGroup modelGroup = XSDComponentHelper.getXSDModelGroup(anonXSDElement, part.getEnclosingDefinition());
returnedXSDElement = XSDComponentHelper.createXSDElementDeclarationCommand(null, getNewXSDElementBaseName(), modelGroup);
// Add the newly created XSDElement to the ModelGroup
XSDComponentHelper.addXSDElementToModelGroup(anonXSDElement, returnedXSDElement);
formatChild(anonXSDElement.getElement());
return returnedXSDElement;
}
protected XSDElementDeclaration createPartElementReferenceComponents(Part part) {
XSDElementDeclaration returnedXSDElement = null;
XSDElementDeclaration partElement = part.getElementDeclaration();
if (style == PART_ELEMENT_SEQ_ELEMENT) {
returnedXSDElement = createPartElementSeqElementPattern(part, partElement);
}
else if (style == PART_ELEMENT) {
if (partElement == null) {
returnedXSDElement = XSDComponentHelper.createXSDElementDeclarationCommand(part.getEnclosingDefinition(), getNewXSDElementBaseName(), part);
if (returnedXSDElement != null && !returnedXSDElement.equals(part.getElementDeclaration())) {
// part.setElementDeclaration(returnedXSDElement);
String prefixedName = getPrefixedComponentName(part.getEnclosingDefinition(), returnedXSDElement);
ComponentReferenceUtil.setComponentReference(part, false, prefixedName);
}
}
else {
returnedXSDElement = createPartElementSeqElementPattern(part, partElement);
}
}
return returnedXSDElement;
}
protected XSDElementDeclaration createPartComplexTypeReference(Part part) {
XSDElementDeclaration returnedXSDElement = null;
if (style == PART_COMPLEXTYPE_SEQ_ELEMENT) {
XSDTypeDefinition originalType = null;
XSDComplexTypeDefinition topLevelType = null;
// Create the ComplexType referenced by the Part if necessary
if (part.getTypeDefinition() == null || part.getTypeDefinition() instanceof XSDSimpleTypeDefinition) {
XSDSchema schema = XSDComponentHelper.getXSDSchema(part.getEnclosingDefinition());
String topLevelName = NameUtil.getXSDComplexTypeName(part.getName(), schema);
topLevelType = XSDComponentHelper.createXSDComplexTypeDefiniion(topLevelName, part);
if (part.getTypeDefinition() instanceof XSDSimpleTypeDefinition) {
originalType = part.getTypeDefinition();
}
}
else if (part.getTypeDefinition() instanceof XSDComplexTypeDefinition){
topLevelType = (XSDComplexTypeDefinition) part.getTypeDefinition();
}
// Create a new XSDElement
XSDModelGroup modelGroup = XSDComponentHelper.getXSDModelGroup(topLevelType);
returnedXSDElement = XSDComponentHelper.createXSDElementDeclarationCommand(null, getNewXSDElementBaseName(), modelGroup);
// Add the 'original' XSDElement if it's type wasn't anonymous
if (originalType != null) {
// Create another new XSDElement to 'contain' the originally referenced XSDSimpleType
XSDElementDeclaration origXSDElement = XSDComponentHelper.createXSDElementDeclarationCommand(null, getNewXSDElementBaseName(), modelGroup);
origXSDElement.setTypeDefinition(originalType);
}
// Change Part reference
// part.setTypeDefinition(topLevelType);
String prefixedName = getPrefixedComponentName(part.getEnclosingDefinition(), topLevelType);
ComponentReferenceUtil.setComponentReference(part, true, prefixedName);
formatChild(topLevelType.getElement());
}
else if (style == PART_COMPLEXTYPE) {
XSDComplexTypeDefinition complexType = null;
if (part.getTypeDefinition() == null) {
// Create a new ComplexType
XSDSchema schema = XSDComponentHelper.getXSDSchema(part.getEnclosingDefinition());
String complexName = NameUtil.getXSDComplexTypeName(part.getName(), schema);
complexType = XSDComponentHelper.createXSDComplexTypeDefiniion(complexName, part);
// Create an XSDElement for the ComplexType
XSDModelGroup xsdModelGroup = XSDComponentHelper.getXSDModelGroup(complexType);
returnedXSDElement = XSDComponentHelper.createXSDElementDeclarationCommand(null, getNewXSDElementBaseName(), xsdModelGroup);
}
else {
// TODO: What should we do here..... We can default to the PART_ELEMENT_SEQ_ELEMENT style
// since it handles 'multiple' XSDElements.... OR ..... we can 'overwrite and set a new
// XSDElement
}
if (complexType != null && !complexType.equals(part.getTypeDefinition())) {
// part.setTypeDefinition(complexType);
String prefixedName = getPrefixedComponentName(part.getEnclosingDefinition(), complexType);
ComponentReferenceUtil.setComponentReference(part, true, prefixedName);
formatChild(complexType.getElement());
}
}
return returnedXSDElement;
}
/*
* Create if necessary a Message and Part for the given MessageReference
* and return it's Part
*/
protected Part createWSDLComponents(MessageReference messageRef) {
Message message = messageRef.getEMessage();
Part part = null;
if (message == null || message.eContainer() == null) {
// Create Message
AddMessageCommand command = new AddMessageCommand(messageRef.getEnclosingDefinition(), getWSDLMessageName());
command.run();
message = (Message) command.getWSDLElement();
messageRef.setEMessage(message);
}
if (message.getEParts().size() == 0) {
// Create Part
String partName = getWSDLPartName();
if (style == PART_ELEMENT_SEQ_ELEMENT) {
partName = getDocLitWrappedPartName();
}
AddPartCommand command = new AddPartCommand(message, partName);
command.run();
part = (Part) command.getWSDLElement();
}
else {
// there is an existing Part
// part = (Part) message.getEParts().get(0);
}
formatChild(message.getElement());
return part;
}
protected String getDocLitWrappedPartName() {
return "parameters"; //$NON-NLS-1$
}
protected XSDElementDeclaration createXSDObjects(Part part) {
XSDElementDeclaration returnedXSDElement = null;
if (isPartElementReference()) {
// Is a Part --> Element reference
if (part == null && getMessageReference() != null && getMessageReference().getEMessage() != null) {
part = (Part) getMessageReference().getEMessage().getEParts().get(0);
}
returnedXSDElement = createPartElementReferenceComponents(part);
}
else {
// Is a Part --> Complex Type reference
// returnedXSDElement = createPartComplexTypeReference(part);
// If it's a Part --> Type reference, adding a new parameter always means adding a new Part
// with a string reference. Because of this case, we should really rename this method instead
// of createXSDObjects() since we may end up creating a Part.
if (part == null && getMessageReference() != null && getMessageReference().getEMessage() != null) {
List partNames = new ArrayList();
Message message = getMessageReference().getEMessage();
Iterator it = message.getEParts().iterator();
while (it.hasNext()) {
Part item = (Part) it.next();
partNames.add(item.getName());
}
String partName = NameUtil.getUniqueNameHelper(getWSDLPartName(), partNames);
AddPartCommand command = new AddPartCommand(message, partName);
command.run();
newPart = (Part) command.getWSDLElement();
}
}
return returnedXSDElement;
}
protected String getPrefixedComponentName(Definition definition, XSDNamedComponent component) {
String name = component.getName();
String tns = component.getTargetNamespace();
List prefixes = getPrefixes(definition, tns);
if (prefixes.size() > 0) {
name = prefixes.get(0) + ":" + name; //$NON-NLS-1$
}
return name;
}
private List getPrefixes(Definition definition, String namespace) {
List list = new ArrayList();
Map map = definition.getNamespaces();
for (Iterator i = map.keySet().iterator(); i.hasNext();) {
String prefix = (String) i.next();
String theNamespace = (String) map.get(prefix);
if (theNamespace != null && theNamespace.equals(namespace)) {
list.add(prefix);
}
}
return list;
}
public static int getParameterPattern(WSDLElement element) {
int pattern = -1;
if (element instanceof Operation) {
pattern = getPattern((Operation) element);
PortType pt = (PortType) ((Operation) element).getContainer();
if (pattern == -1) {
// let's try to search other Operations in the same PortType
Iterator opIt = pt.getEOperations().iterator();
while (pattern == -1 && opIt.hasNext()) {
Operation item = (Operation) opIt.next();
if (!item.equals(element)) {
pattern = getPattern(item);
}
}
}
if (pattern == -1) {
// let's try to search other Operations in OTHER PortTypes
Iterator ptIt = pt.getEnclosingDefinition().getEPortTypes().iterator();
while (pattern == -1 && ptIt.hasNext()) {
PortType item = (PortType) ptIt.next();
if (!item.equals(pt)) {
pattern = getPattern(item);
}
}
}
}
else if (element instanceof PortType) {
PortType pt = (PortType) element;
pattern = getPattern(pt);
if (pattern == -1) {
// let's try to search other Operations in OTHER PortTypes
Iterator ptIt = pt.getEnclosingDefinition().getEPortTypes().iterator();
while (pattern == -1 && ptIt.hasNext()) {
PortType item = (PortType) ptIt.next();
if (!item.equals(pt)) {
pattern = getPattern(item);
}
}
}
}
if (pattern == -1) {
pattern = AddBaseParameterCommand.PART_ELEMENT_SEQ_ELEMENT;
}
return pattern;
}
public static int getParameterPattern(WSDLElement element, boolean useInput) {
int pattern = -1;
if (element instanceof Operation) {
Operation op = (Operation) element;
if (useInput && op.getEInput() != null) {
pattern = getPattern(op.getEInput().getEMessage());
}
if (!useInput && op.getEOutput() != null){
pattern = getPattern(op.getEOutput().getEMessage());
}
PortType pt = (PortType) op.getContainer();
if (pattern == -1) {
// let's try to search other Operations in the same PortType
Iterator opIt = pt.getEOperations().iterator();
while (pattern == -1 && opIt.hasNext()) {
Operation item = (Operation) opIt.next();
if (!item.equals(element)) {
if (useInput && item.getEInput() != null) {
pattern = getPattern(item.getEInput().getEMessage());
}
if (!useInput && item.getEOutput() != null){
pattern = getPattern(item.getEOutput().getEMessage());
}
}
}
}
if (pattern == -1) {
// let's try to search other Operations in OTHER PortTypes
Iterator ptIt = pt.getEnclosingDefinition().getEPortTypes().iterator();
while (pattern == -1 && ptIt.hasNext()) {
PortType item = (PortType) ptIt.next();
if (!item.equals(pt)) {
pattern = getPattern(item, useInput);
}
}
}
}
else if (element instanceof PortType) {
PortType pt = (PortType) element;
pattern = getPattern(pt, useInput);
if (pattern == -1) {
// let's try to search other Operations in OTHER PortTypes
Iterator ptIt = pt.getEnclosingDefinition().getEPortTypes().iterator();
while (pattern == -1 && ptIt.hasNext()) {
PortType item = (PortType) ptIt.next();
if (!item.equals(pt)) {
pattern = getPattern(item, useInput);
}
}
}
}
return pattern;
}
private static int getPattern(PortType portType) {
int pattern = -1;
Iterator opIt = portType.getEOperations().iterator();
while (pattern == -1 && opIt.hasNext()) {
Operation op = (Operation) opIt.next();
pattern = getPattern(op);
}
return pattern;
}
private static int getPattern(PortType portType, boolean useInput) {
int pattern = -1;
Iterator opIt = portType.getEOperations().iterator();
while (pattern == -1 && opIt.hasNext()) {
Operation op = (Operation) opIt.next();
if (useInput && op.getEInput() != null) {
pattern = getPattern(op.getEInput().getEMessage());
}
if (!useInput && op.getEOutput() != null) {
pattern = getPattern(op.getEOutput().getEMessage());
}
}
return pattern;
}
private static int getPattern(Operation operation) {
int pattern = -1;
Input input = operation.getEInput();
Output output = operation.getEOutput();
List faults = operation.getEFaults();
if (input != null) {
pattern = getPattern(input.getEMessage());
}
if (pattern == -1 && output != null) {
pattern = getPattern(output.getEMessage());
}
if (pattern == -1 && faults.size() > 0) {
Iterator faultIt = faults.iterator();
while (pattern == -1 && faultIt.hasNext()) {
Fault fault = (Fault) faultIt.next();
pattern = getPattern(fault.getEMessage());
}
}
return pattern;
}
private static int getPattern(Message message) {
int pattern = -1;
if (message != null) {
Iterator parts = message.getEParts().iterator();
while (parts.hasNext()) {
Part part = (Part) parts.next();
if (part.getElementDeclaration() != null) {
pattern = AddBaseParameterCommand.PART_ELEMENT;
XSDElementDeclaration xsdElement = part.getElementDeclaration();
if (isSequencePattern(xsdElement.getTypeDefinition())) {
pattern = AddBaseParameterCommand.PART_ELEMENT_SEQ_ELEMENT;
}
break;
}
else if (part.getTypeDefinition() != null) {
pattern = AddBaseParameterCommand.PART_SIMPLETYPE;
if (part.getTypeDefinition() instanceof XSDComplexTypeDefinition) {
pattern = AddBaseParameterCommand.PART_COMPLEXTYPE;
XSDComplexTypeDefinition xsdType = (XSDComplexTypeDefinition) part.getTypeDefinition();
if (isSequencePattern(xsdType)) {
pattern = AddBaseParameterCommand.PART_COMPLEXTYPE_SEQ_ELEMENT;
}
}
break;
}
}
}
return pattern;
}
private static boolean isSequencePattern(XSDTypeDefinition type) {
boolean isSequencePattern = false;
if (type instanceof XSDComplexTypeDefinition) {
XSDComplexTypeDefinition complexType = (XSDComplexTypeDefinition) type;
if (complexType.getContent() instanceof XSDParticle) {
XSDParticle particle = (XSDParticle) complexType.getContent();
if (particle.getContent() instanceof XSDModelGroup) {
isSequencePattern = true;
}
}
}
return isSequencePattern;
}
protected void formatChild(Element child)
{
if (child instanceof IDOMNode)
{
IDOMModel model = ((IDOMNode)child).getModel();
try
{
// tell the model that we are about to make a big model change
model.aboutToChangeModel();
IStructuredFormatProcessor formatProcessor = new FormatProcessorXML();
formatProcessor.formatNode(child);
}
finally
{
// tell the model that we are done with the big model change
model.changedModel();
}
}
}
public Part getNewlyAddedComponentPart() {
return newPart;
}
protected abstract String getAnonymousXSDElementBaseName();
protected abstract String getNewXSDElementBaseName();
protected abstract String getWSDLMessageName();
protected abstract String getWSDLPartName();
}