summaryrefslogtreecommitdiff
path: root/src/main/java/com/amazon/carbonado
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/amazon/carbonado')
-rw-r--r--src/main/java/com/amazon/carbonado/filter/AndFilter.java6
-rw-r--r--src/main/java/com/amazon/carbonado/filter/ClosedFilter.java16
-rw-r--r--src/main/java/com/amazon/carbonado/filter/Filter.java38
-rw-r--r--src/main/java/com/amazon/carbonado/filter/OpenFilter.java14
-rw-r--r--src/main/java/com/amazon/carbonado/filter/OrFilter.java6
-rw-r--r--src/main/java/com/amazon/carbonado/filter/PropertyFilter.java22
6 files changed, 86 insertions, 16 deletions
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.
*