package org.bbaw.wsp.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 {
xmlnsString += "xmlns:" + prefix + "=\"" + uri + "\" ";
if (prefix != null && prefix.equals(""))
xmlnsString = "xmlns" + "=\"" + 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();
}
}
}