com.legstar.cob2xsd.XsdAnnotationEmitter.java Source code

Java tutorial

Introduction

Here is the source code for com.legstar.cob2xsd.XsdAnnotationEmitter.java

Source

/*******************************************************************************
 * Copyright (c) 2010 LegSem.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v2.1
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     LegSem - initial API and implementation
 ******************************************************************************/
package com.legstar.cob2xsd;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.commons.schema.XmlSchema;
import org.apache.ws.commons.schema.XmlSchemaAnnotation;
import org.apache.ws.commons.schema.XmlSchemaAppInfo;
import org.apache.ws.commons.schema.utils.NamespaceMap;
import org.apache.ws.commons.schema.utils.NamespacePrefixList;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.legstar.cobol.utils.ValueUtil;
import com.legstar.coxb.CobolMarkup;
import com.legstar.coxb.CobolType;

/**
 * This class is used to generate LegStar annotations to be included
 * in an XML schema.
 * <p/>
 * The COBOL annotations are at the element level and belong to the LegStar
 * namespace.
 */
public class XsdAnnotationEmitter {

    /** This properties file holds the annotation names and namespaces. */
    private static final String ANNOTATIONS_FILE_NAME = "annotations.properties";

    /** The XML Schema being built. */
    private XmlSchema _xsd;

    /** Holds the annotations values. */
    private Properties _annotations = new Properties();;

    /** This builder is used for annotation markup elements. */
    private DocumentBuilder _docBuilder;

    /** True if properly initialized. */
    private boolean _initialized = false;

    /** The translator options in effect. */
    private Cob2XsdModel _cob2xsdModel;

    /** Logger. */
    private final Log _log = LogFactory.getLog(getClass());

    /**
     * All annotations are externalized in a properties file loaded from the
     * classpath.
     * We also create a DOM document builder that is needed to create the custom
     * annotations markup.
     * Errors, which are unlikely, are signaled by logging appropriate messages
     * but
     * no exceptions are raised. Rather, the class disables itself and no
     * annotations
     * are produced.
     * 
     * @param xsd the XML Schema to be populated.
     * @param model the translator options in effect
     */
    public XsdAnnotationEmitter(final XmlSchema xsd, final Cob2XsdModel model) {
        try {
            _xsd = xsd;
            _cob2xsdModel = model;

            InputStream is = XsdAnnotationEmitter.class.getResourceAsStream(ANNOTATIONS_FILE_NAME);
            if (is == null) {
                _log.error("Was unable to locate file " + ANNOTATIONS_FILE_NAME + " from the classpath");
            } else {
                _annotations.load(is);
                DocumentBuilderFactory docFac = DocumentBuilderFactory.newInstance();
                docFac.setNamespaceAware(true);
                _docBuilder = docFac.newDocumentBuilder();
                addNamespaceContext();
                _initialized = true;
            }
        } catch (IOException e) {
            _log.error("Unable to load file " + ANNOTATIONS_FILE_NAME, e);
        } catch (ParserConfigurationException e) {
            _log.error("Unable to get DOM document builder ", e);
        }
    }

