Package com.skaringa.javaxml.impl

Source Code of com.skaringa.javaxml.impl.ObjectTransformerImpl

package com.skaringa.javaxml.impl;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import com.skaringa.javaxml.DeserializerException;
import com.skaringa.javaxml.NoImplementationException;
import com.skaringa.javaxml.ObjectTransformer;
import com.skaringa.javaxml.SerializerException;
import com.skaringa.javaxml.handler.sax.AbstractXMLReader;
import com.skaringa.javaxml.handler.sax.DocumentInputHandler;
import com.skaringa.javaxml.handler.sax.ObjectInputSource;
import com.skaringa.javaxml.handler.sax.ObjectXMLReader;
import com.skaringa.javaxml.handler.sax.ObjectXSDReader;
import com.skaringa.javaxml.handler.sax.SAXInputHandler;
import com.skaringa.javaxml.serializers.ComponentSerializer;
import com.skaringa.javaxml.serializers.SerializerRegistry;
import com.skaringa.json.parser.JsonParser;
import com.skaringa.util.Log;

/**
* Implementation of ObjectTransformer. This implementation uses SAX events to
* parse and generate the XML documents.
*/
public final class ObjectTransformerImpl implements ObjectTransformer {

  private SAXTransformerFactory _saxTransFact;

  /**
   * A pre-processed stylesheet for XML-preprocessing Creating new transformers
   * from this object is fast because the stylesheet is already parsed and
   * processed into the transformer's internal model.
   */
  private Templates _preProcessorTemplate;

  /**
   * A pre-processed stylesheet for object transformation.
   */
  private Templates _postProcessorTemplate;

  private Map _properties = new HashMap();
  private ClassLoader _classLoader = getClass().getClassLoader();

  /**
   * Construct a new Implementation of an ObjectTransformer
   *
   * @throws NoImplementationException
   *           If the underlying XML Transformer doesn't support SAXTransformer.
   */
  public ObjectTransformerImpl() throws NoImplementationException {
    TransformerFactory transFact = TransformerFactory.newInstance();
    if (transFact.getFeature(SAXTransformerFactory.FEATURE)) {
      _saxTransFact = (SAXTransformerFactory) transFact;
    } else {
      Log.error("SAXTransformerFactory is not supported.");
      throw new NoImplementationException(
          "SAXTransformerFactory is not supported.");
    }
  }

  /**
   * @see ObjectTransformer#serialize(Object, Result)
   */
  public void serialize(Object obj, Result result) throws SerializerException {

    Log.info("serialize - start "
        + (obj != null ? obj.getClass().getName() : "null"));

    transform(getTransformerHandler(_postProcessorTemplate), obj,
        new ObjectXMLReader(), result);

    Log.info("serialize - end "
        + (obj != null ? obj.getClass().getName() : "null"));
  }

  /**
   * @see ObjectTransformer#serializeToString(Object)
   */
  public String serializeToString(Object obj) throws SerializerException {
    StringWriter out = new StringWriter();
    serialize(obj, new StreamResult(out));

    return out.toString();
  }

  /**
   * @see ObjectTransformer#deserialize(Source)
   */
  public Object deserialize(Source src) throws DeserializerException {

    Object obj;

    Log.info("deserialize - start ...");
    try {
      Transformer transformer;
      if (_preProcessorTemplate != null) {
        // use a preprocessor if one is given
        transformer = _preProcessorTemplate.newTransformer();
      } else {
        transformer = _saxTransFact.newTransformer();
      }
      DocumentInputHandler inputHandler = new DocumentInputHandler();
      inputHandler.setProperties(_properties);
      inputHandler.setClassLoader(_classLoader);
      transformer.transform(src, newObjectResult(inputHandler));

      obj = inputHandler.getObject();
    } catch (TransformerConfigurationException e) {
      Log.error(e);
      throw new DeserializerException(e.toString());
    } catch (TransformerException e) {
      Log.error(e);
      Throwable emb = e.getException();
      if (emb instanceof DeserializerException) {
        throw (DeserializerException) emb;
      }
      throw new DeserializerException(e.getMessage());
    }

    Log.info("deserialize - end "
        + (obj != null ? obj.getClass().getName() : "null"));
    return obj;
  }

