org.wso2.developerstudio.datamapper.diagram.schemagen.util.SchemaGeneratorForXML.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.developerstudio.datamapper.diagram.schemagen.util.SchemaGeneratorForXML.java

Source

/*
 * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 * 
 * Licensed under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.wso2.developerstudio.datamapper.diagram.schemagen.util;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.om.OMText;
import org.apache.axiom.om.util.AXIOMUtil;
import org.apache.commons.io.FileUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.XML;

public class SchemaGeneratorForXML extends SchemaGeneratorForJSON implements ISchemaGenerator {
    private static final String TEMP_AVRO_GEN_LOCATION = "tempXSDGenLocation";
    private static final String JAVA_IO_TMPDIR = "java.io.tmpdir";
    private static final String TEMP_OUTPUT = System.getProperty(JAVA_IO_TMPDIR) + File.separator
            + TEMP_AVRO_GEN_LOCATION;
    protected static final String AT_PREFIX = "@";
    protected static final String DOLLLAR_AT_PREFIX = "$@";
    protected static final String XSI_NAMESPACE_URI = "http://www.w3.org/2001/XMLSchema-instance";
    protected static final String XSI_TYPE = "type";

    @Override
    public String getSchemaContent(String content) throws IOException {

        JSONObject xmlJSONObj;
        try {
            xmlJSONObj = XML.toJSONObject(content);
        } catch (JSONException e) {
            throw new IOException(e.getMessage());
        }

        return super.getSchemaContent(xmlJSONObj.toString());
    }

    /*
    private File generateXSDfromXML(String filePath) throws IOException, XmlException {
           
       File outputDirectory = new File(TEMP_OUTPUT);
       if (!outputDirectory.exists()) {
     outputDirectory.mkdir();
       }
       File outputFile = new File(TEMP_OUTPUT  + File.separator + "temp.xsd");
       if (outputFile.exists()) {
     outputFile.delete();
       }
           
        Inst2XsdOptions options = new Inst2XsdOptions();
    options.setDesign(Inst2XsdOptions.DESIGN_RUSSIAN_DOLL);
    options.setSimpleContentTypes(Inst2XsdOptions.SIMPLE_CONTENT_TYPES_STRING);
    options.setUseEnumerations(Inst2XsdOptions.ENUMERATION_NEVER);
    Reader[] xmlInstance = {new BufferedReader(new FileReader(filePath))};
    SchemaDocument[] xsds = org.apache.xmlbeans.impl.inst2xsd.Inst2Xsd.inst2xsd(xmlInstance, options);
       if(xsds != null && xsds.length > 0) {
     xsds[0].save(outputFile, new  XmlOptions().setSavePrettyPrint());
       }
            
       return outputFile;
    }
    */

    @Override
    public String getSchemaResourcePath(String filePath) throws IOException {
        String entireFileText = FileUtils.readFileToString(new File(filePath));
        entireFileText = replaceAttributesWithElements(entireFileText);
        return getSchemaContent(entireFileText);
    }

    private String replaceAttributesWithElements(String entireFileText) throws IOException {
        try {
            OMElement element = AXIOMUtil.stringToOM(entireFileText);
            OMFactory factory = OMAbstractFactory.getOMFactory();
            element = traverseChildrenAndReplaceAttributes(element, factory);
            entireFileText = element.toString();
        } catch (XMLStreamException e) {
            throw new IOException(e);
        }
        return entireFileText;
    }

    private OMElement traverseChildrenAndReplaceAttributes(OMElement element, OMFactory factory) {

        Iterator attributeIterator = element.getAllAttributes();
        List<OMAttribute> removeList = new ArrayList<OMAttribute>();
        List<OMElement> addList = new ArrayList<OMElement>();
        String modifiedElementName = null;

        while (attributeIterator.hasNext()) {
            OMAttribute atttrib = (OMAttribute) attributeIterator.next();
            OMElement attributeElement = null;
            //If the attribute is an element handler append the prefix to the name
            if (atttrib.getNamespace() != null) {
                QName qName = atttrib.getQName();
                //construct a modified element name when we have xsi:type attribute in the element. 
                if (XSI_NAMESPACE_URI.equals(qName.getNamespaceURI()) && XSI_TYPE.equals(qName.getLocalPart())) {
                    modifiedElementName = element.getQName().getLocalPart() + "_" + DOLLLAR_AT_PREFIX
                            + qName.getPrefix() + ":" + qName.getLocalPart() + "_" + atttrib.getAttributeValue();
                }
                String prefix = atttrib.getNamespace().getPrefix();
                attributeElement = factory.createOMElement(AT_PREFIX + prefix + ":" + atttrib.getLocalName(), null);
            } else {
                //remove attribute and instead add a element with @ infront
                // eg <person age="30"></person> will be replaced by <person><@age>30</@age></person>
                attributeElement = factory.createOMElement(AT_PREFIX + atttrib.getLocalName(), null);
            }

            OMText attributeValue = factory.createOMText(atttrib.getAttributeValue());
            attributeElement.addChild(attributeValue);
            // add to list and later remove
            addList.add(attributeElement);
            removeList.add(atttrib);
        }

        for (OMAttribute arttribute : removeList) {
            element.removeAttribute(arttribute);
        }

        if (addList.size() > 0) {
            //remove the inner text and replace it with <#@content></#@content>
            //eg <city listed="true">colombo</city> will be replaced by <city><@listed>true</@listed><#@content>colombo</#@content></city>
            String elementText = element.getText();
            if (!elementText.isEmpty()) {
                element.setText("");
                OMElement contentElement = factory.createOMElement("#@content", null);
                OMText contentValue = factory.createOMText(elementText);
                contentElement.addChild(contentValue);
                element.addChild(contentElement);
            }
            for (OMElement attrElement : addList) {
                element.addChild(attrElement);
            }
        }

        Iterator elementIterator = element.getChildren();
        while (elementIterator.hasNext()) {
            OMNode child = (OMNode) elementIterator.next();
            if (child instanceof OMElement) {
                traverseChildrenAndReplaceAttributes((OMElement) child, factory);
            }
        }

        if (modifiedElementName != null) {
            element.setLocalName(modifiedElementName);
        }

        return element;
    }
}