/** @name jni.cpp

-----------------------------------------------------------------------------


 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.

-----------------------------------------------------------------------------

   Description: The C++ functions for the Java - C++ interface

-----------------------------------------------------------------------------


   08/04/2000  Initial creation

-------------------------------------------------------------------------- */

//#define DEBUG_VERBOSE 1
/* ----------------------------------------------------------------------- */
/*       Include dependencies                                              */
/* ----------------------------------------------------------------------- */
// this is included ONCE for the main source file of each binary
//#include "uima/configure.h"

#include "uima/pragmas.hpp"

#include "uima/macros.h"
#include "uima/location.hpp"
#include "uima/filename.hpp"

#include "uima/api.hpp"
#include "uima/jni.hpp"

#include "uima/sofaid.hpp"
#include "uima/internal_casimpl.hpp"
#include "uima/cas.hpp"
#include "uima/internal_engine_base.hpp"
#include "uima/internal_casdeserializer.hpp"
#include "uima/result_specification.hpp"
#include "uima/org_apache_uima_uimacpp_UimacppEngine.h"
#include "uima/jni_utils.hpp"
#include "uima/casiterator.hpp"
/* ----------------------------------------------------------------------- */
/*       Constants                                                         */
/* ----------------------------------------------------------------------- */


#define UIMA_JNI_CONCAT(x,y) x##y
#define JAVA_PREFIX(FUNC) UIMA_JNI_CONCAT(Java_org_apache_uima_uimacpp_UimacppEngine_, FUNC )
#define CONST_PREFIX(CONST) UIMA_JNI_CONCAT(org_apache_uima_uimacpp_UimacppEngine_, CONST )

#define JAVA_LOGGER_PROXY "org/apache/uima/uimacpp/UimacppAnalysisComponent"

/* ----------------------------------------------------------------------- */
/*       Forward declarations                                              */
/* ----------------------------------------------------------------------- */
static JNILogger * singleton_jni_logger = 0;
static jobject getSerializedCasData (JNIEnv* jeEnv, jobject joJTaf, jint jiWhichData, uima::internal::SerializedCAS & crSerializedCAS);

/* ----------------------------------------------------------------------- */
/*       Types / Classes                                                   */
/* ----------------------------------------------------------------------- */

/* ----------------------------------------------------------------------- */
/*       Implementation                                                    */
/* ----------------------------------------------------------------------- */


/********************************************************************
 ***** JNILogger
 ********************************************************************/
  JNILogger::JNILogger(JNIEnv * env) : /*iv_jnienv(env),*/ cv_clazz(0), cv_logMethod(0) {
    assert( EXISTS(env) );
    try {
    env->GetJavaVM(&iv_jvm);
    CHECK_FOR_JNI_EXCEPTION(env);

    cv_clazz = env->FindClass(JAVA_LOGGER_PROXY);
    if (cv_clazz == NULL ) {
        uima::ResourceManager::getInstance().getLogger().logError( 
        JAVA_LOGGER_PROXY " class not found. Could not setup Java logging. ");
      env->ExceptionClear();
      return;
    }
    CHECK_FOR_JNI_EXCEPTION(env);

    cv_clazz = (jclass) env->NewGlobalRef(cv_clazz);
    if (cv_clazz == NULL) {
      uima::ResourceManager::getInstance().getLogger().logError( 
                  "Setup global reference to " JAVA_LOGGER_PROXY " class failed. Could not setup Java logging. ");
      cerr << "JNILogger() ERROR: CPPJEDIIEngine could not construct " << endl;
      env->ExceptionClear();
      return;
    }
    CHECK_FOR_JNI_EXCEPTION(env);

     //query the current logging level
     jmethodID iv_getLoggingLevelMethod = env->GetStaticMethodID(cv_clazz,
                                             "getLoggingLevel",
                                             "()I");
     if (iv_getLoggingLevelMethod == NULL) {
       uima::ResourceManager::getInstance().getLogger().logError( 
            JAVA_LOGGER_PROXY ".getLoggingLevel() not found. Could not setup Java logging. " );
       cout << "JNILogger() ERROR: CPPJEDIIEngine.getLoggingLevel() not found " << endl;
       env->ExceptionClear();
       return;
      }
     CHECK_FOR_JNI_EXCEPTION(env);

      //log method
      cv_logMethod = env->GetStaticMethodID(cv_clazz, "log", "("
                       "I"       // level
                       "Ljava/lang/String;"  // source class
                       "Ljava/lang/String;" // source method
                       "Ljava/lang/String;" // message
                       ")V");

      if (cv_logMethod == NULL) {
        uima::ResourceManager::getInstance().getLogger().logError( 
            JAVA_LOGGER_PROXY ".log(int,string,string,string) not found. Could not setup Java logging. " );
          cout << "JNILogger() ERROR: CPPJEDIIEngine.log() not found " << endl;
          env->ExceptionClear();
          return;
      }
      CHECK_FOR_JNI_EXCEPTION(env);

      //get the current logging level
      jint logginglevel = env->CallStaticIntMethod(cv_clazz, iv_getLoggingLevelMethod);

      if (logginglevel == 0) {
        uima::ResourceManager::getInstance().getLogger().logError( 
            "JNILogger() Could not determine current logging level. Setup Java logging failed. " );
          cout << "JNILogger() ERROR: calling CPPJEDIIEngine.getLoggingLevel() " << endl;
          env->ExceptionClear();
          return;
      }
      CHECK_FOR_JNI_EXCEPTION(env);

      if (logginglevel == 3) {
        uima::ResourceManager::getInstance().setLoggingLevel(uima::LogStream::EnError);
      } else if (logginglevel == 2) {
        uima::ResourceManager::getInstance().setLoggingLevel(uima::LogStream::EnWarning);
      } else {
        uima::ResourceManager::getInstance().setLoggingLevel(uima::LogStream::EnMessage);
      }

    } catch (...) {
      cout << "Exception in JNILogger() " << endl;
      env->ExceptionDescribe();
    }
  }
  

  void JNILogger::log(uima::LogStream::EnEntryType entype,
                 string classname,
                 string methodname,
                 string message,
                 long lUserCode) {

      //get JNI env associated with the current thread
      JNIEnv * jnienv=0;
      try {
      iv_jvm->AttachCurrentThread((void**)&jnienv, NULL);

      if (jnienv == 0) {
        cerr << "JNILogger::log() failed to get JNI env handle." << endl;
        return;
      }

      stringstream str;
      if (entype == uima::LogStream::EnMessage) {
        if (lUserCode != 0) {
           str << lUserCode << " " << message;
        } else {
		  str << message;
        }
      } else {
        str << lUserCode << " " << message;
      }
      
      UnicodeString msg(str.str().c_str());
      // Convert the std::strings to Unicode using the default converter
      UnicodeString ustrsource(classname.c_str(), classname.length());
      UnicodeString ustrmethod(methodname.c_str(), methodname.length());
      jstring jsrcclass = jnienv->NewString((jchar const *) ustrsource.getBuffer(), ustrsource.length());
      jstring jsrcmethod = jnienv->NewString((jchar const *) ustrmethod.getBuffer(), ustrmethod.length());
      jstring jmessage = jnienv->NewString((jchar const *) msg.getBuffer(), msg.length());

      jint loglevel;
      if ( entype == uima::LogStream::EnError) {
        loglevel = 3;
      } else  if ( entype == uima::LogStream::EnWarning )  {
        loglevel  = 2;
      } else {
        loglevel = 1;
      }

      // Call exception clear
      jnienv->ExceptionClear();

      jnienv->CallStaticVoidMethod(cv_clazz,
                                   cv_logMethod,
                                   loglevel,
                                   jsrcclass,
                                   jsrcmethod,
                                   jmessage);

      // Check for exceptions :
      jthrowable exc = jnienv->ExceptionOccurred();
      if (exc != NULL) {
        jnienv->ExceptionDescribe();
        jnienv->ExceptionClear();
      }
      iv_jvm->DetachCurrentThread();
      //cout << "ThreadId: " << threadid << " JNILogger::log() DONE" << endl;
    } catch (...) {
      iv_jvm->DetachCurrentThread();
      cout << "JNILogger::log(...) Exception in JavaLogging()" << endl;
    }
  }
