Package nexj.core.util

Source Code of nexj.core.util.XSDUtil

// Copyright 2010 NexJ Systems Inc. This software is licensed under the terms of the Eclipse Public License 1.0
package nexj.core.util;

import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
import org.apache.xerces.impl.dv.ValidatedInfo;
import org.apache.xerces.impl.dv.ValidationContext;
import org.apache.xerces.impl.dv.XSSimpleType;
import org.apache.xerces.impl.validation.ValidationState;
import org.apache.xerces.parsers.XMLGrammarPreparser;
import org.apache.xerces.util.SymbolTable;
import org.apache.xerces.xni.grammars.Grammar;
import org.apache.xerces.xni.grammars.XMLGrammarDescription;
import org.apache.xerces.xni.grammars.XSGrammar;
import org.apache.xerces.xni.parser.XMLEntityResolver;
import org.apache.xerces.xni.parser.XMLInputSource;
import org.apache.xerces.xs.StringList;
import org.apache.xerces.xs.XSAnnotation;
import org.apache.xerces.xs.XSAttributeDeclaration;
import org.apache.xerces.xs.XSAttributeUse;
import org.apache.xerces.xs.XSComplexTypeDefinition;
import org.apache.xerces.xs.XSConstants;
import org.apache.xerces.xs.XSElementDeclaration;
import org.apache.xerces.xs.XSModel;
import org.apache.xerces.xs.XSModelGroup;
import org.apache.xerces.xs.XSObject;
import org.apache.xerces.xs.XSObjectList;
import org.apache.xerces.xs.XSParticle;
import org.apache.xerces.xs.XSSimpleTypeDefinition;
import org.apache.xerces.xs.XSTerm;
import org.apache.xerces.xs.XSTypeDefinition;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import nexj.core.util.XMLUtil.MappedResolver;

public class XSDUtil
{
   private final static String[] EMPTYSTRINGARRAY = new String[0];
  
   // constructors

   /**
    * Prevents instantiation.
    */
   protected XSDUtil()
   {
   }

   // operations

   public static XSParticle getParticle(XSElementDeclaration elemDecl)
   {
      XSComplexTypeDefinition complexDef = getComplexTypeDef(elemDecl);
     
      if (complexDef == null)
      {
         return null;
      }
     
      return getParticle(complexDef);
   }
  
   public static XSParticle getParticle(XSComplexTypeDefinition complexTypeDef)
   {
      switch (complexTypeDef.getContentType())
      {
         case XSComplexTypeDefinition.CONTENTTYPE_EMPTY:
         case XSComplexTypeDefinition.CONTENTTYPE_SIMPLE:
            return null;
      }
     
      return complexTypeDef.getParticle();
   }
                                              
   public static XSElementDeclaration getChildElementDeclaration(XSElementDeclaration parentElemDecl, String nodeName)
   {
      return getElementDeclaration(getModelGroup(parentElemDecl),nodeName);
   }
  
   public static XSElementDeclaration getChildElementDeclaration(XSComplexTypeDefinition parentElemDecl, String nodeName)
   {
      return getElementDeclaration(getModelGroup(parentElemDecl),nodeName);
   }

   public static XSElementDeclaration getElementDeclaration(XSModelGroup modelGroup, String nodeName)
   {
      if (modelGroup == null)
      {
         return null;
      }
     
      XSElementDeclaration retVal = null;
      XSObjectList particles = modelGroup.getParticles();
     
      for (int i=0; i < particles.getLength(); ++i)
      {
         XSParticle particle = (XSParticle)particles.item(i);
         retVal = getElementDeclaration(particle.getTerm(), nodeName);
        
         if (retVal != null)
         {
            break;
         }
      }
      return retVal;
   }
  
   private static XSElementDeclaration getElementDeclaration(XSTerm term, String nodeName)
   {
      switch (term.getType())
      {
         case XSConstants.ELEMENT_DECLARATION:
         {
            return nodeName.equals(term.getName()) ? (XSElementDeclaration)term : null;
         }
         case XSConstants.MODEL_GROUP:
         {           
            return getElementDeclaration((XSModelGroup)term, nodeName);
         }
      }
      return null;
   }

