Author: mukulg
Date: Tue Jan 23 17:12:53 2024
New Revision: 1915372

URL: http://svn.apache.org/viewvc?rev=1915372&view=rev
Log:
committing implementation modifications, for adding collation support needed by 
xpath 3.1 fn:deep-equal method. for this, copying the java class 
XPathCollationSupport from xalanj implementation, as well. for these changes, 
xercesj now needs to build with java min 1.8 level (modifying build.xml file as 
well for this).

Added:
    xerces/java/trunk/src/org/apache/xerces/dom/XPathCollationSupport.java   
(with props)
Modified:
    xerces/java/trunk/build.xml
    xerces/java/trunk/src/org/apache/xerces/dom/ElementImpl.java
    xerces/java/trunk/src/org/apache/xerces/dom/NodeEqualityWithQname.java
    xerces/java/trunk/src/org/apache/xerces/dom/NodeImpl.java
    xerces/java/trunk/src/org/apache/xerces/dom/ParentNode.java

Modified: xerces/java/trunk/build.xml
URL: 
http://svn.apache.org/viewvc/xerces/java/trunk/build.xml?rev=1915372&r1=1915371&r2=1915372&view=diff
==============================================================================
--- xerces/java/trunk/build.xml (original)
+++ xerces/java/trunk/build.xml Tue Jan 23 17:12:53 2024
@@ -98,8 +98,8 @@ Authors:
     <!--<property name="javac.source" value="${ant.java.version}"/>
     <property name="javac.target" value="${ant.java.version}"/>-->
     
-    <property name="javac.source" value="1.7"/>
-    <property name="javac.target" value="1.7"/>
+    <property name="javac.source" value="1.8"/>
+    <property name="javac.target" value="1.8"/>
 
     <property name="docs.book" value="${docs.dir}/docs-book.xml"/>
 

Modified: xerces/java/trunk/src/org/apache/xerces/dom/ElementImpl.java
URL: 
http://svn.apache.org/viewvc/xerces/java/trunk/src/org/apache/xerces/dom/ElementImpl.java?rev=1915372&r1=1915371&r2=1915372&view=diff
==============================================================================
--- xerces/java/trunk/src/org/apache/xerces/dom/ElementImpl.java (original)
+++ xerces/java/trunk/src/org/apache/xerces/dom/ElementImpl.java Tue Jan 23 
17:12:53 2024
@@ -941,8 +941,8 @@ public class ElementImpl
      * This method implementation is added, to support use
      * cases like use of XPath 3.1 function fn:deep-equal.
      */
