[PPL-devel] [GIT] ppl/ppl(master): Added native methods toString() and setStringifier() to class Variable.

Enea Zaffanella zaffanella at cs.unipr.it
Tue Aug 7 19:11:11 CEST 2012


Module: ppl/ppl
Branch: master
Commit: af3298eea9b68aaaada91f7d6af72d8d6520c215
URL:    http://www.cs.unipr.it/git/gitweb.cgi?p=ppl/ppl.git;a=commit;h=af3298eea9b68aaaada91f7d6af72d8d6520c215

Author: Enea Zaffanella <zaffanella at 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();




More information about the PPL-devel mailing list