/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 *
 * The Original Code is Protege-2000.
 *
 * The Initial Developer of the Original Code is Stanford University. Portions
 * created by Stanford University are Copyright (C) 2007.  All Rights Reserved.
 *
 * Protege was developed by Stanford Medical Informatics
 * (http://www.smi.stanford.edu) at the Stanford University School of Medicine
 * with support from the National Library of Medicine, the National Science
 * Foundation, and the Defense Advanced Research Projects Agency.  Current
 * information about Protege can be obtained at http://protege.stanford.edu.
 *
 */


// TODO: should probably a more specific exception - not SWRLRuleEngineBridgeException

package edu.stanford.smi.protegex.owl.swrl.bridge;

import java.util.HashMap;
import java.util.Set;
import java.util.logging.Logger;

import edu.stanford.smi.protege.plugin.PluginUtilities;
import edu.stanford.smi.protege.util.Log;
import edu.stanford.smi.protegex.owl.model.OWLModel;
import edu.stanford.smi.protegex.owl.swrl.bridge.exceptions.InvalidBridgeNameException;
import edu.stanford.smi.protegex.owl.swrl.bridge.exceptions.NoRegisteredBridgesException;
import edu.stanford.smi.protegex.owl.swrl.bridge.exceptions.SWRLRuleEngineBridgeException;

/**
 ** Factory to create instances of common bridge entities
 */
public class BridgeFactory
{
    private static transient final Logger log = Log.getLogger(BridgeFactory.class);
  private static HashMap<String, BridgeCreator> registeredBridges;

  static {
    registeredBridges = new HashMap<String, BridgeCreator>();
  } // static

  static {
    Class cls = PluginUtilities.forName("edu.stanford.smi.protegex.owl.swrl.bridge.jess.SWRLJessBridge", true);
    if (cls == null) System.err.println("SWRLJessBridge load failed - could not find class");
   } // static

  public static void registerBridge(String bridgeName, BridgeCreator bridgeCreator)
  {
    if (registeredBridges.containsKey(bridgeName)) {
      registeredBridges.remove(bridgeName);
      registeredBridges.put(bridgeName, bridgeCreator);
    } else registeredBridges.put(bridgeName, bridgeCreator);

    log.info("Rule engine '" + bridgeName + "' registered with the SWRLTab bridge.");
  } // registerBridge

  public static boolean isBridgeRegistered(String bridgeName) { return registeredBridges.containsKey(bridgeName); }
  public static Set<String> getRegisteredBridgeNames() { return registeredBridges.keySet(); }

  /**
   ** Create an instance of a rule engine - a random registered engine is returned. If no engine is registered, a
   ** NoRegisteredBridgesException is returned.
   */
  public static SWRLRuleEngineBridge createBridge(OWLModel owlModel) throws SWRLRuleEngineBridgeException
  {
    if (!registeredBridges.isEmpty()) return createBridge(registeredBridges.keySet().iterator().next(), owlModel);
    else throw new NoRegisteredBridgesException();
  } // createBridge

  /**
   ** Create an instance of a named rule engine. Throws an InvalidBridgeNameException if an engine of this name is not registered.
   */
  public static SWRLRuleEngineBridge createBridge(String bridgeName, OWLModel owlModel) throws SWRLRuleEngineBridgeException
  {
    SWRLRuleEngineBridge bridge = null;

    if (registeredBridges.containsKey(bridgeName)) {

      try {
        bridge = registeredBridges.get(bridgeName).create(owlModel);
      } catch (Throwable e) {
        throw new SWRLRuleEngineBridgeException("Error creating rule engine '" + bridgeName + "': " + e.getMessage());
      } // try

    } else throw new InvalidBridgeNameException(bridgeName);

    return bridge;
  } // createBridge

  public static void unregisterBridge(String bridgeName)
  {
    if (registeredBridges.containsKey(bridgeName)) registeredBridges.remove(bridgeName);
  } // unregisterBridge

  public interface BridgeCreator
  {
    SWRLRuleEngineBridge create(OWLModel owlModel) throws SWRLRuleEngineBridgeException;
  } // BridgeCreator

} // BridgeFactory