   public static XSComplexTypeDefinition getComplexTypeDef(XSElementDeclaration elemDecl)
   {
      if (elemDecl == null)
      {
         return null;
      }
     
      XSTypeDefinition td = elemDecl.getTypeDefinition();
     
      if (td.getTypeCategory()!=XSTypeDefinition.COMPLEX_TYPE)
      {
         return null;
      }
     
      return (XSComplexTypeDefinition)td;
   }

   public static String getLabel(XSElementDeclaration elemDecl)
   {
      if (elemDecl == null)
      {
         return "";
      }
     
      XSAnnotation annotation = elemDecl.getAnnotation();
     
      if (annotation == null)
      {
         return "";     
      }
     
      return XSDUtil.getText(annotation, "label");
   }

   public static XSModelGroup getModelGroup(XSElementDeclaration decl)
   {
      return getModelGroup(getParticle(decl));
   }

   public static XSModelGroup getModelGroup(XSComplexTypeDefinition decl)
   {
      return getModelGroup(getParticle(decl));
   }

   public static XSModelGroup getModelGroup(XSParticle part)
   {
      if (part == null)
      {
         return null;
      }
     
      XSTerm term = part.getTerm();
     
      if (term.getType()!=XSConstants.MODEL_GROUP)
      {
         return null;
      }
      return (XSModelGroup)term;
   }

   /**
    * Gets the model from the schema at the given URL. For security and efficiency reasons, references to other
    * schemas will not be followed unless they are present in the schemaURLMap.
    * @param xsdURL The URL of the schema.
    * @param schemaMap The map of schema URL strings to the actual URLs to use.
    * @return The schema model
    * @throws IOException If an I/O error occurs.
    */
   public static XSModel getXSModel(URL xsdURL, Lookup schemaMap) throws IOException
   {
      return getXSModel(toXMLInputSource(xsdURL), schemaMap);
   }

   /**
    * Gets the schema model from a schema input source.
    * @param inputSource The schema input source.
    * @param schemaMap The map of schema URL strings to the actual URLs to use.
    * @return The schema model.
    * @throws IOException If an I/O error occurs.
    */
   public static XSModel getXSModel(XMLInputSource inputSource, Lookup schemaMap) throws IOException
   {
      return getXSModel(preloadGrammar(inputSource, schemaMap, false));
   }

   /**
    * Gets the model from the schema at the given URL.
    * @param xsdURL The URL of the schema.
    * @return The schema model.
    * @throws IOException If an I/O error occurs.
    */
   public static XSModel getXSModel(URL xsdURL) throws IOException
   {
      return getXSModel(toXMLInputSource(xsdURL), false);
   }

   public static XSModel getXSModel(XMLInputSource inputSource, boolean bAllowDownload, XMLEntityResolver resolver) throws IOException
   {
      return getXSModel(preloadGrammar(inputSource, null, bAllowDownload, resolver));
   }
  
   /**
    * Gets the schema model from a schema input source.
    * @param inputSource The schema input source.
    * @param bAllowDownload True to allow download of unmapped URLs; false to throw an exception.
    * @return The schema model.
    * @throws IOException If an I/O error occurs.
    */
   public static XSModel getXSModel(XMLInputSource inputSource, boolean bAllowDownload) throws IOException
   {
      return getXSModel(preloadGrammar(inputSource, null, bAllowDownload));
   }

   public static XSModel getXSModel(Grammar g)
   {
      if (g instanceof XSGrammar)
      {
         return ((XSGrammar)g).toXSModel();
      }

      return null;
   }

   private static Grammar preloadGrammar(XMLInputSource inputSource, Lookup schemaMap, boolean bResolveUnmappedEntities) throws IOException
   {
      return preloadGrammar(inputSource, schemaMap, bResolveUnmappedEntities, null);
   }
  