-    public boolean isEqualNodeWithQName(Node arg) {
-        if (!super.isEqualNodeWithQName(arg)) {
+    public boolean isEqualNodeWithQName(Node arg, String collationUri) {
+        if (!super.isEqualNodeWithQName(arg, collationUri)) {
             return false;
         }
         
@@ -1014,7 +1014,7 @@ public class ElementImpl
                     
                     Node n2 = map2.getNamedItemNS(n1.getNamespaceURI(),
                                                   n1.getLocalName());
-                    if (n2 == null || !((NodeImpl) 
n1).isEqualNodeWithQName(n2)) {
+                    if (n2 == null || !((NodeImpl) 
n1).isEqualNodeWithQName(n2, collationUri)) {
                        return false;
                     }
                 }

Modified: xerces/java/trunk/src/org/apache/xerces/dom/NodeEqualityWithQname.java
URL: 
http://svn.apache.org/viewvc/xerces/java/trunk/src/org/apache/xerces/dom/NodeEqualityWithQname.java?rev=1915372&r1=1915371&r2=1915372&view=diff
==============================================================================
--- xerces/java/trunk/src/org/apache/xerces/dom/NodeEqualityWithQname.java 
(original)
+++ xerces/java/trunk/src/org/apache/xerces/dom/NodeEqualityWithQname.java Tue 
Jan 23 17:12:53 2024
@@ -32,6 +32,6 @@ import org.w3c.dom.Node;
  */
 public interface NodeEqualityWithQname {
     
-    public boolean isEqualNodeWithQName(Node arg);
+    public boolean isEqualNodeWithQName(Node arg, String collationUri);
     
 }

Modified: xerces/java/trunk/src/org/apache/xerces/dom/NodeImpl.java
URL: 
http://svn.apache.org/viewvc/xerces/java/trunk/src/org/apache/xerces/dom/NodeImpl.java?rev=1915372&r1=1915371&r2=1915372&view=diff
==============================================================================
--- xerces/java/trunk/src/org/apache/xerces/dom/NodeImpl.java (original)
+++ xerces/java/trunk/src/org/apache/xerces/dom/NodeImpl.java Tue Jan 23 
17:12:53 2024
@@ -22,6 +22,8 @@ import java.io.ObjectOutputStream;
 import java.io.Serializable;
 import java.util.Hashtable;
 
+import javax.xml.transform.TransformerException;
+
 import org.w3c.dom.DOMException;
 import org.w3c.dom.Document;
 import org.w3c.dom.DocumentType;
@@ -1797,7 +1799,7 @@ public abstract class NodeImpl
      * @return If the nodes, and possibly subtrees are equal, 
      *   <code>true</code> otherwise <code>false</code>.
      */
-    public boolean isEqualNodeWithQName(Node arg) {
+    public boolean isEqualNodeWithQName(Node arg, String collationUri) {
         if (arg == this) {
             return true;
         }
@@ -1828,8 +1830,29 @@ public abstract class NodeImpl
                 return false;
             }
         }
-        else if (!getNodeValue().equals(arg.getNodeValue())) {
-            return false;
+        else if (arg.getNodeValue() != null) {
+           String nodeValue1 = getNodeValue();
+           String nodeValue2 = arg.getNodeValue();           
+           if (collationUri != null) {
+               String defaultCollation = 
XPathCollationSupport.UNICODE_CODEPOINT_COLLATION_URI;
+               XPathCollationSupport xPathCollationSupport = new 
XPathCollationSupport(defaultCollation);               
+               
+               int comparisonResult;               
+               try {
+                   comparisonResult = 
xPathCollationSupport.compareStringsUsingCollation(
+                                                                    
nodeValue1, nodeValue2, collationUri);
+                   if (comparisonResult != 0) {
+                      return false;  
+                   }
+               }
+               catch (TransformerException ex) {
+                  // may be, we should handle this exception differently. 
REVISIT
+                  return false; 
+               }
+           }
+           else if (!nodeValue1.equals(nodeValue2)) {
+               return false;
+           }
         }
 
         return true; 

Modified: xerces/java/trunk/src/org/apache/xerces/dom/ParentNode.java
URL: 
http://svn.apache.org/viewvc/xerces/java/trunk/src/org/apache/xerces/dom/ParentNode.java?rev=1915372&r1=1915371&r2=1915372&view=diff
==============================================================================
--- xerces/java/trunk/src/org/apache/xerces/dom/ParentNode.java (original)
+++ xerces/java/trunk/src/org/apache/xerces/dom/ParentNode.java Tue Jan 23 
17:12:53 2024
@@ -881,8 +881,8 @@ public abstract class ParentNode
      * This method implementation is added, to support use
      * cases like use of XPath 3.1 function fn:deep-equal.
      */
-    public boolean isEqualNodeWithQName(Node arg) {
-        if (!super.isEqualNodeWithQName(arg)) {
+    public boolean isEqualNodeWithQName(Node arg, String collationUri) {
+        if (!super.isEqualNodeWithQName(arg, collationUri)) {
             return false;
         }
         
@@ -893,12 +893,11 @@ public abstract class ParentNode
         Node child2 = arg.getFirstChild();
         
         while (child1 != null && child2 != null) {
-            if ((child1 instanceof ElementImpl) && 
-                                             (child2 instanceof ElementImpl)) {
-                if (!((ElementImpl)child1).isEqualNodeWithQName((ElementImpl)
-                                                                           
child2)) {
-                    return false;
-                }  
+            if ((child1 instanceof NodeImpl) && (child2 instanceof NodeImpl)) {
+                if (!((NodeImpl)child1).isEqualNodeWithQName((NodeImpl)
+                                                                     child2, 
collationUri)) {
+                   return false;
+                }
             }
             else if (!child1.isEqualNode(child2)) {
                 return false;

Added: xerces/java/trunk/src/org/apache/xerces/dom/XPathCollationSupport.java
URL: 
http://svn.apache.org/viewvc/xerces/java/trunk/src/org/apache/xerces/dom/XPathCollationSupport.java?rev=1915372&view=auto
==============================================================================
--- xerces/java/trunk/src/org/apache/xerces/dom/XPathCollationSupport.java 
(added)
+++ xerces/java/trunk/src/org/apache/xerces/dom/XPathCollationSupport.java Tue 
Jan 23 17:12:53 2024
@@ -0,0 +1,533 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.xerces.dom;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.xml.transform.TransformerException;
+
+/**
+ * This class provides, collation support for XalanJ's XPath 3.1 
+ * implementation.
+ * 
+ * Ref : https://www.w3.org/TR/xpath-functions-31/#collations
+ * 
+ * @author Mukul Gandhi <muk...@apache.org>
+ * 
+ * @version $Id$
+ *
+ * @xsl.usage advanced
+ */
+public class XPathCollationSupport {
+    
+    public static final String UNICODE_CODEPOINT_COLLATION_URI = 
"http://www.w3.org/2005/xpath-functions/collation/codepoint";;
+    
+    public static final String UNICODE_COLLATION_ALGORITHM_URI = 
"http://www.w3.org/2013/collation/UCA";;
+    
+    public static final String HTML_ASCII_CASE_INSENSITIVE_COLLATION_URI = 
"http://www.w3.org/2005/xpath-functions/collation/html-ascii-case-insensitive";;
+    
+    private final String UCA_KEYWORD_FALLBACK = "fallback";
+    
+    private final String UCA_FALLBACK_YES = "yes";    
+    private final String UCA_FALLBACK_NO = "no";
+    
+    private final String UCA_KEYWORD_LANG = "lang";
+    
+    private final String UCA_KEYWORD_STRENGTH = "strength";
+    
+    private final String UCA_STRENGTH_PRIMARY = "primary";
+    private final String UCA_STRENGTH_SECONDARY = "secondary";
+    private final String UCA_STRENGTH_TERTIARY = "tertiary";
+    private final String UCA_STRENGTH_IDENTICAL = "identical";
+    
+    private final String DEFAULT_UCA_FALLBACK_VALUE = UCA_FALLBACK_YES;
+    
+    private final Locale DEFAULT_UCA_LOCALE = Locale.getDefault();     
+    
+    private final String DEFAULT_UCA_STRENGTH_VALUE = UCA_STRENGTH_TERTIARY;
+    
+    private final String UCA_QUERY_STRING_PREFIX = "?";
+    
+    private final String UCA_QUERY_STRING_PARTS_DELIM = ";";
+    
+    private final String UCA_QUERY_STRING_PART_SUB_DELIM = "=";
+    
+    private List<UCAParameter> fUcaSupportedParameters = new 
ArrayList<UCAParameter>();
+    
+    private String fQueryStrFallbackValue = null;
+    
+    private String fDefaultCollationUri = null;
+    
+    /**
+     * Class constructor.
+     */
+    public XPathCollationSupport(String defaultCollationUri) {
+       fDefaultCollationUri = defaultCollationUri; 
+       buildSupportedUCAParamList();  
+    }
+    
+    /**
+     * This method, compares two string values, using a specified collation.
+     * 
+     * @param str1               the first string
+     * @param str2               the second string
+     * @param collationUri       collation uri
+     * 
+     * @return                   the string comparison result represented as 
an integer value. The value -1
+     *                           indicates that string 'str1' collates before 
string 'str2', the value 1
+     *                           indicates that string 'str1' collates after 
string 'str2', the value 0
+     *                           indicates that string 'str1' is equal to 
string 'str2'. 
+     *                             
+     * @throws javax.xml.transform.TransformerException
+     */
+    public int compareStringsUsingCollation(String str1, String str2, String 
collationUri) 
+                                                                               
   throws javax.xml.transform.TransformerException {
+       int comparisonResult = 0;
+       
+       if (UNICODE_CODEPOINT_COLLATION_URI.equals(collationUri)) {
+          comparisonResult = 
compareStringsUsingUnicodeCodepointCollation(str1, str2);
+       }
+       else if (collationUri.startsWith(UNICODE_COLLATION_ALGORITHM_URI)) {
+          try {
+             Collator strComparisonCollator = 
getUCACollatorFromCollationUri(collationUri);
+             
+             if (strComparisonCollator != null) {
+                comparisonResult = strComparisonCollator.compare(str1, str2);  
              
+             }
+             else if (UCA_FALLBACK_YES.equals(fQueryStrFallbackValue)) {       
             
+                comparisonResult = compareStringsUsingCollation(str1, str2, 
fDefaultCollationUri);
+             }
+             else {
+                throw new javax.xml.transform.TransformerException("FOCH0002 : 
The requested collation '" + collationUri + 
+                                                                               
                                    "' is not supported.");  
+             }
+          }
+          catch (javax.xml.transform.TransformerException ex) {
+             throw new 
javax.xml.transform.TransformerException(ex.getMessage());    
+          }
+            
+          if (comparisonResult < 0) {
+             comparisonResult = -1;  
+          }
+          else if (comparisonResult > 0) {
+             comparisonResult = 1; 
+          }    
+       }
+       else if 
(HTML_ASCII_CASE_INSENSITIVE_COLLATION_URI.equals(collationUri)) {
+          int str1Len = str1.length();
+          int str2Len = str2.length();
+           
+          int idx1 = 0;
+          int idx2 = 0;
+           
+          while (true) {
+             if (idx1 == str1Len) {
+                if (idx2 == str2Len) {
+                   comparisonResult = 0;
+                   break;
+                } else {
+                   comparisonResult = -1;
+                   break;
+                }
+             }
+             
+             if (idx2 == str2Len) {
+                comparisonResult = 1;
+                break;
+             }
+             
+             int codepoint1 = str1.codePointAt(idx1);
+             idx1 += 1;
+             
+             int codepoint2 = str2.codePointAt(idx2);
+             idx2 += 1;
+             
+             if ((codepoint1 >= 'a') && (codepoint1 <= 'z')) {
+                codepoint1 += 'A' - 'a';
+             }
+             
+             if ((codepoint2 >= 'a') && (codepoint2 <= 'z')) {
+                codepoint2 += 'A' - 'a';
+             }
+             
+             int codepointDiff = codepoint1 - codepoint2;             
+             if (codepointDiff != 0) {
+                if (codepointDiff < 0) {
+                   comparisonResult = -1;
+                }
+                else {
+                   comparisonResult = 1; 
+                }                
+                break;
+             }
+          }          
+       }
+       else {
+          throw new javax.xml.transform.TransformerException("FOCH0002 : The 
requested collation '" + collationUri + "' "
+                                                                               
                            + "is not supported."); 
+       }
+       
+       return comparisonResult;
+    }
+    
+    /**
+     * Given a string, get a corresponding primitive integer array of
+     * the codepoints of all the characters of the string in order.
+     */
+    public int[] getCodepointsFromString(String str) {
+        int[] codePointsArr = null;
+        
+        codePointsArr = (str.codePoints()).toArray();
+        
+        return codePointsArr;
+    }
+    
+    /**
+     * This method compares, two string values using 'Unicode Codepoint 
Collation'
+     * as specified by XPath 3.1 F&O spec.
+     *
+     * @param str1    the first string
+     * @param str2    the second string
+     * 
+     * @return        an integer value denoting, the result of comparison
+     */
+    private int compareStringsUsingUnicodeCodepointCollation(String str1, 
String str2) {
+       int comparisonResult = 0;
+       
+       int[] codePointsArr1 = getCodepointsFromString(str1);       
+       int[] codePointsArr2 = getCodepointsFromString(str2);
+       
+       comparisonResult = compareCodepointArrays(codePointsArr1, 
codePointsArr2); 
+       
+       return comparisonResult; 
+    }
+    
+    /**
+     * This method compares two int[] arrays comprising unicode codepoints 
+     * (corresponding to the strings to be compared), according to 'Unicode 
+     * Codepoint Collation' as defined by XPath 3.1 F&O spec.
+     */
+    private int compareCodepointArrays(int[] codePointsArr1, int[] 
codePointsArr2) {
+       
+       int comparisonResult = 0;
+       
+       if (((codePointsArr1 == null) || (codePointsArr1.length == 0)) && 
+           ((codePointsArr2 == null) || (codePointsArr2.length == 0))) {
+          // both strings are equal
+          comparisonResult = 0; 
+       }
+       else if (((codePointsArr1 == null) || (codePointsArr1.length == 0)) &&
+                ((codePointsArr2 != null) && (codePointsArr2.length > 0))) {
+          // the first string collates before the second one
+          comparisonResult = -1; 
+       }
+       else if (((codePointsArr1 != null) && (codePointsArr1.length > 0)) &&
+                ((codePointsArr2 == null) || (codePointsArr2.length == 0))) {
+          // the first string collates after the second one
+          comparisonResult = 1; 
+       }
+       else {
+          // both the strings to be compared, have non empty code point 
+          // arrays.
+          int arr1FirstCodepoint = codePointsArr1[0];
+          int arr2FirstCodepoint = codePointsArr2[0];
+          if (arr1FirstCodepoint < arr2FirstCodepoint) {
+             comparisonResult = -1;  
+          }
+          else if (arr1FirstCodepoint > arr2FirstCodepoint) {
+             comparisonResult = 1; 
+          }
+          else {             
+             List<Integer> list1 = getIntegerListFromIntArray(codePointsArr1);
+             List<Integer> list2 = getIntegerListFromIntArray(codePointsArr2);
+                 
+             // get all, except the first item in the list 'list1'
+             list1 = list1.subList(1, list1.size());
+             
+             // get all, except the first item in the list 'list2'
+             list2 = list2.subList(1, list2.size());
+             
+             // recursive call to this function
+             comparisonResult = 
compareCodepointArrays(getIntArrayFromIntegerList(list1), 
+                                                                       
getIntArrayFromIntegerList(list2));     
+          }
+       }
+       
+       return comparisonResult;
+    }
+    
+    /**
+     * Given an array of primitive integers, get the corresponding
+     * list of type List<Integer>.
+     */
+    private List<Integer> getIntegerListFromIntArray(int[] intArr) {
+       List<Integer> integerList = new ArrayList<Integer>();
+       
+       for (int idx = 0; idx < intArr.length; idx++) {
+          integerList.add(Integer.valueOf(intArr[idx])); 
+       }
+       
+       return integerList;
+    }
+    
+    /**
+     * Given a list of type List<Integer>, get the corresponding array
+     * of primitive integers.  
+     */
+    private int[] getIntArrayFromIntegerList(List<Integer> integerList) {
+       int[] intArray = new int[integerList.size()];
+       
+       for (int idx = 0; idx < integerList.size(); idx++) {
+          intArray[idx] = (integerList.get(idx)).intValue();  
+       }
+       
+       return intArray;
+    }
+    
+    /**
+     * This method implements, 'Unicode Collation Algorithm' as specified by 
XPath 3.1 F&O spec
+     * (which in turn is based on UTS #10 [Unicode Technical Standard #10 : 
Unicode Collation
+     * Algorithm]).
+     * 
+     * @param collationUri     the requested collation uri, during XPath 3.1 
string comparisons,
+     *                         and sorting of strings.
+     *                         
+     * @return                 a configured Java object of type 
java.text.Collator, that callers of
+     *                         this method can use to do locale specific 
string comparisons.
+     * 
+     * @throws TransformerException
+     */
+    private Collator getUCACollatorFromCollationUri(String collationUri) 
throws TransformerException {
+       
+       Collator strComparisonCollator = null;
+       
+       try {
+           if (collationUri.equals(UNICODE_COLLATION_ALGORITHM_URI)) {
+              strComparisonCollator = getDefaultUCACollator();
+           }
+           else {
+              int ucaUriPrefixLength = 
UNICODE_COLLATION_ALGORITHM_URI.length();              
+              String uriAndQueryStrDelim = 
collationUri.substring(ucaUriPrefixLength, ucaUriPrefixLength + 1);
+              
+              if (UCA_QUERY_STRING_PREFIX.equals(uriAndQueryStrDelim)) {
+                 String uriQueryStr = 
collationUri.substring(collationUri.indexOf(UCA_QUERY_STRING_PREFIX) + 1);
+                 Map<String, String> queryStrMap = 
getUCAQueryStrComponents(uriQueryStr);
+                 
+                 String queryStrFallbackValue = 
queryStrMap.get(UCA_KEYWORD_FALLBACK);
+                 String queryStrLangCode = queryStrMap.get(UCA_KEYWORD_LANG);
+                 String queryStrStrengthValue = 
queryStrMap.get(UCA_KEYWORD_STRENGTH);
+                    
+                 if (queryStrFallbackValue == null) {
+                    fQueryStrFallbackValue = DEFAULT_UCA_FALLBACK_VALUE;  
+                 }
+                 else {
+                    fQueryStrFallbackValue = queryStrFallbackValue;  
+                 }
+                    
+                 if (queryStrLangCode == null) {
+                    queryStrLangCode = DEFAULT_UCA_LOCALE.getCountry(); 
+                 }
+                    
+                 if (queryStrStrengthValue == null) {
+                    queryStrStrengthValue = DEFAULT_UCA_STRENGTH_VALUE;  
+                 }
+                    
+                 strComparisonCollator = Collator.getInstance(new 
Locale(queryStrLangCode));
+                    
+                 switch (queryStrStrengthValue) {
+                    case UCA_STRENGTH_PRIMARY :
+                       strComparisonCollator.setStrength(Collator.PRIMARY);
+                       break;
+                    case UCA_STRENGTH_SECONDARY :
+                       strComparisonCollator.setStrength(Collator.SECONDARY);
+                       break;
+                    case UCA_STRENGTH_TERTIARY :
+                       strComparisonCollator.setStrength(Collator.TERTIARY);
+                       break;
+                    case UCA_STRENGTH_IDENTICAL :
+                       strComparisonCollator.setStrength(Collator.IDENTICAL);
+                       break;
+                    default:
+                       // no op    
+                 }
+              }
+              else {
+                 throw new TransformerException("FOCH0002 : The first 
character if present after collation uri '" + 
+                                                                        
UNICODE_COLLATION_ALGORITHM_URI + "' must be "
+                                                                        + "'" 
+ UCA_QUERY_STRING_PREFIX + "', to denote the "
+                                                                        + 
"start of query string within the collation uri.");   
+              }
+           }
+       }
+       catch (Exception ex) {
+           throw new TransformerException(ex.getMessage());  
+       }
+       
+       return strComparisonCollator;
+    }
+    
+    /**
+     * Get the java.text.Collator object, corresponding to XalanJ's 
+     * default collation when using 'Unicode Collation Algorithm' (UCA).
+     */
+    private Collator getDefaultUCACollator() {
+        
+        Collator strComparisonCollator = 
Collator.getInstance(DEFAULT_UCA_LOCALE);
+        
+        switch (DEFAULT_UCA_STRENGTH_VALUE) {
+            case UCA_STRENGTH_PRIMARY :
+               strComparisonCollator.setStrength(Collator.PRIMARY);
+               break;
+            case UCA_STRENGTH_SECONDARY :
+               strComparisonCollator.setStrength(Collator.SECONDARY); 
+               break;
+            case UCA_STRENGTH_TERTIARY :   
+               strComparisonCollator.setStrength(Collator.TERTIARY);
+               break;
+            case UCA_STRENGTH_IDENTICAL :
+               strComparisonCollator.setStrength(Collator.IDENTICAL);
+               break;
+            default :
+               // no op
+        }
+        
+        return strComparisonCollator;
+    }
+    
+    /**
+     * From the requested collation uri, build a corresponding java.util.Map
+     * object representation.  
+     */
+    private Map<String, String> getUCAQueryStrComponents(String uriQueryStr) 
throws TransformerException {
+       Map<String, String> queryStrMap = new HashMap<String, String>();
+       
+       String[] queryStrParts = 
uriQueryStr.split(UCA_QUERY_STRING_PARTS_DELIM);
+       
+       for (int idx = 0; idx < queryStrParts.length; idx++) {
+          String queryStrPart = queryStrParts[idx];
+          int delimIdx = queryStrPart.indexOf(UCA_QUERY_STRING_PART_SUB_DELIM);
+          String keyword = queryStrPart.substring(0, delimIdx);
+          String value = queryStrPart.substring(delimIdx + 1);
+          if (!queryStrMap.containsKey(keyword)) {
+             if (isUCAKeywordAndValueOk(keyword, value)) {
+                queryStrMap.put(keyword, value);
+             }
+             else {
+                throw new TransformerException("FOCH0002 : The keyword 
'"+keyword+"' and corresponding value '" + 
+                                                                               
       value + "', provided within the "
+                                                                               
       + "requested collation uri is not supported.");  
+             }
+          }
+          else {
+             throw new TransformerException("FOCH0002 : The keyword '" + 
keyword + "' occurs more than once, within "
+                                                                               
         + "the specified collation uri."); 
+          }
+       }
+       
+       return queryStrMap;
+    }
+    
+    /**
+     * Check whether, within requested collation uri's query string, the given
+     * keyword and value is supported by XalanJ's XPath 3.1 processor.
+     */
+    private boolean isUCAKeywordAndValueOk(String keyword, String value) {
+       boolean isUCAKeywordAndValueOk = false;
+       
+       for (int idx = 0; idx < fUcaSupportedParameters.size(); idx++) {
+          UCAParameter ucaParameter = fUcaSupportedParameters.get(idx);
+          if ((ucaParameter.getKeywordName()).equals(keyword)) {
+             List<String> paramValues = ucaParameter.getParamValues();
+             if (paramValues.contains(value)) {
+                isUCAKeywordAndValueOk = true;
+                break;
+             }
+          }
+       }
+        
+       return isUCAKeywordAndValueOk; 
+    }
+    
+    /**
+     * This method configures, the collation support provided by
+     * XalanJ XPath 3.1 implementation.
+     */
+    private void buildSupportedUCAParamList() {        
+        List<String> fallbackList = new ArrayList<String>();
+        fallbackList.add(UCA_FALLBACK_YES);
+        fallbackList.add(UCA_FALLBACK_NO);
+        UCAParameter ucaFallbackParam = new UCAParameter(UCA_KEYWORD_FALLBACK, 
fallbackList);
+        
+        String[] isoLanguageCodes = Locale.getISOLanguages();
+        List<String> isoLanguageList = Arrays.asList(isoLanguageCodes);
+        UCAParameter ucaLanguageParam = new UCAParameter(UCA_KEYWORD_LANG, 
isoLanguageList);
+        
+        List<String> collationStrengthList = new ArrayList<String>();
+        collationStrengthList.add(UCA_STRENGTH_PRIMARY);
+        collationStrengthList.add(UCA_STRENGTH_SECONDARY);
+        collationStrengthList.add(UCA_STRENGTH_TERTIARY);
+        collationStrengthList.add(UCA_STRENGTH_IDENTICAL);
+        UCAParameter ucaCollationStrengthParam = new 
UCAParameter(UCA_KEYWORD_STRENGTH, collationStrengthList);
+        
+        fUcaSupportedParameters.add(ucaFallbackParam);
+        fUcaSupportedParameters.add(ucaLanguageParam);
+        fUcaSupportedParameters.add(ucaCollationStrengthParam);
+    }
+    
+    /**
+     * An object of this class, stores data for one 'Unicode 
+     * Collation Algorithm' (UCA) collation uri query parameter/
+     * keyword (the words 'parameter' and 'keyword' are synonym,
+     * here).
+     * 
+     * XalanJ's XPath 3.1 implementation, currently supports only
+     * following UCA parameters : 'fallback', 'lang', 'strength'. 
+     */
+    private class UCAParameter {        
+        
+        // Variable denoting, UCA keyword name (for e.g, 
+        // 'fallback', 'lang', 'strength').
+        private String keywordName;
+        
+        // Variable denoting, permitted values for an UCA keyword (for e.g, 
+        // the 'fallback' parameter has possible values 'yes', 'no'. The 
+        // 'strength' parameter has possible values 'primary', 'secondary',
+        // 'tertiary', 'identical').
+        private List<String> paramValues;
+        
+        public UCAParameter(String keywordName, List<String> paramValues) {
+           this.keywordName = keywordName;
+           this.paramValues = paramValues;
+        }
+
+        public String getKeywordName() {
+            return keywordName;
+        }
+
+        public List<String> getParamValues() {
+            return paramValues;
+        }
+        
+    }
+
+}

Propchange: 
xerces/java/trunk/src/org/apache/xerces/dom/XPathCollationSupport.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
xerces/java/trunk/src/org/apache/xerces/dom/XPathCollationSupport.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@xerces.apache.org
For additional commands, e-mail: commits-h...@xerces.apache.org

Reply via email to