/********************************************************************
 ***** JNI Functions
 ********************************************************************/

/*********************************************************************
 * static method to get this UIMACPP JNI version
 */
JNIEXPORT jstring JNICALL JAVA_PREFIX(getVersionJNI) (JNIEnv* jeEnv, jclass) {
  try {
    jstring jsVersion = jeEnv->NewStringUTF(UIMA_JNI_VERSION);
    ASSERT_NO_JNI_EXCEPTION(jeEnv);
    return jsVersion;
  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return NULL;
  } catch (...) {
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION_WITH_RETURN_VALUE(jeEnv, NULL);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return NULL;
  }
}

/*******************************************************************
 * create UIMACPP resource manager
 */
JNIEXPORT void JNICALL JAVA_PREFIX(createResourceManagerJNI) (JNIEnv* jeEnv, jclass) {
  try {
    UIMA_TPRINT("createResourceManagerJNI() entered");

    (void) uima::ResourceManager::createInstance("Main", UIMA_STRINGIFY(UIMA_PREFIX));

    UIMA_TPRINT("createResourceManagerJNI() finished");
  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString());
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return;
  } catch (...) {
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION(jeEnv);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return;
  }

}


/********************************************************************
 * configure UIMACPP resource manager
 */
JNIEXPORT void JNICALL JAVA_PREFIX(configureResourceManagerJNI) (JNIEnv* jeEnv,
    jclass,
    jstring jsWorkDirectory,
    jstring jsDataDirectory) {
  try {
    UIMA_TPRINT("configureResourceManagerJNI entered");
 
    uima::ResourceManager& rResourceManager = uima::ResourceManager::getInstance();

    JNIUString workDir(jeEnv, jsWorkDirectory);
    string strWorkDirectory;
    workDir.convertToSystemCodePage(strWorkDirectory);

    JNIUString dataDir(jeEnv, jsDataDirectory);
    string strDataDirectory;
    dataDir.convertToSystemCodePage(strDataDirectory);

    UIMA_TPRINT(" configuring resource manager with");
    UIMA_TPRINT("   working directory: " << strWorkDirectory);
    UIMA_TPRINT("   data    directory: " << strDataDirectory);

    // Since UIMA_DATAPATH is a list of paths and UIMACPP wants just one,
    // we'll take the first by pretending to search for a empty file.
    // Will find the first path that exists, or the last if none exist.
    // No longer check that the data path exists.

    uima::util::Filename dataPath("");
    dataPath.determinePath( strDataDirectory.c_str());
    uima::util::Location dataLocation(dataPath.getAsCString());

    uima::util::Location workLocation(strWorkDirectory.c_str());
    if (! workLocation.isExistent() ) {
      uima::ErrorInfo errInfo(uima::ErrorMessage(UIMA_MSG_ID_RESMGR_WORKDIR_DOES_NOT_EXIST, strWorkDirectory.c_str()),
                              UIMA_ERR_RESMGR_WORK_DIR_DOES_NOT_EXIST,
                              uima::ErrorInfo::recoverable);
      JNIUtils::throwNewInternalException(jeEnv, errInfo);
      return;
    }

    rResourceManager.setNewLocationWork(workLocation);
    rResourceManager.setNewLocationData(dataLocation);
    
    UIMA_TPRINT("configureResourceManagerJNI finished");
  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return;
  } catch (...) {
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION(jeEnv);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return;
  }
}

