All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kuali.student.contract.model.impl.ServiceContractModelPescXsdLoader Maven / Gradle / Ivy

/*
 * Copyright 2010 The Kuali Foundation
 *
 * Licensed under the Educational Community 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.osedu.org/licenses/ECL-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.kuali.student.contract.model.impl;

import com.sun.xml.xsom.XSAnnotation;
import com.sun.xml.xsom.XSComplexType;
import com.sun.xml.xsom.XSContentType;
import com.sun.xml.xsom.XSElementDecl;
import com.sun.xml.xsom.XSFacet;
import com.sun.xml.xsom.XSModelGroup;
import com.sun.xml.xsom.XSParticle;
import com.sun.xml.xsom.XSSchema;
import com.sun.xml.xsom.XSSchemaSet;
import com.sun.xml.xsom.XSSimpleType;
import com.sun.xml.xsom.XSTerm;
import com.sun.xml.xsom.XSType;
import com.sun.xml.xsom.parser.AnnotationContext;
import com.sun.xml.xsom.parser.AnnotationParser;
import com.sun.xml.xsom.parser.AnnotationParserFactory;
import com.sun.xml.xsom.parser.SchemaDocument;
import com.sun.xml.xsom.parser.XSOMParser;
import com.sun.xml.xsom.util.DomAnnotationParserFactory;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.kuali.student.contract.model.MessageStructure;
import org.kuali.student.contract.model.Service;
import org.kuali.student.contract.model.ServiceContractModel;
import org.kuali.student.contract.model.ServiceMethod;
import org.kuali.student.contract.model.ServiceMethodReturnValue;
import org.kuali.student.contract.model.XmlType;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;

/**
 *
 * @author nwright
 */
