Coverage Report - org.kuali.student.contract.model.impl.ServiceContractModelPescXsdLoader
 
Classes in this File Line Coverage Branch Coverage Complexity
ServiceContractModelPescXsdLoader
0%
0/200
0%
0/76
2.892
ServiceContractModelPescXsdLoader$1
N/A
N/A
2.892
ServiceContractModelPescXsdLoader$XsdAnnotationParser
0%
0/4
N/A
2.892
ServiceContractModelPescXsdLoader$XsdAnnotationParserFactory
0%
0/2
N/A
2.892
ServiceContractModelPescXsdLoader$XsdContentHandler
0%
0/21
0%
0/6
2.892
 
 1  
 /*
 2  
  * Copyright 2010 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may        obtain a copy of the License at
 7  
  *
 8  
  *         http://www.osedu.org/licenses/ECL-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.kuali.student.contract.model.impl;
 17  
 
 18  
 import com.sun.xml.xsom.XSAnnotation;
 19  
 import com.sun.xml.xsom.XSComplexType;
 20  
 import com.sun.xml.xsom.XSContentType;
 21  
 import com.sun.xml.xsom.XSElementDecl;
 22  
 import com.sun.xml.xsom.XSFacet;
 23  
 import com.sun.xml.xsom.XSModelGroup;
 24  
 import com.sun.xml.xsom.XSParticle;
 25  
 import com.sun.xml.xsom.XSSchema;
 26  
 import com.sun.xml.xsom.XSSchemaSet;
 27  
 import com.sun.xml.xsom.XSSimpleType;
 28  
 import com.sun.xml.xsom.XSTerm;
 29  
 import com.sun.xml.xsom.XSType;
 30  
 import com.sun.xml.xsom.parser.AnnotationContext;
 31  
 import com.sun.xml.xsom.parser.AnnotationParser;
 32  
 import com.sun.xml.xsom.parser.AnnotationParserFactory;
 33  
 import com.sun.xml.xsom.parser.SchemaDocument;
 34  
 import com.sun.xml.xsom.parser.XSOMParser;
 35  
 import com.sun.xml.xsom.util.DomAnnotationParserFactory;
 36  
 import java.io.File;
 37  
 import java.io.IOException;
 38  
 import java.util.ArrayList;
 39  
 import java.util.LinkedHashMap;
 40  
 import java.util.List;
 41  
 import java.util.Map;
 42  
 import java.util.Set;
 43  
 import org.kuali.student.contract.model.MessageStructure;
 44  
 import org.kuali.student.contract.model.Service;
 45  
 import org.kuali.student.contract.model.ServiceContractModel;
 46  
 import org.kuali.student.contract.model.ServiceMethod;
 47  
 import org.kuali.student.contract.model.ServiceMethodReturnValue;
 48  
 import org.kuali.student.contract.model.XmlType;
 49  
 import org.xml.sax.Attributes;
 50  
 import org.xml.sax.ContentHandler;
 51  
 import org.xml.sax.EntityResolver;
 52  
 import org.xml.sax.ErrorHandler;
 53  
 import org.xml.sax.Locator;
 54  
 import org.xml.sax.SAXException;
 55  
 
 56  
 /**
 57  
  *
 58  
  * @author nwright
 59  
  */
 60  
 public class ServiceContractModelPescXsdLoader implements
 61  
         ServiceContractModel {
 62  
 
 63  
     private List<String> xsdFileNames;
 64  0
     private List<Service> services = null;
 65  0
     private List<ServiceMethod> serviceMethods = null;
 66  0
     private Map<String, XmlType> xmlTypeMap = null;
 67  
     private List<MessageStructure> messageStructures;
 68  
 
 69  0
     public ServiceContractModelPescXsdLoader(List<String> xsdFileNames) {
 70  0
         this.xsdFileNames = xsdFileNames;
 71  0
     }
 72  
 
 73  
     @Override
 74  
     public List<ServiceMethod> getServiceMethods() {
 75  0
         if (this.serviceMethods == null) {
 76  0
             this.parse();
 77  
         }
 78  0
         return this.serviceMethods;
 79  
     }
 80  
 
 81  
     @Override
 82  
     public List<String> getSourceNames() {
 83  0
         List<String> list = new ArrayList();
 84  0
         list.addAll(this.xsdFileNames);
 85  0
         return list;
 86  
     }
 87  
 
 88  
     @Override
 89  
     public List<Service> getServices() {
 90  0
         if (services == null) {
 91  0
             this.parse();
 92  
         }
 93  0
         return services;
 94  
     }
 95  
 
 96  
     @Override
 97  
     public List<XmlType> getXmlTypes() {
 98  0
         if (xmlTypeMap == null) {
 99  0
             this.parse();
 100  
         }
 101  0
         return new ArrayList(xmlTypeMap.values());
 102  
     }
 103  
 
 104  
     @Override
 105  
     public List<MessageStructure> getMessageStructures() {
 106  0
         if (messageStructures == null) {
 107  0
             this.parse();
 108  
         }
 109  0
         return this.messageStructures;
 110  
     }
 111  
 
 112  
     private void parse() {
 113  0
         System.out.println("ServiceContractModelQDoxLoader: Starting parse");
 114  0
         services = new ArrayList();
 115  0
         Service service = new Service();
 116  0
         services.add(service);
 117  0
         service.setKey("Pesc");
 118  0
         service.setName("PescService");
 119  0
         service.setComments("Derived from pesc CoreMain");
 120  0
         serviceMethods = new ArrayList();
 121  0
         ServiceMethod method = new ServiceMethod();
 122  0
         serviceMethods.add(method);
 123  0
         method.setName("dummy");
 124  0
         method.setDescription("Dummy method so validation won't fail");
 125  0
         method.setService("Pesc");
 126  0
         method.setParameters(new ArrayList());
 127  0
         ServiceMethodReturnValue rv = new ServiceMethodReturnValue();
 128  0
         rv.setType("void");
 129  0
         rv.setDescription("returns nothing");
 130  0
         method.setReturnValue(rv);
 131  0
         xmlTypeMap = new LinkedHashMap();
 132  0
         messageStructures = new ArrayList();
 133  
 
 134  0
         XSOMParser parser = new XSOMParser(); 
 135  0
         parser.setAnnotationParser(new DomAnnotationParserFactory());
 136  
 //        parser.setAnnotationParser(new XsdAnnotationParserFactory());        
 137  
         try {
 138  0
             for (String xsdFileName : this.xsdFileNames) {
 139  
 //                System.out.println("Parsing " + xsdFileName);
 140  0
                 parser.parse(new File(xsdFileName));
 141  
             }
 142  0
         } catch (SAXException ex) {
 143  0
             throw new IllegalArgumentException(ex);
 144  0
         } catch (IOException ex) {
 145  0
             throw new IllegalArgumentException(ex);
 146  0
         }
 147  
         XSSchemaSet schemas;
 148  
         try {
 149  0
             schemas = parser.getResult();
 150  0
         } catch (SAXException ex) {
 151  0
             throw new IllegalArgumentException(ex);
 152  0
         }
 153  
 //        for (XSSchema schema : schemas.getSchemas()) {
 154  
 //            this.processSchema(schema);
 155  
 //        }
 156  0
         Set<SchemaDocument> schemaDocuments = parser.getDocuments();
 157  0
         for (SchemaDocument doc : schemaDocuments) {
 158  0
             XSSchema schema = doc.getSchema();
 159  0
             this.processSchema(schema);
 160  0
         }
 161  0
     }
 162  
 
 163  
     private void processSchema(XSSchema schema) {
 164  0
         for (XSElementDecl element : schema.getElementDecls().values()) {
 165  0
             this.addElementDecl(element);
 166  
         }
 167  0
         for (XSSimpleType st : schema.getSimpleTypes().values()) {
 168  
 //            System.out.println("SimpleType =" + st.getName() + " namespace=" + st.getTargetNamespace());
 169  0
             addSimpleType(st);
 170  
         }
 171  0
         for (XSComplexType ct : schema.getComplexTypes().values()) {
 172  0
             if (!shouldInclude(ct)) {
 173  
 //                System.out.println("Skipping ComplexType =" + ct.getName() + " namespace=" + ct.getTargetNamespace());
 174  0
                 continue;
 175  
             }
 176  
 //            System.out.println("ComplexType =" + ct.getName() + " namespace=" + ct.getTargetNamespace());
 177  0
             addComplexType(ct);
 178  
         }
 179  0
     }
 180  
 
 181  
     private boolean shouldInclude(XSComplexType ct) {
 182  
 //        if (ct.getTargetNamespace().equals("urn:org:pesc:core:CoreMain:v1.8.0")) {
 183  0
         return true;
 184  
 //        }
 185  
 //        return false;
 186  
     }
 187  
 
 188  
     private void addSimpleType(XSSimpleType simpleType) {
 189  0
         XmlType xmlType = xmlTypeMap.get(simpleType.getName());
 190  0
         if (xmlType != null) {
 191  
 //            System.out.println("Already processed simple Type="
 192  
 //                    + simpleType.getName());
 193  0
             return;
 194  
         }
 195  0
         xmlType = new XmlType();
 196  0
         xmlTypeMap.put(simpleType.getName(), xmlType);
 197  0
         xmlType.setName(simpleType.getName());
 198  0
         xmlType.setDesc(calcMissing(calcDesc(simpleType.getAnnotation())));
 199  0
         xmlType.setComments("???");
 200  0
         xmlType.setExamples("???");
 201  0
         xmlType.setService("Pesc");
 202  0
         xmlType.setPrimitive("Primitive");
 203  0
     }
 204  
 
 205  
     private void addComplexType(XSComplexType complexType) {
 206  0
         addComplexType(complexType, complexType.getName());
 207  0
     }
 208  
 
 209  
     private void addElementDecl(XSElementDecl element) {
 210  0
         String name = element.getName();
 211  0
         XmlType xmlType = xmlTypeMap.get(name);
 212  0
         if (xmlType != null) {
 213  
 //            System.out.println("Already processed element name=" + name);
 214  0
             return;
 215  
         }
 216  
 //        System.out.println("processing element=" + name);
 217  0
         xmlType = new XmlType();
 218  0
         xmlTypeMap.put(name, xmlType);
 219  0
         xmlType.setName(name);
 220  0
         xmlType.setDesc(calcMissing(calcDesc(element.getAnnotation())));
 221  0
         xmlType.setComments("???");
 222  0
         xmlType.setExamples("???");
 223  0
         xmlType.setService("Pesc");
 224  0
         xmlType.setPrimitive(XmlType.COMPLEX);
 225  0
         addMessageStructure(xmlType.getName(), element);
 226  0
     }
 227  
 
 228  
     private void addComplexType(XSComplexType complexType, String name) {
 229  0
         XmlType xmlType = xmlTypeMap.get(name);
 230  0
         if (xmlType != null) {
 231  
 //            System.out.println("Already processed complex Type=" + name);
 232  0
             return;
 233  
         }
 234  
 //        System.out.println("processing complex type=" + name);
 235  0
         xmlType = new XmlType();
 236  0
         xmlTypeMap.put(name, xmlType);
 237  0
         xmlType.setName(name);
 238  0
         xmlType.setDesc(calcMissing(calcDesc(complexType.getAnnotation())));
 239  0
         xmlType.setComments("???");
 240  0
         xmlType.setExamples("???");
 241  0
         xmlType.setService("Pesc");
 242  0
         xmlType.setPrimitive(XmlType.COMPLEX);
 243  
 
 244  0
         boolean found = false;
 245  0
         XSContentType contentType = complexType.getContentType();
 246  0
         XSParticle particle = contentType.asParticle();
 247  0
         if (particle != null) {
 248  0
             XSTerm term = particle.getTerm();
 249  0
             if (term.isModelGroup()) {
 250  0
                 XSModelGroup xsModelGroup = term.asModelGroup();
 251  0
                 XSParticle[] particles = xsModelGroup.getChildren();
 252  0
                 for (XSParticle p : particles) {
 253  0
                     XSTerm pterm = p.getTerm();
 254  0
                     if (pterm.isElementDecl()) { //xs:element inside complex type
 255  0
                         XSElementDecl element = pterm.asElementDecl();
 256  0
                         addMessageStructure(xmlType.getName(), element);
 257  0
                         found = true;
 258  
                     }
 259  
                 }
 260  
             }
 261  
         }
 262  
 //        if (!found) {
 263  
 //            System.out.println("*** WARNING *** Complex Type, " + xmlType.getName() + ", has no message structure fields");
 264  
 //        }
 265  0
     }
 266  
 
 267  
     private String calcMissing(String str) {
 268  0
         if (str == null) {
 269  0
             return "???";
 270  
         }
 271  0
         if (str.trim().isEmpty()) {
 272  0
             return "???";
 273  
         }
 274  0
         return str;
 275  
     }
 276  
 
 277  
     private String calcDesc(XSAnnotation annotation) {
 278  0
         if (annotation == null) {
 279  0
             return null;
 280  
         }
 281  0
         if (annotation.getAnnotation() == null) {
 282  0
             return null;
 283  
         }
 284  0
         return annotation.getAnnotation().toString();
 285  
     }
 286  
 
 287  
     private void addMessageStructure(String xmlObject, XSElementDecl element) {
 288  0
         MessageStructure ms = new MessageStructure();
 289  0
         this.messageStructures.add(ms);
 290  0
         ms.setXmlObject(xmlObject);
 291  0
         ms.setShortName(element.getName());
 292  0
         ms.setName("???");
 293  0
         ms.setId(xmlObject + "." + ms.getShortName());
 294  0
         ms.setType(calcType(element, xmlObject + "" + ms.getShortName()));
 295  0
         ms.setDescription(calcMissing(calcDesc(element.getAnnotation())));
 296  
 //        System.out.println("Element " + ms.getId() + " " + ms.getType());
 297  0
         ms.setRequired(calcRequired(element));
 298  0
         ms.setCardinality(calcCardinality(element));
 299  0
     }
 300  
 
 301  
     private String calcType(XSElementDecl element, String inLinePrefix) {
 302  0
         String type = calcType(element.getType(), inLinePrefix);
 303  0
         if (type != null) {
 304  0
             return type;
 305  
         }
 306  0
         return type;
 307  
     }
 308  
 
 309  
     private String calcType(XSType xsType, String inLinePrefix) {
 310  0
         if (xsType.isSimpleType()) {
 311  0
             XSSimpleType st = xsType.asSimpleType();
 312  0
             return st.getBaseType().getName();
 313  
 //   if (st.isRestriction ())
 314  
 //   {
 315  
 //    XSRestrictionSimpleType res = st.asRestriction ();
 316  
 //    return res.getBaseType ().getName ();
 317  
 //   }
 318  
         }
 319  0
         String type = xsType.getName();
 320  0
         if (type != null) {
 321  0
             return type;
 322  
         }
 323  0
         if ((xsType.isComplexType())) {
 324  0
             XSComplexType ct = xsType.asComplexType();
 325  0
             String baseType = ct.getBaseType().getName();
 326  0
             if (baseType.equals("anyType")) {
 327  0
                 baseType = "";
 328  
             }
 329  0
             String inlineTypeName = inLinePrefix + baseType;
 330  0
             addComplexType(ct, inlineTypeName);
 331  0
             return inlineTypeName;
 332  
         }
 333  0
         throw new IllegalArgumentException("cannot calculate the type of the field " + inLinePrefix);
 334  
     }
 335  
 
 336  
     private String calcRequired(XSElementDecl element) {
 337  
         // TODO: isNillable seems to ALWAYS be true so... figure out another way        
 338  
 //        if (element.isNillable()) {
 339  
 //            return null;
 340  
 //        }
 341  
 //        return "Required";
 342  
         // TODO: facets only hold min/maxLength not min/maxOccurs find out where min/maxOccurs is parsed into        
 343  
 //        String minOccurs = this.getFacetValue(element, "minOccurs");
 344  
 //        if (minOccurs == null) {
 345  
 //            return "No";
 346  
 //        }
 347  
 //        if (minOccurs.equals("0")) {
 348  
 //            return "No";
 349  
 //        }
 350  
 //        System.out.println(element.getName() + " has a minOccurs that is " + minOccurs);
 351  
 //        return "Required";
 352  0
         return "???";
 353  
     }
 354  
 
 355  
     private String calcCardinality(XSElementDecl element) {
 356  
 //        if (element.getName().equals ("NoteMessage")) {
 357  
 //            System.out.println ("start debugging because NoteMessage has maxOccurs=unbounded");
 358  
 //        }
 359  0
         if (this.getIsRepeated(element)) {
 360  0
             return "Many";
 361  
         }
 362  
         // TODO: facets only hold min/maxLength not min/maxOccurs find out where min/maxOccurs is parsed into
 363  
 //        String maxOccurs = this.getFacetValue(element, "maxOccurs");
 364  
 //        if (maxOccurs == null) {
 365  
 //            return "One";
 366  
 //        }
 367  
 //        if (maxOccurs.equals("unbounded")) {
 368  
 //            return "Many";
 369  
 //        }
 370  
 //        System.out.println(element.getName() + " has a maxOccurs that is " + maxOccurs);
 371  
 //        return "Many";
 372  0
         return null;
 373  
     }
 374  
     
 375  
     private boolean getIsRepeated (XSElementDecl element) {
 376  0
         XSType type = element.getType();
 377  0
         if (type == null) {
 378  0
             return false;
 379  
         }
 380  0
         if (type.isComplexType()) {
 381  0
             XSContentType contentType = type.asComplexType().getContentType();
 382  0
             if (contentType == null) {
 383  0
                 return false;
 384  
             }
 385  0
             XSParticle particle = contentType.asParticle();
 386  0
             if (particle == null) {
 387  0
                 return false;
 388  
             }
 389  0
             particle.isRepeated();
 390  
         }
 391  
 //        if (type.isSimpleType())
 392  0
         return false;
 393  
     }
 394  
 
 395  
     private String getFacetValue(XSElementDecl element, String name) {
 396  0
         XSType type = element.getType();
 397  0
         if (type == null) {
 398  0
             return null;
 399  
         }
 400  0
         if (type.isSimpleType()) {
 401  0
             XSFacet facet = type.asSimpleType().getFacet(name);
 402  0
             if (facet == null) {
 403  0
                 return null;
 404  
             }
 405  0
             return facet.getValue().toString();
 406  
         }
 407  0
         if (type.isComplexType()) {
 408  0
             XSContentType contentType = type.asComplexType().getContentType();
 409  0
             if (contentType == null) {
 410  0
                 return null;
 411  
             }
 412  0
             XSSimpleType simpleType = contentType.asSimpleType();
 413  0
             if (simpleType == null) {
 414  0
                 return null;
 415  
             }
 416  0
             XSFacet facet = simpleType.getFacet(name);
 417  0
             if (facet == null) {
 418  0
                 return null;
 419  
             }
 420  0
             return facet.getValue().toString();
 421  
         }
 422  0
         return null;
 423  
     }
 424  
 
 425  
     /**
 426  
      * helper class
 427  
      */
 428  0
     private static class XsdAnnotationParserFactory implements AnnotationParserFactory {
 429  
 
 430  
         @Override
 431  
         public AnnotationParser create() {
 432  0
             return new XsdAnnotationParser();
 433  
         }
 434  
     }
 435  
 
 436  
     /** 
 437  
      * helper class
 438  
      */
 439  0
     private static class XsdAnnotationParser extends AnnotationParser {
 440  
 
 441  0
         private StringBuilder documentation = new StringBuilder();
 442  
 
 443  
         @Override
 444  
         public ContentHandler getContentHandler(AnnotationContext context,
 445  
                 String parentElementName,
 446  
                 ErrorHandler handler,
 447  
                 EntityResolver resolver) {
 448  0
             return new XsdContentHandler(documentation);
 449  
         }
 450  
 
 451  
         @Override
 452  
         public Object getResult(Object existing) {
 453  0
             return documentation.toString().trim();
 454  
         }
 455  
     }
 456  
 
 457  
     /**
 458  
      * helper class
 459  
      */
 460  
     private static class XsdContentHandler implements ContentHandler {
 461  
 
 462  
         private StringBuilder documentation;
 463  
 
 464  0
         public XsdContentHandler(StringBuilder documentation) {
 465  0
             this.documentation = documentation;
 466  0
         }
 467  0
         private boolean parsingDocumentation = false;
 468  
 
 469  
         @Override
 470  
         public void characters(char[] ch, int start, int length)
 471  
                 throws SAXException {
 472  0
             if (parsingDocumentation) {
 473  0
                 documentation.append(ch, start, length);
 474  
             }
 475  0
         }
 476  
 
 477  
         @Override
 478  
         public void endElement(String uri, String localName, String name)
 479  
                 throws SAXException {
 480  0
             if (localName.equals("documentation")) {
 481  0
                 parsingDocumentation = false;
 482  
             }
 483  0
         }
 484  
 
 485  
         @Override
 486  
         public void startElement(String uri, String localName, String name,
 487  
                 Attributes atts) throws SAXException {
 488  0
             if (localName.equals("documentation")) {
 489  0
                 parsingDocumentation = true;
 490  
             }
 491  0
         }
 492  
 
 493  
         @Override
 494  
         public void endDocument() throws SAXException {
 495  
             // do nothing
 496  0
         }
 497  
 
 498  
         @Override
 499  
         public void endPrefixMapping(String prefix) throws SAXException {
 500  
             // do nothing
 501  0
         }
 502  
 
 503  
         @Override
 504  
         public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
 505  
             // do nothing
 506  0
         }
 507  
 
 508  
         @Override
 509  
         public void processingInstruction(String target, String data) throws SAXException {
 510  
             // do nothing
 511  0
         }
 512  
 
 513  
         @Override
 514  
         public void setDocumentLocator(Locator locator) {
 515  
             // do nothing
 516  0
         }
 517  
 
 518  
         @Override
 519  
         public void skippedEntity(String name) throws SAXException {
 520  
             // do nothing
 521  0
         }
 522  
 
 523  
         @Override
 524  
         public void startDocument() throws SAXException {
 525  
             // do nothing
 526  0
         }
 527  
 
 528  
         @Override
 529  
         public void startPrefixMapping(String prefix, String uri) throws SAXException {
 530  
             // do nothing
 531  0
         }
 532  
     }
 533  
 }