# HG changeset patch
# User Ernst Reissner <rei3ner@arcor.de>
# Date 1471626096 -7200
#      Fri Aug 19 19:01:36 2016 +0200
# Node ID 2164b6e1cc1a615212ec7aba680b96e81f026900
# Parent  bf99617e2b1880cbfb374296689fc5431a422542
bugfix #48591: double(.) and int64(.) on octave_java

- ov-java.h: added methods as_double and as_int64
- ov-java.cc: implemented those wrapping ClassHelper.asDouble(.) and ClassHelper.asLong(.)
- ClassHelper.java: implemented asDouble(.) and asLong(.)

diff -r bf99617e2b18 -r 2164b6e1cc1a libinterp/octave-value/ov-java.cc
--- a/libinterp/octave-value/ov-java.cc	Fri Aug 19 12:40:55 2016 +0200
+++ b/libinterp/octave-value/ov-java.cc	Fri Aug 19 19:01:36 2016 +0200
@@ -2818,6 +2818,90 @@
 #endif
 }
 
+octave_value
+octave_java::as_double (void) const
+{
+#if defined (HAVE_JAVA)
+
+  octave_value retval;
+
+  JNIEnv *jni_env = thread_jni_env ();
+
+  if (jni_env)
+    {
+      jclass_ref helperClass (jni_env, 
+                              find_octave_class (jni_env, 
+                                                 "org/octave/ClassHelper"));
+      jmethodID mID = jni_env->GetStaticMethodID 
+        (helperClass, "asDouble", "(Ljava/lang/Object;)Ljava/lang/Double;");
+      jobject_ref resObj (jni_env, jni_env->CallStaticObjectMethod 
+                          (helperClass, mID, to_java ()));
+
+      if (resObj)
+        retval = java2octType (jni_env, resObj);
+      else
+        retval = check_exception (jni_env);
+
+      octave_set_default_fpucw ();
+    }
+
+  return retval;
+
+#else
+
+  octave_unused_parameter (jni_env_arg);
+  octave_unused_parameter (name);
+
+  // This shouldn't happen because construction of octave_java
+  // objects is supposed to be impossible if Java is not available.
+
+  panic_impossible ();
+
+#endif
+}
+octave_value
+octave_java::as_int64 (void) const
+{
+#if defined (HAVE_JAVA)
+
+  octave_value retval;
+
+  JNIEnv *jni_env = thread_jni_env ();
+
+  if (jni_env)
+    {
+      jclass_ref helperClass (jni_env, 
+                              find_octave_class (jni_env, 
+                                                 "org/octave/ClassHelper"));
+      jmethodID mID = jni_env->GetStaticMethodID 
+        (helperClass, "asLong", "(Ljava/lang/Object;)Ljava/lang/Long;");
+      jobject_ref resObj (jni_env, jni_env->CallStaticObjectMethod 
+                          (helperClass, mID, to_java ()));
+
+      if (resObj)
+        retval = java2octType (jni_env, resObj);
+      else
+        retval = check_exception (jni_env);
+
+      octave_set_default_fpucw ();
+    }
+
+  return retval;
+
+#else
+
+  octave_unused_parameter (jni_env_arg);
+  octave_unused_parameter (name);
+
+  // This shouldn't happen because construction of octave_java
+  // objects is supposed to be impossible if Java is not available.
+
+  panic_impossible ();
+
+#endif
+}
+
+
 void
 octave_java::init (void *jobj_arg, void *jcls_arg)
 {
diff -r bf99617e2b18 -r 2164b6e1cc1a libinterp/octave-value/ov-java.h
--- a/libinterp/octave-value/ov-java.h	Fri Aug 19 12:40:55 2016 +0200
+++ b/libinterp/octave-value/ov-java.h	Fri Aug 19 19:01:36 2016 +0200
@@ -150,6 +150,12 @@
   do_java_set (const std::string& class_name, const std::string& name,
                const octave_value& val);
 
+  octave_value
+  as_double (void) const;
+
+  octave_value
+  as_int64 (void) const;
+
 private:
 
   void init (void *jobj, void *jcls);
diff -r bf99617e2b18 -r 2164b6e1cc1a scripts/java/org/octave/ClassHelper.java
--- a/scripts/java/org/octave/ClassHelper.java	Fri Aug 19 12:40:55 2016 +0200
+++ b/scripts/java/org/octave/ClassHelper.java	Fri Aug 19 19:01:36 2016 +0200
@@ -1709,4 +1709,97 @@
   {
     return createArray (cls, new int[] {length});
   }
-}
+
+  //! Return @c obj as a @c Double if possible: 
+  //! If @c obj implements java.lang.Number,
+  //! convert using java.lang.Number::doubleValue().
+  //! Otherwise, if a method <code>public double toDouble()<code>
+  //! or <code>public Double toDouble()<code> exists, use this one 
+  //! (even if static).
+  //!
+  //! @param obj
+  //!    the instance to be converted into a @c Double. 
+  //! @return
+  //!    this object as a @c Double if possible. 
+  //! @throws NumberFormatException
+  //!    if no conversion method was found.
+  //! @throws Throwable
+  //!    if the conversion method @c toDouble() throws an exception. 
+  public static Double asDouble(Object obj)
+    throws IllegalAccessException, Throwable
+  {
+    if (obj instanceof Number)
+      {
+        return Double.valueOf(((Number)obj).doubleValue());
+      }
+    try
+      {
+        // may throw NoSuchMethodException
+        Method toDouble = findMethod (obj.getClass(), "toDouble", false, 
+                                      new Class[0]);
+        if (toDouble.getReturnType() == Double.class ||
+            toDouble.getReturnType() == Double.TYPE)
+          {
+            // may throw InvocationTargetException, 
+            // impossible IllegalAccessException
+            return (Double)invokeMethod (toDouble, obj, new Object[0]);
+          }
+      }
+    catch (NoSuchMethodException e)// NOPMD: rulecheck suspended
+      {
+        // fall through
+      }
+    catch (InvocationTargetException e)
+      {
+        throw e.getCause();
+
+      }
+    throw new NumberFormatException("Object cannot be converted to a double.");
+  }
+
+  //! Return @c obj as a @c Long if possible: 
+  //! If @c obj implements java.lang.Number,
+  //! convert using java.lang.Number::longValue().
+  //! Otherwise, if a method <code>public long toLong()<code>
+  //! or <code>public Long toLong()<code> exists, use this one 
+  //! (even if static).
+  //!
+  //! @param obj
+  //!    the instance to be converted into a @c Long. 
+  //! @return
+  //!    this object as a @c Long if possible. 
+  //! @throws NumberFormatException
+  //!    if no conversion method was found.
+  //! @throws Throwable
+  //!    if the conversion method @c toLong() throws an exception. 
+  public static Long asLong(Object obj)
+    throws IllegalAccessException, Throwable
+  {
+    if (obj instanceof Number)
+      {
+        return Long.valueOf(((Number)obj).longValue());
+      }
+    try
+      {
+        // may throw NoSuchMethodException
+        Method toLong = findMethod (obj.getClass(), "toLong", false, 
+                                      new Class[0]);
+        if (toLong.getReturnType() == Long.class ||
+            toLong.getReturnType() == Long.TYPE)
+          {
+            // may throw InvocationTargetException, 
+            // impossible IllegalAccessException
+            return (Long)invokeMethod (toLong, obj, new Object[0]);
+          }
+      }
+    catch (NoSuchMethodException e)// NOPMD: rulecheck suspended
+      {
+        // fall through
+      }
+    catch (InvocationTargetException e)
+      {
+        throw e.getCause();
+
+      }
+    throw new NumberFormatException("Object cannot be converted to a long.");
+  }}
