Previous topic  Top  Next topic  Print this Topic
 

A Connector Built-in

 

A connector is a built-in which is used to access external servers (for example, databases, indexes, search engines).
Query of the ontology:

?- p(?X) AND democonnector(?X,?Y).

How A Connector Works:

At first OntoBroker looks what variables have to be bound, free and which variables are not important for being evaluable. Then, it asks the connector for the goodness of some of the patterns. It is up to the connector to interpret the goodness, it could be the difference of a full table scan and using the primary key of a database access.

Then, the instance of the connector for the evaluation is created, and init is called. Start is called, followed by some calls for input. The connector could now start to work. If it needs to have all input tuples, it has to start the evaluation when stop is called. The connector has to send all data before leaving the stop method. (So don't use a separate thread for it.) After stop was called, other start/input*/stop cycles could occur. evaluationFinished may possible be called and could be followed from a repetition of the evaluation, but now started with start/input*/stop cycles.

package com.ontoprise.builtin.iconnector;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.net.MalformedURLException;

import java.net.URL;

import java.util.ArrayList;

import java.util.BitSet;

import org.apache.log4j.Logger;

import org.semanticweb.kaon2.api.KAON2Exception;

import org.semanticweb.kaon2.api.KAON2Manager;

import org.semanticweb.kaon2.api.logic.Term;

import com.ontoprise.builtin.BuiltinContext;

import com.ontoprise.builtin.BuiltinSpec;

import com.ontoprise.builtin.interfaces.IConnector;

import com.ontoprise.builtin.interfaces.IGrounds;

import com.ontoprise.builtin.interfaces.IReceiver;

import com.ontoprise.util.OntopriseConstants;

import com.ontoprise.util.TermUtilities;

import com.ontoprise.utils.StringUtil;

/**

* Example connector which reads information from a URL. A connector receives a list of tuples

* and sends away a list of tuples. This demo connector reads the content of each URL and determines

* the number of characters for each URL.

*

*/

public class CountCharactersOfURLsConnector implements IConnector {

  private IReceiver _destination;

  private ArrayList _input;

  protected static Logger _log = Logger.getLogger(OntopriseConstants.CORE_LOG);

//    {{STRING, VARIABLE}};

  /**

    * Provide a no-argument constructur which sets the properties of the connector.

    */

  public CountCharactersOfURLsConnector() {

  }

 

 

  /**

    * Method to get informations about this built-in. This method has to deliver a valid BuiltinSpec object

    * after the constructor finishes, before init() has be called.

    *

    * @return BuiltinSpec object with informations about this built-in.

    */

  @Override

  public BuiltinSpec getInfo() {

      BuiltinSpec.Builder builder = new BuiltinSpec.Builder(this, "countCharactersOfURLs", 2);

      builder.setDescription("gets number of characters of different URI-documents");

      builder.setParameters("URI","number of characters");

      return builder.build();

  }

 

  /**

    * Method to signal that several input tuples will arrive. Between start() and stop() the grounds will not change.

    *

    * @param grounds IGrounds object with grounding informations of all following input tuples.

    * @param destination Receiver for each result created.

    * @throws KAON2Exception Is thrown on Error

    * @throws InterruptedException Is thrown on Interruption

    */

  @Override

  public void start(IGrounds grounds, IReceiver destination) throws KAON2Exception, InterruptedException {

      _destination = destination;

      _input = new ArrayList(200);

  }

 

  /**

    * This method will provide the input tuples. May just called between start() and stop().

    *

    * @param input Term[] with input.

    * @throws KAON2Exception Is thrown on Error

    * @throws InterruptedException Is thrown on Interruption

    */

  @Override

  public void input(Term[] input) throws KAON2Exception, InterruptedException {

      Term[] terms = new Term[input.length];

      System.arraycopy(input, 0, terms, 0, input.length);

      _input.add(terms);

  }

 

  /**

    * Method to signal that no further input will follow within this block.

    * (Although there could be another start() / stop() cycle.)

    * All what has to be done to deliver results has to be done here if it was not done before.

    * After this method has finished, any results have to be sended by the IReceiver, no additional

    * data is allowed.

    *

    * @throws KAON2Exception Is thrown on Error

    * @throws InterruptedException Is thrown on Interruption

    */

  @Override

  public void stop() throws KAON2Exception, InterruptedException {

      Term[] newArguments = new Term[2];

      for (Term[] arguments: _input) {

          String url = StringUtil.unQuote((String) TermUtilities.getValue(arguments[0]));

          int numOfCharacters = openAndReadURL(url);

          newArguments[0] = arguments[0];

          newArguments[1] = KAON2Manager.factory().constant(new Double(numOfCharacters));

          _destination.send(newArguments);

      }

  }

 

 

  /**

    * Opens a URL, reads the content and counts the characters.

    *

    * @param urlString                 the URL

    * @return                          the number of characters of the document at the URL location

    */

  private int openAndReadURL(String urlString) {

      int numOfCharacters = 0;

      try {

          URL url = new URL(urlString);

          InputStreamReader isr = new InputStreamReader(url.openStream());

          BufferedReader in = new BufferedReader(isr);

          String line;

          while ((line = in.readLine()) != null) {

              numOfCharacters += line.length();

          }

          in.close();

      } catch (MalformedURLException ex) {

          _log.error("DemoConnector received invalid URL: " + urlString);

      } catch (IOException ex) {

          _log.error("DemoConnector got an IOException while reading the URL '" + urlString + "'.", ex);

      }

      return numOfCharacters;

  }

  /**

    * Returns how effective these grounds may be evaluated. Should deliver 0 if it does not matter.

    * Like IBuiltin.isEvaluable() this method may be called before init() has been called.

    *

    * @param grounds IGrounds object with grounding informations of all following input tuples.

    * @param builtinContext BuiltinContext with additional context informations

    * @param args Literal arguments

    * @return int with goodness value.

    */

  @Override

  public int getGoodness(IGrounds grounds, BuiltinContext builtinContext, Term[] args) throws KAON2Exception, InterruptedException {

      // this connector has just one possible binding, so just use a constant number between 0 and 1000.

      // 1000 should mean this connector is much faster than a connector with goodness 0.

      return 500;

  }

 

  /**

    * This method will be called after evaluation for cleanup purposes.

    *

    * NOTE: It is possible that this operator will be used again when the same query object is openened again.

    * init() won't be called a second time.

    *

    * @throws KAON2Exception Is thrown on Error

    * @throws InterruptedException Is thrown on Interruption

    */

  @Override

  public void evaluationFinished() throws KAON2Exception, InterruptedException {

      // This built-in has just one state, no need to set it back.

      // It is used to set a built-in to the post-init() state.

      // btw.: This is not a dispose method, don't use it to clean up. Maybe it won't be called.

  }

  /**

    * Initialisation of this built-in. This is done for the instance before evaluation.

    *

    * @param context Contains additional Informations needed for some built-ins

    * @param args Term[] that contains the literal arguments.

    * @throws KAON2Exception Is thrown on Error

    * @throws InterruptedException Is thrown on Interruption

    */

  @Override

  public void init(BuiltinContext context, Term[] args) throws KAON2Exception, InterruptedException {

  }

 

  /**

    * Method to determine if a certain grounds configuration is evaluable.

    * This method has to be usable context free, init() is called in an other instance as

    * isEvaluable will be called. All needed information should be provided by the current

    * method arguments.

    *

    * @param grounds Object with grounding informations.

    * @param variableInstantiations This BitSets has the instantiation of all variables that occurs. Needed especially if partial-ground functions are used.

    * @param builtinContext BuiltinContext with additional context informations

    * @param args Literal arguments

    * @return if this grounds are evaluable or not.

    * @throws KAON2Exception Is thrown on Error

    */

  @Override

  public boolean isEvaluable(IGrounds grounds, BitSet variableInstantiations, BuiltinContext builtinContext, Term[] args) throws KAON2Exception {

      return grounds.getBitSet().get(0) && !grounds.getBitSet().get(1); // the first argument must be ground, the second argument must not be ground.

  }

}