  /**
   * @see ObjectTransformer#deserializeFromString(String)
   */
  public Object deserializeFromString(String s) throws DeserializerException {
    StringReader in = new StringReader(s);
    Object obj = deserialize(new StreamSource(in));

    return obj;
  }

  /**
   * @see ObjectTransformer#writeXMLSchema(Class, Result)
   */
  public void writeXMLSchema(Class type, Result result)
      throws SerializerException {

    Log.info("writeXMLSchema - start "
        + (type != null ? type.getName() : "null"));

    transform(getCopyTransformerHandler(), type, new ObjectXSDReader(), result);

    Log
        .info("writeXMLSchema - end "
            + (type != null ? type.getName() : "null"));
  }

  /**
   * @see ObjectTransformer#writeXMLSchema(Class, Collection, Result)
   */
  public void writeXMLSchema(Class type, Collection componentTypes,
      Result result) throws SerializerException {

    Log.info("writeXMLSchema - start "
        + (type != null ? type.getName() : "null"));

    ObjectXSDReader xsdReader = new ObjectXSDReader();
    xsdReader.addUsedClasses(componentTypes);

    transform(getCopyTransformerHandler(), type, xsdReader, result);

    Log
        .info("writeXMLSchema - end "
            + (type != null ? type.getName() : "null"));
  }

  /**
   * @see ObjectTransformer#transform(Object, Source)
   * @deprecated
   */
  public Object transform(Object obj, Source transformationInstruction)
      throws SerializerException, DeserializerException {

    Log.info("transform - start "
        + (obj != null ? obj.getClass().getName() : "null"));

    DocumentInputHandler inputHandler = new DocumentInputHandler();
    inputHandler.setProperties(_properties);
    inputHandler.setClassLoader(_classLoader);
    transform(getTransformerHandler(transformationInstruction), obj,
        new ObjectXMLReader(), newObjectResult(inputHandler));

    Log.info("transform - end "
        + (obj != null ? obj.getClass().getName() : "null"));

    return inputHandler.getObject();
  }

  /**
   * @see ObjectTransformer#transform(Object)
   */
  public Object transform(Object obj) throws SerializerException,
      DeserializerException {

    Log.info("transform - start "
        + (obj != null ? obj.getClass().getName() : "null"));

    DocumentInputHandler inputHandler = new DocumentInputHandler();
    inputHandler.setProperties(_properties);
    inputHandler.setClassLoader(_classLoader);
    transform(getTransformerHandler(_postProcessorTemplate), obj,
        new ObjectXMLReader(), newObjectResult(inputHandler));

    Log.info("transform - end "
        + (obj != null ? obj.getClass().getName() : "null"));

    return inputHandler.getObject();
  }

  /**
   * @see ObjectTransformer#transform(Object, Source, Result)
   * @deprecated
   */
  public void transform(Object obj, Source transformationInstruction,
      Result result) throws SerializerException {

    transform(getTransformerHandler(transformationInstruction), obj,
        new ObjectXMLReader(), result);
  }

  /**
   * @see ObjectTransformer#setProperty(String, Object)
   */
  public void setProperty(String name, Object value) {
    _properties.put(name, value);
  }

  /**
   * @see com.skaringa.javaxml.ObjectTransformer#setClassLoader(java.lang.ClassLoader)
   */
  public void setClassLoader(ClassLoader classLoader) {
    _classLoader = classLoader;
  }

  /**
   * Obtain a transformer handler for a source of transformation instructions.
   *
   * @param transformationInstruction
   *          The source of trafo instructions.
   * @return The transformer handler.
   * @throws SerializerException
   *           If the transformer can't be created.
   */
  private TransformerHandler getTransformerHandler(
      Source transformationInstruction) throws SerializerException {

    TransformerHandler transHand;

    try {
      if (transformationInstruction != null) {
        // if transformation instructions are given explicitely, then use them.
        transHand = _saxTransFact
            .newTransformerHandler(transformationInstruction);
      } else {
        // otherwise use an empty stylesheet (copy transformation)
        transHand = _saxTransFact.newTransformerHandler();
      }

      return transHand;
    } catch (TransformerConfigurationException e) {
      Log.error(e);
      throw new SerializerException(e.getMessage());
    }
  }

