XMLSplitter.java 8.16 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.aemfd.docmanager.Document
 */
package com.adobe.aemds.guide.batch.impl;

import com.adobe.aemfd.docmanager.Document;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
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.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.ext.DefaultHandler2;

public class XMLSplitter
extends DefaultHandler2 {
    private static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
    private static final TransformerFactory transformerFactory;
    private static final Properties transformerProperties;
    public static final String DEFAULT_RECORD_IDENTIFIER = "id";
    public static final String DEFAULT_RECORD_NAME = "record";
    public static final String DEFAULT_RECORD_XPATH = "/root/record";
    public static final Integer DEFAULT_RECORD_LEVEL;
    private String mRecordName = null;
    private String mRecordXPath = null;
    private String mRecordIdentifier = "id";
    private int mRecordLevel = -1;
    private Map<Document, String> recordDocuments = new LinkedHashMap<Document, String>();
    private org.w3c.dom.Document mDocument = null;
    private Node mCurElement = null;
    private List<String> mCurXPath = new ArrayList<String>();
    private int mCurLevel = -1;
    private int mRecordCount = 0;

    public void setRecordName(String recordName) {
        this.mRecordName = recordName;
    }

    public void setRecordLevel(int recordLevel) {
        this.mRecordLevel = recordLevel;
    }

    public void setRecordXPath(String recordXPath) {
        this.mRecordXPath = recordXPath;
    }

    public void setRecordIdentifier(String recordIdentifier) {
        this.mRecordIdentifier = recordIdentifier == null ? "" : recordIdentifier.trim().replaceAll("@", "");
    }

    @Override
    public void startDocument() throws SAXException {
    }

    @Override
    public void endDocument() throws SAXException {
    }

    @Override
    public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
        try {
            ++this.mCurLevel;
            this.mCurXPath.add("/" + qName);
            if (this.mCurElement == null && this.atRecordBoundary(qName)) {
                this.mDocument = this.init().newDocument();
                this.mCurElement = this.mDocument;
            }
            if (this.mCurElement != null) {
                qName = this.stripNS(qName);
                this.mCurElement = this.mCurElement.appendChild(this.mDocument.createElement(qName));
                if (atts != null) {
                    for (int i = 0; i < atts.getLength(); ++i) {
                        ((Element)this.mCurElement).setAttribute(atts.getQName(i), atts.getValue(i));
                    }
                }
            }
        }
        catch (ParserConfigurationException e) {
            throw new SAXException(e.getMessage(), e);
        }
    }

    @Override
    public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
        try {
            if (this.mCurElement != null) {
                if (this.atRecordBoundary(qName)) {
                    String recordId = this.getRecordId();
                    Document recordDoc = this.getRecordDocument();
                    this.recordDocuments.put(recordDoc, recordId);
                    ++this.mRecordCount;
                    this.mCurElement = null;
                } else {
                    this.mCurElement = this.mCurElement.getParentNode();
                }
            }
        }
        catch (Exception e) {
            throw new SAXException(e.getMessage(), e);
        }
        --this.mCurLevel;
        this.mCurXPath.remove(this.mCurXPath.size() - 1);
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        if (this.mCurElement != null) {
            Text text = this.mDocument.createTextNode(new String(ch, start, length));
            this.mCurElement.appendChild(text);
        }
    }

    @Override
    public void processingInstruction(String target, String data) throws SAXException {
        if (this.mCurElement != null) {
            ProcessingInstruction pi = this.mDocument.createProcessingInstruction(target, data);
            this.mCurElement.appendChild(pi);
        }
    }

    @Override
    public void startPrefixMapping(String prefix, String uri) throws SAXException {
    }

    @Override
    public void endPrefixMapping(String prefix) throws SAXException {
    }

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

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

    @Override
    public void setDocumentLocator(Locator locator) {
    }

    public int getRecordCount() {
        return this.mRecordCount;
    }

    public Map<Document, String> getRecordDocuments() {
        return this.recordDocuments;
    }

    private boolean atRecordBoundary(String recordName) {
        boolean atBoundary = false;
        if (this.mRecordName == null) {
            atBoundary = this.mRecordLevel == -1 ? this.isEquivalent(this.mRecordXPath, this.mCurXPath) : this.mRecordLevel == this.mCurLevel;
        } else if (this.mRecordName.equals(recordName)) {
            if (this.mRecordLevel == -1) {
                this.mRecordLevel = this.mCurLevel;
            }
            atBoundary = this.mRecordLevel == this.mCurLevel;
        }
        return atBoundary;
    }

    private String getRecordId() {
        return this.mDocument.getDocumentElement().getAttribute(this.mRecordIdentifier);
    }

    private boolean isEquivalent(String xPath1, List<String> xPath2) {
        if (xPath1 == null || xPath2 == null) {
            return false;
        }
        StringBuilder strXPath2 = new StringBuilder();
        for (String pathElement : xPath2) {
            if (pathElement == null) continue;
            strXPath2.append(pathElement);
        }
        return strXPath2.toString().equals(xPath1);
    }

    private Document getRecordDocument() throws TransformerException, IOException {
        Transformer transformer = transformerFactory.newTransformer();
        ByteArrayOutputStream recordBytes = new ByteArrayOutputStream();
        transformer.setOutputProperties(transformerProperties);
        transformer.transform(new DOMSource(this.mDocument), new StreamResult(recordBytes));
        Document recordDocument = new Document(recordBytes.toByteArray());
        recordDocument.passivate();
        return recordDocument;
    }

    private String stripNS(String qName) {
        int index = qName.indexOf(58);
        if (index != -1 && !qName.startsWith("xfa:") && !qName.startsWith("xdp:")) {
            qName = qName.substring(index + 1);
        }
        return qName;
    }

    private DocumentBuilder init() throws ParserConfigurationException {
        return documentBuilderFactory.newDocumentBuilder();
    }

    static {
        documentBuilderFactory.setNamespaceAware(true);
        documentBuilderFactory.setValidating(false);
        transformerFactory = TransformerFactory.newInstance();
        transformerProperties = new Properties();
        transformerProperties.put("method", "xml");
        transformerProperties.put("encoding", "UTF-8");
        transformerProperties.put("omit-xml-declaration", "no");
        transformerProperties.put("indent", "no");
        DEFAULT_RECORD_LEVEL = 1;
    }
}