/** @name jni_utils.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:

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


   07/26/2000  Initial creation

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

/*@{*/                                                /* Doc++ Group */

/* ----------------------------------------------------------------------- */
/*       Include dependencies                                              */
/* ----------------------------------------------------------------------- */
#include "uima/pragmas.hpp"
#include "uima/jni_utils.hpp"
#include "uima/macros.h"

/* ----------------------------------------------------------------------- */
/*       Constants                                                         */
/* ----------------------------------------------------------------------- */
#define JAVA_CLASS_INTERNALTAFEXCEPTION "org/apache/uima/uimacpp/InternalTafException"
#define JUIMA_FIELD_CPPENGINEPOINTER "cppEnginePointer"
/* ----------------------------------------------------------------------- */
/*       Forward declarations                                              */
/* ----------------------------------------------------------------------- */

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

/* ----------------------------------------------------------------------- */
/*       Implementation                                                    */
/* ----------------------------------------------------------------------- */
using namespace std;
jfieldID JNIUtils::getFieldID(JNIEnv* jeEnv, jobject jo, char const * sig, char const * cpszFieldID) {
  jclass clazz = jeEnv->GetObjectClass(jo);
  ASSERT_NO_JNI_EXCEPTION(jeEnv);
  jfieldID jFID = jeEnv->GetFieldID(clazz, cpszFieldID, sig);
  ASSERT_NO_JNI_EXCEPTION(jeEnv);
  return jFID;
}


long JNIUtils::getLongField(JNIEnv* jeEnv, jobject jo, char const * cpszFieldName) {
  assertWithMsg(sizeof(long) == sizeof(jlong), "Port required");
  jlong jValue = jeEnv->GetLongField(jo, getFieldID(jeEnv, jo, "J", cpszFieldName) );
  ASSERT_NO_JNI_EXCEPTION(jeEnv);
  return (long) jValue;
}

void JNIUtils::setLongField(JNIEnv* jeEnv, jobject jo, char const * cpszFieldName, long l) {
  assertWithMsg(sizeof(long) == sizeof(jlong), "Port required");
  jeEnv->SetLongField(jo, getFieldID(jeEnv, jo, "J", cpszFieldName), (jlong) l);
  ASSERT_NO_JNI_EXCEPTION(jeEnv);
}

/*
void JNIUtils::throwNewInternalException(JNIEnv* jeEnv,
                                            icu::UnicodeString errorMessage) {
   throwNewInternalException(jeEnv, errorMessage, UIMA_ERR_ENGINE_UNEXPECTED_EXCEPTION);
}
*/

void JNIUtils::throwNewInternalException(JNIEnv* jeEnv,
    icu::UnicodeString errorMessage,
    uima::TyErrorId errorId) {
  jclass clazz = jeEnv->FindClass(JAVA_CLASS_INTERNALTAFEXCEPTION);
  ASSERT_NO_JNI_EXCEPTION(jeEnv);
  // get the constructor which takes a message and an errorID
  jmethodID jmExcConstructor = jeEnv->GetMethodID(clazz, "<init>", "(Ljava/lang/String;J)V");
  ASSERT_NO_JNI_EXCEPTION(jeEnv);
  assertWithMsg( sizeof(jchar) == sizeof(UChar), "Port required");
  assertWithMsg( sizeof(uima::TyErrorId) <= sizeof(jlong), "Port required");
  jstring jsErrorMessage = jeEnv->NewString( (const jchar*) errorMessage.getBuffer(), errorMessage.length());
  jthrowable jtIkfInternalException = (jthrowable) jeEnv->NewObject(clazz, jmExcConstructor, jsErrorMessage, (jlong) errorId);
  jeEnv->Throw(jtIkfInternalException);
}


void JNIUtils::throwNewInternalException(JNIEnv* jeEnv, uima::Exception & rException) {
  string sExc = rException.asString();
  icu::UnicodeString usExc(sExc.c_str(), sExc.length());
  throwNewInternalException(jeEnv, usExc, rException.getErrorInfo().getErrorId());
}

void JNIUtils::throwNewInternalException(JNIEnv* jeEnv, uima::ErrorInfo const & errInfo) {
  string sExc = errInfo.asString();
  icu::UnicodeString usExc(sExc.c_str(), sExc.length());
  throwNewInternalException(jeEnv, usExc, errInfo.getErrorId());
}


