001 package com.hammurapi.eventbus;
002
003 import java.lang.reflect.Array;
004 import java.util.Arrays;
005 import java.util.HashSet;
006 import java.util.Map;
007 import java.util.Set;
008
009 import com.hammurapi.eventbus.AbstractEventBus.Handle;
010 import com.hammurapi.extract.ComparisonResult;
011 import com.hammurapi.extract.Extractor;
012 import com.hammurapi.extract.Predicate;
013
014 public class MappedHandlePredicate<T, P extends Comparable<P>, C, K, H extends EventBus.Handle<T, P, C>, S extends EventStore<T,P,C,H,S>> implements Predicate<Handle<T,P,C,K>[], CompositeContext<T, P, C, K, H, S>> {
015
016 private Predicate<T, C> target;
017 private Mapper<Handle<T,P,C,K>>[] mappers;
018 private int maxIndex;
019 private Set<Integer> parameterIndices = new HashSet<Integer>();
020 private Class<T> targetClass;
021
022 public MappedHandlePredicate(Predicate<T, C> target, Mapper<Handle<T,P,C,K>>[] mappers, Class<T> targetClass) {
023 this.target = target;
024 this.targetClass = targetClass;
025 this.mappers = mappers;
026 for (Integer idx:target.parameterIndices()) {
027 if (idx>maxIndex) {
028 maxIndex = idx;
029 }
030 for (int i=0; i<mappers.length; ++i) {
031 if (mappers[i].mapsTo(idx)) {
032 parameterIndices.add(i);
033 }
034 }
035 }
036 }
037
038 @SuppressWarnings("unchecked")
039 @Override
040 public Boolean extract(
041 CompositeContext<T, P, C, K, H, S> context,
042 Map<CompositeContext<T, P, C, K, H, S>, Map<Extractor<Handle<T,P,C,K>[], ? super Boolean, CompositeContext<T, P, C, K, H, S>>, ? super Boolean>> cache,
043 Handle<T,P,C,K>[]... handles) {
044 Handle<T,P,C,K>[] predicateInputHandles = new Handle[maxIndex+1];
045 for (int i=0; i<mappers.length; ++i) {
046 mappers[i].map(handles[i], predicateInputHandles);
047 }
048
049 T[] predicateInput = (T[]) Array.newInstance(targetClass, maxIndex+1);
050
051 for (int i=0; i<predicateInputHandles.length; ++i) {
052 Handle<T,P,C,K> handle = predicateInputHandles[i];
053 if (handle!=null) {
054 if (!handle.isValid()) {
055 return Boolean.FALSE;
056 }
057 predicateInput[i] = handle.getEvent();
058 }
059 }
060
061 // TODO - associate cache for a tuple with Handle[] using a special class instead of
062 // handle array.
063 return target.extract(context.getHandlerContext(), null, predicateInput);
064 }
065
066 @Override
067 public ComparisonResult compareTo(Extractor<Handle<T,P,C,K>[], Boolean, CompositeContext<T, P, C, K, H, S>> otherPredicate) {
068 // TODO Implement proper comparison for merging of join networks.
069 return ComparisonResult.NOT_EQUAL_NM;
070 }
071
072 @Override
073 public boolean isContextDependent() {
074 return target.isContextDependent();
075 }
076
077 @Override
078 public Set<Integer> parameterIndices() {
079 return parameterIndices;
080 }
081
082 @Override
083 public double getCost() {
084 return target.getCost();
085 }
086
087 @Override
088 public String toString() {
089 return "MappedHandlePredicate [target=" + target + ", mappers="
090 + Arrays.toString(mappers) + ", maxIndex=" + maxIndex
091 + ", parameterIndices=" + parameterIndices + ", targetClass="
092 + targetClass + "]";
093 }
094
095 }