Package at.salzburgresearch.nodekeeper.eca

Source Code of at.salzburgresearch.nodekeeper.eca.RuleHandler$InputOutputHandler

package at.salzburgresearch.nodekeeper.eca;

import at.salzburgresearch.nodekeeper.NodeKeeper;
import at.salzburgresearch.nodekeeper.NodeListener;
import at.salzburgresearch.nodekeeper.eca.function.Function;
import at.salzburgresearch.nodekeeper.eca.function.FunctionFactory;
import at.salzburgresearch.nodekeeper.eca.function.StaticValueFunction;
import at.salzburgresearch.nodekeeper.exception.NodeKeeperException;
import at.salzburgresearch.nodekeeper.model.Node;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

/**
* ...
* <p/>
* Author: Thomas Kurz (tkurz@apache.org)
*/
public class RuleHandler {

    HashMap<String,Rule> rules = new HashMap<String, Rule>();
    NodeKeeper nodeKeeper;

    public RuleHandler(NodeKeeper nodeKeeper) {
        this.nodeKeeper = nodeKeeper;
    }

    public void readRules(InputStream stream) throws NodeKeeperException, IOException, InterruptedException {
        //remove old rules
        List<Rule> rs = InputOutputHandler.parseRules(stream);
        ArrayList<String> keys = new ArrayList<String>(rules.keySet());
        for(String ruleid : keys) {
            removeRule(rules.get(ruleid));
        }
        for(Rule rule : rs) {
            addRule(rule);
        }
    }

    public void writeRules(OutputStream stream) throws ParserConfigurationException, TransformerException, IOException {
        List<Rule> r = new ArrayList<Rule>();
        for(String ruleid : rules.keySet()) {
            r.add(rules.get(ruleid));
        }
        InputOutputHandler.serializeRules(r,stream);
    }

    public void addRule(Rule rule) throws NodeKeeperException, IOException, InterruptedException {
        deactivateRule(rule);
        activateRule(rule);
        rules.put(rule.id,rule);
    }

    public Rule getRule(String id) {
        return rules.get(id);
    }

    public Set<String> getRuleIds() {
        return rules.keySet();
    }

    public void removeRule(Rule rule) {
        deactivateRule(rule);
        rules.remove(rule.id);
    }

    private void activateRule(final Rule rule) throws NodeKeeperException, IOException, InterruptedException {

        //handle event
        rule.setNodeListener(new NodeListener() {

            private void execute(Node node) throws InterruptedException, IOException, NodeKeeperException {
                HashMap<String,String> bindings = bindVariables(node);
                if(checkConditions(bindings)) {
                    for(Action action : rule.actions) {
                        action.execute(nodekeeper,bindings);
                    }
                }
            }

            private HashMap<String,String> bindVariables(Node node) {
                HashMap<String,String> bindings = new HashMap<String, String>();
                for(Binding binding : rule.bindings) {
                    bindings.put(binding.name,binding.execute(nodekeeper,node));
                }
                return bindings;
            }

            private boolean checkConditions(HashMap<String,String> bindings) {
                boolean result = true;
                for(Condition condition : rule.conditions) {
                    result = condition.execute(bindings);
                }
                return result;
            }

            @Override
            public void onNodeCreated(Node node) throws InterruptedException, NodeKeeperException {
                if(rule.event.type == Event.Type.nodeCreated || rule.event.type == Event.Type.nodeCreatedUpdated) try {
                    execute(node);
                } catch (IOException e) {
                    e.printStackTrace()//To change body of catch statement use File | Settings | File Templates.
                }
            }

            @Override
            public void onNodeUpdated(Node node) throws InterruptedException, NodeKeeperException {
                if(rule.event.type == Event.Type.nodeUpdated || rule.event.type == Event.Type.nodeCreatedUpdated) try {
                    execute(node);
                } catch (IOException e) {
                    e.printStackTrace()//To change body of catch statement use File | Settings | File Templates.
                }
            }

            @Override
            public void onNodeDeleted(Node node) throws InterruptedException, NodeKeeperException {
                if(rule.event.type == Event.Type.nodeDeleted) try {
                    execute(node);
                } catch (IOException e) {
                    e.printStackTrace()//To change body of catch statement use File | Settings | File Templates.
                }
            }

            @Override
            public Class getType() {
                return rule.event.nodeType;
            }
        });

        nodeKeeper.addListener(rule.event.pattern, rule.getNodeListener());
        nodeKeeper.startListeners();
    }

    private void deactivateRule(Rule rule) {
        if(rules.containsKey(rule.id)) {
            Rule r = rules.get(rule.id);
            nodeKeeper.removeListener(r.event.pattern, r.getNodeListener());
        }
        //reverting actions is not possible at the moment
    }

    public static class InputOutputHandler {