void JNIUtils::setCppInstance(JNIEnv* jeEnv,
                              jobject joJTaf,
                              uima::JNIInstance* pInstance) {
  jclass clazz = jeEnv->GetObjectClass(joJTaf);
  ASSERT_NO_JNI_EXCEPTION(jeEnv);
  // get the field of clazz named "cppEnginePointer" which is a long
  jfieldID fid = jeEnv->GetFieldID(clazz, JUIMA_FIELD_CPPENGINEPOINTER, "J");
  ASSERT_NO_JNI_EXCEPTION(jeEnv);
  assertWithMsg( sizeof(void*) <= sizeof(jlong), "Port required");
  jeEnv->SetLongField(joJTaf, fid, (jlong) pInstance);
  ASSERT_NO_JNI_EXCEPTION(jeEnv);
}

uima::JNIInstance* JNIUtils::getCppInstance(JNIEnv* jeEnv,
                                      jobject joJTaf) {
  jclass clazz = jeEnv->GetObjectClass(joJTaf);
  ASSERT_NO_JNI_EXCEPTION(jeEnv);
  jfieldID fid = jeEnv->GetFieldID(clazz, JUIMA_FIELD_CPPENGINEPOINTER, "J");
  ASSERT_NO_JNI_EXCEPTION(jeEnv);
  jlong jlPointer = jeEnv->GetLongField(joJTaf, fid);
  ASSERT_NO_JNI_EXCEPTION(jeEnv);
  assertWithMsg( sizeof(void*) <= sizeof(jlong), "Port required");
  return(uima::JNIInstance*) jlPointer;
}


jobjectArray JNIUtils::createStringArray(JNIEnv* jeEnv, vector<uima::UnicodeStringRef> const & crVec) {
  jobjectArray joArr = NULL;
  size_t uiLen = crVec.size();
  ASSERT_NO_JNI_EXCEPTION(jeEnv);
  jclass jcStringClass = jeEnv->FindClass("java/lang/String");
  assert( jcStringClass != NULL );
  ASSERT_NO_JNI_EXCEPTION(jeEnv);
  joArr = jeEnv->NewObjectArray( uiLen, jcStringClass, NULL );
  ASSERT_NO_JNI_EXCEPTION(jeEnv);

  size_t i;
  for (i=0; i<uiLen; ++i) {
    UIMA_TPRINT("Copying string " << i);
    JavaString str(jeEnv, crVec[i]);
    UIMA_TPRINT("Entering string " << i << " into array");
    jeEnv->SetObjectArrayElement(joArr, (jsize) i, str.getJObject());
    ASSERT_NO_JNI_EXCEPTION(jeEnv);
  }
  return joArr;
}

jintArray JNIUtils::createIntArray(JNIEnv* jeEnv, vector<uima::internal::SerializedCAS::TyNum> const & crVec) {
  jintArray jiArr = NULL;
  assert( sizeof(uima::internal::SerializedCAS::TyNum) == sizeof(jint) );

  size_t uiLength = crVec.size();
//   assert( uiLength > 0);
  jiArr = jeEnv->NewIntArray(uiLength);
  ASSERT_NO_JNI_EXCEPTION(jeEnv);

#ifdef TEMP_DISABLED
  // call to SetIntArrayRegion() assumes that vector iterators
  //   are implemented as pointers
  // check at least that they have equal size by the following assert
  assertWithMsg( sizeof(vector<uima::internal::CASSerializer::TyNum>::iterator) == sizeof(void*), "Port required!");
  jeEnv->SetIntArrayRegion(jiArr, 0, uiLength, (jint*) crVec.begin());
  ASSERT_NO_JNI_EXCEPTION(jeEnv);
#endif

  if (uiLength > 0) {
    // since the above code does not work for msc7,
    // allocate a new array and copy it by hand
    jint * pJIntArray = new jint[uiLength];
    size_t i=0;
    vector<uima::internal::SerializedCAS::TyNum>::const_iterator cit;
    for (cit = crVec.begin(); cit != crVec.end(); ++cit) {
      pJIntArray[i++] = (jint) *cit;
    }
    assert( i == uiLength );

    jeEnv->SetIntArrayRegion(jiArr, 0, uiLength, pJIntArray);
    ASSERT_NO_JNI_EXCEPTION(jeEnv);
    delete pJIntArray;
  }

  return jiArr;
}


