You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2007/09/19 07:39:18 UTC

svn commit: r577164 - in /openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf: ConfigurationImpl.java PluginListValue.java Value.java

Author: ppoddar
Date: Tue Sep 18 22:39:17 2007
New Revision: 577164

URL: http://svn.apache.org/viewvc?rev=577164&view=rev
Log:
OPENJPA-305: Add originalValue for Value and modify Configuration equality/hashCode to base on Value equality/hashCode

Modified:
    openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/ConfigurationImpl.java
    openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/PluginListValue.java
    openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/Value.java

Modified: openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/ConfigurationImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/ConfigurationImpl.java?rev=577164&r1=577163&r2=577164&view=diff
==============================================================================
--- openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/ConfigurationImpl.java (original)
+++ openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/ConfigurationImpl.java Tue Sep 18 22:39:17 2007
@@ -778,8 +778,9 @@
     /////////////
 
     /**
-     * Performs an equality check based on the properties returned from
-     * {@link #toProperties}.
+     * Performs an equality check based on equality of values.
+     * {@link Value#equals(Object) Equality} of Values varies if the Value is
+     * {@link Value#isDynamic() dynamic}.  
      */
     public boolean equals(Object other) {
         if (other == this)
@@ -791,18 +792,32 @@
 
         // compare properties
         ConfigurationImpl conf = (ConfigurationImpl) other;
-        Map p1 = (_props == null) ? toProperties(false) : _props;
-        Map p2 = (conf._props == null) ? conf.toProperties(false) : conf._props;
-        return excludeDynamic(p1).equals(excludeDynamic(p2));
+        if (_vals.size() != conf.getValues().length)
+        	return false;
+        Iterator values = _vals.iterator();
+        while (values.hasNext()) {
+        	Value v = (Value)values.next();
+        	Value thatV = conf.getValue(v.getProperty());
+        	if (!v.equals(thatV)) {
+        		return false;
+        	}
+        }
+        return true;
     }
 
     /**
-     * Computes hash code based on the properties returned from
-     * {@link #toProperties}.
+     * Computes hash code based on the hashCodes of the values.
+     * {@link Value#hashCode() HashCode} of a Value varies if the Value is
+     * {@link Value#isDynamic() dynamic}.  
      */
     public int hashCode() {
-    	Map copy = (_props == null) ? toProperties(false) : _props;
-    	return excludeDynamic(copy).hashCode();
+        Iterator values = _vals.iterator();
+        int hash = 0;
+        while (values.hasNext()) {
+        	Value v = (Value)values.next();
+        	hash += v.hashCode();
+        }
+        return hash;
     }
 
     /**
@@ -977,17 +992,5 @@
         PluginListValue val = new PluginListValue(property);
         addValue(val);
         return val;
-    }
-    
-    Map excludeDynamic(Map map) {
-    	if (map == null)
-    		return null;
-    	Map copy = new HashMap(map);
-    	Value[] values = getValues();
-    	for (int i=0; i<values.length; i++) {
-    		if (values[i].isDynamic())
-    			Configurations.removeProperty(values[i].getProperty(), copy);
-    	}
-    	return copy;
     }
 }

Modified: openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/PluginListValue.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/PluginListValue.java?rev=577164&r1=577163&r2=577164&view=diff
==============================================================================
--- openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/PluginListValue.java (original)
+++ openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/PluginListValue.java Tue Sep 18 22:39:17 2007
@@ -110,7 +110,8 @@
         for (int i = 0; i < _names.length; i++) {
             if (i > 0)
                 buf.append(", ");
-            buf.append(Configurations.getPlugin(alias(_names[i]), _props[i]));
+            buf.append(Configurations.getPlugin(alias(_names[i]), 
+            		(i<_props.length) ? _props[i] : null));
         }
         if (buf.length() == 0)
             return null;

Modified: openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/Value.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/Value.java?rev=577164&r1=577163&r2=577164&view=diff
==============================================================================
--- openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/Value.java (original)
+++ openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/Value.java Tue Sep 18 22:39:17 2007
@@ -29,6 +29,7 @@
  * A configuration value.
  *
  * @author Marc Prud'hommeaux
+ * @author Pinaki Poddar (added dynamic Value support)
  */
 public abstract class Value implements Cloneable {
 
@@ -44,6 +45,7 @@
     private boolean aliasListComprehensive = false;
     private Class scope = null;
     private boolean isDynamic = false;
+    private String originalValue = null;
 
     /**
      * Default constructor.
@@ -278,12 +280,22 @@
      * empty and a default is defined, the default is used. If the given
      * string(or default) is an alias key, it will be converted to the
      * corresponding value internally.
+     * <br>
+     * If this Value is being set to a non-default value for the first time
+     * (as designated by <code>originalString</code> being null), then the
+     * value is remembered as <em>original</em>. This original value is used
+     * for equality and hashCode computation if this Value is
+     * {@link #isDynamic() dynamic}. 
+     *
      */
     public void setString(String val) {
     	assertChangeable();
         String str = unalias(val);
         try {
             setInternalString(str);
+            if (originalValue == null && val != null && !isDefault(val)) {
+            	originalValue = getString();
+            }
         } catch (ParseException pe) {
             throw pe;
         } catch (RuntimeException re) {
@@ -293,6 +305,13 @@
 
     /**
      * Set this value as an object.
+     * <br>
+     * If this Value is being set to a non-default value for the first time
+     * (as designated by <code>originalString</code> being null), then the
+     * value is remembered as <em>original</em>. This original value is used
+     * for equality and hashCode computation if this Value is
+     * {@link #isDynamic() dynamic}. 
+     * 
      */
     public void setObject(Object obj) {
         // if setting to null set as string to get defaults into play
@@ -301,6 +320,9 @@
         else {
             try {
                 setInternalObject(obj);
+                if (originalValue == null && obj != null && !isDefault(obj)) {
+                	originalValue = getString();
+                }
             } catch (ParseException pe) {
                 throw pe;
             } catch (RuntimeException re) {
@@ -308,6 +330,22 @@
             }
         }
     }
+    
+    /**
+     * Gets the original value. Original value denotes the Stringified form of 
+     * this Value, from which it has been set, if ever. If this Value has never 
+     * been set to a non-default value, then returns the default value, which 
+     * itself can be null. 
+     * 
+     * @since 1.1.0
+     */
+    public String getOriginalValue() {
+    	return (originalValue == null) ? getDefault() : originalValue;
+    }
+    
+    boolean isDefault(Object val) {
+    	return val != null && val.toString().equals(getDefault());
+    }
 
     /**
      * Returns the type of the property that this Value represents.
@@ -374,6 +412,7 @@
      * Sets if this receiver can be mutated even when the configuration it 
      * belongs to has been {@link Configuration#isReadOnly() frozen}.
      *  
+     * @since 1.1.0
      */
     public void setDynamic(boolean flag) {
     	isDynamic = flag;
@@ -383,18 +422,31 @@
      * Affirms if this receiver can be mutated even when the configuration it 
      * belongs to has been {@link Configuration#isReadOnly() frozen}.
      *  
+     * @since 1.1.0
      */
     public boolean isDynamic() {
     	return isDynamic; 
     }
 
+    /**
+     * Use {@link #getOriginalValue() original value} instead of 
+     * {@link #getString() current value} because they are one and the same 
+     * for non-dynamic Values and ensures that modifying dynamic Values do not
+     * impact equality or hashCode contract.   
+     */
     public int hashCode() {
-        String str = getString();
+        String str = (isDynamic()) ? getOriginalValue() : getString();
         int strHash = (str == null) ? 0 : str.hashCode();
         int propHash = (prop == null) ? 0 : prop.hashCode();
         return strHash ^ propHash;
     }
 
+    /**
+     * Use {@link #getOriginalValue() original value} instead of 
+     * {@link #getString() current value} because they are one and the same 
+     * for non-dynamic Values and ensures that modifying dynamic Values do not
+     * impact equality or hashCode contract.   
+     */
     public boolean equals(Object other) {
         if (other == this)
             return true;
@@ -402,8 +454,11 @@
             return false;
 
         Value o = (Value) other;
-        return StringUtils.equals(prop, o.getProperty())
-            && StringUtils.equals(getString(), o.getString());
+        String thisStr = (isDynamic()) ? getOriginalValue() : getString();
+        String thatStr = (isDynamic()) ? o.getOriginalValue() : o.getString();
+        return (isDynamic() == o.isDynamic())
+            && StringUtils.equals(prop, o.getProperty())
+            && StringUtils.equals(thisStr, thatStr);
     }
 
     public Object clone() {