From 61810baf638c3ba9564f01f6c80fc09d429a128d Mon Sep 17 00:00:00 2001
From: "Brian S. O'Neill" <bronee@gmail.com>
Date: Tue, 22 Jan 2008 01:58:06 +0000
Subject: Filter and FilterValues are now Serializable.

---
 .../com/amazon/carbonado/filter/AndFilter.java     |  2 +
 .../com/amazon/carbonado/filter/ClosedFilter.java  |  9 +++-
 .../com/amazon/carbonado/filter/ExistsFilter.java  |  2 +
 .../java/com/amazon/carbonado/filter/Filter.java   | 12 ++++--
 .../com/amazon/carbonado/filter/FilterValues.java  | 49 +++++++++++++++++++---
 .../com/amazon/carbonado/filter/OpenFilter.java    |  9 +++-
 .../java/com/amazon/carbonado/filter/OrFilter.java |  2 +
 .../amazon/carbonado/filter/PropertyFilter.java    |  2 +
 .../com/amazon/carbonado/info/ChainedProperty.java |  9 +++-
 .../carbonado/info/StorableIntrospector.java       | 39 +++++++++++++++++
 .../amazon/carbonado/info/StorableProperty.java    |  3 +-
 11 files changed, 126 insertions(+), 12 deletions(-)

(limited to 'src/main/java/com/amazon')

