Author: fanningpj
Date: Sun Jul  5 23:22:24 2026
New Revision: 1935920

Log:
report length facets in JavaNotationHolderEx.validateLexical. Thanks to aizu-m. 
This closes #72

Added:
   
xmlbeans/trunk/src/test/java/misc/checkin/NotationLengthFacetValidateTest.java
Modified:
   
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/JavaNotationHolderEx.java
   
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/NamespaceContext.java
   
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/XmlAnySimpleTypeImpl.java
   
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/XmlAnySimpleTypeRestriction.java
   
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/XmlBase64BinaryImpl.java
   
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/XmlComplexContentImpl.java
   
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/XmlObjectBase.java

Modified: 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/JavaNotationHolderEx.java
==============================================================================
--- 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/JavaNotationHolderEx.java
      Sun Jul  5 23:16:17 2026        (r1935919)
+++ 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/JavaNotationHolderEx.java
      Sun Jul  5 23:22:24 2026        (r1935920)
@@ -27,7 +27,7 @@ import javax.xml.namespace.QName;
 
 public abstract class JavaNotationHolderEx extends JavaNotationHolder
 {
-    private SchemaType _schemaType;
+    private final SchemaType _schemaType;
 
 
     public SchemaType schemaType()
@@ -89,7 +89,35 @@ public abstract class JavaNotationHolder
             }
         }
 
-        check(v, sType);
+        // check against length
+        XmlObject len = sType.getFacet(SchemaType.FACET_LENGTH);
+        if (len != null)
+        {
+            int m = ((XmlObjectBase)len).getBigIntegerValue().intValue();
+            if (v.length() != m)
+                context.invalid(XmlErrorCodes.DATATYPE_LENGTH_VALID$STRING,
+                    new Object[] { "NOTATION", v.length(), m, 
QNameHelper.readable(sType) });
+        }
+
+        // check against min length
+        XmlObject min = sType.getFacet(SchemaType.FACET_MIN_LENGTH);
+        if (min != null)
+        {
+            int m = ((XmlObjectBase)min).getBigIntegerValue().intValue();
+            if (v.length() < m)
+                context.invalid(XmlErrorCodes.DATATYPE_MIN_LENGTH_VALID$STRING,
+                    new Object[] { "NOTATION", v.length(), m, 
QNameHelper.readable(sType) });
+        }
+
+        // check against max length
+        XmlObject max = sType.getFacet(SchemaType.FACET_MAX_LENGTH);
+        if (max != null)
+        {
+            int m = ((XmlObjectBase)max).getBigIntegerValue().intValue();
+            if (v.length() > m)
+                context.invalid(XmlErrorCodes.DATATYPE_MAX_LENGTH_VALID$STRING,
+                    new Object[] { "NOTATION", v.length(), m, 
QNameHelper.readable(sType) });
+        }
 
         return name;
     }
@@ -119,8 +147,7 @@ public abstract class JavaNotationHolder
         if (max != null)
         {
             int m = ((XmlObjectBase)max).getBigIntegerValue().intValue();
-            if (!(v.length() <= m))
-                return false;
+            return v.length() <= m;
         }
 
         return true;

Modified: 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/NamespaceContext.java
==============================================================================
--- 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/NamespaceContext.java
  Sun Jul  5 23:16:17 2026        (r1935919)
+++ 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/NamespaceContext.java
  Sun Jul  5 23:22:24 2026        (r1935920)
@@ -23,7 +23,6 @@ import org.apache.xmlbeans.XmlCursor;
 import java.util.ArrayList;
 import java.util.Map;
 import java.lang.reflect.Proxy;
-import java.lang.ref.SoftReference;
 
 import org.apache.xmlbeans.xml.stream.StartElement;
 
@@ -35,8 +34,8 @@ public class NamespaceContext implements
     private static final int START_ELEMENT = 4;
     private static final int RESOLVER      = 5;
 
-    private Object _obj;
-    private int _code;
+    private final Object _obj;
+    private final int _code;
 
     public NamespaceContext(Map prefixToUriMap)
     {
@@ -88,7 +87,8 @@ public class NamespaceContext implements
         }
     }
 
