All Downloads are FREE. Search and download functionalities are using the official Maven repository.

templates.stub.ksoap.envelope.vm Maven / Gradle / Ivy

There is a newer version: 3.5.0
Show newest version
#parse("${include}/generic.include.vm")
#parse("${include}/webclient.ksoap.include.vm")
#set ( $className                ="$C_ENVELOPE")
$codewriter.setCurrentJavaFilename("$pkg", "${className}.java")
package $pkg;

import java.io.IOException;
import java.lang.reflect.MalformedParameterizedTypeException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Vector;

import org.ksoap2.serialization.KvmSerializable;
import org.ksoap2.serialization.MarshalBase64;
import org.ksoap2.serialization.MarshalDate;
import org.ksoap2.serialization.MarshalFloat;
import org.ksoap2.serialization.PropertyInfo;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

/**
 * 实现基于AXS2生成的xml的对象序列化和反序列化
 * @author guyadong
 * 
 */
public class $className extends SoapSerializationEnvelope {
    private static final String ARRAY_TYPE_LABEL = "arrayType";
    private static final String ARRAY_MAPPING_NAME = "Array";
    private static final String TYPE_LABEL = "type";
    private static final String NIL_LABEL = "nil";
    private static final String ITEM_LABEL = "item";
    private static final String HREF_LABEL = "href";
    private static final String ID_LABEL = "id";
    private static final String NULL_LABEL = "null";


    public $className(int version) {
        super(version);
        new MarshalBase64().register(this);
        new MarshalDate().register(this);
        new MarshalFloat().register(this);
        // 覆盖DM设置
        new SimpleTypeMarshal().register(this);
    }

    @Override
    public Object readInstance(XmlPullParser parser, String namespace, String name, PropertyInfo expected)
            throws IOException, XmlPullParserException {
        Object obj = super.readInstance(parser, namespace, name, expected);
        if (null == obj && expected.type instanceof Class) {
            Class expectedType = null;
            if (KvmSerializable.class.isAssignableFrom((Class) expected.type)) {
                expectedType = (Class) expected.type;
            } else if (Vector.class.isAssignableFrom((Class) expected.type)) {
                expectedType = (Class) expected.elementType.type;
            }
            if (null != expectedType) {
                addMapping(namespace, name, (Class) expected.type);
                obj = super.readInstance(parser, namespace, name, expected);
            }
        }
        return obj;
    }

