templates.stub.ksoap.envelope.vm Maven / Gradle / Ivy
#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