    /**
     * Create an XML Schema annotation with markup corresponding to the original
     * COBOL
     * data item attributes.
     * 
     * @param xsdDataItem COBOL data item decorated with XSD attributes
     * @return an XML schema annotation
     */
    public XmlSchemaAnnotation createLegStarAnnotation(final XsdDataItem xsdDataItem) {

        Document doc = _docBuilder.newDocument();
        Element el = doc.createElementNS(getCOXBNamespace(), getCOXBElements());
        Element elc = doc.createElementNS(getCOXBNamespace(), getCOXBElement());

        elc.setAttribute(CobolMarkup.LEVEL_NUMBER, Integer.toString(xsdDataItem.getLevelNumber()));
        elc.setAttribute(CobolMarkup.COBOL_NAME, xsdDataItem.getCobolName());
        elc.setAttribute(CobolMarkup.TYPE, xsdDataItem.getCobolType().toString());

        if (xsdDataItem.getCobolType() != CobolType.GROUP_ITEM) {
            if (xsdDataItem.getPicture() != null) {
                elc.setAttribute(CobolMarkup.PICTURE, xsdDataItem.getPicture());
            }
            if (xsdDataItem.getUsage() != null) {
                elc.setAttribute(CobolMarkup.USAGE, xsdDataItem.getUsageForCobol());
            }
            if (xsdDataItem.isJustifiedRight()) {
                elc.setAttribute(CobolMarkup.IS_JUSTIFIED_RIGHT, "true");
            }
            if (xsdDataItem.getTotalDigits() > 0) {
                elc.setAttribute(CobolMarkup.IS_SIGNED, (xsdDataItem.isSigned()) ? "true" : "false");
                elc.setAttribute(CobolMarkup.TOTAL_DIGITS, Integer.toString(xsdDataItem.getTotalDigits()));
                if (xsdDataItem.getFractionDigits() > 0) {
                    elc.setAttribute(CobolMarkup.FRACTION_DIGITS,
                            Integer.toString(xsdDataItem.getFractionDigits()));
                }
                if (xsdDataItem.isSignLeading()) {
                    elc.setAttribute(CobolMarkup.IS_SIGN_LEADING, "true");
                }
                if (xsdDataItem.isSignSeparate()) {
                    elc.setAttribute(CobolMarkup.IS_SIGN_SEPARATE, "true");
                }
            }
        }

        /*
         * Annotations transfer the COBOL occurs semantic (as opposed to
         * the XSD semantic). No depending on => fixed size array
         */
        if (xsdDataItem.getCobolMaxOccurs() > 0) {
            elc.setAttribute(CobolMarkup.MAX_OCCURS, Integer.toString(xsdDataItem.getCobolMaxOccurs()));
            if (xsdDataItem.getDependingOn() == null) {
                elc.setAttribute(CobolMarkup.MIN_OCCURS, Integer.toString(xsdDataItem.getCobolMaxOccurs()));
            } else {
                elc.setAttribute(CobolMarkup.DEPENDING_ON, xsdDataItem.getDependingOn());
                elc.setAttribute(CobolMarkup.MIN_OCCURS, Integer.toString(xsdDataItem.getCobolMinOccurs()));
            }
        }

        if (xsdDataItem.isODOObject()) {
            elc.setAttribute(CobolMarkup.IS_ODO_OBJECT, "true");
        }
        if (xsdDataItem.getRedefines() != null) {
            elc.setAttribute(CobolMarkup.REDEFINES, xsdDataItem.getRedefines());
        }
        if (xsdDataItem.isRedefined()) {
            elc.setAttribute(CobolMarkup.IS_REDEFINED, "true");
            elc.setAttribute(CobolMarkup.UNMARSHAL_CHOICE_STRATEGY, "");
        }

        if (xsdDataItem.getValue() != null && xsdDataItem.getValue().length() > 0) {
            elc.setAttribute(CobolMarkup.VALUE, ValueUtil.resolveFigurative(xsdDataItem.getValue(),
                    xsdDataItem.getMaxStorageLength(), getModel().quoteIsQuote()));
        }

        if (xsdDataItem.getSrceLine() > 0) {
            elc.setAttribute(CobolMarkup.SRCE_LINE, Integer.toString(xsdDataItem.getSrceLine()));
        }

        el.appendChild(elc);

        XmlSchemaAppInfo appInfo = new XmlSchemaAppInfo();
        appInfo.setMarkup(el.getChildNodes());

        /* Create annotation */
        XmlSchemaAnnotation annotation = new XmlSchemaAnnotation();
        annotation.getItems().add(appInfo);
        return annotation;
    }

    /**
     * Adds the COXB namespace and associated prefixes to the XML schema.
     */
    protected void addNamespaceContext() {
        NamespaceMap prefixmap = new NamespaceMap();
        NamespacePrefixList npl = getXsd().getNamespaceContext();
        if (npl == null) {
            /* We get an NPE if we don't add this. */
            prefixmap.add("", XMLConstants.W3C_XML_SCHEMA_NS_URI);
        } else {
            for (int i = 0; i < npl.getDeclaredPrefixes().length; i++) {
                prefixmap.add(npl.getDeclaredPrefixes()[i], npl.getNamespaceURI(npl.getDeclaredPrefixes()[i]));
            }
        }
        prefixmap.add(getCOXBNamespacePrefix(), getCOXBNamespace());
        getXsd().setNamespaceContext(prefixmap);

    }

    /**
     * @return the COXB namespace
     */
    public String getCOXBNamespace() {
        return _annotations.getProperty("coxb-namespace");
    }

    /**
     * @return the COXB namespace prefix
     */
    public String getCOXBNamespacePrefix() {
        return _annotations.getProperty("coxb-ns-prefix");
    }

    /**
     * @return the COXB qualified elements element
     */
    public String getCOXBElements() {
        return getCOXBNamespacePrefix() + ':' + _annotations.getProperty("coxb-elements");
    }

    /**
     * @return the COXB qualified element element
     */
    public String getCOXBElement() {
        return getCOXBNamespacePrefix() + ':' + _annotations.getProperty("coxb-element");
    }

    /**
     * @return true if properly initialized
     */
    public boolean initialized() {
        return _initialized;
    }

    /**
     * @return the XML Schema being built
     */
    public XmlSchema getXsd() {
        return _xsd;
    }

    /**
     * @return the translator options in effect
     */
    public Cob2XsdModel getModel() {
        return _cob2xsdModel;
    }

}