Code Search for Developers
 
 
  

KBPartitionFacadeBean.java from Texai at Krugle


Show KBPartitionFacadeBean.java syntax highlighted

/*
 * KBPartitionFacadeBean.java
 *
 * Created on May 2, 2007, 12:29 PM
 *
 * Description: Provides a single interface to wrap TermFinderFacadeLocal, TermDeleterFacadeLocal, TermDefinitionAccessorLocal,
 * AssociationFinderLocal and AssociationEditorLocal with respect to a single KB partition.
 *
 * Copyright (C) May 2, 2007 Stephen L. Reed.
 *
 * This program is free software; you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program;
 * if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

package org.texai.kb.ejb.session.shared;

import com.sleepycat.je.DatabaseException;
import com.sleepycat.persist.EntityCursor;
import com.sleepycat.persist.EntityIndex;
import com.sleepycat.persist.EntityStore;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.Stack;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import net.jcip.annotations.GuardedBy;
import net.jcip.annotations.ThreadSafe;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import org.apache.log4j.Logger;
import org.apache.servicemix.beanflow.Activity;
import org.apache.servicemix.beanflow.CallableActivity;
import org.apache.servicemix.beanflow.JoinAll;
import org.apache.servicemix.beanflow.JoinFirstCallableActivityResult;
import org.texai.kb.Constants;
import org.texai.kb.entity.AbstractReifiedTerm;
import org.texai.kb.entity.AbstractTerm;
import org.texai.kb.entity.AtomicTerm;
import org.texai.kb.entity.BinaryGAF;
import org.texai.kb.entity.Formula;
import org.texai.kb.entity.LocalTermIdReference;
import org.texai.kb.entity.NonAtomicTerm;
import org.texai.kb.entity.PByteArray;
import org.texai.kb.entity.PDate;
import org.texai.kb.entity.PDouble;
import org.texai.kb.entity.PLong;
import org.texai.kb.entity.PString;
import org.texai.kb.entity.PVariable;
import org.texai.kb.entity.QuaternaryGAF;
import org.texai.kb.entity.QuintaryGAF;
import org.texai.kb.entity.RemoteTermIdReference;
import org.texai.kb.entity.Rule;
import org.texai.kb.entity.Symbol;
import org.texai.kb.entity.TernaryGAF;
import org.texai.kb.entity.UnaryGAF;
import org.texai.util.ByteUtils;
import org.texai.util.TexaiException;

/**
 *
 * @author reed
 */
@ThreadSafe
public class KBPartitionFacadeBean implements KBPartitionFacadeLocal {
  
  /** the KB shard peer facade dictionary, [low term id, hi term id] --> KB shard facade */
  private final Map<Integer[], KBPartitionFacadeLocal> kbShardPeerFacadeDictionary = new HashMap<Integer[], KBPartitionFacadeLocal>();
  
  /** the executor */
  private Executor executor;
  
  /** the KB shard in which new KB objects are created */
  @GuardedBy("itself")
  private volatile KBPartitionFacadeLocal kbShardForNewObjects;
  
  /** the logger */
  private transient Logger logger;                         // NOPMD
  
  /** Creates a new instance of KBPartitionFacadeBean. */
  public KBPartitionFacadeBean() {
    super();
  }
  
  /** Sets the KB shard in which new KB objects are created.  A value of null forces a peek at each KB shard
   * to recover the KB shard in which new KB objects are created.
   *
   * @param kbShardForNewObjects the KB shard in which new KB objects are created
   */
  public void setKBShardForNewObjects(final KBPartitionFacadeLocal kbShardForNewObjects) {
    this.kbShardForNewObjects = kbShardForNewObjects;
  }
  
  // TermFinderFacadeLocal
  
