    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    }