[lsc-changes] r301 - lsc/branches/v1.1/src/main/java/org/lsc/beans
jclarke at lsc-project.org
jclarke at lsc-project.org
Mon Jul 20 17:34:05 CEST 2009
Author: jclarke
Date: 2009-07-20 17:34:05 +0200 (Mon, 20 Jul 2009)
New Revision: 301
Modified:
lsc/branches/v1.1/src/main/java/org/lsc/beans/BeanComparator.java
Log:
Backporting commit #300 to 1.1 branch
Modified: lsc/branches/v1.1/src/main/java/org/lsc/beans/BeanComparator.java
===================================================================
--- lsc/branches/v1.1/src/main/java/org/lsc/beans/BeanComparator.java 2009-07-20 15:32:29 UTC (rev 300)
+++ lsc/branches/v1.1/src/main/java/org/lsc/beans/BeanComparator.java 2009-07-20 15:34:05 UTC (rev 301)
@@ -529,97 +529,155 @@
*/
private static ModificationItem compareAttribute(Attribute srcAttr, Attribute dstAttr) throws NamingException {
- boolean differs = false;
+ // convert to easily comparable type
+ List<Object> srcAttrValues = attributeToList(srcAttr);
+ List<Object> dstAttrValues = attributeToList(dstAttr);
- // read in all values from dstAttr
- List<Object> dstAttrValues = new ArrayList<Object>(dstAttr.size());
- NamingEnumeration<?> dstNe = dstAttr.getAll();
- while (dstNe.hasMore()) {
- dstAttrValues.add(dstNe.next());
- }
+ if (!doAttributesMatch(srcAttrValues, dstAttrValues))
+ {
+ // build up replacement attribute
+ Attribute toReplaceAttr = new BasicAttribute(srcAttr.getID());
+ for (Object srcValue : srcAttrValues)
+ {
+ toReplaceAttr.add(srcValue);
+ }
- // check if there are any values in srcAttr not in dstAttr
- // and build up replacement attribute, in case
- Attribute toReplaceAttr = new BasicAttribute(srcAttr.getID());
- NamingEnumeration<?> srcNe = srcAttr.getAll();
- while (srcNe.hasMore()) {
- Object srcValue = srcNe.next();
+ LOGGER.debug("Attribute " + dstAttr.getID() + ": source values are " + srcAttr + ", old values were " + dstAttr + ", new values are " + toReplaceAttr);
- if (srcValue != null) {
- toReplaceAttr.add(srcValue);
+ return new ModificationItem(DirContext.REPLACE_ATTRIBUTE, toReplaceAttr);
+ }
+ else return null;
- // Handle binary attribute specifically
- if (srcValue.getClass().isAssignableFrom(byte[].class)) {
- ByteBuffer srcBuff = ByteBuffer.wrap((byte[]) srcValue);
- for (Object dstValue : dstAttrValues) {
- // make sure destination value is a byte[] too
- if (dstValue.getClass().isAssignableFrom(String.class)) {
- dstValue = ((String) dstValue).getBytes();
- }
- if (!dstValue.getClass().isAssignableFrom(byte[].class)) {
- differs = true;
- break;
- }
+ }
- ByteBuffer destBuff = ByteBuffer.wrap((byte[]) dstValue);
- if (srcBuff.compareTo(destBuff) != 0) {
- differs = true;
- break;
- }
- }
- } else {
- if (!dstAttrValues.contains(srcValue)) {
- differs = true;
- }
- }
- }
- }
+ /**
+ * Compare two lists of values to see if they contain the same values. This
+ * method is type-aware and will intelligently compare byte[], String, etc.
+ *
+ * @param srcAttrValues
+ * @param dstAttrValues
+ * @return
+ */
+ private static boolean doAttributesMatch(List<Object> srcAttrValues, List<Object> dstAttrValues)
+ {
+ // make sure value counts are the same
+ if (srcAttrValues.size() != dstAttrValues.size()) return false;
- // check if there are any values in dstAttr not in srcAttr
- Iterator<Object> dstIt = dstAttrValues.iterator();
- while (dstIt.hasNext()) {
- Object dstValue = dstIt.next();
+ // check if there are any values in srcAttr not in dstAttr
+ if (!listContainsAll(dstAttrValues, srcAttrValues)) return false;
- // Handle binary attribute specifically
- if (dstValue.getClass().isAssignableFrom(byte[].class)) {
- ByteBuffer destBuff = ByteBuffer.wrap((byte[]) dstValue);
+ // check if there are any values in dstAttr not in srcAttr
+ if (!listContainsAll(srcAttrValues, dstAttrValues)) return false;
- NamingEnumeration<?> toReplaceAttrValues = toReplaceAttr.getAll();
+ // looks ok!
+ return true;
+ }
- while (toReplaceAttrValues.hasMore()) {
- Object o = toReplaceAttrValues.next();
+ /**
+ * Check to make sure all needles are in the haystack. In other words each
+ * value from the list needles must be in the list haystack. This method is
+ * type-aware and will intelligently compare byte[], String, etc.
+ *
+ * @param haystack
+ * List of Objects to find the needles in.
+ * @param needles
+ * List of Objects to search for in the haystack.
+ */
+ private static boolean listContainsAll(List<Object> haystack, List<Object> needles)
+ {
+ return (findMissingNeedles(haystack, needles).size() == 0);
+ }
- // make sure source value is a byte[] too
- if (o.getClass().isAssignableFrom(String.class)) {
- o = ((String) o).getBytes();
- }
- if (!o.getClass().isAssignableFrom(byte[].class)) {
- differs = true;
- break;
- }
+ /**
+ * Find missing needles from a haystack. In other words, identify values in
+ * the list of needles that are not in the haystack, and return them in a
+ * new List. This method is type-aware and will intelligently compare
+ * byte[], String, etc.
+ *
+ * @param haystack
+ * List of Objects to find the needles in.
+ * @param needles
+ * List of Objects to search for in the haystack.
+ * @return
+ */
+ private static List<Object> findMissingNeedles(List<Object> haystack, List<Object> needles)
+ {
+ List<Object> missingNeedles = new ArrayList<Object>();
- ByteBuffer toReplaceBuff = ByteBuffer.wrap((byte[]) o);
- if (toReplaceBuff.compareTo(destBuff) != 0) {
- differs = true;
- break;
- }
- }
- } else {
- if (!toReplaceAttr.contains(dstValue)) {
- differs = true;
- break;
- }
- }
- }
+ for (Object needle : needles)
+ {
+ ByteBuffer needleBuff = null;
- if (differs) {
- LOGGER.debug("Attribute " + dstAttr.getID() + ": source values are " + srcAttr + ", old values were " + dstAttr + ", new values are " + toReplaceAttr);
- return new ModificationItem(DirContext.REPLACE_ATTRIBUTE, toReplaceAttr);
- } else {
- return null;
- }
- }
+ // use a byte buffer is needle is binary
+ if (needle.getClass().isAssignableFrom(byte[].class)) needleBuff = ByteBuffer.wrap((byte[]) needle);
+ boolean foundInHaystack = false;
+ for (Object haystackValue : haystack)
+ {
+ ByteBuffer haystackValueBuff = null;
+
+ // use a byte buffer if haystack value is binary
+ if (haystackValue.getClass().isAssignableFrom(byte[].class))
+ {
+ haystackValueBuff = ByteBuffer.wrap((byte[]) haystackValue);
+
+ // make sure we have a byte buffer for the needle too
+ if (needleBuff == null)
+ {
+ // if needle is binary, make this haystack value binary
+ if (needle.getClass().isAssignableFrom(String.class)) needleBuff = ByteBuffer.wrap(((String) needle).getBytes());
+ else continue;
+ }
+ }
+
+ // needleBuff is set if either needle or haystack value are binary
+ // do a binary comparison
+ if (needleBuff != null)
+ {
+ // make sure we have a byte buffer for haystack value too
+ if (haystackValueBuff == null)
+ {
+ if (haystackValue.getClass().isAssignableFrom(String.class)) haystackValueBuff = ByteBuffer.wrap(((String) haystackValue).getBytes());
+ else continue;
+ }
+
+ // binary comparison
+ if (haystackValueBuff.compareTo(needleBuff) == 0) foundInHaystack = true;
+ }
+ else
+ {
+ // fall back to standard compare (works well for String, int, boolean, etc)
+ if (haystackValue.equals(needle)) foundInHaystack = true;
+ }
+ }
+
+ if (!foundInHaystack) missingNeedles.add(needle);
+ }
+
+ return missingNeedles;
+ }
+
+ /**
+ * Return an ArrayList containing all the Objects that are an Attribute's
+ * values.
+ *
+ * @param attr
+ * An Attribute containing values to extract.
+ * @return ArrayList<Object> values as an array.
+ * @throws NamingException
+ */
+ private static List<Object> attributeToList(Attribute attr)
+ throws NamingException
+ {
+ List<Object> attrValues = new ArrayList<Object>(attr.size());
+ NamingEnumeration<?> ne = attr.getAll();
+ while (ne.hasMore())
+ {
+ attrValues.add(ne.next());
+ }
+ return attrValues;
+ }
+
/**
* Merge two attributes and compute a modification item
*
@@ -633,39 +691,19 @@
private static ModificationItem mergeAttributes(Attribute srcAttr, Attribute dstAttr) throws NamingException {
// read in all values from dstAttr
- List<Object> dstAttrValues = new ArrayList<Object>(dstAttr.size());
- NamingEnumeration<?> dstNe = dstAttr.getAll();
- while (dstNe.hasMore()) {
- Object o = dstNe.next();
- dstAttrValues.add((String) o);
- }
+ List<Object> dstAttrValues = attributeToList(dstAttr);
+ List<Object> srcAttrValues = attributeToList(srcAttr);
// check if there are any extra values to be added from the source attribute
- Attribute addValuesAttr = new BasicAttribute(srcAttr.getID());
- NamingEnumeration<?> srcNe = srcAttr.getAll();
- Object value;
- while (srcNe.hasMore()) {
- value = srcNe.next();
+ List<Object> missingValues = findMissingNeedles(dstAttrValues, srcAttrValues);
+
+ if (missingValues.size() > 0) {
+ // build an attribute to add missing values
+ Attribute addValuesAttr = new BasicAttribute(dstAttr.getID());
+ for (Object missingValue : missingValues) {
+ addValuesAttr.add(missingValue);
+ }
- if (value != null) {
- if (value.getClass().isAssignableFrom(byte[].class)) {
- ByteBuffer srcBuff = ByteBuffer.wrap((byte[]) value);
-
- for (Object dstValue : dstAttrValues) {
- ByteBuffer destBuff = ByteBuffer.wrap((byte[]) dstValue);
- if (srcBuff.compareTo(destBuff) != 0) {
- addValuesAttr.add(value);
- }
- }
- } else {
- if (!dstAttrValues.contains(value)) {
- addValuesAttr.add(value);
- }
- }
- }
- }
-
- if (addValuesAttr.size() > 0) {
return new ModificationItem(DirContext.ADD_ATTRIBUTE, addValuesAttr);
} else {
return null;
More information about the lsc-changes
mailing list