fast.servicescreen.client.gui.RuleGUI.java Source code

Java tutorial

Introduction

Here is the source code for fast.servicescreen.client.gui.RuleGUI.java

Source

/**
 * Copyright (c) 2008-2011, FAST Consortium
 * 
 * This file is part of FAST Platform.
 * 
 * FAST Platform is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * FAST Platform is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
 * License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with FAST Platform. If not, see <http://www.gnu.org/licenses/>.
 * 
 * Info about members and contributors of the FAST Consortium
 * is available at http://fast.morfeo-project.eu
 *
 **/
package fast.servicescreen.client.gui;

import java.util.ArrayList;
import java.util.Iterator;

import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.user.client.ui.TreeItem;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
import com.google.gwt.xml.client.Node;
import com.google.gwt.xml.client.NodeList;

import fast.common.client.BuildingBlock;
import fast.common.client.FASTMappingRule;
import fast.common.client.FactAttribute;
import fast.common.client.FactType;
import fast.common.client.ServiceDesigner;
import fast.servicescreen.client.gui.parser.OperationHandler;
import fast.servicescreen.client.rpc.SendRequestHandler;

public class RuleGUI {
    public RuleGUI(BuildingBlock buildingBlock, SendRequestHandler rh) {
        this.buildingBlock = buildingBlock;
        requestHandler = rh;
    }

    protected BuildingBlock buildingBlock;
    protected SendRequestHandler requestHandler;

    //Ressource Trees
    public Tree xmlTree;

    //Output Tree
    public Tree factsTree;

    //TransRule Tree
    public Tree rulesTree;
    protected FASTMappingRule selectedRule;

    /**
     * creates and returns a flextable containing the trees
     * for translation design
     * */
    public Widget createTranslationTable() {
        final FlexTable translationTable = new FlexTable();
        int rowCount = translationTable.getRowCount();

        // headlines, labels and buttons in first row
        translationTable.setWidget(rowCount, 0, new Label("Result:"));
        translationTable.setWidget(rowCount, 1, createRulesHeadlineTable());
        translationTable.setWidget(rowCount, 2, new Label("Facts:"));
        rowCount++;

        // add result tree
        ScrollPanel resultScrollPanel = new ScrollPanel();
        resultScrollPanel.setAlwaysShowScrollBars(true);
        resultScrollPanel.setSize("11cm", "11cm");

        //create xmlTree and add a selection/PropertyChange - handler
        xmlTree = new Tree();
        xmlTree.addSelectionHandler(new XmlTreeHandler());
        resultScrollPanel.setWidget(xmlTree);
        translationTable.setWidget(rowCount, 0, resultScrollPanel);

        // add rule table
        ScrollPanel rulesScrollPanel = new ScrollPanel();
        rulesScrollPanel.setAlwaysShowScrollBars(true);
        rulesScrollPanel.setSize("11cm", "11cm");
        rulesScrollPanel.setWidget(createRulesTree());
        translationTable.setWidget(rowCount, 1, rulesScrollPanel);

        // add facts tree
        ScrollPanel factsScrollPanel = new ScrollPanel();
        factsScrollPanel.setAlwaysShowScrollBars(true);
        factsScrollPanel.setSize("11cm", "11cm");

        factsTree = new Tree();
        factsScrollPanel.setWidget(factsTree);
        translationTable.setWidget(rowCount, 2, factsScrollPanel);

        // return the table
        translationTable.ensureDebugId("cwFlexTable");
        return translationTable;
    }