-    private static ThreadLocal tl_namespaceContextStack = new ThreadLocal();
+    private static final ThreadLocal<NamespaceContextStack> 
tl_namespaceContextStack =
+            new ThreadLocal<>();
 
     public static void clearThreadLocals() {
         tl_namespaceContextStack.remove();
@@ -96,7 +96,7 @@ public class NamespaceContext implements
 
     private static NamespaceContextStack getNamespaceContextStack()
     {
-        NamespaceContextStack namespaceContextStack = (NamespaceContextStack) 
tl_namespaceContextStack.get();
+        NamespaceContextStack namespaceContextStack = 
tl_namespaceContextStack.get();
         if (namespaceContextStack==null)
         {
             namespaceContextStack = new NamespaceContextStack();
@@ -115,7 +115,7 @@ public class NamespaceContext implements
         NamespaceContextStack nsContextStack = getNamespaceContextStack();
         nsContextStack.pop();
 
-        if (nsContextStack.stack.size()==0)
+        if (nsContextStack.stack.isEmpty())
             tl_namespaceContextStack.set(null);
     }
 

Modified: 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/XmlAnySimpleTypeImpl.java
==============================================================================
--- 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/XmlAnySimpleTypeImpl.java
      Sun Jul  5 23:16:17 2026        (r1935919)
+++ 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/XmlAnySimpleTypeImpl.java
      Sun Jul  5 23:22:24 2026        (r1935920)
@@ -67,7 +67,7 @@ public class XmlAnySimpleTypeImpl extend
     }
 
     protected int value_hash_code() {
-        // matches JavaStringHolder's value_hash_code, so we can be hased 
against strings
+        // matches JavaStringHolder's value_hash_code, so we can be hashed 
against strings
         return (_textvalue == null ? 0 : _textvalue.hashCode());
     }
 }

Modified: 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/XmlAnySimpleTypeRestriction.java
==============================================================================
--- 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/XmlAnySimpleTypeRestriction.java
       Sun Jul  5 23:16:17 2026        (r1935919)
+++ 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/XmlAnySimpleTypeRestriction.java
       Sun Jul  5 23:22:24 2026        (r1935920)
@@ -19,11 +19,15 @@ import org.apache.xmlbeans.SchemaType;
 
 public class XmlAnySimpleTypeRestriction extends XmlAnySimpleTypeImpl
 {
-    public XmlAnySimpleTypeRestriction(SchemaType type, boolean complex)
-        { _schemaType = type; initComplexType(complex, false); }
+    private final SchemaType _schemaType;
 
-    private SchemaType _schemaType;
+    public XmlAnySimpleTypeRestriction(SchemaType type, boolean complex) {
+        _schemaType = type;
+        initComplexType(complex, false);
+    }
 
-    public SchemaType schemaType()
-        { return _schemaType; }
+
+    public SchemaType schemaType() {
+        return _schemaType;
+    }
 }

Modified: 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/XmlBase64BinaryImpl.java
==============================================================================
--- 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/XmlBase64BinaryImpl.java
       Sun Jul  5 23:16:17 2026        (r1935919)
+++ 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/XmlBase64BinaryImpl.java
       Sun Jul  5 23:22:24 2026        (r1935920)
@@ -15,7 +15,6 @@
 
 package org.apache.xmlbeans.impl.values;
 
-import org.apache.xmlbeans.SchemaType;
 import org.apache.xmlbeans.XmlBase64Binary;
 
 

Modified: 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/XmlComplexContentImpl.java
==============================================================================
--- 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/XmlComplexContentImpl.java
     Sun Jul  5 23:16:17 2026        (r1935919)
+++ 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/XmlComplexContentImpl.java
     Sun Jul  5 23:22:24 2026        (r1935920)
@@ -69,12 +69,9 @@ public class XmlComplexContentImpl exten
 
     // LEFT
     public boolean equal_to(XmlObject complexObject) {
-        if (!_schemaType.equals(complexObject.schemaType())) {
-            return false;
-        }
+        return _schemaType.equals(complexObject.schemaType());
 
         // BUGBUG: by-value structure comparison undone
-        return true;
     }
 
     // LEFT

