ObjectSerializer.java
001 /*
002  *
003  * Licensed to the Apache Software Foundation (ASF) under one
004  * or more contributor license agreements.  See the NOTICE file
005  * distributed with this work for additional information
006  * regarding copyright ownership.  The ASF licenses this file
007  * to you under the Apache License, Version 2.0 (the
008  * "License"); you may not use this file except in compliance
009  * with the License.  You may obtain a copy of the License at
010  *
011  *   http://www.apache.org/licenses/LICENSE-2.0
012  *
013  * Unless required by applicable law or agreed to in writing,
014  * software distributed under the License is distributed on an
015  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016  * KIND, either express or implied.  See the License for the
017  * specific language governing permissions and limitations
018  * under the License.
019  *
020  */
021 package org.apache.qpid.management.wsdm.muse.serializer;
022 
023 import java.net.URI;
024 import java.util.Date;
025 import java.util.HashMap;
026 import java.util.Map;
027 import java.util.UUID;
028 
029 import javax.xml.XMLConstants;
030 import javax.xml.namespace.QName;
031 
032 import org.apache.muse.core.serializer.Serializer;
033 import org.apache.muse.core.serializer.SerializerRegistry;
034 import org.apache.muse.ws.addressing.soap.SoapFault;
035 import org.apache.qpid.management.Names;
036 import org.w3c.dom.Attr;
037 import org.w3c.dom.Element;
038 
039 /**
040  * Generic Serializer for objects.
041  * It is a general-purpose serializer used for encoding Object values.  
042  */
043 public class ObjectSerializer implements Serializer 
044 {
045   /**
046    * Mapping between xsd and java types.
047    */
048   private Map<String, Class<?>> xml2Java = new HashMap<String, Class<?>>();
049   {
050     xml2Java.put("xsd:long", Long.class);
051     xml2Java.put("xsd:boolean",Boolean.class);
052     xml2Java.put("xsd:double",Double.class);
053     xml2Java.put("xsd:float",Float.class);
054     xml2Java.put("xsd:integer",Integer.class);
055     xml2Java.put("xsd:int",Integer.class);
056     xml2Java.put("xsd:short",Short.class);
057     xml2Java.put("xsd:string",String.class);
058     xml2Java.put("xsd:anyURI",URI.class);
059     xml2Java.put("xsd:dateTime",Date.class);
060     xml2Java.put("xsd:QName",QName.class);
061     xml2Java.put("xsd:element",Element.class);
062     xml2Java.put("xsd:base64Binary",byte[].class);
063     xml2Java.put("qman:arrayOfLong",Long[].class);
064     xml2Java.put("qman:arrayOfBoolean",Boolean[].class);
065     xml2Java.put("qman:arrayOfDouble",Double[].class);
066     xml2Java.put("qman:arrayOfFloat",Float[].class);
067     xml2Java.put("qman:arrayOfInteger",Integer[].class);
068     xml2Java.put("qman:arrayOfShort",Short[].class);
069     xml2Java.put("qman:arrayOfString",String[].class);
070     xml2Java.put("qman:arrayOfURI",URI[].class);
071     xml2Java.put("qman:arrayOfDate",Date[].class);
072     xml2Java.put("qman:uuid",UUID.class);
073     xml2Java.put("qman:map",Map.class);    
074     xml2Java.put("qman:map",HashMap.class);    
075   }
076   
077   private Map<Class<?>, String> java2Xml = new HashMap<Class<?>, String>();
078   {    
079     java2Xml.put(UUID.class,"qman:uuid");
080     java2Xml.put(Long.class,"xsd:long");
081     java2Xml.put(long.class,"xsd:long");
082     java2Xml.put(Boolean.class,"xsd:boolean");
083     java2Xml.put(boolean.class,"xsd:boolean");
084     java2Xml.put(Double.class,"xsd:double");
085     java2Xml.put(double.class,"xsd:double");
086     java2Xml.put(Float.class,"xsd:float");
087     java2Xml.put(float.class,"xsd:float");
088     java2Xml.put(Integer.class,"xsd:integer");
089     java2Xml.put(int.class,"xsd:integer");
090     java2Xml.put(Short.class,"xsd:short");
091     java2Xml.put(short.class,"xsd:short");
092     java2Xml.put(String.class,"xsd:string");
093     java2Xml.put(URI.class,"xsd:anyURI");
094     java2Xml.put(Date.class,"xsd:dateTime");
095     java2Xml.put(QName.class,"xsd:QName");
096     java2Xml.put(Element.class,"xsd:element");
097     java2Xml.put(byte[].class,"xsd:base64Binary");
098     java2Xml.put(Long[].class,"qman:arrayOfLong");  
099     java2Xml.put(long[].class,"qman:arrayOfLong");
100     java2Xml.put(Boolean[].class,"qman:arrayOfBoolean");
101     java2Xml.put(boolean[].class,"qman:arrayOfBoolean");
102     java2Xml.put(Double[].class,"qman:arrayOfDouble");
103     java2Xml.put(double[].class,"qman:arrayOfDouble");
104     java2Xml.put(Float[].class,"qman:arrayOfFloat");
105     java2Xml.put(float[].class,"qman:arrayOfFloat");
106     java2Xml.put(Integer[].class,"qman:arrayOfInteger");
107     java2Xml.put(int[].class,"qman:arrayOfInteger");
108     java2Xml.put(Short[].class,"qman:arrayOfShort");
109     java2Xml.put(short[].class,"qman:arrayOfShort");
110     java2Xml.put(String[].class,"qman:arrayOfString");
111     java2Xml.put(URI[].class,"qman:arrayOfURI");
112     java2Xml.put(Date[].class,"qman:arrayOfDate");
113     java2Xml.put(Map.class,"qman:map");
114     java2Xml.put(HashMap.class,"qman:map");
115   }
116   
117   /**
118    * Converts the incoming element into the appropriate Java type.
119    * The method will fail if :
120    
121    <br>1) The element has no xsi:type attribute;
122    <br>2) The xsi:type attribute has no corresponding java type on this serializer mappings.
123    
124    @param elementData the xml element containing data to be unmarshalled.l
125    @return the java object as result of xml element unmarshalling.
126    @throws SoapFault when the marshalling fails.
127    */
128   public Object fromXML(Element elementDatathrows SoapFault
129   {
130     Attr typeAttribute = elementData.getAttributeNodeNS(
131         XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, 
132         Names.TYPE);
133     
134     if (typeAttribute == null)
135     {
136       throw new SoapFault(
137         "No type attribute was found for the current element. " +
138         "If you are using this serializer, in order to unmarshal the" +
139         " opportune type the xsi:type must be specified.");
140     }
141     
142     Class<?> clazz = xml2Java.get(typeAttribute.getValue());
143     
144     if (clazz == null)
145     {
146       throw new SoapFault(
147           String.format(
148               "No corresponding class was found on this serializer mappings for xsi:type %s.",
149               typeAttribute));
150     }
151     
152     if (clazz == byte[].class) {
153       return new ByteArraySerializer().fromXML(elementData);
154     }
155     
156     return SerializerRegistry.getInstance().getSerializer(clazz).fromXML(elementData);
157   }
158 
159   /**
160    * As this serializer is supposed to deal with generic object types, this method returns Object.class.
161    
162    @return Object.class
163    */
164   public Class<?> getSerializableType() 
165   {
166     return Object.class;
167   }
168 
169   /**
170    * Converts the given object (with the given qname) in XML format.
171    * This method fails if there's no corresponding xml type for the given runtime type of the input object.
172    
173    @param obj the object to be marshalled.
174    @param qname the qualified name that will be used in encoding.
175    */
176   public Element toXML(Object obj, QName qnamethrows SoapFault 
177   {
178     Class<?> clazz = obj.getClass();    
179 
180     Element result = null;
181     
182     if (clazz == byte[].class) {
183       result = new ByteArraySerializer().toXML(obj,qname);
184     
185     else {
186       result = SerializerRegistry.getInstance().getSerializer(clazz).toXML(obj,qname);
187     }
188     result.setAttribute(Names.XSI_TYPE, java2Xml.get(clazz));
189     return result;
190   }
191   
192   /**
193    * Returns the xml type associated with the given class. 
194    
195    @param clazz the class.
196    @return the xml type associated with the given class.
197    */
198   public String getXmlType(Class<?> clazz
199   {
200     return java2Xml.get(clazz);
201   }
202 }