/**********************************************************************
 * constructs a new UIMACPP engine and CASSerializer
 * and sets the field in the Java object
 */
JNIEXPORT void JNICALL JAVA_PREFIX(constructorJNI) (JNIEnv* jeEnv,
    jobject joJTaf) {
  try {
    UIMA_TPRINT("constructorJNI() entered");

    uima::JNIInstance * pInstance = new uima::JNIInstance();
    if (pInstance == NULL) {
      uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_OUT_OF_MEMORY,
                              UIMA_ERR_ENGINE_OUT_OF_MEMORY,
                              uima::ErrorInfo::unrecoverable);
      JNIUtils::throwNewInternalException(jeEnv, errInfo);
      return;
    }
    //setup JNI logger
    if (singleton_jni_logger == NULL) {
      cout << "creating JNILogger" << endl;
      singleton_jni_logger = new JNILogger(jeEnv);
      uima::ResourceManager::getInstance().registerLogger(singleton_jni_logger);
    }

    // setting engine
    JNIUtils::setCppInstance(jeEnv, joJTaf, pInstance);

    UIMA_TPRINT("constructorJNI() finished");
  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return;
  } catch (...) {
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION(jeEnv);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return;
  }
}


/*********************************************************************
 * deletes the objects created by constructorJNI()
 */
JNIEXPORT void JNICALL JAVA_PREFIX(destructorJNI) (JNIEnv* jeEnv, jobject joJTaf) {
  try {
    UIMA_TPRINT("destructorJNI() entered");

    uima::JNIInstance* pInstance = JNIUtils::getCppInstance(jeEnv, joJTaf);
    assert( EXISTS(pInstance) );

    delete pInstance;

    UIMA_TPRINT("destructorJNI() finished");
  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return;
  } catch (...) {
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION(jeEnv);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return;
  }
}


/**********************************************************************
 * initialize engine
 */
JNIEXPORT void JNICALL JAVA_PREFIX(initializeJNI) (JNIEnv* jeEnv,
    jobject joJTaf,
    jstring jsConfigFile
                                                  ) {
  try {
    UIMA_TPRINT("entering initializeJNI()");

    assert(jsConfigFile != NULL);

    JNIUString configFile(jeEnv, jsConfigFile);

    uima::UnicodeStringRef uref = configFile.toUStrPtrLenPair();

    uima::JNIInstance* pInstance = JNIUtils::getCppInstance(jeEnv, joJTaf);
    assert( EXISTS(pInstance) );

    uima::ErrorInfo errInfo;

    UIMA_TPRINT("creating engine");
    UIMA_TPRINT(uref);
    uima::ResourceManager::getInstance().enableSchemaValidation(false);
    // initialize engine
    uima::AnalysisEngine * pEngine = uima::Framework::createAnalysisEngine( (UChar*)uref.getBuffer(), 
       uref.length(), errInfo);
    if (errInfo.getErrorId() != UIMA_ERR_NONE) {
      assert( pEngine == NULL );
      UIMA_TPRINT("Error during initializing engine (code= " << errInfo.getErrorId() << ")" );
      JNIUtils::throwNewInternalException(jeEnv, errInfo );
      return;
    }
    pInstance->setEngine( pEngine );
    UIMA_TPRINT("engine created and set");

    UIMA_TPRINT("Creating CAS");
    // create CAS
    uima::CAS * pCAS = pEngine->newCAS();
    assert( EXISTS(pCAS) );
    pInstance->setCAS(pCAS);
    UIMA_TPRINT("CAS created");

    UIMA_TPRINT("initializeJNI() finished");
  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return;
  }
#ifdef NDEBUG
  catch (...) {
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION(jeEnv);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return;
  }
#endif
}


/**********************************************************************
 * initialize engine
 */
