001    package com.hammurapi.reasoning.impl;
002    
003    import java.util.ArrayList;
004    import java.util.Collection;
005    import java.util.Collections;
006    import java.util.List;
007    import java.util.concurrent.Future;
008    
009    import com.hammurapi.config.bootstrap.ConfigurationException;
010    import com.hammurapi.flow.runtime.Invocable;
011    import com.hammurapi.flow.runtime.Invoker;
012    import com.hammurapi.flow.runtime.ProcessingPathElement;
013    import com.hammurapi.flow.runtime.PropertySet;
014    import com.hammurapi.flow.runtime.impl.Inlineable;
015    import com.hammurapi.flow.runtime.impl.Joiner.InputConsumer;
016    import com.hammurapi.util.Context;
017    
018    /**
019     * Transition which doesn't do any processing - it simply passes invocation from source to targets.
020     * @author Pavel Vlasov
021     */
022    public class ReasoningPassThroughNode<F> extends ReasoningNodeBase<F> implements Inlineable {
023            
024            private List<Output<F>> outputs = new ArrayList<Output<F>>();
025    
026            private Invocable<KnowledgeBase<F>,InferenceToken<F>> invocable = new Invocable<KnowledgeBase<F>,InferenceToken<F>>() {
027    
028                    @Override
029                    public Collection<Future<?>> invoke(
030                                    KnowledgeBase<F> flowState,                                
031                                    InferenceToken<F>[] args,                         
032                                    PropertySet properties,
033                                    Context context,
034                                    List<ProcessingPathElement> processingPath)
035                                    throws Exception {
036                            Collection<Future<?>> ret = new ArrayList<Future<?>>();
037                            for (Output<F> o: outputs) {
038                                    Collection<Future<?>> invokeResult = o.invocable.invoke(flowState, args, properties, context, processingPath);
039                                    if (invokeResult!=null) {
040                                            ret.addAll(invokeResult);
041                                    }
042                            }
043                            return ret;
044                    }
045                    
046            };
047            
048            @Override
049            public Invocable<KnowledgeBase<F>,InferenceToken<F>> getInvocable(String pinName, Integer connectKey) {
050                    return invocable;
051            }
052    
053            @Override
054            public Invoker<KnowledgeBase<F>,InferenceToken<F>> getInvoker(String pinName, Integer connectKey) {
055                    Output<F> ret = new Output<F>(null, connectKey);
056                    outputs.add(ret);
057                    return ret;
058            }
059            
060            @Override
061            public void beforeConnect() throws ConfigurationException {
062                    // NOP          
063            }
064            
065            @Override
066            public void afterConnect() throws ConfigurationException {
067                    Collections.sort(outputs);
068            }
069    
070            @Override
071            public void addPin(String pinName, List<?> pin) {
072                    // NOP - pass-through node doesn't care about pin configuration.
073                    
074            }
075    
076            @Override
077            public boolean inline() {
078                    return true;
079            }
080    
081            @Override
082            protected Collection<Future<?>> process(
083                            KnowledgeBase<F> knowledgeBase,
084                            List<InferenceToken<F>>[] inputs, 
085                            PropertySet properties,
086                            Context context, List<ProcessingPathElement> processingPath,
087                            InputConsumer consumer,
088                            int activator) throws Exception {
089                    // Should never be invoked.
090                    throw new UnsupportedOperationException();
091            }
092    }