Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 60 additions & 36 deletions src/org/apache/xpath/XPathCollationSupport.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import javax.xml.transform.TransformerException;

/**
* This class provides, collation support to XalanJ's XPath 3.1
* This class provides, collation support for XalanJ's XPath 3.1
* implementation.
*
* Ref : https://www.w3.org/TR/xpath-functions-31/#collations
Expand Down Expand Up @@ -99,25 +99,26 @@ public XPathCollationSupport(String defaultCollationUri) {
*
* @throws javax.xml.transform.TransformerException
*/
public int compareStringsUsingCollationUri(String str1, String str2, String collationUri)
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 collator = getCollatorFromCollationUri(collationUri);
Collator strComparisonCollator = getUCACollatorFromCollationUri(collationUri);

if (collator != null) {
comparisonResult = collator.compare(str1, str2);
if (strComparisonCollator != null) {
comparisonResult = strComparisonCollator.compare(str1, str2);
}
else if (UCA_FALLBACK_YES.equals(fQueryStrFallbackValue)) {
comparisonResult = compareStringsUsingCollationUri(str1, str2, fDefaultCollationUri);
comparisonResult = compareStringsUsingCollation(str1, str2, fDefaultCollationUri);
}
else {
throw new javax.xml.transform.TransformerException("FOCH0002 : The requested collation '" + collationUri + "' is not supported.");
throw new javax.xml.transform.TransformerException("FOCH0002 : The requested collation '" + collationUri +
"' is not supported.");
}
}
catch (javax.xml.transform.TransformerException ex) {
Expand Down Expand Up @@ -157,7 +158,8 @@ public int[] getCodepointsFromString(String str) {
}

/**
* This method compares, two string values using 'unicode codepoint collation'.
* 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
Expand All @@ -177,7 +179,7 @@ private int compareStringsUsingUnicodeCodepointCollation(String str1, String str

/**
* Compare two int[] arrays comprising unicode codepoints, according to
* 'unicode codepoint collation'.
* 'Unicode Codepoint Collation'.
*/
private int compareCodepointArrays(int[] codePointsArr1, int[] codePointsArr2) {

Expand Down Expand Up @@ -256,26 +258,25 @@ private int[] getIntArrayFromIntegerList(List<Integer> integerList) {
}

/**
* This method helps to implement, 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).
* 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 collation uri, specified by users of XPath 3.1 string comparison
* , or sorting of strings.
* @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 getCollatorFromCollationUri(String collationUri) throws TransformerException {
private Collator getUCACollatorFromCollationUri(String collationUri) throws TransformerException {

Collator strComparisonCollator = null;

try {
if (collationUri.equals(UNICODE_COLLATION_ALGORITHM_URI)) {
strComparisonCollator = Collator.getInstance(DEFAULT_UCA_LOCALE);
strComparisonCollator.setStrength(Collator.TERTIARY);
strComparisonCollator = getDefaultUCACollator();
}
else {
int ucaUriPrefixLength = UNICODE_COLLATION_ALGORITHM_URI.length();
Expand Down Expand Up @@ -338,6 +339,34 @@ private Collator getCollatorFromCollationUri(String collationUri) throws Transfo
return strComparisonCollator;
}

/**
* Get the java.text.Collator object, for XalanJ's
* default collation when using 'unicode collation algorithm'.
*/
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.TERTIARY);
break;
default :
// no op
}

return strComparisonCollator;
}