JNIEXPORT void JNICALL JAVA_PREFIX(typeSystemInitJNI) (JNIEnv* jeEnv,
    jobject joJTaf,

    jobjectArray typeNames,
    jobjectArray featureNames,
    jintArray typeInheritance,
    jintArray featDecls,
    jint topTypeCode,
    jintArray featureOffsets,
    jintArray typeOrder,

    jintArray stringSubTypes,
    jobjectArray stringSubTypeValues,
    jintArray stringSubTypeValuePos,

    jobjectArray indexNames,
    jintArray nameToIndexMap,
    jintArray indexingStrategy,
    jintArray comparatorIndex,
    jintArray comparators
                                                      ) {
  try {
    UIMA_TPRINT("entering typeSystemInitJNI()");
    uima::JNIInstance* pInstance = JNIUtils::getCppInstance(jeEnv, joJTaf);
    assert( EXISTS(pInstance) );

    assert( typeNames != NULL );
    assert( featureNames != NULL );
    assert( typeInheritance != NULL );
    assert( featDecls != NULL );
    assert( typeOrder != NULL );
//      assert( featureOffsets != NULL );

    assert( indexNames != NULL );
    assert( nameToIndexMap != NULL );
    assert( indexingStrategy != NULL );
    assert( comparatorIndex != NULL );
    assert( comparators != NULL);

    vector<icu::UnicodeString> vecTypeNames, vecFeatureNames, vecIndexNames, vecSubStringValues;

    // prepare deserialization
    uima::internal::SerializedCAS rSerCAS;
    UIMA_TPRINT("converting type inh vector");
    JNIUtils::createIntVector(jeEnv, typeInheritance, rSerCAS.iv_vecTypeInheritanceTable );
    UIMA_TPRINT("   converted");
    JNIUtils::createIntVector(jeEnv, featDecls, rSerCAS.iv_vecFeatureDefinitionTable );
    UIMA_TPRINT("converting type name vector");
    JNIUtils::createStringVector(jeEnv, typeNames, rSerCAS.iv_vecTypeSymbolTable, vecTypeNames);
    UIMA_TPRINT("   converted");
    JNIUtils::createStringVector( jeEnv, featureNames,  rSerCAS.iv_vecFeatureSymbolTable, vecFeatureNames );
    JNIUtils::createIntVector(jeEnv, typeOrder, rSerCAS.iv_vecTypePriorityTable );
    //      JNIUtils::createIntVector(jeEnv, featureOffsets, rSerCAS.iv_vecFeatureOffsetTable );
    rSerCAS.iv_vecFeatureOffsetTable.clear();

    JNIUtils::createIntVector(jeEnv, stringSubTypes, rSerCAS.iv_stringSubTypes);
    JNIUtils::createStringVector(jeEnv, stringSubTypeValues, rSerCAS.iv_stringSubTypeValues, vecSubStringValues);
    JNIUtils::createIntVector(jeEnv, stringSubTypeValuePos, rSerCAS.iv_stringSubTypeValuePos);

    JNIUtils::createStringVector(jeEnv, indexNames, rSerCAS.iv_vecIndexIDTable, vecIndexNames );
    JNIUtils::createIntVector(jeEnv,comparators, rSerCAS.iv_vecComparatorDefinitionTable);
    JNIUtils::createIntVector(jeEnv,comparatorIndex, rSerCAS.iv_vecComparatorStartTable);
    JNIUtils::createIntVector(jeEnv, indexingStrategy, rSerCAS.iv_vecIndexKindTable );

    uima::AnalysisEngine * pEngine =  pInstance->getEngine();
    uima::internal::EngineBase & engineBase = uima::internal::EngineBase::promoteEngine(*pEngine);
    uima::internal::CASDefinition & casDef = engineBase.getCASDefinition();

    UIMA_TPRINT("deserializng definitions");
    // deserialize CAS definitions (type system and index info)
    uima::internal::CASDeserializer deSerializer;
    deSerializer.deserializeDefinitions( rSerCAS, casDef );
    UIMA_TPRINT("   done deserializing definitions");

    engineBase.reinitTypeSystem();

    uima::CAS * pCAS = pInstance->getCAS();
    if (pCAS != NULL) {
      delete pCAS;
      pInstance->setCAS(NULL);
    }

    UIMA_TPRINT("recreate CAS");
    pCAS = pEngine->newCAS();
    assert( EXISTS(pCAS) );
    pInstance->setCAS(pCAS);

    UIMA_TPRINT("typeSystemInitJNI() finished");
  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return;
  }
#ifdef NDEBUG
  catch (...) {
    //cout << "typeSystemInitJNI: Unknown Exception " << endl;
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION(jeEnv);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return;
  }
#endif
}


/**********************************************************************
 * fill CAS
 */

JNIEXPORT void JNICALL JAVA_PREFIX(fillCASJNI) (JNIEnv* jeEnv,
    jobject joJTaf,
    jintArray heapArray,
    jintArray fsIndex,
    jobjectArray stringTable,
    jbyteArray byteHeapArray,
    jshortArray shortHeapArray,
    jlongArray longHeapArray ) {
  try {
    UIMA_TPRINT("fillCASJNI() started");
    uima::JNIInstance* pInstance = JNIUtils::getCppInstance(jeEnv, joJTaf);
    assert( EXISTS(pInstance) );

    uima::CAS * cas = pInstance->getCAS();
    assert( EXISTS(cas) );
    uima::internal::SerializedCAS serCAS;

    vector<icu::UnicodeString> vecStringTable;

    JNIUtils::createStringVector(jeEnv, stringTable, serCAS.iv_vecStringSymbolTable, vecStringTable );
#ifdef DEBUG_VERBOSE
    size_t iVerbose;
    UIMA_TPRINT("STRINGHeap: ");
    for (iVerbose=0; iVerbose<serCAS.iv_vecStringSymbolTable.size(); ++iVerbose) {
      UIMA_TPRINT("   " << iVerbose << ": " << serCAS.iv_vecStringSymbolTable[iVerbose]);
    }
#endif

    JNIUtils::createIntVector(jeEnv, heapArray, serCAS.iv_vecFSHeapArray);
#ifdef DEBUG_VERBOSE
    UIMA_TPRINT("HEAP: ");
    for (iVerbose=0; iVerbose<serCAS.iv_vecFSHeapArray.size(); ++iVerbose) {
      UIMA_TPRINT("   " << iVerbose << ": " << serCAS.iv_vecFSHeapArray[iVerbose]);
    }
#endif

    JNIUtils::createIntVector(jeEnv, fsIndex, serCAS.iv_vecIndexedFSs);

    JNIUtils::createByteVector(jeEnv,byteHeapArray, serCAS.iv_vecByteHeapArray);
    JNIUtils::createShortVector(jeEnv,shortHeapArray, serCAS.iv_vecShortHeapArray);
    JNIUtils::createLongVector(jeEnv,longHeapArray, serCAS.iv_vecLongHeapArray);
    uima::internal::CASDeserializer casDeSerializer;
    casDeSerializer.deserializeData( serCAS, *cas );
    UIMA_TPRINT("fillCASJNI() finished");
  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return;
  } catch (...) {
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION(jeEnv);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return;
  }
}

