Java tutorial
/** * Copyright Microsoft Open Technologies, Inc. * * All Rights Reserved * * 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 * * THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION * ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A * PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT. * * See the Apache License, Version 2.0 for the specific language * governing permissions and limitations under the License. */ package com.msopentech.odatajclient.engine.data; import com.fasterxml.aalto.stax.InputFactoryImpl; import com.fasterxml.aalto.stax.OutputFactoryImpl; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler; import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule; import com.fasterxml.jackson.dataformat.xml.XmlFactory; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.msopentech.odatajclient.engine.data.atom.AtomDeserializer; import com.msopentech.odatajclient.engine.data.atom.AtomEntry; import com.msopentech.odatajclient.engine.data.atom.AtomFeed; import com.msopentech.odatajclient.engine.data.json.JSONEntry; import com.msopentech.odatajclient.engine.data.json.JSONFeed; import com.msopentech.odatajclient.engine.data.json.JSONLinkCollection; import com.msopentech.odatajclient.engine.data.json.JSONProperty; import com.msopentech.odatajclient.engine.data.json.JSONServiceDocument; import com.msopentech.odatajclient.engine.data.json.error.JSONODataError; import com.msopentech.odatajclient.engine.data.json.error.JSONODataErrorBundle; import com.msopentech.odatajclient.engine.data.metadata.edm.AbstractAnnotatedEdm; import com.msopentech.odatajclient.engine.data.metadata.edm.AbstractAnnotatedEdmUtils; import com.msopentech.odatajclient.engine.data.metadata.edm.Edmx; import com.msopentech.odatajclient.engine.data.xml.XMLLinkCollection; import com.msopentech.odatajclient.engine.data.xml.XMLServiceDocument; import com.msopentech.odatajclient.engine.data.xml.XMLODataError; import com.msopentech.odatajclient.engine.format.ODataFormat; import com.msopentech.odatajclient.engine.utils.ODataConstants; import com.msopentech.odatajclient.engine.utils.XMLUtils; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.util.ArrayList; import java.util.List; import org.w3c.dom.Element; import org.w3c.dom.NodeList; /** * Utility class for serialization. */ public final class Deserializer { private Deserializer() { // Empty private constructor for static utility classes } public static Edmx toMetadata(final InputStream input) { try { final XmlMapper xmlMapper = new XmlMapper( new XmlFactory(new InputFactoryImpl(), new OutputFactoryImpl()), new JacksonXmlModule()); xmlMapper.addHandler(new DeserializationProblemHandler() { @Override public boolean handleUnknownProperty(final DeserializationContext ctxt, final JsonParser jp, final JsonDeserializer<?> deserializer, final Object beanOrClass, final String propertyName) throws IOException, JsonProcessingException { // 1. special handling of AbstractAnnotatedEdm's fields if (beanOrClass instanceof AbstractAnnotatedEdm && AbstractAnnotatedEdmUtils.isAbstractAnnotatedProperty(propertyName)) { AbstractAnnotatedEdmUtils.parseAnnotatedEdm((AbstractAnnotatedEdm) beanOrClass, jp); } // 2. skip any other unknown property else { ctxt.getParser().skipChildren(); } return true; } }); return xmlMapper.readValue(input, Edmx.class); } catch (Exception e) { throw new IllegalArgumentException("Could not parse as Edmx document", e); } } /** * Gets a feed object from the given InputStream. * * @param <T> reference class type * @param input stream to be de-serialized. * @param reference reference class (AtomFeed.class, JSONFeed.class). * @return FeedResource instance. */ @SuppressWarnings("unchecked") public static <T extends FeedResource> T toFeed(final InputStream input, final Class<T> reference) { T entry; if (AtomFeed.class.equals(reference)) { entry = (T) toAtomFeed(input); } else { entry = (T) toJSONFeed(input); } return entry; } /** * Gets an entry object from the given InputStream. * * @param <T> reference class type * @param input stream to be de-serialized. * @param reference reference class (AtomEntry.class, JSONEntry.class). * @return EntryResource instance. */ @SuppressWarnings("unchecked") public static <T extends EntryResource> T toEntry(final InputStream input, final Class<T> reference) { T entry; if (AtomEntry.class.equals(reference)) { entry = (T) toAtomEntry(input); } else { entry = (T) toJSONEntry(input); } return entry; } /** * Gets a DOM representation of the given InputStream. * * @param input stream to be de-serialized. * @param format OData format. * @return DOM. */ public static Element toPropertyDOM(final InputStream input, final ODataFormat format) { return format == ODataFormat.XML ? toPropertyDOMFromXML(input) : toPropertyDOMFromJSON(input); } /** * Gets the ServiceDocumentResource object represented by the given InputStream. * * @param input stream to be de-serialized. * @param format OData service document format. * @return ServiceDocumentResource object. */ public static ServiceDocumentResource toServiceDocument(final InputStream input, final ODataFormat format) { return format == ODataFormat.XML ? toServiceDocumentFromXML(input) : toServiceDocumentFromJSON(input); } /** * Gets a list of links from the given InputStream. * * @param input stream to be de-serialized. * @param format OData format. * @return de-serialized links. */ public static LinkCollectionResource toLinkCollection(final InputStream input, final ODataFormat format) { return format == ODataFormat.XML ? toLinkCollectionFromXML(input) : toLinkCollectionFromJSON(input); } /** * Gets the ODataError object represented by the given InputStream. * * @param input stream to be parsed and de-serialized. * @param isXML 'TRUE' if the error is represented by XML; 'FALSE' otherwise. * @return */ public static ODataError toODataError(final InputStream input, final boolean isXML) { return isXML ? toODataErrorFromXML(input) : toODataErrorFromJSON(input); } /** * Parses the given input into a DOM tree. * * @param input stream to be parsed and de-serialized. * @return DOM tree */ public static Element toDOM(final InputStream input) { return XMLUtils.PARSER.parse(input); } /* * ------------------ Private methods ------------------ */ @SuppressWarnings("unchecked") private static AtomFeed toAtomFeed(final InputStream input) { try { return AtomDeserializer.feed(toDOM(input)); } catch (Exception e) { throw new IllegalArgumentException("While deserializing Atom feed", e); } } @SuppressWarnings("unchecked") private static AtomEntry toAtomEntry(final InputStream input) { try { return AtomDeserializer.entry(toDOM(input)); } catch (Exception e) { throw new IllegalArgumentException("While deserializing Atom entry", e); } } private static JSONFeed toJSONFeed(final InputStream input) { try { final ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL); return mapper.readValue(input, JSONFeed.class); } catch (IOException e) { throw new IllegalArgumentException("While deserializing JSON feed", e); } } private static JSONEntry toJSONEntry(final InputStream input) { try { final ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL); return mapper.readValue(input, JSONEntry.class); } catch (IOException e) { throw new IllegalArgumentException("While deserializing JSON entry", e); } } private static Element toPropertyDOMFromXML(final InputStream input) { return toDOM(input); } private static Element toPropertyDOMFromJSON(final InputStream input) { try { final ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL); return mapper.readValue(input, JSONProperty.class).getContent(); } catch (IOException e) { throw new IllegalArgumentException("While deserializing JSON property", e); } } private static ServiceDocumentResource toServiceDocumentFromXML(final InputStream input) { final Element service = toDOM(input); final XMLServiceDocument serviceDoc = new XMLServiceDocument(); serviceDoc.setBaseURI(URI.create(service.getAttribute(ODataConstants.ATTR_XMLBASE))); final NodeList collections = service.getElementsByTagName(ODataConstants.ELEM_COLLECTION); for (int i = 0; i < collections.getLength(); i++) { final Element collection = (Element) collections.item(i); final NodeList title = collection.getElementsByTagName(ODataConstants.ATOM_ATTR_TITLE); if (title.getLength() != 1) { throw new IllegalArgumentException("Invalid collection element found"); } serviceDoc.addToplevelEntitySet(title.item(0).getTextContent(), collection.getAttribute(ODataConstants.ATTR_HREF)); } return serviceDoc; } private static ServiceDocumentResource toServiceDocumentFromJSON(final InputStream input) { try { final ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL); return mapper.readValue(input, JSONServiceDocument.class); } catch (IOException e) { throw new IllegalArgumentException("While deserializing JSON service document", e); } } private static XMLLinkCollection toLinkCollectionFromXML(final InputStream input) { final Element root = toDOM(input); final NodeList uris = root.getOwnerDocument().getElementsByTagName(ODataConstants.ELEM_URI); final List<URI> links = new ArrayList<URI>(); for (int i = 0; i < uris.getLength(); i++) { links.add(URI.create(uris.item(i).getTextContent())); } final NodeList next = root.getElementsByTagName(ODataConstants.NEXT_LINK_REL); final XMLLinkCollection linkCollection = next.getLength() > 0 ? new XMLLinkCollection(URI.create(next.item(0).getTextContent())) : new XMLLinkCollection(); linkCollection.setLinks(links); return linkCollection; } private static JSONLinkCollection toLinkCollectionFromJSON(final InputStream input) { try { final ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL); return mapper.readValue(input, JSONLinkCollection.class); } catch (IOException e) { throw new IllegalArgumentException("While deserializing JSON $links", e); } } private static XMLODataError toODataErrorFromXML(final InputStream input) { try { final XmlMapper xmlMapper = new XmlMapper( new XmlFactory(new InputFactoryImpl(), new OutputFactoryImpl()), new JacksonXmlModule()); return xmlMapper.readValue(input, XMLODataError.class); } catch (Exception e) { throw new IllegalArgumentException("While deserializing XML error", e); } } private static JSONODataError toODataErrorFromJSON(final InputStream input) { try { final ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL); return mapper.readValue(input, JSONODataErrorBundle.class).getError(); } catch (IOException e) { throw new IllegalArgumentException("While deserializing JSON error", e); } } }