   /**
    * Loads the grammar from a schema input source.
    * @param inputSource The schema input source.
    * @param schemaMap
    * @param bResolveUnmappedEntities True to resolve unmapped URLs; false to throw an exception.
    * @return The schema grammar.
    * @throws IOException If an I/O error occurs.
    */
   private static Grammar preloadGrammar(XMLInputSource inputSource, Lookup schemaMap, boolean bResolveUnmappedEntities, XMLEntityResolver resolver) throws IOException
   {
      XMLGrammarPreparser preparser =
         new XMLGrammarPreparser(new SymbolTable(XMLUtil.SYMBOL_TABLE_SIZE));

      preparser.registerPreparser(XMLGrammarDescription.XML_SCHEMA, null);
      preparser.setFeature(XMLUtil.NAMESPACES_FEATURE, true);
      preparser.setFeature(XMLUtil.VALIDATION_FEATURE, true);
      preparser.setFeature(XMLUtil.SCHEMA_VALIDATION_FEATURE, true);
      preparser.setFeature(XMLUtil.NODE_DEFERRAL_FEATURE, false);
      preparser.setFeature(XMLUtil.HONOR_ALL_SCHEMALOCATIONS_FEATURE, true);
     
      if (resolver == null)
      {
         resolver = new MappedResolver(schemaMap, bResolveUnmappedEntities);
      }
     
      preparser.setEntityResolver(resolver);

      return preparser.preparseGrammar(XMLGrammarDescription.XML_SCHEMA, inputSource);
   }

   /**
    *
    * @param elemDeclaration
    * @param choiceElement hint for a choice, can be null
    * @return
    */
   public static String getTemplateXML(final XSElementDeclaration elemDeclaration, String choiceElement)
   {    
      return "<xml>" + internalGetTemplateXML(elemDeclaration, choiceElement) + "</xml>";
   }
  
   public static String internalGetTemplateXML(final XSElementDeclaration elemDeclaration, String choiceElement)
   {
      String begin = "<" + elemDeclaration.getName();
      XSParticle particle = getParticle(elemDeclaration);

      if (particle == null)
      {
         return begin + "/>";
      }

      return begin + ">" + getTemplateXML(particle, choiceElement) + "</" + elemDeclaration.getName() + ">";
   }

   private static String getTemplateXML(XSParticle particle, String choiceElement)
   {
      String retVal = "";
      if (particle.getMinOccurs() > 0)
      {
         String innerXML = getTemplateXML(particle.getTerm(), choiceElement);
         for (int j=0; j < particle.getMinOccurs(); j++)
         {
            retVal += innerXML;
         }
      }
      return retVal;
   }

   private static String getTemplateXML(XSTerm term, String choiceElement)
   {
      switch (term.getType())
      {
         case XSConstants.MODEL_GROUP:
         {
            return getTemplateXML((XSModelGroup)term, choiceElement);
         }
         case XSConstants.ELEMENT_DECLARATION:
         {
            return internalGetTemplateXML((XSElementDeclaration)term, choiceElement);
         }
      }
      return "<" + term.getName() + "/>";
   }

   private static String getTemplateXML(XSModelGroup modelGroup, String choiceElement)
   {
      XSObjectList particles = modelGroup.getParticles();
      String retVal = "";
      switch (modelGroup.getCompositor())
      {
         case XSModelGroup.COMPOSITOR_ALL:
         case XSModelGroup.COMPOSITOR_SEQUENCE:
         {
            for (int i=0; i < particles.getLength(); ++i)
            {
               XSParticle particle = (XSParticle)particles.item(i);
               retVal += getTemplateXML(particle, null);
            }
         }
         break;
         case XSModelGroup.COMPOSITOR_CHOICE:
         {
            if (choiceElement != null)
            {
               for (int i=0; i < particles.getLength(); ++i)
               {
                  XSParticle particle = (XSParticle)particles.item(i);
                  if (choiceElement.equals(particle.getTerm().getName()) && (particle.getMaxOccursUnbounded() || particle.getMaxOccurs() > 0))
                  {
                     retVal += getTemplateXML(particle, null);
                     break;
                  }
               }
            }
         }
         break;
      }
      return retVal;
   }

   public static String getText(XSAnnotation annotation, final String fTagName)
   {
      final CharArrayWriter retVal = new CharArrayWriter();
      annotation.writeAnnotation(new DefaultHandler()
      {
         boolean m_insideTag;
         public void startElement(java.lang.String uri, java.lang.String localName, java.lang.String qName, org.xml.sax.Attributes attributes)
         {
            if (fTagName.equals(localName))
            {
               m_insideTag = true;
            }
            else
            {
               m_insideTag = false;
            }
         }
         public void characters (char ch[], int start, int length)
        throws SAXException
         {
            if (m_insideTag)
            {
               retVal.write(ch,start,length);
            }
         }
      }, XSAnnotation.SAX_CONTENTHANDLER);
      return retVal.toString().trim();
   }

   public static XSAttributeUse searchForAttributeUse(XSElementDeclaration descriptor, String attrName)
   {
      XSComplexTypeDefinition def = getComplexTypeDef(descriptor);
      if (def == null)
      {
         return null;
      }
      XSObjectList l = def.getAttributeUses();
      for (int i=0; i < l.getLength(); ++i)
      {
         XSAttributeUse use = (XSAttributeUse)l.item(i);
         if (attrName.equals(use.getAttrDeclaration().getName()))
         {
            return use;
         }
      }
      return null;
   }

   public static List toList(XSObjectList srcList)
   {
      List newList = new ArrayList(srcList.getLength());
      for (int i=0; i < srcList.getLength(); ++i)
      {
         newList.add(srcList.item(i));
      }
      return newList;
   }

   /**
    * @return A boolean value indicating whether attrUse requires validation against a pattern.
    */
   static public boolean hasPattern(XSAttributeDeclaration attrDecl)
   {
      return containsFacet(attrDecl, XSSimpleTypeDefinition.FACET_PATTERN);
   }

  
   /**
    * @param elemDecl
    * @param attribute Cannot be null.
    * @return
    */
   static public XSAttributeUse getAttributeUse(XSElementDeclaration elemDecl, String attrName)
   {
       return getAttributeUse(XSDUtil.getComplexTypeDef(elemDecl), attrName);
   }

   static public XSAttributeUse getAttributeUse(XSComplexTypeDefinition def, String attrName)
   {
      if (def == null)
      {
         return null;
      }
     
      XSObjectList attributeUses = def.getAttributeUses();
     
      if (attributeUses == null || attributeUses.getLength() == 0)
      {
         return null;
      }
     
      for (int i=0; i<attributeUses.getLength(); ++i)
      {
         XSAttributeUse attr = (XSAttributeUse)attributeUses.item(i);

         if (attrName.equals(attr.getAttrDeclaration().getName()))
         {
            return attr;
         }
      }
     
      return null;
   }

   static public String[] getEnumeration(XSSimpleTypeDefinition simpleType)
   {
      if (!containsFacet(simpleType, XSSimpleTypeDefinition.FACET_ENUMERATION))
      {
         return EMPTYSTRINGARRAY;
      }
     
      StringList sList = simpleType.getLexicalEnumeration();
     
      if (sList == null || sList.getLength() == 0)
      {
         return EMPTYSTRINGARRAY;
      }
     
      String[] retVal = new String[sList.getLength()];
     
      for (int i = 0; i < sList.getLength(); ++i)
      {
         retVal[i] = sList.item(i);
      }

      return retVal;
   }
  
   /**
    * @return The array of enumerated string values or the empty array.
    */
   static public String[] getEnumeration(XSAttributeDeclaration attrDecl)
   {
      return getEnumeration(attrDecl.getTypeDefinition());
   }

   static private boolean containsFacet(XSAttributeDeclaration attrDecl, short facet)
   {
      return containsFacet(attrDecl.getTypeDefinition(), facet);
   }

   static private boolean containsFacet(XSSimpleTypeDefinition def, short facet)
   {
      return ((def.getDefinedFacets() & facet) != 0);
   }

   /**
    * @return true if attrDecl is type boolean.
    */
   static public boolean isBooleanAttribute(XSAttributeDeclaration attrDecl)
   {
      XSSimpleTypeDefinition def = attrDecl.getTypeDefinition();
      def = def.getPrimitiveType();
     
      if (def == null)
      {
         return false;     
      }
     
      return (def.getName().equals("boolean"));
   }

   /**
    * Validates a string against an attribute type with a pattern.
    * @return Error message or null value if successful.
    */  
   static public String validate(String value, XSAttributeDeclaration attrDecl)
   {
      XSSimpleTypeDefinition def = attrDecl.getTypeDefinition();
     
      if (!(def instanceof XSSimpleType))
      {
         return null;     
      }
     
      XSSimpleType simpleType = (XSSimpleType)def;
      ValidatedInfo validatedInfo = new ValidatedInfo();
      ValidationContext validationState = new ValidationState();

      try
      {
          simpleType.validate(value, validationState, validatedInfo);
      }
      catch(InvalidDatatypeValueException ex)
      {
          return ObjUtil.getMessage(ex);
      }
     
      return null;
   }

   static public String getDefaultAttributeValue(XSElementDeclaration elemDecl, String attrName)
   {
      return getDefaultAttributeValue(getAttributeUse(elemDecl, attrName));
   }

   static public String getDefaultAttributeValue(XSComplexTypeDefinition elemDecl, String attrName)
   {
      return getDefaultAttributeValue(getAttributeUse(elemDecl, attrName));
   }
  
   static public String getDefaultAttributeValue(XSAttributeUse attrUse)
   {
      if (attrUse != null && attrUse.getConstraintType() == XSConstants.VC_DEFAULT)
      {
         String defaultVal = attrUse.getConstraintValue();              
         return defaultVal == null ? "" : defaultVal;
      }
     
      return "";
   }
  
   static public boolean hasWildCard(XSObject obj)
   {
      switch (obj.getType())
      {
         case XSConstants.PARTICLE:
         {
            return hasWildCard(((XSParticle)obj).getTerm());
         }
         case XSConstants.MODEL_GROUP:
         {
            return hasWildCard((XSModelGroup)obj);
         }
         case XSConstants.WILDCARD:
         {
            return true;
         }
      }

      return false;
   }
  
   static public boolean hasWildCard(XSModelGroup group)
   {
      XSObjectList l = group.getParticles();
     
      for (int i = 0; i < l.getLength(); ++i)
      {
         XSObject obj = l.item(i);
        
         if (hasWildCard(obj))
         {
            return true;
         }
      }
     
      return false;
   }
  
   static public XSObjectList getAttributeUses(XSElementDeclaration elemDecl)
   {
      XSComplexTypeDefinition def = XSDUtil.getComplexTypeDef(elemDecl);
     
      return def != null ? def.getAttributeUses() : null;
   }
  
   static public void stripAttributes(Element element, XSElementDeclaration elemDecl)
   {
      XSObjectList attributeUses = getAttributeUses(elemDecl);
     
      if (attributeUses == null)
      {
         return;
      }
     
      Set nameLookup = new HashSet(attributeUses.getLength());
     
      for (int i=0; i < attributeUses.getLength(); ++i)
      {
         XSAttributeUse attr = (XSAttributeUse)attributeUses.item(i);
         XSAttributeDeclaration attrDecl = attr.getAttrDeclaration();
         nameLookup.add(attrDecl.getName());
      }
     
      stripAttributes(element, nameLookup);
   }

   static public void stripAttributes(Element element, Set nameLookup)
   {
      NamedNodeMap attributes = element.getAttributes();
     
      if (attributes == null || attributes.getLength() == 0)
      {
         return;
      }
     
      for (int i = 0; i < attributes.getLength(); ++i)
      {
         Node node = attributes.item(i);
        
         if (!nameLookup.contains(node.getNodeName()))
         {
            element.removeAttributeNode((Attr)node);
         }
      }
   }

   public static String transform(Transformer transformer, Reader reader) throws TransformerException
   {
      return transform(transformer, new StreamSource(reader));
   }
  
   public static String transform(Transformer transformer, Source xmlSource) throws TransformerException
   {
      transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "3");    
      StringWriter writer = new StringWriter(8192);
      transformer.transform(xmlSource, new StreamResult(writer));
      return writer.toString();
   }
  
   public static XMLInputSource toXMLInputSource(URL xsdURL)
   {
      return new XMLInputSource(null, xsdURL.toExternalForm(), null);
   }
}
TOP

Related Classes of nexj.core.util.XSDUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.