void JNIUtils::createIntVector(JNIEnv* jeEnv, jintArray array, vector<uima::internal::SerializedCAS::TyNum> & rResult) {
  size_t uiLen = jeEnv->GetArrayLength(array);
  rResult.resize(uiLen);

  jeEnv->PushLocalFrame( uiLen );
  jboolean jbCopy;
  jint * pArray = jeEnv->GetIntArrayElements(array, & jbCopy);
  size_t i;
  for (i=0; i<uiLen; ++i) {
    rResult[i] = pArray[i];
  }
  jeEnv->ReleaseIntArrayElements(array, pArray, JNI_ABORT);
  jeEnv->PopLocalFrame(NULL);
}


void JNIUtils::createStringVector(JNIEnv* jeEnv, jobjectArray joArray, vector<uima::UnicodeStringRef> & rResult, vector<icu::UnicodeString> & rStringPool) {
  size_t uiLen = jeEnv->GetArrayLength(joArray);
  rResult.resize(uiLen);
  rStringPool.resize(uiLen);
  jeEnv->PushLocalFrame( uiLen );
//   cout << __FILE__ << __LINE__ << ": len: " << uiLen << endl;
  size_t i;
  for (i=0; i<uiLen; ++i) {
    jobject jo = jeEnv->GetObjectArrayElement(joArray, i);

    if (jo != 0) {
      jstring js = (jstring) jo;
      JNIUString uString(jeEnv, js);
      uima::UnicodeStringRef ref = uString.toUStrPtrLenPair();
//         cout << __FILE__ << __LINE__ << ":" << i << "  string " << uString.toUStrPtrLenPair() << endl;
      rStringPool[i] = icu::UnicodeString( ref.getBuffer(), ref.length() );
      rResult[i] = uima::UnicodeStringRef(rStringPool[i]);
    } else {
      rResult[i] = uima::UnicodeStringRef();
    }
  }
   jeEnv->PopLocalFrame(NULL);
}

jbyteArray JNIUtils::createByteArray(JNIEnv* jeEnv, vector<char> const & crVec) {
  jbyteArray jiArr = NULL;

  size_t uiLength = crVec.size();
//   assert( uiLength > 0);
  jiArr = jeEnv->NewByteArray(uiLength);
  ASSERT_NO_JNI_EXCEPTION(jeEnv);

#ifdef TEMP_DISABLED
  // call to SetIntArrayRegion() assumes that vector iterators
  //   are implemented as pointers
  // check at least that they have equal size by the following assert
  //assertWithMsg( sizeof(vector<uima::internal::CASSerializer::TyNum>::iterator) == sizeof(void*), "Port required!");
  jeEnv->SetByteArrayRegion(jiArr, 0, uiLength, (jbyte*) crVec.begin());
  ASSERT_NO_JNI_EXCEPTION(jeEnv);
#endif

  if (uiLength > 0) {
    // since the above code does not work for msc7,
    // allocate a new array and copy it by hand
    jbyte * pJByteArray = new jbyte[uiLength];
    size_t i=0;
    vector<char>::const_iterator cit;
    for (cit = crVec.begin(); cit != crVec.end(); ++cit) {
      pJByteArray[i++] = (jbyte) *cit;
    }
    assert( i == uiLength );

    jeEnv->SetByteArrayRegion(jiArr, 0, uiLength, pJByteArray);
    ASSERT_NO_JNI_EXCEPTION(jeEnv);
    delete pJByteArray;
  }

  return jiArr;
}

jshortArray JNIUtils::createShortArray(JNIEnv* jeEnv, vector<short> const & crVec) {
  jshortArray jiArr = NULL;

  size_t uiLength = crVec.size();
//   assert( uiLength > 0);
  jiArr = jeEnv->NewShortArray(uiLength);
  ASSERT_NO_JNI_EXCEPTION(jeEnv);

#ifdef TEMP_DISABLED
  // call to SetIntArrayRegion() assumes that vector iterators
  //   are implemented as pointers
  // check at least that they have equal size by the following assert
  //assertWithMsg( sizeof(vector<uima::internal::CASSerializer::TyNum>::iterator) == sizeof(void*), "Port required!");
  jeEnv->SetShortArrayRegion(jiArr, 0, uiLength, (jshort*) crVec.begin());
  ASSERT_NO_JNI_EXCEPTION(jeEnv);
#endif

  if (uiLength > 0) {
    // since the above code does not work for msc7,
    // allocate a new array and copy it by hand
    jshort * pJShortArray = new jshort[uiLength];
    size_t i=0;
    vector<short>::const_iterator cit;
    for (cit = crVec.begin(); cit != crVec.end(); ++cit) {
      pJShortArray[i++] = (jshort) *cit;
    }
    assert( i == uiLength );

    jeEnv->SetShortArrayRegion(jiArr, 0, uiLength, pJShortArray);
    ASSERT_NO_JNI_EXCEPTION(jeEnv);
    delete pJShortArray;
  }

  return jiArr;
}