Modified: 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/XmlObjectBase.java
==============================================================================
--- 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/XmlObjectBase.java 
    Sun Jul  5 23:16:17 2026        (r1935919)
+++ 
xmlbeans/trunk/src/main/java/org/apache/xmlbeans/impl/values/XmlObjectBase.java 
    Sun Jul  5 23:22:24 2026        (r1935920)
@@ -15,7 +15,6 @@
 
 package org.apache.xmlbeans.impl.values;
 
-import net.sf.saxon.expr.Component;
 import org.apache.xmlbeans.*;
 import org.apache.xmlbeans.impl.common.*;
 import org.apache.xmlbeans.impl.schema.SchemaTypeImpl;
@@ -1098,7 +1097,7 @@ public abstract class XmlObjectBase impl
         if ((_flags & FLAG_HASDEFAULT) != 0 && (_flags & FLAG_SETTINGDEFAULT) 
== 0) {
             // This isn't quite correct since the .equals("") test should be
             // done on the actual text, not the wscanon text
-            if ((_flags & FLAG_ATTRIBUTE) == 0 && v.equals("")) {
+            if ((_flags & FLAG_ATTRIBUTE) == 0 && v.isEmpty()) {
                 String def = get_store().compute_default_text();
                 if (def == null) {
                     throw new XmlValueOutOfRangeException();
@@ -1817,13 +1816,6 @@ public abstract class XmlObjectBase impl
             synchronized (monitor()) {
                 assert (instanceType.getSimpleVariety() == SchemaType.ATOMIC);
                 switch (instanceType.getPrimitiveType().getBuiltinTypeCode()) {
-                    default:
-                        assert (false) : "encountered nonprimitive type.";
-                        // case SchemaType.BTC_ANY_SIMPLE:  This is handled 
below...
-                        // but we eventually want to handle it with a 
treecopy, so
-                        // eventually we should break here.
-                        break primitive;
-
                     case SchemaType.BTC_BOOLEAN: {
                         boolean bool = ((SimpleValue) v).getBooleanValue();
                         set_prepare();
@@ -1892,16 +1884,16 @@ public abstract class XmlObjectBase impl
                                 set_BigInteger(bi);
                                 break;
                             }
-                            default: {
-                                assert (false) : "invalid numeric bit count";
-                                // fallthrough
-                            }
                             case SchemaType.SIZE_BIG_DECIMAL: {
                                 BigDecimal bd = ((SimpleValue) 
v).getBigDecimalValue();
                                 set_prepare();
                                 set_BigDecimal(bd);
                                 break;
                             }
+                            default: {
+                                assert (false) : "invalid numeric bit count";
+                                // fallthrough
+                            }
                         }
                         break;
                     }
@@ -1958,6 +1950,12 @@ public abstract class XmlObjectBase impl
                         }
                         break;
                     }
+                    default:
+                        assert (false) : "encountered nonprimitive type.";
+                        // case SchemaType.BTC_ANY_SIMPLE:  This is handled 
below...
+                        // but we eventually want to handle it with a 
treecopy, so
+                        // eventually we should break here.
+                        break primitive;
                 }
                 set_commit();
                 return; // primitive node tree copy handled.
@@ -2986,8 +2984,7 @@ public abstract class XmlObjectBase impl
                         // System.out.println("Count: " + count + " " + 
cur.currentTokenType().toString() + " " + QName.pretty(cur.getName()));
                     }
                 }
-                XmlObject result = cur.getObject();
-                return result;
+                return cur.getObject();
             }
         }
     }
@@ -3045,11 +3042,11 @@ public abstract class XmlObjectBase impl
                     case SchemaType.SIZE_BIG_INTEGER:
                         return base.getBigIntegerValue();
 
+                    case SchemaType.SIZE_BIG_DECIMAL:
+                        return base.getBigDecimalValue();
                     default:
                         assert (false) : "invalid numeric bit count";
                         // fallthrough
