/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.webservice.util;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xsd.XSDAttributeDeclaration;
import org.eclipse.xsd.XSDConcreteComponent;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDModelGroup;
import org.eclipse.xsd.XSDNamedComponent;
import org.eclipse.xsd.XSDTypeDefinition;
import org.teiid.core.designer.util.CoreStringUtil;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.metamodel.MetamodelDescriptor;
import org.teiid.designer.core.workspace.ModelResource;
import org.teiid.designer.core.workspace.ModelWorkspaceException;
import org.teiid.designer.metamodels.webservice.Input;
import org.teiid.designer.metamodels.webservice.Interface;
import org.teiid.designer.metamodels.webservice.Message;
import org.teiid.designer.metamodels.webservice.Operation;
import org.teiid.designer.metamodels.webservice.Output;
import org.teiid.designer.metamodels.webservice.WebServiceComponent;
import org.teiid.designer.metamodels.webservice.WebServicePackage;
import org.teiid.designer.metamodels.xml.XmlDocument;
import org.teiid.designer.metamodels.xml.XmlValueHolder;
import org.teiid.designer.query.sql.ISQLConstants;
import org.teiid.designer.query.sql.lang.IExpression;
import org.teiid.designer.query.sql.proc.IAssignmentStatement;
import org.teiid.designer.query.sql.symbol.IConstant;
import org.teiid.designer.query.sql.symbol.IFunction;
import org.teiid.designer.transformation.util.TransformationHelper;
import org.teiid.designer.webservice.WebServicePlugin;
import org.teiid.designer.webservice.procedure.DocumentGenerator;
import org.teiid.designer.webservice.procedure.XsdInstanceNode;
/**
* @since 8.0
*/
public class WebServiceUtil {
// ===========================================================================================================================
// Constants
private static final String DEFAULT_INPUT_NAME = "NEWINPUT"; //$NON-NLS-1$
private static final String PLACEHOLDER = WebServicePlugin.Util.getString("WebServiceUtil.chooseElementOrAttribute"); //$NON-NLS-1$
public static final String INPUT_VARIABLE_UNQUALIFIED_PREFIX = "IN_"; //$NON-NLS-1$
public static final String INPUT_VARIABLE_PREFIX = ISQLConstants.VARIABLES + '.' + INPUT_VARIABLE_UNQUALIFIED_PREFIX;
// Special xpathvalue function
public static final String XPATHVALUE = "xpathvalue"; //$NON-NLS-1$
// ===========================================================================================================================
// Static Methods
public static String createXPath(XsdInstanceNode node) {
StringBuffer xpath = new StringBuffer();
for (XsdInstanceNode segNode = node; segNode != null;) {
XsdInstanceNode parent = segNode.getParent();
XSDConcreteComponent comp = segNode.getResolvedXsdComponent();
if (!(comp instanceof XSDModelGroup)) {
StringBuffer seg = new StringBuffer("/"); //$NON-NLS-1$
if (comp instanceof XSDAttributeDeclaration) {
seg.append('@');
}
String name = segNode.getName();
boolean conflict = false;
if (parent != null) {
XsdInstanceNode[] siblings = parent.getChildren();
for (int ndx = siblings.length; --ndx >= 0;) {
XsdInstanceNode sibling = siblings[ndx];
if (sibling != segNode && sibling.getName().equals(name)) {
conflict = true;
break;
}
} // for
}
if (conflict) {
seg.append("*[local-name()=\""); //$NON-NLS-1$
seg.append(name);
seg.append("\" and namespace-uri()=\""); //$NON-NLS-1$
seg.append(segNode.getTargetNamespace());
seg.append("\"]"); //$NON-NLS-1$
} else {
seg.append("*:"); //$NON-NLS-1$
seg.append(name);
}
xpath.insert(0, seg);
}
segNode = parent;
} // for
return xpath.toString();
}
/**
* Generate a string that is a request XML document for the specified web service operation.
*
* @param operation
* the operation whose request document will be generated
* @param paramValues
* the ordered set of values to be inserted into the document or <code>null</code> if no values are inserted
* @return the request document
* @since 5.5.3
*/
public static String generateRequestDocument(Operation operation,
List<String> paramValues) {
XsdInstanceNode node = new XsdInstanceNode(operation.getInput().getContentElement());
return DocumentGenerator.SHARED.generate(node, paramValues);
}
/**
* Get the messages content element type definition.
*
* @param message
* the input or ouput message
* @return the ContentElement TypeDefn or <code>null</code>
*/
public static XSDTypeDefinition getContentElementTypeDefn(Message message) {
XSDTypeDefinition typeDefn = null;
if (message != null) {
XSDElementDeclaration elem = message.getContentElement();
if (elem != null) {
typeDefn = elem.getTypeDefinition();
}
}
return typeDefn;
}
/**
* This method will get the operation input, then get the input elements from it (if available) to use in the transformation
* sql.
*
* @param operation
* the webservice operation
* @param includeFixedValueFeatures
* <code>true</code> if input elements with fixed values should be returned
* @return the list of input elements (never <code>null</code>)
*/
public static List<EObject> getInputElements(Operation operation,
boolean includeFixedValueFeatures) {
List<EObject> elemList = new ArrayList<EObject>();
if (operation != null) {
addInputElements(operation.getInput(), elemList);
}
return elemList;
}
private static void addInputElements(Input input,
List variables) {
if (input != null) {
XSDElementDeclaration element = input.getContentElement();
if (element != null) {
addInputElements(new XsdInstanceNode(element), variables);
}
}
}
private static void addInputElements(XsdInstanceNode node,
List variables) {
if (node.isSelectable()) {
variables.add(node.getResolvedXsdComponent());
}
XsdInstanceNode[] children = node.getChildren();
for (int ndx = 0; ndx<children.length; ndx++) {
addInputElements(children[ndx], variables);
} // for
}
public static String getSql(Operation operation,
List<String> paramValues) {
StringBuffer sql = new StringBuffer("EXEC "); //$NON-NLS-1$
String rawFullName = ModelerCore.getModelEditor().getModelRelativePathIncludingModel(operation).toString();
rawFullName = rawFullName.replace('/', '.');
// Wrap segments in double-quotes
StringBuffer sb = new StringBuffer(rawFullName.length());
sb.append('"');
for( char nextChar : rawFullName.toCharArray() ) {
if( nextChar != '.') {
sb.append(nextChar);
} else {
sb.append('"').append('.').append('"');
}
}
sb.append('"');
String dquotedName = sb.toString();
sql.append(dquotedName);
if (!paramValues.isEmpty()) {
sql.append("('"); //$NON-NLS-1$
sql.append(generateRequestDocument(operation, paramValues));
sql.append("\n')"); //$NON-NLS-1$
}else{
//No parms
sql.append("()"); //$NON-NLS-1$
}
return sql.toString();
}
public static MetamodelDescriptor getWebServiceModelDescriptor() {
return ModelerCore.getMetamodelRegistry().getMetamodelDescriptor(WebServicePackage.eNS_URI);
}
public static String getXpath(IAssignmentStatement statement) {
IFunction function = getXpathFunction(statement);
if (function != null && function.getArgs().length > 1) {
return (String)((IConstant)function.getArg(1)).getValue();
}
return CoreStringUtil.Constants.EMPTY_STRING;
}
public static IFunction getXpathFunction(IAssignmentStatement statement) {
if (statement.getExpression() != null) {
IExpression expr = statement.getExpression();
if (expr != null && expr instanceof IFunction) {
IFunction function = (IFunction)expr;
if (XPATHVALUE.equalsIgnoreCase(function.getName())) {
return function;
}
}
}
return null;
}
public static boolean isWebServiceComponent(final Object object) {
boolean result = false;
if (object instanceof WebServiceComponent) {
result = true;
}
return result;
}
public static boolean isWebServiceInterface(final Object object) {
boolean result = false;
if (object instanceof Interface) {
result = true;
}
return result;
}
public static boolean isWebServiceModelResource(final ModelResource modelResource) {
boolean result = false;
if (modelResource != null) {
MetamodelDescriptor descriptor = null;
try {
descriptor = modelResource.getPrimaryMetamodelDescriptor();
} catch (ModelWorkspaceException e) {
e.printStackTrace();
}
if (descriptor != null && descriptor.getNamespaceURI().equals(WebServicePackage.eNS_URI)) {
result = true;
}
}
return result;
}
// ===========================================================================================================================
// Constructors
/**
* @since 4.2
*/
public WebServiceUtil() {
super();
}
// ===========================================================================================================================
// Methods
public String generateTransformationSql(final Output output,
final XmlDocument xmlDoc) {
if (output == null || xmlDoc == null) {
return null;
}
final List variables = new ArrayList();
// Find the corresponding Input ...
final Operation op = output.getOperation();
String inputName = DEFAULT_INPUT_NAME;
if (op != null) {
final Input input = op.getInput();
addInputVariables(input, variables);
if (input.getName() != null && input.getName().trim().length() != 0) {
inputName = getFullName(input);
}
}
final StringBuffer sb = new StringBuffer();
// Create the basic header ...
sb.append("CREATE VIRTUAL PROCEDURE BEGIN "); //$NON-NLS-1$
// Add the variables ...
final Iterator iter = variables.iterator();
final List criteriaStrings = new ArrayList();
int i = 0;
while (iter.hasNext()) {
final InputVariable variable = (InputVariable)iter.next();
++i;
String name = variable.getName();
// Add the declaration ...
if (name == null || name.trim().length() == 0) {
name = "VARIABLE"; //$NON-NLS-1$
variable.setName(name);
}
sb.append("DECLARE string "); //$NON-NLS-1$
sb.append(WebServiceUtil.INPUT_VARIABLE_PREFIX);
sb.append(variable.getName());
sb.append("; "); //$NON-NLS-1$
// Add the assignment ...
sb.append(WebServiceUtil.INPUT_VARIABLE_PREFIX);
sb.append(variable.getName());
sb.append(" = xpathValue("); //$NON-NLS-1$
sb.append(inputName);
sb.append(",'"); //$NON-NLS-1$
sb.append(variable.getXpath());
sb.append("'); "); //$NON-NLS-1$
// Add criteria for each value holder ...
final List xmlValueHolders = variable.getXmlDocumentEntityForCriteria();
if (!xmlValueHolders.isEmpty()) {
final Iterator vhIter = xmlValueHolders.iterator();
while (vhIter.hasNext()) {
final XmlValueHolder valueHolder = (XmlValueHolder)vhIter.next();
if (valueHolder == null) {
continue;
}
final String valueHolderPath = getFullName(valueHolder);
if (valueHolderPath == null || valueHolderPath.trim().length() == 0) {
continue;
}
final StringBuffer criteria = new StringBuffer();
criteria.append(valueHolderPath);
criteria.append(" = "); //$NON-NLS-1$
criteria.append(WebServiceUtil.INPUT_VARIABLE_PREFIX);
criteria.append(variable.getName());
criteriaStrings.add(criteria.toString());
}
} else {
final String valueHolderPath = getFullName(xmlDoc);
final StringBuffer criteria = new StringBuffer();
criteria.append(valueHolderPath);
criteria.append(PLACEHOLDER);
criteria.append(" = "); //$NON-NLS-1$
criteria.append(WebServiceUtil.INPUT_VARIABLE_PREFIX);
criteria.append(variable.getName());
criteriaStrings.add(criteria.toString());
}
}
// Add the variable assignments ...
// Create the SELECT FROM <XMLDOC> ...
final String docPath = getFullName(xmlDoc);
sb.append("SELECT * FROM "); //$NON-NLS-1$
sb.append(docPath);
if (criteriaStrings.size() != 0) {
sb.append(" WHERE "); //$NON-NLS-1$
final Iterator criteriaIter = criteriaStrings.iterator();
boolean moreThanOne = false;
while (criteriaIter.hasNext()) {
final String criteriaString = (String)criteriaIter.next();
if (moreThanOne) {
sb.append(" AND "); //$NON-NLS-1$
}
sb.append(criteriaString);
moreThanOne = true;
}
sb.append(" "); //$NON-NLS-1$
}
sb.append("; END"); //$NON-NLS-1$
return sb.toString();
}
public String getFullName(final EObject object) {
return TransformationHelper.getSqlEObjectFullName(object);
}
public void addInputVariables(Input input,
List variables) {
if (input != null) {
XSDElementDeclaration element = input.getContentElement();
if (element != null) {
addInputVariables(new XsdInstanceNode(element), variables);
}
}
}
public void addInputVariables(XsdInstanceNode node,
List variables) {
if (node.isSelectable()) {
variables.add(new InputVariable((XSDNamedComponent)node.getResolvedXsdComponent(), node.getName(), createXPath(node)));
}
XsdInstanceNode[] children = node.getChildren();
for (int ndx = children.length; --ndx >= 0;) {
addInputVariables(children[ndx], variables);
} // for
}
}