/*********************************************************************
 * de initialize engine
 */
JNIEXPORT void JNICALL JAVA_PREFIX(destroyJNI) (JNIEnv* jeEnv, jobject joJTaf) {
  try {
    UIMA_TPRINT("entering destroyJNI()");

    uima::JNIInstance* pInstance = JNIUtils::getCppInstance(jeEnv, joJTaf);
    assert( EXISTS(pInstance) );

    uima::AnalysisEngine * pEngine =  pInstance->getEngine();

    uima::TyErrorId tyErrorId = pEngine->destroy();
    if (tyErrorId != UIMA_ERR_NONE) {
      UIMA_TPRINT("Error during deInitializing engine (code= " << tyErrorId << ")" );
      JNIUtils::throwNewInternalException(jeEnv, pEngine->getAnnotatorContext().getLogger().getLastError() );
      return;
    }

    if (pEngine != NULL) {
      delete pEngine;
      pInstance->setEngine(NULL);
    }

    JNIUtils::setCppInstance(jeEnv, joJTaf, 0);

    uima::CAS * pCAS = pInstance->getCAS();
    if (pCAS != NULL) {
      delete pCAS;
      pInstance->setCAS(NULL);
    }

    delete pInstance;

    UIMA_TPRINT("exiting destroy()");
  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return;
  } catch (...) {
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION(jeEnv);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return;
  }
}





/************************************************************
 * process the CAS.
 */
JNIEXPORT void JNICALL JAVA_PREFIX(processJNI) (JNIEnv* jeEnv,
    jobject joJTaf,
    jint isTCas,
    jstring sofaName,
    jintArray resultSpecTypes,
    jintArray resultSpecFeatures) {
  try {
    //    cout << "processJNI" << endl;
    UIMA_TPRINT("entering processDocument");

    uima::JNIInstance* pInstance = JNIUtils::getCppInstance(jeEnv, joJTaf);
    assert( EXISTS(pInstance) );

    uima::AnalysisEngine * pEngine = pInstance->getEngine();
    assert( EXISTS(pEngine) );

    uima::CAS & cas = *pInstance->getCAS();
    uima::ResultSpecification rs;

    vector<uima::internal::SerializedCAS::TyNum> rsTypes;
    JNIUtils::createIntVector(jeEnv, resultSpecTypes, rsTypes);
    vector<uima::internal::SerializedCAS::TyNum> rsFeatures;
    JNIUtils::createIntVector(jeEnv, resultSpecFeatures, rsFeatures);
    uima::internal::CASDeserializer::deserializeResultSpecification(rsTypes, rsFeatures, pInstance->getCASImpl().getCASDefinition(), rs);

//      cerr << __FILE__ << __LINE__ << ": ";
//      rs.print(cerr);

    UIMA_TPRINT("CAS BEFORE process: ");
#ifdef DEBUG_VERBOSE
#ifndef NDEBUG
    ///uima::internal::CASImpl const & crCASImpl = uima::internal::CASImpl::promoteCAS( *pInstance->getCAS() );
    ///crCASImpl.getHeap().print(cerr);
#endif
#endif
    //uima::TyErrorId tyErrorId;
    uima::CAS* tcas;
    if (isTCas) {
      JNIUString usSofaName(jeEnv, sofaName);
      UIMA_TPRINT("TCAS BEFORE process: " );
      UIMA_TPRINT(sofaName );
      uima::SofaID sofaid;
      uima::UnicodeStringRef ref = usSofaName.toUStrPtrLenPair();
      icu::UnicodeString usofa = icu::UnicodeString( ref.getBuffer(), ref.length() );
      sofaid.setSofaId( UnicodeString(usofa) );
      sofaid.setComponentSofaName(usofa);
      tcas = cas.getView(cas.getSofa(sofaid));
      ///tyErrorId = ((uima::AnalysisEngine*) pEngine)->process(*tcas);
      uima::CASIterator iter  = ((uima::AnalysisEngine*) pEngine)->processAndOutputNewCASes(*tcas);
    } else {
      /////tyErrorId = ((uima::AnalysisEngine*) pEngine)->process(cas);
      UIMA_TPRINT("CAS BEFORE process: " );
      uima::CASIterator iter = ((uima::AnalysisEngine*) pEngine)->processAndOutputNewCASes(cas);
    }
    /****
    if (tyErrorId != UIMA_ERR_NONE) {
       UIMA_TPRINT("Error during processDocument() (code= " << tyErrorId << ")" );
       uima::ErrorInfo const & lastError = pEngine->getAnnotatorContext(). getLogger().getLastError();
       if ( lastError.getErrorId() == UIMA_ERR_NONE ) {
          uima::ErrorInfo newError;
          newError.setErrorId(tyErrorId);
          JNIUtils::throwNewInternalException(jeEnv, newError);
       }
       else {
          assert(lastError.getErrorId() == tyErrorId);
          JNIUtils::throwNewInternalException(jeEnv, lastError);
       }
       return;
    } ****/

    UIMA_TPRINT("CAS AFTER process: ");
#ifdef DEBUG_VERBOSE
#ifndef NDEBUG
    crCASImpl.getHeap().print(cerr);
#endif
#endif


    UIMA_TPRINT("exiting processDocument");
  } catch (uima::Exception & rException) {
    cout << "processJNI: Exception " << rException.asString() << endl;
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return;
  }
#ifdef NDEBUG
//#ifdef TEMP_DISABLED
  catch (...) {
    //cout << "processJNI: all other execptions" << endl;
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION(jeEnv);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return;
  }
#endif
}


