001package net.gdface.codegen.webclient;
002
003import java.lang.reflect.Type;
004import java.net.URI;
005import java.util.HashMap;
006import java.util.Iterator;
007import java.util.Map;
008import java.util.Map.Entry;
009
010import javax.xml.namespace.QName;
011
012import net.gdface.codegen.AbstractSchema;
013import net.gdface.codegen.CodeGenUtils;
014import net.gdface.codegen.Method;
015import net.gdface.codegen.wsdl.WebServiceInfo;
016import net.gdface.utils.Assert;
017
018import org.apache.axis2.description.AxisMessage;
019import org.apache.axis2.description.AxisOperation;
020import org.apache.axis2.description.AxisService;
021import org.apache.axis2.description.java2wsdl.TypeTable;
022import org.apache.axis2.wsdl.WSDLConstants;
023import org.apache.ws.commons.schema.XmlSchema;
024
025public class KSoapStub<T> extends AbstractSchema implements KSoapConstants {
026        private final WebServiceInfo webServiceInfo;
027        private final AxisService service;
028        protected final Class<?> serviceClass;
029        private final Map<QName, ComplexType> complexTypeBeans = new HashMap<QName, ComplexType>();
030        private final Map<QName, ComplexType> complexTypeRequests = new HashMap<QName, ComplexType>();
031        private final Map<QName, ComplexType> complexTypeResponses = new HashMap<QName, ComplexType>();
032        private final Map<QName, ComplexType> complexTypeFaults = new HashMap<QName, ComplexType>();
033        private final Map<QName, ComplexType> complexTypeOthers = new HashMap<QName, ComplexType>();
034        private final Map<String, Map<QName, ComplexType>> schemaMap = new HashMap<String, Map<QName, ComplexType>>() {
035                private static final long serialVersionUID = 1L;
036                {
037                        put(TypePurpose.BEAN.name(), complexTypeBeans);
038                        put(TypePurpose.REQUEST.name(), complexTypeRequests);
039                        put(TypePurpose.RESPONSE.name(), complexTypeResponses);
040                        put(TypePurpose.FAULT.name(), complexTypeFaults);
041                        put(TypePurpose.OTHER.name(), complexTypeOthers);
042                }
043        };
044
045        public KSoapStub(Class<?> serviceClass, URI wsdlURI, String serviceName) {
046                Assert.notNull(wsdlURI,"wsdlURI");
047                Assert.notNull(serviceClass, "serviceClass");
048                this.serviceClass=serviceClass;
049                webServiceInfo = new WebServiceInfo(wsdlURI, serviceClass, serviceName);
050                service = this.webServiceInfo.getAxisService();
051        }
052
053        @Override
054        public boolean compile() {
055                boolean compileOk = false;
056                try{
057                        addImportedClassFromMethods(webServiceInfo.getPorts().values());
058                        this.createSchemaForBeans();
059                        this.createSchemaForPorts();
060                        this.createSchemaForOthers();
061                        compileOk = true;
062                }finally{
063                        
064                }
065                return compileOk;
066        }
067
068        private void createSchemaForBeans() {
069                Entry<QName, Class<?>> entry;
070                for (Iterator<Entry<QName, Class<?>>> it = this.webServiceInfo.getQNameToClassMap().entrySet().iterator(); it
071                                .hasNext();) {
072                        entry = it.next();
073                        complexTypeBeans.put(entry.getKey(), new ComplexType(
074                                        webServiceInfo.getXmlSchemaComplexType(entry.getKey()), webServiceInfo, null, null));
075                }
076        }
077
078        private void createSchemaForOthers() {
079                QName name;
080                for (XmlSchema schema : this.webServiceInfo.getSchema()) {
081                        for (@SuppressWarnings("unchecked")
082                        Iterator<QName> it = schema.getSchemaTypes().getNames(); it.hasNext();) {
083                                name = it.next();
084                                if (!this.hasComplexType(name)) {
085                                        complexTypeOthers.put(name, new ComplexType(webServiceInfo.getXmlSchemaComplexType(name),
086                                                        webServiceInfo, null, null));
087                                }
088                        }
089                }
090        }
091
092        private final void setComplexTypeUsedRelatedBy(Class<?>... classes) {
093                String className;
094                QName name;
095                TypeTable typeTable = this.service.getTypeTable();
096                ComplexType complexType;
097
098                for (Class<?> clazz : classes) {
099                        if (null != clazz) {
100                                clazz = CodeGenUtils.getElementClass(clazz);
101                                if (!typeTable.isSimpleType(className = clazz.getName())) {
102                                        if (null != (name = typeTable.getQNamefortheType(className))) {
103                                                if (null != (complexType = this.complexTypeBeans.get(name))) {
104                                                        complexType.setUsed(true);
105                                                } else
106                                                        throw new IllegalArgumentException(String.format("can't found complex type for QName [%s]",
107                                                                        name));
108                                        } else
109                                                throw new IllegalArgumentException(String.format("can't found QName for [%s] in typeTable",
110                                                                className));
111                                }
112                        }
113                }
114        }
115        
116        private final void setComplexTypeUsedRelatedBy(Type... types) {
117                for (Type type : types) {
118                        if (null != type) {
119                                if (type instanceof Class) {
120                                        setComplexTypeUsedRelatedBy((Class<?>) type);
121                                } else {
122                                        setComplexTypeUsedRelatedBy(Method.getAllClassForGenericType(type.toString()));                                 
123                                }
124                        }
125                }
126        }
127
128        private void createSchemaForPorts() {
129                Entry<String, Method> entry;
130                QName qn;
131                AxisOperation op;
132                ComplexType complexType;
133                AxisMessage msg;
134                boolean used=true;
135                for (Iterator<Entry<String, Method>> it = this.webServiceInfo.getPorts().entrySet().iterator(); it.hasNext();) {
136                        entry = it.next();
137                        op = service.getOperation(new QName(service.getTargetNamespace(), entry.getKey()));
138                        try {
139                                msg = op.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
140                                qn = msg.getElementQName();
141                                complexType = new ComplexType(msg.getSchemaElement(), webServiceInfo, entry.getValue()
142                                                .getGenericParameterTypes(), op);
143                                complexType.setUsed(used);
144                                setComplexTypeUsedRelatedBy(entry.getValue().getGenericParameterTypes());
145                                this.complexTypeRequests.put(qn, complexType);
146                        } catch (UnsupportedOperationException e) {
147
148                        }
149                        try {
150                                msg = op.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
151                                qn = msg.getElementQName();
152                                complexType = new ComplexType(msg.getSchemaElement(),webServiceInfo, entry.getValue().getGenericReturnType(), op);
153                                complexType.setUsed(used);
154                                setComplexTypeUsedRelatedBy(entry.getValue().getGenericReturnType());
155                                this.complexTypeResponses.put(qn, complexType);
156                        } catch (UnsupportedOperationException e) {
157                        }
158                        setComplexTypeUsedRelatedBy(entry.getValue().getGenericExceptionTypes());
159                        for (AxisMessage fault : op.getFaultMessages()) {
160                                qn = fault.getElementQName();
161                                if (!complexTypeFaults.containsKey(qn)) {
162                                        complexType = new ComplexType(fault.getSchemaElement(),webServiceInfo, FAULT_MESSAGE, op);
163                                        complexType.setUsed(used);
164                                        this.complexTypeFaults.put(qn, complexType);
165                                }
166                        }
167                }
168        }
169
170        public ComplexType getComplexType(QName name) {
171                ComplexType complexType = null;
172                for (Map<QName, ComplexType> schema : schemaMap.values()) {
173                        if (null != (complexType = schema.get(name)))
174                                return complexType;
175                }
176                return complexType;
177        }
178
179        /**
180         * @return webServiceInfo
181         */
182        public WebServiceInfo getWebServiceInfo() {
183                return webServiceInfo;
184        }
185
186        public boolean hasComplexType(QName name) {
187                return getComplexType(name) != null;
188        }
189
190        /**
191         * @return complexTypeBeans
192         */
193        public Map<QName, ComplexType> getComplexTypeBeans() {
194                return complexTypeBeans;
195        }
196
197        /**
198         * @return complexTypeRequests
199         */
200        public Map<QName, ComplexType> getComplexTypeRequests() {
201                return complexTypeRequests;
202        }
203
204        /**
205         * @return complexTypeResponses
206         */
207        public Map<QName, ComplexType> getComplexTypeResponses() {
208                return complexTypeResponses;
209        }
210
211        /**
212         * @return complexTypeFaults
213         */
214        public Map<QName, ComplexType> getComplexTypeFaults() {
215                return complexTypeFaults;
216        }
217
218        /**
219         * @return complexTypeOthers
220         */
221        public Map<QName, ComplexType> getComplexTypeOthers() {
222                return complexTypeOthers;
223        }
224
225        /**
226         * @return schemaMap
227         */
228        public Map<String, Map<QName, ComplexType>> getSchemaMap() {
229                return schemaMap;
230        }
231
232        /**
233         * @param name
234         * @return
235         * @see java.util.Map#get(java.lang.Object)
236         */
237        public Map<QName, ComplexType> getSchema(String name) {
238                return schemaMap.get(name);
239        }
240
241        /**
242         * @return serviceClass
243         */
244        public Class<?> getServiceClass() {
245                return serviceClass;
246        }
247        
248        
249}