    /** 
     * 修改读取{@link Vector}的逻辑
* 父类中的方法用{@code END_TAG}来判断数组结束,但axis2生成的xml中数组成员中的元素与其他成员在同一层,
* 所以改为通过{@link XmlPullParser} 的当前{@code name}({@code parser.getName()})来判断数组是否结束
* 同时在执行 parser.nextTag()前也要判断当前的name是不是数组元素的name,如果是就不执行
*/ @SuppressWarnings("unchecked") @Override protected void readVector(XmlPullParser parser, @SuppressWarnings("rawtypes") Vector v, PropertyInfo elementType) throws IOException, XmlPullParserException { String namespace = null; String name = null; int size = v.size(); boolean dynamic = true; String type = parser.getAttributeValue(enc, ARRAY_TYPE_LABEL); if (type != null) { int cut0 = type.indexOf(':'); int cut1 = type.indexOf("[", cut0); name = type.substring(cut0 + 1, cut1); String prefix = cut0 == -1 ? "" : type.substring(0, cut0); namespace = parser.getNamespace(prefix); size = getIndex(type, cut1, -1); if (size != -1) { v.setSize(size); dynamic = false; } } //判断当前的name是不是数组元素的name,如果是就不执行 if(elementType == null||!elementType.name.equals(parser.getName())||!elementType.namespace.equals(parser.getNamespace())) parser.nextTag(); if (elementType == null && (null == (elementType = getElementInfo(parser, v)))) { elementType = PropertyInfo.OBJECT_TYPE; } int position = getIndex(parser.getAttributeValue(enc, "offset"), 0, 0); //如果当前元素name与Vector元素的名字(elementType.name)不相等,就判断数组结束 while (parser.getEventType() != XmlPullParser.END_TAG&&elementType.name.equals(parser.getName())) { // handle position position = getIndex(parser.getAttributeValue(enc, "position"), 0, position); if (dynamic && position >= size) { size = position + 1; v.setSize(size); } // implicit handling of position exceeding specified size v.setElementAt(read(parser, v, position, namespace, name, elementType), position); position++; parser.nextTag(); } } /** * 从父类复制 * @param value * @param start * @param dflt * @return int */ private int getIndex(String value, int start, int dflt) { if (value == null) { return dflt; } try { return value.length() - start < 3 ? dflt : Integer.parseInt(value.substring(start + 1, value.length() - 1)); } catch (Exception ex) { return dflt; } } protected PropertyInfo getElementInfo(XmlPullParser parser, @SuppressWarnings("rawtypes") Vector v) { if (v instanceof KvmSerializable) { PropertyInfo propertyInfo = new PropertyInfo(); KvmSerializable k = (KvmSerializable) v; k.getPropertyInfo(0, properties, propertyInfo); return propertyInfo; } else { return getPropertyInfoFromPaser(parser, v); } } protected PropertyInfo getPropertyInfoFromPaser(XmlPullParser parser, @SuppressWarnings("rawtypes") Vector v) { String type = parser.getAttributeValue(xsi, TYPE_LABEL); PropertyInfo propertyInfo = new PropertyInfo(); if (type != null) { propertyInfo.name = parser.getName(); propertyInfo.namespace = parser.getNamespace(); int cut = type.indexOf(':'); String prefix = cut == -1 ? "" : type.substring(0, cut); propertyInfo.type = qNameToClass.get(new SoapPrimitive(parser.getNamespace(prefix), type.substring(cut + 1), null)); if (propertyInfo.type == null) { Class[] types = getParameterizedTypeNoThrow(v.getClass()); if (types.length > 0) propertyInfo.type = types[0]; } return propertyInfo.type == null ? null : propertyInfo; } else return null; } /** * 如果无法获取泛型参数对象,返回null * * @param clazz * @return class * @see #getParameterizedType(Class) */ public static Class[] getParameterizedTypeNoThrow(Class clazz) { try { Class[] types = getParameterizedType(clazz); return types; } catch (Exception e) { return new Class[0]; } } /** * 返回{@code clazz}泛型超类的参数对象
* 如果超类不是泛型对象,则抛出{@link IllegalArgumentException}
* * @param clazz * @return class[] * @throws MalformedParameterizedTypeException * 超类不是泛型类 * @throws IllegalArgumentException * 无法获取实际泛型参数对象类型 */ public static Class[] getParameterizedType(Class clazz) throws MalformedParameterizedTypeException, IllegalArgumentException { Type partype = clazz.getGenericSuperclass(); if (!(partype instanceof ParameterizedType))// 超类不是泛型 throw new IllegalArgumentException(String.format("superclass of %s not ParameterizedType(超类不是泛型类)", clazz.getName())); Type[] types = ((ParameterizedType) partype).getActualTypeArguments(); if (!(types[0] instanceof Class)) { System.err.print("cant'not get class for ParameterizedType (无法获取实际泛型参数对象类型(Class))"); throw new MalformedParameterizedTypeException(); } Class[] paramClass = new Class[types.length]; for (int i = 0; i < paramClass.length; i++) paramClass[i] = (Class) types[i]; return paramClass; } @Override protected void writeProperty(XmlSerializer writer, Object obj, PropertyInfo type) throws IOException { if (obj == null) { writer.attribute(xsi, NIL_LABEL, "true"); // axis2-1.6.2 固定使用nil判断空值,所以在此重载方法修改对null的处理 // 参见org.apache.axis2.databinding.utils.BeanUtil#processObject(OMElement, Class, MultirefHelper, boolean,ObjectSupplier, Type) 795行 return; } super.writeProperty(writer, obj, type); } /** * Writes the body of an KvmSerializable object. This method is public for access from Marshal subclasses. */ @Override public void writeObjectBody(XmlSerializer writer, KvmSerializable obj) throws IOException { int cnt = obj.getPropertyCount(); PropertyInfo propertyInfo = new PropertyInfo(); String namespace; String name; String type; Object value,prop; for (int i = 0; i < cnt; i++) { // get the property prop = obj.getProperty(i); // and importantly also get the property info which holds the name potentially! obj.getPropertyInfo(i, properties, propertyInfo); if (!(prop instanceof SoapObject)) { // prop is a PropertyInfo if ((propertyInfo.flags & PropertyInfo.TRANSIENT) == 0) { value = obj.getProperty(i); if (propertyInfo.type != Vector.class||value==null)// 为Vector时不加头,与AXIS2兼容 writer.startTag(propertyInfo.namespace, propertyInfo.name); if (propertyInfo.type != Vector.class||((null!=value)&&((Vector)value).size()>0))// Vector为空时跳过,避免异常:illegal position for attribute writeProperty(writer, value, propertyInfo); if (propertyInfo.type != Vector.class||value==null)// 为Vector时不加尾 writer.endTag(propertyInfo.namespace, propertyInfo.name); value=null; } } else { // prop is a SoapObject SoapObject nestedSoap = (SoapObject) prop; // lets get the info from the soap object itself Object[] qName = getInfo(null, nestedSoap); namespace = (String) qName[QNAME_NAMESPACE]; type = (String) qName[QNAME_TYPE]; // prefer the name from the property info if (propertyInfo.name != null && propertyInfo.name.length() > 0) { name = propertyInfo.name; } else { name = (String) qName[QNAME_TYPE]; } writer.startTag((dotNet) ? "" : namespace, name); String prefix = writer.getPrefix(namespace, true); writer.attribute(xsi, TYPE_LABEL, prefix + ":" + type); writeObjectBody(writer, nestedSoap); writer.endTag((dotNet) ? "" : namespace, name); } } } @Override protected void writeVectorBody(XmlSerializer writer, @SuppressWarnings("rawtypes") Vector vector, PropertyInfo elementType) throws IOException { String itemsTagName = ITEM_LABEL; String itemsNamespace = null; if (elementType == null) { elementType = PropertyInfo.OBJECT_TYPE; } else if (elementType instanceof PropertyInfo) { if (elementType.name != null) { itemsTagName = elementType.name; itemsNamespace = elementType.namespace; } } int cnt = vector.size(); Object[] arrType = getInfo(elementType.type, null); // This removes the arrayType attribute from the xml for arrays(required for most .Net services to work) if (!implicitTypes) { writer.attribute(enc, ARRAY_TYPE_LABEL, writer.getPrefix((String) arrType[0], false) + ":" + arrType[1] + "[" + cnt + "]"); } //修改输出Vector的逻辑,当为null时,输出NIL_LABEL for (int i = 0; i < cnt; i++) { writer.startTag(itemsNamespace, itemsTagName); if (vector.elementAt(i) == null) writer.attribute(xsi, NIL_LABEL, "true"); else writeProperty(writer, vector.elementAt(i), elementType); writer.endTag(itemsNamespace, itemsTagName); } } /** * 重写该方法,修改解析逻辑,
* 分拆为 {@link #readSerializableBean(XmlPullParser, KvmSerializable)}和 {@link #readSoapObject(XmlPullParser, KvmSerializable)} */ @Override protected void readSerializable(XmlPullParser parser, KvmSerializable obj) throws IOException, XmlPullParserException { if (!implicitTypes || !(obj instanceof SoapObject)) readSerializableBean(parser, obj); else readSoapObject(parser, obj);//此分支不会用到,只是兼容性考虑保留 } /** * 处理所有定义了KvmSerializable类的对象
* 假设所有的元素都是按对象定义的顺序排序的,且为{@code null}的对象没有被跳过
* @param parser * @param obj * @throws IOException * @throws XmlPullParserException */ protected void readSerializableBean(XmlPullParser parser, KvmSerializable obj) throws IOException, XmlPullParserException { PropertyInfo info = new PropertyInfo(); int propertyCount = obj.getPropertyCount(); int eventType=parser.getEventType(); String name = parser.getName(); String namespace=parser.getNamespace(); for(int i=0;i) info.type)){ if(!info.name.equals(parser.getName())||!info.namespace.equals(parser.getNamespace())) parser.nextTag();//确保当前光标指向要求的对象,否则就执行netxTag obj.setProperty(i, read(parser, obj, i, info.namespace, info.name, info)); }else{ if(parser.getName().equals(info.name)||(eventType=parser.nextTag()) != XmlPullParser.END_TAG){ obj.setProperty(i, read(parser, obj, i, null, null, info)); } } } skiptoEND_TAG(parser,namespace,name); } protected void readSoapObject(XmlPullParser parser, KvmSerializable obj) throws IOException, XmlPullParserException { while (parser.nextTag() != XmlPullParser.END_TAG) { String name = parser.getName(); // I can only make this work for SoapObjects - hence the check above // I don't understand namespaces well enough to know whether it is correct in the next line... ((SoapObject) obj).addProperty( parser.getName(), read(parser, obj, obj.getPropertyCount(), ((SoapObject) obj).getNamespace(), name, PropertyInfo.OBJECT_TYPE)); } parser.require(XmlPullParser.END_TAG, null, null); } /** * 根据axis2生成的xml格式做特别处理
* 与ksoap的逻辑不同,axis2生成xml时,对于数组成员对象没有特别标记,所有数组元素与其他成员在同一层(没有开始和结束标签),
* 所以不能从{@code parser}中获取(namespace和name),
* 在读取完数组对象后,不能执行{@code parser.require}检查尾部标签
*/ @Override public Object read(XmlPullParser parser, Object owner, int index, String namespace, String name, PropertyInfo expected) throws IOException, XmlPullParserException { if (parser.getAttributeValue(null, HREF_LABEL) != null || parser.getAttributeValue(null, ID_LABEL) != null) return super.read(parser, owner, index, namespace, name, expected);//此分支不会用到,只是兼容性考虑保留 String elementName = parser.getName(); Object obj; String nullAttr = parser.getAttributeValue(xsi, NIL_LABEL); if (nullAttr == null) { nullAttr = parser.getAttributeValue(xsi, NULL_LABEL); } if (nullAttr != null && stringToBoolean(nullAttr)) { obj = null; parser.nextTag(); parser.require(XmlPullParser.END_TAG, null, elementName); } else { String type=null; //axis2生成的xml对数组没有特别标记,所以对于vector类型要先处理 if(expected.type instanceof Class &&Vector.class.isAssignableFrom((Class) expected.type)){ //使用输入参数namespace,name Object[] names = getInfo(expected.type, null); namespace = (String) names[0]; name = (String) names[1]; }else if ((type = parser.getAttributeValue(xsi, TYPE_LABEL)) != null) { int cut = type.indexOf(':'); name = type.substring(cut + 1); String prefix = cut == -1 ? "" : type.substring(0, cut); namespace = parser.getNamespace(prefix); } else if (name == null && namespace == null) { if (parser.getAttributeValue(enc, ARRAY_TYPE_LABEL) != null) { namespace = enc; name = ARRAY_MAPPING_NAME; } else { Object[] names = getInfo(expected.type, null); namespace = (String) names[0]; name = (String) names[1]; } } // be sure to set this flag if we don't know the types. if (type == null) { implicitTypes = true; } obj = readInstance(parser, namespace, name, expected); if (obj == null) { obj = readUnknown(parser, namespace, name); } } //Vector类型不检查尾部标签 if(!(expected.type instanceof Class && Vector.class.isAssignableFrom((Class) expected.type))) parser.require(XmlPullParser.END_TAG, null, elementName); return obj; } /** * 跳过所有无关的标签,直到namespace,name指定的元素结束标签(END_TAG) * @param parser * @param namespace * @param name * @throws XmlPullParserException * @throws IOException */ private void skiptoEND_TAG(XmlPullParser parser,String namespace, String name) throws XmlPullParserException, IOException { int eventType=parser.getEventType(); while(eventType!= XmlPullParser.END_TAG||(namespace!=null&&!namespace.equals(parser.getNamespace())) ||(name!=null &&!name.equals(parser.getName()))){ eventType=parser.next(); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy