view software/mpdl-services-new/mpiwg-mpdl-cms/src/de/mpg/mpiwg/berlin/mpdl/cms/transform/GetFragmentsContentHandler.java @ 25:e9fe3186670c default tip

letzter Stand eingecheckt
author Josef Willenborg <jwillenborg@mpiwg-berlin.mpg.de>
date Tue, 21 May 2013 10:19:32 +0200
parents
children
line wrap: on
line source

package de.mpg.mpiwg.berlin.mpdl.cms.transform;

import java.util.ArrayList;
import java.util.Hashtable;

import org.xml.sax.*;

import de.mpg.mpiwg.berlin.mpdl.exception.ApplicationException;
import de.mpg.mpiwg.berlin.mpdl.util.StringUtils;

public class GetFragmentsContentHandler implements ContentHandler {
  private String xmlnsString = "";
  private int currentMilestonePosition = 0;
  private Element currentElement;
  private Element currentMilestoneElement;
  private ArrayList<Element> elementQueue; // queue of opened elements (before they were closed): to connect them to a parent hierarchy 
  private Hashtable<Integer, StringBuilder> resultFragments = new Hashtable<Integer, StringBuilder>();
  private String milestoneElemenName = "pb";  // default is pb
  
  public GetFragmentsContentHandler() throws ApplicationException {
  }

  public GetFragmentsContentHandler(String milestoneElemenName) throws ApplicationException {
    this.milestoneElemenName = milestoneElemenName;
  }

  public Hashtable<Integer, StringBuilder> getResultPages() {
    return resultFragments;  
  }

  public int getMilestoneCount() {
    return currentMilestonePosition;  
  }

  public void startDocument() throws SAXException {
  }

  public void endDocument() throws SAXException {
    // write the closePath after the last minus 1 milestone element (the closing path after the last milestone element is automatically written by the normal closing tags)
    if (currentMilestoneElement != null) {
      String msClosePath = currentMilestoneElement.getClosePath();
      write(msClosePath, currentMilestoneElement.milestonePosition - 1);
    }
    resultFragments.remove(new Integer(0));  // this fragment is filled but should not
  }
  
  public void characters(char[] c, int start, int length) throws SAXException {
    char[] cCopy = new char[length];
    System.arraycopy(c, start, cCopy, 0, length);
    String charactersStr = String.valueOf(cCopy);
    if (charactersStr != null && ! charactersStr.equals("")) {
      if (currentMilestonePosition > 0) {
        charactersStr = StringUtils.deresolveXmlEntities(charactersStr);
        write(charactersStr);
      }
    }
  }

  public void ignorableWhitespace(char[] c, int start, int length) throws SAXException {
  }

  public void processingInstruction(String target, String data) throws SAXException {
  }

  public void setDocumentLocator(Locator locator) {
  }

  public void startPrefixMapping(String prefix, String uri) throws SAXException {
    if (prefix != null && prefix.equals(""))  
      xmlnsString += "xmlns" + "=\"" + uri + "\" ";
    else
      xmlnsString += "xmlns:" + prefix + "=\"" + uri + "\" ";
  }
  
  public void endPrefixMapping(String prefix) throws SAXException {
  }

  public void skippedEntity(String name) throws SAXException {
  }

  public void startElement(String uri, String localName, String name, Attributes attrs) throws SAXException {
    if (elementQueue == null)
      elementQueue = new ArrayList<Element>();
    Element newElement = new Element(name);
    if (currentElement != null) {
      newElement.parent = currentElement;
    }
    currentElement = newElement;
    if (localName != null && localName.equals(milestoneElemenName)) {
      currentMilestonePosition++;
      if (currentMilestoneElement != null) {
        String msClosePath = currentMilestoneElement.getClosePath();
        write(msClosePath, currentMilestoneElement.milestonePosition - 1);
      }
      currentMilestoneElement = currentElement;
      currentMilestoneElement.milestonePosition = currentMilestonePosition;
      String msOpenPath = currentMilestoneElement.getOpenPath();
      write(msOpenPath);
    }
    int attrSize = attrs.getLength();
    String attrString = "";
    for (int i=0; i<attrSize; i++) {
      String attrQName = attrs.getQName(i);
      String attrValue = attrs.getValue(i);
      attrValue = StringUtils.forXML(attrValue);
      attrString = attrString + " " + attrQName + "=\"" + attrValue + "\"";
    }
    if (attrString != null && ! attrString.isEmpty()) {
      attrString = attrString.trim();
      currentElement.attrString = attrString;
    }
    if (xmlnsString != null && ! xmlnsString.isEmpty()) {
      xmlnsString = xmlnsString.trim();
      currentElement.xmlnsString = xmlnsString;
    }
    if (currentMilestonePosition > 0) {
      write("<" + name);
      if (xmlnsString != null && ! xmlnsString.isEmpty())
        write(" " + xmlnsString);
      if (attrString != null && ! attrString.isEmpty())
        write(" " + attrString);
      write(">");
    }
    xmlnsString = "";
    elementQueue.add(currentElement);
  }

  public void endElement(String uri, String localName, String name) throws SAXException {
    if (currentMilestonePosition > 0) {
      write("</" + name + ">");
    }
    if (elementQueue != null && elementQueue.size() > 0) {
      int lastIndex = elementQueue.size() - 1;
      elementQueue.remove(lastIndex);
    }
    if (elementQueue != null && elementQueue.size() > 0) {
      int lastIndex = elementQueue.size() - 1;
      currentElement = elementQueue.get(lastIndex);
    } else {
      currentElement = null;
    }
  }

  private void write(String outStr) throws SAXException {
    StringBuilder resultFragment = resultFragments.get(new Integer(currentMilestonePosition));
    if (resultFragment == null) {
      resultFragment = new StringBuilder();
      resultFragments.put(new Integer(currentMilestonePosition), resultFragment);
    }
    resultFragment.append(outStr);
  }
  
  private void write(String outStr, int milestoneNumber) throws SAXException {
    StringBuilder resultFragment = resultFragments.get(new Integer(milestoneNumber));
    if (resultFragment == null) {
      resultFragment = new StringBuilder();
      resultFragments.put(new Integer(milestoneNumber), resultFragment);
    }
    resultFragment.append(outStr);
  }
  
  public class Element {
    public String name;
    private String xmlnsString;
    private String attrString;
    private int milestonePosition;
    private Element parent;
    
    private Element(String name) {
      this.name = name;
    }

    private String getOpenPath() {
      StringBuilder ancestorsStrBuilder = new StringBuilder();
      if (parent != null) {
        ancestorsStrBuilder.append(parent.getOpenPath()); 
        ancestorsStrBuilder.append("<");
        ancestorsStrBuilder.append(parent.name);
        if (parent.xmlnsString != null && ! parent.xmlnsString.isEmpty()) {
          ancestorsStrBuilder.append(" ");
          ancestorsStrBuilder.append(parent.xmlnsString);
        }
        if (parent.attrString != null && ! parent.attrString.isEmpty()) {
          ancestorsStrBuilder.append(" " + parent.attrString);
        }
        ancestorsStrBuilder.append(">");
      }
      return ancestorsStrBuilder.toString();
    }
 
    private String getClosePath() {
      StringBuilder ancestorsStrBuilder = new StringBuilder();
      if (parent != null) {
        ancestorsStrBuilder.append("</");
        ancestorsStrBuilder.append(parent.name);
        ancestorsStrBuilder.append(">");
        ancestorsStrBuilder.append(parent.getClosePath()); 
      }
      return ancestorsStrBuilder.toString();
    }

  }
}