org.openmrs.module.metadatasharing.converter.BaseConverter.java Source code

Java tutorial

Introduction

Here is the source code for org.openmrs.module.metadatasharing.converter.BaseConverter.java

Source

/**
 * The contents of this file are subject to the OpenMRS Public License
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://license.openmrs.org
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * Copyright (C) OpenMRS, LLC.  All Rights Reserved.
 */
package org.openmrs.module.metadatasharing.converter;

import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.commons.lang.StringUtils;
import org.openmrs.module.metadatasharing.MetadataSharing;
import org.openmrs.module.metadatasharing.util.Version;
import org.openmrs.serialization.SerializationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

/**
 * Allows to perform an xml conversion before deserialization.
 */
public abstract class BaseConverter {

    public static class ConverterContext {

        public Map<String, Node> references = new HashMap<String, Node>();

        public int freeReferenceId = Integer.MAX_VALUE;
    }

    public abstract void convert(Document doc, Version fromVersion, Version toVersion, ConverterContext context)
            throws SerializationException;

    /**
     * Stores or returns a reference to the given node.
     * 
     * @param node
     * @return the referenced node
     */
    protected Node reference(Node node, ConverterContext context) {
        String reference = ((Element) node).getAttribute("reference");

        Node referencedNode = null;
        if (!StringUtils.isBlank(reference)) {
            referencedNode = context.references.get(reference);
        }

        if (referencedNode == null) {
            String id = ((Element) node).getAttribute("id");

            if (!StringUtils.isBlank(id)) {
                context.references.put(id, node);
            }

            referencedNode = node;
        }

        return referencedNode;
    }

    protected Node newReference(Element element, ConverterContext context) {
        element.setAttribute("id", "" + context.freeReferenceId--);

        return reference(element, context);
    }

    protected void newReferenced(Element element, Node referencedNode) {
        String id = ((Element) referencedNode).getAttribute("id");

        element.setAttribute("reference", id);
    }

    protected Element newElement(Document doc, String name, Object object, ConverterContext context)
            throws SerializationException {
        String serializedObject = MetadataSharing.getInstance().getMetadataSerializer().serialize(object);

        Document tmpDoc;
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            DocumentBuilder db = dbf.newDocumentBuilder();
            tmpDoc = db.parse(new InputSource(new StringReader(serializedObject)));
        } catch (Exception e) {
            throw new SerializationException(e);
        }

        Element element = tmpDoc.getDocumentElement();
        element = (Element) tmpDoc.renameNode(element, "", name);

        element = (Element) newReference(element, context);
        newChildReferences(element, context);

        Element importedElement = (Element) doc.importNode(element, true);

        return importedElement;
    }

    private void newChildReferences(Element element, ConverterContext context) {
        NodeList children = element.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            Node child = children.item(i);
            if (child instanceof Element) {
                Element childElement = (Element) child;
                String id = childElement.getAttribute("id");
                if (!StringUtils.isBlank(id)) {
                    newReference(childElement, context);
                    newChildReferences(childElement, context);
                } else {
                    String reference = childElement.getAttribute("reference");
                    if (!StringUtils.isBlank(reference)) {
                        reference(childElement, context);
                    }
                }
            }
        }
    }

    /**
     * Creates a text element
     * 
     * @param doc
     * @param name
     * @param value
     * @return the text element
     */
    protected Element newTextElement(Document doc, String name, String value) {
        Element el = doc.createElement(name);
        el.setTextContent(value);
        return el;
    }

    /**
     * Gets an immediate child element of the given node
     * 
     * @param parent
     * @param childName
     * @return the element or null if not present
     */
    protected Element getChildElement(Node parent, String childName) {
        NodeList children = parent.getChildNodes();
        for (int i = 0; i < children.getLength(); ++i) {
            Node child = children.item(i);
            if (child instanceof Element) {
                if (((Element) child).getTagName().equals(childName))
                    return (Element) child;
            }
        }
        return null;
    }

    protected static String toString(Node doc) throws SerializationException {
        try {
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            StreamResult result = new StreamResult(new StringWriter());
            transformer.transform(new DOMSource(doc), result);
            return result.getWriter().toString();
        } catch (Exception e) {
            throw new SerializationException(e);
        }
    }
}