    //rules headline table
    protected Widget createRulesHeadlineTable() {
        FlexTable rulesHeadlineTable = new FlexTable();

        int rowCount = rulesHeadlineTable.getRowCount();

        rulesHeadlineTable.setWidget(rowCount, 0, new Label("Rules:"));

        int rowCount_upAndDown = rowCount + 1;
        int rowCount_leftAndRight = rowCount + 2;
        int rowCount_headlines = rowCount + 3;

        rulesHeadlineTable.setWidget(rowCount_headlines, 0, new Label("<From>"));
        rulesHeadlineTable.setWidget(rowCount_headlines, 1, new Label("<Kind>"));
        rulesHeadlineTable.setWidget(rowCount_headlines, 2, new Label("<Target>"));

        //add - button
        Button addRuleButton = new Button("Add Kid Rule");
        addRuleButton.setStyleName("fastButton");
        addRuleButton.addClickHandler(new AddKidRuleHandler());
        rulesHeadlineTable.setWidget(rowCount, 0, addRuleButton);

        //remove - button
        Button removeRuleButton = new Button("Remove Rule");
        removeRuleButton.setStyleName("fastButton");
        removeRuleButton.addClickHandler(new RemoveRuleHandler());
        rulesHeadlineTable.setWidget(rowCount, 1, removeRuleButton);

        //up - button
        Button upButton = new Button("up");
        upButton.setStyleName("fastButton");
        upButton.setSize("50px", "35px");
        upButton.addClickHandler(new RuleUpHandler());
        rulesHeadlineTable.setWidget(rowCount_upAndDown, 0, upButton);

        //down - button
        Button downButton = new Button("down");
        downButton.setStyleName("fastButton");
        downButton.setSize("50px", "35px");
        downButton.addClickHandler(new RuleDownHandler());
        rulesHeadlineTable.setWidget(rowCount_upAndDown, 1, downButton);

        //left - button
        Button leftButton = new Button("left");
        leftButton.setStyleName("fastButton");
        leftButton.setSize("50px", "35px");
        leftButton.addClickHandler(new RuleLeftHandler());
        rulesHeadlineTable.setWidget(rowCount_leftAndRight, 0, leftButton);

        //right - button
        Button rightButton = new Button("right");
        rightButton.setStyleName("fastButton");
        rightButton.setSize("50px", "35px");
        rightButton.addClickHandler(new RuleRightHandler());
        rulesHeadlineTable.setWidget(rowCount_leftAndRight, 1, rightButton);

        // return the table
        rulesHeadlineTable.ensureDebugId("cwFlexTable");
        return rulesHeadlineTable;
    }

    //build rules-tree new
    @SuppressWarnings("unchecked")
    protected Tree createRulesTree() {
        if (rulesTree == null)
            rulesTree = new Tree();
        else
            rulesTree.clear();

        TreeItem treeParent = rulesTree.addItem("Rules:");

        //  root rule
        if (buildingBlock.sizeOfMappingRules() == 0) {
            buildingBlock.addToMappingRules(new FASTMappingRule());
        }

        // add existing rules to the tree
        Iterator<FASTMappingRule> iteratorOfMappingRules = buildingBlock.iteratorOfMappingRules();

        while (iteratorOfMappingRules.hasNext()) {
            FASTMappingRule nextRule = (FASTMappingRule) iteratorOfMappingRules.next();
            addRuleTree(nextRule, treeParent);
        }

        TreeItem item = rulesTree.getItem(0);
        item.setState(true);

        SelectionHandler<TreeItem> handler = new RulesTreeHandler();
        rulesTree.addSelectionHandler(handler);

        RuleUtil.expandItem(rulesTree.getItem(0));

        return rulesTree;
    }

    @SuppressWarnings("unchecked")
    protected void addRuleTree(FASTMappingRule nextRule, TreeItem treeParent) {
        TreeItem ruleEditor = createRuleEditor(nextRule, treeParent);

        // add kids
        for (Iterator<FASTMappingRule> kidsIter = nextRule.iteratorOfKids(); kidsIter.hasNext();) {
            FASTMappingRule kidRule = (FASTMappingRule) kidsIter.next();
            addRuleTree(kidRule, ruleEditor);
        }
    }

    protected RulefieldsListener rulefieldListener = new RulefieldsListener(buildingBlock);

