/*
 * 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.
 *
 */


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

import edu.stanford.smi.protegex.owl.swrl.ddm.*;
import edu.stanford.smi.protegex.owl.swrl.bridge.*;
import edu.stanford.smi.protegex.owl.swrl.bridge.exceptions.*;
import edu.stanford.smi.protegex.owl.swrl.bridge.builtins.*;

import java.util.*;
import java.sql.*;

/**
 */
public class SWRLBuiltInLibraryImpl extends AbstractSWRLBuiltInLibrary 
{
  private static String SWRLDDMLibraryName = "SWRLDDMBuiltIns";

  private ArgumentFactory argumentFactory;

  public SWRLBuiltInLibraryImpl() 
  { 
    super(SWRLDDMLibraryName); 

    argumentFactory = ArgumentFactory.getFactory();
  } // SWRLBuiltInLibraryImpl

  public void reset() 
  {
  } // reset

  public boolean makeDatabase(List<BuiltInArgument> arguments) throws BuiltInException
  {
    SWRLBuiltInUtil.checkNumberOfArgumentsEqualTo(7, arguments.size());

    String jdbcDriverName = SWRLBuiltInUtil.getArgumentAsAString(1, arguments);
    String serverName = SWRLBuiltInUtil.getArgumentAsAString(2, arguments);
    String databaseName = SWRLBuiltInUtil.getArgumentAsAString(3, arguments);
    int portNumber  = SWRLBuiltInUtil.getArgumentAsAnInteger(4, arguments);
    String userID = SWRLBuiltInUtil.getArgumentAsAString(5, arguments);
    String password = SWRLBuiltInUtil.getArgumentAsAString(6, arguments);
    Database database = DDMFactory.createDatabase(jdbcDriverName, serverName, databaseName, portNumber);

    try { 
      DatabaseConnection connection = DDMFactory.createDatabaseConnection(database, userID, password);
    } catch (SQLException e) {
      throw new BuiltInException("SQL exception when connecting to database: " + e.getMessage());
    } // try

    return true;
  } // makeDatabase

  public boolean mapOWLClass(List<BuiltInArgument> arguments) throws BuiltInException 
  { 
    boolean result = false, isUnboundIndividualArgument;
    OWLClass owlClass;
    OWLIndividual owlIndividual = null;
    Set<OWLIndividual> individuals = new HashSet<OWLIndividual>();
    String className;
    Mapper mapper;

    SWRLBuiltInUtil.checkNumberOfArgumentsAtLeast(2, arguments.size());

    className = SWRLBuiltInUtil.getArgumentAsAClassName(0, arguments);

    if (!getInvokingBridge().hasMapper()) return false;

    isUnboundIndividualArgument = SWRLBuiltInUtil.isUnboundArgument(1, arguments);

    if (!isUnboundIndividualArgument) throw new BuiltInException("bound arguments not yet implemented, class = '" + className + "'");

    try {
      owlClass = OWLFactory.createOWLClass(className);

      mapper = getInvokingBridge().getMapper();
      if (!mapper.isMapped(owlClass)) return false;

      individuals = mapper.mapOWLClass(owlClass);
      
      //if (!individuals.isEmpty()) getInvokingBridge().createOWLIndividuals(individuals);
      if (isUnboundIndividualArgument) {
        MultiArgument multiArgument = argumentFactory.createMultiArgument(SWRLBuiltInUtil.getVariableName(1, arguments), SWRLBuiltInUtil.getPrefixedVariableName(1, arguments));
        for (OWLIndividual individual : individuals) multiArgument.addArgument(individual);
        arguments.set(1, multiArgument);
        result = !multiArgument.hasNoArguments();
      } else result = false;
    } catch (SWRLRuleEngineBridgeException e) {
      throw new BuiltInException("error mapping OWL class '" + className + "': " + e.getMessage());
    } // try

    return result;
  } // mapOWLClass

  public boolean mapOWLObjectProperty(List<BuiltInArgument> arguments) throws BuiltInException 
  { 
    boolean result = false, hasSubject, hasObject;
    OWLProperty owlProperty;
    OWLIndividual subjectOWLIndividual = null, objectOWLIndividual = null;
    Set<OWLObjectPropertyAssertionAxiom> axioms = new HashSet<OWLObjectPropertyAssertionAxiom>();
    String propertyName;
    Mapper mapper;

    SWRLBuiltInUtil.checkNumberOfArgumentsAtLeast(1, arguments.size());
    SWRLBuiltInUtil.checkForUnboundArguments(arguments);

    propertyName = SWRLBuiltInUtil.getArgumentAsAPropertyName(0, arguments);

    if (!getInvokingBridge().hasMapper()) return false;

    hasSubject = (arguments.size() > 1);
    hasObject = (arguments.size() > 2);

    try {
      owlProperty = OWLFactory.createOWLObjectProperty(propertyName);
      
      if (hasSubject) subjectOWLIndividual = OWLFactory.createOWLIndividual(SWRLBuiltInUtil.getArgumentAsAnIndividualName(1, arguments));
      if (hasObject) objectOWLIndividual = OWLFactory.createOWLIndividual(SWRLBuiltInUtil.getArgumentAsAnIndividualName(2, arguments));
      
      mapper = getInvokingBridge().getMapper();
      
      if (!mapper.isMapped(owlProperty)) return false;
      
      if (!hasSubject && !hasObject) axioms = mapper.mapOWLObjectProperty(owlProperty);
      else if (hasSubject && !hasObject) axioms = mapper.mapOWLObjectProperty(owlProperty, subjectOWLIndividual);
      else axioms = mapper.mapOWLObjectProperty(owlProperty, subjectOWLIndividual, objectOWLIndividual);
      
      if (!axioms.isEmpty()) getInvokingBridge().createOWLObjectPropertyAssertionAxioms(axioms);

    } catch (SWRLRuleEngineBridgeException e) {
      throw new BuiltInException("error mapping OWL object property '" + propertyName + "': " + e.getMessage());
    } // try

    return !axioms.isEmpty();
  } // mapOWLObjectProperty

  public boolean mapOWLDatatypeProperty(List<BuiltInArgument> arguments) throws BuiltInException 
  { 
    boolean result = false, hasSubject, hasValue;
    OWLProperty owlProperty;
    OWLIndividual subjectOWLIndividual = null;
    OWLDatatypeValue value = null;
    Set<OWLDatatypePropertyAssertionAxiom> axioms = new HashSet<OWLDatatypePropertyAssertionAxiom>();
    String propertyName;
    Mapper mapper;

    SWRLBuiltInUtil.checkNumberOfArgumentsAtLeast(1, arguments.size());
    SWRLBuiltInUtil.checkForUnboundArguments(arguments);

    propertyName = SWRLBuiltInUtil.getArgumentAsAPropertyName(0, arguments);

    if (!getInvokingBridge().hasMapper()) return false;

    hasSubject = (arguments.size() > 1) && SWRLBuiltInUtil.isArgumentAnIndividual(1, arguments);
    hasValue = (arguments.size() > 2 || (arguments.size() > 1 && SWRLBuiltInUtil.isArgumentADatatypeValue(1, arguments)));
    try {
      owlProperty = OWLFactory.createOWLDatatypeProperty(propertyName);
      
      if (hasSubject) subjectOWLIndividual = OWLFactory.createOWLIndividual(SWRLBuiltInUtil.getArgumentAsAnIndividualName(1, arguments));
      if (hasValue) {
        if (hasSubject) value = SWRLBuiltInUtil.getArgumentAsAnOWLDatatypeValue(2, arguments);
        else value = SWRLBuiltInUtil.getArgumentAsAnOWLDatatypeValue(1, arguments);
      } // if
      
      mapper = getInvokingBridge().getMapper();
      
      if (!mapper.isMapped(owlProperty)) return false;

      if (!hasSubject && !hasValue) axioms = mapper.mapOWLDatatypeProperty(owlProperty);
      else if (hasSubject && !hasValue) axioms = mapper.mapOWLDatatypeProperty(owlProperty, subjectOWLIndividual);
      else if (!hasSubject && hasValue) axioms = mapper.mapOWLDatatypeProperty(owlProperty, value);
      else axioms = mapper.mapOWLDatatypeProperty(owlProperty, subjectOWLIndividual, value);
      
      if (!axioms.isEmpty()) getInvokingBridge().createOWLDatatypePropertyAssertionAxioms(axioms);
    } catch (SWRLRuleEngineBridgeException e) {
      throw new BuiltInException("error mapping OWL datatype property '" + propertyName + "': " + e.getMessage());
    } // try

    return !axioms.isEmpty();
  } // mapOWLDatatypeProperty

} // SWRLBuiltInLibraryImpl
