org.openbravo.dal.xml.ModelXMLConverter.java Source code

Java tutorial

Introduction

Here is the source code for org.openbravo.dal.xml.ModelXMLConverter.java

Source

/*
 *************************************************************************
 * The contents of this file are subject to the Openbravo  Public  License
 * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
 * Version 1.1  with a permitted attribution clause; you may not  use this
 * file except in compliance with the License. You  may  obtain  a copy of
 * the License at http://www.openbravo.com/legal/license.html 
 * 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. 
 * The Original Code is Openbravo ERP. 
 * The Initial Developer of the Original Code is Openbravo SLU 
 * All portions are Copyright (C) 2008-2011 Openbravo SLU 
 * All Rights Reserved. 
 * Contributor(s):  ______________________________________.
 ************************************************************************
 */

package org.openbravo.dal.xml;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.openbravo.base.model.Entity;
import org.openbravo.base.model.ModelProvider;
import org.openbravo.base.model.Property;
import org.openbravo.base.model.domaintype.PrimitiveDomainType;
import org.openbravo.base.provider.OBProvider;
import org.openbravo.base.provider.OBSingleton;

/**
 * Generates the XML Schema which represents the REST Webservice in and output. The XML Schema is
 * generated on the basis of the in-memory model provided by the {@link ModelProvider}.
 * 
 * @see Entity
 * @see Property
 * 
 * @author mtaal
 */
// TODO: Support id's with multiple values
public class ModelXMLConverter implements OBSingleton {
    // private static final Logger log =
    // Logger.getLogger(DalToXMLConverter.class);

    private static ModelXMLConverter instance = new ModelXMLConverter();

    public static ModelXMLConverter getInstance() {
        if (instance == null) {
            instance = OBProvider.getInstance().get(ModelXMLConverter.class);
        }
        return instance;
    }

    /**
     * Returns the list of Entities as XML representations.
     * 
     * @return the Dom4j document containing the list of Entities
     */
    public Document getEntitiesAsXML() {
        final Document doc = XMLUtil.getInstance().createDomDocument();
        final Element root = doc.addElement("Types");
        final List<String> entityNames = new ArrayList<String>();
        for (final Entity e : ModelProvider.getInstance().getModel()) {
            entityNames.add(e.getName());
        }
        Collections.sort(entityNames);

        for (final String entityName : entityNames) {
            final Element typeElement = root.addElement("Type");
            typeElement.addAttribute("entityName", entityName);
        }
        return doc;
    }

    /**
     * Generates the XML Schema representation of the in-memory model. This XML Schema represents the
     * in- and output of the REST web-services.
     * 
     * @return the Dom4j document containing the XML Schema.
     */
    public Document getSchema() {
        final Document doc = XMLUtil.getInstance().createDomDocument();
        doc.addComment("\n* ***********************************************************************************\n"
                + "* The contents of this file are subject to the Openbravo  Public  License"
                + "* Version  1.1  (the  \"License\"),  being   the  Mozilla   Public  License"
                + "* Version 1.1  with a permitted attribution clause; you may not  use this"
                + "* file except in compliance with the License. You  may  obtain  a copy of"
                + "* the License at http://www.openbravo.com/legal/license.html "
                + "* 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. " + "* The Original Code is Openbravo ERP. "
                + "* The Initial Developer of the Original Code is Openbravo SLU"
                + "* All portions are Copyright (C) 2008-2011 Openbravo SLU" + "* All Rights Reserved. "
                + "* Contributor(s):  ______________________________________."
                + "* ***********************************************************************************\n");
        final Element root = doc.addElement("xs:schema");
        root.addNamespace("xs", "http://www.w3.org/2001/XMLSchema");
        root.addNamespace("ob", "http://www.openbravo.com");
        root.addAttribute("targetNamespace", "http://www.openbravo.com");

        final List<String> entityNames = new ArrayList<String>();
        for (final Entity e : ModelProvider.getInstance().getModel()) {
            entityNames.add(e.getName());
        }
        Collections.sort(entityNames);

        final Element rootElement = root.addElement("xs:element");
        rootElement.addAttribute("name", XMLConstants.OB_ROOT_ELEMENT);
        final Element complexType = rootElement.addElement("xs:complexType");
        final Element choiceElement = complexType.addElement("xs:choice");
        choiceElement.addAttribute("minOccurs", "0");
        choiceElement.addAttribute("maxOccurs", "unbounded");

        complexType.addElement("xs:attribute").addAttribute("name", XMLConstants.DATE_TIME_ATTRIBUTE)
                .addAttribute("type", "xs:string").addAttribute("use", "optional");
        complexType.addElement("xs:attribute").addAttribute("name", XMLConstants.OB_VERSION_ATTRIBUTE)
                .addAttribute("type", "xs:string").addAttribute("use", "optional");
        complexType.addElement("xs:attribute").addAttribute("name", XMLConstants.OB_REVISION_ATTRIBUTE)
                .addAttribute("type", "xs:string").addAttribute("use", "optional");

        for (final String entityName : entityNames) {
            final Element entityElement = choiceElement.addElement("xs:element");
            entityElement.addAttribute("name", entityName);
            entityElement.addAttribute("type", "ob:" + entityName + "Type");
        }

        for (final String entityName : entityNames) {
            final Element typeElement = root.addElement("xs:complexType");
            typeElement.addAttribute("name", entityName + "Type");

            final Element typeSequenceElement = typeElement.addElement("xs:sequence");
            typeSequenceElement.addAttribute("minOccurs", "0");

            addPropertyElements(typeSequenceElement, ModelProvider.getInstance().getEntity(entityName));

            typeElement.addElement("xs:attribute").addAttribute("name", XMLConstants.ID_ATTRIBUTE)
                    .addAttribute("type", "xs:string").addAttribute("use", "optional");
            typeElement.addElement("xs:attribute").addAttribute("name", XMLConstants.IDENTIFIER_ATTRIBUTE)
                    .addAttribute("type", "xs:string").addAttribute("use", "optional");
            typeElement.addElement("xs:attribute").addAttribute("name", XMLConstants.REFERENCE_ATTRIBUTE)
                    .addAttribute("type", "xs:boolean").addAttribute("use", "optional");
            typeElement.addElement("xs:anyAttribute");
        }

        addSimpleTypeDeclarations(root);
        addReferenceType(root);
        addErrorSchema(root);
        addResultSchema(root);

        return doc;
    }

