Package com.kellerkindt.scs.storage

Source Code of com.kellerkindt.scs.storage.SAXStorageParser

/**
* ShowCaseStandalone
* Copyright (C) 2012 Kellerkindt <copyright at kellerkindt.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.kellerkindt.scs.storage;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.lang.Validate;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;

import com.kellerkindt.scs.internals.Storage;
import com.kellerkindt.scs.utilities.Utilities;


public class SAXStorageParser implements ContentHandler{
  private static final String elementAttrType      = "type";
  private static final String elementAttrTypeString  = "string";
  private static final String elementAttrTypeDouble  = "double";
  private static final String elementAttrTypeInteger  = "integer";
  private static final String elementAttrTypeBoolean  = "boolean";
  private static final String elementAttrTypeStorage  = "storage";
  private static final String elementAttrTypeList    = "list";
  private static final String elementAttrTypeEntry  = "entry";
 
  private static final String elementAttrStrgVersion  = "version";
  private static final String elementAttrStrgUUID    = "uuid";

  private static final String defaultEncoding      = "UTF-8";
 
  private XMLOutputFactory        factory;
  private Transformer            transformer;
  private String              encoding  = defaultEncoding;

  private List<HashMap<String, String>>  elementAttributes  = new ArrayList<HashMap<String, String>>();
  private List<StringBuilder>        elementContents    = new ArrayList<StringBuilder>();
  private List<Storage>          elementStorages    = new ArrayList<Storage>();
  private HashMap<Integer, List<?>>    elementLists    = new HashMap<Integer, List<?>>();
  private int                currentIsNoStorage  = 0// == 0 if it is a storage

  public SAXStorageParser () throws TransformerConfigurationException, TransformerFactoryConfigurationError {
    this.factory    = XMLOutputFactory.newFactory();
    this.transformer  = SAXTransformerFactory.newInstance().newTransformer();

  }
 
  /**
   * Sets a OuputProperty for the Transformer
   * @param key
   * @param value
   */
  public void setTransformerOutputProperty (String key, String value) {
    if (OutputKeys.ENCODING.equals(key))
      encoding = value;
   
    transformer.setOutputProperty(key, value);
  }
 
  /**
   * Saves a Storage to the given destination
   * @param storage     Storage to save
   * @param destination  Destination where the Storage should be saved to
   * @throws IOException
   * @throws XMLStreamException
   * @throws TransformerException
   */
  public void saveStorage (Storage storage, String name, File destination) throws IOException, XMLStreamException, TransformerException {
   
    // prepare streams for writer
    ByteArrayOutputStream  baos    = new ByteArrayOutputStream ();
    FileOutputStream    fos      = new FileOutputStream (destination);
   
    // create writer
    XMLStreamWriter      writer    = factory.createXMLStreamWriter(baos, encoding);
   
    // write document
    writer.writeStartDocument();
    saveStorage(storage, name, writer);
    writer.writeEndDocument();
   
    // flush and close writer
    writer.flush();
    writer.close();

    // prepare for transformation
    ByteArrayInputStream  bais    = new ByteArrayInputStream (baos.toByteArray());
    Source          source    = new StreamSource(bais);
    StreamResult      result    = new StreamResult(fos);
   
    // transform
    transformer.transform(source, result);
   
    // not closed yet?
    if (fos != null) {
      // flush and close file
      fos.flush();
      fos.close();
    }
  }
 
  /**
   * @param object
   * @param name
   * @param writer
   * @throws XMLStreamException
   */
  private void writeListEntry(Object object, XMLStreamWriter writer) throws XMLStreamException {
    String name = null;
   
    if (object instanceof String) {
      name = elementAttrTypeString;
     
    } else if (object instanceof Double) {
      name = elementAttrTypeDouble;
     
    } else if (object instanceof Integer) {
      name = elementAttrTypeInteger;
     
    } else if (object instanceof Boolean) {
      name = elementAttrTypeBoolean;
    }
//    } else if (object instanceof Storage) {
//      name = elementAttrTypeStorage;
//    }
   
    Validate.notNull(name, "Couldn't find type of "+object);
   
    writer.writeStartElement(name);
    writer.writeAttribute(elementAttrType, elementAttrTypeEntry);
   
//    if (object instanceof Storage) {
//      // save the storage
//      saveStorage((Storage)object, elementAttrTypeEntry, writer);
//     
//    } else {
//      // save it "normally"
    writer.writeCharacters(""+object);
//    }
    writer.writeEndElement();
  }
 
  /**
   * Saves the storage to the given writer
   * @param storage  Storage to save
   * @param name    Name of the storage
   * @param writer  Writer to write to
   * @throws XMLStreamException
   */
  private void saveStorage(Storage storage, String name, XMLStreamWriter writer) throws XMLStreamException {
   
    // start of this storage
    writer.writeStartElement(name);
    writer.writeAttribute(elementAttrStrgUUID,     storage.getUUIDAsString());
    writer.writeAttribute(elementAttrStrgVersion, ""+storage.getVersion());
    writer.writeAttribute(elementAttrType,        elementAttrTypeStorage);
   
    // Strings
    for (String key : storage.getStringKeys()) {
      writer.writeStartElement(key);
      writer.writeAttribute(elementAttrType, elementAttrTypeString);
      writer.writeCharacters(storage.getString(key));
      writer.writeEndElement();
    }
   
    // Doubles
    for (String key : storage.getDoubleKeys()) {
      writer.writeStartElement(key);
      writer.writeAttribute(elementAttrType, elementAttrTypeDouble);
      writer.writeCharacters(""+storage.getDouble(key));
      writer.writeEndElement();
    }
   
    // Integers
    for (String key : storage.getIntegerKeys()) {
      writer.writeStartElement(key);
      writer.writeAttribute(elementAttrType, elementAttrTypeInteger);
      writer.writeCharacters(""+storage.getInteger(key));
      writer.writeEndElement();
    }
   
    // Booleans
    for (String key : storage.getBooleanKeys()) {
      writer.writeStartElement(key);
      writer.writeAttribute(elementAttrType, elementAttrTypeBoolean);
      writer.writeCharacters(""+storage.getBoolean(key));
      writer.writeEndElement();
    }
   
    // Storages
    for (String key : storage.getStorageKeys())
      saveStorage(storage.getStorage(key), key, writer);
   
    // lists
    for (String key : storage.getListKeys()) {
     
      List<?> list = storage.getList(key);
     
      if (list == null) {
        continue;
      }
     
      writer.writeStartElement(key);
      writer.writeAttribute(elementAttrType, elementAttrTypeList);
     
      System.out.println ("list: "+list);
     
      for (Object object : list) {
        System.out.println ("object: " + object);
        writeListEntry(object, writer);
      }
     
      writer.writeEndElement();
    }
   
    // end of this storage
    writer.writeEndElement();
    writer.flush();
  }
 
  /**
   * Loads a Storage from the given File
   * @param source  File to load from
   * @return Loaded Storage or null
   * @throws SAXException
   * @throws IOException
   */
  public Storage loadStorage (File source) throws SAXException, IOException {
   
    elementAttributes.clear();
    elementContents.clear();
    elementStorages.clear();
   
    XMLReader  reader  = XMLReaderFactory.createXMLReader();
   
   
//    FileReader  fReader  = new FileReader  (source);
    FileInputStream  fis    = new FileInputStream(source);
    InputSource    iSource  = new InputSource  (fis);
   
//    iSource.setEncoding(encoding);
   
    reader.setContentHandler(this);
    reader.parse(iSource);
   
//    fReader.close();
    fis.close();
   
    if (elementStorages.size() > 0)
      return elementStorages.get(0)// return the last
    else
      return null;
  }
 
