Package org.freezedry.persistence.writers

Source Code of org.freezedry.persistence.writers.XmlWriter

/*
* Copyright 2012 Robert Philipp
*
*  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.freezedry.persistence.writers;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;
import org.freezedry.persistence.PersistenceEngine;
import org.freezedry.persistence.tree.InfoNode;
import org.freezedry.persistence.utils.Constants;
import org.freezedry.persistence.utils.DomUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
* Writes an the semantic model (starting at the {@link InfoNode} root node) to an XML file through
* the use of the DOM tree.
*
* @author Robert Philipp
*/
public class XmlWriter implements PersistenceWriter {
 
  private static final Logger LOGGER = Logger.getLogger( XmlWriter.class );
 
  public static final String TYPE_ATTRIBUTE = "type";
 
  private boolean isDisplayTypeInfo = false;
   
  /**
   * @return true if type information is written to the XML file
   */
  public boolean getDisplayTypeInfo()
  {
    return isDisplayTypeInfo;
  }
 
  /**
   * Set whether to display type info as an attribute in the XML
   * @param isDisplay set to true to have the type info displayed as an attribute
   */
  public void setDisplayTypeInfo( final boolean isDisplay )
  {
    isDisplayTypeInfo = isDisplay;
  }
 
  /**
   * Writes the DOM tree to XML
   * @param rootNode The root {@link InfoNode} of the semantic model
   * @throws ParserConfigurationException
   */
  public void write( final InfoNode rootNode, final Writer output )
  {
    final Document document = buildDom( rootNode );
    if( LOGGER.isInfoEnabled() )
    {
      LOGGER.info( DomUtils.toString( document ) );
    }
   
    // use a Transformer to write the output xml
    final TransformerFactory factory = TransformerFactory.newInstance();
    try
    {
      final DOMSource source = new DOMSource( document );
      final StreamResult result = new StreamResult( output );
     
      final Transformer transformer = factory.newTransformer();
      transformer.transform( source, result );
    }
    catch( TransformerException e )
    {
      throw new IllegalStateException( "Unable to transform the DOM tree to XML.", e );
    }
  }
 
  /**
   * Builds the DOM tree from the info node tree through recursive algorithm.
   * @param rootInfoNode The root {@link InfoNode}
   * @return The DOM tree as a {@link Document}
   */
  private Document buildDom( final InfoNode rootInfoNode )
  {
    // create the document-builder factory, from which to create the document-builder,
    // from which to create the document, which is the root node into which the new
    // DOM tree will be built.
    final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = null;
    try
    {
      builder = factory.newDocumentBuilder();
    }
    catch( ParserConfigurationException e )
    {
      final StringBuffer message = new StringBuffer();
      message.append( "Unable to create the DOM document builder:" + Constants.NEW_LINE );
      message.append( "  Root Persistence Name: " + rootInfoNode.getPersistName() );
      LOGGER.error( message.toString() );
      throw new IllegalStateException( message.toString(), e );
    }
    final Document document = builder.newDocument();
   
    // create the first DOM node from the info-node and add it to the document
    final Node domNode = createDomNode( rootInfoNode, document, document );
   
    // recursively build the DOM tree from the info-node tree
    buildDom( rootInfoNode, domNode, document );
   
    // once complete, then return the document (root node of the DOM tree)
    return document;
  }

  /*
   * Recurses through the {@link InfoNode} tree and builds the DOM {@link Node} tree.
   * @param infoNode The {@link InfoNode} from which to build the domNode
   * @param domNode The DOM {@link Node} to which to add the new DOM {@link Node}s
   * @param document The root node of the DOM tree (which is a {@link Document})
   */
  private void buildDom( final InfoNode infoNode, final Node domNode, final Document document )
  {
    final List< InfoNode > children = infoNode.getChildren();
    for( InfoNode child : children )
    {
      final Node newDomNode = createDomNode( child, domNode, document );
      domNode.appendChild( newDomNode );
     
      buildDom( child, newDomNode, document );
    }
  }

  /*
   * Creates a DOM node from the {@link InfoNode}.
   * @param infoNode The {@link InfoNode} from which to build the domNode
   * @param domNode The DOM {@link Node} to which to add the new DOM {@link Node}s
   * @param document The root node of the DOM tree (which is a {@link Document})
   * @return The DOM node representation of the {@link InfoNode}
   */
  private Node createDomNode( final InfoNode infoNode, final Node domNode, final Document document )
  {
    final Element newDomNode = document.createElement( infoNode.getPersistName() );
   
    // set the type of the node
    if( isDisplayTypeInfo )
    {
      newDomNode.setAttribute( TYPE_ATTRIBUTE, infoNode.getClazz().getName() );
    }

    // add the node the parent
    domNode.appendChild( newDomNode );

    // if the node is a leaf node, then it has a value, and we need to
    // add a DOM text node that holds the value
    if( infoNode.isLeafNode() )
    {
      final Object value = infoNode.getValue();
      final Node textNode = document.createTextNode( value.toString() );
      newDomNode.appendChild( textNode );
    }
   
    return newDomNode;
  }

  /**
   * For testing
   * @param args
   * @throws ParserConfigurationException
   * @throws ReflectiveOperationException
   * @throws IOException
   */
  public static void main( String[] args ) throws ParserConfigurationException, ReflectiveOperationException, IOException
  {
    DOMConfigurator.configure( "log4j.xml" );

//    final Division division = new Division();
//    final PersistenceEngine engine = new PersistenceEngine();
//    final InfoNode rootNode = engine.createSemanticModel( division );
//    System.out.println( rootNode.treeToString() );
//
//    try( final PrintWriter printWriter = new PrintWriter( new FileWriter( "person.xml" ) ) )
//    {
//      final XmlWriter writer = new XmlWriter();
//      // uncomment this to prevent type information to be written to XML
////      writer.setDisplayTypeInfo( false );
//      writer.write( rootNode, printWriter );
//    }
//    catch( IOException e )
//    {
//      e.printStackTrace();
//    }
   
//    final int[] test = new int[] { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3 };
    final int[][] test = new int[][] { { 3, 1 }, { 4, 1 }, { 5, 9 }, { 2, 6 }, { 5, 3 } };
    final PersistenceEngine engine = new PersistenceEngine();
    final InfoNode rootNode = engine.createSemanticModel( test );
    System.out.println( rootNode.treeToString() );

    try( final PrintWriter printWriter = new PrintWriter( new FileWriter( "test.xml" ) ) )
    {
      final XmlWriter writer = new XmlWriter();
      // uncomment this to prevent type information to be written to XML
//      writer.setDisplayTypeInfo( true );
      writer.write( rootNode, printWriter );
    }
    catch( IOException e )
    {
      e.printStackTrace();
    }
  }
}
TOP

Related Classes of org.freezedry.persistence.writers.XmlWriter

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.