/*
* Copyright 2005-2015 by BerryWorks Software, LLC. All rights reserved.
*
* This file is part of EDIReader. You may obtain a license for its use directly from
* BerryWorks Software, and you may also choose to use this software under the terms of the
* GPL version 3. Other products in the EDIReader software suite are available only by licensing
* with BerryWorks. Only those files bearing the GPL statement below are available under the GPL.
*
* EDIReader 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 3 of
* the License, or (at your option) any later version.
*
* EDIReader 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 EDIReader. If not,
* see <http://www.gnu.org/licenses/>.
*/
package com.berryworks.edireader.util.sax;
import com.berryworks.edireader.EDIAttributes;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.util.ArrayList;
import java.util.List;
/**
* This implementation of a SAX ContentHandler
* maintains a stack corresponding to the nested XML elements.
* It is not used in EDIReader, but can be convenient in certain
* situations for processing the SAX output from EDIReader.
*/
public class StackedContentHandler extends DefaultHandler {
private final ContentHandler wrappedHandler;
private final List<StackedItem> stack = new ArrayList<>();
public StackedContentHandler(ContentHandler handler) {
wrappedHandler = handler;
}
@Override
public void startDocument() throws SAXException {
wrappedHandler.startDocument();
}
@Override
public void endDocument() throws SAXException {
wrappedHandler.endDocument();
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// displayStack("startElement " + localName);
stack.add(new StackedItem(uri, localName, qName, attributes));
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// displayStack("endElement " + localName);
for (StackedItem stackedItem : stack)
if (!stackedItem.isStarted())
stackedItem.start(wrappedHandler);
pop().end(wrappedHandler);
}
private StackedItem pop() {
int n = stack.size();
if (n == 0)
throw new RuntimeException("attempt to pop an empty stack");
return stack.remove(n - 1);
}
private void displayStack(String msg) {
System.out.println(msg + ", stack size " + stack.size());
for (StackedItem stackedItem : stack) {
System.out.println("..." + stackedItem.getLocalName());
}
}
@Override
public void characters(char[] chars, int start, int length) throws SAXException {
characters(new String(chars, start, length));
}
public void characters(String data) {
stack.get(stack.size() - 1).addData(data);
}
public void addAttribute(String tag, String attributeName, String data) {
for (StackedItem stackedItem : stack) {
if (tag.equals(stackedItem.getLocalName())) {
EDIAttributes attributes = stackedItem.getAttributes();
attributes.addCDATA(attributeName, data);
// System.out.println("Added " + attributeName + "=" + data + " to " + tag);
return;
}
}
throw new RuntimeException("Could not find stacked element " + tag + " for putAttribute()");
}
static class StackedItem {
private final String uri;
private final String localName;
private final String qName;
private final EDIAttributes attributes;
private String data;
private boolean started;
StackedItem(String uri, String localName, String qName, Attributes attributes) {
this.uri = uri;
this.localName = localName;
this.qName = qName;
this.attributes = new EDIAttributes(attributes);
}
public String getUri() {
return uri;
}
public String getLocalName() {
return localName;
}
public String getQName() {
return qName;
}
public EDIAttributes getAttributes() {
return attributes;
}
public String getData() {
return data;
}
public boolean isStarted() {
return started;
}
public void addData(String data) {
if (this.data == null)
this.data = data;
else
this.data += data;
}
public void start(ContentHandler handler) throws SAXException {
handler.startElement(uri, localName, qName, attributes);
if (data != null)
handler.characters(data.toCharArray(), 0, data.length());
started = true;
}
public void end(ContentHandler handler) throws SAXException {
handler.endElement(uri, localName, qName);
}
}
}