/***********************************************************************
 * delete the current document.
 */
JNIEXPORT void JNICALL JAVA_PREFIX(resetJNI) (JNIEnv* jeEnv, jobject joJTaf) {
  try {
    UIMA_TPRINT("entering resetDocument()");

    uima::JNIInstance* pInstance = JNIUtils::getCppInstance(jeEnv, joJTaf);
    assert( EXISTS(pInstance) );
    pInstance->getSerializedCAS().reset();

    uima::TyErrorId tyErrorId = pInstance->getCAS()->reset();

    //TODO: handle CAS multiplier - return new CASs to pool
    //     end the segementation.

    if (tyErrorId != UIMA_ERR_NONE) {
      UIMA_TPRINT("Error during resetDocument() (code= " << tyErrorId << ")" );
      uima::ErrorInfo errInfo(UIMA_MSG_ID_NO_MESSAGE_AVAILABLE,
                              tyErrorId,
                              uima::ErrorInfo::unrecoverable);
      JNIUtils::throwNewInternalException(jeEnv, errInfo);
      return;
    }
    UIMA_TPRINT("exiting resetDocument()");
  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return;
  } catch (...) {
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION(jeEnv);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return;
  }
}


/***********************************************************************
 */
JNIEXPORT void JNICALL JAVA_PREFIX(serializeCASJNI) (JNIEnv* jeEnv, jobject joJTaf, jboolean jbSerializeData) {
  try {
    UIMA_TPRINT("entering serializeCASJNI()");

    uima::JNIInstance* pInstance = JNIUtils::getCppInstance(jeEnv, joJTaf);
    assert( EXISTS(pInstance) );

    uima::internal::CASSerializer serializer(false);

    // definitions should not be called from here any more (see initializeJNI() )
    assert( jbSerializeData == JNI_TRUE );
    serializer.serializeData( pInstance->getCASImpl(), pInstance->getSerializedCAS() );

#ifdef UIMA_ENABLE_SERIALIZATION_TIMING
    cout << __FILE__ << __LINE__ << ": CPP/JEDII JNI layer - Time for serialization of heap: " << serializer.getHeapTimer().timeString() << endl;
    cout << __FILE__ << __LINE__ << ": CPP/JEDII JNI layer - Time for serialization of indexed FSs: " << serializer.getIndexTimer().timeString() << endl;
#endif
    UIMA_TPRINT("serializeCASJNI() finished");
  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return;
  } catch (...) {
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION(jeEnv);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return;
  }
}

/***********************************************************************
 */
JNIEXPORT void JNICALL JAVA_PREFIX(serializeSegmentJNI) (JNIEnv* jeEnv, jobject joJTaf, jboolean jbSerializeData) {
  try {
    UIMA_TPRINT("entering serializeSegmentJNI()");

    uima::JNIInstance* pInstance = JNIUtils::getCppInstance(jeEnv, joJTaf);
    assert( EXISTS(pInstance) );

    uima::internal::CASSerializer serializer(false);

    // definitions should not be called from here any more (see initializeJNI() )
    assert( jbSerializeData == JNI_TRUE );
    uima::internal::CASImpl & casimpl = uima::internal::CASImpl::promoteCAS( *(pInstance->getSegment()) );
    UIMA_TPRINT(casimpl.getDocumentText());
    serializer.serializeData( casimpl, pInstance->getSerializedSegment() );

#ifdef UIMA_ENABLE_SERIALIZATION_TIMING
    cout << __FILE__ << __LINE__ << ": TAF/JEDII JNI layer - Time for serialization of heap: " << serializer.getHeapTimer().timeString() << endl;
    cout << __FILE__ << __LINE__ << ": TAF/JEDII JNI layer - Time for serialization of indexed FSs: " << serializer.getIndexTimer().timeString() << endl;
#endif
    UIMA_TPRINT("serializeSegmentJNI() finished");
  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return;
  } catch (...) {
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION(jeEnv);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return;
  }
}



class JavaIntegerObject : public JavaObject {
private:
  JavaIntegerObject(JavaIntegerObject const &);

public:
  JavaIntegerObject(JNIEnv * jeEnv, int iNum)
      : JavaObject(jeEnv, "java/lang/Integer", "(I)V") {
    assertWithMsg( (sizeof(jint) == sizeof(int)), "Port required");
    jvalue args[1];
    args[0].i = iNum;
    createJObject(args);
  }
};


JNIEXPORT jobject JNICALL JAVA_PREFIX(getSerializedDataJNI) (JNIEnv* jeEnv, jobject joJTaf, jint jiWhichData) {
  jobject joResult = NULL;
  try {
    UIMA_TPRINT("getSerializedDataJNI() entered");
    uima::JNIInstance* pInstance = JNIUtils::getCppInstance(jeEnv, joJTaf);
    assert( EXISTS(pInstance) );
    uima::internal::SerializedCAS & crSerializedCAS = pInstance->getSerializedCAS();
    joResult = getSerializedCasData(jeEnv, joJTaf, jiWhichData, crSerializedCAS);
    UIMA_TPRINT("getSerializedDataJNI() finished");
  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return NULL;
  } catch (...) {
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION_WITH_RETURN_VALUE(jeEnv, NULL);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return NULL;
  }
  return joResult;
}

