
Module: ppl/ppl Branch: master Commit: af3298eea9b68aaaada91f7d6af72d8d6520c215 URL: http://www.cs.unipr.it/git/gitweb.cgi?p=ppl/ppl.git;a=commit;h=af3298eea9b68...
Author: Enea Zaffanella zaffanella@cs.unipr.it Date: Tue Aug 7 19:06:57 2012 +0200
Added native methods toString() and setStringifier() to class Variable. Implemented variable output function using the customizable stringifier.
---
interfaces/Java/jni/ppl_java_common.cc | 44 ++++++++++++++++++++ interfaces/Java/jni/ppl_java_common.defs.hh | 16 +++++++ interfaces/Java/jni/ppl_java_globals.cc | 42 +++++++++++++++++++ .../Java/parma_polyhedra_library/Makefile.am | 1 + .../Java/parma_polyhedra_library/Variable.java | 25 +++++++++-- 5 files changed, 123 insertions(+), 5 deletions(-)
diff --git a/interfaces/Java/jni/ppl_java_common.cc b/interfaces/Java/jni/ppl_java_common.cc index b3447c3..d97c53c 100644 --- a/interfaces/Java/jni/ppl_java_common.cc +++ b/interfaces/Java/jni/ppl_java_common.cc @@ -34,6 +34,8 @@ Java_Class_Cache cached_classes; Java_FMID_Cache cached_FMIDs;
Java_Class_Cache::Java_Class_Cache() { + // Java Virtual Machine pointer. + jvm = NULL; // Non-PPL classes. Boolean = NULL; Integer = NULL; @@ -75,6 +77,7 @@ Java_Class_Cache::Java_Class_Cache() { PPL_Object = NULL; Relation_Symbol = NULL; Variable = NULL; + Variable_Stringifier = NULL; Variables_Set = NULL; }
@@ -93,6 +96,8 @@ Java_Class_Cache::init_cache(JNIEnv* env, jclass& field, const char* name) { void Java_Class_Cache::init_cache(JNIEnv* env) { assert(env != NULL); + // Java Virtual Machine pointer. + env->GetJavaVM(&jvm); // Non-PPL classes. init_cache(env, Boolean, "java/lang/Boolean"); init_cache(env, Integer, "java/lang/Integer"); @@ -155,6 +160,8 @@ Java_Class_Cache::init_cache(JNIEnv* env) { init_cache(env, PPL_Object, "parma_polyhedra_library/PPL_Object"); init_cache(env, Relation_Symbol, "parma_polyhedra_library/Relation_Symbol"); init_cache(env, Variable, "parma_polyhedra_library/Variable"); + // NOTE: initialization of concrete Variable_Stringifier is responsibility + // of static (native) method Variable.setStringifier. init_cache(env, Variables_Set, "parma_polyhedra_library/Variables_Set"); }
@@ -170,6 +177,8 @@ Java_Class_Cache::clear_cache(JNIEnv* env, jclass& field) { void Java_Class_Cache::clear_cache(JNIEnv* env) { assert(env != NULL); + // Clearing the JVM pointer. + jvm = NULL; // Non-PPL classes. clear_cache(env, Boolean); clear_cache(env, Integer); @@ -209,6 +218,7 @@ Java_Class_Cache::clear_cache(JNIEnv* env) { clear_cache(env, PPL_Object); clear_cache(env, Relation_Symbol); clear_cache(env, Variable); + clear_cache(env, Variable_Stringifier); clear_cache(env, Variables_Set); }
@@ -1195,6 +1205,40 @@ build_java_artificial_parameter return ret; }
+void +Java_Variable_output_function(std::ostream& s, Variable v) { + // Use cached Java Virtual Machine pointer to retrieve JNI env. + JavaVM* jvm = cached_classes.jvm; + JNIEnv *env = 0; + jvm->AttachCurrentThread((void **)&env, NULL); + CHECK_EXCEPTION_ASSERT(env); + // Retrieve stringifier object. + jclass var_class = cached_classes.Variable; + jfieldID fID = cached_FMIDs.Variable_stringifier_ID; + jobject stringifier = env->GetStaticObjectField(var_class, fID); + CHECK_RESULT_THROW(env, stringifier); + // Use it to get the Java string for the variable. + jmethodID mID = cached_FMIDs.Variable_Stringifier_stringify_ID; +#ifndef NDEBUG + { + // Dynamically retrieve stringifier class and use it to compute + // the corresponding method ID, so as to compare it with cached one. + jclass dyn_class = env->GetObjectClass(stringifier); + jmethodID dyn_mID = env->GetMethodID(dyn_class, "stringify", + "(I)Ljava/lang/String;"); + CHECK_RESULT_ASSERT(env, mID == dyn_mID); + } +#endif // #ifndef NDEBUG + jstring bi_string + = (jstring) env->CallObjectMethod(stringifier, mID, v.id()); + CHECK_EXCEPTION_THROW(env); + // Convert the string and print it on C++ stream. + const char* nativeString = env->GetStringUTFChars(bi_string, 0); + CHECK_RESULT_THROW(env, nativeString); + s << nativeString; + env->ReleaseStringUTFChars(bi_string, nativeString); +} + } // namespace Java
} // namespace Interfaces diff --git a/interfaces/Java/jni/ppl_java_common.defs.hh b/interfaces/Java/jni/ppl_java_common.defs.hh index 990d4f8..805c5e5 100644 --- a/interfaces/Java/jni/ppl_java_common.defs.hh +++ b/interfaces/Java/jni/ppl_java_common.defs.hh @@ -189,6 +189,8 @@ handle_exception(JNIEnv* env); */ class Java_Class_Cache { public: + // The Java VM pointer (not a class, but sometimes needed). + JavaVM* jvm; // Non-PPL types. jclass Boolean; jclass Integer; @@ -230,6 +232,7 @@ public: jclass PPL_Object; jclass Relation_Symbol; jclass Variable; + jclass Variable_Stringifier; jclass Variables_Set;
//! Default constructor. @@ -400,7 +403,10 @@ struct Java_FMID_Cache { jmethodID Relation_Symbol_ordinal_ID; // Variable. jfieldID Variable_varid_ID; + jfieldID Variable_stringifier_ID; jmethodID Variable_init_ID; + // Variable_Stringifier. + jmethodID Variable_Stringifier_stringify_ID; // Variables_Set. jmethodID Variables_Set_init_ID; jmethodID Variables_Set_add_ID; @@ -622,6 +628,16 @@ jobject build_java_variable(JNIEnv* env, const Variable var);
/*! \brief + The customizable variable output function for Java interface. + + Customization is obtained by providing an object implementing interface + <CODE>Variable_Stringifier</CODE> and attaching it to class + <CODE>Variable</CODE> using static method <CODE>setStringifier</CODE>. +*/ +void +Java_Variable_output_function(std::ostream& s, Variable v); + +/*! \brief Builds a C++ Coefficient from Java parma_polyhedra_library::Coefficient \p j_coeff. */ diff --git a/interfaces/Java/jni/ppl_java_globals.cc b/interfaces/Java/jni/ppl_java_globals.cc index 47b679a..a071be4 100644 --- a/interfaces/Java/jni/ppl_java_globals.cc +++ b/interfaces/Java/jni/ppl_java_globals.cc @@ -678,6 +678,10 @@ Java_parma_1polyhedra_1library_Variable_initIDs jfieldID fID = env->GetFieldID(j_variable_class, "varid", "I"); CHECK_RESULT_ASSERT(env, fID); cached_FMIDs.Variable_varid_ID = fID; + fID = env->GetStaticFieldID(j_variable_class, "stringifier", + "Lparma_polyhedra_library/Variable_Stringifier;"); + CHECK_RESULT_ASSERT(env, fID); + cached_FMIDs.Variable_stringifier_ID = fID; jmethodID mID = env->GetMethodID(j_variable_class, "<init>", "(I)V"); CHECK_RESULT_ASSERT(env, mID); cached_FMIDs.Variable_init_ID = mID; @@ -1252,6 +1256,44 @@ Java_parma_1polyhedra_1library_MIP_1Problem_ascii_1dump }
JNIEXPORT jstring JNICALL +Java_parma_1polyhedra_1library_Variable_toString +(JNIEnv* env, jobject j_this) { + using namespace Parma_Polyhedra_Library::IO_Operators; + Variable ppl_var = build_cxx_variable(env, j_this); + std::ostringstream s; + s << ppl_var; + return env->NewStringUTF(s.str().c_str()); +} + +JNIEXPORT void JNICALL +Java_parma_1polyhedra_1library_Variable_setStringifier +(JNIEnv* env, jclass j_variable_class, jobject j_stringifier) { + // Store j_stringifier in the corresponding static field. + env->SetStaticObjectField(j_variable_class, + cached_FMIDs.Variable_stringifier_ID, + j_stringifier); + if (j_stringifier == NULL) { + // No stringifier object: reset cache values. + cached_classes.Variable_Stringifier = NULL; + cached_FMIDs.Variable_Stringifier_stringify_ID = NULL; + // Reset default C++ output function. + Variable::set_output_function(&Variable::default_output_function); + } + else { + // Update cache with values computed for concrete class. + jclass vs_class = env->GetObjectClass(j_stringifier); + CHECK_RESULT_ASSERT(env, vs_class); + cached_classes.Variable_Stringifier = vs_class; + jmethodID mID = env->GetMethodID(vs_class, "stringify", + "(I)Ljava/lang/String;"); + CHECK_RESULT_ASSERT(env, mID); + cached_FMIDs.Variable_Stringifier_stringify_ID = mID; + // Set C++ output function to the Java wrapper. + Variable::set_output_function(&Java_Variable_output_function); + } +} + +JNIEXPORT jstring JNICALL Java_parma_1polyhedra_1library_Linear_1Expression_toString (JNIEnv* env, jobject j_this) { using namespace Parma_Polyhedra_Library::IO_Operators; diff --git a/interfaces/Java/parma_polyhedra_library/Makefile.am b/interfaces/Java/parma_polyhedra_library/Makefile.am index 7031ed5..1f848cf 100644 --- a/interfaces/Java/parma_polyhedra_library/Makefile.am +++ b/interfaces/Java/parma_polyhedra_library/Makefile.am @@ -186,6 +186,7 @@ $(srcdir)/PPL_Object.java \ $(srcdir)/Relation_Symbol.java \ $(srcdir)/Timeout_Exception.java \ $(srcdir)/Variable.java \ +$(srcdir)/Variable_Stringifier.java \ $(srcdir)/Variables_Set.java
# NOTE: do _NOT_ add Fake_Class_for_Doxygen.java to this list. diff --git a/interfaces/Java/parma_polyhedra_library/Variable.java b/interfaces/Java/parma_polyhedra_library/Variable.java index 7d1d66f..ea13aa0 100644 --- a/interfaces/Java/parma_polyhedra_library/Variable.java +++ b/interfaces/Java/parma_polyhedra_library/Variable.java @@ -59,15 +59,30 @@ public class Variable implements Comparable<Variable> { return varid; }
- /*! \brief - Returns a negative number if \p this comes first than \p v, - a zero if \p this equals \p v, a positive number if - if \p this comes first than \p v. - */ + /*! \brief + Returns a negative number if \p this is smaller than \p v, + a zero if \p this equals \p v, a positive number if \p v + is greater than \p v. + */ public int compareTo(Variable v) { return varid - v.varid; }
+ //! Optional customization provider for \c toString. + private static Variable_Stringifier stringifier; + + /*! \brief + Sets the variable stringifier object. + + A variable stringifier object provides customization for the + \c toString method; if no variable stringifier object is set + (or if it is set to a null refeerence value), the PPL default + variable output function will be used. + */ + public static native void setStringifier(Variable_Stringifier vs); + + public native String toString(); + private static native void initIDs(); static { initIDs();