org.dlw.ai.blackboard.Controller.java Source code

Java tutorial

Introduction

Here is the source code for org.dlw.ai.blackboard.Controller.java

Source

/**
 * Copyright 2010,2011,2012,2013,2014 
 * David L. Whitehurst
 *
 * Licensed under the Apache License, Version 2.0 
 * (the "License"); You may not use this file except 
 * in compliance with the License. You may obtain a 
 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, 
 * software distributed under the License is distributed on an 
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
 * either express or implied. See the License for the specific 
 * language governing permissions and limitations under the 
 * License.
 * 
 */
package org.dlw.ai.blackboard;

import java.util.Collections;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dlw.ai.blackboard.domain.Assumption;
import org.dlw.ai.blackboard.exception.CollectionLoadingException;
import org.dlw.ai.blackboard.exception.InitializationException;
import org.dlw.ai.blackboard.knowledge.KnowledgeSource;
import org.dlw.ai.blackboard.knowledge.KnowledgeSources;
import org.dlw.ai.blackboard.knowledge.KnowledgeSourcesImpl;
import org.dlw.ai.blackboard.util.SystemConstants;

/**
 * The Controller class is used to orchestrate (state machine controller) the
 * problem solving that occurs at the blackboard. Knowledge sources are called
 * to evaluate the current blackboard state and accept hints and try them in
 * turn until the problem is solved.
 * 
 * @author <a href="mailto:dlwhitehurst@gmail.com">David L. Whitehurst</a>
 * @version 1.0.0
 * 
 */
public class Controller {

    /**
     * Attribute active or current knowledge source
     */
    private KnowledgeSource activeKnowledgeSource;

    /**
     * Attribute collection and entire problem domain of knowledge sources
     */
    private final KnowledgeSourcesImpl knowledgeSources = new KnowledgeSourcesImpl();

    /**
     * Attribute class logger
     */
    private static final Log log = LogFactory.getLog(Controller.class);

    /**
     * Attribute enum state of the controller
     */
    private ControllerState state;

    /**
     * Attribute blackboard or problem solving sandbox
     */
    private Blackboard blackboard;

    /**
     * Public constructor
     */
    public Controller() {
        /**
         * State - initializing
         */
        this.state = ControllerState.INITIALIZING;
    }

    /**
     * Public method to signal halt of the controller
     * 
     */
    public final void done() {
        System.exit(0); // Temporary for testing
        state = ControllerState.SOLVED;
    }

    /**
     * Public method to determine if the controller is stuck and cannot proceed
     * 
     * @return boolean primitive
     */
    public final boolean unableToProceed() {
        boolean result = false;

        if (state == ControllerState.STUCK) {
            result = true;
        }

        return result;
    }

    /**
     * Public method to determine if the controller is done (solved)
     * 
     * @return boolean primitive
     */
    public boolean isSolved() {

        boolean result = false;

        if (state == ControllerState.SOLVED) {
            result = true;
        }

        return result;
    }

    /**
     * Public method to cycle each KnowledgeSource and evaluate the current
     * blackboard problem string (repeatable method)
     */
    public final void processNextHint() {

        KnowledgeSourcesImpl knowledgeSources = (KnowledgeSourcesImpl) getKnowledgeSources();

        Collections.sort(knowledgeSources);

        /**
         * go thru ks experts and choose the best one to go to the blackboard
         */
        for (KnowledgeSource ks : knowledgeSources) {

            ks.evaluate();
            state = ControllerState.EVALUATING;

            ConcurrentLinkedQueue<Assumption> queue = ks.getPastAssumptions();

            if (queue.size() > 0) {
                activeKnowledgeSource = ks;
                break;
            }

        }

        log.info("processNextHint->The " + activeKnowledgeSource.toString() + " is now active.");

        if (activeKnowledgeSource != null) {

            /**
             * Take a turn at the board
             */
            visitBlackboard(activeKnowledgeSource);

            /**
             * Step down and give the next expert a chance
             */
            leaveBlackboard(activeKnowledgeSource);

            /**
             * Null activeKnowledgeSource
             */
            activeKnowledgeSource = null;
        }

    }

    /**
     * Public reset method to null the brain and knowledge sources and create a
     * new brain. Knowledge sources are not created until the engage() method on
     * brain is called.
     */
    public final void reset() {

        /**
         * Dismiss experts
         */
        activeKnowledgeSource = null;

        try {
            knowledgeSources.reset();
        } catch (InitializationException e) {
            log.error("Could not reset and initialize knowledge sources.");
        } catch (CollectionLoadingException e) {
            log.error("Some failure occurred loading knowledge source collection.");
        }

        /**
         * Initial controller state
         */
        state = ControllerState.INITIALIZING;

    }

    /**
     * Private method for KnowledgeSource expert to have a turn at the
     * blackboard problem
     * 
     * @param hint
     *            the KnowledgeSource (or Expert) 
     */
    private void visitBlackboard(KnowledgeSource ks) {

        blackboard = BlackboardContext.getInstance().getBlackboard();

        log.info("visitBlackboard-> Controller is now connecting " + ks.toString() + " to the blackboard.");

        blackboard.connect(ks);

    }

    /**
     * Private method to leave or disengage from the blackboard.
     * 
     * @param hint
     *            the KnowledgeSource (or Expert)
     */
    private void leaveBlackboard(KnowledgeSource ks) {

        blackboard.disconnect(ks);

        log.info("leaveBlackboard-> Controller has disconnected the " + ks.toString() + " from the blackboard.");
    }

    /**
     * Connect and manage the brain
     */
    public final void connect() {

        engage();
        if (log.isInfoEnabled()) {
            log.info(
                    "Controller::connect-> Controller has requested the brain employ the services of its knowledge experts.");
        } else {
            System.err.println(SystemConstants.INFO_LEVEL_FATAL);
            System.exit(0); // die
        }
    }

    /**
     * Public method to engage and load knowledge sources (intelligence)
     */
    public void engage() {

        try {
            knowledgeSources.init();
        } catch (InitializationException e) {
            log.error("Could not engage and initialize knowledge sources.");
        } catch (CollectionLoadingException e) {
            log.error("Some failure occurred loading knowledge source collection.");
        }
    }

    /**
     * @return the knowledgeSources
     */
    public KnowledgeSources getKnowledgeSources() {
        return knowledgeSources;
    }

}