    protected TreeItem createRuleEditor(FASTMappingRule nextRule, TreeItem treeParent) {
        // "from" attribute
        // new SuggestBox
        TextBox fromBox = CTextChangeHandler.createWidthTextBox(nextRule, "3cm", "sourceTagname");

        // "kind" attribute
        MultiWordSuggestOracle oracle = new MultiWordSuggestOracle();
        ArrayList<String> words = new ArrayList<String>();

        words.add("createObject");
        words.add("fillAttributes");
        words.add("dummyRule");

        for (String word : words)
            oracle.add(word);

        oracle.setDefaultSuggestionsFromText(words);
        SuggestBox kindBox = CTextChangeHandler.createWidthSuggestBox(nextRule, "3cm", "kind", oracle);

        // "target" attribute
        MultiWordSuggestOracle typeOracle = new MultiWordSuggestOracle();

        ServiceDesigner serviceDesigner = (ServiceDesigner) buildingBlock.get("serviceDesigner");

        fillTypesOracle(nextRule, typeOracle, serviceDesigner);
        final SuggestBox targetBox = CTextChangeHandler.createWidthSuggestBox(nextRule, "3cm", "targetElemName",
                typeOracle);
        ;
        targetBox.setValue(nextRule.getTargetElemName());
        targetBox.setWidth("3cm");

        Grid ruleRow = new Grid(1, 3);
        ruleRow.setWidget(0, 0, fromBox);
        ruleRow.setWidget(0, 1, kindBox);
        ruleRow.setWidget(0, 2, targetBox);

        // add listeners for oracle relevant changes
        UpdateTargetBoxOracleHandler handler = new UpdateTargetBoxOracleHandler(nextRule, typeOracle,
                serviceDesigner);
        kindBox.addSelectionHandler(handler);

        if (treeParent != null) {
            Grid parentGrid = (Grid) treeParent.getWidget();
            if (parentGrid != null) {
                SuggestBox parentTargetBox = (SuggestBox) parentGrid.getWidget(0, 2); // the target box of the parent
                parentTargetBox.addSelectionHandler(handler);
            }
        }

        //adding a RulefieldsListener (and handler) to rule fields
        fromBox.addChangeHandler(rulefieldListener);
        kindBox.addSelectionHandler(rulefieldListener);
        targetBox.addSelectionHandler(rulefieldListener);

        fromBox.addValueChangeHandler(new ValueChangeHandler<String>() {
            @Override
            public void onValueChange(ValueChangeEvent<String> event) {
                updateFactsTree();
            }
        });

        TreeItem result = treeParent.addItem(ruleRow);
        result.setUserObject(nextRule);

        return result;
    }

    @SuppressWarnings("unchecked")
    protected void fillTypesOracle(FASTMappingRule nextRule, MultiWordSuggestOracle typeOracle,
            ServiceDesigner serviceDesigner) {
        // for create object rules add fact types to oracle
        ArrayList<String> types = new ArrayList<String>();
        String kind = nextRule.getKind();
        if ("createObject".equals(kind)) {
            for (Iterator typeIter = serviceDesigner.iteratorOfFactTypes(); typeIter.hasNext();) {
                FactType type = (FactType) typeIter.next();
                String typeName = type.getUri();
                //format type name: (e.g. name - http://fast.amazon.com/domain/name)
                typeName = typeName.substring(typeName.lastIndexOf("/") + 1) + " - " + type.getUri();
                //add to oracle words
                //System.out.println("Add type to oracle: " + typeName);
                if (typeName != null) {
                    types.add(typeName);
                }
            }
        } else if ("fillAttributes".equals(kind)) {
            // retrieve type of parent rule and add its attributes to the oracle
            FASTMappingRule parent = nextRule.getParent();
            String typeName = parent.getTargetElemName();
            typeName = typeName.substring(typeName.indexOf("http"));
            FactType factType = findFactType(typeName);

            if (factType != null) {
                for (Iterator iter = factType.iteratorOfFactAttributes(); iter.hasNext();) {
                    FactAttribute attr = (FactAttribute) iter.next();
                    types.add(attr.getAttrName());
                }
            }
        } else if ("dummyRule".equals(kind)) {
            //do nothing here
        }

        for (String word : types)
            typeOracle.add(word);

        typeOracle.setDefaultSuggestionsFromText(types);
    }

