Add approximate operator and fix a couple bugs. (FELIX-2039)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@926976 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/capabilityset/CapabilitySet.java b/framework/src/main/java/org/apache/felix/framework/capabilityset/CapabilitySet.java
index 466af81..910cb01 100644
--- a/framework/src/main/java/org/apache/felix/framework/capabilityset/CapabilitySet.java
+++ b/framework/src/main/java/org/apache/felix/framework/capabilityset/CapabilitySet.java
@@ -19,6 +19,7 @@
package org.apache.felix.framework.capabilityset;
import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -338,19 +339,19 @@
return true;
}
+ // The substring operator only works on string values, so if the
+ // lhs is not a string, then do an equality comparison using the
+ // original string containing wildcards.
+ if ((op == SimpleFilter.SUBSTRING) && !(lhs instanceof String))
+ {
+ op = SimpleFilter.EQ;
+ rhsUnknown = SimpleFilter.unparseSubstring((List<String>) rhsUnknown);
+ }
+
// If the type is comparable, then we can just return the
// result immediately.
if (lhs instanceof Comparable)
{
- // The substring operator only works on string values, so if the
- // lhs is not a string, then do an equality comparison using the
- // original string containing wildcards.
- if ((op == SimpleFilter.SUBSTRING) && !(lhs instanceof String))
- {
- op = SimpleFilter.EQ;
- rhsUnknown = SimpleFilter.unparseSubstring((List<String>) rhsUnknown);
- }
-
Object rhs;
if (op == SimpleFilter.SUBSTRING)
{
@@ -376,8 +377,8 @@
return (((Comparable) lhs).compareTo(rhs) >= 0);
case SimpleFilter.LTE :
return (((Comparable) lhs).compareTo(rhs) <= 0);
-// case SimpleFilter.APPROX :
-// return compareToApprox(((Comparable) lhs), rhs);
+ case SimpleFilter.APPROX :
+ return compareApproximate(((Comparable) lhs), rhs);
case SimpleFilter.SUBSTRING :
return SimpleFilter.compareSubstring((String) lhs, (List<String>) rhs);
default:
@@ -403,7 +404,7 @@
case SimpleFilter.EQ :
case SimpleFilter.GTE :
case SimpleFilter.LTE :
-// case SimpleFilter.APPROX:
+ case SimpleFilter.APPROX :
return (lhs.equals(rhs));
default:
throw new RuntimeException(
@@ -446,6 +447,30 @@
}
}
+ private static boolean compareApproximate(Object lhs, Object rhs)
+ {
+ if (rhs instanceof String)
+ {
+ String s = (String) rhs;
+ StringBuffer sb = new StringBuffer(s.length());
+ for (int i = 0; i < s.length(); i++)
+ {
+ if (!Character.isWhitespace(s.charAt(i)))
+ {
+ sb.append(s.charAt(i));
+ }
+ }
+ s = sb.toString();
+ return s.equalsIgnoreCase((String) lhs);
+ }
+ else if (rhs instanceof Character)
+ {
+ return Character.toLowerCase(((Character) lhs))
+ == Character.toLowerCase(((Character) rhs));
+ }
+ return lhs.equals(rhs);
+ }
+
private static Object coerceType(Object lhs, String rhsString) throws Exception
{
// If the LHS expects a string, then we can just return
@@ -468,9 +493,10 @@
}
else
{
- rhs = lhs.getClass()
- .getConstructor(STRING_CLASS)
- .newInstance(new Object[] { rhsString });
+// TODO: FELIX3 - Use SecureAction.
+ Constructor ctor = lhs.getClass().getConstructor(STRING_CLASS);
+ ctor.setAccessible(true);
+ rhs = ctor.newInstance(new Object[] { rhsString });
}
}
catch (Exception ex)
diff --git a/framework/src/main/java/org/apache/felix/framework/capabilityset/SimpleFilter.java b/framework/src/main/java/org/apache/felix/framework/capabilityset/SimpleFilter.java
index 42205e9..1e0ae63 100644
--- a/framework/src/main/java/org/apache/felix/framework/capabilityset/SimpleFilter.java
+++ b/framework/src/main/java/org/apache/felix/framework/capabilityset/SimpleFilter.java
@@ -33,6 +33,7 @@
// special case of string equality comparison?
public static final int SUBSTRING = 7;
public static final int PRESENT = 8;
+ public static final int APPROX = 9;
private final String m_name;
private final Object m_value;
@@ -89,6 +90,9 @@
case PRESENT:
s = "(" + m_name + "=*)";
break;
+ case APPROX:
+ s = "(" + m_name + "~=" + toEncodedString(m_value) + ")";
+ break;
}
return s;
}
@@ -249,7 +253,7 @@
private static SimpleFilter subfilter(String filter, int startIdx, int endIdx)
{
- final String opChars = "=<>";
+ final String opChars = "=<>~";
// Determine the ending index of the attribute name.
int attrEndIdx = startIdx;
@@ -301,6 +305,15 @@
op = GTE;
startIdx += 2;
break;
+ case '~':
+ if (filter.charAt(startIdx + 1) != '=')
+ {
+ throw new IllegalArgumentException(
+ "Unknown operator: " + filter.substring(startIdx, endIdx));
+ }
+ op = APPROX;
+ startIdx += 2;
+ break;
default:
throw new IllegalArgumentException(
"Unknown operator: " + filter.substring(startIdx, endIdx));