  /** Returns the highest term id without incrementing it.
   *
   * @return the highest term id without incrementing it
   */
  @SuppressWarnings("unchecked")
  public int peekHighestTermId() {
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity<Integer>(getExecutor(), new CallPeekHighestTermId(kbShardFacade)));
    }
    // run parallel activities
    final JoinAll joinAll = new JoinAll(activities);
    // wait for them to all complete
    joinAll.join();
    int highestTermId = -1;
    for (final Activity activity : activities) {
      final CallableActivity<Integer> callableActivity = (CallableActivity) activity;
      int result;
      try {
        result = callableActivity.getFuture().get();
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      }
      if (result > highestTermId) {
        highestTermId = result;
      }
    }
    return highestTermId;
  }
  
  /** Call the peekHighestTermId method in a given kb shard facade. */
  @ThreadSafe
  class CallPeekHighestTermId implements Callable<Integer> {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    
    /** Create a new instance of CallPeekHighestTermId.
     *
     * @param kbShardFacade the kb shard facade
     */
    public CallPeekHighestTermId(final KBPartitionFacadeLocal kbShardFacade) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      
      this.kbShardFacade = kbShardFacade;
    }
    
    /** Call the peekHighestTermId method.
     *
     * @return the highest term id without incrementing it
     */
    public Integer call() {
      return Integer.valueOf(kbShardFacade.peekHighestTermId());
    }
  }
  
  /** Finds the LocalTermIdReference having the given termId.
   *
   * @param termId the given term id
   * @return the LocalTermIdReference having the given termId
   * @throws TexaiException if the term is not found
   */
  public LocalTermIdReference findLocalTermIdReferenceByTermId(final int termId) {
    //Preconditions
    assert termId >= 0 : "termId must be positive";
    
    return findKBShardFacadeByTermId(termId).findLocalTermIdReferenceByTermId(termId);
  }
  
  /** Finds the LocalTermIdReference having the given UUID.
   *
   * @param uuid the given UUID
   * @return the LocalTermIdReference having the given UUID
   */
  @SuppressWarnings("unchecked")
  public LocalTermIdReference findLocalTermIdReferenceByUUID(final UUID uuid) {
    //Preconditions
    assert uuid != null : "uuid must not be null";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindLocalTermIdReferenceByUUID(kbShardFacade, uuid)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<LocalTermIdReference> callableActivity = (CallableActivity) activity;
      LocalTermIdReference localTermIdReference = null;
      try {
        localTermIdReference = callableActivity.getFuture().get();
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      }
      if (localTermIdReference != null) {
        return localTermIdReference;
      }
    }
    // not found
    return null;
  }
  
  /** Call the findLocalTermIdReferenceByUUID method in a given kb shard facade. */
  @ThreadSafe
  class CallFindLocalTermIdReferenceByUUID implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the UUID */
    final UUID uuid;
    
    /** Create a new instance of CallFindLocalTermIdReferenceByUUID.
     *
     * @param kbShardFacade the kb shard facade
     * @param uuid the UUID
     */
    public CallFindLocalTermIdReferenceByUUID(final KBPartitionFacadeLocal kbShardFacade, final UUID uuid) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert uuid != null : "uuid must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.uuid = uuid;
    }
    
    /** Call the findLocalTermIdReferenceByUUID method.
     *
     * @return the LocalTermIdReference having the given UUID
     */
    public LocalTermIdReference call() {
      return kbShardFacade.findLocalTermIdReferenceByUUID(uuid);
    }
  }
  
  /** Finds the RemoteTermIdReference having the given termId.
   *
   * @param termId the given term id
   * @return the RemoteTermIdReference having the given termId
   */
  public RemoteTermIdReference findRemoteTermIdReferenceByTermId(final int termId) {
    //Preconditions
    assert termId >= 0 : "termId must be positive";
    
    return findKBShardFacadeByTermId(termId).findRemoteTermIdReferenceByTermId(termId);
  }
  
  /** Finds the term having the given value.
   *
   * @param value the given value object
   * @return the term having the given value
   */
  public AbstractTerm findTermByValue(final Object value) {
    //Preconditions
    assert value != null : "value must not be null";
    
    AbstractTerm valueTerm = null;
    if (value instanceof String) {
      valueTerm = findPStringByStringValue((String) value);
    } else if (value instanceof Integer) {
      valueTerm = findPLongByLongValue(Long.valueOf(((Integer) value).longValue()));
    } else if (value instanceof Long) {
      valueTerm = findPLongByLongValue((Long) value);
    } else if (value instanceof Float) {
      valueTerm = findPDoubleByDoubleValue(Double.valueOf(((Float) value).doubleValue()));
    } else if (value instanceof Double) {
      valueTerm = findPDoubleByDoubleValue((Double) value);
    } else if (value instanceof Date) {
      valueTerm = findPDateByDateValue((Date) value);
    } else {
      throw new TexaiException("cannot find term for value type: " + value);
    }
    return valueTerm;
  }
  
  /** Call the findTermByValue method in a given kb shard facade. */
  @ThreadSafe
  class CallFindTermByValue implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the given value object */
    final Object value;
    
    /** Create a new instance of CallFindTermByValue.
     *
     * @param kbShardFacade the kb shard facade
     * @param value the given value object
     */
    public CallFindTermByValue(final KBPartitionFacadeLocal kbShardFacade, final Object value) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert value != null : "value must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.value = value;
    }
    
    /** Call the findTermByValue method.
     *
     * @return the term having the given value
     */
    public AbstractTerm call() {
      return kbShardFacade.findTermByValue(value);
    }
  }
  
  /** Finds the Term having the given termType and termId.
   *
   * @param termType the given term type
   * @param termId the given term id
   * @return the Term having the given termType and termId
   * @throws TexaiException if the term is not found
   */
  public AbstractTerm findTermByTermTypeAndId(final byte termType, final int termId) {
    //Preconditions
    assert termType >= 0 : "termType must be positive";
    assert termId >= 0 : "termId must be positive";
    
    return findKBShardFacadeByTermId(termId).findTermByTermTypeAndId(termType, termId);
  }
  
  /** Finds the Symbol having the given termId.
   *
   * @param termId the given term id
   * @return the Symbol having the given termId
   * @throws TexaiException if the term is not found
   */
  public Symbol findSymbolByTermId(final int termId) {
    //Preconditions
    assert termId >= 0 : "termId must be positive";
    
    return findKBShardFacadeByTermId(termId).findSymbolByTermId(termId);
  }
  
  /** Finds the Symbol having the given nameValue or null if not found.
   *
   * @param nameValue the given name value
   * @return the Symbol having the given nameValue or null if not found
   */
  @SuppressWarnings("unchecked")
  public Symbol findSymbolByNameValue(final String nameValue) {
    //Preconditions
    assert nameValue != null : "nameValue must not be null";
    assert !nameValue.isEmpty() : "nameValue must not be an empty string";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindSymbolByNameValue(kbShardFacade, nameValue)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<Symbol> callableActivity = (CallableActivity) activity;
      Symbol symbol = null;
      try {
        symbol = callableActivity.getFuture().get();
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      }
      if (symbol != null) {
        return symbol;
      }
    }
    // not found
    return null;
  }
  
  /** Call the findSymbolByNameValue method in a given kb shard facade. */
  @ThreadSafe
  class CallFindSymbolByNameValue implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the given name value */
    final String nameValue;
    
    /** Create a new instance of CallFindSymbolByNameValue.
     *
     * @param kbShardFacade the kb shard facade
     * @param nameValue the given name value
     */
    public CallFindSymbolByNameValue(final KBPartitionFacadeLocal kbShardFacade, final String nameValue) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert nameValue != null : "nameValue must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.nameValue = nameValue;
    }
    
    /** Call the findSymbolByNameValue method.
     *
     * @return the Symbol having the given nameValue or null if not found
     */
    public Symbol call() {
      return kbShardFacade.findSymbolByNameValue(nameValue);
    }
  }
  
  /** Finds the PVariable having the given termId.
   *
   * @param termId the given term id
   * @return the PVariable having the given termId
   * @throws TexaiException if the term is not found
   */
  public PVariable findPVariableByTermId(final int termId) {
    //Preconditions
    assert termId >= 0 : "termId must be positive";
    
    return findKBShardFacadeByTermId(termId).findPVariableByTermId(termId);
  }
  
  /** Finds the PVariable having the given nameValue or null if not found.
   *
   * @param nameValue the given name value
   * @return the PVariable having the given nameValue or null if not found
   */
  @SuppressWarnings("unchecked")
  public PVariable findPVariableByNameValue(final String nameValue) {
    //Preconditions
    assert nameValue != null : "nameValue must not be null";
    assert !nameValue.isEmpty() : "nameValue must not be an empty string";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindPVariableByNameValue(kbShardFacade, nameValue)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<PVariable> callableActivity = (CallableActivity) activity;
      PVariable pVariable = null;
      try {
        pVariable = callableActivity.getFuture().get();
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      }
      if (pVariable != null) {
        return pVariable;
      }
    }
    // not found
    return null;
  }
  
  /** Call the findPVariableByNameValue method in a given kb shard facade. */
  @ThreadSafe
  class CallFindPVariableByNameValue implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the given name value */
    final String nameValue;
    
    /** Create a new instance of CallFindSymbolByNameValue.
     *
     * @param kbShardFacade the kb shard facade
     * @param nameValue the given name value
     */
    public CallFindPVariableByNameValue(final KBPartitionFacadeLocal kbShardFacade, final String nameValue) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert nameValue != null : "nameValue must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.nameValue = nameValue;
    }
    
    /** Call the findPVariableByNameValue method.
     *
     * @return the PVariable having the given nameValue or null if not found
     */
    public PVariable call() {
      return kbShardFacade.findPVariableByNameValue(nameValue);
    }
  }
  
  /** Finds the PLong having the given termId.
   *
   * @param termId the given term id
   * @return the PLong having the given termId
   * @throws TexaiException if the term is not found
   */
  public PLong findPLongByTermId(final int termId) {
    //Preconditions
    assert termId >= 0 : "termId must be positive";
    
    return findKBShardFacadeByTermId(termId).findPLongByTermId(termId);
  }
  
  /** Finds the PLong having the given longValue or null if not found.
   *
   * @param longValue the given long value
   * @return the PLong having the given nameValue or null if not found
   */
  @SuppressWarnings("unchecked")
  public PLong findPLongByLongValue(final Long longValue) {
    //Preconditions
    assert longValue != null : "longValue must not be null";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindPLongByLongValue(kbShardFacade, longValue)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<PLong> callableActivity = (CallableActivity) activity;
      PLong pLong = null;
      try {
        pLong = callableActivity.getFuture().get();
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      }
      if (pLong != null) {
        return pLong;
      }
    }
    // not found
    return null;
  }
  
  /** Call the findPLongByLongValue method in a given kb shard facade. */
  @ThreadSafe
  class CallFindPLongByLongValue implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the given long value */
    final Long longValue;
    
    /** Create a new instance of CallFindPLongByLongValue.
     *
     * @param kbShardFacade the kb shard facade
     * @param longValue the given long value
     */
    public CallFindPLongByLongValue(final KBPartitionFacadeLocal kbShardFacade, final Long longValue) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert longValue != null : "nameValue must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.longValue = longValue;
    }
    
    /** Call the findPLongByLongValue method.
     *
     * @return the Plong having the given nameValue or null if not found
     */
    public PLong call() {
      return kbShardFacade.findPLongByLongValue(longValue);
    }
  }
  
  /** Finds the PDouble having the given termId.
   *
   * @param termId the given term id
   * @return the PDouble having the given termId
   * @throws TexaiException if the term is not found
   */
  public PDouble findPDoubleByTermId(final int termId) {
    //Preconditions
    assert termId >= 0 : "termId must be positive";
    
    return findKBShardFacadeByTermId(termId).findPDoubleByTermId(termId);
  }
  
  /** Finds the PDouble having the given doubleValue or null if not found.
   *
   * @param doubleValue the given double value
   * @return the PDouble having the given doubleValue or null if not found
   */
  @SuppressWarnings("unchecked")
  public PDouble findPDoubleByDoubleValue(final Double doubleValue) {
    //Preconditions
    assert doubleValue != null : "doubleValue must not be null";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindPDoubleByDoubleValue(kbShardFacade, doubleValue)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<PDouble> callableActivity = (CallableActivity) activity;
      PDouble pDouble = null;
      try {
        pDouble = callableActivity.getFuture().get();
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      }
      if (pDouble != null) {
        return pDouble;
      }
    }
    // not found
    return null;
  }
  
  /** Call the findPDoubleByDoubleValue method in a given kb shard facade. */
  @ThreadSafe
  class CallFindPDoubleByDoubleValue implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the given double value */
    final Double doubleValue;
    
    /** Create a new instance of CallFindPDoubleByDoubleValue.
     *
     * @param kbShardFacade the kb shard facade
     * @param longValue the given long value
     */
    public CallFindPDoubleByDoubleValue(final KBPartitionFacadeLocal kbShardFacade, final Double doubleValue) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert doubleValue != null : "doubleValue must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.doubleValue = doubleValue;
    }
    
    /** Call the findPDoubleByDoubleValue method.
     *
     * @return the Plong having the given nameValue or null if not found
     */
    public PDouble call() {
      return kbShardFacade.findPDoubleByDoubleValue(doubleValue);
    }
  }
  
  /** Finds the PString having the given termId.
   *
   * @param termId the given term id
   * @return the PString having the given termId
   * @throws TexaiException if the term is not found
   */
  public PString findPStringByTermId(final int termId) {
    //Preconditions
    assert termId >= 0 : "termId must be positive";
    
    return findKBShardFacadeByTermId(termId).findPStringByTermId(termId);
  }
  
  /** Finds the PString having the given stringValue or null if not found.
   *
   * @param stringValue the given string value
   * @return the PString having the given stringValue or null if not found
   */
  @SuppressWarnings("unchecked")
  public PString findPStringByStringValue(final String stringValue) {
    //Preconditions
    assert stringValue != null : "stringValue must not be null";
    assert !stringValue.isEmpty() : "stringValue must not be an empty string";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindPStringByStringValue(kbShardFacade, stringValue)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<PString> callableActivity = (CallableActivity) activity;
      PString pString = null;
      try {
        pString = callableActivity.getFuture().get();
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      }
      if (pString != null) {
        return pString;
      }
    }
    // not found
    return null;
  }
  
  /** Call the findPStringByStringValue method in a given kb shard facade. */
  @ThreadSafe
  class CallFindPStringByStringValue implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the given string value */
    final String stringValue;
    
    /** Create a new instance of CallFindPStringByStringValue.
     *
     * @param kbShardFacade the kb shard facade
     * @param longValue the given string value
     */
    public CallFindPStringByStringValue(final KBPartitionFacadeLocal kbShardFacade, final String stringValue) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert stringValue != null : "stringValue must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.stringValue = stringValue;
    }
    
    /** Call the findPStringByStringValue method.
     *
     * @return the PString having the given stringValue or null if not found
     */
    public PString call() {
      return kbShardFacade.findPStringByStringValue(stringValue);
    }
  }
  
  /** Finds the PByteArray having the given termId.
   *
   * @param termId the given term id
   * @return the PByteArray having the given termId
   * @throws TexaiException if the term is not found
   */
  public PByteArray findPByteArrayByTermId(final int termId) {
    //Preconditions
    assert termId >= 0 : "termId must be positive";
    
    return findKBShardFacadeByTermId(termId).findPByteArrayByTermId(termId);
  }
  
  /** Finds the PDate having the given termId.
   *
   * @param termId the given term id
   * @return the PDate having the given termId
   * @throws TexaiException if the term is not found
   */
  public PDate findPDateByTermId(final int termId) {
    //Preconditions
    assert termId >= 0 : "termId must be positive";
    
    return findKBShardFacadeByTermId(termId).findPDateByTermId(termId);
  }
  
  /** Finds the PDate having the given dateValue or null if not found.
   *
   * @param dateValue the given date value
   * @return the PDate having the given dateValue or null if not found
   */
  @SuppressWarnings("unchecked")
  public PDate findPDateByDateValue(final Date dateValue) {
    //Preconditions
    assert dateValue != null : "dateValue must not be null";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindPDateByDateValue(kbShardFacade, dateValue)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<PDate> callableActivity = (CallableActivity) activity;
      PDate pDate = null;
      try {
        pDate = callableActivity.getFuture().get();
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      }
      if (pDate != null) {
        return pDate;
      }
    }
    // not found
    return null;
  }
  
  /** Call the findPDateByDateValue method in a given kb shard facade. */
  @ThreadSafe
  class CallFindPDateByDateValue implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the given date value */
    final Date dateValue;
    
    /** Create a new instance of CallFindPDateByDateValue.
     *
     * @param kbShardFacade the kb shard facade
     * @param dateValue the given date value
     */
    public CallFindPDateByDateValue(final KBPartitionFacadeLocal kbShardFacade, final Date dateValue) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert dateValue != null : "dateValue must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.dateValue = dateValue;
    }
    
    /** Call the findPDateByDateValue method.
     *
     * @return the PDate having the given dateValue or null if not found
     */
    public PDate call() {
      return kbShardFacade.findPDateByDateValue(dateValue);
    }
  }
  
  /** Finds the AtomicTerm having the given UUID.
   *
   * @param uuid the given UUID
   * @return the AtomicTerm having the given uuid
   * @throws TexaiException if the term is not found
   */
  @SuppressWarnings("unchecked")
  public AtomicTerm findAtomicTermByUUID(final UUID uuid) {
    //Preconditions
    assert uuid != null : "uuid must not be null";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindAtomicTermByUUID(kbShardFacade, uuid)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<AtomicTerm> callableActivity = (CallableActivity) activity;
      AtomicTerm atomicTerm = null;
      try {
        atomicTerm = callableActivity.getFuture().get();
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      }
      if (atomicTerm != null) {
        return atomicTerm;
      }
    }
    // not found
    throw new TexaiException("AtomicTerm not found for UUID " + uuid);
  }
  
  /** Call the findAtomicTermByUUID method in a given kb shard facade. */
  @ThreadSafe
  class CallFindAtomicTermByUUID implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the UUID */
    final UUID uuid;
    
    /** Create a new instance of CallFindAtomicTermByUUID.
     *
     * @param kbShardFacade the kb shard facade
     * @param uuid the given UUID
     */
    public CallFindAtomicTermByUUID(final KBPartitionFacadeLocal kbShardFacade, final UUID uuid) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert uuid != null : "uuid must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.uuid = uuid;
    }
    
    /** Call the findAtomicTermByUUID method.
     *
     * @return the AtomicTerm having the given uuid
     */
    public AtomicTerm call() {
      return kbShardFacade.findAtomicTermByUUID(uuid);
    }
  }
  
  /** Finds the AtomicTerm having the given termId.
   *
   * @param termId the given term id
   * @return the AtomicTerm having the given termId
   * @throws TexaiException if the term is not found
   */
  public AtomicTerm findAtomicTermByTermId(final int termId) {
    //Preconditions
    assert termId >= 0 : "termId must be positive";
    
    return findKBShardFacadeByTermId(termId).findAtomicTermByTermId(termId);
  }
  
  /** Finds the AtomicTerm having the given term name or null if not found.
   *
   * @param termName the given term name
   * @return the AtomicTerm having the given term name or null if not found
   */
  @SuppressWarnings("unchecked")
  public AtomicTerm findAtomicTermByTermName(final String termName) {
    //Preconditions
    assert termName != null : "termName must not be null";
    assert !termName.isEmpty() : "termName must not be an empty string";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindAtomicTermByTermName(kbShardFacade, termName)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<AtomicTerm> callableActivity = (CallableActivity) activity;
      AtomicTerm atomicTerm = null;
      try {
        atomicTerm = callableActivity.getFuture().get();
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      }
      if (atomicTerm != null) {
        return atomicTerm;
      }
    }
    // not found
    return null;
  }
  
  /** Call the findAtomicTermByTermName method in a given kb shard facade. */
  @ThreadSafe
  class CallFindAtomicTermByTermName implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the given term name */
    final String termName;
    
    /** Create a new instance of CallFindAtomicTermByUUID.
     *
     * @param kbShardFacade the kb shard facade
     * @param termName the given term name
     */
    public CallFindAtomicTermByTermName(final KBPartitionFacadeLocal kbShardFacade, final String termName) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert termName != null : "termName must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.termName = termName;
    }
    
    /** Call the findAtomicTermByTermName method.
     *
     * @return the AtomicTerm having the given term name
     */
    public AtomicTerm call() {
      return kbShardFacade.findAtomicTermByTermName(termName);
    }
  }
  
  /** Finds the NonAtomicTerm having the given UUID.
   *
   * @param uuid the given uuid
   * @return the NonAtomicTerm having the given uuid
   * @throws TexaiException if the term is not found
   */
  @SuppressWarnings("unchecked")
  public NonAtomicTerm findNonAtomicTermByUUID(final UUID uuid) {
    //Preconditions
    assert uuid != null : "uuid must not be null";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindAtomicTermByUUID(kbShardFacade, uuid)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<NonAtomicTerm> callableActivity = (CallableActivity) activity;
      NonAtomicTerm nonAtomicTerm = null;
      try {
        nonAtomicTerm = callableActivity.getFuture().get();
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      }
      if (nonAtomicTerm != null) {
        return nonAtomicTerm;
      }
    }
    // not found
    throw new TexaiException("NonAtomicTerm not found for UUID " + uuid);
  }
  
  /** Call the findNonAtomicTermByUUID method in a given kb shard facade. */
  @ThreadSafe
  class CallFindNonAtomicTermByUUID implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the UUID */
    final UUID uuid;
    
    /** Create a new instance of CallFindAtomicTermByUUID.
     *
     * @param kbShardFacade the kb shard facade
     * @param uuid the given UUID
     */
    public CallFindNonAtomicTermByUUID(final KBPartitionFacadeLocal kbShardFacade, final UUID uuid) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert uuid != null : "uuid must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.uuid = uuid;
    }
    
    /** Call the findNonAtomicTermByUUID method.
     *
     * @return the NonAtomicTerm having the given uuid
     */
    public NonAtomicTerm call() {
      return kbShardFacade.findNonAtomicTermByUUID(uuid);
    }
  }
  
  /** Finds the NonAtomicTerm having the given termId.
   *
   * @param termId the given term id
   * @return the NonAtomicTerm having the given termId
   * @throws TexaiException if the term is not found
   */
  public NonAtomicTerm findNonAtomicTermByTermId(final int termId) {
    //Preconditions
    assert termId >= 0 : "termId must be positive";
    
    return findKBShardFacadeByTermId(termId).findNonAtomicTermByTermId(termId);
  }
  
  /** Finds the NonAtomicTerm having the given termName or null if not found.
   *
   * @param termName the given term name
   * @return the NonAtomicTerm having the given termName or null if not found
   */
  @SuppressWarnings("unchecked")
  public NonAtomicTerm findNonAtomicTermByTermName(final String termName) {
    //Preconditions
    assert termName != null : "termName must not be null";
    assert !termName.isEmpty() : "termName must not be an empty string";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindNonAtomicTermByTermName(kbShardFacade, termName)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<NonAtomicTerm> callableActivity = (CallableActivity) activity;
      NonAtomicTerm nonAtomicTerm = null;
      try {
        nonAtomicTerm = callableActivity.getFuture().get();
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      }
      if (nonAtomicTerm != null) {
        return nonAtomicTerm;
      }
    }
    // not found
    return null;
  }
  
  /** Call the findNonAtomicTermByTermName method in a given kb shard facade. */
  @ThreadSafe
  class CallFindNonAtomicTermByTermName implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the given term name */
    final String termName;
    
    /** Create a new instance of CallFindAtomicTermByUUID.
     *
     * @param kbShardFacade the kb shard facade
     * @param termName the given term name
     */
    public CallFindNonAtomicTermByTermName(final KBPartitionFacadeLocal kbShardFacade, final String termName) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert termName != null : "termName must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.termName = termName;
    }
    
    /** Call the findNonAtomicTermByTermName method.
     *
     * @return the NonAtomicTerm having the given termName or null if not found
     */
    public NonAtomicTerm call() {
      return kbShardFacade.findNonAtomicTermByTermName(termName);
    }
  }
  
  /** Finds the Formula having the given termId.
   *
   * @param termId the given term id
   * @return the Formula having the given termId
   * @throws TexaiException if the term is not found
   */
  public Formula findFormulaByTermId(final int termId) {
    //Preconditions
    assert termId >= 0 : "termId must be positive";
    
    return findKBShardFacadeByTermId(termId).findFormulaByTermId(termId);
  }
  
  /** Finds the Formula having the given term list or null if not found.
   *
   * @param termList the given term list
   * @return the Formula having the given term list or null if not found
   */
  @SuppressWarnings("unchecked")
  public Formula findFormulaByTermList(final List<AbstractTerm> termList) {
    //Preconditions
    assert termList != null : "termList must not be null";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindFormulaByTermList(kbShardFacade, termList)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<Formula> callableActivity = (CallableActivity) activity;
      Formula formula = null;
      try {
        formula = callableActivity.getFuture().get();
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      }
      if (formula != null) {
        return formula;
      }
    }
    // not found
    return null;
  }
  
  /** Call the findFormulaByTermList method in a given kb shard facade. */
  @ThreadSafe
  class CallFindFormulaByTermList implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the given term list */
    final List<AbstractTerm> termList;
    
    /** Create a new instance of CallFindFormulaByTermList.
     *
     * @param kbShardFacade the kb shard facade
     * @param termList the given term list
     */
    public CallFindFormulaByTermList(final KBPartitionFacadeLocal kbShardFacade, final List<AbstractTerm> termList) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert termList != null : "termList must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.termList = termList;
    }
    
    /** Call the findFormulaByTermList method.
     *
     * @return the Formula having the given term list or null if not found
     */
    public Formula call() {
      return kbShardFacade.findFormulaByTermList(termList);
    }
  }
  
  /** Finds the Formula having the given formulaString or null if not found.
   *
   * @param formulaString the given formula string
   * @return the Formula having the given formulaString or null if not found
   */
  @SuppressWarnings("unchecked")
  public Formula findFormulaByFormulaString(final String formulaString) {
    //Preconditions
    assert formulaString != null : "formulaString must not be null";
    assert !formulaString.isEmpty() : "formulaString must not be an empty string";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindFormulaByFormulaString(kbShardFacade, formulaString)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<Formula> callableActivity = (CallableActivity) activity;
      Formula formula = null;
      try {
        formula = callableActivity.getFuture().get();
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      }
      if (formula != null) {
        return formula;
      }
    }
    // not found
    return null;
  }
  
  /** Call the findFormulaByFormulaString method in a given kb shard facade. */
  @ThreadSafe
  class CallFindFormulaByFormulaString implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the given formula string */
    final String formulaString;
    
    /** Create a new instance of CallFindFormulaByFormulaString.
     *
     * @param kbShardFacade the kb shard facade
     * @param formulaString the given formula string
     */
    public CallFindFormulaByFormulaString(final KBPartitionFacadeLocal kbShardFacade, final String formulaString) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert formulaString != null : "formulaString must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.formulaString = formulaString;
    }
    
    /** Call the findFormulaByFormulaString method.
     *
     * @return the Formula having the given term list or null if not found
     */
    public Formula call() {
      return kbShardFacade.findFormulaByFormulaString(formulaString);
    }
  }
  
  /** Finds the Rule having the given UUID.
   *
   * @param uuid the given uuid
   * @return the Rule having the given uuid
   * @throws TexaiException if the term is not found
   */
  @SuppressWarnings("unchecked")
  public Rule findRuleByUUID(final UUID uuid) {
    //Preconditions
    assert uuid != null : "uuid must not be null";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindRuleByUUID(kbShardFacade, uuid)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<Rule> callableActivity = (CallableActivity) activity;
      Rule rule = null;
      try {
        rule = callableActivity.getFuture().get();
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      }
      if (rule != null) {
        return rule;
      }
    }
    // not found
    throw new TexaiException("Rule not found for UUID " + uuid);
  }
  
  /** Call the findRuleByUUID method in a given kb shard facade. */
  @ThreadSafe
  class CallFindRuleByUUID implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the UUID */
    final UUID uuid;
    
    /** Create a new instance of CallFindRuleByUUID.
     *
     * @param kbShardFacade the kb shard facade
     * @param uuid the given UUID
     */
    public CallFindRuleByUUID(final KBPartitionFacadeLocal kbShardFacade, final UUID uuid) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert uuid != null : "uuid must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.uuid = uuid;
    }
    
    /** Call the findRuleByUUID method.
     *
     * @return the Rule having the given termId
     */
    public Rule call() {
      return kbShardFacade.findRuleByUUID(uuid);
    }
  }
  
  /** Finds the Rule having the given termId.
   *
   * @param termId the given term id
   * @return the Rule having the given termId
   * @throws TexaiException if the term is not found
   */
  public Rule findRuleByTermId(final int termId) {
    //Preconditions
    assert termId >= 0 : "termId must be positive";
    
    return findKBShardFacadeByTermId(termId).findRuleByTermId(termId);
  }
  
  /** Finds the Rule having the given formula or null if not found.
   *
   * @param formula the given formula
   * @return the Rule having the given formula or null if not found
   */
  @SuppressWarnings("unchecked")
  public Rule findRuleByFormula(final Formula formula) {
    //Preconditions
    assert formula != null : "formula must not be null";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindRuleByFormula(kbShardFacade, formula)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<Rule> callableActivity = (CallableActivity) activity;
      Rule rule = null;
      try {
        rule = callableActivity.getFuture().get();
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      }
      if (rule != null) {
        return rule;
      }
    }
    // not found
    return null;
  }
  
  /** Call the findRuleByFormula method in a given kb shard facade. */
  @ThreadSafe
  class CallFindRuleByFormula implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the given formula */
    final Formula formula;
    
    /** Create a new instance of CallFindRuleByFormula.
     *
     * @param kbShardFacade the kb shard facade
     * @param formula the given formula
     */
    public CallFindRuleByFormula(final KBPartitionFacadeLocal kbShardFacade, final Formula formula) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert formula != null : "formula must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.formula = formula;
    }
    
    /** Call the findRuleByFormula method.
     *
     * @return the Rule having the given formula or null if not found
     */
    public Rule call() {
      return kbShardFacade.findRuleByFormula(formula);
    }
  }
  
  /** Finds the UnaryGAF having the given UUID.
   *
   * @param uuid the given uuid
   * @return the UnaryGAF having the given uuid
   * @throws TexaiException if the term is not found
   */
  @SuppressWarnings("unchecked")
  public UnaryGAF findUnaryGAFByUUID(final UUID uuid) {
    //Preconditions
    assert uuid != null : "uuid must not be null";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindUnaryGAFByUUID(kbShardFacade, uuid)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<UnaryGAF> callableActivity = (CallableActivity) activity;
      UnaryGAF unaryGAF = null;
      try {
        unaryGAF = callableActivity.getFuture().get();
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      }
      if (unaryGAF != null) {
        return unaryGAF;
      }
    }
    // not found
    throw new TexaiException("UnaryGAF not found for UUID " + uuid);
  }
  
  /** Call the findUnaryGAFByUUID method in a given kb shard facade. */
  @ThreadSafe
  class CallFindUnaryGAFByUUID implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the UUID */
    final UUID uuid;
    
    /** Create a new instance of CallFindUnaryGAFByUUID.
     *
     * @param kbShardFacade the kb shard facade
     * @param uuid the given uuid
     */
    public CallFindUnaryGAFByUUID(final KBPartitionFacadeLocal kbShardFacade, final UUID uuid) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert uuid != null : "uuid must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.uuid = uuid;
    }
    
    /** Call the findUnaryGAFByUUID method.
     *
     * @return the UnaryGAF having the given termId
     */
    public UnaryGAF call() {
      return kbShardFacade.findUnaryGAFByUUID(uuid);
    }
  }
  
  /** Finds the UnaryGAF having the given termId.
   *
   * @param termId the given term id
   * @return the UnaryGAF having the given termId
   * @throws TexaiException if the term is not found
   */
  public UnaryGAF findUnaryGAFByTermId(final int termId) {
    //Preconditions
    assert termId >= 0 : "termId must be positive";
    
    return findKBShardFacadeByTermId(termId).findUnaryGAFByTermId(termId);
  }
  
  /** Finds the UnaryGAF having the given constitutents or null if not found.
   *
   * @param predicate the given predicate
   * @param args the argument list
   * @param context the context
   * @return the UnaryGAF having the given constitutents or null if not found
   */
  @SuppressWarnings("unchecked")
  public UnaryGAF findUnaryGAFByConstituents(
          final AbstractReifiedTerm predicate,
          final List<AbstractTerm> args,
          final AbstractReifiedTerm context) {
    //Preconditions
    assert predicate != null : "predicate must not be null";
    assert args != null : "args must not be null";
    assert context != null : "context must not be null";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindUnaryGAFByConstituents(
              kbShardFacade,
              predicate,
              args,
              context)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<UnaryGAF> callableActivity = (CallableActivity) activity;
      UnaryGAF unaryGAF = null;
      try {
        unaryGAF = callableActivity.getFuture().get();
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      }
      if (unaryGAF != null) {
        return unaryGAF;
      }
    }
    // not found
    return null;
  }
  
  /** Call the findUnaryGAFByConstituents method in a given kb shard facade. */
  @ThreadSafe
  class CallFindUnaryGAFByConstituents implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the given predicate */
    final AbstractReifiedTerm predicate;
    /** the argument list */
    final List<AbstractTerm> args;
    /** the context */
    final AbstractReifiedTerm context;
    
    /** Create a new instance of CallFindUnaryGAFByConstituents.
     *
     * @param kbShardFacade the kb shard facade
     * @param predicate the given predicate
     * @param args the argument list
     * @param context the context
     */
    public CallFindUnaryGAFByConstituents(
            final KBPartitionFacadeLocal kbShardFacade,
            final AbstractReifiedTerm predicate,
            final List<AbstractTerm> args,
            final AbstractReifiedTerm context) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert predicate != null : "predicate must not be null";
      assert args != null : "args must not be null";
      assert context != null : "context must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.predicate = predicate;
      this.args = args;
      this.context = context;
    }
    
    /** Call the findUnaryGAFByConstituents method.
     *
     * @return the UnaryGAF having the given constitutents or null if not found
     */
    public UnaryGAF call() {
      return kbShardFacade.findUnaryGAFByConstituents(
              predicate,
              args,
              context);
    }
  }
  
  /** Finds the BinaryGAF having the given UUID.
   *
   * @param uuid the given uuid
   * @return the BinaryGAF having the given uuid
   * @throws TexaiException if the term is not found
   */
  @SuppressWarnings("unchecked")
  public BinaryGAF findBinaryGAFByUUID(final UUID uuid) {
    //Preconditions
    assert uuid != null : "uuid must not be null";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindBinaryGAFByUUID(kbShardFacade, uuid)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<BinaryGAF> callableActivity = (CallableActivity) activity;
      BinaryGAF binaryGAF = null;
      try {
        binaryGAF = callableActivity.getFuture().get();
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      }
      if (binaryGAF != null) {
        return binaryGAF;
      }
    }
    // not found
    throw new TexaiException("BinaryGAF not found for UUID " + uuid);
  }
  
  /** Call the findBinaryGAFByUUID method in a given kb shard facade. */
  @ThreadSafe
  class CallFindBinaryGAFByUUID implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the UUID */
    final UUID uuid;
    
    /** Create a new instance of CallFindBinaryGAFByUUID.
     *
     * @param kbShardFacade the kb shard facade
     * @param uuid the given uuid
     */
    public CallFindBinaryGAFByUUID(final KBPartitionFacadeLocal kbShardFacade, final UUID uuid) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert uuid != null : "uuid must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.uuid = uuid;
    }
    
    /** Call the findBinaryGAFByUUID method.
     *
     * @return the BinaryGAF having the given uuid
     */
    public BinaryGAF call() {
      return kbShardFacade.findBinaryGAFByUUID(uuid);
    }
  }
  
  /** Finds the BinaryGAF having the given termId.
   *
   * @param termId the given term id
   * @return the BinaryGAF having the given termId
   * @throws TexaiException if the term is not found
   */
  public BinaryGAF findBinaryGAFByTermId(final int termId) {
    //Preconditions
    assert termId >= 0 : "termId must be positive";
    
    return findKBShardFacadeByTermId(termId).findBinaryGAFByTermId(termId);
  }
  
  /** Finds the BinaryGAF having the given constitutents or null if not found.
   *
   * @param predicate the given predicate
   * @param args the argument list
   * @param context the context
   * @return the BinaryGAF having the given constitutents or null if not found
   */
  @SuppressWarnings("unchecked")
  public BinaryGAF findBinaryGAFByConstituents(
          final AbstractReifiedTerm predicate,
          final List<AbstractTerm> args,
          final AbstractReifiedTerm context) {
    //Preconditions
    assert predicate != null : "predicate must not be null";
    assert args != null : "args must not be null";
    assert context != null : "context must not be null";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindBinaryGAFByConstituents(
              kbShardFacade,
              predicate,
              args,
              context)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<BinaryGAF> callableActivity = (CallableActivity) activity;
      BinaryGAF binaryGAF = null;
      try {
        binaryGAF = callableActivity.getFuture().get();
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      }
      if (binaryGAF != null) {
        return binaryGAF;
      }
    }
    // not found
    return null;
  }
  
  /** Call the findBinaryGAFByConstituents method in a given kb shard facade. */
  @ThreadSafe
  class CallFindBinaryGAFByConstituents implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the given predicate */
    final AbstractReifiedTerm predicate;
    /** the argument list */
    final List<AbstractTerm> args;
    /** the context */
    final AbstractReifiedTerm context;
    
    /** Create a new instance of CallFindBinaryGAFByConstituents.
     *
     * @param kbShardFacade the kb shard facade
     * @param predicate the given predicate
     * @param args the argument list
     * @param context the context
     */
    public CallFindBinaryGAFByConstituents(
            final KBPartitionFacadeLocal kbShardFacade,
            final AbstractReifiedTerm predicate,
            final List<AbstractTerm> args,
            final AbstractReifiedTerm context) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert predicate != null : "predicate must not be null";
      assert args != null : "args must not be null";
      assert context != null : "context must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.predicate = predicate;
      this.args = args;
      this.context = context;
    }
    
    /** Call the findBinaryGAFByConstituents method.
     *
     * @return the BinaryGAF having the given constitutents or null if not found
     */
    public BinaryGAF call() {
      return kbShardFacade.findBinaryGAFByConstituents(
              predicate,
              args,
              context);
    }
  }
  
  /** Finds the TernaryGAF having the given UUID.
   *
   * @param uuid the given uuid
   * @return the TernaryGAF having the given uuid
   * @throws TexaiException if the term is not found
   */
  @SuppressWarnings("unchecked")
  public TernaryGAF findTernaryGAFByUUID(final UUID uuid) {
    //Preconditions
    assert uuid != null : "uuid must not be null";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindTernaryGAFByUUID(kbShardFacade, uuid)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<TernaryGAF> callableActivity = (CallableActivity) activity;
      TernaryGAF ternaryGAF = null;
      try {
        ternaryGAF = callableActivity.getFuture().get();
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      }
      if (ternaryGAF != null) {
        return ternaryGAF;
      }
    }
    // not found
    throw new TexaiException("TernaryGAF not found for UUID " + uuid);
  }
  
  /** Call the findTernaryGAFByUUID method in a given kb shard facade. */
  @ThreadSafe
  class CallFindTernaryGAFByUUID implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the UUID */
    final UUID uuid;
    
    /** Create a new instance of CallFindTernaryGAFByUUID.
     *
     * @param kbShardFacade the kb shard facade
     * @param uuid the given uuid
     */
    public CallFindTernaryGAFByUUID(final KBPartitionFacadeLocal kbShardFacade, final UUID uuid) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert uuid != null : "uuid must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.uuid = uuid;
    }
    
    /** Call the findTernaryGAFByUUID method.
     *
     * @return the TernaryGAF having the given termId
     */
    public TernaryGAF call() {
      return kbShardFacade.findTernaryGAFByUUID(uuid);
    }
  }
  
  /** Finds the TernaryGAF having the given termId.
   *
   * @param termId the given term id
   * @return the TernaryGAF having the given termId
   * @throws TexaiException if the term is not found
   */
  public TernaryGAF findTernaryGAFByTermId(final int termId) {
    //Preconditions
    assert termId >= 0 : "termId must be positive";
    
    return findKBShardFacadeByTermId(termId).findTernaryGAFByTermId(termId);
  }
  
  /** Finds the TernaryGAF having the given constitutents or null if not found.
   *
   * @param predicate the given predicate
   * @param args the argument list
   * @param context the context
   * @return the TernaryGAF having the given constitutents or null if not found
   */
  @SuppressWarnings("unchecked")
  public TernaryGAF findTernaryGAFByConstituents(
          final AbstractReifiedTerm predicate,
          final List<AbstractTerm> args,
          final AbstractReifiedTerm context) {
    //Preconditions
    assert predicate != null : "predicate must not be null";
    assert args != null : "args must not be null";
    assert context != null : "context must not be null";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindTernaryGAFByConstituents(
              kbShardFacade,
              predicate,
              args,
              context)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<TernaryGAF> callableActivity = (CallableActivity) activity;
      TernaryGAF ternaryGAF = null;
      try {
        ternaryGAF = callableActivity.getFuture().get();
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      }
      if (ternaryGAF != null) {
        return ternaryGAF;
      }
    }
    // not found
    return null;
  }
  
  /** Call the findTernaryGAFByConstituents method in a given kb shard facade. */
  @ThreadSafe
  class CallFindTernaryGAFByConstituents implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the given predicate */
    final AbstractReifiedTerm predicate;
    /** the argument list */
    final List<AbstractTerm> args;
    /** the context */
    final AbstractReifiedTerm context;
    
    /** Create a new instance of CallFindTernaryGAFByConstituents.
     *
     * @param kbShardFacade the kb shard facade
     * @param predicate the given predicate
     * @param args the argument list
     * @param context the context
     */
    public CallFindTernaryGAFByConstituents(
            final KBPartitionFacadeLocal kbShardFacade,
            final AbstractReifiedTerm predicate,
            final List<AbstractTerm> args,
            final AbstractReifiedTerm context) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert predicate != null : "predicate must not be null";
      assert args != null : "args must not be null";
      assert context != null : "context must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.predicate = predicate;
      this.args = args;
      this.context = context;
    }
    
    /** Call the findTernaryGAFByConstituents method.
     *
     * @return the TernaryGAF having the given constitutents or null if not found
     */
    public TernaryGAF call() {
      return kbShardFacade.findTernaryGAFByConstituents(
              predicate,
              args,
              context);
    }
  }
  
  /** Finds the QuaternaryGAF having the given UUID.
   *
   * @param uuid the given uuid
   * @return the QuaternaryGAF having the given uuid
   * @throws TexaiException if the term is not found
   */
  @SuppressWarnings("unchecked")
  public QuaternaryGAF findQuaternaryGAFByUUID(final UUID uuid) {
    //Preconditions
    assert uuid != null : "uuid must not be null";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindQuaternaryGAFByUUID(kbShardFacade, uuid)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<QuaternaryGAF> callableActivity = (CallableActivity) activity;
      QuaternaryGAF quaternaryGAF = null;
      try {
        quaternaryGAF = callableActivity.getFuture().get();
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      }
      if (quaternaryGAF != null) {
        return quaternaryGAF;
      }
    }
    // not found
    throw new TexaiException("QuaternaryGAF not found for UUID " + uuid);
  }
  
  /** Call the findQuaternaryGAFByUUID method in a given kb shard facade. */
  @ThreadSafe
  class CallFindQuaternaryGAFByUUID implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the UUID */
    final UUID uuid;
    
    /** Create a new instance of CallFindQuaternaryGAFByUUID.
     *
     * @param kbShardFacade the kb shard facade
     * @param uuid the given uuid
     */
    public CallFindQuaternaryGAFByUUID(final KBPartitionFacadeLocal kbShardFacade, final UUID uuid) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert uuid != null : "uuid must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.uuid = uuid;
    }
    
    /** Call the findQuaternaryGAFByUUID method.
     *
     * @return the QuaternaryGAF having the given termId
     */
    public QuaternaryGAF call() {
      return kbShardFacade.findQuaternaryGAFByUUID(uuid);
    }
  }
  
  /** Finds the QuaternaryGAF having the given termId.
   *
   * @param termId the given term id
   * @return the QuaternaryGAF having the given termId
   * @throws TexaiException if the term is not found
   */
  public QuaternaryGAF findQuaternaryGAFByTermId(final int termId) {
    //Preconditions
    assert termId >= 0 : "termId must be positive";
    
    return findKBShardFacadeByTermId(termId).findQuaternaryGAFByTermId(termId);
  }
  
  /** Finds the QuaternaryGAF having the given constitutents or null if not found.
   *
   * @param predicate the given predicate
   * @param args the argument list
   * @param context the context
   * @return the QuaternaryGAF having the given constitutents or null if not found
   */
  @SuppressWarnings("unchecked")
  public QuaternaryGAF findQuaternaryGAFByConstituents(
          final AbstractReifiedTerm predicate,
          final List<AbstractTerm> args,
          final AbstractReifiedTerm context) {
    //Preconditions
    assert predicate != null : "predicate must not be null";
    assert args != null : "args must not be null";
    assert context != null : "context must not be null";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindQuaternaryGAFByConstituents(
              kbShardFacade,
              predicate,
              args,
              context)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<QuaternaryGAF> callableActivity = (CallableActivity) activity;
      QuaternaryGAF quaternaryGAF = null;
      try {
        quaternaryGAF = callableActivity.getFuture().get();
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      }
      if (quaternaryGAF != null) {
        return quaternaryGAF;
      }
    }
    // not found
    return null;
  }
  
  /** Call the findQuaternaryGAFByConstituents method in a given kb shard facade. */
  @ThreadSafe
  class CallFindQuaternaryGAFByConstituents implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the given predicate */
    final AbstractReifiedTerm predicate;
    /** the argument list */
    final List<AbstractTerm> args;
    /** the context */
    final AbstractReifiedTerm context;
    
    /** Create a new instance of CallFindQuaternaryGAFByConstituents.
     *
     * @param kbShardFacade the kb shard facade
     * @param predicate the given predicate
     * @param args the argument list
     * @param context the context
     */
    public CallFindQuaternaryGAFByConstituents(
            final KBPartitionFacadeLocal kbShardFacade,
            final AbstractReifiedTerm predicate,
            final List<AbstractTerm> args,
            final AbstractReifiedTerm context) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert predicate != null : "predicate must not be null";
      assert args != null : "args must not be null";
      assert context != null : "context must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.predicate = predicate;
      this.args = args;
      this.context = context;
    }
    
    /** Call the findQuaternaryGAFByConstituents method.
     *
     * @return the UnaryGAF having the given constitutents or null if not found
     */
    public QuaternaryGAF call() {
      return kbShardFacade.findQuaternaryGAFByConstituents(
              predicate,
              args,
              context);
    }
  }
  
  /** Finds the QuintaryGAF having the given UUID.
   *
   * @param uuid the given uuid
   * @return the QuintaryGAF having the given uuid
   * @throws TexaiException if the term is not found
   */
  @SuppressWarnings("unchecked")
  public QuintaryGAF findQuintaryGAFByUUID(final UUID uuid) {
    //Preconditions
    assert uuid != null : "uuid must not be null";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindQuintaryGAFByUUID(kbShardFacade, uuid)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<QuintaryGAF> callableActivity = (CallableActivity) activity;
      QuintaryGAF quintaryGAF = null;
      try {
        quintaryGAF = callableActivity.getFuture().get();
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      }
      if (quintaryGAF != null) {
        return quintaryGAF;
      }
    }
    // not found
    throw new TexaiException("QuintaryGAF not found for UUID " + uuid);
  }
  
  /** Call the findQuintaryGAFByUUID method in a given kb shard facade. */
  @ThreadSafe
  class CallFindQuintaryGAFByUUID implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the UUID */
    final UUID uuid;
    
    /** Create a new instance of CallFindQuintaryGAFByUUID.
     *
     * @param kbShardFacade the kb shard facade
     * @param uuid the given uuid
     */
    public CallFindQuintaryGAFByUUID(final KBPartitionFacadeLocal kbShardFacade, final UUID uuid) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert uuid != null : "uuid must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.uuid = uuid;
    }
    
    /** Call the findQuintaryGAFByUUID method.
     *
     * @return the QuintaryGAF having the given termId
     */
    public QuintaryGAF call() {
      return kbShardFacade.findQuintaryGAFByUUID(uuid);
    }
  }
  
  /** Finds the QuintaryGAF having the given termId.
   *
   * @param termId the given term id
   * @return the QuintaryGAF having the given termId
   * @throws TexaiException if the term is not found
   */
  public QuintaryGAF findQuintaryGAFByTermId(final int termId) {
    //Preconditions
    assert termId >= 0 : "termId must be positive";
    
    return findKBShardFacadeByTermId(termId).findQuintaryGAFByTermId(termId);
  }
  
  /** Finds the QuintaryGAF having the given constitutents or null if not found.
   *
   * @param predicate the given predicate
   * @param args the argument list
   * @param context the context
   * @return the QuintaryGAF having the given constitutents or null if not found
   */
  @SuppressWarnings("unchecked")
  public QuintaryGAF findQuintaryGAFByConstituents(
          final AbstractReifiedTerm predicate,
          final List<AbstractTerm> args,
          final AbstractReifiedTerm context) {
    //Preconditions
    assert predicate != null : "predicate must not be null";
    assert args != null : "args must not be null";
    assert context != null : "context must not be null";
    
    final List<Activity> activities = new ArrayList<Activity>();
    for (final KBPartitionFacadeLocal kbShardFacade : kbShardPeerFacadeDictionary.values()) {
      activities.add(new CallableActivity(getExecutor(), new CallFindQuintaryGAFByConstituents(
              kbShardFacade,
              predicate,
              args,
              context)));
    }
    // run parallel activities
    final JoinFirstCallableActivityResult joinFirstCallableActivityResult = new JoinFirstCallableActivityResult(activities);
    // wait for one of them to find the result, or for none of them to find the result
    joinFirstCallableActivityResult.join();
    for (final Activity activity : activities) {
      final CallableActivity<QuintaryGAF> callableActivity = (CallableActivity) activity;
      QuintaryGAF quintaryGAF = null;
      try {
        quintaryGAF = callableActivity.getFuture().get();
      } catch (final ExecutionException ex) {
        throw new TexaiException(ex);
      } catch (final InterruptedException ex) {
        throw new TexaiException(ex);
      }
      if (quintaryGAF != null) {
        return quintaryGAF;
      }
    }
    // not found
    return null;
  }
  
  /** Call the findQuintaryGAFByConstituents method in a given kb shard facade. */
  @ThreadSafe
  class CallFindQuintaryGAFByConstituents implements Callable {
    /** the kb shard facade */
    final KBPartitionFacadeLocal kbShardFacade;
    /** the given predicate */
    final AbstractReifiedTerm predicate;
    /** the argument list */
    final List<AbstractTerm> args;
    /** the context */
    final AbstractReifiedTerm context;
    
    /** Create a new instance of CallFindQuintaryGAFByConstituents.
     *
     * @param kbShardFacade the kb shard facade
     * @param predicate the given predicate
     * @param args the argument list
     * @param context the context
     */
    public CallFindQuintaryGAFByConstituents(
            final KBPartitionFacadeLocal kbShardFacade,
            final AbstractReifiedTerm predicate,
            final List<AbstractTerm> args,
            final AbstractReifiedTerm context) {
      //Preconditions
      assert kbShardFacade != null : "kbShardFacade must not be null";
      assert predicate != null : "predicate must not be null";
      assert args != null : "args must not be null";
      assert context != null : "context must not be null";
      
      this.kbShardFacade = kbShardFacade;
      this.predicate = predicate;
      this.args = args;
      this.context = context;
    }
    
    /** Call the findQuintaryGAFByConstituents method.
     *
     * @return the QuintaryGAF having the given constitutents or null if not found
     */
    public QuintaryGAF call() {
      return kbShardFacade.findQuintaryGAFByConstituents(
              predicate,
              args,
              context);
    }
  }
  
  /** Creates the Symbol having the given nameValue.
   *
   * @param nameValue the given name value
   * @return the Symbol having the given nameValue
   */
  public Symbol createSymbolByNameValue(final String nameValue) {
    return getKBShardForNewObjects().createSymbolByNameValue(nameValue);
  }
  
  
  /** Creates the PVariable having the given nameValue.
   *
   * @param nameValue the given name value
   * @return the PVariable having the given nameValue
   */
  public PVariable createPVariableByNameValue(final String nameValue) {
    return getKBShardForNewObjects().createPVariableByNameValue(nameValue);
  }
  
  /** Creates the PLong having the given longValue.
   *
   * @param longValue the given long value
   * @return the PLong having the given nameValue
   */
  public PLong createPLongByLongValue(final Long longValue) {
    return getKBShardForNewObjects().createPLongByLongValue(longValue);
  }
  
  /** Creates the PDouble having the given doubleValue.
   *
   * @param doubleValue the given double value
   * @return the PLong having the given doubleValue
   */
  public PDouble createPDoubleByDoubleValue(final Double doubleValue) {
    return getKBShardForNewObjects().createPDoubleByDoubleValue(doubleValue);
  }
  
  /** Creates the PString having the given stringValue.
   *
   * @param stringValue the given double value
   * @return the PLong having the given doubleValue
   */
  public PString createPStringByStringValue(final String stringValue) {
    return getKBShardForNewObjects().createPStringByStringValue(stringValue);
  }
  
  /** Creates the PDate having the given dateValue.
   *
   * @param dateValue the given date value
   * @return the PDate having the given dateValue
   */
  public PDate createPDateByDateValue(final Date dateValue) {
    return getKBShardForNewObjects().createPDateByDateValue(dateValue);
  }
  
  /** Creates the bootstrap AtomicTerm having the given termName.
   *
   * @param uuid the UUID
   * @param termName the term name
   * @param prettyName the pretty name
   * @return the AtomicTerm having the given termName
   */
  public AtomicTerm createBootstrapAtomicTerm(
          final UUID uuid,
          final String termName,
          final String prettyName) {
    return getKBShardForNewObjects().createBootstrapAtomicTerm(
            uuid,
            termName,
            prettyName);
  }
  
  /** Creates the AtomicTerm having the given termName.
   *
   * @param termName the term name
   * @param prettyName the pretty name
   * @param creator the creator
   * @param creationPurpose the creation purpose
   * @return the AtomicTerm having the given termName
   */
  public AtomicTerm createAtomicTermByTermName(
          final String termName,
          final String prettyName,
          final AbstractReifiedTerm creator,
          final AbstractReifiedTerm creationPurpose) {
    return getKBShardForNewObjects().createAtomicTermByTermName(
            termName,
            prettyName,
            creator,
            creationPurpose);
  }
  
  /** Creates the NonAtomicTerm having the given termName.
   *
   * @param termName the term name
   * @param prettyName the pretty name
   * @param formula the formula
   * @param creator the creator
   * @param creationPurpose the creation purpose
   * @return the NonAtomicTerm having the given termName or a new one having
   * the given constituents
   */
  public NonAtomicTerm createNonAtomicTermByTermName(
          final String termName,
          final String prettyName,
          final Formula formula,
          final AbstractReifiedTerm creator,
          final AbstractReifiedTerm creationPurpose) {
    return getKBShardForNewObjects().createNonAtomicTermByTermName(
            termName,
            prettyName,
            formula,
            creator,
            creationPurpose);
  }
  
  /** Creates the Formula having the given term list.
   *
   * @param formulaTerms the list of terms that constitute this formula
   * @param creator the creator
   * @param creationPurpose the creation purpose
   * @return the persisted Formula having the given term list
   */
  public Formula createFormulaByTermList(
          final List<AbstractTerm> formulaTerms,
          final AbstractReifiedTerm creator,
          final AbstractReifiedTerm creationPurpose) {
    return getKBShardForNewObjects().createFormulaByTermList(
            formulaTerms,
            creator,
            creationPurpose);
  }
  
  /** Creates (with the term list omitted) the Formula having the given formulaString.
   *
   * @param termId the given term id
   * @param creator the creator
   * @param creationPurpose the creation purpose
   * @return the persisted Formula having the given formulaString or a new Formula having the
   * given term list
   */
  public Formula createFormulaByFormulaString(
          final String formulaString,
          final AbstractReifiedTerm creator,
          final AbstractReifiedTerm creationPurpose) {
    return getKBShardForNewObjects().createFormulaByFormulaString(
            formulaString,
            creator,
            creationPurpose);
  }
  
  /** Creates the Rule having the given formula.
   *
   * @param formula the given formula
   * @param context the context
   * @param strength the strength
   * @param creator the creator
   * @param creationPurpose the creation purpose
   * @return the Rule having the given formulaString
   */
  public Rule createRuleByFormula(
          final Formula formula,
          final AbstractReifiedTerm context,
          final Double strength,
          final AbstractReifiedTerm creator,
          final AbstractReifiedTerm creationPurpose) {
    return getKBShardForNewObjects().createRuleByFormula(
            formula,
            context,
            strength,
            creator,
            creationPurpose);
  }
  
  /** Creates the UnaryGAF having the given constitutents.
   *
   * @param predicate the given predicate
   * @param args the argument list
   * @param context the context
   * @param strength the assertion strength
   * @param generatedPhrase the generated phrase for this ground atomic formula
   * @param creator the creator
   * @param creationPurpose the creation purpose
   * @return the UnaryGAF having the given constitutents
   */
  public UnaryGAF createUnaryGAFByConstituents(
          final AbstractReifiedTerm predicate,
          final List<AbstractTerm> args,
          final AbstractReifiedTerm context,
          final Double strength,
          final String generatedPhrase,
          final AbstractReifiedTerm creator,
          final AbstractReifiedTerm creationPurpose) {
    return getKBShardForNewObjects().createUnaryGAFByConstituents(
            predicate,
            args,
            context,
            strength,
            generatedPhrase,
            creator,
            creationPurpose);
  }
  
  /**
   * Creates the BinaryGAF having the given constitutents.
   *
   * @param predicate the given predicate
   * @param args the argument list
   * @param context the context
   * @param strength the assertion strength
   * @param generatedPhrase the generated phrase for this ground atomic formula
   * @param validateWellFormedFormula the indicator to validate the gaf as a well-formed formula
   * @param creator the creator
   * @param creationPurpose the creation purpose
   * @return the BinaryGAF having the given constitutents
   */
  public BinaryGAF createBinaryGAFByConstituents(
          final AbstractReifiedTerm predicate,
          final List<AbstractTerm> args,
          final AbstractReifiedTerm context,
          final Double strength,
          final String generatedPhrase,
          boolean validateWellFormedFormula,
          final AbstractReifiedTerm creator,
          final AbstractReifiedTerm creationPurpose) {
    //Preconditions
    assert predicate != null : Constants.PREDICATE_ERR;
    assert args != null : Constants.ARGS_ERR;
    assert args.size() ==  Constants.BINARY_ARGS_SIZE : "binary gaf must have two arguments";
    assert args.get(0) != null : "binary gaf arg1 must not be null";
    assert args.get(1) != null : "binary gaf arg2 must not be null";
    assert context != null : Constants.CONTEXT_ERR;
    assert strength != null : "strength must not be null";
    
    if (validateWellFormedFormula) {
      final String reasonWhyFormulaNotWellFormed = getReasonWhyFormulaIsNotWellFormed(predicate, args, context);
      if (!reasonWhyFormulaNotWellFormed.isEmpty()) {
        throw new TexaiException(reasonWhyFormulaNotWellFormed);
      }
    }
    return getKBShardForNewObjects().createBinaryGAFByConstituents(
            predicate,
            args,
            context,
            strength,
            generatedPhrase,
            validateWellFormedFormula,
            creator,
            creationPurpose);
  }
  
  /** Creates the TernaryGAF having the given constitutents.
   *
   * @param predicate the given predicate
   * @param args the argument list
   * @param context the context
   * @param strength the assertion strength
   * @param generatedPhrase the generated phrase for this ground atomic formula
   * @param creator the creator
   * @param creationPurpose the creation purpose
   * @return the TernaryGAF having the given constitutents
   */
  public TernaryGAF createTernaryGAFByConstituents(
          final AbstractReifiedTerm predicate,
          final List<AbstractTerm> args,
          final AbstractReifiedTerm context,
          final Double strength,
          final String generatedPhrase,
          final AbstractReifiedTerm creator,
          final AbstractReifiedTerm creationPurpose) {
    return getKBShardForNewObjects().createTernaryGAFByConstituents(
            predicate,
            args,
            context,
            strength,
            generatedPhrase,
            creator,
            creationPurpose);
  }
  
  /** Creates the QuaternaryGAF having the given constitutents.
   *
   * @param predicate the given predicate
   * @param args the argument list
   * @param context the context
   * @param strength the assertion strength
   * @param generatedPhrase the generated phrase for this ground atomic formula
   * @param creator the creator
   * @param creationPurpose the creation purpose
   * @return the QuaternaryGAF having the given constitutents
   */
  public QuaternaryGAF createQuaternaryGAFByConstituents(
          final AbstractReifiedTerm predicate,
          final List<AbstractTerm> args,
          final AbstractReifiedTerm context,
          final Double strength,
          final String generatedPhrase,
          final AbstractReifiedTerm creator,
          final AbstractReifiedTerm creationPurpose) {
    return getKBShardForNewObjects().createQuaternaryGAFByConstituents(
            predicate,
            args,
            context,
            strength,
            generatedPhrase,
            creator,
            creationPurpose);
  }
  
  /** Creates the QuintaryGAF having the given constitutents.
   *
   * @param predicate the given predicate
   * @param args the argument list
   * @param context the context
   * @param strength the assertion strength
   * @param generatedPhrase the generated phrase for this ground atomic formula
   * @param creator the creator
   * @param creationPurpose the creation purpose
   * @return the QuintaryGAF having the given constitutents
   */
  public QuintaryGAF createQuintaryGAFByConstituents(
          final AbstractReifiedTerm predicate,
          final List<AbstractTerm> args,
          final AbstractReifiedTerm context,
          final Double strength,
          final String generatedPhrase,
          final AbstractReifiedTerm creator,
          final AbstractReifiedTerm creationPurpose) {
    return getKBShardForNewObjects().createQuintaryGAFByConstituents(
            predicate,
            args,
            context,
            strength,
            generatedPhrase,
            creator,
            creationPurpose);
  }
  
  /** Creates the defined atomic term.
   *
   * @param termName the term name
   * @param prettyName the pretty name
   * @param commentString the comment string
   * @param isaTerms the list of isa (type) terms
   * @param creator the creator
   * @param creationPurpose the creation purpose
   * @return the specified defined term
   */
  public AtomicTerm createDefinedTerm(
          final String termName,
          final String prettyName,
          final String commentString,
          final List<AbstractReifiedTerm> isaTerms,
          final AbstractReifiedTerm creator,
          final AbstractReifiedTerm creationPurpose) {
    return getKBShardForNewObjects().createDefinedTerm(
            termName,
            prettyName,
            commentString,
            isaTerms,
            creator,
            creationPurpose);
  }
  
  /** Creates the specified binary predicate term with default list of isa (type) terms [BinaryPredicate, PredicateFocalInArg1],
   * and list of genlPreds (super property) terms [conceptuallyRelated].
   *
   * @param termName the predicate name
   * @param prettyName the pretty name
   * @param commentString the comment string
   * @param creator the creator
   * @param argConstraintTerms the list of argument constraint terms
   * @param creationPurpose the creation purpose
   * @return the specified binary predicate term
   */
  public AtomicTerm createBinaryPredicateTerm(
          final String termName,
          final String prettyName,
          final String commentString,
          final List<AbstractReifiedTerm> argConstraintTerms,
          final AbstractReifiedTerm creator,
          final AbstractReifiedTerm creationPurpose) {
    return getKBShardForNewObjects().createBinaryPredicateTerm(
            termName,
            prettyName,
            commentString,
            argConstraintTerms,
            creator,
            creationPurpose);
  }
  
  /** Creates the specified binary predicate term.
   *
   *
   * @param termName the predicate name
   * @param prettyName the pretty name
   * @param commentString the comment string
   * @param isaTerms the list of isa (type) terms, defaults to [BinaryPredicate, PredicateFocalInArg1]
   * @param genlPredTerms the list of genlPreds (super property) terms, defaults to [conceptuallyRelated]
   * @param argConstraintTerms the list of argument constraint terms
   * @param creator the creator
   * @param creationPurpose the creation purpose
   * @return the specified binary predicate term
   */
  public AtomicTerm createBinaryPredicateTerm(
          final String termName,
          final String prettyName,
          final String commentString,
          final List<AbstractReifiedTerm> isaTerms,
          final List<AbstractReifiedTerm> genlPredTerms,
          final List<AbstractReifiedTerm> argConstraintTerms,
          final AbstractReifiedTerm creator,
          final AbstractReifiedTerm creationPurpose) {
    return getKBShardForNewObjects().createBinaryPredicateTerm(
            termName,
            prettyName,
            commentString,
            isaTerms,
            genlPredTerms,
            argConstraintTerms,
            creator,
            creationPurpose);
  }
  
  /**
   * Creates the specified collection term.
   *
   * @param termName the term name
   * @param prettyName the pretty name
   * @param commentString the comment string
   * @param isaTerms the list of isa (type) terms
   * @param genlsTerms the list of genls (superclass) terms
   * @param creator the creator
   * @param creationPurpose the creation purpose
   * @return the specified collection term
   */
  public AtomicTerm createCollectionTerm(
          final String termName,
          final String prettyName,
          final String commentString,
          final List<AbstractReifiedTerm> isaTerms,
          final List<AbstractReifiedTerm> genlsTerms,
          final AbstractReifiedTerm creator,
          final AbstractReifiedTerm creationPurpose) {
    return getKBShardForNewObjects().createCollectionTerm(
            termName,
            prettyName,
            commentString,
            isaTerms,
            genlsTerms,
            creator,
            creationPurpose);
  }
  
  /**
   * Creates the specified context term.
   *
   * @param termName the term name
   * @param prettyName the pretty name
   * @param commentString the comment string
   * @param isaTerms the list of isa (type) terms which defaults to [Microtheory] when empty
   * @param genlMtTerms the list of genlMt (super context) terms which defaults to [BaseKB] when empty
   * @param creator the creator
   * @param creationPurpose the creation purpose
   * @return the specified collection term
   */
  public AtomicTerm createContextTerm(
          final String termName,
          final String prettyName,
          final String commentString,
          final List<AbstractReifiedTerm> isaTerms,
          final List<AbstractReifiedTerm> genlMtTerms,
          final AbstractReifiedTerm creator,
          final AbstractReifiedTerm creationPurpose) {
    return getKBShardForNewObjects().createContextTerm(
            termName,
            prettyName,
            commentString,
            isaTerms,
            genlMtTerms,
            creator,
            creationPurpose);
  }
  
  /** Returns a description of why the given formula is not well formed, or an empty string if the formula is well formed.
   *
   * @param predicate the predicate
   * @param args the argument list
   * @param context the context
   */
  public  String getReasonWhyFormulaIsNotWellFormed(
          final AbstractReifiedTerm predicate,
          final List<AbstractTerm> args,
          final AbstractReifiedTerm context) {
    //Preconditions
    assert predicate != null : Constants.PREDICATE_ERR;
    assert args != null : Constants.ARGS_ERR;
    assert context != null : Constants.CONTEXT_ERR;
    
    final int argsSize = args.size();
    int predicateArity;
    try {
      predicateArity = predicateArity(predicate);
    } catch (final TexaiException ex) {
      return ex.getMessage();
    }
    if (predicateArity != argsSize) {
      return "wrong number of args for predicate, arity: " + predicateArity + ", args: " + args;
    }
    final List<AbstractReifiedTerm> argConstraints = predicateArgConstraints(predicate);
    final Set<AbstractReifiedTerm> contextTypes = gatherAllTypesForTerm(
            context,
            findAtomicTermByTermName(Constants.TERM_NAME_BASE_KB));
    if (!contextTypes.contains(findAtomicTermByTermName(Constants.TERM_NAME_MICROTHEORY))) {
      return context + " is not a context (Microtheory)";
    }
    final Iterator<AbstractTerm> argsIter = args.iterator();
    int argumentPosition = 0;
    for (final AbstractReifiedTerm argConstraint : argConstraints) {
      final AbstractTerm arg = argsIter.next();
      argumentPosition++;
      Set<AbstractReifiedTerm> allTypes = null;
      if (arg instanceof AbstractReifiedTerm) {
        allTypes = gatherAllTypesForTerm((AbstractReifiedTerm) arg, context);
        if(allTypes.isEmpty()) {
          allTypes.add(findAtomicTermByTermName(Constants.TERM_NAME_THING));
        }
      } else if (arg instanceof PString) {
        allTypes = new HashSet<AbstractReifiedTerm>();
        allTypes.add(findAtomicTermByTermName(Constants.TERM_NAME_CHARACTER_STRING));
        allTypes.add(findAtomicTermByTermName(Constants.TERM_NAME_CONTROL_CHARACTER_FREE_STRING));
      } else if (arg instanceof PLong) {
        allTypes = new HashSet<AbstractReifiedTerm>();
        allTypes.add(findAtomicTermByTermName(Constants.TERM_NAME_INTEGER));
        if (((PLong) arg).getLongValue().longValue() >= 0) {
          allTypes.add(findAtomicTermByTermName(Constants.TERM_NAME_NON_NEGATIVE_INTEGER));
          if (((PLong) arg).getLongValue().longValue() > 0) {
            allTypes.add(findAtomicTermByTermName(Constants.TERM_NAME_POSITIVE_INTEGER));
          }
        }
      } else {
        throw new TexaiException("unhandled types for arg " + arg + " at argument position " + argumentPosition);
      }
      if (!allTypes.contains(argConstraint) && !predicate.toString().equals("isa")) {
        return "argument " + arg + " having types " + allTypes + "\n  is not required type " + argConstraint
                + "\n  at argument position " + argumentPosition + "\n  of predicate " + predicate
                + "\n  having args " + args;
      }
    }
    return Constants.EMPTY_STRING;
  }
  
  // TermDeleterFacadeLocal
  
  /** Deletes the given AtomicTerm.
   *
   * @param atomicTerm the given atomic term
   * @return whether the atomic term was found and deleted
   */
  public boolean deleteAtomicTerm(final AtomicTerm atomicTerm) {
    //Preconditions
    assert atomicTerm != null : "atomicTerm must not be null";
    
    return this.findKBShardFacadeByTermId(atomicTerm.getTermId()).deleteAtomicTerm(atomicTerm);
  }
  
  /**
   * Deletes the given domain instance term and the binary GAFs which persist its fields.
   *
   * @param domainInstanceTerm the domain instance term to delete
   */
  public boolean deleteDomainInstanceTerm(final AtomicTerm domainInstanceTerm) {
    //Preconditions
    assert domainInstanceTerm != null : "domainInstanceTerm must not be null";
    
    getLogger().debug("deleting domain instance term: " + domainInstanceTerm);
    for (final BinaryGAF binaryGAF : gatherBinaryGAFsByArgTerm(domainInstanceTerm)) {
      deleteBinaryGAF(binaryGAF);
    }
    return deleteAtomicTerm(domainInstanceTerm);
  }
  
  /** Deletes the given unary ground atomic formula.
   *
   * @param unaryGAF the given unary ground atomic formula
   * @return whether the unary ground atomic formula was found and deleted
   */
  public boolean deleteUnaryGAF(final UnaryGAF unaryGAF) {
    //Preconditions
    assert unaryGAF != null : "unaryGAF must not be null";
    
    return findKBShardFacadeByTermId(unaryGAF.getTermId()).deleteUnaryGAF(unaryGAF);
  }
  
  /** Deletes the given binary ground atomic formula.
   *
   * @param binaryGAF the given binary ground atomic formula
   * @return whether the binary ground atomic formula was found and deleted
   */
  public boolean deleteBinaryGAF(final BinaryGAF binaryGAF) {
    //Preconditions
    assert binaryGAF != null : "binaryGAF must not be null";
    
    return findKBShardFacadeByTermId(binaryGAF.getTermId()).deleteBinaryGAF(binaryGAF);
  }
  
  /** Deletes the given ternary ground atomic formula.
   *
   * @param ternaryGAF the given ternary ground atomic formula
   * @return whether the ternary ground atomic formula was found and deleted
   */
  public boolean deleteTernaryGAF(final TernaryGAF ternaryGAF) {
    //Preconditions
    assert ternaryGAF != null : "ternaryGAF must not be null";
    
    return findKBShardFacadeByTermId(ternaryGAF.getTermId()).deleteTernaryGAF(ternaryGAF);
  }
  
  /** Deletes the given quaternary ground atomic formula.
   *
   * @param quaternaryGAF the given quaternary ground atomic formula
   * @return whether the quaternary ground atomic formula was found and deleted
   */
  public boolean deleteQuaternaryGAF(final QuaternaryGAF quaternaryGAF) {
    //Preconditions
    assert quaternaryGAF != null : "quaternaryGAF must not be null";
    
    return findKBShardFacadeByTermId(quaternaryGAF.getTermId()).deleteQuaternaryGAF(quaternaryGAF);
  }
  
  /** Deletes the given quintary ground atomic formula.
   *
   * @param quintaryGAF the given quintary ground atomic formula
   * @return whether the  quintary ground atomic formula was found and deleted
   */
  public boolean deleteQuintaryGAF(final QuintaryGAF quintaryGAF) {
    //Preconditions
    assert quintaryGAF != null : "quintaryGAF must not be null";
    
    return findKBShardFacadeByTermId(quintaryGAF.getTermId()).deleteQuintaryGAF(quintaryGAF);
  }
  
  /** Delete matching binary ground atomic formulas from all contexts relevant to the given context.
   *
   * @param predicate the predicate that gafs must match
   * @param args the arguments that gafs must match
   * @param context the context the given context
   */
  public boolean deleteBinaryGAFsFromRelevantContexts(
          final AtomicTerm predicate,
          final List<AbstractTerm> args,
          final AbstractReifiedTerm context) {
    //Preconditions
    assert predicate != null : "predicate must not be null";
    assert args != null : "args must not be null";
    assert args.size() == Constants.BINARY_ARGS_SIZE : "binary GAF must have two arguments " + args.toString();
    assert context != null : "context must not be null";
    
    boolean isDeleted = false;
    for (final AbstractReifiedTerm relevantContext : gatherContextsRelevantFrom(context)) {
      final BinaryGAF binaryGAF = findBinaryGAFByConstituents(predicate, args, relevantContext);
      if (binaryGAF != null) {
        if (deleteBinaryGAF(binaryGAF)) {
          isDeleted = true;
        }
      }
    }
    return isDeleted;
  }
  
  // TermDefinitionAccessorLocal
  
  /** Gathers the types for which the given term is a direct instance from the given context.
   *
   * @param term the given term
   * @param context the most specific context of those from which types are gathered
   * @return the types for which the given term is a direct instance from the given context
   */
  public Set<AbstractReifiedTerm> gatherTypesForTerm(final AbstractReifiedTerm term, final AbstractReifiedTerm context) {
    //Preconditions
    assert term != null : "term must not be null";
    assert context != null : "context must not be null";
    
    final Set<AbstractReifiedTerm> types = new HashSet<AbstractReifiedTerm>();
    for (final AbstractTerm type : gatherArg2TermsFromBinaryGAFs(
            findAtomicTermByTermName(Constants.TERM_NAME_ISA),
            term,
            context)) {
      types.add((AbstractReifiedTerm) type);
    }
    
    getLogger().debug("gatherTypesForTerm("  + term + "): " + types);
    return types;
  }
  
  /** Gathers the types for which the given term is a direct instance within every context.
   *
   * @param term the given term
   * @return the types for which the given term is a direct instance within every context
   */
  public Set<AbstractReifiedTerm> gatherTypesForTerm(final AbstractReifiedTerm term) {
    //Preconditions
    assert term != null : "term must not be null";
    
    final Set<AbstractReifiedTerm> types = new HashSet<AbstractReifiedTerm>();
    for (final AbstractTerm type : gatherArg2TermsFromBinaryGAFs(
            findAtomicTermByTermName(Constants.TERM_NAME_ISA),
            term)) {
      types.add((AbstractReifiedTerm) type);
    }
    
    getLogger().debug("gatherTypesForTerm("  + term + "): " + types);
    return types;
  }
  
  /** Gathers the types for which the given term is a direct or indirect instance from the given context.
   *
   * @param term the given term
   * @param context the most specific context of those from which types are gathered
   * @return the types for which the given term is an instance from the given context
   */
  public Set<AbstractReifiedTerm> gatherAllTypesForTerm(final AbstractReifiedTerm term, final AbstractReifiedTerm context) {
    //Preconditions
    assert term != null : "term must not be null";
    assert context != null : "context must not be null";
    
    final Set<AbstractReifiedTerm> types = new HashSet<AbstractReifiedTerm>();
    for (final AbstractTerm type : gatherArg2TermsFromBinaryGAFs(
            findAtomicTermByTermName(Constants.TERM_NAME_ISA),
            term,
            context)) {
      types.add((AbstractReifiedTerm) type);
    }
    final Set<AbstractReifiedTerm> allTypes = new HashSet<AbstractReifiedTerm>();
    for (final AbstractReifiedTerm type : types) {
      if (!allTypes.contains(type)) {
        allTypes.add(type);
        allTypes.addAll(gatherTransitiveClosureFrom(
                findAtomicTermByTermName(Constants.TERM_NAME_GENLS),
                type,
                context));
      }
    }
    getLogger().debug("gatherAllTypesForTerm("  + term + "): " + allTypes);
    return allTypes;
  }
  
  /** Gathers the instances of the given collection term from the given context.
   *
   * @param term the given term
   * @param context the most specific context of those from which instances are gathered
   * @return the instances of the given collection term from the given context
   */
  public  Set<AbstractReifiedTerm> gatherInstancesForTerm(final AbstractReifiedTerm term, final AbstractReifiedTerm context) {
    //Preconditions
    assert term != null : "term must not be null";
    assert context != null : "context must not be null";
    
    final Set<AbstractReifiedTerm> instances = new HashSet<AbstractReifiedTerm>();
    for (final AbstractTerm instance : gatherArg1TermsFromBinaryGAFs(
            findAtomicTermByTermName(Constants.TERM_NAME_ISA),
            term,
            context)) {
      instances.add((AbstractReifiedTerm) instance);
    }
    
    getLogger().debug("gatherInstancesForTerm("  + term + "): " + instances);
    return instances;
  }
  
  /** Returns the arity of the given predicate.
   *
   * @param predicate the given predicate
   * @return the arity of the given predicate
   */
  public int predicateArity(final AbstractReifiedTerm predicate) {
    //Preconditions
    assert predicate != null : "predicate must not be null";
    
    final PLong arity = (PLong) getArg2TermFromBinaryGAF(
            findAtomicTermByTermName(Constants.TERM_NAME_ARITY),
            predicate);
    if (arity == null) {
      throw new TexaiException("no arity asserted for predicate " + predicate);
    }
    return arity.getLongValue().intValue();
  }
  
  /** Returns the list argument constraints of the given predicate, one for each
   * corresponding argument position.
   *
   * @param predicate the given predicate
   * @return the list argument constraints of the given predicate, one for each
   * corresponding argument position
   */
  public List<AbstractReifiedTerm> predicateArgConstraints(final AbstractReifiedTerm predicate) {
    //Preconditions
    assert predicate != null : "predicate must not be null";
    
    final int arity = predicateArity(predicate);
    final List<AbstractReifiedTerm> argConstraints = new ArrayList<AbstractReifiedTerm>(arity);
    AbstractReifiedTerm argumentConstraint = (AbstractReifiedTerm) getArg2TermFromBinaryGAF(
            findAtomicTermByTermName(Constants.TERM_NAME_ARG1_ISA),
            predicate);
    argConstraints.add(argumentConstraint);
    if (arity == Constants.UNARY_ARGS_SIZE) {
      return argConstraints;
    }
    argumentConstraint = (AbstractReifiedTerm) getArg2TermFromBinaryGAF(
            findAtomicTermByTermName(Constants.TERM_NAME_ARG2_ISA),
            predicate);
    argConstraints.add(argumentConstraint);
    if (arity == Constants.BINARY_ARGS_SIZE) {
      return argConstraints;
    }
    argumentConstraint = (AbstractReifiedTerm) getArg2TermFromBinaryGAF(
            findAtomicTermByTermName(Constants.TERM_NAME_ARG3_ISA),
            predicate);
    argConstraints.add(argumentConstraint);
    if (arity == Constants.TERNARY_ARGS_SIZE) {
      return argConstraints;
    }
    argumentConstraint = (AbstractReifiedTerm) getArg2TermFromBinaryGAF(
            findAtomicTermByTermName(Constants.TERM_NAME_ARG4_ISA),
            predicate);
    argConstraints.add(argumentConstraint);
    if (arity == Constants.QUATERNARY_ARGS_SIZE) {
      return argConstraints;
    }
    argumentConstraint = (AbstractReifiedTerm) getArg2TermFromBinaryGAF(
            findAtomicTermByTermName(Constants.TERM_NAME_ARG5_ISA),
            predicate);
    argConstraints.add(argumentConstraint);
    return argConstraints;
  }
  
  // AssociationFinderLocal
  
  /** Gets the sole term from the arg1 position of the matching binary ground atomic formula or null if not
   * found.
   *
   * @param predicate the predicate of the matching binary gaf
   * @param arg2 the second argument term of the matching binary gaf
   * @param context the most specific context of those from which the matching gaf is gathered
   * @return the sole term from the arg1 position of the matching binary ground atomic formula or null if not
   * found
   */
  public AbstractTerm getArg1TermFromBinaryGAF(
          final AtomicTerm predicate,
          final AbstractTerm arg2,
          final AbstractReifiedTerm context) {
    //Preconditions
    assert predicate != null : "predicate must not be null";
    assert arg2 != null : "arg2 must not be null";
    assert context != null : "context must not be null";             // NOPMD
    
    final Set<AbstractTerm> arg1s = gatherArg1TermsFromBinaryGAFs(predicate, arg2, context);
    if (arg1s.isEmpty()) {
      return null;
    } else if (arg1s.size() > 1) {
      throw new TexaiException("found more than one arg1 term: " + arg1s
              + " for query, predicate: " + predicate + ", arg2: " + arg2 + ", context: " + context);
    }
    return (AbstractTerm) arg1s.toArray()[0];
  }
  
  /** Gathers the terms from the arg1 position of matching binary ground atomic formulas.
   *
   * @param predicate the predicate of matching binary gafs
   * @param arg2 the second argument term of matching binary gafs
   * @param context the most specific context of those from which matching gafs are gathered
   * @return the terms from the arg1 position of match binary ground atomic formulas
   */
  public Set<AbstractTerm> gatherArg1TermsFromBinaryGAFs(
          final AtomicTerm predicate,
          final AbstractTerm arg2,
          final AbstractReifiedTerm context) {
    //Preconditions
    assert predicate != null : "predicate must not be null";
    assert arg2 != null : "arg2 must not be null";
    assert context != null : "context must not be null";             // NOPMD
    
    final Set<AbstractTerm> arg1s = new HashSet<AbstractTerm>();
    final Set<List<AbstractTerm>> pairs = gatherArg1TermsAndContextsFromBinaryGAFs(predicate, arg2);
    if (!pairs.isEmpty()) {
      final Set<AbstractReifiedTerm> relevantContexts = gatherContextsRelevantFrom(context);
      for (final List<AbstractTerm> pair : pairs) {
        final AbstractTerm gafContext = pair.get(1);
        if (relevantContexts.contains(gafContext)) {
          arg1s.add(pair.get(0));
        }
      }
    }
    getLogger().debug("gatherArg1TermsFromBinaryGAFs(" + predicate + ", " + arg2 + ", " + context + "): " + arg1s);   // NOPMD
    return arg1s;
  }
  
  /** Gets the sole term from the arg2 position of the matching binary ground atomic formula or null if not
   * found.
   *
   * @param predicate the predicate of the matching binary gaf
   * @param arg1 the first argument term of the matching binary gaf
   * @return the sole term from the arg2 position of the matching binary ground atomic formula or null if not
   * found
   */
  public AbstractTerm getArg2TermFromBinaryGAF(
          final AtomicTerm predicate,
          final AbstractTerm arg1) {
    //Preconditions
    assert predicate != null : "predicate must not be null";
    assert arg1 != null : "arg1 must not be null";
    
    final Set<AbstractTerm> arg2s = gatherArg2TermsFromBinaryGAFs(predicate, arg1);
    if (arg2s.isEmpty()) {
      return null;
    } else if (arg2s.size() > 1) {
      throw new TexaiException("found more than one arg2 term: " + arg2s
              + " for query, predicate: " + predicate + ", arg1: " + arg1);
    }
    return (AbstractTerm) arg2s.toArray()[0];
  }
  
  /** Gets the sole term from the arg2 position of the matching binary ground atomic formula or null if not
   * found.
   *
   * @param predicate the predicate of the matching binary gaf
   * @param arg1 the first argument term of the matching binary gaf
   * @param context the most specific context of those from which the matching gaf is gathered
   * @return the sole term from the arg2 position of the matching binary ground atomic formula or null if not
   * found
   */
  public AbstractTerm getArg2TermFromBinaryGAF(
          final AtomicTerm predicate,
          final AbstractTerm arg1,
          final AbstractReifiedTerm context) {
    //Preconditions
    assert predicate != null : "predicate must not be null";
    assert arg1 != null : "arg1 must not be null";
    assert context != null : "context must not be null";             // NOPMD
    
    final Set<AbstractTerm> arg2s = gatherArg2TermsFromBinaryGAFs(predicate, arg1, context);
    if (arg2s.isEmpty()) {
      return null;
    } else if (arg2s.size() > 1) {
      throw new TexaiException("found more than one arg2 term: " + arg2s
              + " for query, predicate: " + predicate + ", arg1: " + arg1 + ", context: " + context);
    }
    return (AbstractTerm) arg2s.toArray()[0];
  }
  
  /** Gathers the terms from the arg2 position of matching binary ground atomic formulas.
   *
   * @param predicate the predicate of matching binary gafs
   * @param arg1 the first argument term of matching binary gafs
   * @param context the most specific context of those from which matching gafs are gathered
   * @return the terms from the arg2 position of match binary ground atomic formulas
   */
  public Set<AbstractTerm> gatherArg2TermsFromBinaryGAFs(
          final AtomicTerm predicate,
          final AbstractTerm arg1,
          final AbstractReifiedTerm context) {
    //Preconditions