You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ri...@apache.org on 2010/01/14 18:49:27 UTC
svn commit: r899324 -
/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/cs/CapabilitySet.java
Author: rickhall
Date: Thu Jan 14 17:49:27 2010
New Revision: 899324
URL: http://svn.apache.org/viewvc?rev=899324&view=rev
Log:
Add more type support to filter matching.
Modified:
felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/cs/CapabilitySet.java
Modified: felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/cs/CapabilitySet.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/cs/CapabilitySet.java?rev=899324&r1=899323&r2=899324&view=diff
==============================================================================
--- felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/cs/CapabilitySet.java (original)
+++ felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/cs/CapabilitySet.java Thu Jan 14 17:49:27 2010
@@ -18,13 +18,13 @@
*/
package org.apache.felix.resolver.cs;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import org.apache.felix.resolver.Version;
public class CapabilitySet
{
@@ -156,30 +156,13 @@
{
Capability cap = it.next();
Attribute attr = cap.getAttribute(sf.getName());
- Comparable value = (Comparable)
- ((attr == null) ? null : cap.getAttribute(sf.getName()).getValue());
- if (value != null)
+ if (attr != null)
{
- switch (sf.getOperation())
+ Object lhs = attr.getValue();
+ Object rhs = coerceType(lhs, (String) sf.getValue());
+ if (compare(lhs, rhs, sf.getOperation()))
{
- case SimpleFilter.EQ:
- if (value.compareTo(coerceType(value, (String) sf.getValue())) == 0)
- {
- matches.add(cap);
- }
- break;
- case SimpleFilter.LTE:
- if (value.compareTo(coerceType(value, (String) sf.getValue())) <= 0)
- {
- matches.add(cap);
- }
- break;
- case SimpleFilter.GTE:
- if (value.compareTo(coerceType(value, (String) sf.getValue())) >= 0)
- {
- matches.add(cap);
- }
- break;
+ matches.add(cap);
}
}
}
@@ -261,49 +244,6 @@
return matched && matchMandatory(cap, sf);
}
- private static final Class[] STRING_CLASS = new Class[] { String.class };
-
- private static Object coerceType(Comparable lhs, String rhs)
- {
- if (lhs instanceof String)
- {
- return rhs;
- }
-
- // Here we know that the LHS is a comparable object, so
- // try to create an object for the RHS by using a constructor
- // that will take the RHS string as a parameter.
- Comparable rhsComparable = null;
- try
- {
- // We are expecting to be able to construct a comparable
- // instance from the RHS string by passing it into the
- // constructor of the corresponing comparable class. The
- // Character class is a special case, since its constructor
- // does not take a string, so handle it separately.
- if (lhs instanceof Character)
- {
- rhsComparable = new Character(rhs.charAt(0));
- }
- else
- {
- rhsComparable = (Comparable) lhs.getClass()
- .getConstructor(STRING_CLASS)
- .newInstance(new Object[] { rhs });
- }
- }
- catch (Exception ex)
- {
- throw new RuntimeException(
- "Could not instantiate class "
- + lhs.getClass().getName()
- + " with constructor String parameter "
- + rhs + " " + ex);
- }
-
- return rhsComparable;
- }
-
private static Set<Capability> matchMandatory(Set<Capability> caps, SimpleFilter sf)
{
for (Iterator<Capability> it = caps.iterator(); it.hasNext(); )
@@ -353,4 +293,210 @@
}
return false;
}
+
+ private static final Class[] STRING_CLASS = new Class[] { String.class };
+
+ private static boolean compare(Object lhs, Object rhs, int op)
+ {
+ // If the type is comparable, then we can just return the
+ // result immediately.
+ if (lhs instanceof Comparable)
+ {
+ switch (op)
+ {
+ case SimpleFilter.EQ :
+ return (((Comparable) lhs).compareTo(rhs) == 0);
+ case SimpleFilter.GTE :
+ return (((Comparable) lhs).compareTo(rhs) >= 0);
+ case SimpleFilter.LTE :
+ return (((Comparable) lhs).compareTo(rhs) <= 0);
+// case SimpleFilter.APPROX :
+// return compareToApprox(((Comparable) lhs), rhs);
+ default:
+ throw new RuntimeException(
+ "Unknown comparison operator: " + op);
+ }
+ }
+ // Booleans do not implement comparable, so special case them.
+ else if (lhs instanceof Boolean)
+ {
+ switch (op)
+ {
+ case SimpleFilter.EQ :
+ case SimpleFilter.GTE :
+ case SimpleFilter.LTE :
+// case SimpleFilter.APPROX:
+ return (lhs.equals(rhs));
+ default:
+ throw new RuntimeException(
+ "Unknown comparison operator: " + op);
+ }
+ }
+ // If the LHS is not a comparable or boolean, check if it is an
+ // array. If so, call compare() on each element of the array until
+ // a match is found.
+ else if (lhs.getClass().isArray())
+ {
+ // If this is an array of primitives, then convert
+ // the entire array to an array of the associated
+ // primitive wrapper class instances.
+ if (lhs.getClass().getComponentType().isPrimitive())
+ {
+ lhs = convertPrimitiveArray(lhs);
+ }
+
+ // Now call compare on each element of array.
+ Object[] array = (Object[]) lhs;
+ for (int i = 0; i < array.length; i++)
+ {
+ if (compare(array[i], rhs, op))
+ {
+ return true;
+ }
+ }
+ }
+ // If LHS is a collection, then call compare() on each element
+ // of the collection until a match is found.
+ else if (lhs instanceof Collection)
+ {
+ for (Iterator iter = ((Collection) lhs).iterator(); iter.hasNext(); )
+ {
+ if (compare(iter.next(), rhs, op))
+ {
+ return true;
+ }
+ }
+ }
+
+ // Since we cannot identify the LHS type, then we can only perform
+ // equality comparison.
+ return lhs.equals(rhs);
+ }
+
+ private static Object coerceType(Object lhs, String rhsString)
+ {
+ // If the LHS expects a string, then we can just return
+ // the RHS since it is a string.
+ if (lhs.getClass() == rhsString.getClass())
+ {
+ return rhsString;
+ }
+
+ // Try to convert the RHS type to the LHS type by using
+ // the string constructor of the LHS class, if it has one.
+ Object rhs = null;
+ try
+ {
+ // The Character class is a special case, since its constructor
+ // does not take a string, so handle it separately.
+ if (lhs instanceof Character)
+ {
+ rhs = new Character(rhsString.charAt(0));
+ }
+ else
+ {
+ rhs = lhs.getClass()
+ .getConstructor(STRING_CLASS)
+ .newInstance(new Object[] { rhsString });
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new RuntimeException(
+ "Could not instantiate class "
+ + lhs.getClass().getName()
+ + " using string constructor with argument '"
+ + rhsString + "' because " + ex);
+ }
+
+ return rhs;
+ }
+
+ /**
+ * This is an ugly utility method to convert an array of primitives
+ * to an array of primitive wrapper objects. This method simplifies
+ * processing LDAP filters since the special case of primitive arrays
+ * can be ignored.
+ * @param array An array of primitive types.
+ * @return An corresponding array using pritive wrapper objects.
+ **/
+ private static Object[] convertPrimitiveArray(Object array)
+ {
+ Class clazz = array.getClass().getComponentType();
+
+ if (clazz == Boolean.TYPE)
+ {
+ boolean[] src = (boolean[]) array;
+ array = new Boolean[src.length];
+ for (int i = 0; i < src.length; i++)
+ {
+ ((Object[]) array)[i] = (src[i] ? Boolean.TRUE : Boolean.FALSE);
+ }
+ }
+ else if (clazz == Character.TYPE)
+ {
+ char[] src = (char[]) array;
+ array = new Character[src.length];
+ for (int i = 0; i < src.length; i++)
+ {
+ ((Object[]) array)[i] = new Character(src[i]);
+ }
+ }
+ else if (clazz == Byte.TYPE)
+ {
+ byte[] src = (byte[]) array;
+ array = new Byte[src.length];
+ for (int i = 0; i < src.length; i++)
+ {
+ ((Object[]) array)[i] = new Byte(src[i]);
+ }
+ }
+ else if (clazz == Short.TYPE)
+ {
+ byte[] src = (byte[]) array;
+ array = new Byte[src.length];
+ for (int i = 0; i < src.length; i++)
+ {
+ ((Object[]) array)[i] = new Byte(src[i]);
+ }
+ }
+ else if (clazz == Integer.TYPE)
+ {
+ int[] src = (int[]) array;
+ array = new Integer[src.length];
+ for (int i = 0; i < src.length; i++)
+ {
+ ((Object[]) array)[i] = new Integer(src[i]);
+ }
+ }
+ else if (clazz == Long.TYPE)
+ {
+ long[] src = (long[]) array;
+ array = new Long[src.length];
+ for (int i = 0; i < src.length; i++)
+ {
+ ((Object[]) array)[i] = new Long(src[i]);
+ }
+ }
+ else if (clazz == Float.TYPE)
+ {
+ float[] src = (float[]) array;
+ array = new Float[src.length];
+ for (int i = 0; i < src.length; i++)
+ {
+ ((Object[]) array)[i] = new Float(src[i]);
+ }
+ }
+ else if (clazz == Double.TYPE)
+ {
+ double[] src = (double[]) array;
+ array = new Double[src.length];
+ for (int i = 0; i < src.length; i++)
+ {
+ ((Object[]) array)[i] = new Double(src[i]);
+ }
+ }
+
+ return (Object[]) array;
+ }
}
\ No newline at end of file