  /**
   * Obtain a transformer handler for a pre-parsed transformer template.
   *
   * @param template
   *          The pre-parsed transformer template.
   * @return The transformer handler.
   * @throws SerializerException
   *           If the transformer can't be created.
   */
  private TransformerHandler getTransformerHandler(Templates template)
      throws SerializerException {

    TransformerHandler transHand;

    try {
      if (template != null) {
        // use a template if one is given
        transHand = _saxTransFact.newTransformerHandler(template);
      } else {
        // otherwise use an empty stylesheet (copy transformation)
        transHand = _saxTransFact.newTransformerHandler();
      }

      return transHand;
    } catch (TransformerConfigurationException e) {
      Log.error(e);
      throw new SerializerException(e.getMessage());
    }
  }

  /**
   * Obtain a transformer handler for a copy transformation (empty stylesheet).
   *
   * @return The transformer handler.
   * @throws SerializerException
   *           If the transformer can't be created.
   */
  private TransformerHandler getCopyTransformerHandler()
      throws SerializerException {

    try {
      return _saxTransFact.newTransformerHandler();
    } catch (TransformerConfigurationException e) {
      Log.error(e);
      throw new SerializerException(e.getMessage());
    }
  }

  /**
   * Transform a Java object into a XML Result.
   *
   * @param transHand
   *          The transformer handler.
   * @param obj
   *          The object to transform.
   * @param objReader
   *          The reader which is used to evaluate ("parse") the Java object.
   * @param result
   *          The result of the transformation.
   * @throws SerializerException
   *           If the transformation failes.
   */
  private void transform(TransformerHandler transHand, Object obj,
      AbstractXMLReader objReader, Result result) throws SerializerException {

    try {
      // set properties of the Transformer
      Transformer transformer = transHand.getTransformer();
      transformer.setOutputProperty(OutputKeys.METHOD, "xml");

      // set the destination for the XSLT transformation
      transHand.setResult(result);

      // pass the properties to the XSL transformer or to the XMLReader
      setProperties(transformer, objReader);

      // attach the XSLT processor to the XMLReader
      objReader.setContentHandler(transHand);
      // parse and transform
      objReader.parse(new ObjectInputSource(obj));
    } catch (IOException e) {
      Log.error(e);
      throw new SerializerException(e.getMessage());
    } catch (org.xml.sax.SAXException e) {
      Log.error(e);
      Exception emb = e.getException();
      if (emb instanceof SerializerException) {
        throw (SerializerException) emb;
      }
      throw new SerializerException(e.getMessage());
    }
  }

  /**
   * Pass the properties to the XSL transformer or to the XML reader. All
   * properties that are not valid for the XML reader are passed to the
   * underlying XSL transformer.
   *
   * @param transformer
   *          The XSL transformer.
   * @param objReader
   *          The XML reader.
   * @throws org.xml.sax.SAXNotRecognizedException
   *           When the XMLReader does not recognize the property name.
   * @throws org.xml.sax.SAXNotSupportedException
   *           When the XMLReader recognizes the property name but cannot set
   *           the requested value.
   */
  private void setProperties(Transformer transformer,
      AbstractXMLReader objReader)
      throws org.xml.sax.SAXNotRecognizedException,
      org.xml.sax.SAXNotSupportedException {
    Iterator it = _properties.entrySet().iterator();
    while (it.hasNext()) {
      Map.Entry entry = (Map.Entry) it.next();
      String name = (String) entry.getKey();
      Object value = entry.getValue();
      if (PropertyHelper.isValidNameForObjectTransformer(name)) {
        objReader.setProperty(name, value);
      } else {
        transformer.setOutputProperty(name, (String) value);
      }
    }
  }

