From c5e6a41a0e071e342b6f82d219e390354d34041a Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" <bronee@gmail.com> Date: Fri, 22 Sep 2006 06:40:51 +0000 Subject: Added asJoinedFrom method. Refined return values of subclasses. --- .../com/amazon/carbonado/filter/AndFilter.java | 6 ++++ .../com/amazon/carbonado/filter/ClosedFilter.java | 16 ++++++--- .../java/com/amazon/carbonado/filter/Filter.java | 38 +++++++++++++++++++--- .../com/amazon/carbonado/filter/OpenFilter.java | 14 +++++--- .../java/com/amazon/carbonado/filter/OrFilter.java | 6 ++++ .../amazon/carbonado/filter/PropertyFilter.java | 22 +++++++++++-- 6 files changed, 86 insertions(+), 16 deletions(-) (limited to 'src/main/java') diff --git a/src/main/java/com/amazon/carbonado/filter/AndFilter.java b/src/main/java/com/amazon/carbonado/filter/AndFilter.java index a5aa61e..2b5ff0f 100644 --- a/src/main/java/com/amazon/carbonado/filter/AndFilter.java +++ b/src/main/java/com/amazon/carbonado/filter/AndFilter.java @@ -22,6 +22,8 @@ import java.io.IOException; import com.amazon.carbonado.Storable; +import com.amazon.carbonado.info.ChainedProperty; + /** * Filter tree node that performs a logical 'and' test. * @@ -60,6 +62,10 @@ public class AndFilter<S extends Storable> extends BinaryOpFilter<S> { return mLeft.unbind().and(mRight.unbind()); } + public <T extends Storable> Filter<T> asJoinedFrom(ChainedProperty<T> joinProperty) { + return mLeft.asJoinedFrom(joinProperty).and(mRight.asJoinedFrom(joinProperty)); + } + Filter<S> buildDisjunctiveNormalForm() { Filter<S> left = mLeft.reduce().dnf(); Filter<S> right = mRight.reduce().dnf(); diff --git a/src/main/java/com/amazon/carbonado/filter/ClosedFilter.java b/src/main/java/com/amazon/carbonado/filter/ClosedFilter.java index 7895a3d..6538f8d 100644 --- a/src/main/java/com/amazon/carbonado/filter/ClosedFilter.java +++ b/src/main/java/com/amazon/carbonado/filter/ClosedFilter.java @@ -22,6 +22,8 @@ import java.io.IOException; import com.amazon.carbonado.Storable; +import com.amazon.carbonado.info.ChainedProperty; + /** * Filter which blocks any results from passing through. * @@ -32,7 +34,7 @@ public class ClosedFilter<S extends Storable> extends Filter<S> { super(type); } - public Filter<S> and(Filter<S> filter) { + public ClosedFilter<S> and(Filter<S> filter) { return this; } @@ -40,7 +42,7 @@ public class ClosedFilter<S extends Storable> extends Filter<S> { return filter; } - public Filter<S> not() { + public OpenFilter<S> not() { return getOpenFilter(getStorableType()); } @@ -58,7 +60,11 @@ public class ClosedFilter<S extends Storable> extends Filter<S> { return visitor.visit(this, param); } - public Filter<S> bind() { + public ClosedFilter<S> bind() { + return this; + } + + public ClosedFilter<S> unbind() { return this; } @@ -66,8 +72,8 @@ public class ClosedFilter<S extends Storable> extends Filter<S> { return true; } - public Filter<S> unbind() { - return this; + public <T extends Storable> ClosedFilter<T> asJoinedFrom(ChainedProperty<T> joinProperty) { + return getClosedFilter(joinProperty.getPrimeProperty().getEnclosingType()); } void markBound() { diff --git a/src/main/java/com/amazon/carbonado/filter/Filter.java b/src/main/java/com/amazon/carbonado/filter/Filter.java index 338b768..55e0b93 100644 --- a/src/main/java/com/amazon/carbonado/filter/Filter.java +++ b/src/main/java/com/amazon/carbonado/filter/Filter.java @@ -28,6 +28,7 @@ import com.amazon.carbonado.MalformedFilterException; import com.amazon.carbonado.Storable; import com.amazon.carbonado.info.ChainedProperty; +import com.amazon.carbonado.info.StorableIntrospector; import com.amazon.carbonado.util.Appender; @@ -95,7 +96,7 @@ public abstract class Filter<S extends Storable> implements Appender { * @return canonical Filter instance * @see OpenFilter */ - public static <S extends Storable> Filter<S> getOpenFilter(Class<S> type) { + public static <S extends Storable> OpenFilter<S> getOpenFilter(Class<S> type) { Map<Object, Filter<S>> filterCache = getFilterCache(type); synchronized (filterCache) { Filter<S> filter = filterCache.get(OPEN_KEY); @@ -103,7 +104,7 @@ public abstract class Filter<S extends Storable> implements Appender { filter = new OpenFilter<S>(type); filterCache.put(OPEN_KEY, filter); } - return filter; + return (OpenFilter<S>) filter; } } @@ -115,7 +116,7 @@ public abstract class Filter<S extends Storable> implements Appender { * @return canonical Filter instance * @see ClosedFilter */ - public static <S extends Storable> Filter<S> getClosedFilter(Class<S> type) { + public static <S extends Storable> ClosedFilter<S> getClosedFilter(Class<S> type) { Map<Object, Filter<S>> filterCache = getFilterCache(type); synchronized (filterCache) { Filter<S> filter = filterCache.get(CLOSED_KEY); @@ -123,7 +124,7 @@ public abstract class Filter<S extends Storable> implements Appender { filter = new ClosedFilter<S>(type); filterCache.put(CLOSED_KEY, filter); } - return filter; + return (ClosedFilter<S>) filter; } } @@ -450,6 +451,35 @@ public abstract class Filter<S extends Storable> implements Appender { return isReduced() ? this : accept(new Reducer<S>(), null); } + /** + * Prepends a join property to all properties of this filter. For example, + * consider two Storable types, Person and Address. Person has a property + * "homeAddress" which joins to Address. An Address filter, "city = ?", as + * joined from Person's "homeAddress", becomes "homeAddress.city = ?". + * + * @param type type of T which contains join property + * @param joinProperty property of T which joins to this Filter's Storable type + * @return filter for type T + * @throws IllegalArgumentException if property does not exist or is not a + * join to type S + */ + public final <T extends Storable> Filter<T> asJoinedFrom(Class<T> type, String joinProperty) { + return asJoinedFrom + (ChainedProperty.parse(StorableIntrospector.examine(type), joinProperty)); + } + + /** + * Prepends a join property to all properties of this filter. For example, + * consider two Storable types, Person and Address. Person has a property + * "homeAddress" which joins to Address. An Address filter, "city = ?", as + * joined from Person's "homeAddress", becomes "homeAddress.city = ?". + * + * @param joinProperty property of T which joins to this Filter's Storable type + * @return filter for type T + * @throws IllegalArgumentException if property is not a join to type S + */ + public abstract <T extends Storable> Filter<T> asJoinedFrom(ChainedProperty<T> joinProperty); + abstract Filter<S> buildDisjunctiveNormalForm(); abstract Filter<S> buildConjunctiveNormalForm(); diff --git a/src/main/java/com/amazon/carbonado/filter/OpenFilter.java b/src/main/java/com/amazon/carbonado/filter/OpenFilter.java index 6f6e211..235c27d 100644 --- a/src/main/java/com/amazon/carbonado/filter/OpenFilter.java +++ b/src/main/java/com/amazon/carbonado/filter/OpenFilter.java @@ -22,6 +22,8 @@ import java.io.IOException; import com.amazon.carbonado.Storable; +import com.amazon.carbonado.info.ChainedProperty; + /** * Filter which lets all results pass through. * @@ -36,11 +38,11 @@ public class OpenFilter<S extends Storable> extends Filter<S> { return filter; } - public Filter<S> or(Filter<S> filter) { + public OpenFilter<S> or(Filter<S> filter) { return this; } - public Filter<S> not() { + public ClosedFilter<S> not() { return getClosedFilter(getStorableType()); } @@ -58,11 +60,11 @@ public class OpenFilter<S extends Storable> extends Filter<S> { return visitor.visit(this, param); } - public Filter<S> bind() { + public OpenFilter<S> bind() { return this; } - public Filter<S> unbind() { + public OpenFilter<S> unbind() { return this; } @@ -70,6 +72,10 @@ public class OpenFilter<S extends Storable> extends Filter<S> { return true; } + public <T extends Storable> OpenFilter<T> asJoinedFrom(ChainedProperty<T> joinProperty) { + return getOpenFilter(joinProperty.getPrimeProperty().getEnclosingType()); + } + void markBound() { } diff --git a/src/main/java/com/amazon/carbonado/filter/OrFilter.java b/src/main/java/com/amazon/carbonado/filter/OrFilter.java index 1e7bf72..e1d4f6e 100644 --- a/src/main/java/com/amazon/carbonado/filter/OrFilter.java +++ b/src/main/java/com/amazon/carbonado/filter/OrFilter.java @@ -22,6 +22,8 @@ import java.io.IOException; import com.amazon.carbonado.Storable; +import com.amazon.carbonado.info.ChainedProperty; + /** * Filter tree node that performs a logical 'or' test. * @@ -60,6 +62,10 @@ public class OrFilter<S extends Storable> extends BinaryOpFilter<S> { return mLeft.unbind().or(mRight.unbind()); } + public <T extends Storable> Filter<T> asJoinedFrom(ChainedProperty<T> joinProperty) { + return mLeft.asJoinedFrom(joinProperty).or(mRight.asJoinedFrom(joinProperty)); + } + Filter<S> buildDisjunctiveNormalForm() { return mLeft.dnf().or(mRight.dnf()).reduce(); } diff --git a/src/main/java/com/amazon/carbonado/filter/PropertyFilter.java b/src/main/java/com/amazon/carbonado/filter/PropertyFilter.java index 824d1d1..b66ad22 100644 --- a/src/main/java/com/amazon/carbonado/filter/PropertyFilter.java +++ b/src/main/java/com/amazon/carbonado/filter/PropertyFilter.java @@ -105,7 +105,7 @@ public class PropertyFilter<S extends Storable> extends Filter<S> { } @Override - public Filter<S> not() { + public PropertyFilter<S> not() { if (mBindID == BOUND_CONSTANT) { return getCanonical(mProperty, mOp.reverse(), mConstant); } else { @@ -156,11 +156,11 @@ public class PropertyFilter<S extends Storable> extends Filter<S> { return mBindID; } - public Filter<S> bind() { + public PropertyFilter<S> bind() { return mBindID == 0 ? getCanonical(this, 1) : this; } - public Filter<S> unbind() { + public PropertyFilter<S> unbind() { return mBindID == 0 ? this : getCanonical(this, 0); } @@ -168,6 +168,22 @@ public class PropertyFilter<S extends Storable> extends Filter<S> { return mBindID != 0; } + public <T extends Storable> PropertyFilter<T> asJoinedFrom(ChainedProperty<T> joinProperty) { + if (joinProperty.getType() != getStorableType()) { + throw new IllegalArgumentException + ("Property is not of type \"" + getStorableType().getName() + "\": " + + joinProperty); + } + + ChainedProperty<T> newProperty = joinProperty.append(getChainedProperty()); + + if (isConstant()) { + return getCanonical(newProperty, mOp, mConstant); + } else { + return getCanonical(newProperty, mOp, mBindID); + } + } + /** * Returns another PropertyFilter instance which is bound to the given constant value. * -- cgit v1.2.3