001package net.gdface.codegen.webclient;
002
003import java.beans.PropertyDescriptor;
004import java.lang.reflect.Type;
005import java.util.ArrayList;
006import java.util.HashMap;
007import java.util.Iterator;
008import java.util.Map;
009import java.util.Map.Entry;
010
011import javax.xml.namespace.QName;
012
013import org.apache.axis2.description.AxisOperation;
014import org.apache.axis2.description.java2wsdl.TypeTable;
015import org.apache.ws.commons.schema.XmlSchemaComplexType;
016import org.apache.ws.commons.schema.XmlSchemaElement;
017import org.apache.ws.commons.schema.XmlSchemaObject;
018import org.slf4j.Logger;
019import org.slf4j.LoggerFactory;
020
021import net.gdface.codegen.AbstractSchema;
022import net.gdface.codegen.wsdl.WebServiceInfo;
023import net.gdface.utils.Assert;
024import net.gdface.utils.BeanPropertyUtils;
025
026/**
027 * {@link}
028 * @author guyadong
029 *
030 */
031public class ComplexType extends AbstractSchema implements KSoapConstants {
032        private static final Logger logger = LoggerFactory.getLogger(ComplexType.class);
033
034        private final ArrayList<XmlSchemaElement> fieldElements;
035        private final XmlSchemaObject schemaObj;
036        private final WebServiceInfo webServiceInfo;
037        private final Object objectForPort;
038        private final TypeTable typeTable;
039        private KSoapConstants.TypePurpose purpose;
040        private boolean used=false;
041        private final AxisOperation operation;
042        protected ComplexType(XmlSchemaObject schemaObj, WebServiceInfo webServiceInfo, Object objectForPort, AxisOperation operation) {
043                Assert.notNull(schemaObj, "schemaObj");
044                Assert.notNull(webServiceInfo, "webServiceInfo");
045                this.objectForPort = objectForPort;
046                this.schemaObj = schemaObj;
047                this.webServiceInfo = webServiceInfo;
048                this.typeTable = webServiceInfo.getAxisService().getTypeTable();
049                this.operation=operation;
050                if(schemaObj instanceof XmlSchemaComplexType){
051                        this.fieldElements = webServiceInfo.getFieldElements(((XmlSchemaComplexType)this.schemaObj).getQName());
052                }else if(schemaObj instanceof XmlSchemaElement){
053                        this.fieldElements = webServiceInfo.getFieldElements(((XmlSchemaElement)schemaObj).getQName());
054                }else 
055                        throw new IllegalArgumentException(String.format("invalid type,schemaObj must be  %s OR %s",
056                                        XmlSchemaElement.class.getSimpleName(),XmlSchemaComplexType.class.getSimpleName()));    
057                init();
058        }
059
060        private void addImportedBeanFieldClass(Class<?> beanClass) {
061                this.addImportedClass(getReadablePropertiesReturnClass(beanClass).values().toArray(new Type[0]));
062        }
063
064        private void addImportedFieldElementsClass() {
065                XmlSchemaElement element;
066                String className;
067                QName typeName;
068                for (Iterator<XmlSchemaElement> it = getFieldElements().iterator(); it.hasNext();) {
069                        element = it.next();
070                        typeName = element.getSchemaTypeName();
071                        try {
072                                className = typeTable.getClassNameForQName(typeName);
073                                if(className!=null){
074                                        this.addImportedClass(className);
075                                }
076                        } catch (ClassNotFoundException e) {
077                                throw new RuntimeException(e);
078                        }
079                }
080        }
081        private void init(){
082                try {
083                        //根据objectForPort的类型判断对象类型
084                        if(schemaObj instanceof XmlSchemaComplexType){
085                                String className = typeTable.getClassNameForQName(((XmlSchemaComplexType)this.schemaObj).getQName());
086                                if (className != null) {// bean对象
087                                        this.baseClass = Class.forName(className);
088                                        this.addImportedClass(baseClass);
089                                        this.addImportedBeanFieldClass(baseClass);
090                                        this.purpose = TypePurpose.BEAN;        
091                                }else{
092                                        this.addImportedFieldElementsClass();
093                                        this.purpose = TypePurpose.OTHER;
094                                }
095                        } else if (this.objectForPort.getClass().isArray()) {// request:参数类型数组(message)
096                                this.addImportedClass((Type[]) objectForPort);
097                                this.purpose = TypePurpose.REQUEST;
098                        } else if (this.objectForPort instanceof Type) {// response:返回类型(message)
099                                this.addImportedClass((Type) this.objectForPort);
100                                this.purpose = TypePurpose.RESPONSE;
101                        } else if (this.objectForPort==FAULT_MESSAGE) {// fault:异常返回消息(message)
102                                this.purpose = TypePurpose.FAULT;
103                        } else {
104                                // 其他消息类型
105                                this.addImportedFieldElementsClass();
106                                this.purpose = TypePurpose.OTHER;
107                        }
108                } catch (ClassNotFoundException e) {
109                        logger.error(e.toString());
110                } finally {
111                }
112        }
113        @Override
114        public boolean compile() {
115                return true;
116        }
117
118        /**
119         * @return fieldElements
120         */
121        public ArrayList<XmlSchemaElement> getFieldElements() {
122                return fieldElements;
123        }
124
125        public Map<String, PropertyDescriptor> getReadableProperties() {
126                return BeanPropertyUtils.getProperties(this.baseClass, 2);
127        }
128
129        public Map<String, PropertyDescriptor> getRwProperties() {
130                return BeanPropertyUtils.getProperties(this.baseClass, 3);
131        }
132
133        public Map<String, PropertyDescriptor> getAllProperties() {
134                return BeanPropertyUtils.getProperties(this.baseClass, 0);
135        }
136
137        public Map<String, Type> getReadablePropertiesReturnClass() {
138                return getReadablePropertiesReturnClass(this.baseClass);
139        }
140
141        public Map<String, Type> getReadablePropertiesReturnClass(Class<?> beanClass) {
142                try {
143                        Map<String, PropertyDescriptor> properties = BeanPropertyUtils.getProperties(beanClass, 2);
144                        Map<String, Type> classMap = new HashMap<String, Type>(properties.size());
145                        Entry<String, PropertyDescriptor> entry;
146                        for (Iterator<Entry<String, PropertyDescriptor>> it = properties.entrySet().iterator(); it.hasNext();) {
147                                entry = it.next();
148                                classMap.put(entry.getKey(), entry.getValue().getReadMethod().getGenericReturnType());
149                        }
150                        return classMap;
151                } catch (Exception e) {
152                        throw new RuntimeException(e);
153                }
154        }
155
156        public boolean isBean() {
157                return this.purpose == KSoapConstants.TypePurpose.BEAN;
158        }
159
160        public boolean isRequest() {
161                return this.purpose == KSoapConstants.TypePurpose.REQUEST;
162        }
163
164        public boolean isResponse() {
165                return this.purpose == KSoapConstants.TypePurpose.RESPONSE;
166        }
167        public boolean isFault() {
168                return this.purpose == KSoapConstants.TypePurpose.FAULT;
169        }
170        public boolean isOther() {
171                return this.purpose == KSoapConstants.TypePurpose.OTHER;
172        }
173
174        /**
175         * @return webServiceInfo
176         */
177        public WebServiceInfo getWebServiceInfo() {
178                return webServiceInfo;
179        }
180
181        /**
182         * @return used
183         */
184        public boolean isUsed() {
185                return used;
186        }
187
188        /**
189         * @param used 要设置的 used
190         */
191        public void setUsed(boolean used) {
192                this.used = used;
193        }
194
195        /**
196         * @return schemaObj
197         */
198        public XmlSchemaObject getSchemaObj() {
199                return schemaObj;
200        }
201        /**
202         * @return objectForPort
203         */
204        public Object getObjectForPort() {
205                return objectForPort;
206        }
207
208        /**
209         * @return operation
210         */
211        public AxisOperation getOperation() {
212                return operation;
213        }
214        
215
216
217}