/** @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                                                    */
/* ----------------------------------------------------------------------- */

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] = 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> */