/**
* From the requested collation uri, build a corresponding java.util.Map object
* representation.
Expand Down Expand Up @@ -419,21 +448,24 @@ private void buildSupportedUCAParamList() {
}

/**
* An object of this class, stores definition of one
* "Unicode Collation Algorithm" (UCA) uri query
* parameter.
* 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, keyword/parameter name
// (for e.g, 'fallback', 'lang', 'strength').
// Variable denoting, UCA keyword name (for e.g,
// 'fallback', 'lang', 'strength').
private String keywordName;

// Variable denoting, permitted values for the keyword/parameter
// name.
// For e.g, the 'fallback' parameter has possible values 'yes'/'no'.
// The 'strength' parameter has possible values 'primary',
// 'secondary', 'tertiary', 'identical'.
// 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) {
Expand All @@ -445,17 +477,9 @@ public String getKeywordName() {
return keywordName;
}

public void setKeywordName(String keywordName) {
this.keywordName = keywordName;
}

public List<String> getParamValues() {
return paramValues;
}

public void setParamValues(List<String> paramValues) {
this.paramValues = paramValues;
}

}

Expand Down
8 changes: 4 additions & 4 deletions src/org/apache/xpath/functions/FuncCompare.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ public XObject execute(XPathContext xctxt) throws javax.xml.transform.Transforme
// set the collation to default collation
String collationUri = xctxt.getDefaultCollation();

int comparisonResult = xPathCollationSupport.compareStringsUsingCollationUri(
str0, str1, collationUri);
int comparisonResult = xPathCollationSupport.compareStringsUsingCollation(
str0, str1, collationUri);

result = new XSInteger(BigInteger.valueOf((long)comparisonResult));
}
Expand All @@ -100,8 +100,8 @@ public XObject execute(XPathContext xctxt) throws javax.xml.transform.Transforme

String collationUri = XslTransformEvaluationHelper.getStrVal(xObject2);

int comparisonResult = xPathCollationSupport.compareStringsUsingCollationUri(
str0, str1, collationUri);
int comparisonResult = xPathCollationSupport.compareStringsUsingCollation(
str0, str1, collationUri);

result = new XSInteger(BigInteger.valueOf((long)comparisonResult));
}
Expand Down
56 changes: 40 additions & 16 deletions src/org/apache/xpath/functions/FuncSort.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,21 @@ public XObject execute(XPathContext xctxt) throws javax.xml.transform.Transforme
List<InpSeqItemWithSortKeyValue> inpSeqItemWithSortKeyValueList = new
ArrayList<InpSeqItemWithSortKeyValue>();

if ((numOfArgs == 3) || (numOfArgs == 2)) {
arg1 = m_arg1;
String collationUri = xctxt.getDefaultCollation();

if ((numOfArgs == 2) || (numOfArgs == 3)) {
arg1 = m_arg1;

XObject XObjArg1 = arg1.execute(xctxt);

if (!((XObjArg1 instanceof ResultSequence) &&
(((ResultSequence)XObjArg1).size() == 0))) {
throw new javax.xml.transform.TransformerException("FORG0006 : The collation corresponding to supplied value of "
+ "second argument to function call fn:sort, is "
+ "not supported.", srcLocator);
if ((XObjArg1 instanceof ResultSequence) &&
(((ResultSequence)XObjArg1).size() == 0)) {
collationUri = xctxt.getDefaultCollation();
}
else {
// a collation uri was, explicitly provided during the function call fn:sort

collationUri = XslTransformEvaluationHelper.getStrVal(XObjArg1);
}

arg2 = m_arg2;
Expand Down Expand Up @@ -160,7 +166,12 @@ else if ((numOfArgs == 2) || (numOfArgs == 1)) {
}
}

inpSeqItemWithSortKeyValueList.sort(new FnSortComparator(srcLocator));
FnSortComparator fnSortComparator = new FnSortComparator(collationUri, srcLocator);
inpSeqItemWithSortKeyValueList.sort(fnSortComparator);

if (fnSortComparator.getErrMessage() != null) {
throw new javax.xml.transform.TransformerException(fnSortComparator.getErrMessage(), srcLocator);
}

for (int idx = 0; idx < inpSeqItemWithSortKeyValueList.size(); idx++) {
InpSeqItemWithSortKeyValue inpSeqItemWithSortKeyValue = inpSeqItemWithSortKeyValueList.get(idx);
Expand Down Expand Up @@ -208,7 +219,12 @@ else if ((numOfArgs == 2) || (numOfArgs == 1)) {
}
}

inpSeqItemWithSortKeyValueList.sort(new FnSortComparator(srcLocator));
FnSortComparator fnSortComparator = new FnSortComparator(collationUri, srcLocator);
inpSeqItemWithSortKeyValueList.sort(fnSortComparator);

if (fnSortComparator.getErrMessage() != null) {
throw new javax.xml.transform.TransformerException(fnSortComparator.getErrMessage(), srcLocator);
}

for (int idx = 0; idx < inpSeqItemWithSortKeyValueList.size(); idx++) {
InpSeqItemWithSortKeyValue inpSeqItemWithSortKeyValue = inpSeqItemWithSortKeyValueList.get(idx);
Expand Down Expand Up @@ -289,14 +305,19 @@ public void setInpSeqItemSortKeyVal(XObject inpSeqItemSortKeyVal) {
* An object of this class, is used to support sorting of an
* xdm input sequence.
*/
class FnSortComparator implements Comparator {
private class FnSortComparator implements Comparator {

private String collationUri;

private SourceLocator srcLocator;

private String errMesg = null;

/*
* The class constructor.
*/
public FnSortComparator(SourceLocator srcLocator) {
public FnSortComparator(String collationUri, SourceLocator srcLocator) {
this.collationUri = collationUri;
this.srcLocator = srcLocator;
}

Expand All @@ -308,20 +329,23 @@ public int compare(Object obj1, Object obj2) {
XObject sortKeyVal2 = ((InpSeqItemWithSortKeyValue)obj2).getInpSeqItemSortKeyVal();

try {
if (sortKeyVal1.vcGreaterThan(sortKeyVal2, null, true)) {
if (sortKeyVal1.vcGreaterThan(sortKeyVal2, null, collationUri, true)) {
comparisonResult = 1;
}
else if (sortKeyVal1.vcLessThan(sortKeyVal2, null, false)) {
else if (sortKeyVal1.vcLessThan(sortKeyVal2, null, collationUri, true)) {
comparisonResult = -1;
}
}
catch (javax.xml.transform.TransformerException ex) {
// NO OP
// REVISIT
errMesg = ex.getMessage();
}

return comparisonResult;
}
}

public String getErrMessage() {
return errMesg;
}
}

}
Loading