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