        public static List<Rule> parseRules(InputStream inputStream) throws IOException {
            try {
                List<Rule> rules = new ArrayList<Rule>();

                DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
                DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
                Document doc = dBuilder.parse(inputStream);

                //get rules
                NodeList rulesNodes = doc.getDocumentElement().getChildNodes();

                for(int i = 0; i < rulesNodes.getLength(); i++) {
                    org.w3c.dom.Node ruleNode = rulesNodes.item(i);

                    if (ruleNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                        Element ruleElement = (Element)ruleNode;

                        Rule rule = new Rule();
                        if(ruleElement.getAttribute("name") != null) rule.id = ruleElement.getAttribute("name");

                        //get event
                        NodeList events = ruleElement.getElementsByTagName("event");
                        NodeList bindings = ruleElement.getElementsByTagName("bindings");
                        NodeList conditions = ruleElement.getElementsByTagName("conditions");//TODO
                        NodeList actions = ruleElement.getElementsByTagName("actions");

                        for(int j = 0; j < events.getLength(); j++) {
                            org.w3c.dom.Node eventNode = events.item(j);
                            if (eventNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                                Element eventElement = (Element)eventNode;
                                String typeString  = eventElement.getAttribute("type");

                                if(typeString == null) throw new IOException(String.format("Type of event #$s in rule #%s must be set", j, i));
                                if(eventElement.getElementsByTagName("params").getLength()<0) throw new IOException(String.format("Type of event #$s in rule #%s must have a param", j, i));

                                Event.Type type = Event.Type.valueOf(typeString);
                                if(type == null) throw new IOException(String.format("Type %s of event #$s in rule #%s is not supported", typeString, j, i));

                                rule.event = new Event(type,eventElement.getElementsByTagName("param").item(0).getTextContent().trim());
                            }
                        }
                        if(rule.event == null) throw new IOException(String.format("Rule #%s must contain an event element",i));

                        if(bindings.getLength()>0) {
                            NodeList bindingList = bindings.item(0).getChildNodes();
                            for(int j = 0; j < bindingList.getLength(); j++) {
                                org.w3c.dom.Node bindingNode = bindingList.item(j);
                                if (bindingNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                                    Element bindingElement = (Element)bindingNode;

                                    String name  = bindingElement.getAttribute("name");
                                    String type  = bindingElement.getAttribute("type");

                                    if(type==null || type.equals("")) {
                                        Function f = new StaticValueFunction();
                                        f.init(bindingElement.getTextContent().trim());
                                        rule.bindings.add(new Binding(name,f));
                                    } else {
                                        Function f = createFunction(type,bindingElement.getChildNodes());
                                        rule.bindings.add(new Binding(name,f));
                                    }
                                }
                            }
                        }

                        //TODO conditions

                        if (actions.getLength() > 0) {
                            NodeList actionList = actions.item(0).getChildNodes();
                            for (int j = 0; j < actionList.getLength(); j++) {
                                org.w3c.dom.Node actionNode = actionList.item(j);
                                if (actionNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                                    Element actionElement = (Element) actionNode;
                                    String typeString = actionElement.getAttribute("type");

                                    if (typeString == null)
                                        throw new IOException(String.format("Type of action #$s in rule #%s must be set", j, i));

                                    Action.Type type = Action.Type.valueOf(typeString);
                                    if (type == null)
                                        throw new IOException(String.format("Type %s of event #$s in rule #%s is not supported", typeString, j, i));

                                    NodeList paramNodes = actionElement.getElementsByTagName("param");
                                    String[] params = new String[paramNodes.getLength()];
                                    for (int k = 0; k < paramNodes.getLength(); k++) {
                                        org.w3c.dom.Node paramNode = paramNodes.item(k);
                                        if (paramNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                                            Element paramElement = (Element) paramNode;
                                            params[k] = paramElement.getTextContent().trim();
                                        }
                                    }

                                    rule.actions.add(new Action(type,params));
                                }
                            }
                        }

                        rules.add(rule);
                    }

                }

                return rules;

            } catch (ParserConfigurationException e) {
                e.printStackTrace()//To change body of catch statement use File | Settings | File Templates.
            } catch (SAXException e) {
                e.printStackTrace()//To change body of catch statement use File | Settings | File Templates.
            } catch (IOException e) {
                e.printStackTrace()//To change body of catch statement use File | Settings | File Templates.
            }
            return null;
        }

        private static Function createFunction(String name, NodeList params) {
            Function f = FunctionFactory.createFunction(name);
            ArrayList<Object> paramObjects = new ArrayList<Object>();
            for(int i = 0; i < params.getLength(); i++) {
                org.w3c.dom.Node paramNode = params.item(i);
                if(paramNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                    Element param = (Element)paramNode;
                    String pname  = param.getAttribute("name");
                    String ptype  =param.getAttribute("type");

                    if(ptype==null || ptype.equals("")) {
                        Function fx = new StaticValueFunction();
                        fx.init(param.getTextContent());
                        paramObjects.add(fx);
                    } else {
                        Function fx = createFunction(ptype,param.getChildNodes());
                        paramObjects.add(fx);
                    }
                }
            }
            f.init(paramObjects.toArray());
            return f;
        }

        public static void serializeRules(List<Rule> rules, OutputStream stream) throws ParserConfigurationException, TransformerException, IOException  {
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            Document doc = docBuilder.newDocument();

            Element rootElement = doc.createElement("rules");
            doc.appendChild(rootElement);

            for(Rule rule : rules) {
                rootElement.appendChild(rule.toElement(doc));
            }

            DOMSource domSource = new DOMSource(doc);
            StreamResult result = new StreamResult(stream);

            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer transformer = tf.newTransformer();
            transformer.transform(domSource, result);
            stream.flush();
        }

    }
}
TOP

Related Classes of at.salzburgresearch.nodekeeper.eca.RuleHandler$InputOutputHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.