/* * 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.query.proc.wsdl; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import org.teiid.designer.query.proc.wsdl.IWsdlAttributeInfo; import org.teiid.designer.query.proc.wsdl.IWsdlColumnInfo; import org.teiid.designer.query.proc.wsdl.IWsdlConstants; import org.teiid.designer.query.proc.wsdl.IWsdlRequestInfo; import org.teiid.designer.query.proc.wsdl.IWsdlWrapperInfo; import org.teiid.designer.query.proc.wsdl.model.IMessage; import org.teiid.designer.query.proc.wsdl.model.IPart; import org.teiid.designer.query.sql.ISQLConstants; import org.teiid.designer.runtime.version.spi.ITeiidServerVersion; /** * */ public class WsdlRequestProcedureHelper extends AbstractWsdlHelper implements IWsdlConstants, ISQLConstants { private final IWsdlRequestInfo requestInfo; private final Properties properties; private final static String NSSTRING = "nsString"; //$NON-NLS-1$ private final static String NS = "ns"; //$NON-NLS-1$ private final static String NSPREFIX = "prefix"; //$NON-NLS-1$ /** * @param teiidVersion * @param requestInfo * @param properties */ public WsdlRequestProcedureHelper(ITeiidServerVersion teiidVersion, IWsdlRequestInfo requestInfo, Properties properties) { super(teiidVersion); this.requestInfo = requestInfo; this.properties = properties; } private IWsdlWrapperInfo getWrapperProcedure() { return requestInfo.getWrapperProcedure(); } private String getFullParameterName(String procedureName, String name) { StringBuilder builder = new StringBuilder(); builder.append(getWrapperProcedure().getViewModelName()); builder.append('.').append(procedureName).append('.').append(convertSqlNameSegment(name)); return builder.toString(); } private String getPartElementName(IPart part) { String partElementName = null; partElementName = part.getTypeName(); if (partElementName == null) { partElementName = part.getElementName(); } return partElementName; } private void addAttributesForElement(StringBuffer sb, IWsdlColumnInfo columnInfo) { if( columnInfo.getAttributeInfoArray().length > 0 ) { sb.append(COMMA).append(RETURN).append(TAB).append(TAB).append(TAB).append(TAB).append(XMLATTRIBUTES); sb.append(L_PAREN); int index = 0; for( IWsdlAttributeInfo attrInfo : columnInfo.getAttributeInfoArray() ) { if( index > 0 ) { sb.append(COMMA).append(SPACE); } sb.append(attrInfo.getSymbolName()); if( !attrInfo.getSymbolName().equalsIgnoreCase(attrInfo.getAlias())) { sb.append(SPACE).append(AS).append(SPACE); sb.append(attrInfo.getAlias()); } index++; } sb.append(R_PAREN); } } private String getHeaderString() { /* EXAMPLE XMLELEMENT(NAME "soapenv:Envelope", XMLNAMESPACES('http://schemas.xmlsoap.org/soap/envelope/' AS soapenv, DEFAULT 'http://soapheader.ibm.com'), XMLELEMENT(NAME "soapenv:Header", XMLELEMENT(NAME quote_timestamp, StockServiceServiceView.getLastSellPrice_request.quote_timestamp)), XMLELEMENT(NAME "soapenv:Body", XMLELEMENT(NAME getLastSellPrice, XMLELEMENT(NAME ticker, StockServiceServiceView.getLastSellPrice_request.ticker)))) AS xml_out; */ StringBuilder headerString = new StringBuilder(); if( requestInfo.isMessageServiceMode()) { //Initial Envelope Element. headerString.append(XMLELEMENT).append(L_PAREN).append(NAME).append(SPACE).append(D_QUOTE).append(ENVELOPE_NAME).append(D_QUOTE).append(COMMA); headerString.append(SPACE).append(XMLNAMESPACES).append(L_PAREN).append(S_QUOTE).append(ENVELOPE_NS).append(S_QUOTE).append(SPACE).append(AS).append(SPACE); headerString.append(ENVELOPE_NS_ALIAS); if (requestInfo.getNamespaceMap().size()>0 || (getWrapperProcedure().getNamespaceURI() != null && !getWrapperProcedure().getNamespaceURI().isEmpty())){ String prefix=requestInfo.getReverseNSMap().get(getWrapperProcedure().getNamespaceURI()); if (isDefaultNS(prefix)) { headerString.append(COMMA).append(SPACE).append(DEFAULT).append(SPACE).append(S_QUOTE).append(getWrapperProcedure().getNamespaceURI()); headerString.append(S_QUOTE); }else{ headerString.append(COMMA).append(SPACE).append(S_QUOTE).append(getWrapperProcedure().getNamespaceURI()).append(S_QUOTE).append(SPACE).append(AS).append(SPACE); headerString.append(prefix); } for (Entry<String, String> entry: requestInfo.getNamespaceMap().entrySet()){ //We already added this, so skip it if (entry.getValue().equals(getWrapperProcedure().getNamespaceURI())) break; prefix=requestInfo.getReverseNSMap().get(entry.getValue()); if (isDefaultNS(prefix)) { headerString.append(COMMA).append(SPACE).append(DEFAULT).append(SPACE).append(S_QUOTE).append(entry.getValue()); }else{ headerString.append(COMMA).append(SPACE).append(S_QUOTE).append(entry.getValue()).append(S_QUOTE).append(SPACE).append(AS).append(SPACE); headerString.append(prefix); } } } headerString.append(R_PAREN).append(COMMA).append(SPACE).append(XMLELEMENT).append(L_PAREN).append(NAME).append(SPACE); headerString.append(D_QUOTE).append(HEADER_NAME).append(D_QUOTE); for (IWsdlColumnInfo columnInfo : requestInfo.getHeaderColumnInfoList()){ headerString.append(COMMA).append(SPACE).append(XMLELEMENT).append(L_PAREN).append(NAME).append(SPACE).append(columnInfo.getSymbolName()); headerString.append(COMMA).append(SPACE).append(getFullParameterName(requestInfo.getProcedureName(), columnInfo.getSymbolName())); headerString.append(R_PAREN); } headerString.append(R_PAREN).append(COMMA).append(SPACE); headerString.append(XMLELEMENT).append(L_PAREN).append(NAME).append(SPACE).append(D_QUOTE).append(BODY_NAME).append(D_QUOTE).append(COMMA); } return headerString.toString(); } /** * @param prefix * @return */ private boolean isDefaultNS(String prefix) { return prefix!=null && prefix.trim().length()==0; } private String getPartElementNamespace(IPart part) { String partElementNamespace = null; partElementNamespace = part.getTypeNamespace(); if (partElementNamespace == null) { partElementNamespace = part.getElementNamespace(); } return partElementNamespace; } private Map<String, String> getNamespaceString(IPart[] parts) { Map<String, String> nsMap = new HashMap<String, String>(); String ns = null; String nsPrefix = null; if( getWrapperProcedure().getNamespaceURI() == null ) { return nsMap; } if (parts!=null && parts.length==1){ ns = getPartElementNamespace(parts[0]); } if (ns==null) ns = getWrapperProcedure().getNamespaceURI(); StringBuffer sb = new StringBuffer(); nsPrefix=requestInfo.getReverseNSMap().get(ns); nsMap.put(NS, ns); nsMap.put(NSPREFIX, nsPrefix); if (isDefaultNS(nsPrefix)) { sb.append(DEFAULT).append(SPACE).append(S_QUOTE).append(ns).append(S_QUOTE); }else{ sb.append(XMLNAMESPACES).append(L_PAREN); sb.append(SPACE).append(S_QUOTE).append(getWrapperProcedure().getNamespaceURI()).append(S_QUOTE).append(SPACE).append(AS).append(SPACE); sb.append(nsPrefix); } sb.append(R_PAREN); nsMap.put(NSSTRING, sb.toString()); return nsMap; } /** * Generate the SQL statement for this request info * * @return SQL string */ public String getSQLStatement() { // CREATE VIRTUAL PROCEDURE // BEGIN // SELECT // XMLELEMENT(NAME "update", XMLNAMESPACES(DEFAULT 'http://quickstart.samples/xsd'), // XMLELEMENT(NAME symbol, StockQuoteServiceXML."update".create_update_.symbol, // XMLATTRIBUTES( symbol.empno AS "work_number"), // XMLELEMENT(NAME price, StockQuoteServiceXML."update".create_update_.price) // ) AS xml_out; // END // // CREATE VIRTUAL PROCEDURErequestInfo.operation.getName() // BEGIN // SELECT | ------------- element-namespace------------------| // XMLELEMENT(NAME "<operation-name>", XMLNAMESPACES(DEFAULT 'http://<schema-namespace>'), // | ------------- element-content-expression ----------------------| // XMLELEMENT(NAME <element-name-1>, <element-content-value>. ...), // XMLELEMENT(NAME <element-name-2>, <element-content-value>. ...), // ... // ) AS xml_out; // END // // Request procedure name may have been overridden String requestProcedureName = properties.getProperty(KEY_REQUEST_PROCEDURE_NAME); if( requestProcedureName == null ) { requestProcedureName = requestInfo.getProcedureName(); } String alias = "xml_out"; //$NON-NLS-1$ StringBuffer sb = new StringBuffer(); int i=0; sb.append(SQL_BEGIN); sb.append(TAB).append(SELECT).append(RETURN); String header = getHeaderString(); if( header.length() > 0 ) { sb.append(TAB).append(TAB).append(header).append(RETURN); } sb.append(TAB).append(TAB).append(XMLELEMENT); sb.append(L_PAREN); sb.append(NAME).append(SPACE); String elementName = null; IMessage message = null; IPart[] parts = null; if (!(requestInfo.isMessageServiceMode())) { message = requestInfo.getOperation().getInputMessage(); parts = message.getParts(); if (parts.length>0) { elementName = getPartElementName(parts[0]); } } if (elementName == null){ elementName = requestInfo.getOperation().getName(); } Map<String, String> nsMap = getNamespaceString(parts); if( nsMap == null ) { nsMap = new HashMap<String, String>(); } String nsString = nsMap.get(NSSTRING); String nsPrefix = nsMap.get(NSPREFIX); if (nsPrefix!=null && !isDefaultNS(nsPrefix)){ sb.append("\""+nsPrefix+":"+elementName+"\"").append(COMMA).append(SPACE); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ }else{ sb.append(convertSqlNameSegment(elementName)).append(COMMA).append(SPACE); } //If this is MESSAGE mode, no need to add NS since we did that at the Envelope level if (!(requestInfo.isMessageServiceMode())) { if( nsString != null && !nsString.isEmpty() ) { sb.append(nsString); } } int nColumns = requestInfo.getBodyColumnInfoList().length; if( nColumns > 0 ) { //If this is MESSAGE mode, we don't need this extra comma if (!(requestInfo.isMessageServiceMode())) sb.append(COMMA); } sb.append(SPACE).append(RETURN); // EXAMPLE: XMLELEMENT(NAME FromCurrency, CurrencyConvertorView.request_ConversionRate.FromCurrency) // SELECT XMLELEMENT(NAME GetStateInfo, XMLNAMESPACES(DEFAULT 'http://www.teiid.org/stateService/'), // XMLELEMENT(NAME stateCode, XMLNAMESPACES(NO DEFAULT), stateServiceView.GetStateInfo_request.stateCode)) AS xml_out; for( IWsdlColumnInfo columnInfo : requestInfo.getBodyColumnInfoList()) { String name = columnInfo.getSymbolName(); String convertedName = convertSqlNameSegment(name); Object nsPrefixObject = this.requestInfo.getReverseNSMap().get(columnInfo.getNamespace()); if (nsPrefixObject!=null) { convertedName = D_QUOTE.concat((String) nsPrefixObject).concat(COLON).concat(convertedName).concat(D_QUOTE); } sb.append(TAB).append(TAB).append(TAB).append(XMLELEMENT); sb.append(L_PAREN); sb.append(NAME).append(SPACE).append(convertedName); if (columnInfo.getNamespace()==null){ sb.append(COMMA).append(SPACE).append(XMLNAMESPACES).append(L_PAREN).append(NO_DEFAULT).append(R_PAREN); } if( columnInfo.getAttributeInfoArray().length == 0 ) { sb.append(COMMA).append(SPACE).append(getFullParameterName(requestProcedureName, name)); } addAttributesForElement(sb, columnInfo); sb.append(R_PAREN); if(i < (nColumns-1)) { sb.append(COMMA).append(SPACE).append(RETURN); } i++; } sb.append(R_PAREN); //Need two extra parenthesis for MESSAGE mode to wrap everything in the SOAP Envelope and Body if (requestInfo.isMessageServiceMode()) sb.append(R_PAREN).append(R_PAREN); sb.append(SPACE).append(AS).append(SPACE).append(alias).append(SEMI_COLON); sb.append(SQL_END); return sb.toString(); } }