    001    package com.hammurapi.reasoning.impl;
    002
    003    import java.util.ArrayList;
    004    import java.util.List;
    005    import java.util.Map;
    006
    007    import org.eclipse.emf.common.util.TreeIterator;
    008    import org.eclipse.emf.ecore.EObject;
    009
    010    import com.hammurapi.flow.Flow;
    011    import com.hammurapi.flow.Node;
    012    import com.hammurapi.flow.Pin;
    013    import com.hammurapi.flow.Transition;
    014    import com.hammurapi.flow.runtime.impl.PassThroughTransition;
    015
    016    /**
    017     * Optimizes flow by finding equal conditions emanating from
    018     * the same pin and merging them.
    019     * @author Pavel Vlasov
    020     *
    021     */
    022    public class ConditionSharingOptimizer implements RuleSetFlowOptimizer {
    023
    024            // TODO - Copy connection keys during optimization.
    025
    026            /*
    027             * Algorithm:
    028             * 1. Iterate over pins
    029             * 2. For a pin iterate over all permutations of two outbound transitions.
    030             * 3. If transitions are passthrough or mapping, and the nodes on the other ends are conditional, check two nodes for equality.
    031             * 4. If nodes are equal or mappingly equal, check that all inbound transitions can be re-connected from one node's pins to the other's pins.
    032             * 5. Reconnect transitions, change pass-through to mapping or change mapping where required.
    033             */
    034
    035            @Override
    036            public void optimize(Flow ruleSetFlow) {
    037                    boolean optimized;
    038                    Z: do {
    039                            optimized = false;
    040                            TreeIterator<EObject> rcit = ruleSetFlow.eAllContents();
    041                            N: while (rcit.hasNext()) {
    042                                    EObject next = rcit.next();
    043                                    if (next instanceof Pin) {
    044                                            Pin pin = (Pin) next;
    045                                            Transition[] outputs = pin.getOutput().toArray(new Transition[pin.getOutput().size()]);
    046                                            /* For every two outbound transitions from the pin we check if the transitions
    047                                             * are pass-through
    048                                             */
    049                                            for (int idx1=0; idx1<outputs.length-1; ++idx1) {
    050                                                    for (int idx2=idx1+1; idx2<outputs.length; ++idx2) {
    051                                                            if (isPassThrhoughOrMapping(outputs[idx1]) && isPassThrhoughOrMapping(outputs[idx2])) {
    052                                                                    Pin pin1 = outputs[idx1].getToPin();
    053                                                                    Pin pin2 = outputs[idx2].getToPin();
    054                                                                    /*
    055                                                                     * If target pins belong to condition nodes
    056                                                                     */
    057                                                                    if (ConditionNode.class.equals(pin1.getNode().getType()) &&     ConditionNode.class.equals(pin2.getNode().getType())) {
    058                                                                            /* List of parameter mappings with which conditions are equal. Maps parameters of the second node to
    059                                                                             * parameters of the first node. */
    060                                                                            List<Map<Integer, Integer>> paramMaps = new ArrayList<Map<Integer, Integer>>();
    061                                                                            if (equal(pin1.getNode(), pin2.getNode(), paramMaps)) {
    062                                                                                    throw new UnsupportedOperationException();
    063                                                                            }
    064                                                                    }
    065                                                            }
    066                                                    }
    067                                            }
    068
    069                                    }
    070                            }
    071                    } while (optimized);
    072            }
    073
    074            private boolean sameName(String name, String name2) {
    075                    return name==null ? name2==null : name.equals(name2);
    076            }
    077
    078            /**
    079             * Compares conditions.
    080             * @param name
    081             * @param node
    082             * @return
    083             */
    084            private boolean equal(Node node1, Node node2, List<Map<Integer,Integer>> paramMaps) {
    085                    // TODO Auto-generated method stub
    086                    return false;
    087            }
    088
    089            private boolean isPassThrhoughOrMapping(Transition transition) {
    090                    return PassThroughTransition.class.getName().equals(transition.getType()) || MappingTransition.class.getName().equals(transition.getType());
    091            }
    092
    093            /**
    094             * This optimization shall be executed after elimination
    095             * of unnecessary pass-through nodes and transitions.
    096             */
    097            @Override
    098            public int getOrder() {
    099                    return 10;
    100            }
    101
    102    }