public class ServiceContractModelPescXsdLoader implements
        ServiceContractModel {

    private List xsdFileNames;
    private List services = null;
    private List serviceMethods = null;
    private Map xmlTypeMap = null;
    private List messageStructures;

    public ServiceContractModelPescXsdLoader(List xsdFileNames) {
        this.xsdFileNames = xsdFileNames;
    }

    @Override
    public List getServiceMethods() {
        if (this.serviceMethods == null) {
            this.parse();
        }
        return this.serviceMethods;
    }

    @Override
    public List getSourceNames() {
        List list = new ArrayList();
        list.addAll(this.xsdFileNames);
        return list;
    }

    @Override
    public List getServices() {
        if (services == null) {
            this.parse();
        }
        return services;
    }

    @Override
    public List getXmlTypes() {
        if (xmlTypeMap == null) {
            this.parse();
        }
        return new ArrayList(xmlTypeMap.values());
    }

    @Override
    public List getMessageStructures() {
        if (messageStructures == null) {
            this.parse();
        }
        return this.messageStructures;
    }

    private void parse() {
        System.out.println("ServiceContractModelQDoxLoader: Starting parse");
        services = new ArrayList();
        Service service = new Service();
        services.add(service);
        service.setKey("Pesc");
        service.setName("PescService");
        service.setComments("Derived from pesc CoreMain");
        serviceMethods = new ArrayList();
        ServiceMethod method = new ServiceMethod();
        serviceMethods.add(method);
        method.setName("dummy");
        method.setDescription("Dummy method so validation won't fail");
        method.setService("Pesc");
        method.setParameters(new ArrayList());
        ServiceMethodReturnValue rv = new ServiceMethodReturnValue();
        rv.setType("void");
        rv.setDescription("returns nothing");
        method.setReturnValue(rv);
        xmlTypeMap = new LinkedHashMap();
        messageStructures = new ArrayList();

        XSOMParser parser = new XSOMParser(); 
        parser.setAnnotationParser(new DomAnnotationParserFactory());
//        parser.setAnnotationParser(new XsdAnnotationParserFactory());        
        try {
            for (String xsdFileName : this.xsdFileNames) {
//                System.out.println("Parsing " + xsdFileName);
                parser.parse(new File(xsdFileName));
            }
        } catch (SAXException ex) {
            throw new IllegalArgumentException(ex);
        } catch (IOException ex) {
            throw new IllegalArgumentException(ex);
        }
        XSSchemaSet schemas;
        try {
            schemas = parser.getResult();
        } catch (SAXException ex) {
            throw new IllegalArgumentException(ex);
        }
//        for (XSSchema schema : schemas.getSchemas()) {
//            this.processSchema(schema);
//        }
        Set schemaDocuments = parser.getDocuments();
        for (SchemaDocument doc : schemaDocuments) {
            XSSchema schema = doc.getSchema();
            this.processSchema(schema);
        }
    }

    private void processSchema(XSSchema schema) {
        for (XSElementDecl element : schema.getElementDecls().values()) {
            this.addElementDecl(element);
        }
        for (XSSimpleType st : schema.getSimpleTypes().values()) {
//            System.out.println("SimpleType =" + st.getName() + " namespace=" + st.getTargetNamespace());
            addSimpleType(st);
        }
        for (XSComplexType ct : schema.getComplexTypes().values()) {
            if (!shouldInclude(ct)) {
//                System.out.println("Skipping ComplexType =" + ct.getName() + " namespace=" + ct.getTargetNamespace());
                continue;
            }
//            System.out.println("ComplexType =" + ct.getName() + " namespace=" + ct.getTargetNamespace());
            addComplexType(ct);
        }
    }

    private boolean shouldInclude(XSComplexType ct) {
//        if (ct.getTargetNamespace().equals("urn:org:pesc:core:CoreMain:v1.8.0")) {
        return true;
//        }
//        return false;
    }

    private void addSimpleType(XSSimpleType simpleType) {
        XmlType xmlType = xmlTypeMap.get(simpleType.getName());
        if (xmlType != null) {
//            System.out.println("Already processed simple Type="
//                    + simpleType.getName());
            return;
        }
        xmlType = new XmlType();
        xmlTypeMap.put(simpleType.getName(), xmlType);
        xmlType.setName(simpleType.getName());
        xmlType.setDesc(calcMissing(calcDesc(simpleType.getAnnotation())));
        xmlType.setComments("???");
        xmlType.setExamples("???");
        xmlType.setService("Pesc");
        xmlType.setPrimitive("Primitive");
    }

    private void addComplexType(XSComplexType complexType) {
        addComplexType(complexType, complexType.getName());
    }

    private void addElementDecl(XSElementDecl element) {
        String name = element.getName();
        XmlType xmlType = xmlTypeMap.get(name);
        if (xmlType != null) {
//            System.out.println("Already processed element name=" + name);
            return;
        }
//        System.out.println("processing element=" + name);
        xmlType = new XmlType();
        xmlTypeMap.put(name, xmlType);
        xmlType.setName(name);
        xmlType.setDesc(calcMissing(calcDesc(element.getAnnotation())));
        xmlType.setComments("???");
        xmlType.setExamples("???");
        xmlType.setService("Pesc");
        xmlType.setPrimitive(XmlType.COMPLEX);
        addMessageStructure(xmlType.getName(), element);
    }

    private void addComplexType(XSComplexType complexType, String name) {
        XmlType xmlType = xmlTypeMap.get(name);
        if (xmlType != null) {
//            System.out.println("Already processed complex Type=" + name);
            return;
        }
//        System.out.println("processing complex type=" + name);
        xmlType = new XmlType();
        xmlTypeMap.put(name, xmlType);
        xmlType.setName(name);
        xmlType.setDesc(calcMissing(calcDesc(complexType.getAnnotation())));
        xmlType.setComments("???");
        xmlType.setExamples("???");
        xmlType.setService("Pesc");
        xmlType.setPrimitive(XmlType.COMPLEX);

        boolean found = false;
        XSContentType contentType = complexType.getContentType();
        XSParticle particle = contentType.asParticle();
        if (particle != null) {
            XSTerm term = particle.getTerm();
            if (term.isModelGroup()) {
                XSModelGroup xsModelGroup = term.asModelGroup();
                XSParticle[] particles = xsModelGroup.getChildren();
                for (XSParticle p : particles) {
                    XSTerm pterm = p.getTerm();
                    if (pterm.isElementDecl()) { //xs:element inside complex type
                        XSElementDecl element = pterm.asElementDecl();
                        addMessageStructure(xmlType.getName(), element);
                        found = true;
                    }
                }
            }
        }
//        if (!found) {
//            System.out.println("*** WARNING *** Complex Type, " + xmlType.getName() + ", has no message structure fields");
//        }
    }

    private String calcMissing(String str) {
        if (str == null) {
            return "???";
        }
        if (str.trim().isEmpty()) {
            return "???";
        }
        return str;
    }

    private String calcDesc(XSAnnotation annotation) {
        if (annotation == null) {
            return null;
        }
        if (annotation.getAnnotation() == null) {
            return null;
        }
        return annotation.getAnnotation().toString();
    }

    private void addMessageStructure(String xmlObject, XSElementDecl element) {
        MessageStructure ms = new MessageStructure();
        this.messageStructures.add(ms);
        ms.setXmlObject(xmlObject);
        ms.setShortName(element.getName());
        ms.setName("???");
        ms.setId(xmlObject + "." + ms.getShortName());
        ms.setType(calcType(element, xmlObject + "" + ms.getShortName()));
        ms.setDescription(calcMissing(calcDesc(element.getAnnotation())));
//        System.out.println("Element " + ms.getId() + " " + ms.getType());
        ms.setRequired(calcRequired(element));
        ms.setCardinality(calcCardinality(element));
    }

    private String calcType(XSElementDecl element, String inLinePrefix) {
        String type = calcType(element.getType(), inLinePrefix);
        if (type != null) {
            return type;
        }
        return type;
    }

    private String calcType(XSType xsType, String inLinePrefix) {
        if (xsType.isSimpleType()) {
            XSSimpleType st = xsType.asSimpleType();
            return st.getBaseType().getName();
//   if (st.isRestriction ())
//   {
//    XSRestrictionSimpleType res = st.asRestriction ();
//    return res.getBaseType ().getName ();
//   }
        }
        String type = xsType.getName();
        if (type != null) {
            return type;
        }
        if ((xsType.isComplexType())) {
            XSComplexType ct = xsType.asComplexType();
            String baseType = ct.getBaseType().getName();
            if (baseType.equals("anyType")) {
                baseType = "";
            }
            String inlineTypeName = inLinePrefix + baseType;
            addComplexType(ct, inlineTypeName);
            return inlineTypeName;
        }
        throw new IllegalArgumentException("cannot calculate the type of the field " + inLinePrefix);
    }

    private String calcRequired(XSElementDecl element) {
        // TODO: isNillable seems to ALWAYS be true so... figure out another way        
//        if (element.isNillable()) {
//            return null;
//        }
//        return "Required";
        // TODO: facets only hold min/maxLength not min/maxOccurs find out where min/maxOccurs is parsed into        
//        String minOccurs = this.getFacetValue(element, "minOccurs");
//        if (minOccurs == null) {
//            return "No";
//        }
//        if (minOccurs.equals("0")) {
//            return "No";
//        }
//        System.out.println(element.getName() + " has a minOccurs that is " + minOccurs);
//        return "Required";
        return "???";
    }

    private String calcCardinality(XSElementDecl element) {
//        if (element.getName().equals ("NoteMessage")) {
//            System.out.println ("start debugging because NoteMessage has maxOccurs=unbounded");
//        }
        if (this.getIsRepeated(element)) {
            return "Many";
        }
        // TODO: facets only hold min/maxLength not min/maxOccurs find out where min/maxOccurs is parsed into
//        String maxOccurs = this.getFacetValue(element, "maxOccurs");
//        if (maxOccurs == null) {
//            return "One";
//        }
//        if (maxOccurs.equals("unbounded")) {
//            return "Many";
//        }
//        System.out.println(element.getName() + " has a maxOccurs that is " + maxOccurs);
//        return "Many";
        return null;
    }
    
    private boolean getIsRepeated (XSElementDecl element) {
        XSType type = element.getType();
        if (type == null) {
            return false;
        }
        if (type.isComplexType()) {
            XSContentType contentType = type.asComplexType().getContentType();
            if (contentType == null) {
                return false;
            }
            XSParticle particle = contentType.asParticle();
            if (particle == null) {
                return false;
            }
            particle.isRepeated();
        }
//        if (type.isSimpleType())
        return false;
    }

    private String getFacetValue(XSElementDecl element, String name) {
        XSType type = element.getType();
        if (type == null) {
            return null;
        }
        if (type.isSimpleType()) {
            XSFacet facet = type.asSimpleType().getFacet(name);
            if (facet == null) {
                return null;
            }
            return facet.getValue().toString();
        }
        if (type.isComplexType()) {
            XSContentType contentType = type.asComplexType().getContentType();
            if (contentType == null) {
                return null;
            }
            XSSimpleType simpleType = contentType.asSimpleType();
            if (simpleType == null) {
                return null;
            }
            XSFacet facet = simpleType.getFacet(name);
            if (facet == null) {
                return null;
            }
            return facet.getValue().toString();
        }
        return null;
    }

    /**
     * helper class
     */
    private static class XsdAnnotationParserFactory implements AnnotationParserFactory {

        @Override
        public AnnotationParser create() {
            return new XsdAnnotationParser();
        }
    }

    /** 
     * helper class
     */
    private static class XsdAnnotationParser extends AnnotationParser {

        private StringBuilder documentation = new StringBuilder();

        @Override
        public ContentHandler getContentHandler(AnnotationContext context,
                String parentElementName,
                ErrorHandler handler,
                EntityResolver resolver) {
            return new XsdContentHandler(documentation);
        }

        @Override
        public Object getResult(Object existing) {
            return documentation.toString().trim();
        }
    }

    /**
     * helper class
     */
    private static class XsdContentHandler implements ContentHandler {

        private StringBuilder documentation;

        public XsdContentHandler(StringBuilder documentation) {
            this.documentation = documentation;
        }
        private boolean parsingDocumentation = false;

        @Override
        public void characters(char[] ch, int start, int length)
                throws SAXException {
            if (parsingDocumentation) {
                documentation.append(ch, start, length);
            }
        }

        @Override
        public void endElement(String uri, String localName, String name)
                throws SAXException {
            if (localName.equals("documentation")) {
                parsingDocumentation = false;
            }
        }

        @Override
        public void startElement(String uri, String localName, String name,
                Attributes atts) throws SAXException {
            if (localName.equals("documentation")) {
                parsingDocumentation = true;
            }
        }

        @Override
        public void endDocument() throws SAXException {
            // do nothing
        }

        @Override
        public void endPrefixMapping(String prefix) throws SAXException {
            // do nothing
        }

        @Override
        public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
            // do nothing
        }

        @Override
        public void processingInstruction(String target, String data) throws SAXException {
            // do nothing
        }

        @Override
        public void setDocumentLocator(Locator locator) {
            // do nothing
        }

        @Override
        public void skippedEntity(String name) throws SAXException {
            // do nothing
        }

        @Override
        public void startDocument() throws SAXException {
            // do nothing
        }

        @Override
        public void startPrefixMapping(String prefix, String uri) throws SAXException {
            // do nothing
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy