< prev index next >

src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDAbstractTraverser.java

Print this page

        

@@ -21,10 +21,12 @@
 package com.sun.org.apache.xerces.internal.impl.xs.traversers;
 
 import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
 import com.sun.org.apache.xerces.internal.impl.dv.XSFacets;
 import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
+import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
+import com.sun.org.apache.xerces.internal.impl.dv.xs.XSSimpleTypeDecl;
 import com.sun.org.apache.xerces.internal.impl.validation.ValidationState;
 import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar;
 import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols;
 import com.sun.org.apache.xerces.internal.impl.xs.XSAnnotationImpl;
 import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeGroupDecl;

@@ -40,10 +42,11 @@
 import com.sun.org.apache.xerces.internal.util.SymbolTable;
 import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
 import com.sun.org.apache.xerces.internal.xni.QName;
 import com.sun.org.apache.xerces.internal.xs.XSAttributeUse;
 import com.sun.org.apache.xerces.internal.xs.XSObjectList;
+import com.sun.org.apache.xerces.internal.xs.XSSimpleTypeDefinition;
 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 import org.w3c.dom.Element;

@@ -278,10 +281,11 @@
             fFixedFacets = fixedFacets;
         }
     }
 
     FacetInfo traverseFacets(Element content,
+            XSTypeDefinition typeDef,
             XSSimpleType baseValidator,
             XSDocumentInfo schemaDoc) {
 
         short facetsPresent = 0 ;
         short facetsFixed = 0; // facets that have fixed="true"

@@ -291,10 +295,13 @@
         XSObjectListImpl enumAnnotations = null;
         XSObjectListImpl patternAnnotations = null;
         List<NamespaceContext> enumNSDecls = hasQName ? new ArrayList<>() : null;
         int currentFacet = 0;
         xsFacets.reset();
+        boolean seenPattern = false;
+        Element contextNode = (Element)content.getParentNode();
+        boolean hasLengthFacet = false, hasMinLengthFacet = false, hasMaxLengthFacet = false;
         while (content != null) {
             // General Attribute Checking
             Object[] attrs = null;
             facet = DOMUtil.getLocalName(content);
             if (facet.equals(SchemaSymbols.ELT_ENUMERATION)) {

@@ -362,11 +369,10 @@
                 if (child !=null) {
                     reportSchemaError("s4s-elt-must-match.1", new Object[]{"enumeration", "(annotation?)", DOMUtil.getLocalName(child)}, child);
                 }
             }
             else if (facet.equals(SchemaSymbols.ELT_PATTERN)) {
-                facetsPresent |= XSSimpleType.FACET_PATTERN;
                 attrs = fAttrChecker.checkAttributes(content, false, schemaDoc);
                 String patternVal = (String)attrs[XSAttributeChecker.ATTIDX_VALUE];
                 // The facet can't be used if the value is missing. Ignore
                 // this facet element.
                 if (patternVal == null) {

@@ -374,10 +380,11 @@
                     fAttrChecker.returnAttrArray (attrs, schemaDoc);
                     content = DOMUtil.getNextSiblingElement(content);
                     continue;
                 }
 
+                seenPattern = true;
                 if (fPattern.length() == 0) {
                     fPattern.append(patternVal);
                 } else {
                     // ---------------------------------------------
                     //datatypes: 5.2.4 pattern: src-multiple-pattern

@@ -475,13 +482,15 @@
                     facetsFixed |= currentFacet;
                 }
                 switch (currentFacet) {
                 case XSSimpleType.FACET_MINLENGTH:
                     xsFacets.minLength = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue();
+                    hasMinLengthFacet = true;
                     break;
                 case XSSimpleType.FACET_MAXLENGTH:
                     xsFacets.maxLength = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue();
+                    hasMaxLengthFacet = true;
                     break;
                 case XSSimpleType.FACET_MAXEXCLUSIVE:
                     xsFacets.maxExclusive = (String)attrs[XSAttributeChecker.ATTIDX_VALUE];
                     break;
                 case XSSimpleType.FACET_MAXINCLUSIVE:

@@ -502,10 +511,11 @@
                 case XSSimpleType.FACET_WHITESPACE:
                     xsFacets.whiteSpace = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).shortValue();
                     break;
                 case XSSimpleType.FACET_LENGTH:
                     xsFacets.length = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue();
+                    hasLengthFacet = true;
                     break;
                 }
 
                 Element child = DOMUtil.getFirstChildElement( content );
                 XSAnnotationImpl annotation = null;

@@ -564,20 +574,152 @@
             facetsPresent |= XSSimpleType.FACET_ENUMERATION;
             xsFacets.enumeration = enumData;
             xsFacets.enumNSDecls = enumNSDecls;
             xsFacets.enumAnnotations = enumAnnotations;
         }
-        if ((facetsPresent & XSSimpleType.FACET_PATTERN) != 0) {
+        if (seenPattern) {
+            facetsPresent |= XSSimpleType.FACET_PATTERN;
             xsFacets.pattern = fPattern.toString();
             xsFacets.patternAnnotations = patternAnnotations;
         }
 
         fPattern.setLength(0);
 
+        // check if length, minLength and maxLength facets contradict with enumeration facets.
+        // currently considers the case when the baseValidator is a built-in type.
+        if (enumData != null) {
+           if (hasLengthFacet) {
+              checkEnumerationAndLengthInconsistency(baseValidator, enumData, contextNode, getSchemaTypeName(typeDef));
+           }
+           if (hasMinLengthFacet) {
+              checkEnumerationAndMinLengthInconsistency(baseValidator, enumData, contextNode, getSchemaTypeName(typeDef));
+           }
+           if (hasMaxLengthFacet) {
+              checkEnumerationAndMaxLengthInconsistency(baseValidator, enumData, contextNode, getSchemaTypeName(typeDef));
+           }
+        }
+
         return new FacetInfo(xsFacets, content, facetsPresent, facetsFixed);
     }
 
+    /*
+     * Get name of an XSD type definition as a string value (which will typically be the value of "name" attribute of a
+     * type definition, or an internal name determined by the validator for anonymous types).
+     */
+    public static String getSchemaTypeName(XSTypeDefinition typeDefn) {
+
+        String typeNameStr = "";
+        if (typeDefn instanceof XSSimpleTypeDefinition) {
+            typeNameStr = ((XSSimpleTypeDecl) typeDefn).getTypeName();
+        }
+        else {
+            typeNameStr = ((XSComplexTypeDecl) typeDefn).getTypeName();
+        }
+
+        return typeNameStr;
+
+    } // getSchemaTypeName
+
+    /*
+     * Check whether values of xs:maxLength and xs:enumeration are consistent. Report a warning message if they are not.
+     */
+    private void checkEnumerationAndMaxLengthInconsistency(XSSimpleType baseValidator, List<String> enumData, Element contextNode, String typeName) {
+        if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(baseValidator.getNamespace()) &&
+            SchemaSymbols.ATTVAL_HEXBINARY.equals(baseValidator.getName())) {
+            for (int enumIdx = 0; enumIdx < enumData.size(); enumIdx++) {
+                String enumVal = (enumData.get(enumIdx));
+                if (enumVal.length() / 2 > xsFacets.maxLength) {
+                    reportSchemaWarning("FacetsContradict", new Object[]{enumVal, SchemaSymbols.ELT_MAXLENGTH, typeName}, contextNode);
+                }
+            }
+        }
+        else if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(baseValidator.getNamespace()) &&
+                 SchemaSymbols.ATTVAL_BASE64BINARY.equals(baseValidator.getName())) {
+            for (int enumIdx = 0; enumIdx < enumData.size(); enumIdx++) {
+                String enumVal = (enumData.get(enumIdx));
+                byte[] decodedVal = Base64.decode(enumVal);
+                if (decodedVal != null && (new String(decodedVal)).length() > xsFacets.maxLength) {
+                   reportSchemaWarning("FacetsContradict", new Object[]{enumVal, SchemaSymbols.ELT_MAXLENGTH, typeName}, contextNode);
+                }
+            }
+        }
+        else {
+            for (int enumIdx = 0; enumIdx < enumData.size(); enumIdx++) {
+                String enumVal = (enumData.get(enumIdx));
+                if (enumVal.length() > xsFacets.maxLength) {
+                    reportSchemaWarning("FacetsContradict", new Object[]{enumVal, SchemaSymbols.ELT_MAXLENGTH, typeName}, contextNode);
+                }
+            }
+        }
+    } // checkEnumerationAndMaxLengthInconsistency
+
+    /*
+     * Check whether values of xs:minLength and xs:enumeration are consistent. Report a warning message if they are not.
+     */
+    private void checkEnumerationAndMinLengthInconsistency(XSSimpleType baseValidator, List<String> enumData, Element contextNode, String typeName) {
+        if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(baseValidator.getNamespace()) &&
+            SchemaSymbols.ATTVAL_HEXBINARY.equals(baseValidator.getName())) {
+            for (int enumIdx = 0; enumIdx < enumData.size(); enumIdx++) {
+                String enumVal = (enumData.get(enumIdx));
+                if (enumVal.length() / 2 < xsFacets.minLength) {
+                    reportSchemaWarning("FacetsContradict", new Object[]{enumVal, SchemaSymbols.ELT_MINLENGTH, typeName}, contextNode);
+                }
+            }
+        }
+        else if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(baseValidator.getNamespace()) &&
+                 SchemaSymbols.ATTVAL_BASE64BINARY.equals(baseValidator.getName())) {
+            for (int enumIdx = 0; enumIdx < enumData.size(); enumIdx++) {
+                String enumVal = (enumData.get(enumIdx));
+                byte[] decodedVal = Base64.decode(enumVal);
+                if (decodedVal != null && (new String(decodedVal)).length() < xsFacets.minLength) {
+                   reportSchemaWarning("FacetsContradict", new Object[]{enumVal, SchemaSymbols.ELT_MINLENGTH, typeName}, contextNode);
+                }
+            }
+        }
+        else {
+            for (int enumIdx = 0; enumIdx < enumData.size(); enumIdx++) {
+                String enumVal = (enumData.get(enumIdx));
+                if (enumVal.length() < xsFacets.minLength) {
+                    reportSchemaWarning("FacetsContradict", new Object[]{enumVal, SchemaSymbols.ELT_MINLENGTH, typeName}, contextNode);
+                }
+            }
+        }
+    } // checkEnumerationAndMinLengthInconsistency
+
+    /*
+     * Check whether values of xs:length and xs:enumeration are consistent. Report a warning message if they are not.
+     */
+    private void checkEnumerationAndLengthInconsistency(XSSimpleType baseValidator, List<String> enumData, Element contextNode, String typeName) {
+        if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(baseValidator.getNamespace()) &&
+            SchemaSymbols.ATTVAL_HEXBINARY.equals(baseValidator.getName())) {
+            for (int enumIdx = 0; enumIdx < enumData.size(); enumIdx++) {
+                String enumVal = (enumData.get(enumIdx));
+                if (enumVal.length() / 2 != xsFacets.length) {
+                    reportSchemaWarning("FacetsContradict", new Object[]{enumVal, SchemaSymbols.ELT_LENGTH, typeName}, contextNode);
+                }
+            }
+        }
+        else if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(baseValidator.getNamespace()) &&
+                 SchemaSymbols.ATTVAL_BASE64BINARY.equals(baseValidator.getName())) {
+            for (int enumIdx = 0; enumIdx < enumData.size(); enumIdx++) {
+                String enumVal = (enumData.get(enumIdx));
+                byte[] decodedVal = Base64.decode(enumVal);
+                if (decodedVal != null && (new String(decodedVal)).length() != xsFacets.length) {
+                   reportSchemaWarning("FacetsContradict", new Object[]{enumVal, SchemaSymbols.ELT_LENGTH, typeName}, contextNode);
+                }
+            }
+        }
+        else {
+            for (int enumIdx = 0; enumIdx < enumData.size(); enumIdx++) {
+                String enumVal = (enumData.get(enumIdx));
+                if (enumVal.length() != xsFacets.length) {
+                    reportSchemaWarning("FacetsContradict", new Object[]{enumVal, SchemaSymbols.ELT_LENGTH, typeName}, contextNode);
+                }
+            }
+        }
+    } // checkEnumerationAndLengthInconsistency
+
 
     // return whether QName/NOTATION is part of the given type
     private boolean containsQName(XSSimpleType type) {
         if (type.getVariety() == XSSimpleType.VARIETY_ATOMIC) {
             short primitive = type.getPrimitiveKind();

@@ -722,10 +864,14 @@
 
     void reportSchemaError (String key, Object[] args, Element ele) {
         fSchemaHandler.reportSchemaError(key, args, ele);
     }
 
+    void reportSchemaWarning (String key, Object[] args, Element ele) {
+        fSchemaHandler.reportSchemaWarning(key, args, ele);
+    }
+
     /**
      * Element/Attribute traversers call this method to check whether
      * the type is NOTATION without enumeration facet
      */
     void checkNotationType(String refName, XSTypeDefinition typeDecl, Element elem) {
< prev index next >