    protected void addPropertyElements(Element sequence, Entity e) {
        for (final Property p : e.getProperties()) {
            final Element element = sequence.addElement("xs:element");

            element.addAttribute("name", p.getName());

            element.addAttribute("minOccurs", "0");

            if (p.isOneToMany() && p.isChild()) {
                element.addAttribute("minOccurs", "0");
            } else {
                if ((p.isPrimitive() && p.isId()) || !p.isMandatory()) {
                    // element.addAttribute("minOccurs", "0");
                } else if (p.isMandatory()) {
                    // element.addAttribute("minOccurs", "1");
                }
                element.addAttribute("nillable", Boolean.toString(!p.isMandatory()));
            }

            // set the type
            if (p.isPrimitive()) {
                element.addAttribute("type", ((PrimitiveDomainType) p.getDomainType()).getXMLSchemaType());
            } else if (p.isOneToMany() && p.isChild()) {
                final Element complexChildElement = element.addElement("xs:complexType");
                final Element sequenceChildElement = complexChildElement.addElement("xs:sequence");
                final Element childElement = sequenceChildElement.addElement("xs:element");

                childElement.addAttribute("name", p.getTargetEntity().getName());
                childElement.addAttribute("type", "ob:" + p.getTargetEntity().getName() + "Type");
                childElement.addAttribute("minOccurs", "0");
                childElement.addAttribute("maxOccurs", "unbounded");
            } else {
                element.addAttribute("type", "ob:ReferenceType");
            }
        }
    }

    /**
     * @deprecated do not use this method anymore, the reference attributes are defined in the new
     *             addReferenceType method
     */
    protected void addReferenceAttributes(Element elem) {
        final Element complexElem = elem.addElement("xs:complexType");
        complexElem.addElement("xs:attribute").addAttribute("name", "id").addAttribute("type", "xs:string")
                .addAttribute("use", "optional");
        complexElem.addElement("xs:attribute").addAttribute("name", "entityName").addAttribute("type", "xs:string")
                .addAttribute("use", "optional");
        complexElem.addElement("xs:attribute").addAttribute("name", "identifier").addAttribute("type", "xs:string")
                .addAttribute("use", "optional");
    }

