001 package com.hammurapi.reasoning.impl;
002
003 import java.util.Collections;
004 import java.util.Comparator;
005 import java.util.Iterator;
006 import java.util.List;
007
008 import com.hammurapi.reasoning.ExceptionHandler;
009
010 public class AcceptMethodConditionNode<F> extends ConditionNode<F> {
011
012
013 private List<Integer> parameterMap;
014
015 public void setParameterMap(List<Integer> parameterMap) {
016 this.parameterMap = parameterMap;
017 }
018
019 /**
020 * Evaluate condition as soon as all condition arguments are available.
021 */
022 @SuppressWarnings("unchecked")
023 @Override
024 protected boolean partialJoin(List<com.hammurapi.reasoning.impl.InferenceToken<F>>[] inputs, int index) throws Exception {
025 if (index==lastConditionPin) {
026 Object[] cArgs = new Object[parameterTypes.length];
027 Iterator<Integer> pmit = parameterMap.iterator();
028 Z: for (int i=0; pmit.hasNext(); ++i) {
029 Integer pIdx = pmit.next();
030 for (int j=0; j<=index; ++j) {
031 List<TokenInfo> pinConfig = (List<TokenInfo>) getInputPins().get(j).config;
032 if (pinConfig.size()!=inputs[j].size()) {
033 throw new IllegalArgumentException("Number of input tokens is different from number of token infos");
034 }
035 for (int k=0, l=pinConfig.size(); k<l; ++k) {
036 TokenInfo ti = pinConfig.get(k);
037 if (ti.getParameterIndex() == pIdx) {
038 InferenceToken<F> it = inputs[j].get(k);
039 if (it.isConsumed()) {
040 return false;
041 }
042
043 cArgs[i] = knowledgeBase.get(it.getHandle());
044 if (cArgs[i]==null) {
045 return false;
046 }
047 continue Z;
048 }
049 }
050 }
051 }
052
053 try {
054 return Boolean.TRUE.equals(method.invoke(rule, cArgs));
055 } catch (Exception e) {
056 ExceptionHandler exceptionHandler = knowledgeBase.getExceptionHandler();
057 if (exceptionHandler==null) {
058 throw e;
059 }
060 exceptionHandler.handleException(e);
061 return false;
062 }
063 }
064
065 return true;
066 }
067
068 private boolean hasConditionArgument(PinEntry<F> pin) {
069 for (Object o: pin.config) {
070 TokenInfo ti = (TokenInfo) o;
071 for (Integer pIdx: parameterMap) {
072 if (pIdx==ti.getParameterIndex()) {
073 return true;
074 }
075 }
076 }
077
078 return false;
079 }
080
081 private int lastConditionPin=-1;
082
083 /**
084 * Sort input pins to move pins with conditon arguments to first positions.
085 */
086 @Override
087 protected void sortInputs() {
088 Collections.sort(getInputPins(), new Comparator<PinEntry<F>>() {
089
090 @Override
091 public int compare(PinEntry<F> pe1, PinEntry<F> pe2) {
092 if (hasConditionArgument(pe1)) {
093 if (hasConditionArgument(pe2)) {
094 return pe1.index-pe2.index;
095 }
096 return -1; // pe1 shall be before pe2
097 }
098
099 if (hasConditionArgument(pe2)) {
100 return 1; // pe1 shall be after pe2.
101 }
102
103 return pe1.index - pe2.index;
104 }
105 });
106
107 for (int i=0; i<getInputPins().size(); ++i) {
108 if (hasConditionArgument(getInputPins().get(i))) {
109 lastConditionPin = i;
110 }
111 }
112 }
113
114 }