/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.muse.tools.generator.synthesizer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.xml.namespace.QName;
import org.apache.muse.tools.generator.util.Capability;
import org.apache.muse.tools.generator.util.ConfigurationData;
import org.apache.muse.tools.generator.util.ConfigurationDataDescriptor;
import org.apache.muse.tools.inspector.JavaMethod;
import org.apache.muse.tools.inspector.JavaProperty;
import org.apache.muse.tools.inspector.ResourceInspector;
import org.apache.muse.util.ReflectUtils;
import org.apache.muse.util.xml.XmlUtils;
import org.apache.muse.ws.addressing.soap.SoapFault;
import org.apache.muse.ws.metadata.WsxConstants;
import org.apache.muse.ws.notification.WsnConstants;
import org.apache.muse.ws.notification.remote.NotificationConsumerClient;
import org.apache.muse.ws.notification.remote.NotificationProducerClient;
import org.apache.muse.ws.resource.lifetime.WsrlConstants;
import org.apache.muse.ws.resource.properties.WsrpConstants;
import org.apache.muse.ws.resource.remote.WsResourceClient;
import org.apache.muse.ws.wsdl.WsdlUtils;
import org.w3c.dom.Document;
public class ProxyInterfaceSynthesizer extends AbstractSynthesizer {
private static final String TARGET_NS_ATTR = "targetNamespace";
protected static final String PARAM_NAME = "param";
static ConfigurationDataDescriptor[] REQUIRED_PARAMETERS =
new ConfigurationDataDescriptor[] {
ConfigurationData.CAPABILITIES_MAP_LIST_CONFIGURATION,
ConfigurationData.GENERATE_CUSTOM_HEADERS_CONFIGURATION,
ConfigurationData.WSDL_DOCUMENT_LIST_CONFIGURATION
};
protected static Set _ignoredCapabilitySet;
static {
_ignoredCapabilitySet = new HashSet();
_ignoredCapabilitySet.add(WsxConstants.GET_METADATA_CAPABILITY);
}
protected static Map _clientCapabilitiesMap;
static {
_clientCapabilitiesMap = new HashMap();
Set baseClientset = new HashSet();
baseClientset.add(WsrpConstants.GET_CAPABILITY);
baseClientset.add(WsrpConstants.QUERY_CAPABILITY);
baseClientset.add(WsrpConstants.SET_CAPABILITY);
baseClientset.add(WsrlConstants.IMMEDIATE_TERMINATION_URI);
baseClientset.add(WsrlConstants.SCHEDULED_TERMINATION_URI);
_clientCapabilitiesMap.put(WsResourceClient.class, baseClientset);
Set set = new HashSet();
set.add(WsnConstants.PRODUCER_URI);
set.addAll(baseClientset);
_clientCapabilitiesMap.put(NotificationProducerClient.class, set);
set = new HashSet();
set.add(WsnConstants.CONSUMER_URI);
set.addAll(baseClientset);
_clientCapabilitiesMap.put(NotificationConsumerClient.class, set);
}
protected StringBuffer _headerCode;
protected StringBuffer _operationsCode;
protected StringBuffer _propertiesCode;
String _className;
protected Set _importSet;
private boolean _hasProperties;
protected boolean _generateCustomHeaders;
private Map[] _capabilityMaps;
private Document[] _wsdlDocuments;
protected Class _baseClientClass;
private Map[] _filesMaps;
private int _index = 0;
public ConfigurationData synthesize(ConfigurationData data)
throws Exception {
ConfigurationData.checkConfiguration(this, data);
loadParameters(data);
for (int i = 0; i < _capabilityMaps.length; i++) {
if (_filesMaps[i] == null) {
_filesMaps[i] = new HashMap();
}
generateCode(_wsdlDocuments[i], _capabilityMaps[i], _filesMaps[i]);
}
return data;
}
protected void loadParameters(ConfigurationData data) {
_generateCustomHeaders = ((Boolean)data.getParameter(ConfigurationData.GENERATE_CUSTOM_HEADERS)).booleanValue();
_capabilityMaps = (Map[])data.getParameter(ConfigurationData.CAPABILITIES_MAP_LIST);
_wsdlDocuments = (Document[])data.getParameter(ConfigurationData.WSDL_DOCUMENT_LIST);
_filesMaps = (Map[])data.getParameter(ConfigurationData.FILES_MAP_LIST);
if(_filesMaps == null) {
_filesMaps = new HashMap[_capabilityMaps.length];
data.addParameter(ConfigurationData.FILES_MAP_LIST, _filesMaps);
}
}
protected void generateCode(Document wsdl, Map capabilityMap, Map files) {
String className = generateClassName(wsdl);
_baseClientClass = getBaseClientClass(capabilityMap);
initializeCode(className);
ClassInfo classInfo = new ClassInfo();
for (Iterator i = capabilityMap.values().iterator(); i.hasNext();) {
Capability capability = (Capability)i.next();
if(needsGeneratedCode(_baseClientClass, capability)) {
classInfo.setCapability(capability);
updateCode(classInfo);
}
}
files.put(createFileName(className), generateCombinedCode(classInfo));
}
private boolean needsGeneratedCode(Class clientClass, Capability capability) {
boolean needsGeneratedCode = true;
String uri = capability.getURI();
Class clazz = null;
if(NotificationProducerClient.class.isAssignableFrom(clientClass)) {
clazz = NotificationProducerClient.class;
} else if(NotificationConsumerClient.class.isAssignableFrom(clientClass)) {
clazz = NotificationConsumerClient.class;
} else { // if(WsResourceClient.class.isAssignableFrom(clientClass)) {
clazz = WsResourceClient.class;
}
if(clazz != null) {
Set set = (Set)_clientCapabilitiesMap.get(clazz);
if(set.contains(uri) || _ignoredCapabilitySet.contains(uri)) {
needsGeneratedCode = false;
}
}
return needsGeneratedCode;
}
private Class getBaseClientClass(Map capabilityMap) {
if(capabilityMap.containsKey(WsnConstants.PRODUCER_URI)) {
return NotificationProducerClient.class;
} else if(capabilityMap.containsKey(WsnConstants.CONSUMER_URI)) {
return NotificationConsumerClient.class;
} else {
return WsResourceClient.class;
}
}
protected String generateClassName(Document wsdlDocument) {
String packageName = ClassInfo.getPackageName(wsdlDocument
.getDocumentElement().getAttribute(TARGET_NS_ATTR));
return packageName
+ "."
+ WsdlUtils.getServiceName(XmlUtils
.getDocumentRoot(wsdlDocument));
}
protected void initializeCode(String className) {
_className = className;
_headerCode = beginHeaderCode(_className);
_operationsCode = beginOperationsCode();
_propertiesCode = beginPropertiesCode();
_importSet = new HashSet();
_hasProperties = false;
resetIndex();
}
protected void resetIndex() {
_index = 0;
}
private StringBuffer beginOperationsCode() {
return new StringBuffer();
}
private StringBuffer beginPropertiesCode() {
StringBuffer code = new StringBuffer();
indent(code);
code.append("QName[] PROPERTIES = {");
return code;
}
protected void updateCode(ClassInfo classInfo) {
Capability capability = classInfo.getCapability();
updateMethods(classInfo, _operationsCode);
if (!capability.getProperties().isEmpty()) {
_hasProperties = true;
updateProperties(classInfo, _propertiesCode);
}
classInfo.addImports(_importSet);
}
protected void updateMethods(ClassInfo classInfo, StringBuffer code) {
Iterator i = classInfo.getCapability().getOperations().iterator();
while (i.hasNext()) {
JavaMethod method = (JavaMethod) i.next();
generateMethod(method, classInfo, code);
}
i = classInfo.getCapability().getProperties().iterator();
while (i.hasNext()) {
JavaProperty property = (JavaProperty) i.next();
generatePropertyGet(property, classInfo, getIndex(), code);
if (property.isAppendable())
generatePropertyInsert(property, classInfo, getIndex(), code);
if (property.isMutable()) {
generatePropertyUpdate(property, classInfo, getIndex(), code);
generatePropertyDelete(property, classInfo, getIndex(), code);
}
incrementIndex();
}
}
private void incrementIndex() {
_index++;
}
private int getIndex() {
return _index;
}
private void generateMethod(JavaMethod method, ClassInfo classInfo,
StringBuffer code) {
newLine(2, code);
indent(code);
generateMethodQualifier(code);
Class returnType = method.getReturnType();
code.append(ReflectUtils.getShortName(returnType));
code.append(' ');
code.append(method.getJavaName());
QName[] paramNames = method.getParameterTypeNames();
Class[] paramTypes = method.getParameterTypes();
generateParamList(paramNames, paramTypes, code);
newLine(code);
indent(2, code);
code.append("throws SoapFault");
addImport(SoapFault.class);
generateMethodBody(method, classInfo, code);
newLine(code);
}
protected void addImports(Class[] classes) {
for(int i=0; i < classes.length; i++) {
addImport(classes[i]);
}
}
protected void addImport(Class className) {
_importSet.add(className);
}
protected void generateMethodQualifier(StringBuffer code) {
//Do nothing
}
protected void generateParamList(QName[] paramNames, Class[] paramTypes,
StringBuffer code) {
code.append('(');
for (int n = 0; n < paramTypes.length; ++n) {
code.append(ReflectUtils.getShortName(paramTypes[n]));
code.append(' ');
if (paramNames != null)
code.append(ResourceInspector.getLowerCamelName(paramNames[n]
.getLocalPart()));
else
code.append(PARAM_NAME + n);
if (n != paramTypes.length - 1)
code.append(", ");
}
if (_generateCustomHeaders) {
if (paramTypes.length > 0) {
code.append(", ");
}
code.append("Element[] customHeaders");
}
code.append(")");
}
protected void generateMethodBody(JavaMethod method, ClassInfo classInfo, StringBuffer code) {
code.append(';');
}
private void generatePropertyGet(JavaProperty property,
ClassInfo classInfo, int propertyIndex, StringBuffer code) {
newLine(code);
indent(code);
generateMethodQualifier(code);
Class type = property.getJavaType();
code.append(convertType(type, classInfo));
code.append(' ');
code.append("get" + property.getName().getLocalPart());
code.append("()");
newLine(code);
indent(2, code);
code.append("throws SoapFault");
addImport(SoapFault.class);
generatePropertyGetBody(property, classInfo, propertyIndex, code);
newLine(code);
}
protected void generatePropertyGetBody(JavaProperty property, ClassInfo classInfo, int propertyIndex, StringBuffer code) {
code.append(';');
}
private void generatePropertyUpdate(JavaProperty property,
ClassInfo classInfo, int propertyIndex, StringBuffer code) {
generatePropertySet(property, classInfo, propertyIndex, "update", code);
}
private void generatePropertyInsert(JavaProperty property,
ClassInfo classInfo, int propertyIndex, StringBuffer code) {
generatePropertySet(property, classInfo, propertyIndex, "insert", code);
}
private void generatePropertySet(JavaProperty property,
ClassInfo classInfo, int propertyIndex, String setType, StringBuffer code) {
newLine(code);
indent(code);
generateMethodQualifier(code);
Class type = property.getJavaType();
if(type.isArray()) {
type = ReflectUtils.getClassFromArrayClass(type);
}
code.append("void ");
code.append(setType);
code.append(property.getName().getLocalPart());
code.append('(');
code.append(ReflectUtils.getShortName(type));
code.append(" value)");
newLine(code);
indent(2, code);
code.append("throws SoapFault");
addImport(SoapFault.class);
generatePropertySetBody(property, classInfo, propertyIndex, setType, code);
newLine(code);
}
protected void generatePropertySetBody(JavaProperty property, ClassInfo classInfo, int propertyIndex, String setType, StringBuffer code) {
code.append(';');
}
private void generatePropertyDelete(JavaProperty property,
ClassInfo classInfo, int propertyIndex, StringBuffer code) {
newLine(code);
indent(code);
generateMethodQualifier(code);
code.append("void delete" + property.getName().getLocalPart());
code.append("()");
newLine(code);
indent(2, code);
code.append("throws SoapFault");
addImport(SoapFault.class);
generatePropertyDeleteBody(property, classInfo, propertyIndex, code);
newLine(code);
}
protected void generatePropertyDeleteBody(JavaProperty property, ClassInfo classInfo, int propertyIndex, StringBuffer code) {
code.append(';');
}
private void updateProperties(ClassInfo classInfo, StringBuffer code) {
Iterator i = classInfo.getCapability().getProperties().iterator();
if (i.hasNext()) {
addImport(QName.class);
}
while (i.hasNext()) {
generatePropertyConstant((JavaProperty) i.next(), code);
}
}
private void generatePropertyConstant(JavaProperty property,
StringBuffer code) {
newLine(code);
indent(2, code);
generateQName(property.getName(), code);
code.append(",");
}
protected String generateCombinedCode(ClassInfo classInfo) {
endHeaderCode(classInfo);
endOperationsCode();
endPropertiesCode();
StringBuffer code = new StringBuffer();
code.append(_headerCode);
code.append(_operationsCode);
if (_hasProperties) {
code.append(_propertiesCode);
}
return code.append(generateFooterCode()).toString();
}
protected void endHeaderCode(ClassInfo classInfo) {
generateImports(classInfo, _headerCode);
generateClassDef(_className, true, _headerCode);
}
private void endOperationsCode() {
newLine(_operationsCode);
}
private void endPropertiesCode() {
int length = _propertiesCode.length();
_propertiesCode.delete(length - 1, length);
newLine(_propertiesCode);
indent(_propertiesCode);
generateCloseBlock(_propertiesCode);
_propertiesCode.append(";");
newLine(_propertiesCode);
}
private StringBuffer generateFooterCode() {
StringBuffer code = new StringBuffer();
newLine(code);
generateCloseBlock(code);
newLine(code);
return code;
}
public ConfigurationDataDescriptor[] getConfigurationDataDescriptions() {
return REQUIRED_PARAMETERS;
}
}