    private void addReferenceType(Element schemaElement) {
        final Element complexElem = schemaElement.addElement("xs:complexType").addAttribute("name",
                "ReferenceType");
        complexElem.addElement("xs:attribute").addAttribute("name", XMLConstants.ID_ATTRIBUTE)
                .addAttribute("type", "xs:string").addAttribute("use", "optional");
        complexElem.addElement("xs:attribute").addAttribute("name", XMLConstants.ENTITYNAME_ATTRIBUTE)
                .addAttribute("type", "xs:string").addAttribute("use", "optional");
        complexElem.addElement("xs:attribute").addAttribute("name", XMLConstants.IDENTIFIER_ATTRIBUTE)
                .addAttribute("type", "xs:string").addAttribute("use", "optional");
        complexElem.addElement("xs:attribute").addAttribute("name", XMLConstants.TRANSIENT_ATTRIBUTE)
                .addAttribute("type", "xs:boolean").addAttribute("use", "optional");
        complexElem.addElement("xs:attribute").addAttribute("name", XMLConstants.INACTIVE_ATTRIBUTE)
                .addAttribute("type", "xs:boolean").addAttribute("use", "optional");
    }

    private void addSimpleTypeDeclarations(Element schema) {
        addSimpleTypeDeclaration(schema, "string");
        addSimpleTypeDeclaration(schema, "boolean");
        addSimpleTypeDeclaration(schema, "dateTime");
        addSimpleTypeDeclaration(schema, "decimal");
        addSimpleTypeDeclaration(schema, "long");
        addSimpleTypeDeclaration(schema, "float");
        addSimpleTypeDeclaration(schema, "base64Binary");
    }

    private void addSimpleTypeDeclaration(Element schema, String typeName) {
        final Element complex = schema.addElement("xs:complexType").addAttribute("name", typeName);
        final Element simple = complex.addElement("xs:simpleContent");
        final Element extension = simple.addElement("xs:extension").addAttribute("base", "xs:" + typeName);
        extension.addElement("xs:attribute").addAttribute("name", XMLConstants.TRANSIENT_ATTRIBUTE)
                .addAttribute("type", "xs:boolean");
        extension.addElement("xs:attribute").addAttribute("name", XMLConstants.INACTIVE_ATTRIBUTE)
                .addAttribute("type", "xs:boolean").addAttribute("use", "optional");
    }

    protected void addErrorSchema(Element rootSchema) {
        final Element errElem = rootSchema.addElement("xs:element").addAttribute("name", "error");
        final Element complexType = errElem.addElement("xs:complexType");
        final Element seqElement = complexType.addElement("xs:sequence");
        seqElement.addElement("xs:element").addAttribute("name", "message").addAttribute("type", "xs:string");
    }

    private void addResultSchema(Element schemaElement) {
        final Element resultElem = schemaElement.addElement("xs:element").addAttribute("name", "result");
        final Element complexType = resultElem.addElement("xs:complexType").addAttribute("mixed", "true");
        final Element seqElement = complexType.addElement("xs:sequence");
        addStringElement(seqElement, "msg");
        addStringElement(seqElement, "log");
        addStringElement(seqElement, "warning");
        addGroupTypeElement(seqElement, "inserted");
        addGroupTypeElement(seqElement, "updated");
        addGroupTypeElement(seqElement, "deleted");
        addGroupResultType(schemaElement);
    }

    private void addStringElement(Element sequence, String name) {
        sequence.addElement("xs:element").addAttribute("name", name).addAttribute("minOccurs", "0")
                .addAttribute("type", "xs:string");
    }

    private void addGroupTypeElement(Element sequence, String name) {
        sequence.addElement("xs:element").addAttribute("name", name).addAttribute("minOccurs", "0")
                .addAttribute("type", "ob:ResultEntitiesType");
    }

    private void addGroupResultType(Element schemaElement) {
        final Element complexElem = schemaElement.addElement("xs:complexType").addAttribute("name",
                "ResultEntitiesType");
        final Element choiceElement = complexElem.addElement("xs:choice");
        choiceElement.addAttribute("minOccurs", "0");
        choiceElement.addAttribute("maxOccurs", "unbounded");

        final List<String> entityNames = new ArrayList<String>();
        for (final Entity e : ModelProvider.getInstance().getModel()) {
            entityNames.add(e.getName());
        }
        Collections.sort(entityNames);
        for (String entityName : entityNames) {
            choiceElement.addElement("xs:element").addAttribute("name", entityName).addAttribute("type",
                    "ob:ResultEntityType");
        }
        addGroupTypeDef(schemaElement);
    }

    private void addGroupTypeDef(Element schemaElement) {
        final Element complexElem = schemaElement.addElement("xs:complexType").addAttribute("name",
                "ResultEntityType");
        complexElem.addElement("xs:attribute").addAttribute("name", XMLConstants.ID_ATTRIBUTE)
                .addAttribute("type", "xs:string").addAttribute("use", "optional");
        complexElem.addElement("xs:attribute").addAttribute("name", XMLConstants.IDENTIFIER_ATTRIBUTE)
                .addAttribute("type", "xs:string").addAttribute("use", "optional");
    }

}