    class UpdateTargetBoxOracleHandler implements SelectionHandler<Suggestion> {
        protected FASTMappingRule rule;
        protected MultiWordSuggestOracle oracle;
        protected ServiceDesigner serviceDesigner;

        public UpdateTargetBoxOracleHandler(FASTMappingRule rule, MultiWordSuggestOracle oracle,
                ServiceDesigner serviceDesigner) {
            // this rule's kind or parent rule's target type has changed.
            // in case of a fillAttributes rule, the oracle for attr names needs to be changed. 
            this.oracle = oracle;
            this.rule = rule;
            this.serviceDesigner = serviceDesigner;
        }

        @Override
        public void onSelection(SelectionEvent<Suggestion> event) {
            // update oracle
            oracle.clear();
            fillTypesOracle(rule, oracle, serviceDesigner);
        }
    }

    protected ServiceDesigner tmpServiceDesigner = null;
    protected FactType tmpFactType;

    protected void withNewFactAttr(String string) {
        FactAttribute factAttribute = new FactAttribute().withAttrName(string);
        tmpFactType.addToFactAttributes(factAttribute);
    }

    protected void addToFactTypes(String string) {
        tmpFactType = new FactType().withTypeName(string);
        tmpServiceDesigner.addToFactTypes(tmpFactType);
    }

    @SuppressWarnings("unchecked")
    protected FactType findFactType(String typeName) {
        FactType factType = null;
        for (Iterator iter = ((ServiceDesigner) buildingBlock.get("serviceDesigner")).iteratorOfFactTypes(); iter
                .hasNext();) {
            factType = (FactType) iter.next();
            String factTypeName = factType.getUri();
            if ((factTypeName != null && factTypeName.equals(typeName))
                    || (factTypeName == null && typeName == null)) {
                return factType;
            }
        }
        return null;
    }

    protected FASTMappingRule rootRule;

    /**
     * Updates the facts trees (for XML Ressources!)
     * */
    public void updateFactsTree() {
        //transforms the rule hierarchy to Strings in facts - tree
        if (rootRule == null) {
            rootRule = (FASTMappingRule) buildingBlock.iteratorOfMappingRules().next();
        }

        requestHandler.xmlDoc.getDocumentElement();

        buildFactsTree(factsTree);
    }

    protected void buildFactsTree(Tree aFactsTree) {
        //(re)build the facts tree 
        aFactsTree.clear();

        TreeItem rootItem = aFactsTree.addItem("Facts:");

        try {
            transform(requestHandler.xmlDoc, rootRule, rootItem);
        } catch (Exception e) {
            e.printStackTrace();
        }

        RuleUtil.expandItem(aFactsTree.getItem(0));

    }