diff --git a/src/main/java/com/amazon/carbonado/filter/AndFilter.java b/src/main/java/com/amazon/carbonado/filter/AndFilter.java
index a260b8c..09d0d9f 100644
--- a/src/main/java/com/amazon/carbonado/filter/AndFilter.java
+++ b/src/main/java/com/amazon/carbonado/filter/AndFilter.java
@@ -30,6 +30,8 @@ import com.amazon.carbonado.info.ChainedProperty;
  * @author Brian S O'Neill
  */
 public class AndFilter<S extends Storable> extends BinaryOpFilter<S> {
+    private static final long serialVersionUID = 1L;
+
     /**
      * Returns a canonical instance.
      *
diff --git a/src/main/java/com/amazon/carbonado/filter/ClosedFilter.java b/src/main/java/com/amazon/carbonado/filter/ClosedFilter.java
index 0630bab..b4bd00e 100644
--- a/src/main/java/com/amazon/carbonado/filter/ClosedFilter.java
+++ b/src/main/java/com/amazon/carbonado/filter/ClosedFilter.java
@@ -32,7 +32,14 @@ import com.amazon.carbonado.info.ChainedProperty;
  * @author Brian S O'Neill
  */
 public class ClosedFilter<S extends Storable> extends Filter<S> {
-    ClosedFilter(Class<S> type) {
+    private static final long serialVersionUID = 1L;
+
+    @SuppressWarnings("unchecked")
+    static <S extends Storable> ClosedFilter<S> getCanonical(Class<S> type) {
+        return (ClosedFilter<S>) cCanonical.put(new ClosedFilter<S>(type));
+    }
+
+    private ClosedFilter(Class<S> type) {
         super(type);
     }
 
diff --git a/src/main/java/com/amazon/carbonado/filter/ExistsFilter.java b/src/main/java/com/amazon/carbonado/filter/ExistsFilter.java
index 0e5abf2..b30c01b 100644
--- a/src/main/java/com/amazon/carbonado/filter/ExistsFilter.java
+++ b/src/main/java/com/amazon/carbonado/filter/ExistsFilter.java
@@ -34,6 +34,8 @@ import com.amazon.carbonado.info.StorableProperty;
  * @since 1.2
  */
 public class ExistsFilter<S extends Storable> extends Filter<S> {
+    private static final long serialVersionUID = 1L;
+
     /**
      * Returns a canonical instance, creating a new one if there isn't one
      * already in the cache.
diff --git a/src/main/java/com/amazon/carbonado/filter/Filter.java b/src/main/java/com/amazon/carbonado/filter/Filter.java
index aaf00f6..abaf09a 100644
--- a/src/main/java/com/amazon/carbonado/filter/Filter.java
+++ b/src/main/java/com/amazon/carbonado/filter/Filter.java
@@ -19,6 +19,7 @@
 package com.amazon.carbonado.filter;
 
 import java.io.IOException;
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -65,7 +66,7 @@ import com.amazon.carbonado.util.Appender;
  *
  * @author Brian S O'Neill
  */
-public abstract class Filter<S extends Storable> implements Appender {
+public abstract class Filter<S extends Storable> implements Serializable, Appender {
 
     private static final Object OPEN_KEY = new Object();
     private static final Object CLOSED_KEY = new Object();
@@ -111,7 +112,7 @@ public abstract class Filter<S extends Storable> implements Appender {
         synchronized (filterCache) {
             Filter<S> filter = filterCache.get(OPEN_KEY);
             if (filter == null) {
-                filter = new OpenFilter<S>(type);
+                filter = OpenFilter.getCanonical(type);
                 filterCache.put(OPEN_KEY, filter);
             }
             return (OpenFilter<S>) filter;
@@ -131,7 +132,7 @@ public abstract class Filter<S extends Storable> implements Appender {
         synchronized (filterCache) {
             Filter<S> filter = filterCache.get(CLOSED_KEY);
             if (filter == null) {
-                filter = new ClosedFilter<S>(type);
+                filter = ClosedFilter.getCanonical(type);
                 filterCache.put(CLOSED_KEY, filter);
             }
             return (ClosedFilter<S>) filter;
@@ -793,6 +794,11 @@ public abstract class Filter<S extends Storable> implements Appender {
     public abstract void appendTo(Appendable app, FilterValues<S> values)
         throws IOException;
 
+    // Package-private in order to be inherited by subclasses.
+    Object readResolve() {
+        return cCanonical.put(this);
+    }
+
     /**
      * Result from calling {@link Filter#notJoinedFrom}.
      */
diff --git a/src/main/java/com/amazon/carbonado/filter/FilterValues.java b/src/main/java/com/amazon/carbonado/filter/FilterValues.java
index 331ee3f..954d3ac 100644
--- a/src/main/java/com/amazon/carbonado/filter/FilterValues.java
+++ b/src/main/java/com/amazon/carbonado/filter/FilterValues.java
@@ -18,7 +18,11 @@
 
 package com.amazon.carbonado.filter;
 
+import java.io.Externalizable;
 import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.Serializable;
 import java.util.IdentityHashMap;
 import java.util.Map;
 
@@ -31,7 +35,7 @@ import com.amazon.carbonado.util.Appender;
  *
  * @author Brian S O'Neill
  */
-public class FilterValues<S extends Storable> implements Appender {
+public class FilterValues<S extends Storable> implements Serializable, Appender {
     private static final Object[] NO_VALUES = new Object[0];
 
     static <S extends Storable> FilterValues<S>
@@ -55,10 +59,10 @@ public class FilterValues<S extends Storable> implements Appender {
         return fv;
     }
 
-    private final Filter<S> mFilter;
-    private final PropertyFilterList<S> mCurrentProperty;
-    private final FilterValues<S> mPrevValues;
-    private final Object mPrevValue;
+    private final transient Filter<S> mFilter;
+    private final transient PropertyFilterList<S> mCurrentProperty;
+    private final transient FilterValues<S> mPrevValues;
+    private final transient Object mPrevValue;
 
     private transient volatile Map<PropertyFilter<S>, Object> mValueMap;
 
@@ -721,4 +725,39 @@ public class FilterValues<S extends Storable> implements Appender {
 
         b.append("th");
     }
+
+    private Object writeReplace() {
+        return new FaV(mFilter, getSuppliedValues());
+    }
+
+    // Filter and Values
+    private static class FaV implements Externalizable {
+        private static final long serialVersionUID = 1L;
+
+        private Filter<?> mFilter;
+        private Object[] mValues;
+
+        // Required for Externalizable.
+        public FaV() {
+        }
+
+        FaV(Filter<?> filter, Object[] values) {
+            mFilter = filter;
+            mValues = values;
+        }
+
+        public void writeExternal(ObjectOutput out) throws IOException {
+            out.writeObject(mFilter);
+            out.writeObject(mValues);
+        }
+
+        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+            mFilter = (Filter<?>) in.readObject();
+            mValues = (Object[]) in.readObject();
+        }
+
+        private Object readResolve() {
+            return mFilter.initialFilterValues().withValues(mValues);
+        }
+    }
 }
diff --git a/src/main/java/com/amazon/carbonado/filter/OpenFilter.java b/src/main/java/com/amazon/carbonado/filter/OpenFilter.java
index 35659e6..d14e7a8 100644
--- a/src/main/java/com/amazon/carbonado/filter/OpenFilter.java
+++ b/src/main/java/com/amazon/carbonado/filter/OpenFilter.java
@@ -32,7 +32,14 @@ import com.amazon.carbonado.info.ChainedProperty;
  * @author Brian S O'Neill
  */
 public class OpenFilter<S extends Storable> extends Filter<S> {
-    OpenFilter(Class<S> type) {
+    private static final long serialVersionUID = 1L;
+
+    @SuppressWarnings("unchecked")
+    static <S extends Storable> OpenFilter<S> getCanonical(Class<S> type) {
+        return (OpenFilter<S>) cCanonical.put(new OpenFilter<S>(type));
+    }
+
+    private OpenFilter(Class<S> type) {
         super(type);
     }
 
diff --git a/src/main/java/com/amazon/carbonado/filter/OrFilter.java b/src/main/java/com/amazon/carbonado/filter/OrFilter.java
index a06912a..64be6be 100644
--- a/src/main/java/com/amazon/carbonado/filter/OrFilter.java
+++ b/src/main/java/com/amazon/carbonado/filter/OrFilter.java
@@ -30,6 +30,8 @@ import com.amazon.carbonado.info.ChainedProperty;
  * @author Brian S O'Neill
  */
 public class OrFilter<S extends Storable> extends BinaryOpFilter<S> {
+    private static final long serialVersionUID = 1L;
+
     /**
      * Returns a canonical instance.
      *
diff --git a/src/main/java/com/amazon/carbonado/filter/PropertyFilter.java b/src/main/java/com/amazon/carbonado/filter/PropertyFilter.java
index c3c5c79..37d92e0 100644
--- a/src/main/java/com/amazon/carbonado/filter/PropertyFilter.java
+++ b/src/main/java/com/amazon/carbonado/filter/PropertyFilter.java
@@ -35,6 +35,8 @@ import com.amazon.carbonado.info.StorableProperty;
  * @author Brian S O'Neill
  */
 public class PropertyFilter<S extends Storable> extends Filter<S> {
+    private static final long serialVersionUID = 1L;
+
     // Indicates property has been bound to a constant value.
     private static int BOUND_CONSTANT = -1;
 
diff --git a/src/main/java/com/amazon/carbonado/info/ChainedProperty.java b/src/main/java/com/amazon/carbonado/info/ChainedProperty.java
index 71f1ba5..d30fc8f 100644
--- a/src/main/java/com/amazon/carbonado/info/ChainedProperty.java
+++ b/src/main/java/com/amazon/carbonado/info/ChainedProperty.java
@@ -19,6 +19,7 @@
 package com.amazon.carbonado.info;
 
 import java.io.IOException;
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -36,7 +37,9 @@ import com.amazon.carbonado.util.Appender;
  *
  * @author Brian S O'Neill
  */
-public class ChainedProperty<S extends Storable> implements Appender {
+public class ChainedProperty<S extends Storable> implements Serializable, Appender {
+    private static final long serialVersionUID = 1L;
+
     static WeakCanonicalSet cCanonical = new WeakCanonicalSet();
 
     /**
@@ -578,4 +581,8 @@ public class ChainedProperty<S extends Storable> implements Appender {
             app.append(')');
         }
     }
+
+    private Object readResolve() {
+        return cCanonical.put(this);
+    }
 }
diff --git a/src/main/java/com/amazon/carbonado/info/StorableIntrospector.java b/src/main/java/com/amazon/carbonado/info/StorableIntrospector.java
index 7e8fbf8..fdfb51f 100644
--- a/src/main/java/com/amazon/carbonado/info/StorableIntrospector.java
+++ b/src/main/java/com/amazon/carbonado/info/StorableIntrospector.java
@@ -18,7 +18,10 @@
 
 package com.amazon.carbonado.info;
 
+import java.io.Externalizable;
 import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
 import java.lang.annotation.Annotation;
 import java.lang.ref.Reference;
 import java.lang.ref.SoftReference;
@@ -2080,6 +2083,42 @@ public class StorableIntrospector {
 
             return derivedToSet.size() > originalSize;
         }
+
+        // Package-private in order to be inherited by subclasses.
+        Object writeReplace() {
+            return new NaET(mName, mEnclosingType);
+        }
+
+        // Name and Enclosing Type
+        private static class NaET implements Externalizable {
+            private static final long serialVersionUID = 1L;
+
+            private String mName;
+            private Class<? extends Storable> mEnclosingType;
+
+            // Required for Externalizable.
+            public NaET() {
+            }
+
+            NaET(String name, Class<? extends Storable> enclosingType) {
+                mName = name;
+                mEnclosingType = enclosingType;
+            }
+
+            public void writeExternal(ObjectOutput out) throws IOException {
+                out.writeObject(mName);
+                out.writeObject(mEnclosingType);
+            }
+
+            public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+                mName = (String) in.readObject();
+                mEnclosingType = (Class<? extends Storable>) in.readObject();
+            }
+
+            private Object readResolve() {
+                return StorableIntrospector.examine(mEnclosingType).getAllProperties().get(mName);
+            }
+        }
     }
 
     private static final class JoinProperty<S extends Storable> extends SimpleProperty<S> {
diff --git a/src/main/java/com/amazon/carbonado/info/StorableProperty.java b/src/main/java/com/amazon/carbonado/info/StorableProperty.java
index 53b5098..0d77481 100644
--- a/src/main/java/com/amazon/carbonado/info/StorableProperty.java
+++ b/src/main/java/com/amazon/carbonado/info/StorableProperty.java
@@ -18,6 +18,7 @@
 
 package com.amazon.carbonado.info;
 
+import java.io.Serializable;
 import java.lang.reflect.Method;
 import com.amazon.carbonado.Storable;
 import com.amazon.carbonado.util.Appender;
@@ -28,7 +29,7 @@ import com.amazon.carbonado.util.Appender;
  * @author Brian S O'Neill
  * @see StorableIntrospector
  */
-public interface StorableProperty<S extends Storable> extends Appender {
+public interface StorableProperty<S extends Storable> extends Serializable, Appender {
     /**
      * Returns the name of this property.
      */
-- 
cgit v1.2.3