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    }