    /**
     * This method transform the data with the rules
     * to the this.factsTree (XML)
     * */
    public void transform(Node xmlDocElement, FASTMappingRule rule, TreeItem treeItem) {
        if ("dummyRule".equals(rule.getKind())) {
            rule.setTargetElemName("useless");
        }

        if (RuleUtil.isCompleteRule(rule)) {
            TreeItem kidItem = null;
            NodeList elements = null;

            //create a handler for operations in the decoded fromField 
            OperationHandler opHandler = new OperationHandler(rule.getSourceTagname());
            String sourceTagname = opHandler.getLastSourceTagname();

            //add the handler within parse results into the rule
            rule.setOperationHandler(opHandler);

            //take source
            elements = RuleUtil.get_ElementsByTagname(xmlDocElement, sourceTagname);

            //"createObject" creates a new tag
            String targetElemName = rule.getTargetElemName();
            if (rule.getKind().equals("createObject")) {
                for (int i = 0; i < elements.getLength(); ++i) {
                    kidItem = treeItem.addItem(targetElemName);
                    callTransformForKids(elements.item(i), rule, kidItem);
                }
            }

            //"fillAttribute" fills attribute strings on right possition
            else if (rule.getKind().equals("fillAttributes")) {
                // create tag value pair for that attributes
                for (int i = 0; i < elements.getLength(); ++i) {
                    //execute operation
                    String nodeValue = opHandler.executeOperations(xmlDocElement, i);

                    kidItem = treeItem.addItem(targetElemName + " : " + nodeValue);
                }

                //access attribute if there where no elements
                if (elements.getLength() == 0) {
                    String nodeValue = opHandler.executeOperations(xmlDocElement, 0);

                    kidItem = treeItem.addItem(targetElemName + " : " + nodeValue);
                }
            }
            //TODO dk need scenario.. This way it doesnt work
            else if (rule.getKind().equals("dummyRule")) {
                String sourceName = rule.getSourceTagname();

                NodeList nodeList = RuleUtil.get_ElementsByTagname(xmlDocElement, sourceName);

                xmlDocElement = nodeList.item(0);

                callTransformForKids(xmlDocElement, rule, treeItem);
            }
        }
    }

    /**
     * Helps reuse the code. Call transform(..) for any kid
     * rule the rule u gave got. 
    * */
    @SuppressWarnings("unchecked")
    protected void callTransformForKids(Node xmlDocElement, FASTMappingRule rule, TreeItem treeItem) {
        for (Iterator<FASTMappingRule> kidIter = rule.iteratorOfKids(); kidIter.hasNext();) {
            FASTMappingRule kid = (FASTMappingRule) kidIter.next();
            transform(xmlDocElement, kid, treeItem);
        }
    }

    //Handler

    /**
     * Handles changes in Rulefields
     * */
    class RulefieldsListener implements ChangeHandler, SelectionHandler<Suggestion> {
        protected BuildingBlock buildingBlock = null;

        public RulefieldsListener(BuildingBlock block) {
            this.buildingBlock = block;
        }

        /**
         * This method is called when any of the Rule - Fields
         * changes.
         * It bind the changed Fieldname to the Facte - Tree.
         * */
        @Override
        public void onChange(ChangeEvent event) {
            // Only TextBoxes should be bind to the Facts - Tree
            Object source = event.getSource();
            if ((source instanceof TextBox) || source instanceof SuggestBox) {
                // that should happen any time the rule tree changes!
                updateFactsTree();
            }
        }

        @Override
        public void onSelection(SelectionEvent<Suggestion> event) {
            updateFactsTree();
        }
    }

    /**
     * Handles the xml tree (Selection and PropChange)
     * */
    class XmlTreeHandler implements SelectionHandler<TreeItem> {
        @Override
        public void onSelection(SelectionEvent<TreeItem> event) {
            // print selected element in rule area
            TreeItem selectedItem = event.getSelectedItem();
            String text = selectedItem.getText();

            // try to find corresponding xmlDoc element
            String tagName = text.split(":")[0].trim();

            if (selectedRule != null) {
                // transfer tagName to the currently selected mapping rule. 
                selectedRule.setSourceTagname(tagName);

                updateFactsTree();
            }
        }
    }

    class RulesTreeHandler implements SelectionHandler<TreeItem> {
        @Override
        public void onSelection(SelectionEvent<TreeItem> event) {
            // store selected rule
            TreeItem selectedItem = event.getSelectedItem();
            FASTMappingRule mappingRule = (FASTMappingRule) selectedItem.getUserObject();
            selectedRule = mappingRule;
        }
    }

    /**
     * Add a Kidrule - Handler
     * */
    class AddKidRuleHandler implements ClickHandler {
        @Override
        public void onClick(ClickEvent event) {
            FASTMappingRule newRule = new FASTMappingRule();
            newRule.setKind("createObject");

            TreeItem selectedItem = rulesTree.getSelectedItem();
            selectedRule.addToKids(newRule);
            createRuleEditor(newRule, selectedItem);

            updateFactsTree();
        }
    }