  /**
   * Create a new SAXResult which is assoziated with a DocumentInputHandler.
   *
   * @param inputHandler
   *          The document input handler which can construct a new Java object
   *          from SAX envents.
   * @return A SAXResult that geta events from a SAX parser and forwards them to
   *         the inputHandler.
   */
  private Result newObjectResult(DocumentInputHandler inputHandler) {

    SAXInputHandler saxHandler = new SAXInputHandler(inputHandler);
    return new SAXResult(saxHandler);
  }

  /**
   * @see ObjectTransformer#setPreprocessorInstruction(Source)
   */
  public void setPreprocessorInstruction(Source transformationInstruction)
      throws NoImplementationException {
    try {
      _preProcessorTemplate = _saxTransFact
          .newTemplates(transformationInstruction);
    } catch (TransformerConfigurationException e) {
      Log.error(e);
      throw new NoImplementationException(e.getMessage());
    }
  }

  /**
   * @see ObjectTransformer#setPostprocessorInstruction(Source)
   */
  public void setPostprocessorInstruction(Source transformationInstruction)
      throws NoImplementationException {
    try {
      _postProcessorTemplate = _saxTransFact
          .newTemplates(transformationInstruction);
    } catch (TransformerConfigurationException e) {
      Log.error(e);
      throw new NoImplementationException(e.getMessage());
    }
  }

  /**
   * @see ObjectTransformer#serializeToJson(Object, OutputStream)
   */
  public void serializeToJson(Object obj, OutputStream stream)
      throws SerializerException {
    Log.info("toJson - start "
        + (obj != null ? obj.getClass().getName() : "null"));

    Class type = Object.class;
    if (obj != null) {
      type = obj.getClass();
    }

    ComponentSerializer ser = SerializerRegistry.getInstance().getSerializer(
        type);

    PrintStream output;
    try {
      output = new PrintStream(new BufferedOutputStream(stream), false, "UTF-8");
    } catch (UnsupportedEncodingException e) {
      throw new RuntimeException(e); // UTF-8 should always be supported
    }

    ser.toJson(obj, type, _properties, output);

    output.flush();
    Log.info("toJson - end "
        + (obj != null ? obj.getClass().getName() : "null"));
  }

  /**
   * @see ObjectTransformer#serializeToJsonString(Object)
   */
  public String serializeToJsonString(Object obj) throws SerializerException {
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    serializeToJson(obj, stream);
    try {
      return stream.toString("UTF-8");
    } catch (UnsupportedEncodingException e) {
      throw new RuntimeException(e); // UTF-8 should always be supported
    }
  }

  /**
   * @see com.skaringa.javaxml.ObjectTransformer#deserializeFromJson(InputStream, Class)
   */
  public Object deserializeFromJson(InputStream stream, Class rootType)
      throws DeserializerException {

    try {
      Reader reader = new InputStreamReader(new BufferedInputStream(stream), "UTF-8");
      JsonParser parser = new JsonParser(reader, rootType, _properties, _classLoader);
      parser.process();
      return parser.getObject();
    } catch (IOException e) {
      Log.error(e);
      throw new DeserializerException(e.getMessage());
    }
  }

  /**
   * @see com.skaringa.javaxml.ObjectTransformer#deserializeFromJsonString(java.lang.String,
   *      java.lang.Class)
   */
  public Object deserializeFromJsonString(String s, Class rootType)
      throws DeserializerException {
    try {
      Reader reader = new StringReader(s);
      JsonParser parser = new JsonParser(reader, rootType, _properties, _classLoader);
      parser.process();
      return parser.getObject();
    } catch (IOException e) {
      Log.error(e);
      throw new DeserializerException(e.getMessage());
    }
  }

  /**
   * @see com.skaringa.javaxml.ObjectTransformer#deserializeFromJson(java.io.InputStream)
   */
  public Object deserializeFromJson(InputStream stream)
      throws DeserializerException {
    return deserializeFromJson(stream, null);
  }

  /**
   * @see com.skaringa.javaxml.ObjectTransformer#deserializeFromJsonString(java.lang.String)
   */
  public Object deserializeFromJsonString(String s)
      throws DeserializerException {
    return deserializeFromJsonString(s, null);
  }

}
TOP

Related Classes of com.skaringa.javaxml.impl.ObjectTransformerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.