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    }