org.ms123.common.importing.XmlImporter.java Source code

Java tutorial

Introduction

Here is the source code for org.ms123.common.importing.XmlImporter.java

Source

/**
 * This file is part of SIMPL4(http://simpl4.org).
 *
 *    Copyright [2014] [Manfred Sattler] <manfred@ms123.org>
 *
 * SIMPL4 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.
 *
 * SIMPL4 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 SIMPL4.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.ms123.common.importing;

import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathConstants;
import net.sf.sojo.common.ObjectUtil;
import net.sf.sojo.interchange.json.JsonSerializer;
import org.apache.commons.beanutils.PropertyUtils;
import org.milyn.container.ExecutionContext;
import org.milyn.delivery.DomModelCreator;
import org.milyn.delivery.DOMModel;
import org.milyn.delivery.sax.DefaultSAXElementSerializer;
import org.milyn.delivery.sax.SAXElement;
import org.ms123.common.data.api.SessionContext;
import org.ms123.common.libhelper.Inflector;
import org.apache.commons.lang3.StringUtils;
import org.ms123.common.utils.XPathUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Element;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSOutput;
import org.w3c.dom.ls.LSSerializer;
import org.w3c.dom.Node;
import org.xml.sax.Attributes;

@SuppressWarnings("unchecked")
public class XmlImporter extends DomModelCreator {

    private static final Logger m_logger = LoggerFactory.getLogger(XmlImporter.class);

    protected Inflector m_inflector = Inflector.getInstance();

    private final String ENTITY = "entity";

    private Document m_document;

    private JsonSerializer m_sojoJson;

    private List<Map> m_defaults;

    private List<Map> m_mappings;

    private int m_max;

    private List<Object> m_resultList;

    private Map m_moduleTree;

    private ObjectUtil m_objUtils;

    private SessionContext m_sessionContext;

    private String m_mainEntityName;

    private String m_userName;

    private XPathUtils m_xpathUtils;

    private int m_num = 0;

    public XmlImporter() throws ParserConfigurationException {
        DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        m_document = documentBuilder.newDocument();
        m_xpathUtils = new XPathUtils();
        m_resultList = new ArrayList();
        m_sojoJson = new JsonSerializer();
        m_objUtils = new ObjectUtil();
    }

    public List<Object> getResultList() {
        return m_resultList;
    }

    public void setMappings(List<Map> mappings) {
        m_mappings = mappings;
    }

    public void setMax(int max) {
        m_max = max;
    }

    public void setModuleTree(Map moduleTree) {
        m_moduleTree = moduleTree;
    }

    public void setDefaults(List<Map> defaults) {
        m_defaults = defaults;
    }

    public void setMainEntityName(String mainEntityName) {
        m_mainEntityName = mainEntityName;
    }

    public void setUserName(String userName) {
        m_userName = userName;
    }

    public void setSessionContext(SessionContext sessionContext) {
        m_sessionContext = sessionContext;
    }

    public void visitAfter(SAXElement element, ExecutionContext executionContext) throws IOException {
        super.visitAfter(element, executionContext);
        if (m_max != -1 && m_num >= m_max)
            return;
        m_num++;
        DOMModel nodeModel = DOMModel.getModel(executionContext);
        Element domElement = null;
        Iterator it = nodeModel.getModels().keySet().iterator();
        if (it.hasNext()) {
            domElement = (Element) nodeModel.getModels().get(it.next());
        }
        if (domElement == null) {
            throw new RuntimeException("XmlImporter.visitAfter:rootElement is null");
        }
        try {
            Object o = createBeanGraph(m_sessionContext, m_moduleTree, domElement, m_mappings, m_defaults);
            System.out.println("=====>>>>beanGraph:" + m_sojoJson.serialize(o));
            m_resultList.add(o);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("XmlImporter.visitAfter:", e);
        }
    }

    private Object createBeanGraph(SessionContext sessionContext, Map<String, Object> moduleTree,
            Element rootElement, List<Map> mappings, List<Map> defaults) throws Exception {
        Stack<Element> parentElementStack = new Stack();
        parentElementStack.push(rootElement);
        return traverseModuleTree(null, parentElementStack, (String) moduleTree.get("name"), moduleTree);
    }

    private Object traverseModuleTree(Object parentBean, Stack<Element> parentElementStack, String path,
            Map<String, Object> moduleMap) throws Exception {
        String entityName = (String) moduleMap.get(ENTITY);
        System.out.println("===> traverseModuleTree.parentElementStack:" + parentElementStack + "\t\t|path:" + path
                + "\t\t|parent:" + parentBean);
        Map<String, String> wiring = getWiringForPath(path);
        System.out.println("wiring:" + path + "/" + wiring);
        if (wiring == null) {
            Map<String, String> w = getWiringForPathFromBinding(path);
            if (w == null) {
                return null;
            }
            wiring = w;
        }
        String targetType = wiring.get("targetType");
        System.out.println("targetType:" + targetType);
        Object newBean = null;
        if ("list".equals(targetType)) {
            List<Map> children = (List) moduleMap.get("children");
            System.out.println("\tchildren:" + children);
            if (children.size() > 0) {
                Map<String, Object> listType = children.get(0);
                List<Map> lchildren = (List) listType.get("children");
                Map<String, String> typeMapping = getWiringForPath(path + "." + listType.get("name"));
                List<Element> childElementList = getChildElements(parentElementStack, wiring);
                System.out.println("childElementList:" + childElementList);
                if (childElementList.size() > 0) {
                    Set<Object> beanList = new HashSet();
                    List<Map> bindings = getBindingsForPath(path + "." + listType.get("name"));
                    System.out.println("\tbindings:" + bindings);
                    for (Element childElement : childElementList) {
                        parentElementStack.push(childElement);
                        Map<String, Object> tmpMap = new HashMap();
                        for (Map<String, String> binding : bindings) {
                            String value = getSourceValue(parentElementStack, binding);
                            tmpMap.put(getLastSegment(binding.get("target")), value);
                        }
                        evaluteFormulas((String) listType.get(ENTITY), tmpMap);
                        Object bean = createBean((String) listType.get(ENTITY));
                        m_objUtils.makeComplex(tmpMap, bean);
                        beanList.add(bean);
                        if (lchildren != null) {
                            for (Map child : lchildren) {
                                traverseModuleTree(bean, parentElementStack,
                                        path + "." + listType.get("name") + "." + child.get("name"), child);
                            }
                        }
                        parentElementStack.pop();
                    }
                    PropertyUtils.setProperty(parentBean, (String) moduleMap.get("name"), beanList);
                }
            }
        } else {
            List<Map> bindings = getBindingsForPath(path);
            Map<String, Object> tmpMap = new HashMap();
            for (Map<String, String> binding : bindings) {
                String value = getSourceValue(parentElementStack, binding);
                tmpMap.put(getLastSegment(binding.get("target")), value);
            }
            evaluteFormulas((String) moduleMap.get(ENTITY), tmpMap);
            newBean = createBean((String) moduleMap.get(ENTITY));
            m_objUtils.makeComplex(tmpMap, newBean);
            if (parentBean != null) {
                PropertyUtils.setProperty(parentBean, (String) moduleMap.get("name"), newBean);
            }
            List<Map> children = (List) moduleMap.get("children");
            if (children != null) {
                for (Map child : children) {
                    traverseModuleTree(newBean, parentElementStack, path + "." + child.get("name"), child);
                }
            }
        }
        return newBean;
    }

    private void evaluteFormulas(String entityName, Map data) throws Exception {
        data.put("_isnew", true);
        data.put("_user", m_userName);
        entityName = m_inflector.getEntityName(entityName);
        m_sessionContext.evaluteFormulas(entityName, data);
    }

    private Object createBean(String entityName) throws Exception {
        Class clazz = m_sessionContext.getClass(m_inflector.getClassName(entityName));
        Object bean = clazz.newInstance();
        Map defaults = getDefaults(entityName);
        if (defaults != null) {
            m_sessionContext.populate(defaults, bean);
        }
        return bean;
    }

    private String getElementPath(Element e) {
        StringBuilder sb = new StringBuilder();
        sb.append(e.getNodeName());
        Node n = e.getParentNode();
        while (n != null) {
            String s = n.getNodeName();
            if ("#document".equals(s)) {
                break;
            }
            sb.insert(0, s + "/");
            n = n.getParentNode();
        }
        String ret = sb.toString();
        int slash = ret.indexOf("/");
        if (slash != -1) {
            return ret.substring(slash + 1);
        }
        return ret;
    }

    private String removePart(String s1, String s2) {
        if (s1.startsWith(s2) && s1.length() > s2.length()) {
            return s1.substring(s2.length() + 1);
        }
        return s1;
    }

    private String removeLastDotSegment(String s1) {
        int lastDot = s1.lastIndexOf(".");
        if (lastDot != -1) {
            return s1.substring(0, lastDot);
        }
        return s1;
    }

    private List<Element> getChildElements(Stack<Element> parentElementStack, Map<String, String> wiring) {
        int size = parentElementStack.size();
        Element bestElement = null;
        String bestSource = null;
        for (int i = size - 1; i >= 0; i--) {
            Element element = parentElementStack.get(i);
            String p = getElementPath(element);
            String s = wiring.get("source");
            String source = removePart(s, p);
            if (bestSource == null || (countSegments(bestSource) > countSegments(source))) {
                if (m_xpathUtils.isExist(source, element, XPathConstants.NODESET)) {
                    bestSource = source;
                    bestElement = element;
                }
            }
        }
        System.out.println("\tgetChildElements.bestSource:" + bestSource);
        System.out.println("\tgetChildElements.bestElement:" + bestElement);
        return m_xpathUtils.getChildElements(m_xpathUtils.getValueNode(bestSource, bestElement));
    }

    private String getSourceValue(Stack<Element> parentElementStack, Map<String, String> binding) {
        int size = parentElementStack.size();
        Element bestElement = null;
        String bestSource = null;
        for (int i = size - 1; i >= 0; i--) {
            Element element = parentElementStack.get(i);
            String p = getElementPath(element);
            String s = binding.get("source");
            String source = removePart(s, p);
            if (bestSource == null || (countSegments(bestSource) > countSegments(source))) {
                if (m_xpathUtils.isExist(source, element, XPathConstants.NODE)) {
                    bestSource = source;
                    bestElement = element;
                }
            }
        }
        System.out.println("\tgetSourceValue.bestSource:" + bestSource);
        System.out.println("\tgetSourceValue.bestElement:" + bestElement);
        String value = m_xpathUtils.getValueString(bestSource, bestElement);
        System.out.println("getSourceValue.value:" + value);
        return value;
    }

    private Map<String, Object> getDefaults(String entityName) {
        entityName = m_inflector.getEntityName(entityName);
        for (Map m : m_defaults) {
            if (entityName.toLowerCase()
                    .equals((m_inflector.getEntityName((String) m.get("name"))).toLowerCase())) {
                return (Map) m.get("content");
            }
        }
        return null;
    }

    private int countDotSegments(String toCheck) {
        return StringUtils.countMatches(toCheck, ".");
    }

    private int countSegments(String toCheck) {
        return StringUtils.countMatches(toCheck, "/");
    }

    private Map<String, String> getWiringForPath(String path) throws Exception {
        for (Map<String, String> mapping : m_mappings) {
            String target = mapping.get("target");
            String targetType = mapping.get("targetType");
            if ("list".equals(targetType) || "object".equals(targetType)) {
                if (path.compareTo(target) == 0) {
                    return mapping;
                }
            }
        }
        return null;
    }

    private List<Map> getBindingsForPath(String path) {
        System.out.println("\t\tgb.path:" + path + "/" + countDotSegments(path));
        int pathSegments = countDotSegments(path);
        int len = path.length();
        List<Map> ret = new ArrayList();
        for (Map<String, String> mapping : m_mappings) {
            String source = mapping.get("source");
            String target = mapping.get("target");
            String targetType = mapping.get("targetType");
            if (!("list".equals(targetType) || "object".equals(targetType))) {
                System.out.println("\t\t\tgb.target:" + target + "/" + countDotSegments(target));
                int targetSegments = countDotSegments(target);
                if ((targetSegments - pathSegments) == 1) {
                    String x = removeLastDotSegment(target);
                    System.out.println("\t\tx:" + x + "/s:" + m_inflector.singularize(x));
                    if (path.compareTo(x) == 0) {
                        ret.add(mapping);
                    }
                }
            }
        }
        return ret;
    }

    private Map<String, String> getWiringForPathFromBinding(String path) {
        int len = path.length();
        for (Map<String, String> mapping : m_mappings) {
            String source = mapping.get("source");
            String target = mapping.get("target");
            String targetType = mapping.get("targetType");
            if (!("list".equals(targetType) || "object".equals(targetType))) {
                if (target.length() > len) {
                    if (target.startsWith(path)) {
                        String s = target.substring(path.length() + 1);
                        System.out.println("s:" + s);
                        if (s.indexOf(".") == -1) {
                            Map<String, String> b = new HashMap();
                            b.put("target", path);
                            b.put("targetType", "object");
                            return b;
                        }
                    }
                }
            }
        }
        return null;
    }

    private String getLastSegment(String path) {
        return getLastSegment(path, ".");
    }

    private String getLastSegment(String path, String sep) {
        int lastDot = path.lastIndexOf(sep);
        return path.substring(lastDot + 1);
    }

    private String prettyPrint(Element e) {
        DOMImplementation domImplementation = m_document.getImplementation();
        if (domImplementation.hasFeature("LS", "3.0") && domImplementation.hasFeature("Core", "2.0")) {
            DOMImplementationLS domImplementationLS = (DOMImplementationLS) domImplementation.getFeature("LS",
                    "3.0");
            LSSerializer lsSerializer = domImplementationLS.createLSSerializer();
            DOMConfiguration domConfiguration = lsSerializer.getDomConfig();
            if (domConfiguration.canSetParameter("format-pretty-print", Boolean.TRUE)) {
                lsSerializer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE);
                LSOutput lsOutput = domImplementationLS.createLSOutput();
                lsOutput.setEncoding("UTF-8");
                StringWriter stringWriter = new StringWriter();
                lsOutput.setCharacterStream(stringWriter);
                lsSerializer.write(e, lsOutput);
                return stringWriter.toString();
            } else {
                throw new RuntimeException("DOMConfiguration 'format-pretty-print' parameter isn't settable.");
            }
        } else {
            throw new RuntimeException("DOM 3.0 LS and/or DOM 2.0 Core not supported.");
        }
    }
}