private static String makeRequestString(final Object command) {
      if (command instanceof CycList) {
        return ((CycList) command).cyclify();
      } else {
        return command.toString();
      }

    }
  }

  /**
   * Converses with Cyc to perform an API command whose result is returned as a boolean.
   *
   * @param command the command string or CycList
   *
   * @return the result of processing the API command
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean converseBoolean(Object command)
          throws UnknownHostException, IOException, CycApiException {
    Object[] response = {null, null};
    response = converse(command);

    if (response[0].equals(Boolean.TRUE)) {
      if (response[1].toString().equals("T")) {
        return true;
      } else {
        return false;
      }
    } else {
      throw new ConverseException(command, response);
    }
  }

  /**
   * Converses with Cyc to perform an API command whose result is returned as an int.
   *
   * @param command the command string or CycList
   *
   * @return the result of processing the API command
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public int converseInt(Object command)
          throws UnknownHostException, IOException, CycApiException {
    Object[] response = {null, null};
    response = converse(command);

    if (response[0].equals(Boolean.TRUE)) {
      return Integer.valueOf(response[1].toString());
    } else {
      throw new ConverseException(command, response);
    }
  }

  /**
   * Converses with Cyc to perform an API command whose result is void.
   *
   * @param command the command string or CycList
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void converseVoid(final Object command)
          throws UnknownHostException, IOException, CycApiException {
    Object[] response = {null, null};
    response = converse(command);

    if (response[0].equals(Boolean.FALSE)) {
      throw new ConverseException(command, response);
    }
  }

  /** Try to enhance <code>urlString</code> to log <code>cyclist</code> in and redirect to
   * the page it would otherwise go to directly.
   */
  public String maybeAddLoginRedirect(final String urlString, final CycFort cyclist,
          final CycDenotationalTerm applicationTerm) {
    // sample urlString: cg?CB-CF&236134
    final int questionMarkPos = urlString.indexOf('?');
    if ((cyclist instanceof CycConstant) && (questionMarkPos >= 0)) {
      final String cgiProgram = urlString.substring(0, questionMarkPos);
      final String originalQueryString = urlString.substring(questionMarkPos + 1);
      final StringBuilder stringBuilder = new StringBuilder(cgiProgram);
      stringBuilder.append("?cb-login-handler");
      stringBuilder.append("&new_login_name=").append(((CycConstant) cyclist).getName());
      maybeAddPassword(cyclist, applicationTerm, stringBuilder);
      stringBuilder.append("&redirect-handler=").append(originalQueryString);
      return stringBuilder.toString();
    } else {
      return urlString;
    }
  }

  private String doubleURLEncode(final String password) throws UnsupportedEncodingException {
    return urlEncode(urlEncode(password));
  }

  private String urlEncode(final String password) throws UnsupportedEncodingException {
    return URLEncoder.encode(password, UTF8);
  }

  /** Add a piece to the URL being string-built to specify cyclist's (encrypted) password */
  private void maybeAddPassword(final CycFort cyclist, final CycDenotationalTerm applicationTerm,
          final StringBuilder stringBuilder) {
    if (cyclist instanceof CycConstant) {
      final PasswordManager passwordManager = new PasswordManager(this);
      try {
        if (passwordManager.isPasswordRequired()) {
          final String password = passwordManager.lookupPassword((CycConstant) cyclist, applicationTerm);
          if (password != null) {
            // @hack -- Cyc decodes '+' characters twice, so we encode twice:
            final String urlEncodedPassword = doubleURLEncode(password);
            stringBuilder.append("&new_login_hashed_password=").append(urlEncodedPassword);
          }
        }
      } catch (IOException ex) {
        // Ignore: User may have to supply password to browser.
      }
    }
  }

  /**
   * Sets the print-readable-narts feature on.
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void setReadableNarts()
          throws UnknownHostException, IOException, CycApiException {
    converseVoid("(csetq *print-readable-narts t)");
  }

  /**
   * Gets a known CycConstant by using its constant name.
   *
   * @param constantName the name of the constant to be instantiated
   *
   * @return the complete <tt>CycConstant</tt> if found, otherwise throw an exception
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycConstant getKnownConstantByName(String constantName)
          throws UnknownHostException, IOException, CycApiException {
    CycConstant cycConstant = getConstantByName(constantName);

    if (cycConstant == null) {
      throw new CycApiException("Expected constant not found " + constantName);
    }

    return cycConstant;
  }

  /**
   * Gets a known CycFort by using its constant name or NART string.
   *
   * @param fortName the name of the FORT to be instantiated
   * @return the complete <tt>CycFort</tt> if found, otherwise throw an exception
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycFort getKnownFortByName(String fortName)
          throws UnknownHostException, IOException, CycApiException {
    CycFort fort = null;
    if (fortName.contains(")")) {
      final CycList terms = new CycListParser(this).read(fortName);
      fort = getCycNartFromCons(terms);
    } else {
      fort = getKnownConstantByName(fortName);
    }
    return fort;
  }

  public List findConstantsForNames(List constantNames)
          throws UnknownHostException, IOException, CycApiException {
    if ((constantNames == null) || (constantNames.size() <= 0)) {
      return null;
    }
    StringBuffer command = new StringBuffer("(MAPCAR (QUOTE FIND-CONSTANT) (LIST");
    for (Iterator iter = constantNames.iterator(); iter.hasNext();) {
      command.append(" \"");
      String curConstName = StringUtils.escapeDoubleQuotes("" + iter.next());
      command.append(curConstName);
      command.append("\"");
    }
    command.append("))");
    final Object result = converseCycObject("" + command);
    if (!(result instanceof CycList)) {
      return null;
    }
    return (CycList) result;
  }

  public List findConstantsForGuids(List constantGuids)
          throws UnknownHostException, IOException, CycApiException {
    if ((constantGuids == null) || (constantGuids.size() <= 0)) {
      return null;
    }
    List result = new ArrayList();
    // @ToDo this is very inefficient...we need to find a way to do this
    // with a single round trip to Cyc. --Tony
    for (Iterator iter = constantGuids.iterator(); iter.hasNext();) {
      CycConstant item = (CycConstant) iter.next();
      try {
        result.add(getConstantByGuid(item.getGuid()));
      } catch (Exception e) {
        result.add(CycObjectFactory.nil);
      }
    }
    return result;
  }

  /**
   * Gets a CycConstant by using its constant name.
   *
   * @param constantName the name of the constant to be instantiated
   *
   * @return the complete <tt>CycConstant</tt> if found, otherwise return null
   *
   * @throws IOException if a data communication error occurs
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycConstant getConstantByName(final String constantName)
          throws UnknownHostException, IOException, CycApiException {
    String name = constantName;
    if (constantName.startsWith("#$")) {
      name = name.substring(2);
    }
    CycConstant answer = CycObjectFactory.getCycConstantCacheByName(name);
    if (answer != null) {
      return answer;
    }
    final String command = makeSubLStmt("find-constant", name);
    final Object answerObject = converseObject(command);
    if (answerObject instanceof CycConstant) {
      answer = (CycConstant) answerObject;
      CycObjectFactory.addCycConstantCache(answer);
      return answer;
    }
    return null;
  }

  /**
   * Gets the Guid for the given constant name, raising an exception if the constant does not
   * exist.
   *
   * @param constantName the name of the constant object for which the Guid is sought
   *
   * @return the Guid for the given CycConstant
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public Guid getConstantGuid(String constantName)
          throws UnknownHostException, IOException, CycApiException {
    final String command =
            makeSubLStmt("guid-to-string",
            makeNestedSubLStmt("constant-external-id",
            makeNestedSubLStmt("find-constant", constantName)));
    return CycObjectFactory.makeGuid(converseString(command));
  }

  /**
   * Gets a <tt>CycAssertion</tt> by using its ID.
   *
   * @param id the id of the <tt>CycAssertion</tt> sought
   *
   * @return the <tt>CycAssertion</tt> if found or <tt>null</tt> if not found
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycAssertion getAssertionById(Integer id)
          throws UnknownHostException, IOException, CycApiException {
    final String command = makeSubLStmt("find-assertion-by-id", id);
    Object obj = converseObject(command);

    if (obj.equals(new CycSymbol("NIL"))) {
      return null;
    } else if (!(obj instanceof CycAssertion)) {
      throw new RuntimeException(obj + " is not a CycAssertion");
    } else {
      return (CycAssertion) obj;
    }
  }

  /**
   * Gets the name for the given constant guid.
   *
   * @param guid the guid of the constant object for which the name is sought
   *
   * @return the name for the given CycConstant
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public String getConstantName(Guid guid)
          throws UnknownHostException, IOException, CycApiException {
    // Optimized for the binary api.

    String command = makeSubLStmt("constant-name",
            makeNestedSubLStmt("find-constant-by-external-id",
            makeNestedSubLStmt("string-to-guid"), guid.toString()));

    return converseString(command);
  }

  /**
   * Gets a known CycConstant by using its GUID string.
   *
   * @param guidString the globally unique ID string of the constant to be instantiated
   *
   * @return the complete <tt>CycConstant</tt> if found, otherwise throw an exception
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycConstant getKnownConstantByGuid(String guidString)
          throws UnknownHostException, IOException, CycApiException {
    Guid guid = CycObjectFactory.makeGuid(guidString);

    return getKnownConstantByGuid(guid);
  }

  /**
   * Gets a known CycConstant by using its GUID.
   *
   * @param guid the globally unique ID of the constant to be instantiated
   *
   * @return the complete <tt>CycConstant</tt> if found, otherwise throw an exception
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycConstant getKnownConstantByGuid(Guid guid)
          throws UnknownHostException, IOException, CycApiException {
    CycConstant cycConstant = getConstantByGuid(guid);

    if (cycConstant == null) {
      throw new CycApiException("Expected constant not found " + guid);
    }

    return cycConstant;
  }

  /**
   * Gets a CycConstant by using its GUID.
   *
   * @param guid the GUID from which to find the constant
   *
   * @return the complete <tt>CycConstant</tt> if found, otherwise return <tt>null</tt>
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycConstant getConstantByGuid(Guid guid)
          throws UnknownHostException, IOException, CycApiException {
    CycConstant answer = CycObjectFactory.getCycConstantCacheByGuid(
            guid);
    if (answer != null) {
      return answer;
    }
    final String command =
            makeSubLStmt("find-constant-by-external-id",
            makeNestedSubLStmt("string-to-guid", guid.getGuidString()));
    final Object answerObject = converseObject(command);
    if (answerObject instanceof CycConstant) {
      answer = (CycConstant) answerObject;
      CycObjectFactory.addCycConstantCache(answer);
      return answer;
    }
    return null;
  }

  /**
   * Adds #$ to string for all CycConstants mentioned in the string that don't already have them
   * @param str the String that will have #$'s added to it.
   *
   * @return a copy of str with #$'s added where appropriate.
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public String cyclifyString(String str)
          throws UnknownHostException, IOException, CycApiException {
    final String command =
            makeSubLStmt("cyclify-string", str);
    final String answer = converseString(command);
    return answer;
  }

  /**
   * Makes a known CycConstant by using its GUID and name, adding it to the cache.
   *
   * @param guidString the known GUID string from which to make the constant
   * @param constantName the known name to associate with the constant
   *
   * @return the complete <tt>CycConstant</tt> if found, otherwise return <tt>null</tt>
   */
  public CycConstant makeConstantWithGuidName(String guidString,
          String constantName) {
    return makeConstantWithGuidName(CycObjectFactory.makeGuid(
            guidString),
            constantName);
  }

  /**
   * Makes a known CycConstant by using its GUID and name, adding it to the cache.
   *
   * @param guid the known GUID from which to make the constant
   * @param constantName the known name to associate with the constant
   *
   * @return the complete <tt>CycConstant</tt> if found, otherwise return <tt>null</tt>
   */
  public CycConstant makeConstantWithGuidName(Guid guid,
          String constantName) {
    CycConstant answer = CycObjectFactory.getCycConstantCacheByGuid(guid);
    if (answer != null) {
      return answer;
    }
    answer = new CycConstant(constantName, guid);
    CycObjectFactory.addCycConstantCache(answer);

    return answer;
  }

  /**
   * Gets the CycNart object from a Cons object that lists the names of its functor and its
   * arguments.
   *
   * @param elCons the given list which names the functor and arguments
   *
   * @return a CycNart object from a Cons object that lists the names of its functor and its
   *         arguments
   */
  public CycNart getCycNartFromCons(CycList elCons) {
    return new CycNart(elCons);
  }

  /**
   * Returns true if CycConstant BINARYPREDICATE relates CycFort ARG1 and CycFort ARG2.
   *
   * @param binaryPredicate the predicate
   * @param arg1 the first argument related by the predicate
   * @param arg2 the second argument related by the predicate
   *
   * @return true if CycConstant BINARYPREDICATE relates CycFort ARG1 and CycFort ARG2 otherwise
   *         false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean predicateRelates(CycConstant binaryPredicate,
          CycFort arg1,
          CycFort arg2)
          throws UnknownHostException, IOException, CycApiException {
    Object[] response = {null, null};
    final String command =
            makeSubLStmt("pred-u-v-holds-in-any-mt", binaryPredicate, arg1, arg2);
    response = converse(command);

    if (response[0].equals(Boolean.TRUE)) {
      if (response[1] == null) {
        return false;
      } else if (response[1].toString().equals("T")) {
        return true;
      } else {
        return false;
      }
    } else {
      throw new CycApiException(response[1].toString());
    }
  }

  /**
   * Returns true if CycConstant BINARYPREDICATE relates CycFort ARG1 and CycFort ARG2.
   *
   * @param binaryPredicate the predicate
   * @param arg1 the first argument related by the predicate
   * @param arg2 the second argument related by the predicate
   * @param mt the relevant mt
   *
   * @return true if CycConstant BINARYPREDICATE relates CycFort ARG1 and CycFort ARG2 otherwise
   *         false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean predicateRelates(CycConstant binaryPredicate,
          CycFort arg1,
          CycFort arg2,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    Object[] response = {null, null};
    final String command =
            makeSubLStmt("pred-u-v-holds", binaryPredicate, arg1, arg2, makeELMt(mt));
    response = converse(command);

    if (response[0].equals(Boolean.TRUE)) {
      if (response[1] == null) {
        return false;
      } else if (response[1].toString().equals("T")) {
        return true;
      } else {
        return false;
      }
    } else {
      throw new CycApiException(response[1].toString());
    }
  }

  private String getGeneratedPhrase(CycObject cycObject, boolean precise, CycObject languageMt)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    final NLFormat nlf = NLFormat.getInstance(this);
    nlf.setPrecise(precise);
    if (languageMt != null) {
      nlf.setFormatLanguageMt(languageMt);
    }
    return nlf.format(cycObject);
  }

  /**
   * Gets the default generated phrase for a CycFort (intended for predicates).
   *
   * @param cycObject the predicate term for paraphrasing
   *
   * @return the default generated phrase for a CycFort
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public String getGeneratedPhrase(CycObject cycObject)
          throws UnknownHostException, IOException, CycApiException {
    return getGeneratedPhrase(cycObject, true, null);
  }

  /**
   * Gets the default generated phrase for a CycFort (intended for predicates),
   * with precise paraphrasing off.
   *
   * @param cycObject the predicate term for paraphrasing
   *
   * @return the default generated phrase for a CycFort
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  /*
  public String getImpreciseGeneratedPhrase(CycObject cycObject)
  throws UnknownHostException, IOException, CycApiException {
  //// Preconditions
  if (cycObject == null) {
  throw new NullPointerException("cycObject must not be null");
  }
  if (!(cycObject instanceof CycConstant
  || cycObject instanceof CycNart
  || cycObject instanceof CycList)) {
  throw new IllegalArgumentException("cycObject must be a CycConstant, CycNart or CycList " + cycObject.cyclify());
  }
  String command = "(with-precise-paraphrase-off (generate-phrase "
  + cycObject.stringApiValue() + "))";
  return converseString(command);
  }
   */
  /**
   * Gets the default generated phrase for a CycFort (intended for predicates)
   * from a particular MT with precise paraphrasing off.
   *
   * @param cycObject the predicate term for paraphrasing
   *
   * @return the default generated phrase for a CycFort
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  /*
  public String getImpreciseGeneratedPhrase(CycObject cycObject, CycObject mt)
  throws UnknownHostException, IOException, CycApiException {
  //// Preconditions
  if (cycObject == null) {
  throw new NullPointerException("cycObject must not be null");
  }
  if (!(cycObject instanceof CycConstant
  || cycObject instanceof CycNart
  || cycObject instanceof CycList)) {
  throw new IllegalArgumentException("cycObject must be a CycConstant, CycNart or CycList " + cycObject.cyclify());
  }
  String command = "(with-precise-paraphrase-off (generate-phrase "
  + cycObject.stringApiValue() + " :DEFAULT nil " + mt.stringApiValue() + "))";
  return converseString(command);
  }
   */
  /**
   * Gets the paraphrase for a Cyc assertion.
   *
   * @param assertion the assertion formula
   *
   * @return the paraphrase for a Cyc assertion
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public String getParaphrase(CycList assertion)
          throws UnknownHostException, IOException, CycApiException {
    return getGeneratedPhrase(assertion);
  }

  /**
   * Gets the paraphrase for a Cyc sentence.
   *
   * @param sentence the sentence
   *
   * @return the paraphrase
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public String getParaphrase(CycFormulaSentence sentence)
          throws UnknownHostException, IOException, CycApiException {
    return getGeneratedPhrase(sentence);
  }

  /**
   * Gets the imprecise paraphrase for a Cyc assertion.
   *
   * @param assertionString the assertion formula
   *
   * @return the imprecise paraphrase for a Cyc assertion
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public String getImpreciseParaphrase(String assertionString)
          throws UnknownHostException, IOException, CycApiException {
    CycFormulaSentence assertion = this.makeCycSentence(assertionString);
    return getGeneratedPhrase(assertion, false, null);
  }

  /**
   * Gets the imprecise paraphrase for a Cyc assertion.
   *
   * @param assertion the assertion formula
   *
   * @return the imprecise paraphrase for a Cyc assertion
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public String getImpreciseParaphrase(CycList assertion)
          throws UnknownHostException, IOException, CycApiException {
    return getGeneratedPhrase(assertion, false, null);
  }

  /**
   * Gets the concise paraphrase for a Cyc sentence.
   *
   * @param sentence the assertion formula
   *
   * @return the imprecise paraphrase for a Cyc assertion
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public String getImpreciseParaphrase(CycFormulaSentence sentence)
          throws UnknownHostException, IOException, CycApiException {
    return getGeneratedPhrase(sentence, false, null);
  }

  /**
   * Gets the comment for a CycFort.  Embedded quotes are replaced by spaces.
   *
   * @param cycObject the term for which the comment is sought
   *
   * @return the comment for the given CycFort
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public String getComment(CycObject cycObject)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    if (cycObject instanceof CycList) {
      return null;
    }
    String script = "(clet ((comment-string \n" + "         (with-all-mts (comment "
            + cycObject.stringApiValue() + ")))) \n" + "  (fif comment-string \n"
            + "       (string-substitute \" \" \"\\\"\" comment-string) \n"
            + "       \"\"))";

    return converseString(script);
  }

  /**
   * Gets the comment for a CycFort in the relevant mt. Embedded quotes are replaced by spaces.
   *
   * @param cycFort the term for which the comment is sought
   * @param mt the relevant mt from which the comment is visible
   *
   * @return the comment for the given CycFort
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public String getComment(final CycObject cycObject,
          final CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    if (mt == null) {
      throw new NullPointerException("mt must not be null");
    }
    String script =
            "(clet ((comment-string \n"
            + "         (comment " + cycObject.stringApiValue() + " " + makeELMt(mt).stringApiValue() + "))) \n"
            + "  (fif comment-string \n"
            + "       (string-substitute \" \" \"\\\"\" comment-string) \n"
            + "       \"\"))";

    return converseString(script);
  }

  /**
   * Gets the list of the isas for the given CycFort.
   *
   * @param cycObject the term for which its isas are sought
   *
   * @return the list of the isas for the given CycFort
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getIsas(CycObject cycObject)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    return converseList("(remove-duplicates (with-all-mts (isa " + cycObject.stringApiValue()
            + ")))");
  }

  /**
   * Gets the list of the isas for the given CycFort.
   *
   * @param cycObject the term for which its isas are sought
   * @param mt the relevant mt
   *
   * @return the list of the isas for the given CycFort
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getIsas(final CycObject cycObject,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    if (mt == null) {
      throw new NullPointerException("mt must not be null");
    }
    return converseList("(isa " + cycObject.stringApiValue()
            + " " + makeELMt(mt).stringApiValue()
            + ")");
  }

  /**
   * Gets the list of the directly asserted true genls for the given CycFort collection.
   *
   * @param cycObject the given term
   *
   * @return the list of the directly asserted true genls for the given CycFort collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getGenls(CycObject cycObject)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    return converseList("(remove-duplicates (with-all-mts (genls " + cycObject.stringApiValue()
            + ")))");
  }

  /**
   * Gets the list of the directly asserted true genls for the given CycFort collection.
   *
   * @param cycObject the given term
   * @param mt the relevant mt
   *
   * @return the list of the directly asserted true genls for the given CycFort collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getGenls(final CycObject cycObject,
          final CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    if (mt == null) {
      throw new NullPointerException("mt must not be null");
    }
    return converseList("(genls " + cycObject.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets a list of the minimum (most specific) genls for a CycFort collection.
   *
   * @param cycFort the given collection term
   *
   * @return a list of the minimum (most specific) genls for a CycFort collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getMinGenls(CycFort cycFort)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(remove-duplicates (with-all-mts (min-genls "
            + cycFort.stringApiValue() + ")))");
  }

  /**
   * Gets a list of the minimum (most specific) genls for a CycFort collection.
   *
   * @param cycFort the collection
   * @param mt the microtheory in which to look
   *
   * @return a list of the minimum (most specific) genls for a CycFort collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getMinGenls(CycFort cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(min-genls " + cycFort.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets the list of the directly asserted true specs for the given CycFort collection.
   *
   * @param cycFort the given collection
   *
   * @return the list of the directly asserted true specs for the given CycFort collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getSpecs(CycFort cycFort)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(remove-duplicates (with-all-mts (specs " + cycFort.stringApiValue()
            + ")))");
  }

  /**
   * Gets the list of the directly asserted true specs for the given CycFort collection.
   *
   * @param cycFort the given collection
   * @param mt the microtheory in which to look
   *
   * @return the list of the directly asserted true specs for the given CycFort collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getSpecs(CycFort cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(specs " + cycFort.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets the list of the least specific specs for the given CycFort collection.
   *
   * @param cycFort the given collection
   *
   * @return the list of the least specific specs for the given CycFort collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getMaxSpecs(CycFort cycFort)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(remove-duplicates (with-all-mts (max-specs "
            + cycFort.stringApiValue() + ")))");
  }

  /**
   * Gets the list of the least specific specs for the given CycFort collection.
   *
   * @param cycFort the given collection
   * @param mt the microtheory in which to look
   *
   * @return the list of the least specific specs for the given CycFort collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getMaxSpecs(CycFort cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(max-specs " + cycFort.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets the list of the direct genls of the direct specs for the given CycFort collection.
   *
   * @param cycFort the given collection
   *
   * @return the list of the direct genls of the direct specs for the given CycFort collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getGenlSiblings(CycFort cycFort)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(remove-duplicates (with-all-mts (genl-siblings "
            + cycFort.stringApiValue() + ")))");
  }

  /**
   * Gets the list of the direct genls of the direct specs for the given CycFort collection.
   *
   * @param cycFort the given collection
   * @param mt the microtheory in which to look
   *
   * @return the list of the direct genls of the direct specs for the given CycFort collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getGenlSiblings(CycFort cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(genl-siblings " + cycFort.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets the list of the siblings (direct specs of the direct genls) for the given CycFort
   * collection.
   *
   * @param cycFort the given collection
   *
   * @return the list of the siblings (direct specs of the direct genls) for the given CycFort
   *         collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getSiblings(CycFort cycFort)
          throws UnknownHostException, IOException, CycApiException {
    return getSpecSiblings(cycFort);
  }

  /**
   * Gets the list of the siblings (direct specs of the direct genls) for the given CycFort
   * collection.
   *
   * @param cycFort the given collection
   * @param mt the microtheory in which to look
   *
   * @return the list of the siblings (direct specs of the direct genls) for the given CycFort
   *         collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getSiblings(CycFort cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return getSpecSiblings(cycFort,
            mt);
  }

  /**
   * Gets the list of the siblings (direct specs of the direct genls) for the given CycFort
   * collection.
   *
   * @param cycFort the given collection
   *
   * @return the list of the siblings (direct specs of the direct genls) for the given CycFort
   *         collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getSpecSiblings(CycFort cycFort)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(remove-duplicates (with-all-mts (spec-siblings "
            + cycFort.stringApiValue() + ")))");
  }

  /**
   * Gets the list of the siblings (direct specs of the direct genls) for the given CycFort
   * collection.
   *
   * @param cycFort the given collection
   * @param mt the microtheory in which to look
   *
   * @return the list of the siblings (direct specs of the direct genls) for the given CycFort
   *         collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getSpecSiblings(CycFort cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(spec-siblings " + cycFort.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets the list of all of the direct and indirect genls for the given CycFort collection.
   *
   * @param cycFort the collection
   *
   * @return the list of all of the direct and indirect genls for a CycFort collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getAllGenls(CycFort cycFort)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(all-genls-in-any-mt " + cycFort.stringApiValue() + ")");
  }

  /**
   * Gets the list of all of the direct and indirect genls for a CycFort collection given a
   * relevant microtheory.
   *
   * @param cycObject the collection
   * @param mt the relevant mt
   *
   * @return the list of all of the direct and indirect genls for a CycFort collection given a
   *         relevant microtheory
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getAllGenls(CycObject cycObject,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    if (mt == null) {
      throw new NullPointerException("mt must not be null");
    }
    return converseList("(all-genls " + cycObject.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets a list of all of the direct and indirect specs for a CycFort collection.
   *
   * @param cycFort the collection
   *
   * @return the list of all of the direct and indirect specs for the given collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getAllSpecs(CycFort cycFort)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(remove-duplicates (with-all-mts (all-specs "
            + cycFort.stringApiValue() + ")))");
  }

  /**
   * Gets the list of all of the direct and indirect specs for the given collection in the given
   * microtheory.
   *
   * @param cycFort the collection
   * @param mt the microtheory
   *
   * @return the list of all of the direct and indirect specs for the given collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getAllSpecs(CycFort cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(all-specs " + cycFort.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets the list of all of the direct and indirect genls for a CycFort SPEC which are also specs
   * of CycFort GENL.
   *
   * @param spec the given collection
   * @param genl the more general collection
   *
   * @return the list of all of the direct and indirect genls for a CycFort SPEC which are also
   *         specs of CycFort GENL
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getAllGenlsWrt(CycFort spec,
          CycFort genl)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(remove-duplicates (with-all-mts (all-genls-wrt "
            + spec.stringApiValue() + " " + genl.stringApiValue() + ")))");
  }

  /**
   * Gets the list of all of the direct and indirect genls for a CycFort SPEC which are also specs
   * of CycFort GENL.
   *
   * @param spec the given collection
   * @param genl the more general collection
   * @param mt the relevant mt
   *
   * @return the list of all of the direct and indirect genls for a CycFort SPEC which are also
   *         specs of CycFort GENL
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getAllGenlsWrt(CycFort spec,
          CycFort genl,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(all-genls-wrt " + spec.stringApiValue() + " " + genl.stringApiValue()
            + " " + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets the list of all of the dependent specs for a CycFort collection.  Dependent specs are
   * those direct and indirect specs of the collection such that every path connecting the spec to
   * a genl of the collection passes through the collection.  In a typical taxomonmy it is
   * expected that all-dependent-specs gives the same result as all-specs.
   *
   * @param cycFort the given collection
   *
   * @return the list of all of the dependent specs for the given CycFort collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getAllDependentSpecs(CycFort cycFort)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(remove-duplicates (with-all-mts (all-dependent-specs "
            + cycFort.stringApiValue() + ")))");
  }

  /**
   * Gets the list of all of the dependent specs for a CycFort collection.  Dependent specs are
   * those direct and indirect specs of the collection such that every path connecting the spec to
   * a genl of the collection passes through the collection.  In a typical taxomonmy it is
   * expected that all-dependent-specs gives the same result as all-specs.
   *
   * @param cycFort the given collection
   * @param mt the relevant mt
   *
   * @return the list of all of the dependent specs for the given CycFort collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getAllDependentSpecs(CycFort cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(all-dependent-specs " + cycFort.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets the list with the specified number of sample specs of the given CycFort collection.
   * Attempts to return leaves that are maximally differet with regard to their all-genls.
   *
   * @param cycFort the given collection
   * @param numberOfSamples the maximum number of sample specs returned
   *
   * @return the list with the specified number of sample specs of the given CycFort collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getSampleLeafSpecs(CycFort cycFort,
          int numberOfSamples)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(with-all-mts (sample-leaf-specs " + cycFort.stringApiValue() + " "
            + numberOfSamples + "))");
  }

  /**
   * Gets the list with the specified number of sample specs of the given CycFort collection.
   * Attempts to return leaves that are maximally differet with regard to their all-genls.
   *
   * @param cycFort the given collection
   * @param numberOfSamples the maximum number of sample specs returned
   * @param mt the relevant mt
   *
   * @return the list with the specified number of sample specs of the given CycFort collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getSampleLeafSpecs(CycFort cycFort,
          int numberOfSamples,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(sample-leaf-specs " + cycFort.stringApiValue() + " " + numberOfSamples
            + " " + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Returns the single most specific collection from the given list of collectons.
   *
   * @param collections the given collections
   *
   * @return the single most specific collection from the given list of collectons
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycFort getMinCol(final CycList collections)
          throws UnknownHostException, IOException, CycApiException {
    return (CycFort) converseObject("(with-all-mts (min-col " + collections.stringApiValue()
            + "))");
  }

  /**
   * Returns the single most specific collection from the given list of collectons.
   *
   * @param collections the given collections
   * @param mt the relevant mt
   *
   * @return the single most specific collection from the given list of collectons
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycFort getMinCol(final CycList collections, final CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (collections == null) {
      throw new NullPointerException("collections must not be null");
    }
    if (mt == null) {
      throw new NullPointerException("mt must not be null");
    }
    return (CycFort) converseObject("(with-inference-mt-relevance " + makeELMt(mt).stringApiValue()
            + " (min-col " + collections.stringApiValue() + "))");
  }

  /**
   * Returns the most general collections from the given list of collectons.
   *
   * @param collections the given collections
   *
   * @return the most general collections from the given list of collectons
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getMaxCols(final CycList collections)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    assert collections != null : "collections cannot be null";

    return converseList("(with-all-mts (max-cols " + collections.stringApiValue()
            + "))");
  }

  /**
   * Returns the most general collections from the given list of collectons.
   *
   * @param collections the given collections
   * @param mt the inference microtheory
   *
   * @return the most general collections from the given list of collectons
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getMaxCols(final CycList collections, final CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (collections == null) {
      throw new NullPointerException("collections must not be null");
    }
    if (mt == null) {
      throw new NullPointerException("mt must not be null");
    }
    return converseList("(with-inference-mt-relevance " + makeELMt(mt).stringApiValue() + " (max-cols " + collections.stringApiValue()
            + "))");
  }

  /**
   * Returns the most specific collections from the given list of collectons.
   *
   * @param collections the given collections
   *
   * @return the most specific collections from the given list of collectons
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getMinCols(final CycList collections)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    assert collections != null : "collections cannot be null";

    return converseList("(with-all-mts (min-cols " + collections.stringApiValue()
            + "))");
  }

  /**
   * Returns the most specific collections from the given list of collectons.
   *
   * @param collections the given collections
   * @param mt the inference microtheory
   *
   * @return the most specific collections from the given list of collectons
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getMinCols(final CycList collections, final CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (collections == null) {
      throw new NullPointerException("collections must not be null");
    }
    if (mt == null) {
      throw new NullPointerException("mt must not be null");
    }
    return converseList("(with-inference-mt-relevance " + makeELMt(mt).stringApiValue()
            + " (min-cols " + collections.stringApiValue() + "))");
  }

  /**
   * Returns true if CycFort SPEC is a spec of CycFort GENL.
   *
   * @param spec the considered spec collection
   * @param genl the considered genl collection
   *
   * @return true if CycFort SPEC is a spec of CycFort GENL, otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isSpecOf(CycObject spec,
          CycObject genl)
          throws UnknownHostException, IOException, CycApiException {
    return isGenlOf(genl,
            spec);
  }

  /**
   * Returns true if CycFort SPEC is a spec of CycFort GENL.
   *
   * @param spec the considered spec collection
   * @param genl the considered genl collection
   * @param mt the relevant mt
   *
   * @return true if CycFort SPEC is a spec of CycFort GENL, otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isSpecOf(CycObject spec,
          CycObject genl,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return isGenlOf(genl,
            spec,
            mt);
  }

  /**
   * Returns true if CycFort GENL is a genl of CycFort SPEC.
   *
   * @param genl the collection for genl determination
   * @param spec the collection for spec determination
   *
   * @return <tt>true</tt> if CycFort GENL is a genl of CycFort SPEC
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isGenlOf(CycObject genl,
          CycObject spec)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(genl-in-any-mt? " + spec.stringApiValue() + " "
            + genl.stringApiValue() + ")");
  }

  /**
   * Returns true if CycFort GENL is a genl of CycFort SPEC, implements a cache to avoid asking the
   * same question twice from the KB.
   *
   * @param genl the collection for genl determination
   * @param spec the collection for spec determination
   *
   * @return <tt>true</tt> if CycFort GENL is a genl of CycFort SPEC
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isGenlOf_Cached(CycObject genl,
          CycObject spec)
          throws UnknownHostException, IOException, CycApiException {
    final Pair args = new Pair(genl, spec);
    Boolean isGenlOf = isGenlOfCache.get(args);
    if (isGenlOf != null) {
      return isGenlOf.booleanValue();
    }
    final boolean answer = isGenlOf(genl, spec);
    isGenlOfCache.put(args, answer);
    return answer;
  }

  /**
   * Returns true if CycFort GENL is a genl of CycFort SPEC in MT.
   *
   * @param genl the collection for genl determination
   * @param spec the collection for spec determination
   * @param mt the microtheory for spec determination
   *
   * @return <tt>true</tt> if CycFort GENL is a genl of CycFort SPEC in MT
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isGenlOf(CycObject genl,
          CycObject spec,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(genl? " + spec.stringApiValue() + " " + genl.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Returns true if CycFort GENLPRED is a genl-pred of CycFort SPECPRED in MT.
   *
   * @param genlPred the predicate for genl-pred determination
   * @param specPred the predicate for spec-pred determination
   * @param mt the microtheory for subsumption determination
   *
   * @return <tt>true</tt> if CycFort GENLPRED is a genl-pred of CycFort SPECPRED in MT
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isGenlPredOf(CycFort genlPred,
          CycFort specPred,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(genl-predicate? " + specPred.stringApiValue() + " "
            + genlPred.stringApiValue() + " " + makeELMt(
            mt).stringApiValue() + ")");
  }

  /**
   * Returns true if CycFort GENLPRED is a genl-pred of CycFort SPECPRED in any MT.
   *
   * @param genlPred the predicate for genl-pred determination
   * @param specPred the predicate for spec-pred determination
   *
   * @return <tt>true</tt> if CycFort GENLPRED is a genl-pred of CycFort SPECPRED in any MT
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isGenlPredOf(CycFort genlPred,
          CycFort specPred)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(with-all-mts (genl-predicate? " + specPred.stringApiValue() + " "
            + genlPred.stringApiValue() + "))");
  }

  /**
   * Returns true if CycFort GENLPRED is a genl-inverse of CycFort SPECPRED in MT.
   *
   * @param genlPred the predicate for genl-inverse determination
   * @param specPred the predicate for spec-inverse determination
   * @param mt the microtheory for inverse subsumption determination
   *
   * @return <tt>true</tt> if CycFort GENLPRED is a genl-inverse of CycFort SPECPRED in MT
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isGenlInverseOf(CycFort genlPred,
          CycFort specPred,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(genl-inverse? " + specPred.stringApiValue() + " "
            + genlPred.stringApiValue() + " " + makeELMt(
            mt).stringApiValue() + ")");
  }

  /**
   * Returns true if CycFort GENLPRED is a genl-inverse of CycFort SPECPRED in any MT.
   *
   * @param genlPred the predicate for genl-inverse determination
   * @param specPred the predicate for spec-inverse determination
   *
   * @return <tt>true</tt> if CycFort GENLPRED is a genl-inverse of CycFort SPECPRED in any MT
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isGenlInverseOf(CycFort genlPred,
          CycFort specPred)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(with-all-mts (genl-inverse? " + specPred.stringApiValue() + " "
            + genlPred.stringApiValue() + "))");
  }

  /**
   * Returns true if CycFort GENLMT is a genl-mt of CycFort SPECPRED in mt-mt (currently
   * #$UniversalVocabularyMt).
   *
   * @param genlMt the microtheory for genl-mt determination
   * @param specMt the microtheory for spec-mt determination
   *
   * @return <tt>true</tt> if CycFort GENLMT is a genl-mt of CycFort SPECPRED in mt-mt (currently
   *         #$UniversalVocabularyMt)
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isGenlMtOf(CycObject genlMt,
          CycObject specMt)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(genl-mt? " + makeELMt(specMt).stringApiValue() + " "
            + makeELMt(genlMt).stringApiValue() + ")");
  }

  /**
   * Returns true if CycFort COLLECION1 and CycFort COLLECTION2 are tacitly coextensional via
   * mutual genls of each other.
   *
   * @param collection1 the first given collection
   * @param collection2 the second given collection
   *
   * @return true if CycFort COLLECION1 and CycFort COLLECTION2 are tacitly coextensional via
   *         mutual genls of each other, otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean areTacitCoextensional(CycFort collection1,
          CycFort collection2)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(with-all-mts (tacit-coextensional? " + collection1.stringApiValue()
            + " " + collection2.stringApiValue() + "))");
  }

  /**
   * Returns true if CycFort COLLECION1 and CycFort COLLECTION2 are tacitly coextensional via
   * mutual genls of each other.
   *
   * @param collection1 the first given collection
   * @param collection2 the second given collection
   * @param mt the relevant mt
   *
   * @return true if CycFort COLLECION1 and CycFort COLLECTION2 are tacitly coextensional via
   *         mutual genls of each other, otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean areTacitCoextensional(CycFort collection1,
          CycFort collection2,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(tacit-coextensional? " + collection1.stringApiValue() + " "
            + collection2.stringApiValue() + " " + makeELMt(
            mt).stringApiValue() + ")");
  }

  /**
   * Returns true if CycFort COLLECION1 and CycFort COLLECTION2 are asserted coextensional.
   *
   * @param collection1 the first collection
   * @param collection2 the second collection
   *
   * @return true if CycFort COLLECION1 and CycFort COLLECTION2 are asserted coextensional
   *         otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean areAssertedCoextensional(CycFort collection1,
          CycFort collection2)
          throws UnknownHostException, IOException, CycApiException {
    CycConstant coExtensional = this.getKnownConstantByGuid(
            "bd59083a-9c29-11b1-9dad-c379636f7270");

    if (predicateRelates(coExtensional,
            collection1,
            collection2)) {
      return true;
    } else if (predicateRelates(coExtensional,
            collection2,
            collection1)) {
      return true;
    } else {
      return false;
    }
  }

  /**
   * Returns true if CycFort COLLECION1 and CycFort COLLECTION2 are asserted coextensional.
   *
   * @param collection1 the first collection
   * @param collection2 the second collection
   * @param mt the relevant mt
   *
   * @return true if CycFort COLLECION1 and CycFort COLLECTION2 are asserted coextensional
   *         otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean areAssertedCoextensional(CycFort collection1,
          CycFort collection2,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    CycConstant coExtensional = this.getKnownConstantByGuid(
            "bd59083a-9c29-11b1-9dad-c379636f7270");

    if (predicateRelates(coExtensional,
            collection1,
            collection2,
            mt)) {
      return true;
    } else if (predicateRelates(coExtensional,
            collection2,
            collection1,
            mt)) {
      return true;
    } else {
      return false;
    }
  }

  /**
   * Returns true if CycFort COLLECION1 and CycFort COLLECTION2 intersect with regard to all-specs.
   *
   * @param collection1 the first collection
   * @param collection2 the second collection
   *
   * @return true if CycFort COLLECION1 and CycFort COLLECTION2 intersect with regard to all-specs
   *         otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean areIntersecting(CycFort collection1,
          CycFort collection2)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(with-all-mts (collections-intersect? "
            + collection1.stringApiValue() + " " + collection2.stringApiValue()
            + "))");
  }

  /**
   * Returns true if CycFort COLLECION1 and CycFort COLLECTION2 intersect with regard to all-specs.
   *
   * @param collection1 the first collection
   * @param collection2 the second collection
   * @param mt the relevant mt
   *
   * @return true if CycFort COLLECION1 and CycFort COLLECTION2 intersect with regard to all-specs
   *         otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean areIntersecting(CycFort collection1,
          CycFort collection2,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(collections-intersect? " + collection1.stringApiValue() + " "
            + collection2.stringApiValue() + " " + makeELMt(
            mt).stringApiValue() + ")");
  }

  /**
   * Returns true if CycFort COLLECION1 and CycFort COLLECTION2 are in a hierarchy.
   *
   * @param collection1 the first collection
   * @param collection2 the second collection
   *
   * @return true if CycFort COLLECION1 and CycFort COLLECTION2 are in a hierarchy, otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean areHierarchical(CycFort collection1,
          CycFort collection2)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(with-all-mts (hierarchical-collections? "
            + collection1.stringApiValue() + " " + collection2.stringApiValue()
            + "))");
  }

  /**
   * Returns true if CycFort COLLECION1 and CycFort COLLECTION2 are in a hierarchy.
   *
   * @param collection1 the first collection
   * @param collection2 the second collection
   * @param mt the relevant mt
   *
   * @return true if CycFort COLLECION1 and CycFort COLLECTION2 are in a hierarchy, otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean areHierarchical(CycFort collection1,
          CycFort collection2,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(hierarchical-collections? " + collection1.stringApiValue()
            + collection2.stringApiValue() + " " + makeELMt(
            mt).stringApiValue() + ")");
  }

  /**
   * Gets the list of the justifications of why CycFort SPEC is a SPEC of CycFort GENL.
   * getWhyGenl("Dog", "Animal") --> "(((#$genls #$Dog #$CanineAnimal) :TRUE) (#$genls
   * #$CanineAnimal #$NonPersonAnimal) :TRUE) (#$genls #$NonPersonAnimal #$Animal) :TRUE))
   *
   * @param spec the specialized collection
   * @param genl the more general collection
   *
   * @return the list of the justifications of why CycFort SPEC is a SPEC of CycFort GENL
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getWhyGenl(CycFort spec,
          CycFort genl)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(with-all-mts (why-genl? " + spec.stringApiValue() + " "
            + genl.stringApiValue() + "))");
  }

  /**
   * Gets the list of the justifications of why CycFort SPEC is a SPEC of CycFort GENL.
   * getWhyGenl("Dog", "Animal") --> "(((#$genls #$Dog #$CanineAnimal) :TRUE) (#$genls
   * #$CanineAnimal #$NonPersonAnimal) :TRUE) (#$genls #$NonPersonAnimal #$Animal) :TRUE))
   *
   * @param spec the specialized collection
   * @param genl the more general collection
   * @param mt the relevant mt
   *
   * @return the list of the justifications of why CycFort SPEC is a SPEC of CycFort GENL
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getWhyGenl(CycFort spec,
          CycFort genl,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(why-genl? " + spec.stringApiValue() + " " + genl.stringApiValue()
            + " " + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets the English parapharse of the justifications of why CycFort SPEC is a SPEC of CycFort
   * GENL. getWhyGenlParaphrase("Dog", "Animal") --> "a dog is a kind of canine" "a canine is a
   * kind of non-human animal" "a non-human animal is a kind of animal"
   *
   * @param spec the specialized collection
   * @param genl the more general collection
   *
   * @return the English parapharse of the justifications of why CycFort SPEC is a SPEC of CycFort
   *         GENL
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public List getWhyGenlParaphrase(CycFort spec,
          CycFort genl)
          throws UnknownHostException, IOException, CycApiException {
    CycList listAnswer = converseList("(with-all-mts (why-genl? " + spec.stringApiValue() + " "
            + genl.stringApiValue() + "))");
    List answerPhrases = new ArrayList();

    if (listAnswer.size() == 0) {
      return answerPhrases;
    }

    CycList iter = listAnswer;

    for (int i = 0; i < listAnswer.size(); i++) {
      CycList assertion = (CycList) ((CycList) listAnswer.get(
              i)).first();
      answerPhrases.add(getParaphrase(assertion));
    }

    return answerPhrases;
  }

  /**
   * Gets the English parapharse of the justifications of why CycFort SPEC is a SPEC of CycFort
   * GENL. getWhyGenlParaphrase("Dog", "Animal") --> "a dog is a kind of canine" "a canine is a
   * kind of non-human animal" "a non-human animal is a kind of animal"
   *
   * @param spec the specialized collection
   * @param genl the more general collection
   * @param mt the relevant mt
   *
   * @return the English parapharse of the justifications of why CycFort SPEC is a SPEC of CycFort
   *         GENL
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public List getWhyGenlParaphrase(CycFort spec,
          CycFort genl,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    CycList listAnswer = converseList("(why-genl? " + spec.stringApiValue() + " "
            + genl.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
    List answerPhrases = new ArrayList();

    if (listAnswer.size() == 0) {
      return answerPhrases;
    }

    CycList iter = listAnswer;

    for (int i = 0; i < listAnswer.size(); i++) {
      CycList assertion = (CycList) ((CycList) listAnswer.get(
              i)).first();
      answerPhrases.add(getParaphrase(assertion));
    }

    return answerPhrases;
  }

  /**
   * Gets the list of the justifications of why CycFort COLLECTION1 and a CycFort COLLECTION2
   * intersect. see getWhyGenl
   *
   * @param collection1 the first collection
   * @param collection2 the second collection
   *
   * @return the list of the justifications of why CycFort COLLECTION1 and a CycFort COLLECTION2
   *         intersect
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getWhyCollectionsIntersect(CycFort collection1,
          CycFort collection2)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(with-all-mts (why-collections-intersect? "
            + collection1.stringApiValue() + " " + collection2.stringApiValue() + "))");
  }

  /**
   * Gets the list of the justifications of why CycFort COLLECTION1 and a CycFort COLLECTION2
   * intersect. see getWhyGenl
   *
   * @param collection1 the first collection
   * @param collection2 the second collection
   * @param mt the relevant mt
   *
   * @return the list of the justifications of why CycFort COLLECTION1 and a CycFort COLLECTION2
   *         intersect
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getWhyCollectionsIntersect(CycFort collection1,
          CycFort collection2,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(why-collections-intersect? " + collection1.stringApiValue() + " "
            + collection2.stringApiValue() + " " + makeELMt(
            mt).stringApiValue() + ")");
  }

  /**
   * Gets the English parapharse of the justifications of why CycFort COLLECTION1 and a CycFort
   * COLLECTION2 intersect. see getWhyGenlParaphrase
   *
   * @param collection1 the first collection
   * @param collection2 the second collection
   *
   * @return the English parapharse of the justifications of why CycFort COLLECTION1 and a CycFort
   *         COLLECTION2 intersect
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public List getWhyCollectionsIntersectParaphrase(CycFort collection1,
          CycFort collection2)
          throws UnknownHostException, IOException,
          CycApiException {
    CycList listAnswer = converseList("(with-all-mts (why-collections-intersect? "
            + collection1.stringApiValue() + " "
            + collection2.stringApiValue() + "))");
    List answerPhrases = new ArrayList();

    if (listAnswer.size() == 0) {
      return answerPhrases;
    }

    CycList iter = listAnswer;

    for (int i = 0; i < listAnswer.size(); i++) {
      CycList assertion = (CycList) ((CycList) listAnswer.get(
              i)).first();


      //Log.current.println("assertion: " + assertion);
      answerPhrases.add(getParaphrase(assertion));
    }

    return answerPhrases;
  }

  /**
   * Gets the English parapharse of the justifications of why CycFort COLLECTION1 and a CycFort
   * COLLECTION2 intersect. see getWhyGenlParaphrase
   *
   * @param collection1 the first collection
   * @param collection2 the second collection
   * @param mt the relevant mt
   *
   * @return the English parapharse of the justifications of why CycFort COLLECTION1 and a CycFort
   *         COLLECTION2 intersect
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public List getWhyCollectionsIntersectParaphrase(CycFort collection1,
          CycFort collection2,
          CycObject mt)
          throws UnknownHostException, IOException,
          CycApiException {
    CycList listAnswer = converseList("(with-all-mts (why-collections-intersect? "
            + collection1.stringApiValue() + " "
            + collection2.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
    List answerPhrases = new ArrayList();

    if (listAnswer.size() == 0) {
      return answerPhrases;
    }

    CycList iter = listAnswer;

    for (int i = 0; i < listAnswer.size(); i++) {
      CycList assertion = (CycList) ((CycList) listAnswer.get(
              i)).first();


      //Log.current.println("assertion: " + assertion);
      answerPhrases.add(getParaphrase(assertion));
    }

    return answerPhrases;
  }

  /**
   * Gets the list of the collection leaves (most specific of the all-specs) for a CycFort
   * collection.
   *
   * @param cycFort the given collection
   *
   * @return the list of the collection leaves (most specific of the all-specs) for a CycFort
   *         collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getCollectionLeaves(CycFort cycFort)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(with-all-mts (collection-leaves " + cycFort.stringApiValue() + "))");
  }

  /**
   * Gets the list of the collection leaves (most specific of the all-specs) for a CycFort
   * collection.
   *
   * @param cycFort the given collection
   * @param mt the relevant mt
   *
   * @return the list of the collection leaves (most specific of the all-specs) for a CycFort
   *         collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getCollectionLeaves(CycFort cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(collection-leaves " + cycFort.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets the list of the collections asserted to be disjoint with a CycFort collection.
   *
   * @param cycFort the given collection
   *
   * @return the list of the collections asserted to be disjoint with a CycFort collection
   *
   * @throws IOException if a communication error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList getLocalDisjointWith(CycObject cycFort)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(with-all-mts (local-disjoint-with " + cycFort.stringApiValue() + "))");
  }

  /**
   * Gets the list of the collections asserted to be disjoint with a CycFort collection.
   *
   * @param cycFort the given collection
   * @param mt the relevant mt
   *
   * @return the list of the collections asserted to be disjoint with a CycFort collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getLocalDisjointWith(CycObject cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(local-disjoint-with " + cycFort.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Returns true if CycFort COLLECION1 and CycFort COLLECTION2 are disjoint.
   *
   * @param collection1 the first collection
   * @param collection2 the second collection
   *
   * @return true if CycFort COLLECION1 and CycFort COLLECTION2 are disjoint, otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean areDisjoint(CycObject collection1,
          CycObject collection2)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(with-all-mts (disjoint-with? " + collection1.stringApiValue() + " "
            + collection2.stringApiValue() + "))");
  }

  /**
   * Returns true if CycFort COLLECION1 and CycFort COLLECTION2 are disjoint.
   *
   * @param collection1 the first collection
   * @param collection2 the second collection
   * @param mt the relevant mt
   *
   * @return true if CycFort COLLECION1 and CycFort COLLECTION2 are disjoint, otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean areDisjoint(CycObject collection1,
          CycObject collection2,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(with-all-mts (disjoint-with? " + collection1.stringApiValue() + " "
            + collection2.stringApiValue() + " " + makeELMt(
            mt).stringApiValue() + ")");
  }

  /**
   * Gets the list of the most specific collections (having no subsets) which contain a CycFort
   * term.
   *
   * @param cycFort the given term
   *
   * @return the list of the most specific collections (having no subsets) which contain a CycFort
   *         term
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getMinIsas(CycObject cycFort)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(with-all-mts (min-isa " + cycFort.stringApiValue() + "))");
  }

  /**
   * Gets the list of the most specific collections (having no subsets) which contain a CycFort
   * term.
   *
   * @param cycFort the given term
   * @param mt the relevant mt
   *
   * @return the list of the most specific collections (having no subsets) which contain a CycFort
   *         term
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getMinIsas(CycObject cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(min-isa " + cycFort.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets the list of the asserted instances of a CycFort collection.
   *
   * @param cycFort the given collection
   *
   * @return the list of the instances (who are individuals) of a CycFort collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getInstances(CycObject cycFort)
          throws UnknownHostException, IOException, CycApiException {
    CycList result = converseList("(with-all-mts (instances " + cycFort.stringApiValue() + "))");
    return result;
  }

  /**
   * Gets the list of the asserted instances of a CycFort collection.
   *
   * @param cycFort the given collection
   * @param mt the relevant mt
   *
   * @return the list of the instances (who are individuals) of a CycFort collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getInstances(CycObject cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(instances " + cycFort.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets the list of the instance siblings of a CycFort, for all collections of which it is an
   * instance.
   *
   * @param cycFort the given term
   *
   * @return the list of the instance siblings of a CycFort, for all collections of which it is an
   *         instance
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getInstanceSiblings(CycObject cycFort)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(with-all-mts (instance-siblings " + cycFort.stringApiValue() + "))");
  }

  /**
   * Gets the list of the instance siblings of a CycFort, for all collections of which it is an
   * instance.
   *
   * @param cycFort the given term
   * @param mt the relevant mt
   *
   * @return the list of the instance siblings of a CycFort, for all collections of which it is an
   *         instance
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if an error is returned by the Cyc server
   */
  public CycList getInstanceSiblings(CycObject cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(instance-siblings " + cycFort.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets the list of the collections of which the CycFort is directly and indirectly an instance.
   *
   * @param cycFort the given term
   *
   * @return the list of the collections of which the CycFort is directly and indirectly an
   *         instance
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getAllIsa(CycObject cycFort)
          throws UnknownHostException, IOException, CycApiException {
    String command = "(all-isa-in-any-mt " + cycFort.stringApiValue() + ")";
    CycList result = converseList(command);
    return result;
  }

  /**
   * Gets the list of the collections of which the CycFort is directly and indirectly an instance.
   *
   * @param cycFort the given term
   * @param mt the relevant mt
   *
   * @return the list of the collections of which the CycFort is directly and indirectly an
   *         instance
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getAllIsa(CycObject cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(all-isa " + cycFort.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets a list of all the direct and indirect instances (individuals) for a CycFort collection.
   *
   * @param cycFort the collection for which all the direct and indirect instances (individuals)
   *        are sought
   *
   * @return the list of all the direct and indirect instances (individuals) for the given
   *         collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getAllInstances(CycObject cycFort)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(all-instances-in-all-mts " + cycFort.stringApiValue() + ")");
  }

  /**
   * Gets a list of all the direct and indirect instances for a CycFort collection in
   * the given microtheory.
   *
   * @param cycFort the collection for which all the direct and indirect instances are sought
   * @param mt the relevant mt
   *
   * @return the list of all the direct and indirect instances for the
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error given collection
   */
  public CycList getAllInstances(CycObject cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(all-instances " + cycFort.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets a list of all the direct and indirect quoted instances for a CycFort collection in
   * the given microtheory.
   *
   * @param cycFort the collection for which all the direct and indirect quoted instances are sought
   * @param mt the relevant mt
   *
   * @return the list of all the direct and indirect quoted instances for the CycFort collection in
   * the given microtheory
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error given collection
   */
  public CycList getAllQuotedInstances(final CycObject cycFort, final CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return getAllQuotedInstances(cycFort, mt, 0);
  }

  /**
   * Gets a list of all the direct and indirect quoted instances for a CycFort collection in
   * the given microtheory.
   *
   * @param cycFort the collection for which all the direct and indirect quoted instances are sought
   * @param mt the relevant mt
   *
   * @return the list of all the direct and indirect quoted instances for the CycFort collection in
   * the given microtheory
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error given collection
   * @throws TimeOutException if the calculation times out
   */
  public CycList getAllQuotedInstances(final CycObject cycFort, final CycObject mt,
          final long timeoutMsecs)
          throws UnknownHostException, IOException, CycApiException, TimeOutException {
    final CycVariable queryVariable = CycObjectFactory.makeCycVariable("?QUOTED-INSTANCE");
    final CycFormulaSentence query = CycFormulaSentence.makeCycFormulaSentence(
            getKnownConstantByName("quotedIsa"), queryVariable, cycFort);
    return queryVariable(queryVariable, query, makeELMt(mt), null, timeoutMsecs);
  }

  /**
   * Returns true if CycFort TERM is a instance of CycFort COLLECTION, defaulting to all
   * microtheories.
   *
   * @param term the term
   * @param collectionName the name of the collection
   *
   * @return <tt>true</tt> if CycFort TERM is a instance of the CycFort named by COLLECTION
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isa(CycObject term,
          String collectionName)
          throws UnknownHostException, IOException, CycApiException {
    return isa(term,
            getKnownConstantByName(collectionName));
  }

  /**
   * Returns true if CycFort TERM is a instance of CycFort COLLECTION, defaulting to all
   * microtheories.
   *
   * @param term the term
   * @param collection the collection
   *
   * @return <tt>true</tt> if CycFort TERM is a instance of CycFort COLLECTION
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isa(CycObject term,
          CycFort collection)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(isa-in-any-mt? " + term.stringApiValue() + " "
            + collection.stringApiValue() + ")");
  }

  /**
   * Returns true if CycFort TERM is a instance of CycFort COLLECTION, using the given microtheory.
   * Method implementation optimised for the binary api.
   *
   * @param term the term
   * @param collection the collection
   * @param mt the microtheory in which the ask is performed
   *
   * @return <tt>true</tt> if CycFort TERM is a instance of CycFort COLLECTION
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isa(CycObject term,
          CycObject collection,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    final String command = "(isa? " + term.stringApiValue() + " "
            + collection.stringApiValue() + " " + makeELMt(mt).stringApiValue() + ")";

    return converseBoolean(command);
  }

  /**
   * Returns true if the quoted CycFort TERM is a instance of CycFort COLLECTION, in any microtheory.
   * Method implementation optimised for the binary api.
   *
   * @param term the term
   * @param collection the collection
   *
   * @return <tt>true</tt> if the quoted CycFort TERM is a instance of CycFort COLLECTION
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isQuotedIsa(final CycObject term, final CycObject collection)
          throws UnknownHostException, IOException, CycApiException, TimeOutException {
    return isQuotedIsa(term, collection, 0);
  }

  /**
   * Returns true if the quoted CycFort TERM is a instance of CycFort COLLECTION, in any microtheory.
   * Method implementation optimised for the binary api.
   *
   * @param term the term
   * @param collection the collection
   * @param timeoutMsecs the time in milliseconds to wait before giving up, set to
   * zero to wait  forever.
   *
   * @return <tt>true</tt> if the quoted CycFort TERM is a instance of CycFort COLLECTION
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   * @throws TimeOutException if the calculation times out
   */
  public boolean isQuotedIsa(final CycObject term, final CycObject collection, long timeoutMsecs)
          throws UnknownHostException, IOException, CycApiException, TimeOutException {
    //// Preconditions
    if (term == null) {
      throw new NullPointerException("term must not be null");
    }
    if (collection == null) {
      throw new NullPointerException("collection must not be null");
    }
    final CycFormulaSentence query = CycFormulaSentence.makeCycFormulaSentence(
            getKnownConstantByName("quotedIsa"), term, collection);
    return isQueryTrue(query, inferencePSC, null, timeoutMsecs);
  }

  /**
   * Returns true if the quoted CycFort TERM is a instance of CycFort COLLECTION,
   * in the given inference microtheory.
   *
   * @param term the term
   * @param collection the collection
   * @param mt the inference microtheory
   * set to zero in order to wait forever
   *
   * @return <tt>true</tt> if the quoted CycFort TERM is a instance of CycFort COLLECTION
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isQuotedIsa(final CycObject term, final CycObject collection, final CycObject mt)
          throws UnknownHostException, IOException, CycApiException, TimeOutException {
    return isQuotedIsa(term, collection, mt, 0);
  }

  /**
   * Returns true if the quoted CycFort TERM is a instance of CycFort COLLECTION,
   * in the given inference microtheory.
   *
   * @param term the term
   * @param collection the collection
   * @param mt the inference microtheory
   * @param timeoutMsecs the time in milliseconds to wait before giving up,
   * set to zero in order to wait forever
   *
   * @return <tt>true</tt> if the quoted CycFort TERM is a instance of CycFort COLLECTION
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   * @throws TimeOutException if the calculation times out
   */
  public boolean isQuotedIsa(final CycObject term, final CycObject collection, final CycObject mt, long timeoutMsecs)
          throws UnknownHostException, IOException, CycApiException, TimeOutException {
    if (term == null) {
      throw new NullPointerException("Term must not be null.");
    }
    if (collection == null) {
      throw new NullPointerException("Collection must not be null.");
    }
    if (mt == null) {
      throw new NullPointerException("Microtheory must not be null.");
    }
    final CycFormulaSentence query = CycFormulaSentence.makeCycFormulaSentence(
            getKnownConstantByName("quotedIsa"), term, collection);
    return isQueryTrue(query, makeELMt(mt), null, timeoutMsecs);
  }

  /**
   * Gets the list of the justifications of why CycFort TERM is an instance of CycFort COLLECTION.
   * getWhyIsa("Brazil", "Country") --> "(((#$isa #$Brazil #$IndependentCountry) :TRUE) (#$genls
   * #$IndependentCountry #$Country) :TRUE))
   *
   * @param spec the specialized collection
   * @param genl the more general collection
   *
   * @return the list of the justifications of why CycFort TERM is an instance of CycFort
   *         COLLECTION
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getWhyIsa(CycObject spec,
          CycObject genl)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(with-all-mts (why-isa? " + spec.stringApiValue() + " "
            + genl.stringApiValue() + "))");
  }

  /**
   * Gets the list of the justifications of why CycFort TERM is an instance of CycFort COLLECTION.
   * getWhyIsa("Brazil", "Country") --> "(((#$isa #$Brazil #$IndependentCountry) :TRUE) (#$genls
   * #$IndependentCountry #$Country) :TRUE))
   *
   * @param spec the specialized collection
   * @param genl the more general collection
   * @param mt the relevant mt
   *
   * @return the list of the justifications of why CycFort TERM is an instance of CycFort
   *         COLLECTION
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getWhyIsa(CycObject spec,
          CycObject genl,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(why-isa? " + spec.stringApiValue() + " " + genl.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets the English parapharse of the justifications of why CycFort TERM is an instance of
   * CycFort COLLECTION. getWhyGenlParaphase("Brazil", "Country") --> "Brazil is an independent
   * country" "an  independent country is a kind of country"
   *
   * @param spec the specialized collection
   * @param genl the more general collection
   *
   * @return the English parapharse of the justifications of why CycFort TERM is an instance of
   *         CycFort COLLECTION
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public List getWhyIsaParaphrase(CycObject spec,
          CycObject genl)
          throws IOException, CycApiException {
    String command = "(with-all-mts (why-isa? " + spec.stringApiValue() + " "
            + genl.stringApiValue() + "))";
    CycList listAnswer = converseList(command);
    List answerPhrases = new ArrayList();

    if (listAnswer.size() == 0) {
      return answerPhrases;
    }

    for (int i = 0; i < listAnswer.size(); i++) {
      CycList assertion = (CycList) ((CycList) listAnswer.get(
              i)).first();
      answerPhrases.add(getParaphrase(assertion));
    }

    return answerPhrases;
  }

  /**
   * Gets the English parapharse of the justifications of why CycFort TERM is an instance of
   * CycFort COLLECTION. getWhyGenlParaphase("Brazil", "Country") --> "Brazil is an independent
   * country" "an  independent country is a kind of country"
   *
   * @param spec the specialized collection
   * @param genl the more general collection
   * @param mt the relevant mt
   *
   * @return the English parapharse of the justifications of why CycFort TERM is an instance of
   *         CycFort COLLECTION
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public List getWhyIsaParaphrase(CycFort spec,
          CycFort genl,
          CycObject mt)
          throws IOException, CycApiException {
    String command = "(why-isa? " + spec.stringApiValue() + " " + genl.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")";
    CycList listAnswer = converseList(command);
    List answerPhrases = new ArrayList();

    if (listAnswer.size() == 0) {
      return answerPhrases;
    }

    for (int i = 0; i < listAnswer.size(); i++) {
      CycList assertion = (CycList) ((CycList) listAnswer.get(
              i)).first();
      answerPhrases.add(getParaphrase(assertion));
    }

    return answerPhrases;
  }

  /**
   * Gets the list of the genlPreds for a CycConstant predicate.
   *
   * @param predicate the given predicate term
   *
   * @return the list of the more general predicates for the given predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getGenlPreds(final CycObject predicate)
          throws UnknownHostException, IOException, CycApiException {
    if (predicate instanceof CycList) {
      final String script =
              "(clet ((canonicalized-predicate (canonicalize-term " + predicate.stringApiValue() + ")))"
              + "  (pif (fort-p canonicalized-predicate)"
              + "    (remove-duplicates (with-all-mts (genl-predicates canonicalized-predicate)))"
              + "    nil))";
      return converseList(script);
    } else {
      return converseList("(remove-duplicates (with-all-mts (genl-predicates "
              + predicate.stringApiValue() + ")))");
    }
  }

  /**
   * Gets the list of the genlPreds for a CycConstant predicate.
   *
   * @param predicate the given predicate term
   * @param mt the relevant mt
   *
   * @return the list of the more general predicates for the given predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getGenlPreds(final CycObject predicate,
          final CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    if (predicate instanceof CycList) {
      final String script =
              "(clet ((canonicalized-predicate (canonicalize-term " + predicate.stringApiValue() + ")))"
              + "  (pif (fort-p canonicalized-predicate)"
              + "    (remove-duplicates (with-all-mts (genl-predicates canonicalized-predicate " + makeELMt(mt).stringApiValue() + ")))"
              + "    nil))";
      return converseList(script);
    } else {
      return converseList("(genl-predicates " + predicate.stringApiValue() + " " + makeELMt(mt).stringApiValue() + ")");
    }
  }

  /**
   * Gets the list of all of the genlPreds for a CycConstant predicate, using an upward closure.
   *
   * @param predicate the predicate for which all the genlPreds are obtained
   *
   * @return a list of all of the genlPreds for a CycConstant predicate, using an upward closure
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getAllGenlPreds(CycConstant predicate)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(remove-duplicates (with-all-mts (all-genl-predicates "
            + predicate.stringApiValue() + ")))");
  }

  /**
   * Gets the list of all of the genlPreds for a CycConstant predicate, using an upward closure.
   *
   * @param predicate the predicate for which all the genlPreds are obtained
   * @param mt the relevant mt
   *
   * @return a list of all of the genlPreds for a CycConstant predicate, using an upward closure
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getAllGenlPreds(CycConstant predicate,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(all-genl-predicates " + predicate.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets the list of all of the direct and indirect specs-preds for the given predicate in all
   * microtheories.
   *
   * @param cycFort the predicate
   *
   * @return the list of all of the direct and indirect spec-preds for the given predicate in all
   *         microtheories.
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getAllSpecPreds(CycFort cycFort)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(remove-duplicates (with-all-mts (all-spec-predicates "
            + cycFort.stringApiValue() + ")))");
  }

  /**
   * Gets the list of all of the direct and indirect specs-preds for the given predicate in the
   * given microtheory.
   *
   * @param cycFort the predicate
   * @param mt the microtheory
   *
   * @return the list of all of the direct and indirect spec-preds for the given predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getAllSpecPreds(CycFort cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(all-spec-predicates " + cycFort.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets the list of all of the direct and indirect specs-inverses for the given predicate in all
   * microtheories.
   *
   * @param cycFort the predicate
   *
   * @return the list of all of the direct and indirect spec-inverses for the given predicate in
   *         all microtheories.
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getAllSpecInverses(CycFort cycFort)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(remove-duplicates (with-all-mts (all-spec-inverses "
            + cycFort.stringApiValue() + ")))");
  }

  /**
   * Gets the list of all of the direct and indirect specs-inverses for the given predicate in the
   * given microtheory.
   *
   * @param cycFort the predicate
   * @param mt the microtheory
   *
   * @return the list of all of the direct and indirect spec-inverses for the given predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getAllSpecInverses(CycFort cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(all-spec-inverses " + cycFort.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets the list of all of the direct and indirect specs-mts for the given microtheory in mt-mt
   * (currently #$UniversalVocabularyMt).
   *
   * @param mt the microtheory
   *
   * @return the list of all of the direct and indirect specs-mts for the given microtheory in
   *         mt-mt (currently #$UniversalVocabularyMt)
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getAllSpecMts(CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(all-spec-mts " + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets a list of the arg1Isas for a CycConstant predicate.
   *
   * @param cycObject the predicate for which argument 1 contraints are sought.
   *
   * @return the list of the arg1Isas for a CycConstant predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getArg1Isas(CycObject cycObject)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    return converseList("(remove-duplicates (with-all-mts (arg1-isa "
            + cycObject.stringApiValue() + ")))");
  }

  /**
   * Gets the list of the arg1Isas for a CycConstant predicate given an mt.
   *
   * @param predicate the predicate for which argument 1 contraints are sought.
   * @param mt the relevant microtheory
   *
   * @return the list of the arg1Isas for a CycConstant predicate given an mt
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getArg1Isas(final CycObject cycObject,
          final CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    if (mt == null) {
      throw new NullPointerException("mt must not be null");
    }
    return converseList("(arg1-isa " + cycObject.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets a list of the arg2Isas for a CycConstant predicate.
   *
   * @param cycObject the predicate for which argument 2 contraints are sought.
   *
   * @return the list of the arg1Isas for a CycConstant predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getArg2Isas(CycObject cycObject)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    return converseList("(remove-duplicates (with-all-mts (arg2-isa "
            + cycObject.stringApiValue() + ")))");
  }

  /**
   * Gets the list of the arg2Isas for a CycConstant predicate given an mt.
   *
   * @param cycObject the predicate for which argument 2 contraints are sought.
   * @param mt the relevant microtheory
   *
   * @return the list of the arg2Isas for a CycConstant predicate given an mt
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getArg2Isas(CycObject cycObject,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    if (mt == null) {
      throw new NullPointerException("mt must not be null");
    }
    return converseList("(arg2-isa " + cycObject.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets a list of the arg3Isas for a CycConstant predicate.
   *
   * @param predicate the predicate for which argument 3 contraints are sought.
   *
   * @return the list of the arg1Isas for a CycConstant predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getArg3Isas(CycFort predicate)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(remove-duplicates (with-all-mts (arg3-isa "
            + predicate.stringApiValue() + ")))");
  }

  /**
   * Gets the list of the arg3Isas for a CycConstant predicate given an mt.
   *
   * @param predicate the predicate for which argument 3 contraints are sought.
   * @param mt the relevant microtheory
   *
   * @return the list of the arg1Isas for a CycConstant predicate given an mt
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getArg3Isas(CycFort predicate,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(arg3-isa " + predicate.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets a list of the arg4Isas for a CycConstant predicate.
   *
   * @param predicate the predicate for which argument 4 contraints are sought.
   *
   * @return the list of the arg4Isas for a CycConstant predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getArg4Isas(CycFort predicate)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(remove-duplicates (with-all-mts (arg4-isa "
            + predicate.stringApiValue() + ")))");
  }

  /**
   * Gets the list of the arg4Isas for a CycConstant predicate given an mt.
   *
   * @param predicate the predicate for which argument 4 contraints are sought.
   * @param mt the relevant microtheory
   *
   * @return the list of the arg4Isas for a CycConstant predicate given an mt
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getArg4Isas(CycFort predicate,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(arg4-isa " + predicate.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets a list of the argNIsas for a CycConstant predicate.
   *
   * @param predicate the predicate for which argument N contraints are sought.
   * @param argPosition the argument position of argument N
   *
   * @return the list of the argNIsas for a CycConstant predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getArgNIsas(CycFort predicate,
          int argPosition)
          throws UnknownHostException, IOException, CycApiException {
    String command = "(remove-duplicates \n" + "  (with-all-mts \n" + "    (argn-isa "
            + predicate.stringApiValue() + " " + Integer.toString(
            argPosition) + ")))";

    return converseList(command);
  }

  /**
   * Gets the list of the argNIsas for a CycConstant predicate given an mt.
   *
   * @param predicate the predicate for which argument contraints are sought.
   * @param argPosition the argument position of argument N
   * @param mt the relevant microtheory
   *
   * @return the list of the arg1Isas for a CycConstant predicate given an mt
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getArgNIsas(CycFort predicate,
          int argPosition,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    String command = "(remove-duplicates \n" + "  (with-all-mts \n" + "    (argn-isa \n"
            + "      " + predicate.stringApiValue() + "      "
            + Integer.toString(argPosition) + "      " + makeELMt(
            mt).stringApiValue()
            + ")))";

    return converseList(command);
  }

  /**
   * Gets the list of the interArgIsa1-2 isa constraint pairs for the given predicate.  Each item
   * of the returned list is a pair (arg1-isa arg2-isa) which means that when (#$isa arg1
   * arg1-isa) holds, (#$isa arg2 arg2-isa) must also hold for (predicate arg1 arg2 ..) to be well
   * formed.
   *
   * @param predicate the predicate for interArgIsa1-2 contraints are sought.
   *
   * @return the list of the interArgIsa1-2 isa constraint pairs for the given predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getInterArgIsa1_2s(CycFort predicate)
          throws UnknownHostException, IOException, CycApiException {
    String command = "(remove-duplicates \n" + "  (with-all-mts \n" + "    (inter-arg-isa1-2 "
            + predicate.stringApiValue() + ")))";

    return converseList(command);
  }

  /**
   * Gets the list of the interArgIsa1-2 isa constraint pairs for the given predicate.  Each item
   * of the returned list is a pair (arg1-isa arg2-isa) which means that when (#$isa arg1
   * arg1-isa) holds, (#$isa arg2 arg2-isa) must also hold for (predicate arg1 arg2 ..) to be well
   * formed.
   *
   * @param predicate the predicate for interArgIsa1-2 contraints are sought.
   * @param mt the relevant inference microtheory
   *
   * @return the list of the interArgIsa1-2 isa constraint pairs for the given predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getInterArgIsa1_2s(CycFort predicate,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    String command = "(remove-duplicates \n" + "  (with-all-mts \n" + "    (inter-arg-isa1-2 "
            + "      " + predicate.stringApiValue() + "      "
            + makeELMt(mt).stringApiValue() + ")))";

    return converseList(command);
  }

  /**
   * Gets the list of the interArgIsa1-2 isa constraints for arg2, given the predicate and arg1.
   *
   * @param predicate the predicate for interArgIsa1-2 contraints are sought.
   * @param arg1 the argument in position 1
   *
   * @return the list of the interArgIsa1-2 isa constraints for arg2, given the predicate and arg1
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getInterArgIsa1_2_forArg2(CycFort predicate,
          CycFort arg1)
          throws UnknownHostException, IOException, CycApiException {
    CycList result = new CycList();
    ListIterator constraintPairs = getInterArgIsa1_2s(predicate).listIterator();

    while (constraintPairs.hasNext()) {
      CycList pair = (CycList) constraintPairs.next();

      if (pair.first().equals(arg1)) {
        result.add(pair.second());
      }
    }

    return result;
  }

  /**
   * Gets the list of the interArgIsa1-2 isa constraints for arg2, given the predicate and arg1.
   *
   * @param predicate the predicate for interArgIsa1-2 contraints are sought.
   * @param arg1 the argument in position 1
   * @param mt the relevant inference microtheory
   *
   * @return the list of the interArgIsa1-2 isa constraints for arg2, given the predicate and arg1
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getInterArgIsa1_2_forArg2(CycFort predicate,
          CycFort arg1,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    CycList result = new CycList();
    ListIterator constraintPairs = getInterArgIsa1_2s(predicate,
            mt).listIterator();

    while (constraintPairs.hasNext()) {
      CycList pair = (CycList) constraintPairs.next();

      if (pair.first().equals(arg1)) {
        result.add(pair.second());
      }
    }

    return result;
  }

  /**
   * Gets the list of the resultIsa for a CycConstant function.
   *
   * @param function the given function term
   *
   * @return the list of the resultIsa for a CycConstant function
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getResultIsas(CycFort function)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(remove-duplicates (with-all-mts (result-isa "
            + function.stringApiValue() + ")))");
  }

  /**
   * Gets the list of the resultIsa for a CycConstant function.
   *
   * @param function the given function term
   * @param mt the relevant mt
   *
   * @return the list of the resultIsa for a CycConstant function
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getResultIsas(CycFort function,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(result-isa " + function.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets the list of the argNGenls for a CycConstant predicate.
   *
   * @param predicate the given predicate term
   * @param argPosition the argument position for which the genls argument constraints are sought
   *        (position 1 = first argument)
   *
   * @return the list of the argNGenls for a CycConstant predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getArgNGenls(CycFort predicate,
          int argPosition)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(remove-duplicates (with-all-mts (argn-genl "
            + predicate.stringApiValue() + " " + argPosition + ")))");
  }

  /**
   * Gets the list of the argNGenls for a CycConstant predicate.
   *
   * @param predicate the given predicate term
   * @param argPosition the argument position for which the genls argument constraints are sought
   *        (position 1 = first argument)
   * @param mt the relevant mt
   *
   * @return the list of the argNGenls for a CycConstant predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getArgNGenls(CycFort predicate,
          int argPosition,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(argn-genl " + predicate.stringApiValue() + " " + argPosition + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets a list of the arg1Formats for a CycConstant predicate.
   *
   * @param cycObject the given predicate term
   *
   * @return a list of the arg1Formats for a CycConstant predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getArg1Formats(CycObject cycObject)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    return converseList("(with-all-mts (arg1-format " + cycObject.stringApiValue() + "))");
  }

  /**
   * Gets a list of the arg1Formats for a CycConstant predicate.
   *
   * @param cycObject the given predicate term
   * @param mt the relevant mt
   *
   * @return a list of the arg1Formats for a CycConstant predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getArg1Formats(CycObject cycObject,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    return converseList("(arg1-format " + cycObject.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets a list of the arg2Formats for a CycConstant predicate.
   *
   * @param cycObject the given predicate term
   *
   * @return a list of the arg2Formats for a CycConstant predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getArg2Formats(final CycObject cycObject)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    return converseList("(with-all-mts (arg2-format " + cycObject.stringApiValue() + "))");
  }

  /**
   * Gets a list of the arg2Formats for a CycConstant predicate.
   *
   * @param cycObject the given predicate term
   * @param mt the relevant mt
   *
   * @return a list of the arg2Formats for a CycConstant predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getArg2Formats(final CycObject cycObject,
          final CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    return converseList("(arg2-format " + cycObject.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets a list of the disjointWiths for a CycFort.
   *
   * @param cycObject the given collection term
   *
   * @return a list of the disjointWiths for a CycFort
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getDisjointWiths(CycObject cycObject)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    return converseList("(remove-duplicates (with-all-mts (local-disjoint-with "
            + cycObject.stringApiValue() + ")))");
  }

  /**
   * Gets a list of the disjointWiths for a CycFort.
   *
   * @param cycFort the given collection term
   * @param mt the relevant mt
   *
   * @return a list of the disjointWiths for a CycFort
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getDisjointWiths(CycFort cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList("(local-disjoint-with " + cycFort.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Gets a list of the coExtensionals for a CycFort.  Limited to 120 seconds.
   *
   * @param cycObject the given collection term
   *
   * @return a list of the coExtensionals for a CycFort
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getCoExtensionals(CycObject cycObject)
          throws UnknownHostException, IOException, CycApiException {
    return getCoExtensionals(cycObject, 0);
  }

  /**
   * Gets a list of the coExtensionals for a CycFort.  Limited to 120 seconds.
   *
   * @param cycObject the given collection term
   * @param timeoutMsecs the time to wait before giving up
   *
   * @return a list of the coExtensionals for a CycFort
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   * @throws TimeOutException if the calculation times out
   */
  public CycList getCoExtensionals(CycObject cycObject, long timeoutMsecs)
          throws UnknownHostException, IOException, CycApiException, TimeOutException {
    return getCoExtensionals(cycObject, inferencePSC, timeoutMsecs);
  }

  /**
   * Gets a list of the coExtensionals for a CycFort.  Limited to 120 seconds.
   *
   * @param cycObject the given collection term
   * @param mt the microtheory
   *
   * @return a list of the coExtensionals for a CycFort
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getCoExtensionals(CycObject cycObject, CycObject mt)
          throws UnknownHostException, IOException, CycApiException, TimeOutException {
    return getCoExtensionals(cycObject, mt, 0);
  }

  /**
   * Gets a list of the coExtensionals for a CycFort.
   *
   * @param cycFort the given collection term
   * @param mt the relevant mt for inference
   *
   * @return a list of the coExtensionals for a CycFort
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getCoExtensionals(CycObject cycObject,
          CycObject mt, long timeoutMsecs)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    CycList answer = null;
    try {
      final String queryString =
              "(#$and"
              + "  (#$different  " + cycObject.cyclify() + " ?X) "
              + "  (#$or (#$coExtensional " + cycObject.cyclify() + " ?X) "
              + "    (#$coextensionalSetOrCollections " + cycObject.cyclify() + " ?X)))";
      final CycFormulaSentence query = makeCycSentence(queryString);
      final CycVariable queryVariable = CycObjectFactory.makeCycVariable("?X");
      answer = queryVariable(queryVariable, query, makeELMt(mt), null, timeoutMsecs);
    } catch (IOException e) {
      Log.current.println("getCoExtensionals - ignoring:\n" + e.getMessage());
      return new CycList();
    }

    return canonicalizeList(answer);
  }

  /**
   * Returns true if the given term is a microtheory.
   *
   * @param cycFort the constant for determination as a microtheory
   *
   * @return <tt>true</tt> iff cycConstant is a microtheory
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isMicrotheory(CycFort cycFort)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(isa-in-any-mt? " + cycFort.stringApiValue() + " #$Microtheory)");
  }

  /**
   * Returns true if the given term is a Collection.
   *
   * @param cycObject the given term
   *
   * @return true if the given term is a Collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isCollection(final CycObject cycObject)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    return converseBoolean("(isa-in-any-mt? " + cycObject.stringApiValue() + " #$Collection)");
  }

  /**
   * Returns true if the given term is a Collection.
   *
   * @param cycObject the given term
   * @param mt the inference microtheory
   *
   * @return true if the given term is a Collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isCollection(final CycObject cycObject, final CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    if (mt == null) {
      throw new NullPointerException("mt must not be null");
    }
    return converseBoolean("(isa? " + cycObject.stringApiValue() + " #$Collection " + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Returns true if the given object is a Collection.
   *
   * @param term the given term
   *
   * @return true if the given term is a Collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isCollection(final Object obj)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (obj == null) {
      throw new NullPointerException("term must not be null");
    }
    if (obj instanceof CycObject) {
      return isCollection((CycObject) obj);
    } else {
      return false;
    }
  }

  /**
   * Returns true if the given term is a collection, implemented by a cache to avoid asking the same
   * question twice from the KB.
   *
   * @param cycObject the given term
   *
   * @return true if the given term is a collection
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isCollection_Cached(CycObject cycObject)
          throws IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    Boolean isCollection = isCollectionCache.get(cycObject);

    if (isCollection != null) {
      return isCollection.booleanValue();
    }

    final boolean answer = isCollection(cycObject);
    isCollectionCache.put(cycObject, answer);

    return answer;
  }

  public boolean isCollection_Cached(Object term)
          throws IOException, CycApiException {
    if (term instanceof CycObject) {
      return isCollection_Cached((CycObject) term);
    } else {
      return false;
    }
  }

  /**
   * Returns true if the given term is an Individual.
   *
   * @param cycObject the given term
   *
   * @return true if the given term is an Individual
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isIndividual(final CycObject cycObject)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    return converseBoolean("(isa-in-any-mt? " + cycObject.stringApiValue() + " #$Individual)");
  }

  /**
   * Returns true if the given term is an Individual.
   *
   * @param cycObject the given term
   * @param mt the inference microtheory
   *
   * @return true if the given term is an Individual
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isIndividual(final CycObject cycObject, final CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    if (mt == null) {
      throw new NullPointerException("mt must not be null");
    }
    return converseBoolean("(isa? " + cycObject.stringApiValue() + " #$Individual " + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Returns true if the given is a Function.
   *
   * @param cycFort the given term
   *
   * @return true if the given is a Function
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isFunction(CycFort cycFort)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(isa-in-any-mt? " + cycFort.stringApiValue()
            + " #$Function-Denotational)");
  }

  /**
   * Returns true if the given term is an evaluatable predicate.
   *
   * @param predicate the given term
   *
   * @return true if true if the given term is an evaluatable predicate, otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isEvaluatablePredicate(CycFort predicate)
          throws UnknownHostException, IOException, CycApiException {
    final String command = makeSubLStmt("with-all-mts", makeNestedSubLStmt("evaluatable-predicate?", predicate));
    return converseBoolean(command);
  }

  /**
   * Returns true if cycObject is a Predicate.
   *
   * @param cycObject the term for determination as a predicate
   *
   * @return true if cycObject is a Predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isPredicate(CycObject cycObject)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    return converseBoolean("(isa-in-any-mt? " + cycObject.stringApiValue() + " #$Predicate)");
  }

  /**
   * Returns true if cycObject is a Predicate.
   *
   * @param cycObject the term for determination as a predicate
   * @param mt the inference microtheory
   *
   * @return true if cycObject is a Predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isPredicate(final CycObject cycObject, final CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    if (mt == null) {
      throw new NullPointerException("mt must not be null");
    }
    return converseBoolean("(isa? " + cycObject.stringApiValue() + " #$Predicate " + makeELMt(mt).stringApiValue() + ")");
  }

  public boolean isPredicate(final Object object, final CycObject mt) throws UnknownHostException, IOException, CycApiException {
    if (object == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    if (object instanceof CycObject) {
      return isPredicate((CycObject) object, mt);
    } else {
      return false;
    }
  }

  public boolean isPredicate(final Object object) throws UnknownHostException, IOException, CycApiException {
    if (object == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    if (object instanceof CycObject) {
      return isPredicate((CycObject) object);
    } else {
      return false;
    }
  }

  /**
   * Returns true if the given term is a UnaryPredicate.
   *
   * @param cycObject the given term
   *
   * @return true if true if the given term is a UnaryPredicate, otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isUnaryPredicate(CycObject cycObject)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    return converseBoolean("(isa-in-any-mt? " + cycObject.stringApiValue()
            + " #$UnaryPredicate)");
  }

  /**
   * Returns true if the given term is a UnaryPredicate.
   *
   * @param cycObject the given term
   * @param mt the inference microtheory
   *
   * @return true if true if the given term is a UnaryPredicate, otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isUnaryPredicate(CycObject cycObject, final CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    if (mt == null) {
      throw new NullPointerException("mt must not be null");
    }
    return converseBoolean("(isa? " + cycObject.stringApiValue()
            + " #$UnaryPredicate " + makeELMt(mt).stringApiValue() + ")");
  }

  protected void verifyPossibleDenotationalTerm(CycObject cycObject) throws IllegalArgumentException {
    if (!(cycObject instanceof CycDenotationalTerm || cycObject instanceof CycList)) {
      throw new IllegalArgumentException("cycObject must be a Cyc denotational term " + cycObject.cyclify());
    }
  }

  /**
   * Returns true if the cyc object is a BinaryPredicate.
   *
   * @param cycObject the given cyc object
   *
   * @return true if cycObject is a BinaryPredicate, otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isBinaryPredicate(final CycObject cycObject)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    return converseBoolean("(binary-predicate? " + cycObject.stringApiValue() + ")");
  }

  /**
   * Returns true if the cyc object is a BinaryPredicate.
   *
   * @param cycObject the given cyc object
   * @param mt the inference microtheory
   *
   * @return true if cycObject is a BinaryPredicate, otherwise false
   *
   * @obsolete mt is not necessary.
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isBinaryPredicate(final CycObject cycObject, final CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return isBinaryPredicate(cycObject);
  }

  /**
   * Returns true if the candidate name uses valid CycConstant characters.
   *
   * @param candidateName the candidate name
   *
   * @return true if the candidate name uses valid CycConstant characters
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isValidConstantName(String candidateName)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(new-constant-name-spec-p \"" + candidateName + "\")");
  }

  /**
   * Returns true if the candidate name is an available CycConstant name, case insensitive.
   *
   * @param candidateName the candidate name
   *
   * @return true if the candidate name uses valid CycConstant characters
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isConstantNameAvailable(String candidateName)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(constant-name-available \"" + candidateName + "\")");
  }

  /**
   * Returns true if term is a quotedCollection, in any microtheory
   *
   * @param cycFort the given CycFort term
   *
   * @return true if term is a quotedCollection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   * @deprecated
   */
  public boolean isQuotedCollection(CycFort cycFort)
          throws UnknownHostException, IOException, CycApiException {
    throw new CycApiException("quotedCollection is no longer supported, see Quote");
  }

  /**
   * Returns true if term is a quotedCollection is a quotedCollection.
   *
   * @param cycFort the given CycFort term
   * @param mt the microtheory in which the query is made
   *
   * @return true if term is a quotedCollection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   * @deprecated
   */
  public boolean isQuotedCollection(CycFort cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    throw new CycApiException("quotedCollection is no longer supported, see Quote");
  }

  /** @return true iff expression is free of all variables.
   * @throws IOException if a data communication error occurs
   */
  public boolean isGround(CycObject expression) throws IOException {
    return converseBoolean("(ground? " + DefaultCycObject.stringApiValue(expression) + ")");
  }

  /**
   * Returns true if cycConstant is a PublicConstant.
   *
   * @param cycConstant the given constant
   *
   * @return true if cycConstant is a PublicConstant
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isPublicConstant(CycConstant cycConstant)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(isa-in-any-mt? " + cycConstant.stringApiValue()
            + " #$PublicConstant)");
  }

  /**
   * Gets a list of the public Cyc constants.
   *
   * @return a list of the public Cyc constants
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getPublicConstants()
          throws UnknownHostException, IOException, CycApiException {
    // #$PublicConstant
    return getKbSubset(getKnownConstantByGuid("bd7abd90-9c29-11b1-9dad-c379636f7270"));
  }

  /**
   * Gets a list of the elements of the given CycKBSubsetCollection.
   *
   * @param cycKbSubsetCollection the given CycKBSubsetCollection
   *
   * @return a list of the elements of the given CycKBSubsetCollection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getKbSubset(CycFort cycKbSubsetCollection)
          throws UnknownHostException, IOException, CycApiException {
    CycList answer = converseList("(ask-template '?X '(#$isa ?X "
            + cycKbSubsetCollection.stringApiValue() + ") #$EverythingPSC)");

    return canonicalizeList(answer);
  }

  /**
   * Renames the given constant.
   *
   * @param cycConstant the constant term to be renamed
   * @param newName the new constant name
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public synchronized void rename(final CycConstant cycConstant, final String newName)
          throws UnknownHostException, IOException, CycApiException {
    String command = wrapBookkeeping("(ke-rename-now " + cycConstant.stringApiValue() + "\"" + newName + "\")");
    Object result = converseObject(command);
    if (result.equals(CycObjectFactory.nil)) {
      throw new CycApiException(newName + " is an invalid new name for " + cycConstant.cyclify());
    }
    CycObjectFactory.removeCaches(cycConstant);
    cycConstant.setName(newName);
    CycObjectFactory.addCycConstantCache(cycConstant);
  }

  /**
   * Kills a Cyc constant.  If CYCCONSTANT is a microtheory, then all the contained assertions are
   * deleted from the KB, the Cyc Truth Maintenance System (TML) will automatically delete any
   * derived assertions whose sole support is the killed term(s).
   *
   * @param cycConstant the constant term to be removed from the KB
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public synchronized void kill(CycConstant cycConstant)
          throws UnknownHostException, IOException, CycApiException {
    String command = wrapBookkeeping("(ke-kill-now " + cycConstant.stringApiValue() + ")");
    converseBoolean(command);
    CycObjectFactory.removeCaches(cycConstant);
  }

  /**
   * Kills a Cyc constant without issuing a transcript operation. If CYCCONSTANT is a microtheory,
   * then all the contained assertions are deleted from the KB, the Cyc Truth Maintenance System
   * (TMS) will automatically delete any derived assertions whose sole support is the killed
   * term(s).
   *
   * @param cycConstant the constant term to be removed from the KB
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public synchronized void killWithoutTranscript(CycConstant cycConstant)
          throws UnknownHostException, IOException, CycApiException {
    String command = wrapBookkeeping("(cyc-kill " + cycConstant.stringApiValue() + ")");
    converseBoolean(command);
    CycObjectFactory.removeCaches(cycConstant);
  }

  /**
   * Kills the given Cyc constants.  If CYCCONSTANT is a microtheory, then all the contained
   * assertions are deleted from the KB, the Cyc Truth Maintenance System (TMS) will automatically
   * delete any derived assertions whose sole support is the killed term(s).
   *
   * @param cycConstants the list of constant terms to be removed from the KB
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public synchronized void kill(CycConstant[] cycConstants)
          throws UnknownHostException, IOException, CycApiException {
    for (int i = 0; i < cycConstants.length; i++) {
      kill(cycConstants[i]);
    }
  }

  /**
   * Kills the given Cyc constants.  If CYCCONSTANT is a microtheory, then all the contained
   * assertions are deleted from the KB, the Cyc Truth Maintenance System (TMS) will automatically
   * delete any derived assertions whose sole support is the killed term(s).
   *
   * @param cycConstants the list of constant terms to be removed from the KB
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public synchronized void kill(List cycConstants)
          throws UnknownHostException, IOException, CycApiException {
    for (int i = 0; i < cycConstants.size(); i++) {
      kill((CycConstant) cycConstants.get(i));
    }
  }

  /**
   * Kills a Cyc NART (Non Atomic Reified Term).  If CYCFORT is a microtheory, then all the
   * contained assertions are deleted from the KB, the Cyc Truth Maintenance System (TMS) will
   * automatically delete any derived assertions whose sole support is the killed term(s).
   *
   * @param cycFort the NART term to be removed from the KB
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public synchronized void kill(CycFort cycFort)
          throws UnknownHostException, IOException, CycApiException {
    if (cycFort instanceof CycConstant) {
      kill((CycConstant) cycFort);
    } else {
      String command = wrapBookkeeping("(ke-kill-now " + cycFort.stringApiValue() + ")");
      converseBoolean(command);
    }
  }

  /**
   * Returns the value of the Cyclist.
   *
   * @return the value of the Cyclist
   */
  public CycFort getCyclist() {
    return cyclist;
  }

  /**
   * Sets the value of the Cyclist, whose identity will be attached via #$myCreator bookkeeping
   * assertions to new KB entities created in this session.
   *
   * @param cyclistName the name of the cyclist term
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void setCyclist(String cyclistName)
          throws UnknownHostException, IOException, CycApiException {
    if (cyclistName == null || "".equals(cyclistName)) {
      throw new CycApiException("Invalid cyclist name specified.");
    }
    Object term = getHLCycTerm(cyclistName);
    CycFort newCyclist = null;
    if (term instanceof CycFort) {
      newCyclist = (CycFort) term;
    } else {
      // see if it is a blank name
      newCyclist = find(cyclistName);
    }
    if (newCyclist == null) {
      throw new CycApiException("Cannot interpret " + cyclistName + " as a cyclist.");
    }
    setCyclist(newCyclist);
  }

  /**
   * Sets the value of the Cyclist, whose identity will be attached via #$myCreator bookkeeping
   * assertions to new KB entities created in this session.
   *
   * @param cyclist the cyclist term
   */
  public void setCyclist(CycFort cyclist) {
    this.cyclist = cyclist;
  }

  /**
   * Returns the value of the project (KE purpose).
   *
   * @return he value of the project (KE purpose)
   */
  public CycFort getKePurpose() {
    return project;
  }

  /**
   * Sets the value of the KE purpose, whose project name will be attached via #$myCreationPurpose
   * bookkeeping assertions to new KB entities created in this session.
   *
   * @param projectName the string name of the KE Purpose term
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void setKePurpose(String projectName)
          throws UnknownHostException, IOException, CycApiException {
    setKePurpose((CycFort) getHLCycTerm(projectName));
  }

  /**
   * Sets the value of the KE purpose, whose project name will be attached via #$myCreationPurpose
   * bookkeeping assertions to new KB entities created in this session.
   *
   * @param project the KE Purpose term
   */
  public void setKePurpose(CycFort project) {
    this.project = project;
  }

  /**
   * Asserts the given sentence, and then places it on the transcript queue.
   *
   * @param sentence the given sentence for assertion
   * @param mt the microtheory in which the assertion is placed
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertWithTranscript(CycList sentence,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    assertWithTranscript(sentence.stringApiValue(), mt);
  }

  /**
   * Asserts the given sentence, and then places it on the transcript queue.
   *
   * @param sentence the given sentence for assertion
   * @param mt the microtheory in which the assertion is placed
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertWithTranscript(String sentence,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    assertSentence(sentence, makeELMt(mt), false, true);
  }

  /**
   * Asserts the given sentence with bookkeeping, and then places it on the transcript queue.
   *
   * @param sentence the given sentence for assertion
   * @param mt the microtheory in which the assertion is placed
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertWithTranscriptAndBookkeeping(String sentence, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    assertWithTranscriptAndBookkeeping(makeCycSentence(sentence), mt);
  }

  /**
   * Asserts the given sentence with bookkeeping, and then places it on the transcript queue.
   *
   * @param sentence the given sentence for assertion
   * @param mt the microtheory in which the assertion is placed
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertWithTranscriptAndBookkeeping(CycFormulaSentence sentence, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    assertWithTranscriptAndBookkeepingInternal(sentence, mt);
  }

  /**
   * Asserts the given sentence with bookkeeping, and then places it on the transcript queue.
   *
   * @param sentence the given sentence for assertion
   * @param mt the microtheory in which the assertion is placed
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertWithTranscriptAndBookkeeping(CycList sentence, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    assertWithTranscriptAndBookkeepingInternal(sentence, mt);
  }

  /**
   * Asserts the given sentence with bookkeeping, and then places it on the transcript queue.
   *
   * @param sentence the given sentence for assertion
   * @param mt the microtheory in which the assertion is placed
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  private void assertWithTranscriptAndBookkeepingInternal(CycObject sentence, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    assertSentence(sentence.stringApiValue(), makeELMt(mt), true, true);
  }

  /**
   * Asserts the given sentence with bookkeeping and without placing it on the transcript queue.
   *
   * @param sentence the given sentence for assertion
   * @param mt the microtheory in which the assertion is placed
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertWithBookkeepingAndWithoutTranscript(CycList sentence, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    assertWithBookkeepingAndWithoutTranscript(sentence.stringApiValue(), mt);
  }

  /**
   * Asserts the given sentence with bookkeeping and without placing it on the transcript queue.
   *
   * @param sentence the given sentence for assertion
   * @param mt the microtheory in which the assertion is placed
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertWithBookkeepingAndWithoutTranscript(String sentence, CycObject mt)
          throws UnknownHostException, IOException,
          CycApiException {
    assertSentence(sentence, makeELMt(mt), true, false);
  }

  public void assertSentence(String sentence, ELMt mt, boolean bookkeeping, boolean transcript)
          throws UnknownHostException, IOException, CycApiException {
    assertSentence(sentence, mt, bookkeeping, transcript, null);
  }

  public void assertSentence(String sentence, ELMt mt, boolean bookkeeping, boolean transcript,
          CycFort template)
          throws UnknownHostException, IOException, CycApiException {
    String command = "(multiple-value-list (" + (transcript ? "ke-assert-now" : "cyc-assert") + "\n"
            + sentence + "\n" + mt.stringApiValue() + "))";
    if (bookkeeping) {
      command = wrapBookkeeping(command);
    } else {
      command = wrapCyclistAndPurpose(command);
    }
    if (template != null) {
      String loadRules = "(" + "creation-template-allowable-rules" + " " + template.stringApiValue() + ")";
      command = wrapDynamicBinding(command, "*forward-inference-allowed-rules*", loadRules);
    }
    CycList<Object> results = converseList(command);
    boolean statusOk = !results.get(0).equals(CycObjectFactory.nil);
    if (!statusOk) {
      throw new CycApiException("Assertion failed in mt: " + mt.cyclify()
              + "\n" + sentence + "\nbecause: \n" + results.get(1));
    }
  }

  /**
   * Unasserts the given sentence with bookkeeping and without placing it on the transcript queue.
   *
   * @param sentence the given sentence for unassertion
   * @param mt the microtheory from which the assertion is removed
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void unassertWithBookkeepingAndWithoutTranscript(CycList sentence,
          CycObject mt)
          throws UnknownHostException, IOException,
          CycApiException {
    String command = wrapBookkeeping("(cyc-unassert " + sentence.stringApiValue()
            + makeELMt(mt).stringApiValue() + ")");
    boolean unassertOk = converseBoolean(command);

    if (!unassertOk) {
      throw new CycApiException("Could not unassert from mt: " + makeELMt(
              mt) + "\n  "
              + sentence.cyclify());
    }
  }

  /**
   * Finds a Cyc constant in the KB with the specified name
   *
   * @param constantName the name of the new constant
   *
   * @return the constant term or null if the argument name is null or if the term is not found
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycConstant find(String constantName)
          throws UnknownHostException, IOException, CycApiException {
    if (constantName == null) {
      return null;
    }

    return getConstantByName(constantName);
  }

  /**
   * Finds or creates a Cyc constant in the KB with the specified name.  The operation will be
   * added to the KB transcript for replication and archive.
   *
   * @param constantName the name of the new constant
   *
   * @return the new constant term
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycConstant findOrCreate(String constantName)
          throws UnknownHostException, IOException, CycApiException {
    return makeCycConstant(constantName);
  }

  /**
   * Creates a new permanent Cyc constant in the KB with the specified name.  The operation will be
   * added to the KB transcript for replication and archive.
   *
   * @param constantName the name of the new constant
   *
   * @return the new constant term
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycConstant createNewPermanent(String constantName)
          throws UnknownHostException, IOException, CycApiException {
    return makeCycConstant(constantName);
  }

  /**
   * Asserts a ground atomic formula (gaf) in the specified microtheory MT.  The operation will be
   * added to the KB transcript for replication and archive.
   *
   * @param mt the microtheory in which the assertion is made
   * @param predicate the binary predicate of the assertion
   * @param arg1 the first argument of the predicate
   * @param arg2 the second argument of the predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertGaf(CycObject mt,
          CycDenotationalTerm predicate,
          CycDenotationalTerm arg1,
          CycDenotationalTerm arg2)
          throws UnknownHostException, IOException, CycApiException {
    // (predicate <CycFort> <CycFort>)
    CycList sentence = new CycList();
    sentence.add(predicate);
    sentence.add(arg1);
    sentence.add(arg2);
    assertWithTranscriptAndBookkeeping(sentence,
            mt);
  }

  /**
   * Asserts a ground atomic formula (gaf) in the specified microtheory MT.  The operation will be
   * added to the KB transcript for replication and archive.
   *
   * @param mt the microtheory in which the assertion is made
   * @param predicate the binary predicate of the assertion
   * @param arg1 the first argument of the predicate
   * @param arg2 the second argument of the predicate, which is a string
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertGaf(CycObject mt,
          CycFort predicate,
          CycFort arg1,
          String arg2)
          throws UnknownHostException, IOException, CycApiException {
    // (predicate <CycFort> <String>)
    CycList sentence = new CycList();
    sentence.add(predicate);
    sentence.add(arg1);
    sentence.add(arg2);
    assertWithTranscriptAndBookkeeping(sentence,
            mt);
  }

  /**
   * Asserts a ground atomic formula (gaf) in the specified microtheory MT.  The operation will be
   * added to the KB transcript for replication and archive.
   *
   * @param mt the microtheory in which the assertion is made
   * @param predicate the binary predicate of the assertion
   * @param arg1 the first argument of the predicate
   * @param arg2 the second argument of the predicate, which is a CycList
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertGaf(CycObject mt,
          CycConstant predicate,
          CycFort arg1,
          CycList arg2)
          throws UnknownHostException, IOException, CycApiException {
    // (predicate <CycFort> <List>)
    CycList sentence = new CycList();
    sentence.add(predicate);
    sentence.add(arg1);
    sentence.add(arg2);
    assertWithTranscriptAndBookkeeping(sentence, mt);
  }

  /**
   * Asserts a ground atomic formula (gaf) in the specified microtheory MT.  The operation will be
   * added to the KB transcript for replication and archive.
   *
   * @param mt the microtheory in which the assertion is made
   * @param predicate the binary predicate of the assertion
   * @param arg1 the first argument of the predicate
   * @param arg2 the second argument of the predicate, which is an int
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertGaf(CycObject mt,
          CycConstant predicate,
          CycFort arg1,
          int arg2)
          throws UnknownHostException, IOException, CycApiException {
    // (predicate <CycFort> <int>)
    assertGaf(mt, predicate, arg1, arg2);
  }

  /**
   * Asserts a ground atomic formula (gaf) in the specified microtheory.  The operation will be
   * added to the KB transcript for replication and archive.
   *
   * @param mt the microtheory in which the assertion is made
   * @param predicate the binary predicate of the assertion
   * @param arg1 the first argument of the predicate
   * @param arg2 the second argument of the predicate, which is an Integer
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertGaf(CycObject mt,
          CycFort predicate,
          CycFort arg1,
          Integer arg2)
          throws UnknownHostException, IOException, CycApiException {
    // (predicate <CycFort> <int>)
    CycList sentence = new CycList();
    sentence.add(predicate);
    sentence.add(arg1);
    sentence.add(arg2);
    assertWithTranscriptAndBookkeeping(sentence,
            mt);
  }

  /**
   * Asserts a ground atomic formula (gaf) in the specified microtheory.  The operation will be
   * added to the KB transcript for replication and archive.
   *
   * @param mt the microtheory in which the assertion is made
   * @param predicate the binary predicate of the assertion
   * @param arg1 the first argument of the predicate
   * @param arg2 the second argument of the predicate, which is a Double
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertGaf(CycObject mt,
          CycFort predicate,
          CycFort arg1,
          Double arg2)
          throws UnknownHostException, IOException, CycApiException {
    // (predicate <CycFort> <int>)
    CycList sentence = new CycList();
    sentence.add(predicate);
    sentence.add(arg1);
    sentence.add(arg2);
    assertWithTranscriptAndBookkeeping(sentence,
            mt);
  }

  /**
   * Asserts a ground atomic formula (gaf) in the specified microtheory MT. The operation and its
   * bookkeeping info will be added to the KB transcript for replication and archive.
   *
   * @param mt the microtheory in which the assertion is made
   * @param predicate the ternary predicate of the assertion
   * @param arg1 the first argument of the predicate
   * @param arg2 the second argument of the predicate
   * @param arg3 the third argument of the predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertGaf(CycObject mt,
          CycConstant predicate,
          CycFort arg1,
          CycFort arg2,
          CycFort arg3)
          throws UnknownHostException, IOException, CycApiException {
    // (predicate <CycFort> <CycFort> <CycFort>)
    CycList sentence = new CycList();
    sentence.add(predicate);
    sentence.add(arg1);
    sentence.add(arg2);
    sentence.add(arg3);
    assertWithTranscriptAndBookkeeping(sentence,
            mt);
  }

  /**
   * Asserts a ground atomic formula (gaf) in the specified microtheory MT.  The operation will be
   * added to the KB transcript for replication and archive.
   *
   * @param gaf the gaf in the form of a CycList
   * @param mt the microtheory in which the assertion is made
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertGaf(CycList gaf,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    assertWithTranscriptAndBookkeeping(gaf,
            mt);
  }

  /**
   * Asserts a ground atomic formula (gaf) in the specified microtheory MT.  The operation will be
   * added to the KB transcript for replication and archive.
   *
   * @param gaf the gaf in the form of a CycFormulaSentence
   * @param mt the microtheory in which the assertion is made
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertGaf(CycFormulaSentence gaf, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    assertWithTranscriptAndBookkeepingInternal(gaf, mt);
  }

  /**
   * Asserts a ground atomic formula (gaf) in the specified microtheory MT.  The operation is performed at the HL level
   * and does not perform wff-checking, nor forward inference, nor bookkeeping assertions, nor transcript recording.  The advantage of
   * this method is that it is fast.
   *
   * @param gaf the gaf in the form of a CycList
   * @param mt the microtheory in which the assertion is made
   * @param strength the assertion strength (e.g. :default or :monotonic)
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertHLGaf(final CycList gaf, final CycObject mt, final CycSymbol strength)
          throws UnknownHostException, IOException, CycApiException {
    // (HL-ADD-ARGUMENT '(:ASSERTED-ARGUMENT <strength>) '(NIL ((<gaf>)) <mt> :FORWARD NIL)
    final CycList command = new CycList();
    command.add(makeCycSymbol("hl-add-argument"));
    final CycList command1 = new CycList();
    command1.add(makeCycSymbol(":asserted-argument"));
    command1.add(strength);
    command.addQuoted(command1);
    final CycList command2 = new CycList();
    command2.add(CycObjectFactory.nil);
    final CycList command3 = new CycList();
    final CycList canonicalGaf = new CycList();
    final int gaf_size = gaf.size();
    for (int i = 0; i < gaf_size; i++) {
      final Object obj = gaf.get(i);
      if (obj instanceof CycNart) {
        canonicalGaf.add(((CycNart) obj).getFormula());
      } else {
        canonicalGaf.add(obj);
      }
    }
    command3.add(canonicalGaf);
    command2.add(command3);
    command.addQuoted(command2);
    command.add(mt);
    command.add(makeCycSymbol(":forward"));
    command.add(CycObjectFactory.nil);
    converseCycObject(command);
  }

  /**
   * Unasserts the given ground atomic formula (gaf) in the specified microtheory MT.
   *
   * @param gaf the gaf in the form of a CycList
   * @param mt the microtheory in which the assertion is made
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void unassertGaf(CycList gaf,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    String command = wrapBookkeeping("(ke-unassert-now " + gaf.stringApiValue()
            + makeELMt(mt).stringApiValue() + ")");
    converseVoid(command);
  }

  /**
   * Unasserts the given ground atomic formula (gaf) in the specified microtheory MT.
   *
   * @param gaf the gaf in the form of a CycList
   * @param mt the microtheory in which the assertion is made
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void unassertGaf(CycFormulaSentence gaf, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    String command = wrapBookkeeping("(ke-unassert-now " + gaf.stringApiValue()
            + makeELMt(mt).stringApiValue() + ")");
    converseVoid(command);
  }

  /**
   * Assert a nameString for the specified CycConstant in the specified lexical microtheory. The
   * operation will be added to the KB transcript for replication and archive.
   *
   * @param cycConstantName the name of the given term
   * @param nameString the given name string for the term
   * @param mtName the name of the microtheory in which the name string is asserted
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertNameString(String cycConstantName,
          String nameString,
          String mtName)
          throws UnknownHostException, IOException, CycApiException {
    assertGaf(makeELMt(getKnownConstantByName(mtName)),
            getKnownConstantByGuid("c0fdf7e8-9c29-11b1-9dad-c379636f7270"),
            getKnownConstantByName(cycConstantName),
            nameString);
  }

  /**
   * Assert a comment for the specified CycConstant in the specified microtheory MT.  The operation
   * will be added to the KB transcript for replication and archive.
   *
   * @param cycConstantName the name of the given term
   * @param comment the comment string
   * @param mtName the name of the microtheory in which the comment is asserted
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertComment(String cycConstantName,
          String comment,
          String mtName)
          throws UnknownHostException, IOException, CycApiException {
    assertGaf(makeELMt(getKnownConstantByName(mtName)),
            CycAccess.comment,
            getKnownConstantByName(cycConstantName),
            comment);
  }

  /**
   * Assert a comment for the specified CycFort in the specified microtheory. The operation will be
   * added to the KB transcript for replication and archive.
   *
   * @param cycFort the given term
   * @param comment the comment string
   * @param mt the comment assertion microtheory
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertComment(CycFort cycFort,
          String comment,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    ELMt elmt = makeELMt(mt);
    assertGaf(elmt,
            CycAccess.comment,
            cycFort,
            comment);
  }

  /**
   * Assert a name string for the specified CycFort in the specified microtheory. The operation
   * will be added to the KB transcript for replication and archive.
   *
   * @param cycFort the given term
   * @param nameString the name string
   * @param mt the name string assertion microtheory
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertNameString(CycFort cycFort,
          String nameString,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    ELMt elmt = makeELMt(mt);
    assertGaf(elmt,
            this.getKnownConstantByGuid("c0fdf7e8-9c29-11b1-9dad-c379636f7270"),
            cycFort,
            nameString);
  }

  /**
   * Assert a paraphrase format for the specified CycFort in the #$EnglishParaphraseMt. The
   * operation will be added to the KB transcript for replication and archive.
   *
   * @param relation the given term
   * @param genFormatString the genFormat string
   * @param genFormatList the genFormat argument substitution sequence
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  @Deprecated
  public void assertGenFormat(CycFort relation,
          String genFormatString,
          CycList genFormatList)
          throws UnknownHostException, IOException, CycApiException {
    // (#$genFormat <relation> <genFormatString> <genFormatList>)
    CycList sentence = new CycList();
    sentence.add(getKnownConstantByGuid("beed06de-9c29-11b1-9dad-c379636f7270"));
    sentence.add(relation);
    sentence.add(genFormatString);

    if (genFormatList.size() == 0) {
      sentence.add(CycObjectFactory.nil);
    } else {
      sentence.add(genFormatList);
    }

    assertGaf(sentence,
            // #$EnglishParaphraseMt
            makeELMt(getKnownConstantByGuid("bda16220-9c29-11b1-9dad-c379636f7270")));
  }

  /**
   * Create a microtheory MT, with a comment, isa MT-TYPE and CycFort genlMts. An existing
   * microtheory with the same name is killed first, if it exists.
   *
   * @param mtName the name of the microtheory term
   * @param comment the comment for the new microtheory
   * @param isaMt the type of the new microtheory
   * @param genlMts the list of more general microtheories
   *
   * @return the new microtheory term
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycConstant createMicrotheory(String mtName,
          String comment,
          CycFort isaMt,
          List genlMts)
          throws UnknownHostException, IOException, CycApiException {
    CycConstant mt = getConstantByName(mtName);

    if (mt != null) {
      kill(mt);
    }

    mt = createNewPermanent(mtName);
    assertComment(mt,
            comment,
            baseKB);
    assertGaf(universalVocabularyMt,
            isa,
            mt,
            isaMt);

    Iterator iterator = genlMts.iterator();

    while (true) {
      if (!iterator.hasNext()) {
        break;
      }

      CycFort aGenlMt = (CycFort) iterator.next();
      assertGaf(universalVocabularyMt,
              genlMt,
              mt,
              aGenlMt);
    }

    return mt;
  }

  /**
   * Create a microtheory MT, with a comment, isa MT-TYPE and CycFort genlMts.
   *
   * @param mt the microtheory term
   * @param comment the comment for the new microtheory
   * @param isaMt the type of the new microtheory
   * @param genlMts the list of more general microtheories
   *
   * @return the new microtheory term
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void createMicrotheory(CycFort mt,
          String comment,
          CycFort isaMt,
          List genlMts)
          throws UnknownHostException, IOException, CycApiException {
    assertComment(mt,
            comment,
            baseKB);
    assertGaf(universalVocabularyMt,
            isa,
            mt,
            isaMt);
    Iterator iterator = genlMts.iterator();
    while (true) {
      if (!iterator.hasNext()) {
        break;
      }
      final CycList gaf = new CycList(3);
      gaf.add(genlMt);
      gaf.add(mt);
      gaf.add(iterator.next());
      assertGaf(gaf, universalVocabularyMt);
    }
  }

  /**
   * Create a microtheory MT, with a comment, isa MT-TYPE and CycFort genlMts. An existing
   * microtheory with the same name is killed first, if it exists.
   *
   * @param mtName the name of the microtheory term
   * @param comment the comment for the new microtheory
   * @param isaMtName the type (as a string) of the new microtheory
   * @param genlMts the list of more general microtheories (as strings)
   *
   * @return the new microtheory term
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycConstant createMicrotheory(String mtName,
          String comment,
          String isaMtName,
          List genlMts)
          throws UnknownHostException, IOException, CycApiException {
    CycConstant mt = getConstantByName(mtName);

    if (mt != null) {
      kill(mt);
    }

    mt = createNewPermanent(mtName);
    assertComment(mt,
            comment,
            baseKB);
    assertIsa(mtName,
            isaMtName);

    Iterator iterator = genlMts.iterator();

    while (true) {
      if (!iterator.hasNext()) {
        break;
      }

      String genlMtName = (String) iterator.next();
      assertGenlMt(mtName,
              genlMtName);
    }

    return mt;
  }

  /**
   * Create a microtheory system for a new mt.  Given a root mt name, create a theory ROOTMt,
   * create a vocabulary ROOTVocabMt, and a data ROOTDataMt.  Establish genlMt links for the
   * theory mt and data mt.  Assert that the theory mt is a genlMt of the
   * WorldLikeOursCollectorMt. Assert that the data mt is a genlMt of the collector
   * CurrentWorldDataMt.
   *
   * @param mtRootName the root name of the microtheory system
   * @param comment the root comment of the microtheory system
   * @param genlMts the list of more general microtheories
   *
   * @return an array of three elements consisting of the theory mt, vocabulary mt, and the data mt
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycConstant[] createMicrotheorySystem(String mtRootName,
          String comment,
          List genlMts)
          throws UnknownHostException, IOException, CycApiException {
    //traceOn();
    CycConstant[] mts = {null, null, null};
    String theoryMtName = mtRootName + "Mt";
    String vocabMtName = mtRootName + "VocabMt";
    String vocabMtComment = "The #$VocabularyMicrotheory for #$" + theoryMtName;
    String dataMtName = mtRootName + "DataMt";
    String dataMtComment = "The #$DataMicrotheory for #$" + theoryMtName;
    CycConstant worldLikeOursMt = getKnownConstantByGuid(
            "bf4c781d-9c29-11b1-9dad-c379636f7270");
    CycConstant genlMt_Vocabulary = getKnownConstantByGuid(
            "c054a49e-9c29-11b1-9dad-c379636f7270");

    CycConstant theoryMicrotheory = getKnownConstantByGuid(
            "be5275a8-9c29-11b1-9dad-c379636f7270");
    CycConstant theoryMt = createMicrotheory(theoryMtName,
            comment,
            theoryMicrotheory,
            genlMts);
    CycConstant vocabularyMicrotheory = getKnownConstantByGuid(
            "bda19dfd-9c29-11b1-9dad-c379636f7270");
    CycConstant vocabMt = createMicrotheory(vocabMtName,
            vocabMtComment,
            vocabularyMicrotheory,
            new ArrayList());
    CycConstant dataMicrotheory = getKnownConstantByGuid(
            "be5275a8-9c29-11b1-9dad-c379636f7270");
    CycConstant dataMt = createMicrotheory(dataMtName,
            dataMtComment,
            dataMicrotheory,
            new ArrayList());
    assertGaf(baseKB,
            genlMt_Vocabulary,
            theoryMt,
            vocabMt);
    assertGaf(baseKB,
            genlMt,
            dataMt,
            theoryMt);
    assertGaf(baseKB,
            genlMt,
            worldLikeOursMt,
            theoryMt);
    assertGaf(baseKB,
            genlMt,
            currentWorldDataMt,
            dataMt);
    mts[0] = theoryMt;
    mts[1] = vocabMt;
    mts[2] = dataMt;

    //traceOff();
    return mts;
  }

  /**
   * Assert that the specified CycConstant is a collection in the UniversalVocabularyMt. The
   * operation will be added to the KB transcript for replication and archive.
   *
   * @param cycFort the given collection term
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertIsaCollection(CycFort cycFort)
          throws UnknownHostException, IOException, CycApiException {
    assertGaf(universalVocabularyMt,
            isa,
            cycFort,
            collection);
  }

  /**
   * Assert that the specified CycConstant is a collection in the specified defining microtheory
   * MT. The operation will be added to the KB transcript for replication and archive.
   *
   * @param cycFort the given collection term
   * @param mt the assertion microtheory
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertIsaCollection(CycFort cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    ELMt elmt = makeELMt(mt);
    assertGaf(elmt,
            isa,
            cycFort,
            collection);
  }

  /**
   * Assert that the genlsCollection is a genls of specCollection, in the specified defining
   * microtheory MT. The operation will be added to the KB transcript for replication and archive.
   *
   * @param specCollectionName the name of the more specialized collection
   * @param genlsCollectionName the name of the more generalized collection
   * @param mtName the assertion microtheory name
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertGenls(String specCollectionName,
          String genlsCollectionName,
          String mtName)
          throws UnknownHostException, IOException, CycApiException {
    assertGaf(makeELMt(getKnownConstantByName(mtName)),
            genls,
            getKnownConstantByName(specCollectionName),
            getKnownConstantByName(genlsCollectionName));
  }

  /**
   * Assert that the genlsCollection is a genls of specCollection, in the UniversalVocabularyMt The
   * operation will be added to the KB transcript for replication and archive.
   *
   * @param specCollectionName the name of the more specialized collection
   * @param genlsCollectionName the name of the more generalized collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertGenls(String specCollectionName,
          String genlsCollectionName)
          throws UnknownHostException, IOException, CycApiException {
    assertGaf(universalVocabularyMt,
            genls,
            getKnownConstantByName(specCollectionName),
            getKnownConstantByName(genlsCollectionName));
  }

  /**
   * Assert that the genlsCollection is a genls of specCollection, in the UniveralVocabularyMt. The
   * operation will be added to the KB transcript for replication and archive.
   *
   * @param specCollection the more specialized collection
   * @param genlsCollection the more generalized collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertGenls(CycFort specCollection,
          CycFort genlsCollection)
          throws UnknownHostException, IOException, CycApiException {
    assertGaf(universalVocabularyMt,
            genls,
            specCollection,
            genlsCollection);
  }

  /**
   * Assert that the genlsCollection is a genls of specCollection, in the specified defining
   * microtheory MT. The operation will be added to the KB transcript for replication and archive.
   *
   * @param specCollection the more specialized collection
   * @param genlsCollection the more generalized collection
   * @param mt the assertion microtheory
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertGenls(CycFort specCollection,
          CycFort genlsCollection,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    ELMt elmt = makeELMt(mt);
    assertGaf(elmt,
            genls,
            specCollection,
            genlsCollection);
  }

  /**
   * Assert that the more general predicate is a genlPreds of the more specialized predicate,
   * asserted in the UniversalVocabularyMt The operation will be added to the KB transcript for
   * replication and archive.
   *
   * @param specPredName the name of the more specialized predicate
   * @param genlPredName the name of the more generalized predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertGenlPreds(String specPredName,
          String genlPredName)
          throws UnknownHostException, IOException, CycApiException {
    CycConstant genlPreds = getKnownConstantByGuid("bd5b4951-9c29-11b1-9dad-c379636f7270");
    assertGaf(universalVocabularyMt,
            genlPreds,
            getKnownConstantByName(specPredName),
            getKnownConstantByName(genlPredName));
  }

  /**
   * Assert that the more general predicate is a genlPreds of the more specialized predicate,
   * asserted in the UniversalVocabularyMt The operation will be added to the KB transcript for
   * replication and archive.
   *
   * @param specPred the more specialized predicate
   * @param genlPred the more generalized predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertGenlPreds(CycFort specPred,
          CycFort genlPred)
          throws UnknownHostException, IOException, CycApiException {
    CycConstant genlPreds = getKnownConstantByGuid("bd5b4951-9c29-11b1-9dad-c379636f7270");
    assertGaf(universalVocabularyMt,
            genlPreds,
            specPred,
            genlPred);
  }

  /**
   * Assert that term1 is conceptually related to term2 in the specified microtheory. The operation
   * will be added to the KB transcript for replication and archive.
   *
   * @param term1 the first symbol
   * @param term2 the second symbol
   * @param mt the microtheory in which the assertion is made
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertConceptuallyRelated(CycFort term1,
          CycFort term2,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    CycConstant conceptuallyRelated = getKnownConstantByGuid(
            "bd58803e-9c29-11b1-9dad-c379636f7270");
    assertGaf(makeELMt(mt),
            conceptuallyRelated,
            term1,
            term2);
  }

  /**
   * Assert that the more general micortheory is a genlMt of the more specialized microtheory,
   * asserted in the UniversalVocabularyMt The operation will be added to the KB transcript for
   * replication and archive.
   *
   * @param specMtName the name of the more specialized microtheory
   * @param genlsMtName the name of the more generalized microtheory
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertGenlMt(String specMtName,
          String genlsMtName)
          throws UnknownHostException, IOException, CycApiException {
    assertGaf(universalVocabularyMt,
            genlMt,
            getKnownConstantByName(specMtName),
            getKnownConstantByName(genlsMtName));
  }

  /**
   * Assert that the more general micortheory is a genlMt of the more specialized microtheory,
   * asserted in the UniversalVocabularyMt The operation will be added to the KB transcript for
   * replication and archive.
   *
   * @param specMt the more specialized microtheory
   * @param genlsMt the more generalized microtheory
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertGenlMt(CycFort specMt,
          CycFort genlsMt)
          throws UnknownHostException, IOException, CycApiException {
    assertGaf(universalVocabularyMt, genlMt, specMt, genlsMt);
  }

  /**
   * Assert that the cycFort is a collection in the UniversalVocabularyMt. The operation will be
   * added to the KB transcript for replication and archive.
   *
   * @param cycFortName the collection element name
   * @param collectionName the collection name
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertIsa(String cycFortName,
          String collectionName)
          throws UnknownHostException, IOException, CycApiException {
    assertGaf(universalVocabularyMt,
            isa,
            getKnownConstantByName(cycFortName),
            getKnownConstantByName(collectionName));
  }

  /**
   * Assert that the cycFort is a collection, in the specified defining microtheory MT. The
   * operation will be added to the KB transcript for replication and archive.
   *
   * @param cycFortName the collection element name
   * @param collectionName the collection name
   * @param mtName the assertion microtheory name
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertIsa(String cycFortName,
          String collectionName,
          String mtName)
          throws UnknownHostException, IOException, CycApiException {
    assertGaf(makeELMt(getKnownConstantByName(mtName)),
            isa,
            getKnownConstantByName(cycFortName),
            getKnownConstantByName(collectionName));
  }

  /**
   * Assert that the cycFort is a collection, in the specified defining microtheory MT. The
   * operation will be added to the KB transcript for replication and archive.
   *
   * @param cycFort the collection element
   * @param aCollection the collection
   * @param mt the assertion microtheory
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertIsa(CycFort cycFort,
          CycFort aCollection,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    assertGaf(makeELMt(mt),
            isa,
            cycFort,
            aCollection);
  }

  /**
   * Assert that the cycFort term itself is a collection, in the given mt. The operation will be
   * added to the KB transcript for replication and archive.
   *
   * @param cycFort the collection element
   * @param aCollection the collection
   * @param mt the assertion microtheory
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertQuotedIsa(CycFort cycFort, CycFort aCollection, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    assertGaf(makeELMt(mt),
            getKnownConstantByGuid("055544a2-4371-11d6-8000-00a0c9da2002"),
            cycFort,
            aCollection);
  }

  /**
   * Assert that the cycFort is a collection, in the UniversalVocabularyMt. The operation will be
   * added to the KB transcript for replication and archive.
   *
   * @param cycFort the collection element
   * @param aCollection the collection
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertIsa(CycDenotationalTerm instance,
          CycDenotationalTerm aCollection)
          throws UnknownHostException, IOException, CycApiException {
    assertGaf(universalVocabularyMt,
            isa,
            instance,
            aCollection);
  }

  /**
   * Assert that the specified CycConstant is a #$BinaryPredicate in the specified defining
   * microtheory. The operation will be added to the KB transcript for replication and archive.
   *
   * @param cycFort the given term
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertIsaBinaryPredicate(CycFort cycFort)
          throws UnknownHostException, IOException, CycApiException {
    assertIsa(cycFort,
            binaryPredicate,
            universalVocabularyMt);
  }

  /**
   * Assert that the specified CycConstant is a #$BinaryPredicate in the specified defining
   * microtheory. The operation will be added to the KB transcript for replication and archive.
   *
   * @param cycFort the given term
   * @param mt the defining microtheory
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertIsaBinaryPredicate(CycFort cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    assertIsa(cycFort,
            binaryPredicate,
            makeELMt(mt));
  }

  /**
   * Constructs a new CycNaut object by parsing a string.
   *
   * @param string the string in CycL external (EL). For example: (#$MotherFn #$GeorgeWashington)
   *
   * @return the new CycNaut object from parsing the given string
   *
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycNaut makeCycNaut(String string)
          throws CycApiException {
    return new CycNaut(makeCycList(string));
  }

  /**
   * Constructs a new CycFormulaSentence object by parsing a string.
   *
   * @param string the string in CycL external (EL). For example: (#$isa #$Dog #$TameAnimal)
   *
   * @return the new CycFormulaSentence object from parsing the given string
   *
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycFormulaSentence makeCycSentence(String string)
          throws CycApiException {
    return new CycFormulaSentence(makeCycList(string));
  }

  /**
   * Constructs a new CycFormulaSentence object by parsing a string from a string that
   * may or may not include all appropriate "#$"s.
   *
   * @param string the string in CycL external (EL). For example: (#$isa Dog TameAnimal)
   *
   * @return the new CycFormulaSentence object from parsing the given string
   *
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycFormulaSentence makeCyclifiedSentence(String string)
          throws CycApiException, UnknownHostException, IOException {
    String cyclified = cyclifyString(string);
    return makeCycSentence(cyclified);
  }

  /**
   * Constructs a new CycList object by parsing a string.
   *
   * @param string the string in CycL external (EL). For example: (#$isa #$Dog #$TameAnimal)
   *
   * @return the new CycList object from parsing the given string
   *
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList<Object> makeCycList(String string)
          throws CycApiException {
    return (new CycListParser(this)).read(string);
  }

  /**
   * Constructs a new ELMt object by the given CycObject.
   *
   * @param cycObject the given CycObject from which the ELMt is derived
   *
   * @return the new ELMt object by the given CycObject
   *
   * @throws IOException if a communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   * @throws IllegalArgumentException if the cycObject is not the correct type of thing for
   * making into an ELMt
   */
  public ELMt makeELMt(Object object)
          throws IOException, CycApiException {
    if (object instanceof ELMt) {
      return (ELMt) object;
    } else if (object instanceof CycList) {
      return canonicalizeHLMT((CycList) object);
    } else if (object instanceof CycNaut) {
      return canonicalizeHLMT((CycNaut) object);
    } else if (object instanceof CycConstant) {
      return ELMtConstant.makeELMtConstant((CycConstant) object);
    } else if (object instanceof CycNart) {
      return ELMtNart.makeELMtNart((CycNart) object);
    } else if (object instanceof String) {
      String elmtString = object.toString().trim();
      if (elmtString.startsWith("(")) {
        @SuppressWarnings("unchecked")
        CycList<Object> elmtCycList = makeCycList(elmtString);
        return makeELMt(elmtCycList);
      } else {
        return makeELMt(getKnownConstantByName(elmtString));
      }
    } else {
      throw new IllegalArgumentException("Can't make an ELMt from " + object
              + " class: " + object.getClass().getSimpleName());
    }
  }

  /**
   * Returns the canonical Heuristic Level Microtheory (HLMT) given a list  representation.
   *
   * @param cycList the given CycList NART/NAUT representation
   *
   * @return the canonical Heuristic Level Microtheory (HLMT) given a list  representation
   *
   * @throws IOException if a communication error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public ELMt canonicalizeHLMT(CycList cycList)
          throws IOException, CycApiException {
    ELMt mt;
    String command = makeSubLStmt("canonicalize-hlmt", cycList);
    final CycObject result = converseCycObject(command);
    if (result instanceof CycDenotationalTerm) {
      mt = makeELMt(result);
    } else if (result instanceof List) {
      mt = ELMtCycNaut.makeELMtCycNaut((List) result);
    } else {
      throw new CycApiException("Can't canonicalize " + cycList);
    }
    return mt;
  }

  /**
   * Returns the canonical Heuristic Level Microtheory (HLMT) given a list  representation.
   *
   * @param naut the given NAUT representation
   *
   * @return the canonical Heuristic Level Microtheory (HLMT) given a list  representation
   *
   * @throws IOException if a communication error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public ELMt canonicalizeHLMT(CycNaut naut)
          throws IOException, CycApiException {
    return canonicalizeHLMT(naut.toCycList());
  }

  /**
   * Wraps the given api command string with the binding environment for bookkeeping assertions.
   *
   * @param command the given command string
   *
   * @return the given api command string with the binding environment for bookkeeping assertions
   */
  public String wrapBookkeeping(String command) {
    final String projectName = (project == null) ? "nil" : project.stringApiValue();
    final String cyclistName = (cyclist == null) ? "nil" : cyclist.stringApiValue();

    String wrappedCommand = "(with-bookkeeping-info (new-bookkeeping-info " + cyclistName
            + " (the-date) " + projectName + " (the-second))\n"
            + wrapCyclistAndPurpose(command, cyclistName, projectName)
            + "\n)";

    return wrappedCommand;
  }

  public String wrapCyclistAndPurpose(String command) {
    final String projectName = (project == null) ? "nil" : project.stringApiValue();
    final String cyclistName = (cyclist == null) ? "nil" : cyclist.stringApiValue();
    return wrapCyclistAndPurpose(command, cyclistName, projectName);
  }

  public String wrapCyclistAndPurpose(String command, String cyclistName, String projectName) {
    return "(clet ((*require-case-insensitive-name-uniqueness* nil)\n"
            + "       (*the-cyclist* " + cyclistName + ")\n"
            + "       (*ke-purpose* " + projectName + "))\n"
            + "    " + command
            + "\n)";
  }

  public String wrapDynamicBinding(String command, String symbolName, String apiValue) {
    return "(clet ((" + symbolName + " " + apiValue + "))\n"
            + "  " + command + "\n)";
  }

  /**
   * Returns a new <tt>CycConstant</tt> object using the constant name, recording bookkeeping
   * information and archiving to the Cyc transcript.
   *
   * @param name Name of the constant. If prefixed with "#$", then the prefix is removed for
   *        canonical representation.
   *
   * @return a new <tt>CycConstant</tt> object using the constant name, recording bookkeeping
   *         information and archiving to the Cyc transcript
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycConstant makeCycConstant(String name)
          throws UnknownHostException, IOException, CycApiException {
    String constantName = name;

    if (constantName.startsWith("#$")) {
      constantName = constantName.substring(2);
    }

    CycConstant cycConstant = getConstantByName(name);

    if (cycConstant != null) {
      return cycConstant;
    }

    String command = wrapBookkeeping("(ke-create-now \"" + constantName + "\")");
    Object object = converseObject(command);

    if (object instanceof CycConstant) {
      cycConstant = (CycConstant) object;
    } else {
      throw new CycApiException("Cannot create new constant for " + name);
    }
    CycObjectFactory.addCycConstantCache(cycConstant);

    return cycConstant;
  }

  /**
   * Returns a new unique <tt>CycConstant</tt> object using the constant start name prefixed by
   * TMP-, recording bookkeeping information and archiving to the Cyc transcript.  If
   * the start name begins with #$ that portion of the start name is ignored.
   *
   * @param startName the starting name of the constant which will be made unique using a suffix.
   *
   * @return a new <tt>CycConstant</tt> object using the constant starting name, recording
   *         bookkeeping information and archiving to the Cyc transcript
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycConstant makeUniqueCycConstant(final String startName)
          throws UnknownHostException, IOException, CycApiException {
    String constantName = startName;

    if (constantName.startsWith("#$")) {
      constantName = constantName.substring(2);
    }
    String suffix = "";
    int suffixNum = 0;
    while (true) {
      String command = "(constant-name-available \"" + startName + suffix + "\")";
      if (converseBoolean(command)) {
        break;
      }
      if (suffix.length() == 0) {
        suffixNum = ((int) (9 * Math.random())) + 1;
      } else {
        suffixNum = (suffixNum * 10) + ((int) (10 * Math.random()));
      }
      suffix = String.valueOf(suffixNum);
    }
    return makeCycConstant(startName + suffix);
  }

  /**
   * Returns a new unique <tt>CycConstant</tt> object using the constant start name and prefix,
   * recording bookkeeping information and but without archiving to the Cyc transcript. If the
   * start name begins with #$ that portion of the start name is ignored.
   *
   * @param startName the starting name of the constant which will be made unique using a suffix.
   * @param prefix the prefix
   *
   * @return a new <tt>CycConstant</tt> object using the constant starting name, recording
   *         bookkeeping information and archiving to the Cyc transcript
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycConstant makeUniqueCycConstant(String startName,
          String prefix)
          throws UnknownHostException, IOException, CycApiException {
    String constantName = startName;

    if (constantName.startsWith("#$")) {
      constantName = constantName.substring(2);
    }

    String command = wrapBookkeeping("(gentemp-constant \"" + constantName + "\" \"" + prefix
            + "\")");
    CycConstant cycConstant = (CycConstant) converseObject(
            command);
    CycObjectFactory.addCycConstantCache(cycConstant);

    return cycConstant;
  }

  /**
   * Asks a Cyc query (new inference parameters) and returns the binding list.
   *
   * @param query the query expression
   * @param mt the inference microtheory
   * @param queryProperties queryProperties the list of query property keywords and values
   *
   * @return the binding list resulting from the given query
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   * @deprecated use <code>executeQuery</code>
   */
  public CycList askNewCycQuery(final CycList query,
          final CycObject mt,
          final InferenceParameters queryProperties)
          throws UnknownHostException, IOException, CycApiException {
    final String script =
            "(new-cyc-query " + query.stringApiValue() + " " + makeELMt(mt).stringApiValue() + " " + queryPropertiesToString(queryProperties) + ")";
    return converseList(script);
  }

  /**
   * Run a synchronous query against Cyc.
   *
   * </p><strong>Note: </strong> One should put this call in a try/finally statement
   * and the finally statement should explicitly close the result set. Failure to do so
   * could cause garbage to accumulate on the server.
   *
   * @param query the query in CycList form to ask
   * @param mt the microtheory in which the query should be asked
   * @param queryProperties the query properties to use when asking the query
   * @param timeoutMsecs the amount of time in milliseconds to wait before
   * giving up. A zero for this value means to wait forever.
   * @return the <code>InferenceResultSet</code> which provides a convenient
   * mechanism for walking over results similar to java.sql.ResultSet
   * @throws IOException if a communication error occurs
   * @throws CycApiException if an internal error occurs
   * @throws TimeOutException if the query times out
   */
  public InferenceResultSet executeQuery(final CycList query,
          final ELMt mt, final InferenceParameters queryProperties,
          final long timeoutMsecs)
          throws IOException, CycApiException, TimeOutException {
    InferenceWorkerSynch worker =
            new DefaultInferenceWorkerSynch(query, mt, queryProperties, this, timeoutMsecs);
    InferenceResultSet rs = worker.executeQuery();
    return rs;
  }

  /**
   * Run a synchronous query against Cyc.
   *
   * </p><strong>Note: </strong> One should put this call in a try/finally statement
   * and the finally statement should explicitly close the result set. Failure to do so
   * could cause garbage to accumulate on the server.
   *
   * @param query the query in CycFormulaSentence form to ask
   * @param mt the microtheory in which the query should be asked
   * @param queryProperties the query properties to use when asking the query
   * @return the <code>InferenceResultSet</code> which provides a convenient
   * mechanism for walking over results similar to java.sql.ResultSet
   * @throws IOException if a communication error occurs
   * @throws CycApiException if an internal error occurs
   * @throws TimeOutException if the query times out
   */
  public InferenceResultSet executeQuery(final CycFormulaSentence query,
          final ELMt mt, final InferenceParameters queryProperties)
          throws IOException, CycApiException, TimeOutException {
    return executeQuery(query, mt, queryProperties, 0);
  }

  /**
   * Run a synchronous query against Cyc.
   *
   * </p><strong>Note: </strong> One should put this call in a try/finally statement
   * and the finally statement should explicitly close the result set. Failure to do so
   * could cause garbage to accumulate on the server.
   *
   * @param query the query in CycFormulaSentence form to ask
   * @param mt the microtheory in which the query should be asked
   * @param queryProperties the query properties to use when asking the query
   * @param timeoutMsecs the amount of time in milliseconds to wait before
   * giving up. A zero for this value means to wait forever.
   * @return the <code>InferenceResultSet</code> which provides a convenient
   * mechanism for walking over results similar to java.sql.ResultSet
   * @throws IOException if a communication error occurs
   * @throws CycApiException if an internal error occurs
   * @throws TimeOutException if the query times out
   */
  public InferenceResultSet executeQuery(final CycFormulaSentence query,
          final CycObject mt, final InferenceParameters queryProperties,
          final long timeoutMsecs)
          throws IOException, CycApiException, TimeOutException {
    InferenceWorkerSynch worker =
            new DefaultInferenceWorkerSynch(query, (ELMt) mt, queryProperties, this, timeoutMsecs);
    InferenceResultSet rs = worker.executeQuery();
    return rs;
  }

  /**
   * Run a synchronous query against Cyc.
   * 
   * </p><strong>Note: </strong> One should put this call in a try/finally statement
   * and the finally statement should explicitly close the result set. Failure to do so
   * could cause garbage to accumulate on the server.
   * 
   * @param query the query in String form to ask
   * @param mt the microtheory in which the query should be asked (as a String, CycObject or ELMt)
   * @param queryProperties the query properties to use when asking the query
   * @param timeoutMsecs the amount of time in milliseconds to wait before 
   * giving up. A zero for this value means to wait forever.
   * @return the <code>InferenceResultSet</code> which provides a convenient 
   * mechanism for walking over results similar to java.sql.ResultSet
   * @throws IOException if a communication error occurs
   * @throws CycApiException if an internal error occurs
   * @throws TimeOutException if the query times out
   */
  public InferenceResultSet executeQuery(final String query,
          final Object mt, final InferenceParameters queryProperties,
          final long timeoutMsecs)
          throws IOException, CycApiException, TimeOutException {
    InferenceWorkerSynch worker =
            new DefaultInferenceWorkerSynch(query, makeELMt(mt), queryProperties, this, timeoutMsecs);
    InferenceResultSet rs = worker.executeQuery();
    return rs;
  }

  /**
   * Asks a Cyc query (new inference parameters) and returns an XML stream according
   * to the specifications in the CycList xmlSpec.
   *
   * @param query the query expression
   * @param mt the inference microtheory
   * @param queryProperties queryProperties the list of query property keywords and values
   * @param xmlSpec the specification of elements, attributes, sort order and bindings for the XML that the method returns
   *
   * @return the binding list from the query in the XML format specified by xmlSpec
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public String queryResultsToXMLString(CycList query,
          CycObject mt,
          InferenceParameters queryProperties,
          CycList xmlSpec)
          throws UnknownHostException, IOException, CycApiException {
    return queryResultsToXMLStringInternal(query, mt, queryProperties, xmlSpec);
  }

  /**
   * Asks a Cyc query (new inference parameters) and returns an XML stream according
   * to the specifications in the CycList xmlSpec.
   *
   * @param query the query expression
   * @param mt the inference microtheory
   * @param queryProperties queryProperties the list of query property keywords and values
   * @param xmlSpec the specification of elements, attributes, sort order and bindings for the XML that the method returns
   *
   * @return the binding list from the query in the XML format specified by xmlSpec
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public String queryResultsToXMLString(CycFormulaSentence query,
          CycObject mt,
          InferenceParameters queryProperties,
          CycList xmlSpec)
          throws UnknownHostException, IOException, CycApiException {
    return queryResultsToXMLStringInternal(query, mt, queryProperties, xmlSpec);

  }

  private String queryResultsToXMLStringInternal(CycObject query,
          CycObject mt,
          InferenceParameters queryProperties,
          CycList xmlSpec)
          throws UnknownHostException, IOException, CycApiException {
    String xmlSpecString = (xmlSpec == null) ? ":default" : xmlSpec.stringApiValue();
    final String script =
            "(query-results-to-xml-string " + query.stringApiValue() + " " + makeELMt(mt).stringApiValue() + " " + queryPropertiesToString(queryProperties) + " " + xmlSpecString + ")";
    return converseString(script);
  }

  /**
   * Returns true if the  Cyc query (with inference parameters) is proven true.
   *
   * @param query the query expression
   * @param mt the inference microtheory
   * @param queryProperties queryProperties the list of query property keywords
   * and values, or null if the defaults are to used
   *
   * @return true if the query is proven true.
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error or if there are open variables in the query
   */
  public boolean isQueryTrue(CycList query, CycObject mt, InferenceParameters queryProperties)
          throws UnknownHostException, IOException, CycApiException {
    return isQueryTrue(query, mt, queryProperties, 0);
  }

  /**
   * Returns true if the  Cyc query (with inference parameters) is proven true.
   *
   * @param query the query expression
   * @param mt the inference microtheory
   * @param queryProperties queryProperties the list of query property keywords
   * and values, or null if the defaults are to used
   *
   * @return true if the query is proven true.
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error or if there are open variables in the query
   */
  public boolean isQueryTrue(CycFormulaSentence query, CycObject mt, InferenceParameters queryProperties)
          throws UnknownHostException, IOException, CycApiException {
    return isQueryTrue(query, mt, queryProperties, 0);
  }

  /**
   * Returns true if the  Cyc query (with inference parameters) is proven true.
   *
   * @param query the query expression
   * @param mt the inference microtheory
   * @param queryProperties queryProperties the list of query property keywords 
   * and values, or null if the defaults are to used
   * @param timeoutMsecs the time in milliseconds to wait before giving up,
   * set to zero in order to wait forever
   *
   * @return true if the query is proven true.
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error or if there are open variables in the query
   * @throws TimeOutException if the calculation takes too long
   */
  public boolean isQueryTrue(CycList query, CycObject mt, InferenceParameters queryProperties, long timeoutMsecs)
          throws UnknownHostException, IOException, CycApiException {
    InferenceResultSet rs = executeQuery(query, makeELMt(mt), queryProperties, timeoutMsecs);
    try {
      return rs.getTruthValue();
    } finally {
      rs.close();
    }
  }

  /**
   * Returns true if the  Cyc query (with inference parameters) is proven true.
   *
   * @param query the query expression
   * @param mt the inference microtheory
   * @param queryProperties queryProperties the list of query property keywords
   * and values, or null if the defaults are to used
   * @param timeoutMsecs the time in milliseconds to wait before giving up,
   * set to zero in order to wait forever
   *
   * @return true if the query is proven true.
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error or if there are open variables in the query
   * @throws TimeOutException if the calculation takes too long
   */
  public boolean isQueryTrue(CycFormulaSentence query, CycObject mt, InferenceParameters queryProperties, long timeoutMsecs)
          throws UnknownHostException, IOException, CycApiException {
    InferenceResultSet rs = executeQuery(query, makeELMt(mt), queryProperties, timeoutMsecs);
    try {
      return rs.getTruthValue();
    } finally {
      rs.close();
    }
  }

  /**
   * Asks a Cyc query (new inference parameters) and returns the binding list for the given variable.
   *
   * @param variable the unbound variable for which bindings are sought
   * @param query the query expression
   * @param mt the inference microtheory
   * @param queryProperties queryProperties the list of query property keywords and values, or null if the defaults are to used
   *
   * @return the binding list resulting from the given query
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList<Object> queryVariable(final CycVariable queryVariable,
          final CycList query, final CycObject mt,
          final InferenceParameters queryProperties)
          throws UnknownHostException, IOException, CycApiException {
    return queryVariable(queryVariable, query, mt, queryProperties, 0);
  }

  /**
   * Asks a Cyc query (new inference parameters) and returns the binding list for the given variable.
   *
   * @param queryVariable the unbound variable for which bindings are sought
   * @param query the query expression
   * @param mt the inference microtheory
   *
   * @return the binding list resulting from the given query
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList<Object> queryVariable(final CycVariable queryVariable,
          final CycFormulaSentence query, final CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return queryVariable(queryVariable, query, mt, new DefaultInferenceParameters(this));
  }

  /**
   * Asks a Cyc query (new inference parameters) and returns the binding list for the given variable.
   *
   * @param queryVariable the unbound variable for which bindings are sought
   * @param query the query expression
   * @param mt the inference microtheory
   * @param queryProperties queryProperties the list of query property keywords and values, or null if the defaults are to used
   *
   * @return the binding list resulting from the given query
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList<Object> queryVariable(final CycVariable queryVariable,
          final CycFormulaSentence query, final CycObject mt,
          final InferenceParameters queryProperties)
          throws UnknownHostException, IOException, CycApiException {
    final InferenceResultSet rs = executeQuery(query, makeELMt(mt), queryProperties);
    return queryVariableLow(queryVariable, rs);
  }

  /**
   * Asks a Cyc query (new inference parameters) and returns the binding list for the given variable.
   *
   * @param queryVariable the unbound variable for which bindings are sought
   * @param query the query expression
   * @param mt the inference microtheory (given in String, CycObject or ELMt form)
   * @param queryProperties queryProperties the list of query property keywords and values, or null if the defaults are to used
   *
   * @return the binding list resulting from the given query
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList<Object> queryVariable(final CycVariable queryVariable,
          final String query, final Object mt,
          final InferenceParameters queryProperties,
          final long timeoutMsecs)
          throws UnknownHostException, IOException, CycApiException {
    final InferenceResultSet rs = executeQuery(query, mt, queryProperties, timeoutMsecs);
    return queryVariableLow(queryVariable, rs);
  }

  /**
   * Asks a Cyc query (new inference parameters) and returns the binding list for the given variable.
   *
   * @param variable the unbound variable for which bindings are sought
   * @param query the query expression
   * @param mt the inference microtheory
   * @param queryProperties queryProperties the list of query property keywords and values, or null if the defaults are to used
   * @param timeoutMsecs the amount of time in milliseconds to wait before giving up, set to
   * zero in order to wait forever.
   * @return the binding list resulting from the given query
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   * @throws TimeOutException if the calculation takes too long
   */
  public CycList<Object> queryVariable(final CycVariable queryVariable,
          final CycList query, final CycObject mt,
          final InferenceParameters queryProperties, long timeoutMsecs)
          throws UnknownHostException, IOException, CycApiException, TimeOutException {
    InferenceResultSet rs = null;
    try {
      rs = executeQuery(query, makeELMt(mt), queryProperties, timeoutMsecs);
      return queryVariableLow(queryVariable, rs);
    } finally {
      return new CycList<Object>();
    }
  }

  public CycList<Object> queryVariableLow(final CycVariable queryVariable,
          final InferenceResultSet rs)
          throws UnknownHostException, IOException, CycApiException, TimeOutException {
    CycList result = new CycList();
    try {
      if (rs.getCurrentRowCount() == 0) {
        return result;
      }
      int colIndex = rs.findColumn(queryVariable);
      if (colIndex < 0) {
        throw new CycApiException("Unable to find variable: " + queryVariable);
      }
      while (rs.next()) {
        result.add(rs.getObject(colIndex));
      }
      return result;
    } finally {
      if (rs != null) {
        rs.close();
      }
    }
  }

  /**
   * Asks a Cyc query (new inference parameters) and returns the binding list for the given variable.
   *
   * @param variable the unbound variable for which bindings are sought
   * @param query the query expression
   * @param mt the inference microtheory
   * @param queryProperties queryProperties the list of query property keywords and values, or null if the defaults are to used
   * @param timeoutMsecs the amount of time in milliseconds to wait before giving up, set to
   * zero in order to wait forever.
   * @return the binding list resulting from the given query
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   * @throws TimeOutException if the calculation takes too long
   */
  public CycList<Object> queryVariable(final CycVariable queryVariable,
          final CycFormulaSentence query, final CycObject mt,
          final InferenceParameters queryProperties, long timeoutMsecs)
          throws UnknownHostException, IOException, CycApiException, TimeOutException {
    InferenceResultSet rs = executeQuery(query, makeELMt(mt), queryProperties, timeoutMsecs);
    return queryVariableLow(queryVariable, rs);
  }

  /**
   * Asks a Cyc query (new inference parameters) and returns the binding list for the given variable.
   *
   * @param variable the unbound variable for which bindings are sought
   * @param query the query expression
   * @param mt the inference microtheory
   * @param queryProperties queryProperties the list of query property keywords and values, or null if the defaults are to used
   * @param inferenceProblemStoreName the problem store name
   *
   * @return the binding list resulting from the given query
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList queryVariable(final CycVariable queryVariable,
          final CycList query,
          final CycObject mt,
          final InferenceParameters queryProperties,
          final String inferenceProblemStoreName)
          throws UnknownHostException, IOException, CycApiException {
    if (queryVariable == null) {
      throw new NullPointerException("queryVariables must not be null");
    }
    if (query == null) {
      throw new NullPointerException("query must not be null");
    }
    if (query.isEmpty()) {
      throw new IllegalArgumentException("query must not be empty");
    }
    if (mt == null) {
      throw new NullPointerException("mt must not be null");
    }
    if (inferenceProblemStoreName == null) {
      throw new NullPointerException("inferenceProblemStoreName must not be null");
    }
    if (inferenceProblemStoreName.length() == 0) {
      throw new IllegalArgumentException("inferenceProblemStoreName must not be an empty list");
    }
    final InferenceParameters tempQueryProperties = (queryProperties == null) ? getHLQueryProperties() : queryProperties;
    tempQueryProperties.put(makeCycSymbol(":problem-store"), makeCycSymbol("problem-store", false));
    final String script =
            "(clet ((problem-store (find-problem-store-by-name \"" + inferenceProblemStoreName + "\")))"
            + "  (query-variable " + queryVariable.stringApiValue() + " "
            + query.stringApiValue() + " " + makeELMt(mt).stringApiValue() + " " + queryPropertiesToString(tempQueryProperties) + "))";
    return converseList(script);
  }

  /**
   * Asks a Cyc query (new inference parameters) and returns the binding list for the given variable list.
   *
   * @param variables the list of unbound variables for which bindings are sought
   * @param query the query expression
   * @param mt the inference microtheory
   * @param queryProperties queryProperties the list of query property keywords and values, or null if the defaults are to be used
   *
   * @return the binding list resulting from the given query
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList<Object> queryVariables(final CycList<CycVariable> queryVariables,
          final CycList<Object> query,
          final CycObject mt,
          final InferenceParameters queryProperties)
          throws UnknownHostException, IOException, CycApiException {
    // @todo use inference property timeout rather than 0 if given
    return queryVariablesLow(queryVariables, query, mt, queryProperties, 0);
  }

  /**
   * Asks a Cyc query (new inference parameters) and returns the binding list for the given variable list.
   *
   * @param variables the list of unbound variables for which bindings are sought
   * @param query the query expression
   * @param mt the inference microtheory
   * @param queryProperties queryProperties the list of query property keywords and values, or null if the defaults are to be used
   *
   * @return the binding list resulting from the given query
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList<Object> queryVariables(final CycList<CycVariable> queryVariables,
          final CycFormulaSentence query,
          final CycObject mt,
          final InferenceParameters queryProperties)
          throws UnknownHostException, IOException, CycApiException {
    return queryVariablesLow(queryVariables, query, mt, queryProperties, 0);
  }

  /**
   * Asks a Cyc query (new inference parameters) and returns the binding list for the given variable list.
   *
   * @param variables the list of unbound variables for which bindings are sought
   * @param query the query expression
   * @param mt the inference microtheory
   * @param queryProperties queryProperties the list of query property keywords and values, or null if the defaults are to be used
   *
   * @return the binding list resulting from the given query
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  @SuppressWarnings("unchecked")
  public CycList<Object> queryVariables(final CycList<CycVariable> queryVariables,
          final String query,
          final Object mt,
          final InferenceParameters queryProperties,
          final long timeoutMsecs)
          throws UnknownHostException, IOException, CycApiException {
    final String command = makeSubLStmt("query-template", queryVariables, query, makeELMt(mt), queryProperties);
    SubLWorkerSynch worker = new DefaultSubLWorkerSynch(command, this, timeoutMsecs);
    if (CycObjectFactory.nil.equals(worker.getWork())) {
      return new CycList<Object>();
    }
    return (CycList<Object>) worker.getWork();
  }

  private CycList<Object> queryVariablesLow(final CycList<CycVariable> queryVariables,
          final CycObject query,
          final CycObject mt,
          final InferenceParameters queryProperties,
          final long timeoutMsecs)
          throws UnknownHostException, IOException, CycApiException {
    final String command = makeSubLStmt("query-template", queryVariables, query, makeELMt(mt), queryProperties);
    SubLWorkerSynch worker = new DefaultSubLWorkerSynch(command, this, timeoutMsecs);
    if (CycObjectFactory.nil.equals(worker.getWork())) {
      return new CycList<Object>();
    }
    return (CycList<Object>) worker.getWork();
  }

  /**
   * Asks a Cyc query (new inference parameters) and returns the binding list for the given variable list.
   *
   * @param queryVariables the list of unbound variables for which bindings are sought
   * @param query the query expression
   * @param mt the inference microtheory
   * @param queryProperties queryProperties the list of query property keywords and values, or null if the defaults are to be used
   * @param inferenceProblemStoreName the problem store name
   *
   * @return the binding list resulting from the given query
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList queryVariables(final CycList queryVariables,
          final CycList query,
          final CycObject mt,
          final InferenceParameters queryProperties,
          final String inferenceProblemStoreName)
          throws UnknownHostException, IOException, CycApiException {
    if (query.isEmpty()) {
      throw new IllegalArgumentException("query must not be empty");
    }
    return queryVariablesInternal(queryVariables, query, mt, queryProperties, inferenceProblemStoreName, 0);
  }

  /**
   * Asks a Cyc query (new inference parameters) and returns the binding list for the given variable list.
   *
   * @param queryVariables the list of unbound variables for which bindings are sought
   * @param query the query expression
   * @param mt the inference microtheory
   * @param queryProperties queryProperties the list of query property keywords and values, or null if the defaults are to be used
   * @param inferenceProblemStoreName the problem store name
   *
   * @return the binding list resulting from the given query
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList queryVariables(final CycList<CycVariable> queryVariables,
          final CycFormulaSentence query,
          final CycObject mt,
          final InferenceParameters queryProperties,
          final String inferenceProblemStoreName)
          throws UnknownHostException, IOException, CycApiException {
    return queryVariablesInternal(queryVariables, query, mt, queryProperties, inferenceProblemStoreName, 0);
  }

  private CycList queryVariablesInternal(final CycList queryVariables,
          final CycObject query,
          final CycObject mt,
          final InferenceParameters queryProperties,
          final String inferenceProblemStoreName,
          final long timeoutMsecs)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (queryVariables == null) {
      throw new NullPointerException("queryVariables must not be null");
    }
    if (queryVariables.isEmpty()) {
      throw new IllegalArgumentException("queryVariables must not be empty");
    }
    if (query == null) {
      throw new NullPointerException("query must not be null");
    }
    if (mt == null) {
      throw new NullPointerException("mt must not be null");
    }
    if (inferenceProblemStoreName == null) {
      throw new NullPointerException("inferenceProblemStoreName must not be null");
    }
    if (inferenceProblemStoreName.length() == 0) {
      throw new IllegalArgumentException("inferenceProblemStoreName must not be an empty list");
    }
    final InferenceParameters tempQueryProperties = (queryProperties == null) ? getHLQueryProperties() : queryProperties;
    tempQueryProperties.put(makeCycSymbol(":problem-store"), makeCycSymbol("problem-store", false));
    final String script =
            "(clet ((problem-store (find-problem-store-by-name \"" + inferenceProblemStoreName + "\")))"
            + "  (query-template " + queryVariables.stringApiValue() + " "
            + query.stringApiValue() + " " + makeELMt(mt).stringApiValue() + " " + queryPropertiesToString(tempQueryProperties) + "))";
    SubLWorkerSynch worker = new DefaultSubLWorkerSynch(script, this, timeoutMsecs);
    if (CycObjectFactory.nil.equals(worker.getWork())) {
      return new CycList<Object>();
    }
    return (CycList) worker.getWork();
  }

  /**
   * Asks a Cyc query and returns the binding list. Properties:
   * @param query the query expression
   * @param mt the inference microtheory
   * @param maxTransformationDepth the Integer maximum transformation depth or nil for no limit
   * @param maxNumber the Integer maximum number of returned bindings or nil for no limit
   * @param maxTimeSeconds the Integer maximum number of seconds inference duration or nil for no
   *        limit
   * @param maxProofDepth the Integer maximum number of levels in the proof tree or nil for no
   *        limit
   *
   * @return the binding list of answers for the given query and inference property settings
   *
   * @throws IOException if a communication error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList askCycQuery(CycList query,
          CycObject mt,
          Object maxTransformationDepth,
          Object maxNumber,
          Object maxTimeSeconds,
          Object maxProofDepth)
          throws UnknownHostException, IOException, CycApiException {
    HashMap queryProperties = new HashMap();
    queryProperties.put(makeCycSymbol(
            ":max-transformation-depth"),
            maxTransformationDepth);
    queryProperties.put(makeCycSymbol(
            ":max-number"),
            maxNumber);
    queryProperties.put(makeCycSymbol(
            ":max-time"),
            maxTimeSeconds);
    queryProperties.put(makeCycSymbol(
            ":max-proof-depth"),
            maxProofDepth);
    queryProperties.put(makeCycSymbol(
            ":forget-extra-results?"),
            CycObjectFactory.t);

    return askCycQuery(query,
            mt,
            queryProperties);
  }

  /**
   * Asks a Cyc query and returns the binding list.
   * @deprecated use <code>executeQuery</code>
   * @param query the query expression
   * @param mt the inference microtheory
   * @param queryProperties queryProperties the list of query property keywords and values
   *
   * @return the binding list resulting from the given query
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList askCycQuery(CycList query, CycObject mt, HashMap queryProperties)
          throws UnknownHostException, IOException, CycApiException {
    CycList parameterList = new CycList();
    Iterator iter = queryProperties.entrySet().iterator();

    if (iter.hasNext()) {
      while (iter.hasNext()) {
        Entry mapEntry = (Entry) iter.next();
        CycSymbol queryParameterKeyword = (CycSymbol) mapEntry.getKey();
        parameterList.add(queryParameterKeyword);

        Object queryParameterValue = mapEntry.getValue();
        parameterList.add(queryParameterValue);
      }
    }
    String command = makeSubLStmt(CYC_QUERY, query, makeELMt(mt), parameterList);

    return converseList(command);
  }

  /**
   * Returns a list of bindings for a query with a single unbound variable.
   *
   * @param query the query to be asked in the knowledge base
   * @param variable the single unbound variable in the query for which bindings are sought
   * @param mt the microtheory in which the query is asked
   *
   * @return a list of bindings for the query
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList queryVariable(final CycList query,
          final CycVariable variable,
          final CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    StringBuilder queryBuffer = new StringBuilder();
    queryBuffer.append("(clet ((*cache-inference-results* nil) ");
    queryBuffer.append("       (*compute-inference-results* nil) ");
    queryBuffer.append("       (*unique-inference-result-bindings* t) ");
    queryBuffer.append("       (*generate-readable-fi-results* nil)) ");
    queryBuffer.append("  (without-wff-semantics ");
    queryBuffer.append("    (ask-template ").append(variable.stringApiValue()).append(" ");
    queryBuffer.append("                  ").append(query.stringApiValue()).append(" ");
    queryBuffer.append("                  ").append(makeELMt(
            mt).stringApiValue()).append(" ");
    queryBuffer.append("                  0 nil nil nil)))");

    CycList answer = converseList(queryBuffer.toString());

    return canonicalizeList(answer);
  }

  /**
   * Returns a list of bindings for a query with a single unbound variable.
   *
   * @deprecated use queryVariable
   * @param query the query to be asked in the knowledge base
   * @param variable the single unbound variable in the query for which bindings are sought
   * @param mt the microtheory in which the query is asked
   *
   * @return a list of bindings for the query
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList askWithVariable(CycList query,
          CycVariable variable,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    StringBuilder queryBuffer = new StringBuilder();
    queryBuffer.append("(clet ((*cache-inference-results* nil) ");
    queryBuffer.append("       (*compute-inference-results* nil) ");
    queryBuffer.append("       (*unique-inference-result-bindings* t) ");
    queryBuffer.append("       (*generate-readable-fi-results* nil)) ");
    queryBuffer.append("  (without-wff-semantics ");
    queryBuffer.append("    (ask-template ").append(variable.stringApiValue()).append(" ");
    queryBuffer.append("                  ").append(query.stringApiValue()).append(" ");
    queryBuffer.append("                  ").append(makeELMt(
            mt).stringApiValue()).append(" ");
    queryBuffer.append("                  0 nil nil nil)))");

    CycList answer = converseList(queryBuffer.toString());

    return canonicalizeList(answer);
  }

  /**
   * Returns a list of bindings for a query with unbound variables.  The bindings each consist of a
   * list in the order of the unbound variables list parameter, in which each bound term is the
   * binding for the corresponding variable.
   *
   * @deprecated use queryVariables
   * @param query the query to be asked in the knowledge base
   * @param variables the list of unbound variables in the query for which bindings are sought
   * @param mt the microtheory in which the query is asked
   *
   * @return a list of bindings for the query
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList askWithVariables(CycList query,
          List variables,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    StringBuilder queryBuffer = new StringBuilder();
    queryBuffer.append("(clet ((*cache-inference-results* nil) ");
    queryBuffer.append("       (*compute-inference-results* nil) ");
    queryBuffer.append("       (*unique-inference-result-bindings* t) ");
    queryBuffer.append("       (*generate-readable-fi-results* nil)) ");
    queryBuffer.append("  (without-wff-semantics ");
    queryBuffer.append("    (ask-template ").append((new CycList(variables)).stringApiValue()).append(" ");
    queryBuffer.append("                  ").append(query.stringApiValue()).append(" ");
    queryBuffer.append("                  ").append(mt.stringApiValue()).append(" ");
    queryBuffer.append("                  0 nil nil nil)))");

    CycList bindings = converseList(queryBuffer.toString());
    CycList canonicalBindings = new CycList();
    Iterator iter = bindings.iterator();

    while (iter.hasNext()) {
      canonicalBindings.add(this.canonicalizeList((CycList) iter.next()));
    }
    return canonicalBindings;
  }

  /**
   * Returns <tt>true</tt> iff the query is true in the knowledge base.
   *
   * @deprecated
   * @param query the query to be asked in the knowledge base
   * @param mt the microtheory in which the query is asked
   *
   * @return <tt>true</tt> iff the query is true in the knowledge base
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isQueryTrue(CycList query, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    String command = makeSubLStmt(CYC_QUERY, canonicalizeList(query), makeELMt(mt));
    CycList response = converseList(command);

    return response.size() > 0;
  }

  /**
   * Returns <tt>true</tt> iff the query is true in the knowledge base, implements a cache to avoid
   * asking the same question twice from the KB.
   *
   * @deprecated
   * @param query the query to be asked in the knowledge base
   * @param mt the microtheory in which the query is asked
   *
   * @return <tt>true</tt> iff the query is true in the knowledge base
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isQueryTrue_Cached(CycList query,
          CycObject mt)
          throws IOException, CycApiException {
    Boolean isQueryTrue = askCache.get(query);

    if (isQueryTrue != null) {
      return isQueryTrue.booleanValue();
    }

    final boolean answer = isQueryTrue(query, makeELMt(mt));
    askCache.put(query, answer);

    return answer;
  }

  /**
   * Returns the count of the instances of the given collection.
   *
   * @param collection the collection whose instances are counted
   * @param mt microtheory (including its genlMts) in which the count is determined
   *
   * @return the count of the instances of the given collection
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public int countAllInstances(CycFort collection,
          CycObject mt)
          throws IOException, CycApiException {
    return this.converseInt("(count-all-instances " + collection.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Returns the count of the instances of the given collection, implements a cache to avoid asking
   * the same question twice from the KB.
   *
   * @param collection the collection whose instances are counted
   * @param mt microtheory (including its genlMts) in which the count is determined
   *
   * @return the count of the instances of the given collection
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public int countAllInstances_Cached(CycFort collection, CycObject mt)
          throws IOException, CycApiException {
    Integer countAllInstances = countAllInstancesCache.get(collection);

    if (countAllInstances != null) {
      return countAllInstances;
    }

    final int answer = countAllInstances(collection, makeELMt(mt));
    countAllInstancesCache.put(collection, answer);

    return answer;
  }

  /**
   * Gets a list of the backchaining implication rules which might apply to the given rule.
   *
   * @param predicate the predicate for which backward chaining implication rules are sought
   * @param formula the literal for which backward chaining implication rules are sought
   * @param mt the microtheory (and its genlMts) in which the search for backchaining implication
   *        rules takes place
   *
   * @return a list of the backchaining implication rules which might apply to the given predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getBackchainImplicationRules(CycConstant predicate,
          CycList formula, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    StringBuilder command = new StringBuilder();

    if (makeELMt(mt).equals(inferencePSC) || makeELMt(mt).equals(
            everythingPSC)) {
      command.append("(clet (backchain-rules formula) ");
      command.append("  (with-all-mts ");
      command.append("    (do-predicate-rule-index (rule ").
              append(predicate.stringApiValue()).
              append(" :pos nil :backward) ");
      command.append("       (csetq formula (assertion-el-formula rule)) ");
      command.append("       (pwhen (cand (eq (first formula) #$implies) ");
      command.append("                    (unify-el-possible ").
              append(formula.stringApiValue()).
              append(" ");
      command.append("                                          (third formula))) ");
      command.append("         (cpush formula backchain-rules)))) ");
      command.append("   backchain-rules)");
    } else {
      command.append("(clet (backchain-rules formula) ");
      command.append("  (with-inference-mt-relevance ").
              append(makeELMt(mt).stringApiValue()).
              append(" ");
      command.append("    (do-predicate-rule-index (rule ").
              append(predicate.stringApiValue()).
              append(" :pos nil :backward) ");
      command.append("       (csetq formula (assertion-el-formula rule)) ");
      command.append("       (pwhen (cand (eq (first formula) #$implies) ");
      command.append("                    (unify-el-possible ").
              append(formula.stringApiValue()).
              append(" ");
      command.append("                                          (third formula))) ");
      command.append("         (cpush formula backchain-rules)))) ");
      command.append("   backchain-rules)");
    }

    //this.traceOn();
    return converseList(command.toString());
  }

  /**
   * Gets a list of the forward chaining implication rules which might apply to the given rule.
   *
   * @param predicate the predicate for which forward chaining implication rules are sought
   * @param formula the literal for which forward chaining implication rules are sought
   * @param mt the microtheory (and its genlMts) in which the search for forward chaining rules
   *        takes place
   *
   * @return a list of the forward chaining implication rules which might apply to the given
   *         predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getForwardChainRules(CycConstant predicate,
          CycList formula, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    StringBuilder command = new StringBuilder();
    if (makeELMt(mt).equals(inferencePSC) || makeELMt(mt).equals(
            everythingPSC)) {
      command.append("(clet (backchain-rules formula) ");
      command.append("  (with-all-mts ");
      command.append("    (do-predicate-rule-index (rule ").append(predicate.stringApiValue()).append(" :pos nil :forward) ");
      command.append("       (csetq formula (assertion-el-formula rule)) ");
      command.append("       (pwhen (cand (eq (first formula) #$implies) ");
      command.append("                    (unify-el-possible ").append(formula.stringApiValue()).append(" ");
      command.append("                                          (third formula))) ");
      command.append("         (cpush formula backchain-rules)))) ");
      command.append("   backchain-rules)");
    } else {
      command.append("(clet (backchain-rules formula) ");
      command.append("  (with-inference-mt-relevance ").append(makeELMt(mt).stringApiValue()).append(" ");
      command.append("    (do-predicate-rule-index (rule ").append(predicate.stringApiValue()).append(" :pos nil :forward) ");
      command.append("       (csetq formula (assertion-el-formula rule)) ");
      command.append("       (pwhen (cand (eq (first formula) #$implies) ");
      command.append("                    (unify-el-possible ").append(formula.stringApiValue()).append(" ");
      command.append("                                          (third formula))) ");
      command.append("         (cpush formula backchain-rules)))) ");
      command.append("   backchain-rules)");
    }

    return converseList(command.toString());
  }

  /**
   * Gets a list of the backchaining implication rules which might apply to the given predicate.
   *
   * @param predicate the predicate for which backchaining rules are sought
   * @param mt the microtheory (and its genlMts) in which the search for backchaining rules takes
   *        place
   *
   * @return a list of the backchaining implication rules which might apply to the given predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getBackchainRules(CycConstant predicate, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    StringBuilder command = new StringBuilder();
    if (makeELMt(mt).equals(inferencePSC) || makeELMt(mt).equals(
            everythingPSC)) {
      command.append("(clet (backchain-rules) ");
      command.append("  (with-all-mts ");
      command.append("    (do-predicate-rule-index (rule ").append(predicate.stringApiValue()).append(" ");
      command.append("                                :sense :pos ");
      command.append("                                :done nil ");
      command.append("                                :direction :backward) ");
      command.append("       (pwhen (eq (first (assertion-el-formula rule)) #$implies) ");
      command.append("         (cpush (assertion-el-formula rule) backchain-rules)))) ");
      command.append("   backchain-rules)");
    } else {
      command.append("(clet (backchain-rules) ");
      command.append("  (with-inference-mt-relevance ").append(makeELMt(mt).stringApiValue()).append(" ");
      command.append("    (do-predicate-rule-index (rule ").append(predicate.stringApiValue()).append(" ");
      command.append("                                :sense :pos ");
      command.append("                                :done nil ");
      command.append("                                :direction :backward) ");
      command.append("       (pwhen (eq (first (assertion-el-formula rule)) #$implies) ");
      command.append("         (cpush (assertion-el-formula rule) backchain-rules)))) ");
      command.append("   backchain-rules)");
    }

    //this.traceOn();
    return converseList(command.toString());
  }

  /**
   * Gets a list of the forward chaining implication rules which might apply to the given
   * predicate.
   *
   * @param predicate the predicate for which forward chaining rules are sought
   * @param mt the microtheory (and its genlMts) in which the search for forward chaining rules
   *        takes place
   *
   * @return a list of the forward chaining implication rules which might apply to the given
   *         predicate
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getForwardChainRules(CycConstant predicate,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    StringBuilder command = new StringBuilder();

    if (makeELMt(mt).equals(inferencePSC) || makeELMt(mt).equals(
            everythingPSC)) {
      command.append("(clet (backchain-rules) ");
      command.append("  (with-all-mts ");
      command.append("    (do-predicate-rule-index (rule ").append(predicate.stringApiValue()).append(" ");
      command.append("                                :sense :pos ");
      command.append("                                :done nil ");
      command.append("                                :direction :forward) ");
      command.append("       (pwhen (eq (first (assertion-el-formula rule)) #$implies) ");
      command.append("         (cpush (assertion-el-formula rule) backchain-rules)))) ");
      command.append("   backchain-rules)");
    } else {
      command.append("(clet (backchain-rules) ");
      command.append("  (with-inference-mt-relevance ").append(makeELMt(mt).stringApiValue()).append(" ");
      command.append("    (do-predicate-rule-index (rule ").append(predicate.stringApiValue()).append(" ");
      command.append("                                :sense :pos ");
      command.append("                                :done nil ");
      command.append("                                :direction :forward) ");
      command.append("       (pwhen (eq (first (assertion-el-formula rule)) #$implies) ");
      command.append("         (cpush (assertion-el-formula rule) backchain-rules)))) ");
      command.append("   backchain-rules)");
    }

    return converseList(command.toString());
  }

  /**
   * Gets the value of a given KB symbol.  This is intended mainly for test case setup.
   *
   * @param cycSymbol the KB symbol which will have a value bound
   *
   * @return the value assigned to the symbol
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public Object getSymbolValue(CycSymbol cycSymbol)
          throws UnknownHostException, IOException, CycApiException {
    return converseObject("(symbol-value " + cycSymbol.stringApiValue() + ")");
  }

  /**
   * Sets a KB symbol to have the specified value.  This is intended mainly for test case setup. If
   * the symbol does not exist at the KB, then it will be created and assigned the value.
   *
   * @param cycSymbol the KB symbol which will have a value bound
   * @param value the value assigned to the symbol
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void setSymbolValue(CycSymbol cycSymbol, Object value)
          throws UnknownHostException, IOException, CycApiException {
    converseVoid(makeSubLStmt("csetq", new SubLAPIHelper.AsIsTerm(cycSymbol), value));
  }

  /**
   * Returns <tt>true</tt> iff <tt>CycList</tt> represents a well formed formula.
   *
   * @param cycList the candidate well-formed-formula
   *
   * @return true iff cycList represents a well formed formula
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isWellFormedFormula(CycList cycList)
          throws UnknownHostException, IOException, CycApiException {
    return isWellFormedFormulaInternal(cycList);
  }

  /**
   * Returns <tt>true</tt> iff <tt>CycList</tt> represents a well formed formula.
   *
   * @param formula the candidate well-formed-formula
   *
   * @return true iff cycList represents a well formed formula
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isWellFormedFormula(CycFormula formula)
          throws UnknownHostException, IOException, CycApiException {
    return isWellFormedFormulaInternal(formula);
  }

  private boolean isWellFormedFormulaInternal(CycObject cycList)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean(makeSubLStmt(WITH_ALL_MTS, makeNestedSubLStmt(EL_WFF, cycList)));
  }

  /**
   * Returns <tt>true</tt> iff backchain inference on the given predicate is required.
   *
   * @param predicate the <tt>CycConstant</tt> predicate for which backchaining required status is
   *        sought
   * @param mt microtheory (including its genlMts) in which the backchaining required status is
   *        sought
   *
   * @return <tt>true</tt> iff backchain inference on the given predicate is required
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isBackchainRequired(CycConstant predicate,
          CycObject mt)
          throws IOException, CycApiException {
    CycConstant backchainRequired = getKnownConstantByGuid(
            "beaa3d29-9c29-11b1-9dad-c379636f7270");

    return hasSomePredicateUsingTerm(backchainRequired,
            predicate, 1, makeELMt(mt));
  }

  /**
   * Returns <tt>true</tt> iff backchain inference on the given predicate is encouraged.
   *
   * @param predicate the <tt>CycConstant</tt> predicate for which backchaining encouraged status
   *        is sought
   * @param mt microtheory (including its genlMts) in which the backchaining encouraged status is
   *        sought
   *
   * @return <tt>true</tt> iff backchain inference on the given predicate is encouraged
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isBackchainEncouraged(CycConstant predicate,
          CycObject mt)
          throws IOException, CycApiException {
    CycConstant backchainEncouraged = getKnownConstantByGuid(
            "c09d1cea-9c29-11b1-9dad-c379636f7270");

    return hasSomePredicateUsingTerm(backchainEncouraged,
            predicate, 1, makeELMt(mt));
  }

  /**
   * Returns <tt>true</tt> iff backchain inference on the given predicate is discouraged.
   *
   * @param predicate the <tt>CycConstant</tt> predicate for which backchaining discouraged status
   *        is sought
   * @param mt microtheory (including its genlMts) in which the backchaining discouraged status is
   *        sought
   *
   * @return <tt>true</tt> iff backchain inference on the given predicate is discouraged
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isBackchainDiscouraged(CycConstant predicate,
          CycObject mt)
          throws IOException, CycApiException {
    CycConstant backchainDiscouraged = getKnownConstantByGuid(
            "bfcbce14-9c29-11b1-9dad-c379636f7270");

    return hasSomePredicateUsingTerm(backchainDiscouraged,
            predicate, 1, makeELMt(mt));
  }

  /**
   * Returns <tt>true</tt> iff backchain inference on the given predicate is forbidden.
   *
   * @param predicate the <tt>CycConstant</tt> predicate for which backchaining forbidden status is
   *        sought
   * @param mt microtheory (including its genlMts) in which the backchaining forbidden status is
   *        sought
   *
   * @return <tt>true</tt> iff backchain inference on the given predicate is forbidden
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isBackchainForbidden(CycConstant predicate,
          CycObject mt)
          throws IOException, CycApiException {
    CycConstant backchainForbidden = getKnownConstantByGuid(
            "bfa4e9d2-9c29-11b1-9dad-c379636f7270");

    return hasSomePredicateUsingTerm(backchainForbidden,
            predicate, 1, makeELMt(mt));
  }

  /**
   * Returns <tt>true</tt> iff the predicate has the irreflexive property: (#$isa ?PRED
   * #$IrreflexsiveBinaryPredicate).
   *
   * @param predicate the <tt>CycConstant</tt> predicate for which irreflexive status is sought
   * @param mt microtheory (including its genlMts) in which the irreflexive status is sought
   *
   * @return <tt>true</tt> iff the predicate has the irreflexive property: (#$isa ?PRED
   *         #$IrreflexsiveBinaryPredicate)
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isIrreflexivePredicate(CycConstant predicate,
          CycObject mt)
          throws IOException, CycApiException {
    CycConstant irreflexiveBinaryPredicate = getKnownConstantByGuid(
            "bd654be7-9c29-11b1-9dad-c379636f7270");

    return this.isa(predicate,
            irreflexiveBinaryPredicate,
            makeELMt(mt));
  }

  /**
   * Returns <tt>true</tt> iff any ground formula instances exist having the given predicate, and
   * the given term in the given argument position.
   *
   * @param term the term present at the given argument position
   * @param predicate the <tt>CycConstant</tt> predicate for the formula
   * @param argumentPosition the argument position of the given term in the ground formula
   * @param mt microtheory (including its genlMts) in which the existence is sought
   *
   * @return <tt>true</tt> iff any ground formula instances exist having the given predicate, and
   *         the given term in the given argument position
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean hasSomePredicateUsingTerm(CycConstant predicate,
          CycFort term,
          Integer argumentPosition,
          CycObject mt)
          throws IOException, CycApiException {
    String command;
    if (makeELMt(mt).equals(inferencePSC) || makeELMt(mt).equals(everythingPSC)) {
      command = makeSubLStmt(SOME_PRED_VALUE_IN_ANY_MT, term, predicate, argumentPosition);
    } else {
      command = makeSubLStmt(SOME_PRED_VALUE_IN_RELEVANT_MTS, term, predicate,
              makeELMt(mt), argumentPosition);
    }

    //this.traceOn();
    return converseBoolean(command);
  }

  /**
   * Returns the count of the assertions indexed according to the given pattern, using the best
   * index (from among the predicate and argument indices).  The formula can contain variables.
   *
   * @param formula the formula whose indexed instances are counted
   * @param mt microtheory (including its genlMts) in which the count is determined
   *
   * @return the count of the assertions indexed according to the given pattern, using the best
   *         index (from among the predicate and argument indices)
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public int countUsingBestIndex(CycList formula,
          CycObject mt)
          throws IOException, CycApiException {
    String command = makeSubLStmt("with-inference-mt-relevance", makeELMt(mt),
            makeNestedSubLStmt("best-index-count", formula, CycObjectFactory.t, CycObjectFactory.t));
    return converseInt(command);
  }

  /**
   * Imports a MUC (Message Understanding Conference) formatted symbolic expression into cyc via
   * the function which parses the expression and creates assertions for the contained concepts
   * and relations between them.
   *
   * @param mucExpression the MUC (Message Understanding Conference) formatted symbolic expression
   * @param mtName the name of the microtheory in which the imported assertions will be made
   *
   * @return the number of assertions imported from the input MUC expression
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public int importMucExpression(CycList mucExpression,
          String mtName)
          throws IOException, CycApiException {
    String command = makeSubLStmt("convert-netowl-sexpr-to-cycl-assertions",
            mucExpression, mtName);
    return converseInt(command);
  }

  /**
   * Returns a list of parsing expressions, each consisting of a parsing span expression, and a
   * list of parsed terms.
   * <pre>
   * (RKF-PHRASE-READER "penguins" #$RKFEnglishLexicalMicrotheoryPSC #$InferencePSC)
   * ==>
   * (((0) (#$Penguin #$PittsburghPenguins)))
   * </pre>
   *
   * @param text the phrase to be parsed
   * @param parsingMt the microtheory in which lexical info is asked
   * @param domainMt the microtherory in which the info about candidate terms is asked
   *
   * @return a parsing expression consisting of a parsing span expression, and a list of parsed
   *         terms
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList rkfPhraseReader(String text, String parsingMt, String domainMt)
          throws IOException, CycApiException {
    return rkfPhraseReader(text,
            getKnownConstantByName(parsingMt),
            getKnownConstantByName(domainMt));
  }

  /**
   * Returns a list of parsing expressions, each consisting of a parsing span expression, and a
   * list of parsed terms.
   * <pre>
   * (RKF-PHRASE-READER "penguins" #$RKFEnglishLexicalMicrotheoryPSC #$InferencePSC)
   * ==>
   * (((0) (#$Penguin #$PittsburghPenguins)))
   * </pre>
   *
   * @param text the phrase to be parsed
   * @param parsingMt the microtheory in which lexical info is asked
   * @param domainMt the microtherory in which the info about candidate terms is asked
   *
   * @return a parsing expression consisting of a parsing span expression, and a list of parsed
   *         terms
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList rkfPhraseReader(String text,
          CycFort parsingMt,
          CycFort domainMt)
          throws IOException, CycApiException {
    String command = makeSubLStmt("rkf-phrase-reader", text, parsingMt, domainMt);
    return converseList(command);
  }

  /**
   * Returns a list of disambiguation expressions, corresponding to each of the terms in the given
   * list of objects.
   * <pre>
   * (GENERATE-DISAMBIGUATION-PHRASES-AND-TYPES (QUOTE (#$Penguin #$PittsburghPenguins)))
   * ==>
   * ((#$Penguin "penguin" #$Bird "bird")
   *  (#$PittsburghPenguins "the Pittsburgh Penguins" #$IceHockeyTeam "ice hockey team"))
   * </pre>
   *
   * @param objects the list of terms to be disambiguated
   *
   * @return a list of disambiguation expressions, corresponding to each of the terms in the given
   *         list of objects
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList generateDisambiguationPhraseAndTypes(CycList objects)
          throws IOException, CycApiException {
    String command = makeSubLStmt(
            makeCycSymbol("generate-disambiguation-phrases-and-types"), objects);
    return converseList(command);
  }

  public CycList phraseStructureParse(String str)
          throws IOException, CycApiException {
    String command = makeSubLStmt(
            makeCycSymbol("ps-get-cycls-for-phrase"), str);
    return converseList(command);
  }

  /**
   * Returns the arity of the given predicate.
   *
   * @param predicate the given predicate whose number of arguments is sought
   *
   * @return the arity of the given predicate, or zero if the argument is not a predicate
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public int getArity(CycFort predicate)
          throws IOException, CycApiException {
    String command = makeSubLStmt(WITH_ALL_MTS,
            makeNestedSubLStmt("arity", predicate));
    Object object = this.converseObject(command);
    if (object instanceof Integer) {
      return (Integer) object;
    } else {
      return 0;
    }
  }

  /**
   * Returns the list of arg2 values of binary gafs, given the predicate and arg1, looking in all
   * microtheories.
   *
   * @param predicate the given predicate for the gaf pattern
   * @param arg1 the given first argument of the gaf
   *
   * @return the list of arg2 values of the binary gafs
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getArg2s(CycFort predicate,
          Object arg1)
          throws IOException, CycApiException {

    CycVariable variable = CycObjectFactory.makeCycVariable("?arg2");
    final CycFormulaSentence query = CycFormulaSentence.makeCycFormulaSentence(predicate, arg1, variable);

    return queryVariable(variable, query, inferencePSC);
  }

  /**
   * Returns the single (first) arg2 value of a binary gaf, given the predicate and arg0, looking
   * in all microtheories.  Return null if none found.
   *
   * @param predicate the given predicate for the gaf pattern
   * @param arg1 the given first argument of the gaf
   *
   * @return the single (first) arg2 value of the binary gaf(s)
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public Object getArg2(CycFort predicate,
          Object arg1)
          throws IOException, CycApiException {
    CycList arg2s = getArg2s(predicate, arg1);
    if (arg2s.isEmpty()) {
      return null;
    } else {
      return arg2s.first();
    }
  }

  /**
   * Returns true if formula is well-formed in the relevant mt.
   *
   * @param formula the given EL formula
   * @param mt the relevant mt
   *
   * @return true if formula is well-formed in the relevant mt, otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isFormulaWellFormed(CycList formula,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return isFormulaWellFormedInternal(formula, mt);
  }

  /**
   * Returns true if formula is well-formed in the relevant mt.
   *
   * @param formula the given EL formula
   * @param mt the relevant mt
   *
   * @return true if formula is well-formed in the relevant mt, otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isFormulaWellFormed(CycFormula formula,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return isFormulaWellFormedInternal(formula, mt);
  }

  private boolean isFormulaWellFormedInternal(CycObject formula,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(el-formula-ok? " + formula.stringApiValue() + " "
            + makeELMt(mt).stringApiValue() + ")");
  }

  /**
   * Returns true if formula is well-formed Non Atomic Reifable Term.
   *
   * @param formula the given EL formula
   *
   * @return true if formula is well-formed Non Atomic Reifable Term, otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isCycLNonAtomicReifableTerm(CycList formula)
          throws UnknownHostException, IOException, CycApiException {
    return isCycLNonAtomicReifableTermInternal(formula);
  }

  /**
   * Returns true if formula is well-formed Non Atomic Reifable Term.
   *
   * @param formula the given EL formula
   *
   * @return true if formula is well-formed Non Atomic Reifable Term, otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isCycLNonAtomicReifableTerm(CycFormula formula)
          throws UnknownHostException, IOException, CycApiException {
    return isCycLNonAtomicReifableTermInternal(formula);
  }

  private boolean isCycLNonAtomicReifableTermInternal(CycObject formula)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(cycl-nart-p " + formula.stringApiValue() + ")");
  }

  /**
   * Returns true if formula is well-formed Non Atomic Un-reifable Term.
   *
   * @param formula the given EL formula
   *
   * @return true if formula is well-formed Non Atomic Un-reifable Term, otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isCycLNonAtomicUnreifableTerm(CycList formula)
          throws UnknownHostException, IOException, CycApiException {
    return isCycLNonAtomicUnreifableTermInternal(formula);
  }

  /**
   * Returns true if formula is well-formed Non Atomic Un-reifable Term.
   *
   * @param formula the given EL formula
   *
   * @return true if formula is well-formed Non Atomic Un-reifable Term, otherwise false
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isCycLNonAtomicUnreifableTerm(CycFormula formula)
          throws UnknownHostException, IOException, CycApiException {
    return isCycLNonAtomicUnreifableTermInternal(formula);
  }

  private boolean isCycLNonAtomicUnreifableTermInternal(CycObject formula)
          throws UnknownHostException, IOException, CycApiException {
    return converseBoolean("(cycl-naut-p " + formula.stringApiValue() + ")");
  }

  /**
   * Creates a new Collector microtheory and links it more general mts.
   *
   * @param mtName the name of the new collector microtheory
   * @param comment the comment for the new collector microtheory
   * @param genlMts the list of more general microtheories
   *
   * @return the new microtheory
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycConstant createCollectorMt(String mtName,
          String comment,
          List genlMts)
          throws IOException, CycApiException {
    CycConstant collectorMt = getKnownConstantByName("CollectorMicrotheory");

    return createMicrotheory(mtName,
            comment,
            collectorMt,
            genlMts);
  }

  /**
   * Asserts each of the given list of forts to be instances of the given collection in the
   * UniversalVocabularyMt
   *
   * @param fortNames the list of forts
   * @param collectionName
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public void assertIsas(List fortNames,
          String collectionName)
          throws IOException, CycApiException {
    List forts = new ArrayList();

    for (int i = 0; i < forts.size(); i++) {
      Object fort = forts.get(i);

      if (fort instanceof String) {
        forts.add(getKnownConstantByName((String) fort));
      } else if (fort instanceof CycFort) {
        forts.add(fort);
      } else {
        throw new CycApiException(fort + " is neither String nor CycFort");
      }

      assertIsas(forts,
              getKnownConstantByName(collectionName));
    }
  }

  /**
   * Asserts each of the given list of forts to be instances of the given collection in the
   * UniversalVocabularyMt
   *
   * @param forts the list of forts
   * @param collection
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public void assertIsas(List forts,
          CycFort collection)
          throws IOException, CycApiException {
    for (int i = 0; i < forts.size(); i++) {
      assertIsa((CycFort) forts.get(i),
              collection);
    }
  }

  /**
   * Creates a new spindle microtheory in the given spindle system.
   *
   * @param spindleMtName the name of the new spindle microtheory
   * @param comment the comment for the new spindle microtheory
   * @param spindleHeadMtName the name of the spindle head microtheory
   * @param spindleCollectorMtName the name of the spindle head microtheory
   *
   * @return the new spindle microtheory in the given spindle system
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycConstant createSpindleMt(String spindleMtName,
          String comment,
          String spindleHeadMtName,
          String spindleCollectorMtName)
          throws IOException, CycApiException {
    return createSpindleMt(spindleMtName,
            comment,
            getKnownConstantByName(spindleHeadMtName),
            getKnownConstantByName(spindleCollectorMtName));
  }

  /**
   * Creates a new spindle microtheory in the given spindle system.
   *
   * @param spindleMtName the name of the new spindle microtheory
   * @param comment the comment for the new spindle microtheory
   * @param spindleHeadMt the spindle head microtheory
   * @param spindleCollectorMt the spindle head microtheory
   *
   * @return the new spindle microtheory in the given spindle system
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycConstant createSpindleMt(String spindleMtName,
          String comment,
          CycFort spindleHeadMt,
          CycFort spindleCollectorMt)
          throws IOException, CycApiException {
    CycConstant spindleMt = getKnownConstantByName("SpindleMicrotheory");
    List genlMts = new ArrayList();
    genlMts.add(spindleHeadMt);

    CycConstant mt = this.createMicrotheory(spindleMtName,
            comment,
            spindleMt,
            genlMts);
    assertGaf(universalVocabularyMt,
            genlMt,
            spindleCollectorMt,
            mt);

    return mt;
  }

  /**
   * Creates a new binary predicate term.
   *
   * @param predicateName the name of the new binary predicate
   * @param predicateTypeName the type of binary predicate, for example
   *        #$TransitiveBinaryPredicate, which when null defaults to #$BinaryPredicate
   * @param comment the comment for the new binary predicate, or null
   * @param arg1IsaName the argument position one type constraint, or null
   * @param arg2IsaName the argument position two type constraint, or null
   * @param arg1FormatName the argument position one format constraint, or null
   * @param arg2FormatName the argument position two format constraint, or null
   * @param genlPredsName the more general binary predicate of which this new predicate is a
   *        specialization, that when null defaults to #$conceptuallyRelated
   * @param genFormatList the paraphrase generation list string, or null
   * @param genFormatString the paraphrase generation string, or null
   *
   * @return the new binary predicate term
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycConstant createBinaryPredicate(String predicateName,
          String predicateTypeName,
          String comment,
          String arg1IsaName,
          String arg2IsaName,
          String arg1FormatName,
          String arg2FormatName,
          String genlPredsName,
          String genFormatString,
          String genFormatList)
          throws IOException, CycApiException {
    return createBinaryPredicate(predicateName,
            find(predicateTypeName),
            comment,
            find(arg1IsaName),
            find(arg2IsaName),
            find(arg1FormatName),
            find(arg2FormatName),
            find(genlPredsName),
            genFormatString,
            makeCycList(genFormatList));
  }

  /**
   * Creates a new binary predicate term.
   *
   * @param predicateName the name of the new binary predicate
   * @param predicateType the type of binary predicate, for example #$TransitiveBinaryPredicate,
   *        which when null defaults to #$BinaryPredicate
   * @param comment the comment for the new binary predicate, or null
   * @param arg1Isa the argument position one type constraint, or null
   * @param arg2Isa the argument position two type constraint, or null
   * @param arg1Format the argument position one format constraint, or null
   * @param arg2Format the argument position two format constraint, or null
   * @param genlPreds the more general binary predicate of which this new predicate is a
   *        specialization, that when null defaults to #$conceptuallyRelated
   * @param genFormatList the paraphrase generation list string, or null
   * @param genFormatString the paraphrase generation string, or null
   *
   * @return the new binary predicate term
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycConstant createBinaryPredicate(String predicateName,
          CycFort predicateType,
          String comment,
          CycFort arg1Isa,
          CycFort arg2Isa,
          CycFort arg1Format,
          CycFort arg2Format,
          CycFort genlPreds,
          String genFormatString,
          CycList genFormatList)
          throws IOException, CycApiException {
    CycConstant predicate = findOrCreate(predicateName);

    if (predicateType == null) {
      assertIsa(predicate,
              binaryPredicate);
    } else {
      assertIsa(predicate,
              predicateType);
    }

    if (comment != null) {
      assertComment(predicate,
              comment,
              baseKB);
    }

    if (arg1Isa != null) {
      assertArgIsa(predicate,
              1,
              arg1Isa);
    }

    if (arg2Isa != null) {
      assertArgIsa(predicate,
              2,
              arg2Isa);
    }

    if (arg1Format != null) {
      assertArgFormat(predicate,
              1,
              arg1Format);
    }

    if (arg2Format != null) {
      assertArgFormat(predicate,
              2,
              arg2Format);
    }

    if (genlPreds == null) {
      assertGenlPreds(predicate,
              // #$conceptuallyRelated
              getKnownConstantByGuid("bd58803e-9c29-11b1-9dad-c379636f7270"));
    } else {
      assertGenlPreds(predicate,
              genlPreds);
    }

    if ((genFormatString != null) && (genFormatList != null)) {
      assertGenFormat(predicate,
              genFormatString,
              genFormatList);
    }

    return predicate;
  }

  /**
   * Creates a new KB subset collection term.
   *
   * @param constantName the name of the new KB subset collection
   * @param comment the comment for the new KB subset collection
   *
   * @return the new KB subset collection term
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycConstant createKbSubsetCollection(String constantName,
          String comment)
          throws IOException, CycApiException {
    CycConstant kbSubsetCollection = getKnownConstantByName(
            "KBSubsetCollection");
    CycConstant cycConstant = getConstantByName(constantName);

    if (cycConstant == null) {
      cycConstant = createNewPermanent(constantName);
    }

    assertIsa(cycConstant,
            kbSubsetCollection);
    assertComment(cycConstant,
            comment,
            baseKB);
    assertGenls(cycConstant,
            thing);

    CycFort variableOrderCollection = getKnownConstantByGuid(
            "36cf85d0-20a1-11d6-8000-0050dab92c2f");
    assertIsa(cycConstant,
            variableOrderCollection,
            baseKB);

    return cycConstant;
  }

  /**
   * Creates a new collection term.
   *
   * @param collectionName the name of the new collection
   * @param comment the comment for the collection
   * @param commentMtName the name of the microtheory in which the comment is asserted
   * @param isaName the name of the collection of which the new collection is an instance
   * @param genlsName the name of the collection of which the new collection is a subset
   *
   * @return the new collection term
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycConstant createCollection(String collectionName,
          String comment,
          String commentMtName,
          String isaName,
          String genlsName)
          throws IOException, CycApiException {
    CycConstant cycCollection = findOrCreate(collectionName);
    assertComment(cycCollection,
            comment,
            getKnownConstantByName(commentMtName));
    assertIsa(cycCollection,
            getKnownConstantByName(isaName));
    assertGenls(cycCollection,
            getKnownConstantByName(genlsName));

    return cycCollection;
  }

  /**
   * Creates a new collection term.
   *
   * @param collectionName the name of the new collection
   * @param comment the comment for the collection
   * @param commentMt the microtheory in which the comment is asserted
   * @param isa the collection of which the new collection is an instance
   * @param genls the collection of which the new collection is a subset
   *
   * @return the new collection term
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycFort createCollection(String collectionName,
          String comment,
          CycFort commentMt,
          CycFort isa,
          CycFort genls)
          throws IOException, CycApiException {
    return createCollection(findOrCreate(collectionName),
            comment,
            commentMt,
            isa,
            genls);
  }

  /**
   * Creates a new collection term.
   *
   * @param collection the new collection
   * @param comment the comment for the collection
   * @param commentMt the microtheory in which the comment is asserted
   * @param isa the collection of which the new collection is an instance
   * @param genls the collection of which the new collection is a subset
   *
   * @return the new collection term
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycFort createCollection(CycFort collection,
          String comment,
          CycFort commentMt,
          CycFort isa,
          CycFort genls)
          throws IOException, CycApiException {
    assertComment(collection,
            comment,
            commentMt);
    assertIsa(collection,
            isa);
    assertGenls(collection,
            genls);

    return collection;
  }

  /**
   * Creates a new individual term.
   *
   * @param IndividualName the name of the new individual term
   * @param comment the comment for the individual
   * @param commentMt the microtheory in which the comment is asserted
   * @param isa the collection of which the new individual is an instance
   *
   * @return the new individual term
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycFort createIndividual(String IndividualName,
          String comment,
          String commentMt,
          String isa)
          throws IOException, CycApiException {
    return createIndividual(IndividualName,
            comment,
            getKnownConstantByName(commentMt),
            getKnownConstantByName(isa));
  }

  /**
   * Creates a new individual term.
   *
   * @param IndividualName the name of the new individual term
   * @param comment the comment for the individual
   * @param commentMt the microtheory in which the comment is asserted
   * @param isa the collection of which the new individual is an instance
   *
   * @return the new individual term
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycFort createIndividual(String IndividualName,
          String comment,
          CycDenotationalTerm commentMt,
          CycDenotationalTerm isa)
          throws IOException, CycApiException {
    CycFort individual = findOrCreate(IndividualName);
    assertComment(individual,
            comment,
            commentMt);
    assertIsa(individual,
            isa);

    return individual;
  }

  /**
   * Creates a new individual-denoting reifiable unary function term.
   *
   * @param unaryFunction the new collection
   * @param comment the comment for the unary function
   * @param commentMt the microtheory in which the comment is asserted
   * @param arg1Isa the kind of objects this unary function takes as its argument
   * @param resultIsa the kind of object represented by this reified term
   *
   * @return the new individual-denoting reifiable unary function term
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycFort createIndivDenotingUnaryFunction(String unaryFunction,
          String comment,
          String commentMt,
          String arg1Isa,
          String resultIsa)
          throws IOException, CycApiException {
    return createIndivDenotingUnaryFunction(findOrCreate(
            unaryFunction),
            comment,
            getKnownConstantByName(
            commentMt),
            getKnownConstantByName(
            arg1Isa),
            getKnownConstantByName(
            resultIsa));
  }

  /**
   * Creates a new individual-denoting reifiable unary function term.
   *
   * @param unaryFunction the new collection
   * @param comment the comment for the unary function
   * @param commentMt the microtheory in which the comment is asserted
   * @param arg1Isa the kind of objects this unary function takes as its argument
   * @param resultIsa the kind of object represented by this reified term
   *
   * @return the new individual-denoting reifiable unary function term
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycFort createIndivDenotingUnaryFunction(CycFort unaryFunction,
          String comment,
          CycFort commentMt,
          CycFort arg1Isa,
          CycFort resultIsa)
          throws IOException, CycApiException {
    assertComment(unaryFunction,
            comment,
            commentMt);


    // (#$isa unaryFunction #$UnaryFunction)
    assertIsa(unaryFunction,
            getKnownConstantByGuid("bd58af89-9c29-11b1-9dad-c379636f7270"));


    // (#$isa unaryFunction #$ReifiableFunction)
    assertIsa(unaryFunction,
            getKnownConstantByGuid("bd588002-9c29-11b1-9dad-c379636f7270"));


    // (#$isa unaryFunction #$IndividualDenotingFunction)
    assertIsa(unaryFunction,
            getKnownConstantByGuid("bd58fad9-9c29-11b1-9dad-c379636f7270"));


    // (#$isa unaryFunction #$Function-Denotational)
    assertIsa(unaryFunction,
            getKnownConstantByGuid("bd5c40b0-9c29-11b1-9dad-c379636f7270"));
    assertArgIsa(unaryFunction,
            1,
            arg1Isa);
    assertResultIsa(unaryFunction,
            resultIsa);

    return unaryFunction;
  }

  /**
   * Creates a new collection-denoting reifiable unary function term.
   *
   * @param unaryFunction the new collection
   * @param comment the comment for the unary function
   * @param commentMt the microtheory in which the comment is asserted
   * @param arg1Isa the isa type constraint for the argument
   * @param arg1GenlName the genls type constraint for the argument if it is a collection
   * @param resultIsa the isa object represented by this reified term
   * @param resultGenlName the genls object represented by this reified term
   *
   * @return the new collection-denoting reifiable unary function term
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycFort createCollectionDenotingUnaryFunction(String unaryFunction,
          String comment,
          String commentMt,
          String arg1Isa,
          String arg1GenlName,
          String resultIsa,
          String resultGenlName)
          throws IOException, CycApiException {
    CycFort arg1Genl;

    if (arg1GenlName != null) {
      arg1Genl = getKnownConstantByName(arg1GenlName);
    } else {
      arg1Genl = null;
    }

    CycFort resultGenl;

    if (resultGenlName != null) {
      resultGenl = getKnownConstantByName(resultGenlName);
    } else {
      resultGenl = null;
    }

    return createCollectionDenotingUnaryFunction(findOrCreate(
            unaryFunction),
            comment,
            getKnownConstantByName(
            commentMt),
            getKnownConstantByName(
            arg1Isa),
            arg1Genl,
            getKnownConstantByName(
            resultIsa),
            resultGenl);
  }

  /**
   * Creates a new collection-denoting reifiable unary function term.
   *
   * @param unaryFunction the new collection
   * @param comment the comment for the unary function
   * @param commentMt the microtheory in which the comment is asserted
   * @param arg1Isa the isa type constraint for the argument
   * @param arg1Genl the genls type constraint for the argument if it is a collection
   * @param resultIsa the isa object represented by this reified term
   * @param resultGenl the genls object represented by this reified term
   *
   * @return the new collection-denoting reifiable unary function term
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycFort createCollectionDenotingUnaryFunction(CycFort unaryFunction,
          String comment,
          CycFort commentMt,
          CycFort arg1Isa,
          CycFort arg1Genl,
          CycFort resultIsa,
          CycFort resultGenl)
          throws IOException, CycApiException {
    assertComment(unaryFunction,
            comment,
            commentMt);


    // (#$isa unaryFunction #$UnaryFunction)
    assertIsa(unaryFunction,
            getKnownConstantByGuid("bd58af89-9c29-11b1-9dad-c379636f7270"));


    // (#$isa unaryFunction #$ReifiableFunction)
    assertIsa(unaryFunction,
            getKnownConstantByGuid("bd588002-9c29-11b1-9dad-c379636f7270"));


    // (#$isa unaryFunction #$CollectionDenotingFunction)
    assertIsa(unaryFunction,
            getKnownConstantByGuid("bd58806a-9c29-11b1-9dad-c379636f7270"));


    // (#$isa unaryFunction #$Function-Denotational)
    assertIsa(unaryFunction,
            getKnownConstantByGuid("bd5c40b0-9c29-11b1-9dad-c379636f7270"));
    assertArgIsa(unaryFunction,
            1,
            arg1Isa);

    if (arg1Genl != null) {
      assertArg1Genl(unaryFunction,
              arg1Genl);
    }

    assertResultIsa(unaryFunction,
            resultIsa);

    if (resultGenl != null) {
      assertResultGenl(unaryFunction,
              resultGenl);
    }

    return unaryFunction;
  }

  /**
   * Creates a new collection-denoting reifiable binary function term.
   *
   * @param binaryFunction the new collection
   * @param comment the comment for the binary function
   * @param commentMt the microtheory in which the comment is asserted
   * @param arg1IsaName the collection of which the new binary function is an instance
   * @param arg2GenlsName the kind of objects this binary function takes as its first argument, or
   *        null
   * @param arg2IsaName the kind of objects this binary function takes as its second argument, or
   *        null
   * @param arg1GenlsName the general collections this binary function takes as its first argument,
   *        or null
   * @param resultIsa the kind of object represented by this reified term
   *
   * @return the new collection-denoting reifiable binary function term
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycFort createCollectionDenotingBinaryFunction(String binaryFunction,
          String comment,
          String commentMt,
          String arg1IsaName,
          String arg2IsaName,
          String arg1GenlsName,
          String arg2GenlsName,
          String resultIsa)
          throws IOException, CycApiException {
    CycFort arg1Isa = null;
    CycFort arg2Isa = null;
    CycFort arg1Genls = null;
    CycFort arg2Genls = null;

    if (arg1IsaName != null) {
      arg1Isa = getKnownConstantByName(arg1IsaName);
    }

    if (arg2IsaName != null) {
      arg1Isa = getKnownConstantByName(arg2IsaName);
    }

    if (arg1GenlsName != null) {
      arg1Genls = getKnownConstantByName(arg1GenlsName);
    }

    if (arg2GenlsName != null) {
      arg2Genls = getKnownConstantByName(arg2GenlsName);
    }

    return createCollectionDenotingBinaryFunction(findOrCreate(
            binaryFunction),
            comment,
            getKnownConstantByName(
            commentMt),
            arg1Isa,
            arg2Isa,
            arg1Genls,
            arg2Genls,
            getKnownConstantByName(
            resultIsa));
  }

  /**
   * Creates a new collection-denoting reifiable binary function term.
   *
   * @param binaryFunction the new collection
   * @param comment the comment for the binary function
   * @param commentMt the microtheory in which the comment is asserted
   * @param arg1Isa the kind of objects this binary function takes as its first argument, or null
   * @param arg2Isa the kind of objects this binary function takes as its first argument, or null
   * @param arg1Genls the general collections this binary function takes as its first argument, or
   *        null
   * @param arg2Genls the general collections this binary function takes as its second argument, or
   *        null
   * @param resultIsa the kind of object represented by this reified term
   *
   * @return the new collection-denoting reifiable binary function term
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycFort createCollectionDenotingBinaryFunction(CycFort binaryFunction,
          String comment,
          CycFort commentMt,
          CycFort arg1Isa,
          CycFort arg2Isa,
          CycFort arg1Genls,
          CycFort arg2Genls,
          CycFort resultIsa)
          throws IOException, CycApiException {
    assertComment(binaryFunction,
            comment,
            commentMt);


    // (#$isa binaryFunction #$BinaryFunction)
    assertIsa(binaryFunction,
            getKnownConstantByGuid("c0e7247c-9c29-11b1-9dad-c379636f7270"));


    // (#$isa binaryFunction #$ReifiableFunction)
    assertIsa(binaryFunction,
            getKnownConstantByGuid("bd588002-9c29-11b1-9dad-c379636f7270"));


    // (#$isa binaryFunction #$CollectionDenotingFunction)
    assertIsa(binaryFunction,
            getKnownConstantByGuid("bd58806a-9c29-11b1-9dad-c379636f7270"));


    // (#$isa binaryFunction #$Function-Denotational)
    assertIsa(binaryFunction,
            getKnownConstantByGuid("bd5c40b0-9c29-11b1-9dad-c379636f7270"));

    if (arg1Isa != null) {
      assertArgIsa(binaryFunction,
              1,
              arg1Isa);
    }

    if (arg2Isa != null) {
      assertArgIsa(binaryFunction,
              2,
              arg2Isa);
    }

    if (arg1Genls != null) {
      assertArg1Genl(binaryFunction,
              arg1Genls);
    }

    if (arg2Genls != null) {
      assertArg2Genl(binaryFunction,
              arg2Genls);
    }

    assertResultIsa(binaryFunction,
            resultIsa);

    return binaryFunction;
  }

  /**
   * Assert an argument isa contraint for the given relation and argument position. The operation
   * will be added to the KB transcript for replication and archive.
   *
   * @param relation the given relation
   * @param argPosition the given argument position
   * @param argNIsa the argument constraint
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertArgIsa(CycFort relation,
          int argPosition,
          CycFort argNIsa)
          throws UnknownHostException, IOException, CycApiException {
    // (#$argIsa relation argPosition argNIsa)
    CycList sentence = new CycList();
    sentence.add(getKnownConstantByGuid("bee22d3d-9c29-11b1-9dad-c379636f7270"));
    sentence.add(relation);
    sentence.add(argPosition);
    sentence.add(argNIsa);
    assertGaf(sentence, universalVocabularyMt);
  }

  /**
   * Assert an argument one genls contraint for the given relation. The operation will be added to
   * the KB transcript for replication and archive.
   *
   * @param relation the given relation
   * @param argGenl the argument constraint
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertArg1Genl(CycFort relation,
          CycFort argGenl)
          throws UnknownHostException, IOException, CycApiException {
    // (#$arg1Genl relation argGenl)
    CycList sentence = new CycList();
    sentence.add(getKnownConstantByGuid("bd588b1d-9c29-11b1-9dad-c379636f7270"));
    sentence.add(relation);
    sentence.add(argGenl);
    assertGaf(sentence,
            universalVocabularyMt);
  }

  /**
   * Assert an argument two genls contraint for the given relation. The operation will be added to
   * the KB transcript for replication and archive.
   *
   * @param relation the given relation
   * @param argGenl the argument constraint
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertArg2Genl(CycFort relation,
          CycFort argGenl)
          throws UnknownHostException, IOException, CycApiException {
    // (#$arg2Genl relation argGenl)
    CycList sentence = new CycList();
    sentence.add(getKnownConstantByGuid("bd58dcda-9c29-11b1-9dad-c379636f7270"));
    sentence.add(relation);
    sentence.add(argGenl);
    assertGaf(sentence,
            universalVocabularyMt);
  }

  /**
   * Assert an argument three genls contraint for the given relation. The operation will be added
   * to the KB transcript for replication and archive.
   *
   * @param relation the given relation
   * @param argGenl the argument constraint
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertArg3Genl(CycFort relation,
          CycFort argGenl)
          throws UnknownHostException, IOException, CycApiException {
    // (#$arg3Genl relation argGenl)
    CycList sentence = new CycList();
    sentence.add(getKnownConstantByGuid("bd58b8c3-9c29-11b1-9dad-c379636f7270"));
    sentence.add(relation);
    sentence.add(argGenl);
    assertGaf(sentence,
            universalVocabularyMt);
  }

  /**
   * Assert the isa result contraint for the given denotational function. The operation will be
   * added to the KB transcript for replication and archive.
   *
   * @param denotationalFunction the given denotational function
   * @param resultIsa the function's isa result constraint
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertResultIsa(CycFort denotationalFunction,
          CycFort resultIsa)
          throws UnknownHostException, IOException, CycApiException {
    // (#$resultIsa denotationalFunction resultIsa)
    assertGaf(universalVocabularyMt,
            getKnownConstantByGuid("bd5880f1-9c29-11b1-9dad-c379636f7270"),
            denotationalFunction,
            resultIsa);
  }

  /**
   * Assert the genls result contraint for the given denotational function. The operation will be
   * added to the KB transcript for replication and archive.
   *
   * @param denotationalFunction the given denotational function
   * @param resultGenl the function's genls result constraint
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertResultGenl(CycFort denotationalFunction,
          CycFort resultGenl)
          throws UnknownHostException, IOException, CycApiException {
    // (#$resultGenl denotationalFunction resultGenls)
    assertGaf(universalVocabularyMt,
            getKnownConstantByGuid("bd58d6ab-9c29-11b1-9dad-c379636f7270"),
            denotationalFunction,
            resultGenl);
  }

  /**
   * Returns true if this KB is OpenCyc.
   *
   * @return true if this KB is OpenCyc, otherwise false
   *
   * @throws IOException if a data communication error occurs
   * @throws UnknownHostException if cyc server host not found on the network
   */
  public boolean isOpenCyc()
          throws UnknownHostException, IOException {
    boolean answer;

    try {
      answer = converseBoolean("(cyc-opencyc-feature)");
    } catch (CycApiException e) {
      answer = false;
    }

    return answer;
  }

  /**
   * Imports an OWL ontology.
   *
   * @param uri the URI of the ontology
   * @param prefix the prefix to append to names of new constants created for terms in the ontology
   *
   * @return the CycFort representing the imported ontology
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycFort importOwlOntology(final String uri, final String prefix)
          throws IOException, CycApiException {
    final String sourceFile = uri;
    return importOwlOntology(uri, prefix, sourceFile);
  }

  /**
   * Imports an OWL ontology.
   *
   * @param uri the URI of the ontology
   * @param prefix the prefix to append to names of new constants created for terms in the ontology
   * @param sourceFile the path for the file from which to import the ontology
   *
   * @return the CycFort representing the imported ontology
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycFort importOwlOntology(final String uri, final String prefix, final String sourceFile)
          throws IOException, CycApiException {
    final CycFort ontology = null;
    return importOwlOntology(uri, prefix, sourceFile, ontology);
  }

  /**
   * Imports an OWL ontology.
   *
   * @param uri the URI of the ontology
   * @param prefix the prefix to append to names of new constants created for terms in the ontology
   * @param sourceFile the path for the file from which to import the ontology, if not from the URI
   * @param ontology the existing CycFort representing the ontology, if we are to update an already-imported ontology
   *
   * @return the CycFort representing the imported ontology
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycFort importOwlOntology(final String uri, final String prefix,
          final String sourceFile, final CycFort ontology)
          throws IOException, CycApiException {
    final CycFort quotedIsa = null;
    return importOwlOntology(uri, prefix, sourceFile, ontology, quotedIsa);
  }

  /**
   * Imports an OWL ontology.
   *
   * @param uri the URI of the ontology
   * @param prefix the prefix to append to names of new constants created for terms in the ontology
   * @param sourceFile the path for the file from which to import the ontology, if not from the URI
   * @param ontology the existing CycFort representing the ontology, if we are to update an already-imported ontology
   * @param quotedIsa the collection of which newly created terms should be quoted instances. If null, Cyc will create one.
   *
   * @return the CycFort representing the imported ontology
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycFort importOwlOntology(final String uri, final String prefix,
          final String sourceFile, final CycFort ontology, final CycFort quotedIsa)
          throws IOException, CycApiException {
    final CycFort currentCyclist = getCyclist();
    return importOwlOntology(uri, prefix, sourceFile, ontology, quotedIsa, currentCyclist);
  }

  /**
   * Imports an OWL ontology.
   *
   * @param uri the URI of the ontology
   * @param prefix the prefix to append to names of new constants created for terms in the ontology
   * @param sourceFile the path for the file from which to import the ontology, if not from the URI
   * @param ontology the existing CycFort representing the ontology, if we are to update an already-imported ontology
   * @param quotedIsa the collection of which newly created terms should be quoted instances. If null, Cyc will create one.
   * @param cyclist the cyclist to attribute the new terms and assertions to
   *
   * @return the CycFort representing the imported ontology
   *
   * @throws IOException if a communications error occurs
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycFort importOwlOntology(final String uri, final String prefix,
          final String sourceFile, final CycFort ontology, final CycFort quotedIsa,
          final CycFort cyclist)
          throws IOException, CycApiException {
    final String sourceFileString = ((sourceFile != null) && (sourceFile.length() > 0)) ? "\"" + sourceFile + "\"" : "nil";
    final String ontologyString = (ontology == null) ? "nil" : CycFort.stringApiValue(ontology);
    final String quotedIsaString = (quotedIsa == null) ? "nil" : CycFort.stringApiValue(quotedIsa);
    final String cyclistString = (cyclist == null) ? "nil" : CycFort.stringApiValue(cyclist);
    final Object object = converseObject("(import-owl-ontology " + "\"" + uri + "\" " + "\"" + prefix + "\" " + sourceFileString + " " + ontologyString + " " + quotedIsaString + " " + cyclistString + ")");
    if (object instanceof CycFort) {
      return (CycFort) object;
    } else {
      return null;
    }
  }

  /**
   * Returns a constant whose name differs from the given name only by case. Used because Cyc by
   * default requires constant names to be unique by case.
   *
   * @param name the name used to lookup an existing constant
   *
   * @return a constant whose name differs from the given name only by case, otherwise null if none
   *         exists
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycConstant constantNameCaseCollision(String name)
          throws UnknownHostException, IOException, CycApiException {
    Object object = converseObject("(constant-name-case-collision \"" + name + "\")");

    if (object instanceof CycConstant) {
      return (CycConstant) object;
    } else {
      return null;
    }
  }

  /**
   * Returns the list of applicable binary predicates which are elements of any of the given list
   * of KBSubsetCollections.
   *
   * @param kbSubsetCollections the list of KBSubsetCollections
   *
   * @return the list of applicable binary predicates which are elements of any of the given list
   *         of KBSubsetCollections
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList getApplicableBinaryPredicates(CycList kbSubsetCollections)
          throws UnknownHostException, IOException, CycApiException {
    CycList result = new CycList();

    for (int i = 0; i < kbSubsetCollections.size(); i++) {
      CycFort kbSubsetCollection = (CycFort) kbSubsetCollections.get(
              i);
      String query = "(#$and \n" + "  (#$isa ?binary-predicate " + kbSubsetCollection.stringApiValue()
              + ") \n" + "  (#$isa ?binary-predicate #$BinaryPredicate))";
      result.addAllNew(queryVariable(CycObjectFactory.makeCycVariable("?binary-predicate"),
              makeCycSentence(query), inferencePSC, new DefaultInferenceParameters(this)));
    }

    return result;
  }

  /**
   * Returns the list of gafs in which the predicate is a element of the given list of predicates
   * and in which the given term appears in the first argument position.
   *
   * @param cycObject the given term
   * @param predicates the given list of predicates
   * @param mt the relevant inference microtheory
   *
   * @return the list of gafs in which the predicate is a element of the given list of predicates
   *         and in which the given term appears in the first argument position
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList getGafsForPredicates(final CycObject cycObject,
          final List predicates,
          final CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    if (predicates == null) {
      throw new NullPointerException("predicates must not be null");
    }
    if (predicates == null) {
      throw new NullPointerException("predicates must not be null");
    }
    final CycList result = new CycList();

    for (int i = 0; i < predicates.size(); i++) {
      result.addAllNew(getGafs(cycObject,
              (CycFort) predicates.get(
              i),
              makeELMt(mt)));
    }

    return result;
  }

  /**
   * Returns the list of gafs in which the predicate is the given predicate and in which the given
   * term appears in the first argument position.
   *
   * @param cycFort the given term
   * @param predicate the given predicate
   * @param mt the relevant inference microtheory
   *
   * @return the list of gafs in which the predicate is a element of the given list of predicates
   *         and in which the given term appears in the first argument position
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList getGafs(final CycObject cycFort,
          final CycObject predicate,
          final CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    if (cycFort == null) {
      throw new NullPointerException("cycFort must not be null");
    }
    if (predicate == null) {
      throw new NullPointerException("predicate must not be null");
    }
    if (mt == null) {
      throw new NullPointerException("mt must not be null");
      // TODO handle the case where the cycObject is a NAUT,
      //getGafsForNaut
    }
    final CycList gafs = new CycList();
    final String command = "(with-inference-mt-relevance " + makeELMt(mt).stringApiValue() + "\n"
            + "  (pred-values-in-relevant-mts " + cycFort.stringApiValue() + " "
            + predicate.stringApiValue() + "))";
    final CycList values = converseList(command);

    for (int i = 0; i < values.size(); i++) {
      final CycList gaf = new CycList();
      gaf.add(predicate);
      gaf.add(cycFort);
      gaf.add(values.get(i));
      gafs.add(gaf);
    }

    return gafs;
  }

  /**
   * Returns the list of gafs in which the predicate is a element of the given list of predicates
   * and in which the given term appears in the first argument position.
   *
   * @param cycObject the given term
   * @param predicates the given list of predicates
   *
   * @return the list of gafs in which the predicate is a element of the given list of predicates
   *         and in which the given term appears in the first argument position
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList getGafsForPredicates(final CycObject cycObject,
          final List predicates)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    if (predicates == null) {
      throw new NullPointerException("predicates must not be null");
    }
    final CycList result = new CycList();
    for (int i = 0; i < predicates.size(); i++) {
      result.addAllNew(getGafs(cycObject, (CycObject) predicates.get(i)));
    }

    return result;
  }

  /**
   * Returns the list of gafs in which the predicate is the given predicate and in which the given
   * term appears in the first argument position.
   *
   * @param cycObject the given term
   * @param predicate the given predicate
   *
   * @return the list of gafs in which the predicate is a element of the given list of predicates
   *         and in which the given term appears in the first argument position
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList getGafs(final CycObject cycObject,
          final CycObject predicate)
          throws UnknownHostException, IOException, CycApiException {
    //// Preconditions
    if (cycObject == null) {
      throw new NullPointerException("cycObject must not be null");
    }
    verifyPossibleDenotationalTerm(cycObject);
    if (cycObject instanceof CycList) {
      return getGafsForNaut((CycList) cycObject, predicate);
    }
    final CycList gafs = new CycList();
    // TODO handle the case where the cycObject is a NAUT,
    //getGafsForNaut
    final String command = "(with-all-mts \n" + "  (pred-values-in-relevant-mts (canonicalize-term "
            + cycObject.stringApiValue() + ") " + "(canonicalize-term "
            + predicate.stringApiValue() + ")))";
    final CycList values = converseList(command);

    for (int i = 0; i < values.size(); i++) {
      final CycList gaf = new CycList();
      gaf.add(predicate);
      gaf.add(cycObject);
      gaf.add(values.get(i));
      gafs.add(gaf);
    }

    return gafs;
  }

  /**
   * Returns the list of gafs in which the predicate is the given predicate and in which the given
   * term appears in the first argument position.
   *
   * @param cycObject the given term
   * @param predicate the given predicate
   *
   * @return the list of gafs in which the predicate is a element of the given list of predicates
   *         and in which the given term appears in the first argument position
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList getGafsForNaut(final CycList naut,
          final CycObject predicate)
          throws UnknownHostException, IOException, CycApiException {
    final String command =
            "(clet (assertions) "
            + "  (do-gaf-arg-index-naut (assertion " + naut.stringApiValue() + ")"
            + "    (pwhen (equal (formula-arg1 assertion) " + predicate.stringApiValue() + ")"
            + "      (cpush assertion assertions))) "
            + "  assertions)";
    final CycList gafs = converseList(command);

    //// Postconditions
    assert gafs != null : "gafs cannot be null";

    return gafs;
  }

  /**
   * Returns the list of tuples gathered from assertions in given microtheory in which the
   * predicate is the given predicate, in which the given term appears in the indexArg position
   * and in which the list of gatherArgs determines the assertion arguments returned as each
   * tuple.
   *
   * @param term the term in the index argument position
   * @param predicate the given predicate
   * @param indexArg the argument position in which the given term appears
   * @param gatherArgs the list of argument Integer positions which indicate the assertion
   *        arguments to be returned as each tuple
   * @param mt the relevant inference microtheory
   *
   * @return the list of tuples gathered from assertions in given microtheory in which the
   *         predicate is the given predicate, in which the given term appears in the indexArg
   *         position and in which the list of gatherArgs determines the assertion arguments
   *         returned as each tuple
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList getPredicateValueTuplesInMt(CycFort term, CycFort predicate,
          int indexArg, CycList gatherArgs, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    CycList tuples = new CycList();
    String command = makeSubLStmt("pred-value-tuples-in-mt", term, predicate, indexArg,
            gatherArgs, makeELMt(mt));
    return converseList(command);
  }

  /**
   * Assert an argument contraint for the given relation and argument position. The operation will
   * be added to the KB transcript for replication and archive.
   *
   * @param relation the given relation
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertArg1FormatSingleEntry(CycFort relation)
          throws UnknownHostException, IOException, CycApiException {
    // (#$arg1Format relation SingleEntry)
    assertArgFormat(relation, 1, getKnownConstantByGuid("bd5880eb-9c29-11b1-9dad-c379636f7270"));
  }

  /**
   * Assert an argument format contraint for the given relation and argument position. The
   * operation will be added to the KB transcript for replication and archive.
   *
   * @param relation the given relation
   * @param argPosition the given argument position
   * @param argNFormat the argument format constraint
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public void assertArgFormat(CycFort relation, int argPosition, CycFort argNFormat)
          throws UnknownHostException, IOException, CycApiException {
    // (#$argFormat relation argPosition argNFormat)
    CycFormulaSentence sentence = CycFormulaSentence.makeCycFormulaSentence(
            getKnownConstantByGuid("bd8a36e1-9c29-11b1-9dad-c379636f7270"), relation,
            argPosition, argNFormat);
    assertGaf(sentence, baseKB);
  }

  /**
   * Asserts that the given DAML imported term is mapped to the given Cyc term.
   *
   * @param cycTerm the mapped Cyc term
   * @param informationSource the external indexed information source
   * @param externalConcept the external concept within the information source
   * @param mt the assertion microtheory
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public void assertSynonymousExternalConcept(String cycTerm,
          String informationSource,
          String externalConcept,
          String mt)
          throws UnknownHostException, IOException, CycApiException {
    assertSynonymousExternalConcept(getKnownConstantByName(cycTerm),
            getKnownConstantByName(informationSource),
            externalConcept,
            getKnownConstantByName(mt));
  }

  /**
   * Asserts that the given DAML imported term is mapped to the given Cyc term.
   *
   * @param cycTerm the mapped Cyc term
   * @param informationSource the external indexed information source
   * @param externalConcept the external concept within the information source
   * @param mt the assertion microtheory
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public void assertSynonymousExternalConcept(CycFort cycTerm,
          CycFort informationSource,
          String externalConcept,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    CycFormulaSentence gaf = CycFormulaSentence.makeCycFormulaSentence(
            // #$synonymousExternalConcept
            getKnownConstantByGuid("c0e2af4e-9c29-11b1-9dad-c379636f7270"), cycTerm, informationSource, externalConcept);
    assertGaf(gaf, makeELMt(mt));
  }

  /**
   * Gets the list of mappings from the specified information source given the inference
   * microtheory.  Each returned list item is the pair consisting of external concept string and
   * synonymous Cyc term.
   *
   * @param informationSource the external indexed information source
   * @param mt the assertion microtheory
   *
   * @return list of mappings from the specified information source given the inference
   * microtheory
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList getSynonymousExternalConcepts(String informationSource, String mt)
          throws UnknownHostException, IOException, CycApiException {
    return getSynonymousExternalConcepts(getKnownConstantByName(informationSource),
            getKnownConstantByName(mt));
  }

  /**
   * Gets the list of mappings from the specified information source given the inference
   * microtheory.  Each returned list item is the pair consisting of external concept string and
   * synonymous Cyc term.
   *
   * @param informationSource the external indexed information source
   * @param mt the assertion microtheory
   *
   * @return the list of mappings from the specified information source given the inference
   * microtheory
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList getSynonymousExternalConcepts(CycFort informationSource, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    CycList variables = new CycList();
    CycVariable cycTermVar = CycObjectFactory.makeCycVariable("?cyc-term");
    variables.add(cycTermVar);

    CycVariable externalConceptVar = CycObjectFactory.makeCycVariable("?externalConcept");
    variables.add(externalConceptVar);

    final CycFormulaSentence query = CycFormulaSentence.makeCycFormulaSentence(
            // #$synonymousExternalConcept
            getKnownConstantByGuid("c0e2af4e-9c29-11b1-9dad-c379636f7270"),
            cycTermVar, informationSource, externalConceptVar);

    return queryVariables(variables, query, makeELMt(mt), new DefaultInferenceParameters(this));
  }

  /**
   * Asserts a preferred name string for the given term using lexical singular count noun
   * assumptions.
   *
   * @param cycTerm the Cyc term
   * @param phrase the preferred phrase for this term
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public void assertGenPhraseCountNounSingular(CycFort cycTerm,
          String phrase)
          throws UnknownHostException, IOException, CycApiException {
    // (#$genPhrase <term> #$CountNoun #$singular <phrase>) in #$EnglishParaphaseMt
    final CycFormulaSentence gaf = CycFormulaSentence.makeCycFormulaSentence(
            getKnownConstantByGuid("bd5fb28e-9c29-11b1-9dad-c379636f7270"),
            cycTerm,
            getKnownConstantByGuid("bd588078-9c29-11b1-9dad-c379636f7270"),
            getKnownConstantByGuid("bd6757b8-9c29-11b1-9dad-c379636f7270"),
            phrase);

    ELMt elmt = makeELMt(getKnownConstantByGuid("bda16220-9c29-11b1-9dad-c379636f7270"));
    assertGaf(gaf, elmt);
  }

  /**
   * Asserts a preferred name string for the given term using lexical singular count noun
   * assumptions.
   *
   * @param cycTerm the Cyc term
   * @param phrase the preferred phrase for this term
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public void assertGenPhraseCountNounPlural(CycFort cycTerm,
          String phrase)
          throws UnknownHostException, IOException, CycApiException {
    CycList gaf = new CycList();


    // (#$genPhrase <term> #$CountNoun #$plural <phrase>) in
    // #$EnglishParaphaseMt
    gaf.add(getKnownConstantByGuid("bd5fb28e-9c29-11b1-9dad-c379636f7270"));
    gaf.add(cycTerm);
    gaf.add(getKnownConstantByGuid("bd588078-9c29-11b1-9dad-c379636f7270"));
    gaf.add(getKnownConstantByGuid("bd5a6853-9c29-11b1-9dad-c379636f7270"));
    gaf.add(phrase);

    ELMt elmt = makeELMt(getKnownConstantByGuid("bda16220-9c29-11b1-9dad-c379636f7270"));
    assertGaf(gaf,
            elmt);
  }

  /**
   * Gets the list of name strings for the given CycFort.
   *
   * @param cycFort the given FORT
   * @param mt the relevant inference microtheory
   *
   * @return the list of name strings for the given CycFort
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public CycList getNameStrings(CycFort cycFort,
          CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    // (#$nameString <cycFort> ?name-string)

    CycVariable variable = CycObjectFactory.makeCycVariable("?name-string");
    final CycFormulaSentence query = CycFormulaSentence.makeCycFormulaSentence(
            getKnownConstantByGuid("c0fdf7e8-9c29-11b1-9dad-c379636f7270"), cycFort, variable);

    return queryVariable(variable, query, makeELMt(mt));
  }

  /**
   * Ensures that the given term meets the given isa and genl wff constraints in the
   * UniversalVocabularyMt.
   *
   * @param cycFort the given term
   * @param isaConstraintName the given isa type constraint, or null
   * @param genlsConstraintName the given genls type constraint, or null
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public void ensureWffConstraints(String cycFort,
          String isaConstraintName,
          String genlsConstraintName)
          throws UnknownHostException, IOException, CycApiException {
    CycConstant cycConstant = find(cycFort);
    CycConstant isaConstraint = null;
    CycConstant genlsConstraint = null;

    if (isaConstraintName != null) {
      isaConstraint = find(isaConstraintName);
    }

    if (genlsConstraintName != null) {
      genlsConstraint = find(genlsConstraintName);
    }

    ensureWffConstraints(cycConstant, isaConstraint, genlsConstraint);
  }

  /**
   * Ensures that the given term meets the given isa and genl wff constraints in the
   * UniversalVocabularyMt.
   *
   * @param cycFort the given term
   * @param isaConstraint the given isa type constraint, or null
   * @param genlsConstraint the given genls type constraint, or null
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public void ensureWffConstraints(CycFort cycFort, CycFort isaConstraint, CycFort genlsConstraint)
          throws UnknownHostException, IOException, CycApiException {
    if ((isaConstraint != null)
            && (!isa(cycFort, isaConstraint, universalVocabularyMt))) {
      assertIsa(cycFort, isaConstraint);
    }

    if ((genlsConstraint != null)
            && (!isSpecOf(cycFort, genlsConstraint, universalVocabularyMt))) {
      assertGenls(cycFort, genlsConstraint);
    }
  }

  /**
   * Returns the list of arg2 terms from binary gafs having the specified predicate and arg1
   * values.
   *
   * @param predicate the given predicate
   * @param arg1 the given arg1 term
   * @param mt the inference microtheory
   *
   * @return the list of arg2 terms from gafs having the specified predicate and arg1 values
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList getArg2s(String predicate, String arg1, String mt)
          throws UnknownHostException, IOException, CycApiException {
    return getArg2s(getKnownConstantByName(predicate),
            getKnownConstantByName(arg1),
            getKnownConstantByName(mt));
  }

  /**
   * Returns the list of arg2 terms from binary gafs having the specified predicate and arg1
   * values.
   *
   * @param predicate the given predicate
   * @param arg1 the given arg1 term
   * @param mt the inference microtheory
   *
   * @return the list of arg2 terms from gafs having the specified predicate and arg1 values
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList getArg2s(String predicate, CycFort arg1, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return getArg2s(getKnownConstantByName(predicate), arg1, makeELMt(mt));
  }

  /**
   * Returns the list of arg2 terms from binary gafs having the specified predicate and arg1
   * values.
   *
   * @param predicate the given predicate
   * @param arg1 the given arg1 term
   * @param mt the inference microtheory
   *
   * @return the list of arg2 terms from gafs having the specified predicate and arg1 values
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList getArg2s(CycFort predicate, CycFort arg1, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {

    CycVariable variable = CycObjectFactory.makeCycVariable("?arg2");
    final CycFormulaSentence query = CycFormulaSentence.makeCycFormulaSentence(
            predicate, arg1, variable);

    return queryVariable(variable, query, makeELMt(mt));
  }

  /**
   * Returns the first arg2 term from binary gafs having the specified predicate and arg1 values.
   *
   * @param predicate the given predicate
   * @param arg1 the given arg1 term
   * @param mt the inference microtheory
   *
   * @return the first arg2 term from gafs having the specified predicate and arg1 values or null
   *         if none
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public Object getArg2(String predicate, String arg1, String mt)
          throws UnknownHostException, IOException, CycApiException {
    return getArg2(getKnownConstantByName(predicate),
            getKnownConstantByName(arg1),
            getKnownConstantByName(mt));
  }

  /**
   * Returns the first arg2 term from binary gafs having the specified predicate and arg1 values.
   *
   * @param predicate the given predicate
   * @param arg1 the given arg1 term
   * @param mt the inference microtheory
   *
   * @return the first arg2 term from gafs having the specified predicate and arg1 values or null
   *         if none
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public Object getArg2(String predicate, CycFort arg1, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return getArg2(getKnownConstantByName(predicate), arg1, makeELMt(mt));
  }

  /**
   * Returns the first arg2 term from binary gafs having the specified predicate and arg1 values.
   *
   * @param predicate the given predicate
   * @param arg1 the given arg1 term
   * @param mt the inference microtheory
   *
   * @return the first arg2 term from gafs having the specified predicate and arg1 values or null
   *         if none
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public Object getArg2(CycFort predicate, CycFort arg1, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {

    CycVariable variable = CycObjectFactory.makeCycVariable("?arg2");
    final CycFormulaSentence query = CycFormulaSentence.makeCycFormulaSentence(
            predicate, arg1, variable);
    final DefaultInferenceParameters params = new DefaultInferenceParameters(this);
    params.setMaxNumber(1);
    CycList answer = queryVariable(variable, query, makeELMt(mt), params);

    if (answer.size() > 0) {
      return answer.get(0);
    } else {
      return null;
    }
  }

  /**
   * Returns the first arg2 ground or non-term from assertions having the specified predicate and
   * arg1 values.
   *
   * @param predicate the given predicate
   * @param arg1 the given arg1 term
   * @param mt the inference microtheory
   *
   * @return the first arg2 ground or non-term from assertions having the specified predicate and
   *         arg1 values
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public Object getAssertionArg2(String predicate, String arg1, String mt)
          throws UnknownHostException, IOException, CycApiException {
    return getAssertionArg2(getKnownConstantByName(predicate),
            getKnownConstantByName(arg1),
            getKnownConstantByName(mt));
  }

  /**
   * Returns the first arg2 ground or non-term from assertions having the specified predicate and
   * arg1 values.
   *
   * @param predicate the given predicate
   * @param arg1 the given arg1 term
   * @param mt the inference microtheory
   *
   * @return the first arg2 ground or non-term from assertions having the specified predicate and
   *         arg1 values
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public Object getAssertionArg2(CycFort predicate, CycFort arg1, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return this.converseObject(makeSubLStmt(FPRED_VALUE_IN_MT, arg1, predicate, makeELMt(mt)));
  }

  /**
   * Returns the first arg1 term from gafs having the specified predicate and arg2 values.
   *
   * @param predicate the given predicate
   * @param arg2 the given arg2 term
   * @param mt the inference microtheory
   *
   * @return the first arg1 term from gafs having the specified predicate and arg2 values
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public Object getArg1(String predicate, String arg2, String mt)
          throws UnknownHostException, IOException, CycApiException {
    return getArg1(getKnownConstantByName(predicate),
            getKnownConstantByName(arg2),
            getKnownConstantByName(mt));
  }

  /**
   * Returns the first arg1 term from gafs having the specified predicate and arg2 values.
   *
   * @param predicate the given predicate
   * @param arg2 the given arg2 term
   * @param mt the inference microtheory
   *
   * @return the first arg1 term from gafs having the specified predicate and arg2 values
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public Object getArg1(CycFort predicate, CycDenotationalTerm arg2, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    CycList answer = getArg1s(predicate, arg2, makeELMt(mt));

    if (answer.size() > 0) {
      return answer.get(0);
    } else {
      return null;
    }
  }

  /**
   * Returns the list of arg1 terms from gafs having the specified predicate and arg2 values.
   *
   * @param predicate the given predicate
   * @param arg2 the given arg2 term
   * @param mt the inference microtheory
   *
   * @return the list of arg1 terms from gafs having the specified predicate and arg2 values
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList getArg1s(String predicate, String arg2, String mt)
          throws UnknownHostException, IOException, CycApiException {
    return getArg1s(getKnownConstantByName(predicate),
            getKnownConstantByName(arg2),
            getKnownConstantByName(mt));
  }

  /**
   * Returns the list of arg1 terms from gafs having the specified predicate and arg2 values.
   *
   * @param predicate the given predicate
   * @param arg2 the given arg2 term
   * @param mt the inference microtheory
   *
   * @return the list of arg1 terms from gafs having the specified predicate and arg2 values
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList getArg1s(CycFort predicate, CycDenotationalTerm arg2, CycObject mt)
          throws UnknownHostException, IOException, CycApiException {

    CycVariable variable = CycObjectFactory.makeCycVariable("?arg1");
    final CycFormulaSentence query = CycFormulaSentence.makeCycFormulaSentence(
            predicate, variable, arg2);

    return queryVariable(variable, query, makeELMt(mt));
  }

  /**
   * Returns the Cyc image ID.
   *
   * @return the Cyc image ID string
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public String getCycImageID()
          throws UnknownHostException, IOException, CycApiException {
    return converseString(CYC_IMAGE_ID_EXPRESSION);
  }
  static private final String CYC_IMAGE_ID_EXPRESSION = makeSubLStmt("cyc-image-id");

  /**
   * Returns the list of assertions contained in the given mt.
   *
   * @param mt the given microtheory
   *
   * @return the list of assertions contained in the given mt
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList getAllAssertionsInMt(CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    return converseList(makeSubLStmt("gather-mt-index", mt));
  }

  /**
   * Unasserts all assertions from the given mt, with a transcript record of the unassert
   * operation.
   *
   * @param mt the microtheory from which to delete all its assertions
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public void unassertMtContentsWithTranscript(CycObject mt)
          throws UnknownHostException, IOException, CycApiException {
    CycList assertions = getAllAssertionsInMt(mt);
    Iterator iter = assertions.iterator();

    while (iter.hasNext()) {
      CycAssertion assertion = (CycAssertion) iter.next();
      String command = wrapBookkeeping(makeSubLStmt("ke-unassert-now", assertion, makeELMt(mt)));
      converseVoid(command);
    }
  }

  /**
   * Unasserts all assertions from the given mt, without a transcript record of the unassert
   * operation.
   *
   * @param mt the microtheory from which to delete all its assertions
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public void unassertMtContentsWithoutTranscript(CycObject mt)
          throws UnknownHostException, IOException,
          CycApiException {
    CycList assertions = getAllAssertionsInMt(mt);
    Iterator iter = assertions.iterator();

    while (iter.hasNext()) {
      CycAssertion assertion = (CycAssertion) iter.next();
      String command = makeSubLStmt("cyc-unassert", assertion, makeELMt(mt));
      converseVoid(command);
    }
  }

  /**
   * Unasserts all assertions from the given mt having the given predicate and arg1, without a
   * transcript record of the unassert operation.
   *
   * @param predicate the given predicate or null to match all predicates
   * @param arg1 the given arg1
   * @param mt the microtheory from which to delete the matched assertions
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public void unassertMatchingAssertionsWithoutTranscript(CycFort predicate,
          Object arg1,
          CycObject mt)
          throws UnknownHostException, IOException,
          CycApiException {
    CycList assertions = getAllAssertionsInMt(mt);
    Iterator iter = assertions.iterator();

    while (iter.hasNext()) {
      CycAssertion assertion = (CycAssertion) iter.next();
      CycList sentence = assertion.getFormula();

      if (sentence.size() < 2) {
        continue;
      }

      if (!(arg1.equals(sentence.second()))) {
        continue;
      }

      if ((predicate != null) && (!(predicate.equals(sentence.first())))) {
        continue;
      }

      String command = "(cyc-unassert " + assertion.stringApiValue()
              + makeELMt(mt).stringApiValue() + "))";
      converseVoid(command);
    }
  }

  /**
   * Returns the list of Cyc terms whose denotation matches the given English string.
   *
   * @param denotationString the given English denotation string
   *
   * @return the list of Cyc terms whose denotation matches the given English string
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList getDenotsOfString(String denotationString)
          throws UnknownHostException, IOException, CycApiException {
    return new CycList(NLFormat.getInstance(this).parseObjects(denotationString));
  }

  /**
   * Returns the list of Cyc terms whose denotation matches the given English string and which are
   * instances of any of the given collections.
   *
   * @param denotationString the given English denotation string
   * @param collections the given list of collections
   *
   * @return the list of Cyc terms whose denotation matches the given English string
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList getDenotsOfString(String denotationString, CycList collections)
          throws UnknownHostException, IOException, CycApiException {
    CycList terms = getDenotsOfString(denotationString);
    CycList result = new CycList();
    Iterator collectionsIterator = collections.iterator();

    while (collectionsIterator.hasNext()) {
      CycFort oneCollection = (CycFort) collectionsIterator.next();
      Iterator termsIter = terms.iterator();

      while (termsIter.hasNext()) {
        CycFort term = (CycFort) termsIter.next();

        if (this.isa(term, oneCollection)) {
          result.add(term);
        }
      }
    }

    return result;
  }

  /**
   * Returns the list of Cyc terms whose denotation matches the given English multi-word string.
   *
   * @param multiWordDenotationString the given English denotation multi-word string
   *
   * @return the list of Cyc terms whose denotation matches the given English multi-word string
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList getMWSDenotsOfString(CycList multiWordDenotationString)
          throws UnknownHostException, IOException, CycApiException {
    String command = makeSubLStmt("mws-denots-of-string", multiWordDenotationString);
    return converseList(command);
  }

  /**
   * Returns the list of Cyc terms whose denotation matches the given English multi-word string and
   * which are instances of any of the given collections.
   *
   * @param multiWordDenotationString the given English denotation string
   * @param collections the given list of collections
   *
   * @return the list of Cyc terms whose denotation matches the given English multi-word string
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList getMWSDenotsOfString(CycList multiWordDenotationString,
          CycList collections)
          throws UnknownHostException, IOException, CycApiException {
    String command = makeSubLStmt("mws-denots-of-string", multiWordDenotationString);

    CycList terms = converseList(command);
    CycList result = new CycList();
    Iterator collectionsIterator = collections.iterator();

    while (collectionsIterator.hasNext()) {
      CycFort oneCollection = (CycFort) collectionsIterator.next();
      Iterator termsIter = terms.iterator();

      while (termsIter.hasNext()) {
        CycFort term = (CycFort) termsIter.next();

        if (this.isa(term, oneCollection)) {
          result.add(term);
        }
      }
    }

    return result;
  }

  /**
   * Returns true if the given symbol is defined as an api function.
   *
   * @param symbolName the candidate api function symbol name
   *
   * @return true if the given symbol is defined as an api function
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isFunctionBound(String symbolName)
          throws UnknownHostException, IOException, CycApiException {
    CycSymbol cycSymbol = makeCycSymbol(
            symbolName);

    return isFunctionBound(cycSymbol);
  }

  /**
   * Returns true if the given symbol is defined as an api function.
   *
   * @param cycSymbol the candidate api function symbol
   *
   * @return rue if the given symbol is defined as an api function
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  public boolean isFunctionBound(CycSymbol cycSymbol)
          throws UnknownHostException, IOException, CycApiException {
    String command = makeSubLStmt("boolean", makeNestedSubLStmt("fboundp"), cycSymbol);
    return converseBoolean(command);
  }

  /**
   * Returns the Heuristic Level (HL) object represented by the given string.
   *
   * @param string the string which represents a number, quoted string, constant, naut or nart
   *
   * @return the Heuristic Level (HL) object represented by the given string
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public Object getHLCycTerm(String string)
          throws UnknownHostException, IOException, CycApiException {
    return converseObject("(canonicalize-term  '" + string + ")");
  }

  /**
   * Returns the Epistimological Level (EL) object represented by the given string.
   *
   * @param string the string which represents a number, quoted string, constant, naut or nart
   *
   * @return the Epistimological Level (EL)object represented by the given string
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public Object getELCycTerm(String string)
          throws UnknownHostException, IOException, CycApiException {
    return converseObject("(identity '" + string + ")");
  }

  /** Returns the external ID for the given Cyc object.
   *
   * @deprecated Should be replaced in favor of {@link #org.opencyc.cycObject.DefaultCycObject.toCompactExternalId(obj, access)}
   * @param cycObject the Cyc object
   * @return the external ID string
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  @Deprecated
  public String getExternalIDString(final CycObject cycObject)
          throws UnknownHostException, IOException, CycApiException {
    return DefaultCycObject.toCompactExternalId(cycObject, this);
  }

  public static boolean isPossibleExternalIDString(final Object obj) {
    return is64BitString(obj);
  }

  private static boolean is64BitString(final Object obj) {
    if (obj instanceof String) {
      return is64Bit((String) obj);
    } else {
      return false;
    }
  }

  private static boolean is64Bit(final String string) {
    final StringCharacterIterator i = new StringCharacterIterator(string);
    for (char c = i.first(); c != CharacterIterator.DONE; c = i.next()) {
      if (!is64Bit(c)) {
        return false;
      }
    }
    return true;
  }

  private static boolean is64Bit(final char c) {
    return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || //0-51
            (c >= '0' && c <= '9') || //52-61
            (c == '+') || (c == '/') || //62-63 original Base64 standard
            (c == '-') || (c == '_'); //62-63 modified Base64 for URL
  }

  /**
   * Returns a random constant.
   *
   * @return a random constant
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycConstant getRandomConstant()
          throws UnknownHostException, IOException, CycApiException {
    return (CycConstant) converseObject("(random-constant)");
  }

  /**
   * Returns a random nart (Non-Atomic Reified Term).
   *
   * @return a random nart (Non-Atomic Reified Term)
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycNart getRandomNart()
          throws UnknownHostException, IOException, CycApiException {
    return (CycNart) converseObject("(random-nart)");
  }

  /**
   * Returns a random assertion.
   *
   * @return a random assertion
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycAssertion getRandomAssertion()
          throws UnknownHostException, IOException, CycApiException {
    return (CycAssertion) converseObject("(random-assertion)");
  }

  /**
   * Returns the given list with EL NARTS transformed to CycNart objects.
   *
   * @param cycList the given list
   *
   * @return the given list with EL NARTS transformed to CycNart objects
   *
   * @throws IOException if a communications error occurs
   * @throws UnknownHostException if the Cyc server cannot be found
   * @throws CycApiException if the Cyc server returns an error
   */
  public CycList canonicalizeList(CycList cycList)
          throws UnknownHostException, IOException, CycApiException {
    CycList canonicalList = new CycList();
    Iterator iter = cycList.iterator();

    while (iter.hasNext()) {
      Object obj = iter.next();

      if (obj instanceof CycList) {
        canonicalList.add(getHLCycTerm(((CycList) obj).cyclify()));
      } else if (obj instanceof CycNart) {
        canonicalList.add(getHLCycTerm(((CycNart) obj).cyclify()));
      } else {
        canonicalList.add(obj);
      }
    }

    return canonicalList;
  }

  /**
   * Gets the assertion date for the given assertion, or zero if the date is not available.
   *
   * @return the assertion date for the given assertion
   */
  public Long getAssertionDate(CycAssertion cycAssertion)
          throws UnknownHostException, IOException, CycApiException {
    String command = makeSubLStmt("asserted-when", cycAssertion);
    Object date = converseObject(command);
    if (date instanceof Integer) {
      return ((Integer) date).longValue();
    }
    if (date instanceof Long) {
      return (Long) date;
    }
    if (date.equals(CycObjectFactory.nil)) {
      return 0l;
    } else {
      throw new CycApiException("unexpected type of date returned " + date.toString());
    }
  }

  /**
   * Returns true if the given HL formula and microtheory correspond to a valid
   * assertion in that microtheory.
   *
   * @param gaf the given assertion formula
   * @param mt the candidate assertion microtheory
   */
  public boolean isGafValidAssertion(CycList gaf, ELMt mt)
          throws UnknownHostException, IOException, CycApiException {
    String command = makeSubLStmt("find-gaf", gaf, mt);
    Object response = converseObject(command);
    return !response.equals(CycObjectFactory.nil);
  }

  /**
   * Returns true if the given HL formula and microtheory correspond to a valid
   * assertion in that microtheory.
   *
   * @param gaf the given assertion formula
   * @param mt the candidate assertion microtheory
   */
  public boolean isGafValidAssertion(CycFormulaSentence gaf, ELMt mt)
          throws UnknownHostException, IOException, CycApiException {
    return isGafValidAssertion(gaf.getArgs(), mt);
  }

  /**
   * Returns true if the given HL formula and microtheory correspond to a valid
   * assertion in that microtheory.
   *
   * @param hlFormula the given HL formula
   * @param mt the candidate assertion microtheory
   */
  public boolean isAssertionValid(CycList hlFormula, CycFort mt)
          throws UnknownHostException, IOException, CycApiException {
    String command = makeSubLStmt("find-assertion", hlFormula, mt);
    Object response = converseObject(command);
    return !response.equals(CycObjectFactory.nil);
  }

  /** Asserts that the given term is dependent upon the given independent term.  If the latter is
   * killed, then the truth maintenance kills the dependent term.
   *
   * @param dependentTerm the dependent term
   * @param independentTerm the independent term
   * @param mt the assertion microtheory
   */
  public void assertTermDependsOn(final CycFort dependentTerm, final CycFort independentTerm, final CycFort mt) throws IOException, CycApiException {
    // assert (#$termDependsOn <dependentTerm> <independentTerm>) in #$UniversalVocabularyMt
    assertGaf(mt, getKnownConstantByGuid("bdf02d74-9c29-11b1-9dad-c379636f7270"), dependentTerm, independentTerm);
  }

  /** Asserts that the given term is defined in the given mt.  If the mt is
   * subsequently killed, then the truth maintenance kills the dependent term.
   *
   * @param dependentTerm the dependent term
   * @param mt the defining microtheory
   */
  public void assertDefiningMt(final CycFort dependentTerm, final CycFort mt) throws IOException, CycApiException {
    // assert (#$definingMt <dependentTerm> <mt>) in #$BaseKB
    assertGaf(baseKB, getKnownConstantByGuid("bde5ec9c-9c29-11b1-9dad-c379636f7270"), dependentTerm, mt);
  }

  /** Returns the XML datetime string corresponding to the given CycL date
   *
   * @param date the date naut
   * @return the XML datetime string corresponding to the given CycL date
   * @deprecated use DateConverter.
   */
  static public String xmlDatetimeString(final CycList date) throws IOException, CycApiException {
    try {
      final CycNaut dateNaut = (CycNaut) CycNaut.convertIfPromising(date);
      final Date javadate = DateConverter.parseCycDate(dateNaut, TimeZone.getDefault(), false);
      int cycDatePrecision = DateConverter.getCycDatePrecision(dateNaut);
      if (cycDatePrecision > DateConverter.DAY_GRANULARITY) {
        return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(javadate);
      } else {
        return new SimpleDateFormat("yyyy-MM-dd").format(javadate);
      }
    } catch (Exception e) {
      return null;
    }
  }

  /**
   * Returns whether or not we have a valid lease with the Cyc server.
   * @return whether or not we have a valid lease with the Cyc server
   */
  public boolean hasValidLease() {
    return (cycLeaseManager == null) ? true : cycLeaseManager.hasValidLease();
  }

  /** Initializes the query properties. */
  private void initializeQueryProperties() {
    defaultQueryProperties.put(makeCycSymbol(":allowed-rules"), makeCycSymbol(":all"));
    defaultQueryProperties.put(makeCycSymbol(":result-uniqueness"), makeCycSymbol(":bindings"));
    defaultQueryProperties.put(makeCycSymbol(":allow-hl-predicate-transformation?"), false);
    defaultQueryProperties.put(makeCycSymbol(":allow-unbound-predicate-transformation?"), false);
    defaultQueryProperties.put(makeCycSymbol(":allow-evaluatable-predicate-transformation?"), false);
    defaultQueryProperties.put(makeCycSymbol(":intermediate-step-validation-level"), makeCycSymbol(":all"));
    defaultQueryProperties.put(makeCycSymbol(":negation-by-failure?"), false);
    defaultQueryProperties.put(makeCycSymbol(":allow-indeterminate-results?"), true);
    defaultQueryProperties.put(makeCycSymbol(":allow-abnormality-checking?"), true);
    defaultQueryProperties.put(makeCycSymbol(":disjunction-free-el-vars-policy"), makeCycSymbol(":compute-intersection"));
    defaultQueryProperties.put(makeCycSymbol(":allowed-modules"), makeCycSymbol(":all"));
    defaultQueryProperties.put(makeCycSymbol(":completeness-minimization-allowed?"), true);
    defaultQueryProperties.put(makeCycSymbol(":direction"), makeCycSymbol(":backward"));
    defaultQueryProperties.put(makeCycSymbol(":equality-reasoning-method"), makeCycSymbol(":czer-equal"));
    defaultQueryProperties.put(makeCycSymbol(":equality-reasoning-domain"), makeCycSymbol(":all"));
    defaultQueryProperties.put(makeCycSymbol(":max-problem-count"), Long.valueOf(100000));
    defaultQueryProperties.put(makeCycSymbol(":transformation-allowed?"), false);
    defaultQueryProperties.put(makeCycSymbol(":add-restriction-layer-of-indirection?"), true);
    defaultQueryProperties.put(makeCycSymbol(":evaluate-subl-allowed?"), true);
    defaultQueryProperties.put(makeCycSymbol(":rewrite-allowed?"), false);
    defaultQueryProperties.put(makeCycSymbol(":abduction-allowed?"), false);
    defaultQueryProperties.put(makeCycSymbol(":removal-backtracking-productivity-limit"), Long.valueOf(2000000));
    // dynamic query properties
    defaultQueryProperties.put(makeCycSymbol(":max-number"), null);
    defaultQueryProperties.put(makeCycSymbol(":max-time"), Integer.valueOf(120));
    defaultQueryProperties.put(makeCycSymbol(":max-transformation-depth"), Integer.valueOf(0));
    defaultQueryProperties.put(makeCycSymbol(":block?"), false);
    defaultQueryProperties.put(makeCycSymbol(":max-proof-depth"), null);
    defaultQueryProperties.put(makeCycSymbol(":cache-inference-results?"), false);
    defaultQueryProperties.put(makeCycSymbol(":answer-language"), makeCycSymbol(":el"));
    defaultQueryProperties.put(makeCycSymbol(":continuable?"), false);
    defaultQueryProperties.put(makeCycSymbol(":browsable?"), false);
    defaultQueryProperties.put(makeCycSymbol(":productivity-limit"), Long.valueOf(2000000));

    final CycList<CycSymbol> queryPropertiesList = new CycList(defaultQueryProperties.keySet());
    final String command = makeSubLStmt("mapcar", makeCycSymbol("query-property-p"), queryPropertiesList);
    try {
      CycList results = converseList(command);
      for (int i = 0, size = results.size(); i < size; i++) {
        if (results.get(i).equals(CycObjectFactory.nil)) {
          final CycSymbol badProperty = queryPropertiesList.get(i);
          System.err.println(badProperty + " is not a query-property-p");
          defaultQueryProperties.remove(badProperty);
        }
      }
    } catch (Exception e) {
      System.err.println(e.getMessage());
    }
    queryPropertiesInitialized = true;
  }

  /** Migrate to this once inference parameter definitions are included in OpenCyc KB. */
  private void initializeQueryPropertiesNew() {
    synchronized (defaultQueryProperties) {
      defaultQueryProperties.clear();
      try {
        final InferenceParameterDescriptions desc = DefaultInferenceParameterDescriptions.loadInferenceParameterDescriptions(this, 10000);
        final InferenceParameters defaults = desc.getDefaultInferenceParameters();
        final CycList allQueryProperties = converseList(makeSubLStmt("ALL-QUERY-PROPERTIES"));
        for (final Object property : allQueryProperties) {
          if (property instanceof CycSymbol && defaults.containsKey((CycSymbol) property)) {
            final Object value = defaults.get((CycSymbol) property);
            defaultQueryProperties.put((CycSymbol) property, value);
          }
        }
      } catch (UnknownHostException ex) {
        Logger.getLogger(CycAccess.class.getName()).log(Level.SEVERE, null, ex);
      } catch (IOException ex) {
        Logger.getLogger(CycAccess.class.getName()).log(Level.SEVERE, null, ex);
      } catch (CycApiException ex) {
        Logger.getLogger(CycAccess.class.getName()).log(Level.SEVERE, null, ex);
      }
    }
    queryPropertiesInitialized = true;
  }

  /** Returns a clone of the default HL query propoerties.
   *
   * @return the default HL query propoerties
   */
  public InferenceParameters getHLQueryProperties() {
    synchronized (defaultQueryProperties) {
      if (!queryPropertiesInitialized) {
        initializeQueryProperties();
      }
      return (InferenceParameters) defaultQueryProperties.clone();
    }
  }

  /** Returns a query properties string for the given query properties if present, otherwise
   * returns a query properties string for the default query properties.
   *
   * @param queryProperties the given query properties or null if the defaults are to be used
   *
   * @return a query properties string for the given query properties if present, otherwise
   * returns a query properties string for the default query properties
   */
  public String queryPropertiesToString(final InferenceParameters queryProperties) {
    final InferenceParameters tempQueryProperties = (queryProperties == null) ? getHLQueryProperties() : queryProperties;
    final CycList parameterList = new CycList();
    for (final Iterator<Entry<CycSymbol, Object>> iter = tempQueryProperties.entrySet().iterator(); iter.hasNext();) {
      Entry<CycSymbol, Object> mapEntry = iter.next();
      CycSymbol queryParameterKeyword = mapEntry.getKey();
      parameterList.add(queryParameterKeyword);
      final Object rawValue = mapEntry.getValue();
      parameterList.add(tempQueryProperties.parameterValueCycListApiValue(queryParameterKeyword, rawValue));
    }
    return parameterList.stringApiValue();
  }

  /** Initializes a named inference problem store.
   *
   * @param name the unique problem store name
   * @param queryProperties the given query properties or null if the defaults are to be used
   */
  public void initializeNamedInferenceProblemStore(final String name, final InferenceParameters queryProperties) throws IOException, CycApiException {
    //// Preconditions
    if (name == null) {
      throw new NullPointerException("name must not be null");
    }
    if (name.length() == 0) {
      throw new IllegalArgumentException("name must not be an empty string");
    }
    final InferenceParameters tempQueryProperties = (queryProperties == null) ? getHLQueryProperties() : queryProperties;
    final String command =
            "(progn "
            + "  (find-or-create-problem-store-by-name \"" + name + "\" (filter-plist " + queryPropertiesToString(tempQueryProperties) + "'problem-store-property-p)) "
            + "  nil)";
    converseVoid(command);
  }

  /** Destroys the named problem store.
   *
   * @param name the unique problem store name
   */
  public void destroyInferenceProblemStoreByName(final String name) throws IOException, CycApiException {
    //// Preconditions
    if (name == null) {
      throw new NullPointerException("name must not be null");
    }
    if (name.length() == 0) {
      throw new IllegalArgumentException("name must not be an empty string");
    }
    final String command =
            "(destroy-problem-store-by-name \"" + name + "\")";
    converseVoid(command);
  }

  public CycSentence getSimplifiedSentence(CycFormulaSentence sentence) throws UnknownHostException, IOException {
    return sentence.getSimplifiedSentence(this);
  }

  public CycSentence getSimplifiedSentence(CycFormulaSentence sentence, ELMt mt) throws UnknownHostException, IOException {
    return sentence.getSimplifiedSentence(this, mt);
  }

  /** Determines whether the two input objects are equal EL expressions. */
  public boolean equalsEL(Object obj1, Object obj2) throws IOException {
    String command = makeSubLStmt(EQUALS_EL, obj1, obj2);
    // execute the SubL function-call and access the response
    Object response = converseObject(command);
    return !response.equals(CycObjectFactory.nil);
  }

  /** Determines whether the two input queries are equal EL expressions. */
  public boolean queriesEqualAtEL(Object obj1, Object obj2) throws IOException {
    String command = makeSubLStmt("queries-equal-at-el?", obj1, obj2);
    // execute the SubL function-call and access the response
    Object response = converseObject(command);
    return !response.equals(CycObjectFactory.nil);
  }
  //// Protected Area

  /**
   * Provides common local and remote CycAccess object initialization.
   *
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  private final void commonInitialization()
          throws IOException, CycApiException {
    if (Log.current == null) {
      Log.makeLog("cyc-api.log");
    }

    if (areAPIRequestsLoggedToFile) {
      apiRequestLog = new FileWriter("api-requests.lisp");
    }
    cycAccessInstances.put(Thread.currentThread(), this);

    /*if (sharedCycAccessInstance == null) {
    sharedCycAccessInstance = this;
    }*/
    cycImageID = getCycImageID();
    try {
      DefaultInferenceParameterDescriptions.loadInferenceParameterDescriptions(this, 0);
    } catch (Exception e) {
      Logger logger = Logger.getLogger("org.opencyc.api.CycAccess");
      logger.warning("Could not load inference parameter descriptions.");
      Throwable curr = e;
      while (curr != null) {
        logger.warning(curr.getLocalizedMessage());
        curr = curr.getCause();
      }
    }
    if (!isSOAPConnection) // if the communication mode is SOAP, then there is a lease manager, but it is never started
    {
      try {
        // wait for the sockets to initialize
        Thread.sleep(500);
      } catch (java.lang.InterruptedException e) {
      }
      cycLeaseManager = new CycLeaseManager(this);
      cycLeaseManager.start();
    }
  }

  /**
   * Converses with Cyc to perform an API command.  Creates a new connection for this command if
   * the connection is not persistent.
   *
   * @param command the command string or CycList
   *
   * @return the result as an object array of two objects
   * @see org.opencyc.api.CycConnectionInterface.converse
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  // @note Used by BOAPI.
  public Object[] converseRaw(Object command)
          throws UnknownHostException, IOException, CycApiException {
    return converse(command);
  }

  /**
   * Converses with Cyc to perform an API command.  Creates a new connection for this command if
   * the connection is not persistent.
   *
   * @param command the command string or CycList
   *
   * @return the result as an object array of two objects
   * @see CycConnectionInterface.converse
   *
   * @throws UnknownHostException if cyc server host not found on the network
   * @throws IOException if a data communication error occurs
   * @throws CycApiException if the api request results in a cyc server error
   */
  protected Object[] converse(Object command)
          throws UnknownHostException, IOException, CycApiException {
    Object[] response = {null, null};

    if (trace > CycConnection.API_TRACE_NONE || areAPIRequestsLoggedToFile) {
      final CycList commandCycList = (command instanceof CycList) ? (CycList) command : makeCycList((String) command);
      final String prettyCommandCycList = commandCycList.toPrettyCyclifiedString("");
      final String escapedCommandCycList = commandCycList.toPrettyEscapedCyclifiedString("");
      if (areAPIRequestsLoggedToFile) {
        apiRequestLog.write(escapedCommandCycList);
        apiRequestLog.write('\n');
      }
      if (trace > CycConnection.API_TRACE_NONE) {
        Log.current.println(prettyCommandCycList + "\n--> cyc");
      }
    }

    if (!isSOAPConnection) {
//      if ((previousAccessedMilliseconds + MAX_UNACCESSED_MILLIS) < System.currentTimeMillis()) {
//        Log.current.println("Re-establishing a stale Cyc connection.");
//        reEstablishCycConnection();
//      }
//      else
      if (!((CycConnection) getCycConnection()).isValidBinaryConnection()) {
        Log.current.println("Re-establishing an invalid Cyc connection.");
        reEstablishCycConnection();
      }
    }
    response = cycConnection.converse(command);
    previousAccessedMilliseconds = System.currentTimeMillis();

    if (trace > CycConnection.API_TRACE_NONE) {
      String responseString;

      if (response[1] instanceof CycList) {
        responseString = ((CycList) response[1]).toPrettyString("");
      } else if (response[1] instanceof CycFort) {
        responseString = ((CycFort) response[1]).cyclify();
      } else {
        responseString = response[1].toString();
      }
      Log.current.println("cyc --> " + responseString);
    }

    return response;
  }

  /** Re-estabishes a stale binary CycConnection. */
  protected void reEstablishCycConnection() throws UnknownHostException, IOException, CycApiException {
    previousAccessedMilliseconds = System.currentTimeMillis();
    cycConnection.close();
    cycConnection = new CycConnection(hostName,
            port,
            this);
    if (!(cycImageID.equals(getCycImageID()))) {
      Log.current.println("New Cyc image detected, resetting caches.");
      CycObjectFactory.resetCaches();
    }
  }

  /**
   * Returns a with-bookkeeping-info macro expresssion.
   *
   * @return a with-bookkeeping-info macro expresssion
   */
  protected String withBookkeepingInfo() {
    String projectName = "nil";

    if (project != null) {
      projectName = project.stringApiValue();
    }

    String cyclistName = "nil";

    if (cyclist != null) {
      cyclistName = cyclist.stringApiValue();
    }

    return "(with-bookkeeping-info (new-bookkeeping-info " + cyclistName + " (the-date) "
            + projectName + "(the-second)) ";
  }
  //// Private Area

  private CycConstant makePrefetchedConstant(String guidStr, HashMap constantInfoDictionary) {
    Guid guid = CycObjectFactory.makeGuid(guidStr);
    CycConstant prefetchedConstant = makeConstantWithGuidName(guid,
            (String) constantInfoDictionary.get(guid));
    CycObjectFactory.addCycConstantCache(prefetchedConstant);
    return prefetchedConstant;
  }

  /** @return true iff <tt>focalTerm</tt> is known to have a fact sheet accessible to this CycAccess */
  public boolean termKnownToHavePrecachedFactSheet(final CycObject focalTerm) {
    return termsKnownToHavePrecachedFactSheets.contains(focalTerm);
  }