jlongArray JNIUtils::createLongArray(JNIEnv* jeEnv, vector<INT64> const & crVec) {
  jlongArray jiArr = NULL;

  size_t uiLength = crVec.size();
//   assert( uiLength > 0);
  jiArr = jeEnv->NewLongArray(uiLength);
  ASSERT_NO_JNI_EXCEPTION(jeEnv);

#ifdef TEMP_DISABLED
  // call to SetIntArrayRegion() assumes that vector iterators
  //   are implemented as pointers
  // check at least that they have equal size by the following assert
  //assertWithMsg( sizeof(vector<uima::internal::CASSerializer::TyNum>::iterator) == sizeof(void*), "Port required!");
  jeEnv->SetLongArrayRegion(jiArr, 0, uiLength, (jlong*) crVec.begin());
  ASSERT_NO_JNI_EXCEPTION(jeEnv);
#endif

  if (uiLength > 0) {
    // since the above code does not work for msc7,
    // allocate a new array and copy it by hand
    jlong * pJLongArray = new jlong[uiLength];
    size_t i=0;
    vector<INT64>::const_iterator cit;
    for (cit = crVec.begin(); cit != crVec.end(); ++cit) {
      pJLongArray[i++] = (jlong) *cit;
    }
    assert( i == uiLength );

    jeEnv->SetLongArrayRegion(jiArr, 0, uiLength, pJLongArray);
    ASSERT_NO_JNI_EXCEPTION(jeEnv);
    delete pJLongArray;
  }

  return jiArr;
}

void JNIUtils::createByteVector(JNIEnv* jeEnv, jbyteArray array, vector<char> & rResult) {
  size_t uiLen = jeEnv->GetArrayLength(array);
  rResult.resize(uiLen);
  jeEnv->PushLocalFrame( uiLen );
  jboolean jbCopy;
  jbyte * pArray = jeEnv->GetByteArrayElements(array, & jbCopy);
  size_t i;
  for (i=0; i<uiLen; ++i) {
    rResult[i] = pArray[i];
  }
  jeEnv->ReleaseByteArrayElements(array,pArray, JNI_ABORT);
  jeEnv->PopLocalFrame(NULL);
}

void JNIUtils::createShortVector(JNIEnv* jeEnv, jshortArray array, vector<short> & rResult) {
  size_t uiLen = jeEnv->GetArrayLength(array);
  rResult.resize(uiLen);
  jeEnv->PushLocalFrame( uiLen );
  jboolean jbCopy;
  jshort * pArray = jeEnv->GetShortArrayElements(array, & jbCopy);
  size_t i;
  for (i=0; i<uiLen; ++i) {
    rResult[i] = pArray[i];
  }
  jeEnv->ReleaseShortArrayElements(array,pArray, JNI_ABORT);
  jeEnv->PopLocalFrame(NULL);
}

void JNIUtils::createLongVector(JNIEnv* jeEnv, jlongArray array, vector<INT64> & rResult) {
  size_t uiLen = jeEnv->GetArrayLength(array);
  rResult.resize(uiLen);
  jeEnv->PushLocalFrame( uiLen );
  jboolean jbCopy;
  jlong * pArray = jeEnv->GetLongArrayElements(array, & jbCopy);
  size_t i;
  for (i=0; i<uiLen; ++i) {
    rResult[i] = pArray[i];
  }
  jeEnv->ReleaseLongArrayElements(array,pArray, JNI_ABORT);
  jeEnv->PopLocalFrame(NULL);
}



/* ----------------------------------------------------------------------- */
/*@}*/                                                /* e-o-Doc++ Group */

/* <EOF> */