JNIEXPORT jobject JNICALL JAVA_PREFIX(getSerializedSegmentDataJNI) (JNIEnv* jeEnv, jobject joJTaf, jint jiWhichData) {
  jobject joResult = NULL;
  try {
    UIMA_TPRINT("getSerializedSegmentDataJNI() entered");
    uima::JNIInstance* pInstance = JNIUtils::getCppInstance(jeEnv, joJTaf);
    assert( EXISTS(pInstance) );
    uima::internal::SerializedCAS & crSerializedCAS = pInstance->getSerializedSegment();
    joResult = getSerializedCasData(jeEnv, joJTaf, jiWhichData, crSerializedCAS);
    UIMA_TPRINT("getSerializedDataJNI() finished");
  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return NULL;
  } catch (...) {
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION_WITH_RETURN_VALUE(jeEnv, NULL);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return NULL;
  }
  UIMA_TPRINT("getSerializedSegmentDataJNI() done");
  return joResult;
}


jobject getSerializedCasData (JNIEnv* jeEnv, jobject joJTaf, jint jiWhichData, uima::internal::SerializedCAS & crSerializedCAS) {
  jobject joResult = NULL;
  try {
    UIMA_TPRINT("getSerializedDataJNI() entered");
    uima::JNIInstance* pInstance = JNIUtils::getCppInstance(jeEnv, joJTaf);
    assert( EXISTS(pInstance) );
    //////uima::internal::SerializedCAS const & crSerializedCAS = pInstance->getSerializedCAS();

    {

      // the C++ objects created for TOPTYPE and DOCUMENT are destroyed after the switch
      // but the created Java object inside is still alive

      switch (jiWhichData) {
      case CONST_PREFIX( TYPE_INH ):
              joResult = JNIUtils::createIntArray(jeEnv, crSerializedCAS.getTypeInheritanceTable());
        break;
      case CONST_PREFIX(FEATURE_DEF):
              joResult = JNIUtils::createIntArray(jeEnv, crSerializedCAS.getFeatureDefinitionTable());
        break;
      case CONST_PREFIX(FEATURE_OFFSET):
              joResult = JNIUtils::createIntArray(jeEnv, crSerializedCAS.getFeatureOffsetTable());
        break;
      case CONST_PREFIX(TYPE_SYMBOLS):
              joResult = JNIUtils::createStringArray(jeEnv, crSerializedCAS.getTypeSymbolTable());
        break;
      case CONST_PREFIX(FEATURE_SYMBOLS):
              joResult = JNIUtils::createStringArray(jeEnv, crSerializedCAS.getFeatureSymbolTable());
        break;
      case CONST_PREFIX( TYPE_PRIORITIES):
              joResult = JNIUtils::createIntArray(jeEnv, crSerializedCAS.getTypePriorityTable() );
        break;
      case CONST_PREFIX(TOPTYPE): {
        assert( sizeof(uima::lowlevel::TyFSType) == sizeof(jint) );
        uima::lowlevel::TyFSType tyTop = pInstance->getCASImpl().getHeap().getTypeSystem().getTopType();
        assert(pInstance->getCASImpl().getHeap().getTypeSystem().isValidType(tyTop));
        JavaIntegerObject javaInt(jeEnv, (int) tyTop );
        joResult = javaInt.getJObject();
      }
      break;
      case CONST_PREFIX(FSHEAP):
              joResult = JNIUtils::createIntArray(jeEnv, crSerializedCAS.getFSHeapArray());
        break;
      case CONST_PREFIX(BYTEHEAP):
              joResult = JNIUtils::createByteArray(jeEnv, crSerializedCAS.getByteHeapArray());
        break;
      case CONST_PREFIX(SHORTHEAP):
              joResult = JNIUtils::createShortArray(jeEnv, crSerializedCAS.getShortHeapArray());
        break;
      case CONST_PREFIX(LONGHEAP):
              joResult = JNIUtils::createLongArray(jeEnv, crSerializedCAS.getLongHeapArray());
        break;
      case CONST_PREFIX(STRINGSYMBOL):
              joResult = JNIUtils::createStringArray(jeEnv, crSerializedCAS.getStringSymbolTable());
        break;
      case CONST_PREFIX(DOCUMENT): {
//               uima::UnicodeStringRef ustrp = pInstance->getCAS()->getDocumentText();
//            UIMA_TPRINT("Doc text: " << ustrp);
//               JavaString javaStr(jeEnv, ustrp);
//               joResult = javaStr.getJObject();
        break;
      }
      case CONST_PREFIX(INDEXEDFSS):
              joResult = JNIUtils::createIntArray(jeEnv, crSerializedCAS.getIndexedFSs());
        break;
      case CONST_PREFIX(INDEXID):
              joResult = JNIUtils::createStringArray(jeEnv, crSerializedCAS.getIndexIDTable() );
        break;
      case CONST_PREFIX(INDEXKIND):
              joResult = JNIUtils::createIntArray(jeEnv, crSerializedCAS.getIndexKindTable() );
        break;
      case CONST_PREFIX(COMPARATORDEF):
              joResult = JNIUtils::createIntArray(jeEnv, crSerializedCAS.getComparatorDefinitionTable() );
        break;
      case CONST_PREFIX(COMPARATORSTART):
              joResult = JNIUtils::createIntArray(jeEnv, crSerializedCAS.getComparatorStartTable() );
        break;
      default:
        assert(false);
      }
    }
    UIMA_TPRINT("getSerializedDataJNI() finished");
  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return NULL;
  } catch (...) {
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION_WITH_RETURN_VALUE(jeEnv, NULL);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return NULL;
  }
  return joResult;
}


/*********************************************************************
 * static method to get the error message from an errorId.
 */
