001 package com.hammurapi.reasoning.impl;
002
003 import java.util.ArrayList;
004 import java.util.Collection;
005 import java.util.Iterator;
006 import java.util.List;
007 import java.util.concurrent.Future;
008
009 import com.hammurapi.flow.runtime.ProcessingPathElement;
010 import com.hammurapi.flow.runtime.PropertySet;
011 import com.hammurapi.flow.runtime.impl.Joiner.InputConsumer;
012 import com.hammurapi.reasoning.ReasoningException;
013 import com.hammurapi.util.Context;
014
015
016 /**
017 * Base class for condition nodes.
018 *
019 * @author Pavel Vlasov
020 *
021 */
022 public abstract class ConditionNode<F> extends ReasoningNodeBase<F> {
023
024 /**
025 * Dispatch inputs to outputs.
026 */
027 @SuppressWarnings("unchecked")
028 @Override
029 protected Collection<Future<?>> process(
030 KnowledgeBase<F> flowState,
031 List<InferenceToken<F>>[] inputs,
032 PropertySet properties,
033 Context context,
034 List<ProcessingPathElement> processingPath,
035 InputConsumer consumer,
036 int activator) throws Exception {
037
038 Collection<Future<?>> ret = new ArrayList<Future<?>>();
039
040 boolean dispatched = false;
041 Z: for (PinEntry<F> pin: pins) {
042 if (pin.getName().startsWith(Constants.OUTPUT)) {
043 for (Object alt: pin.config) {
044 List<TokenInfo> lti=(List<TokenInfo>) alt;
045 InferenceToken<F>[] out = match(inputs, lti);
046 if (out!=null) {
047 dispatched = true;
048 for (Output<F> output: pin.outputs) {
049 ret.addAll(output.invocable.invoke(flowState, out, properties, context, processingPath));
050 }
051
052 continue Z;
053 }
054 }
055 }
056 }
057 if (!dispatched) {
058 throw new IllegalArgumentException("Condition output was not dispatched to any output pins");
059 }
060 return ret;
061 }
062
063 /**
064 * Matches input tokens with output config.
065 * @param inputs
066 * @param outputConfig
067 * @return Filled out output array or null if there is no match.
068 * @throws ReasoningException
069 */
070 @SuppressWarnings("unchecked")
071 private InferenceToken<F>[] match(List<InferenceToken<F>>[] inputs, List<TokenInfo> outputConfig) throws ReasoningException {
072 InferenceToken<F>[] out = new InferenceToken[outputConfig.size()];
073 Iterator<TokenInfo> outputConfigIterator = outputConfig.iterator();
074 Z: for (int outputIdx=0; outputConfigIterator.hasNext(); ++outputIdx) {
075 TokenInfo outputTokenInfo = outputConfigIterator.next();
076 Iterator<PinEntry<F>> inputPinIterator = getInputPins().iterator();
077 for (int inputPinIndex=0; inputPinIterator.hasNext(); ++inputPinIndex) {
078 PinEntry<F> inputPin = inputPinIterator.next();
079 List<TokenInfo> pinConfig = (List<TokenInfo>) inputPin.config;
080 Iterator<TokenInfo> inputTokenInfoIterator = pinConfig.iterator();
081 for (int inputTokenIndex=0; inputTokenInfoIterator.hasNext(); ++inputTokenIndex) {
082 TokenInfo inputTokenInfo = inputTokenInfoIterator.next();
083 if (outputTokenInfo.getParameterIndex() == inputTokenInfo.getParameterIndex()) {
084 InferenceToken<F> it = inputs[inputPinIndex].get(inputTokenIndex);
085 if (it.isConsumed()) {
086 return null;
087 }
088
089 if (!outputTokenInfo.getType().isInstance(knowledgeBase.get(it.getHandle()))) {
090 return null;
091 }
092
093 out[outputIdx] = it;
094 continue Z;
095 }
096 }
097 }
098 throw new IllegalArgumentException("Could not find input for output index "+outputIdx);
099 }
100 return out;
101 }
102
103 }