//  For testing
//  public static void main (String args[]) throws Exception {
//    SAXStorageParser parser  = new SAXStorageParser();
//   
//    parser.setTransformerOutputProperty(OutputKeys.ENCODING,               "UTF-8");
//    parser.setTransformerOutputProperty(OutputKeys.INDENT,                 "yes");
//    parser.setTransformerOutputProperty("{http://xml.apache.org/xslt}indent-amount",   "4");
//   
////    Storage storage  = new Storage(1, "usid");
////    storage.setString("string", "nein");
////    storage.setDouble("double", 2.1);
////    storage.setInteger("int",   1);
////    storage.setBoolean("bool", true);
////   
////    Storage pony  = new Storage(2, "ponyid");
////        pony.setBoolean("tut", true);
////    storage.setStorage("my-little-pony", pony);
//   
//   
//   
//    File  file  = new File("C:/temp/test.xml");
//    Storage storage = parser.loadStorage(file);
//   
//    System.out.println("storage="+storage);
//     
//   
//    parser.saveStorage(storage, "lolol-storage", new File("C:/temp/test_2.xml"));
//    System.out.println("done");
//  }

  @Override
  public void characters(char[] ch, int start, int length) throws SAXException {
    int       index  = this.elementAttributes.size() - 1;
    StringBuilder  builder  = this.elementContents.get(index);
   
    if (currentIsNoStorage > 0)
      builder.append(ch, start, length);
  }

  @Override
  public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
   
    // Load the attributes
    HashMap<String, String>  attributes  = new HashMap<String, String>();
    for (int i = 0; i < atts.getLength(); i++)
      attributes.put(atts.getLocalName(i), atts.getValue(i));
   
    this.elementAttributes.add(attributes);
    this.elementContents.add(new StringBuilder());
    this.currentIsNoStorage++;

    // only if this is a storage
    String    uuid  = atts.getValue(elementAttrStrgUUID);
    String    version  = atts.getValue(elementAttrStrgVersion);