JNIEXPORT jstring JNICALL JAVA_PREFIX(getErrorMessageJNI) (JNIEnv* jeEnv,
    jclass,
    jlong jlErrorId) {
  try {
    const char* cpszErrorId = (const char*) uima::AnalysisEngine::getErrorIdAsCString( (long) jlErrorId);
    jstring jsError = jeEnv->NewStringUTF(cpszErrorId);
    ASSERT_NO_JNI_EXCEPTION(jeEnv);
    return jsError;
  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return NULL;
  } catch (...) {
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION_WITH_RETURN_VALUE(jeEnv, NULL);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return NULL;
  }
}

/*********************************************************************
 * batchProcessComplete
 */
JNIEXPORT void JNICALL JAVA_PREFIX(batchProcessCompleteJNI) (JNIEnv* jeEnv, jobject joJTaf) {
  try {
    UIMA_TPRINT("entering batchProcessCompleteJNI()");

    uima::JNIInstance* pInstance = JNIUtils::getCppInstance(jeEnv, joJTaf);
    assert( EXISTS(pInstance) );

    uima::AnalysisEngine * pEngine =  pInstance->getEngine();

    uima::TyErrorId tyErrorId = pEngine->batchProcessComplete();
    if (tyErrorId != UIMA_ERR_NONE) {
      UIMA_TPRINT("Error during deInitializing engine (code= " << tyErrorId << ")" );
      JNIUtils::throwNewInternalException(jeEnv, pEngine->getAnnotatorContext().getLogger().getLastError() );
      return;
    }

    UIMA_TPRINT("exiting batchProcessComplete()");
  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return;
  } catch (...) {
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION(jeEnv);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return;
  }
}

/*********************************************************************
 * collectionProcessComplete
 */
JNIEXPORT void JNICALL JAVA_PREFIX(collectionProcessCompleteJNI) (JNIEnv* jeEnv, jobject joJTaf) {
  try {
    UIMA_TPRINT("entering collectionProcessCompleteJNI()");

    uima::JNIInstance* pInstance = JNIUtils::getCppInstance(jeEnv, joJTaf);
    assert( EXISTS(pInstance) );

    uima::AnalysisEngine * pEngine =  pInstance->getEngine();

    uima::TyErrorId tyErrorId = pEngine->collectionProcessComplete();
    if (tyErrorId != UIMA_ERR_NONE) {
      UIMA_TPRINT("Error during deInitializing engine (code= " << tyErrorId << ")" );
      JNIUtils::throwNewInternalException(jeEnv, pEngine->getAnnotatorContext().getLogger().getLastError() );
      return;
    }

    UIMA_TPRINT("exiting collectionProcessComplete()");
  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return;
  } catch (...) {
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION(jeEnv);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return;
  }
}


/*********************************************************************
 * hasNextSegmentJNI
 */
JNIEXPORT jboolean JNICALL JAVA_PREFIX(hasNextSegmentJNI) (JNIEnv* jeEnv, jobject joJTaf) {
  try {
    UIMA_TPRINT("entering hasNextSegmentJNI()");

    uima::JNIInstance* pInstance = JNIUtils::getCppInstance(jeEnv, joJTaf);
    assert( EXISTS(pInstance) );

    jboolean hasNext = pInstance->hasNext();

    UIMA_TPRINT("exiting hasNextSegmentJNI()");

    return hasNext;

  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return false;
  } catch (...) {
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION_WITH_RETURN_VALUE(jeEnv, false);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return false;
  }
  return false;
}


/*********************************************************************
 * nextSegmentJNI
 */
JNIEXPORT void JNICALL JAVA_PREFIX(nextSegmentJNI) (JNIEnv* jeEnv, jobject joJTaf) {
  try {
    UIMA_TPRINT("entering nextSegmentJNI()");

    uima::JNIInstance* pInstance = JNIUtils::getCppInstance(jeEnv, joJTaf);
    assert( EXISTS(pInstance) );

    //release the previous segment if necessary
    UIMA_TPRINT("nextSegmentJNI() release previous segment ");
    pInstance->releaseSegment();

    pInstance->next();
    ////pInstance->setSegment(pInstance->getCASIterator().next());

    if (pInstance->getSegment() == NULL) {
      UIMA_TPRINT("Error during engine.next() " );
      JNIUtils::throwNewInternalException(jeEnv,  pInstance->getEngine()->getAnnotatorContext().getLogger().getLastError() );
      return;
    }

    UIMA_TPRINT("exiting nextSegmentJNI()");
    return;
  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return;
  } catch (...) {
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION(jeEnv);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return;
  }
}


/*********************************************************************
 * releaseSegmentJNI
 */
JNIEXPORT void JNICALL JAVA_PREFIX(releaseSegmentJNI) (JNIEnv* jeEnv, jobject joJTaf) {
  try {
    UIMA_TPRINT("entering releaseSegmentJNI()");

    uima::JNIInstance* pInstance = JNIUtils::getCppInstance(jeEnv, joJTaf);
    assert( EXISTS(pInstance) );

    uima::AnalysisEngine * pEngine =  pInstance->getEngine();

    //release cas.
    pInstance->releaseSegment();

    UIMA_TPRINT("exiting releaseSegmentJNI()");
    return;
  } catch (uima::Exception & rException) {
    UIMA_TPRINT("Exception: " << rException.asString() );
    JNIUtils::throwNewInternalException(jeEnv, rException);
    return;
  } catch (...) {
    UIMA_TPRINT("Unknown Exception" );
    CHECK_FOR_JNI_EXCEPTION(jeEnv);
    uima::ErrorInfo errInfo(UIMA_MSG_ID_EXC_UNEXPECTED_ERROR, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION, uima::ErrorInfo::unrecoverable);
    JNIUtils::throwNewInternalException(jeEnv, errInfo);
    return;
  }
}