-                    case SchemaType.SIZE_BIG_DECIMAL:
-                        return base.getBigDecimalValue();
                 }
             }
             case SchemaType.BTC_ANY_URI:
@@ -3067,19 +3064,19 @@ public abstract class XmlObjectBase impl
             case SchemaType.BTC_G_DAY:
             case SchemaType.BTC_G_MONTH:
                 return base.getCalendarValue();
-
+                case SchemaType.BTC_NOTATION:
+            case SchemaType.BTC_STRING:
+            case SchemaType.BTC_ANY_SIMPLE:
+                // return base.getStringValue();
+                return base.getStringValue();
             default:
                 assert (false) : "encountered nonprimitive type.";
                 // fallthrough
 
                 // NB: for string enums we just do java.lang.String
                 // when in the context of unions. It's easier on users.
-            case SchemaType.BTC_NOTATION:
-            case SchemaType.BTC_STRING:
-            case SchemaType.BTC_ANY_SIMPLE:
-                // return base.getStringValue();
-                return base.getStringValue();
         }
+        return null;
     }
 
     /**

Added: 
xmlbeans/trunk/src/test/java/misc/checkin/NotationLengthFacetValidateTest.java
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ 
xmlbeans/trunk/src/test/java/misc/checkin/NotationLengthFacetValidateTest.java  
    Sun Jul  5 23:22:24 2026        (r1935920)
@@ -0,0 +1,77 @@
+/*   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache 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.apache.org/licenses/LICENSE-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 misc.checkin;
+
+import org.apache.xmlbeans.SchemaTypeLoader;
+import org.apache.xmlbeans.XmlBeans;
+import org.apache.xmlbeans.XmlError;
+import org.apache.xmlbeans.XmlObject;
+import org.apache.xmlbeans.XmlOptions;
+import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class NotationLengthFacetValidateTest {
+
+    // A maxLength facet is applied to a NOTATION type whose inherited 
enumeration
+    // still admits a longer member, so the enumeration check alone does not 
catch
+    // the length violation.
+    private static final String XSD =
+        "<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' " +
+        "xmlns:t='urn:t' targetNamespace='urn:t' 
elementFormDefault='qualified'>" +
+        "  <xs:notation name='a' public='PA'/>" +
+        "  <xs:notation name='bcdefgh' public='PB'/>" +
+        "  <xs:simpleType name='baseN'>" +
+        "    <xs:restriction base='xs:NOTATION'>" +
+        "      <xs:enumeration value='t:a'/>" +
+        "      <xs:enumeration value='t:bcdefgh'/>" +
+        "    </xs:restriction>" +
+        "  </xs:simpleType>" +
+        "  <xs:element name='root'>" +
+        "    <xs:simpleType>" +
+        "      <xs:restriction base='t:baseN'>" +
+        "        <xs:maxLength value='3'/>" +
+        "      </xs:restriction>" +
+        "    </xs:simpleType>" +
+        "  </xs:element>" +
+        "</xs:schema>";
+
+    private static boolean validate(String notationValue) throws Exception {
+        SchemaTypeLoader loader = XmlBeans.loadXsd(new 
XmlObject[]{SchemaDocument.Factory.parse(XSD)});
+        XmlObject doc = loader.parse(
+            "<t:root xmlns:t='urn:t'>" + notationValue + "</t:root>", null, 
null);
+        List<XmlError> errors = new ArrayList<>();
+        return doc.validate(new XmlOptions().setErrorListener(errors));
+    }
+
+    @Test
+    void notationWithinMaxLengthValidates() throws Exception {
+        // 't:a' is in the enumeration and its lexical length (3) matches 
maxLength
+        assertTrue(validate("t:a"));
+    }
+
+    @Test
+    void notationViolatingMaxLengthIsInvalid() throws Exception {
+        // 't:bcdefgh' is in the inherited enumeration but its lexical length 
(9)
+        // exceeds maxLength=3, so document validation must reject it
+        assertFalse(validate("t:bcdefgh"));
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to