//    String    type  = atts.getValue(elementAttrType);  // don't care, if there is a usid and a version, it has to be a storage
   
    // usid == null? -> create random (was at some point after SAX was introduced)
    if (uuid == null)
      uuid = Utilities.getRandomSha1();
   
    // first element has to be a storage + there were missing version attributes in old versions :(
    if (version == null && elementStorages.size() == 0)
      version = "0";
   
    // check if this is a storage
    if (uuid == null || version == null)
      return;
   
    try {
      int   ver   = Integer.parseInt(version);
      UUID  id    = ver >= 6 ? UUID.fromString(uuid) : UUID.randomUUID();
     
      // Add the storage
      Storage  storage  = new Storage(Integer.parseInt(version), id);
     
      // set for storage
      this.currentIsNoStorage--;
     
      // set storage
      if (elementStorages.size() > 0)
        elementStorages.get(elementStorages.size()-1).setStorage(localName, storage);
     
      // add storage
      elementStorages.add(storage);
     
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  @Override
  public void endElement(String uri, String localName, String qName) throws SAXException {
   
    try {
     
      // check for missing values
      if (elementAttributes.size() <= 0 || elementContents.size() <= 0 || elementStorages.size() <= 0) {
        System.out.println( "There is a missing value in a xml entry: " + ( elementAttributes.size() <= 0 ) + " " + ( elementContents.size() <= 0 ) + "" + ( elementStorages.size() <= 0 ) );
       
        return;
      }
       
     
      HashMap<String, String>  atts  = this.elementAttributes.get(elementAttributes.size()-1);
      String          content  = this.elementContents  .get(elementContents.size()-1).toString();
     
      String          name  = localName;
      String          type  = atts.get(elementAttrType);
      Storage          storage  = elementStorages.get(elementStorages.size()-1);

     
      // remove last ones - because it ends here - has to be BEFORE the if!!!
      this.elementAttributes  .remove(elementAttributes  .size()-1);
      this.elementContents  .remove(elementContents     .size()-1);
     
     
      // check for missing attributes
      if (atts == null || content == null || content.length() == 0 || name == null | type == null ||  storage == null)
        return;
     
      // has to be AFTER the if !!!!
      this.currentIsNoStorage--;
     
     
      // Storage
      if (elementAttrTypeStorage.equalsIgnoreCase(type) || type == null) {
       
        if (elementStorages.size() > 1// > 1 because of the main storage...
          elementStorages.remove(storage)// remove the last storage
      }
     
      // entry
      else if (elementAttrTypeEntry.equals(type)) {
        @SuppressWarnings("unchecked")
        List<Object> list = (List<Object>)elementLists.get(currentIsNoStorage);
       
        if (list == null) {
          list = new ArrayList<Object>();
          elementLists.put(currentIsNoStorage, list);
        }
       
        if (elementAttrTypeString.equalsIgnoreCase(name)) {
          list.add(content);
         
        } else if (elementAttrTypeDouble.equalsIgnoreCase(name)) {
          list.add(Double.parseDouble(content));
         
        } else if (elementAttrTypeInteger.equalsIgnoreCase(name)) {
          list.add(Integer.parseInt(content));
         
        } else if (elementAttrTypeBoolean.equalsIgnoreCase(name)) {
          list.add(Boolean.parseBoolean(content));
        }
      }
     
      // String
      else if (elementAttrTypeString.equalsIgnoreCase(type))
        storage.setString(name, content);
     
      // Double
      else if (elementAttrTypeDouble.equalsIgnoreCase(type))
        storage.setDouble(name, Double.parseDouble(content));
     
      // Integer
      else if (elementAttrTypeInteger.equalsIgnoreCase(type))
        storage.setInteger(name, Integer.parseInt(content));
     
      // Boolean
      else if (elementAttrTypeBoolean.equalsIgnoreCase(type))
        storage.setBoolean(name, Boolean.parseBoolean(content));
     
     
    } catch (Exception e) {
      e.printStackTrace();
    }
  }


 

 
 
  @Override
  public void endDocument() throws SAXException { }

  @Override
  public void endPrefixMapping(String arg0) throws SAXException { }
 
  @Override
  public void ignorableWhitespace(char[] arg0, int arg1, int arg2) throws SAXException { }

  @Override
  public void processingInstruction(String arg0, String arg1) throws SAXException { }

  @Override
  public void setDocumentLocator(Locator arg0) { }

  @Override
  public void skippedEntity(String arg0) throws SAXException { }

  @Override
  public void startDocument() throws SAXException { }

  @Override
  public void startPrefixMapping(String arg0, String arg1) throws SAXException {}
}
TOP

Related Classes of com.kellerkindt.scs.storage.SAXStorageParser

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.