| /* |
| * Copyright 2001-2004 The Apache Software Foundation. |
| * |
| * Licensed 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.axis.encoding.ser; |
| |
| import org.apache.axis.AxisFault; |
| import org.apache.axis.Constants; |
| import org.apache.axis.description.FieldDesc; |
| import org.apache.axis.description.TypeDesc; |
| import org.apache.axis.encoding.SerializationContext; |
| import org.apache.axis.encoding.SimpleValueSerializer; |
| import org.apache.axis.encoding.SimpleType; |
| import org.apache.axis.utils.BeanPropertyDescriptor; |
| import org.apache.axis.utils.BeanUtils; |
| import org.apache.axis.utils.Messages; |
| import org.apache.axis.utils.JavaUtils; |
| import org.apache.axis.wsdl.fromJava.Types; |
| import org.w3c.dom.Element; |
| import org.xml.sax.Attributes; |
| import org.xml.sax.helpers.AttributesImpl; |
| |
| import javax.xml.namespace.QName; |
| import java.io.IOException; |
| |
| /** |
| * Serializer for primitives and anything simple whose value is obtained with toString() |
| * |
| * @author Rich Scheuerle <dims@yahoo.com> |
| */ |
| public class SimpleSerializer implements SimpleValueSerializer { |
| public QName xmlType; |
| public Class javaType; |
| |
| private BeanPropertyDescriptor[] propertyDescriptor = null; |
| private TypeDesc typeDesc = null; |
| public static final String VALUE_PROPERTY = "_value"; |
| |
| public SimpleSerializer(Class javaType, QName xmlType) { |
| this.xmlType = xmlType; |
| this.javaType = javaType; |
| init(); |
| } |
| public SimpleSerializer(Class javaType, QName xmlType, TypeDesc typeDesc) { |
| this.xmlType = xmlType; |
| this.javaType = javaType; |
| this.typeDesc = typeDesc; |
| init(); |
| } |
| |
| /** |
| * Initialize the typeDesc and propertyDescriptor array. |
| */ |
| private void init() { |
| // Set the typeDesc if not already set |
| if (typeDesc == null) { |
| typeDesc = TypeDesc.getTypeDescForClass(javaType); |
| } |
| // Get the cached propertyDescriptor from the type or |
| // generate a fresh one. |
| if (typeDesc != null) { |
| propertyDescriptor = typeDesc.getPropertyDescriptors(); |
| } else if (!JavaUtils.isBasic(javaType)) { |
| propertyDescriptor = BeanUtils.getPd(javaType, null); |
| } |
| } |
| |
| /** |
| * Serialize a primitive or simple value. |
| * If the object to serialize is a primitive, the Object value below |
| * is the associated java.lang class. |
| * To determine if the original value is a java.lang class or a primitive, consult |
| * the javaType class. |
| */ |
| public void serialize(QName name, Attributes attributes, |
| Object value, SerializationContext context) |
| throws IOException |
| { |
| if (value != null && value.getClass() == java.lang.Object.class) { |
| throw new IOException(Messages.getMessage("cantSerialize02")); |
| } |
| |
| // get any attributes |
| attributes = getObjectAttributes(value, attributes, context); |
| |
| String valueStr = null; |
| if (value != null) { |
| valueStr = getValueAsString(value, context); |
| } |
| context.startElement(name, attributes); |
| if (valueStr != null) { |
| context.writeSafeString(valueStr); |
| } |
| context.endElement(); |
| } |
| |
| public String getValueAsString(Object value, SerializationContext context) { |
| // We could have separate serializers/deserializers to take |
| // care of Float/Double cases, but it makes more sence to |
| // put them here with the rest of the java lang primitives. |
| if (value instanceof Float || |
| value instanceof Double) { |
| double data = 0.0; |
| if (value instanceof Float) { |
| data = ((Float) value).doubleValue(); |
| } else { |
| data = ((Double) value).doubleValue(); |
| } |
| if (Double.isNaN(data)) { |
| return "NaN"; |
| } else if (data == Double.POSITIVE_INFINITY) { |
| return "INF"; |
| } else if (data == Double.NEGATIVE_INFINITY) { |
| return "-INF"; |
| } |
| } else if (value instanceof QName) { |
| return context.qName2String((QName)value); |
| } |
| |
| if (propertyDescriptor != null && !(value instanceof SimpleType)) { |
| BeanPropertyDescriptor pd = BeanUtils.getSpecificPD(propertyDescriptor, "_value"); |
| if(pd != null) { |
| try { |
| return pd.get(value).toString(); |
| } catch (Exception e) { |
| } |
| } |
| } |
| return value.toString(); |
| } |
| |
| private Attributes getObjectAttributes(Object value, |
| Attributes attributes, |
| SerializationContext context) { |
| if (typeDesc != null && !typeDesc.hasAttributes()) |
| return attributes; |
| |
| AttributesImpl attrs; |
| if (attributes == null) { |
| attrs = new AttributesImpl(); |
| } else if (attributes instanceof AttributesImpl) { |
| attrs = (AttributesImpl)attributes; |
| } else { |
| attrs = new AttributesImpl(attributes); |
| } |
| |
| try { |
| // Find each property that is an attribute |
| // and add it to our attribute list |
| for (int i = 0; |
| propertyDescriptor != null && i < propertyDescriptor.length; |
| i++) { |
| String propName = propertyDescriptor[i].getName(); |
| if (propName.equals("class")) |
| continue; |
| |
| QName qname = null; |
| if(typeDesc != null) { |
| FieldDesc field = typeDesc.getFieldByName(propName); |
| // skip it if its not an attribute |
| if (field == null || field.isElement()) |
| continue; |
| qname = field.getXmlName(); |
| } else { |
| if(propName.equals(VALUE_PROPERTY)) |
| continue; |
| } |
| if (qname == null) { |
| qname = new QName("", propName); |
| } |
| |
| if (propertyDescriptor[i].isReadable() && |
| !propertyDescriptor[i].isIndexed()) { |
| // add to our attributes |
| Object propValue = propertyDescriptor[i].get(value); |
| // If the property value does not exist, don't serialize |
| // the attribute. In the future, the decision to serializer |
| // the attribute may be more sophisticated. For example, don't |
| // serialize if the attribute matches the default value. |
| if (propValue != null) { |
| String propString = getValueAsString(propValue, context); |
| |
| String namespace = qname.getNamespaceURI(); |
| String localName = qname.getLocalPart(); |
| |
| attrs.addAttribute(namespace, |
| localName, |
| context.qName2String(qname), |
| "CDATA", |
| propString); |
| } |
| } |
| } |
| } catch (Exception e) { |
| // no attributes |
| return attrs; |
| } |
| |
| return attrs; |
| } |
| |
| public String getMechanismType() { return Constants.AXIS_SAX; } |
| |
| /** |
| * Return XML schema for the specified type, suitable for insertion into |
| * the <types> element of a WSDL document, or underneath an |
| * <element> or <attribute> declaration. |
| * |
| * @param javaType the Java Class we're writing out schema for |
| * @param types the Java2WSDL Types object which holds the context |
| * for the WSDL being generated. |
| * @return a type element containing a schema simpleType/complexType |
| * @see org.apache.axis.wsdl.fromJava.Types |
| */ |
| public Element writeSchema(Class javaType, Types types) throws Exception { |
| // ComplexType representation of SimpleType bean class |
| Element complexType = types.createElement("complexType"); |
| types.writeSchemaTypeDecl(xmlType, complexType); |
| complexType.setAttribute("name", xmlType.getLocalPart()); |
| |
| // Produce simpleContent extending base type. |
| Element simpleContent = types.createElement("simpleContent"); |
| complexType.appendChild(simpleContent); |
| Element extension = types.createElement("extension"); |
| simpleContent.appendChild(extension); |
| |
| // Get the base type from the "value" element of the bean |
| String base = "string"; |
| for (int i=0; propertyDescriptor != null && i<propertyDescriptor.length; i++) { |
| String propName = propertyDescriptor[i].getName(); |
| if (!propName.equals("value")) { |
| if (typeDesc != null) { |
| FieldDesc field = typeDesc.getFieldByName(propName); |
| if (field != null) { |
| if (field.isElement()) { |
| // throw? |
| } |
| QName qname = field.getXmlName(); |
| if (qname == null) { |
| // Use the default... |
| qname = new QName("", propName); |
| } |
| |
| // write attribute element |
| Class fieldType = propertyDescriptor[i].getType(); |
| |
| // Attribute must be a simple type, enum or SimpleType |
| if (!types.isAcceptableAsAttribute(fieldType)) { |
| throw new AxisFault(Messages.getMessage("AttrNotSimpleType00", |
| propName, |
| fieldType.getName())); |
| } |
| |
| // write attribute element |
| // TODO the attribute name needs to be preserved from the XML |
| Element elem = types.createAttributeElement(propName, |
| fieldType, |
| field.getXmlType(), |
| false, |
| extension.getOwnerDocument()); |
| extension.appendChild(elem); |
| } |
| } |
| continue; |
| } |
| |
| BeanPropertyDescriptor bpd = propertyDescriptor[i]; |
| Class type = bpd.getType(); |
| // Attribute must extend a simple type, enum or SimpleType |
| if (!types.isAcceptableAsAttribute(type)) { |
| throw new AxisFault(Messages.getMessage("AttrNotSimpleType01", |
| type.getName())); |
| } |
| base = types.writeType(type); |
| extension.setAttribute("base", base); |
| } |
| |
| // done |
| return complexType; |
| |
| } |
| } |