com.cloud2bubble.services.RuleEngine.java Source code

Java tutorial

Introduction

Here is the source code for com.cloud2bubble.services.RuleEngine.java

Source

/**
 *    Copyright (C) 2011 Pedro Mauricio Costa <pm.costa [at] imperial [dot] ac [dot] uk>
 *
 *    This file is part of Cloud2Bubble <http://www.cloud2bubble.com>.
 *
 *     Cloud2Bubble is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Lesser Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     Cloud2Bubble 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 Lesser Public License for more details.
 *
 *     You should have received a copy of the GNU Lesser Public License
 *     along with Cloud2Bubble.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.cloud2bubble.services;

import java.util.HashMap;
import java.util.Map;

import net.ponder2.managedobject.Bubble;
import net.ponder2.managedobject.Cloudlet;
import net.ponder2.managedobject.MessagingQueue.Producer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseConfiguration;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderErrors;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.conf.EventProcessingOption;
import org.drools.io.ResourceFactory;
import org.drools.logger.KnowledgeRuntimeLogger;
import org.drools.logger.KnowledgeRuntimeLoggerFactory;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.rule.FactHandle;
import org.drools.runtime.rule.WorkingMemoryEntryPoint;

import com.cloud2bubble.Cloud2Bubble;

/**
 * Provides the functionality of a Rule Engine including temporal event reasoning.
 * 
 * @author Pedro Mauricio Costa <pm.costa@imperial.ac.uk>
 *
 */
public class RuleEngine {

    private static final Log log = LogFactory.getLog(RuleEngine.class);

    public static final String EVENT_LISTENER = "EventListener";

    public static final String MESSAGE_LISTENER = "MessageListener";

    public static final String GLOBAL_LOG = "$log";

    public static final String GLOBAL_PRODUCER = "$producer";

    public static final String ENGINE_LOGGER = "rule-engine";

    private static RuleEngine instance = null;

    private Map<Object, FactHandle> facts;

    private KnowledgeBase kbase;

    private StatefulKnowledgeSession ksession;

    private KnowledgeRuntimeLogger engineLogger;

    private WorkingMemoryEntryPoint eventListenerEntryPoint;

    private WorkingMemoryEntryPoint messageListenerEntryPoint;

    private Producer producer;

    private RuleEngine() {

        try {
            kbase = createKnowledgeBase();
            ksession = kbase.newStatefulKnowledgeSession();
            engineLogger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, ENGINE_LOGGER);
            ksession.setGlobal(GLOBAL_LOG, log);
            eventListenerEntryPoint = ksession.getWorkingMemoryEntryPoint(EVENT_LISTENER);
            messageListenerEntryPoint = ksession.getWorkingMemoryEntryPoint(MESSAGE_LISTENER);

            new Thread(new Runnable() {
                public void run() {
                    ksession.fireUntilHalt();
                }
            }).start();

        } catch (Exception e) {
            log.fatal("Couldn't initiate the Rule Engine", e);
        }

        facts = new HashMap<Object, FactHandle>();
    }

    /**
     * Returns the singleton instance of the Rule Engine.
     * 
     * @return
     */
    public static RuleEngine getInstace() {

        if (instance == null) {
            instance = new RuleEngine();
        }

        return instance;
    }

    public void setProducer(Producer p) {

        ksession.setGlobal(GLOBAL_PRODUCER, p);
    }

    /**
     * Inserts any object into the Rule Engine.
     * 
     * @param o a fact 
     */
    public void insertInSession(Object o) {
        FactHandle fh = ksession.insert(o);
        facts.put(o.hashCode(), fh);
    }

    /**
     * Updates an existing object in the Rule Engine.
     * 
     * @param o a fact
     */
    public void updateInSession(String o) {
        ksession.update(facts.get(o), o.hashCode());
    }

    /**
     * Inserts any object into the Rule Engine through the Event Listener Entry Point.
     * 
     * @param o an event
     */
    public void insertInEventListener(Object o) {

        eventListenerEntryPoint.insert(o);
    }

    public void insertInMessageListener(Object o) {

        messageListenerEntryPoint.insert(o);
    }

    /**
     * Stops the Rule Engine.
     */
    public void stop() {
        ksession.halt();
        engineLogger.close();
    }

    /**
     * Handles the heavy process of loading rules into a knowledge base.
     * 
     * @return knowledge base ready to generate sessions 
     * @throws Exception
     */
    private static KnowledgeBase createKnowledgeBase() throws Exception {
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add(ResourceFactory.newClassPathResource(Cloud2Bubble.getRuleFile()), ResourceType.DRL);
        KnowledgeBuilderErrors errors = kbuilder.getErrors();

        if (errors.size() > 0) {
            for (KnowledgeBuilderError error : errors) {
                log.error(error);
            }
            throw new IllegalArgumentException("Could not parse knowledge.");
        }

        // activates event time-based processing
        KnowledgeBaseConfiguration config = KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
        config.setOption(EventProcessingOption.STREAM);

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(config);
        kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());

        return kbase;
    }

    public void sendQoeEvent(Cloudlet c, Bubble b) {
        this.producer.sendQoEEvent(b.getId(), c.getId());
    }
}