    /**
     * Remove a Rule - Handler
     * */
    class RemoveRuleHandler implements ClickHandler {
        @Override
        public void onClick(ClickEvent event) {
            TreeItem selectedItem = rulesTree.getSelectedItem();

            //if the rule has no parent rule, do nothing (one rule has to remain)
            if (RuleUtil.isNotNullOrRoot(selectedItem)) {
                //the node has subrules, add them to the parent
                if (selectedItem.getChildCount() > 0) {

                    FASTMappingRule parent = selectedRule.getParent();

                    for (int count = selectedItem.getChildCount() - 1; count >= 0; --count) {
                        selectedItem.getParentItem().addItem(selectedItem.getChild(count));
                        selectedItem.removeItem(selectedItem.getChild(count));

                        parent.addToKids(selectedRule.getFromKids(count));
                    }
                }

                //deleting selected item/rule
                selectedItem.remove();
                selectedRule.removeYou();

                rulesTree = createRulesTree();
            }

            updateFactsTree();
        }
    }

    /**
     * Rule up - Handler
     * */
    class RuleUpHandler implements ClickHandler {
        @Override
        public void onClick(ClickEvent event) {
            TreeItem upItem = rulesTree.getSelectedItem();

            if (RuleUtil.isNotNullOrRoot(upItem)) {
                TreeItem parent = upItem.getParentItem();
                int index = parent.getChildIndex(upItem);

                if (index != 0) {
                    //move rule
                    FASTMappingRule parentRule = selectedRule.getParent();
                    FASTMappingRule beforeRule = parentRule.getPreviousOfKids(selectedRule);
                    parentRule.addBeforeOfKids(beforeRule, selectedRule);

                    rulesTree = createRulesTree();
                } else {
                    //maybe call ruleLeft
                }
            }
            updateFactsTree();
        }
    }

    /**
     * Rule down - Handler
     * */
    class RuleDownHandler implements ClickHandler {
        @Override
        public void onClick(ClickEvent event) {
            TreeItem downItem = rulesTree.getSelectedItem();

            if (RuleUtil.isNotNullOrRoot(downItem)) {
                TreeItem parent = downItem.getParentItem();
                int index = parent.getChildIndex(downItem);
                int childCount = parent.getChildCount();

                if (index < (childCount - 1)) {
                    //move rule
                    FASTMappingRule parentRule = selectedRule.getParent();
                    parentRule.addAfterOfKids(selectedRule, selectedRule);

                    rulesTree = createRulesTree();
                }
            }

            updateFactsTree();
        }
    }

    /**
     * Rule left - Handler
     * */
    class RuleLeftHandler implements ClickHandler {
        @Override
        public void onClick(ClickEvent event) {
            TreeItem leftItem = rulesTree.getSelectedItem();

            if (RuleUtil.isNotNullOrRoot(leftItem) && RuleUtil.isNotNullOrRoot(leftItem.getParentItem())) {
                FASTMappingRule parent = selectedRule.getParent();

                FASTMappingRule addRuleHere = parent.getParent();

                addRuleHere.addBeforeOfKids(parent, selectedRule);
                rulesTree = createRulesTree();
            }

            updateFactsTree();
        }
    }

    /**
     * Rule right - Handler
     * */
    class RuleRightHandler implements ClickHandler {
        @Override
        public void onClick(ClickEvent event) {
            TreeItem rightItem = rulesTree.getSelectedItem();

            if (RuleUtil.isNotNullOrRoot(rightItem)) {
                FASTMappingRule parentRule = selectedRule.getParent();
                FASTMappingRule intoRule = parentRule.getNextOfKids(selectedRule);
                intoRule.addToKids(0, selectedRule);
                rulesTree = createRulesTree();
            }

            updateFactsTree();
        }
    }
}