# HG changeset patch
# User Ernst Reissner <rei3ner@arcor.de>
# Date 1471382587 -7200
#      Tue Aug 16 23:23:07 2016 +0200
# Node ID ff3226e37d0f8628226c31baf58f9e4e274873f6
# Parent  40632d3936d8bb9c9fc120ffa95e5d7fd8614642
simplifications in conjunction with method isCallableFrom
and added doxygen comments.

diff -r 40632d3936d8 -r ff3226e37d0f scripts/java/org/octave/ClassHelper.java
--- a/scripts/java/org/octave/ClassHelper.java	Tue Aug 16 12:53:43 2016 +0200
+++ b/scripts/java/org/octave/ClassHelper.java	Tue Aug 16 23:23:07 2016 +0200
@@ -645,7 +645,6 @@
         meth = mList[i];
         if (meth.getName ().equals (name)
             && (!staticOnly || Modifier.isStatic(meth.getModifiers()))
-            && meth.getParameterTypes ().length == argTypes.length
             && isCallableFrom (meth, argTypes))
           {
             // FIXME: returns with the first possibility instead of optimizing
@@ -684,14 +683,13 @@
     catch (NoSuchMethodException e)
       {
         Constructor[] cList = cls.getConstructors ();
-        Constructor c;
+        Constructor constr;
         for (int i = 0; i < cList.length; i++)
           {
-            c = cList[i];
-            if (c.getParameterTypes ().length == argTypes.length
-                && isCallableFrom (c, argTypes))
+            constr = cList[i];
+            if (isCallableFrom (constr, argTypes))
               {
-                return c;
+                return constr;
               }
           }
         throw e;
@@ -701,7 +699,7 @@
   //! Invoke method @c mthd on the object @c target with arguments @c args.
   //!
   //! @param mthd
-  //!    the method to be invoked.
+  //!    the public method to be invoked.
   //! @param target
   //!    the object @c mthd may be invoked on.
   //!    For static methods this may be @c null.
@@ -730,7 +728,7 @@
     try
       {
         // may throw InvocationTargetException,
-        // but no IllegalAccessException
+        // but no IllegalAccessException because mthd is public
         return mthd.invoke (target, args);
       }
     catch (IllegalAccessException ex)
@@ -799,8 +797,19 @@
   //!    the name of the method to be applied 
   //! @param args
   //!    the arguments of the method call. 
-  //! @param 
-  //!    the types of arguments of the methods to be applied
+  //! @param argTypes
+  //!    the types of arguments @c args of the method to be applied.
+  //!    The rules come from 
+  //!    #unbox(JNIEnv*, octave_value&, jobject_ref&, jclass_ref&) 
+  //!    defined in @file{ov-java.cc}: 
+  //!    In general, 
+  //!    <code>argTypes[i]</code> is just <code>args[i].getClass()</code>
+  //!    but there are several exceptions:
+  //!    @arg if <code>args[i]</code> is <code>null</code>
+  //!         so is <code>argTypes[i]</code>.
+  //!    @arg if <code>args[i]</code> has wrapper type 
+  //!         of primitive boolean or number type
+  //!         then <code>argTypes[i]</code> is the according primitive type.
   //! @return
   //!    the return value of the method call, 
   //!    if no exception or error is thrown. 
@@ -832,8 +841,7 @@
       }
   }
 
-  //! Apply static method named @c name of class @c cls
-  //! loaded by #loader 
+  //! Apply static method named @c name of class @c cls loaded by #loader 
   //! with arguments @c args of types @c argTypes. 
   //!
   //! Used internally and by
@@ -848,6 +856,8 @@
   //!    the arguments of the method call. 
   //! @param 
   //!    the types of arguments of the method to be applied.
+  //!    For more details
+  //!    see ::invokeMethod (Object, String, Object[], Class[]).
   //! @return
   //!    the return value of the method call, 
   //!    if no exception or error is thrown. 
@@ -901,8 +911,10 @@
   //!    the class of the constructor to be invoked.
   //! @param args
   //!    the arguments of the constructor call. 
-  //! @param 
+  //! @param argTypes
   //!    the types of arguments of the constructor to be applied.
+  //!    For more details
+  //!    see ::invokeMethod (Object, String, Object[], Class[]).
   //! @throws ClassNotFoundException
   //!    if #loader could not find the class @c cls.
   //! @throw NoSuchMethodException
@@ -938,14 +950,19 @@
   }
 
   //! Return the value of the field with name @c name
-  //! of object @c target.
-  //! Used by @file ov-java.cc only.
+  //! of object @c target. 
+  //! The field may be either static or a member field. 
+  //!
+  //! Used by octave_java::do_java_get (void*, std::string&) 
+  //! defined in @file ov-java.cc only.
   //!
   //! @param target
-  //!    an object to query a field which shall not be @c null.
+  //!    an object with field @c name which shall not be @c null.
   //! @param name
   //!    the name of the field of @c target
   //!    which shall not be @c null.
+  //! @return
+  //!    the value of the specified field.
   //! @throws NoSuchFieldException
   //!    if @c target has no field with the given name.
   //! @throws IllegalAccessException
@@ -974,8 +991,25 @@
       }
   }
 
-  // based on loader
-  // Used by @file ov-java.cc only.
+  //! Return the value of the static field
+  //! of class given by @c cls loaded by #loader with name @c name.
+  //!
+  //! Used by octave_java::do_java_get (void*, std::string&, std::string&) 
+  //! defined in @file ov-java.cc only.
+  //!
+  //! @param cls
+  //!    the name of the class of the static field @c name.
+  //! @param name
+  //!    the name of the field to be read.
+  //! @return
+  //!    the value of the specified
+  //!    if no exception or error is thrown. 
+  //! @throws ClassNotFoundException
+  //!    if #loader could not find the class @c cls.
+  //! @throws NoSuchFieldException
+  //!    if class @c cls has no field with the given name.
+  //! @throws IllegalAccessException
+  //!    if the field @c name of class @c cls is not accessible.
   public static Object getStaticField (String cls, String name)
     throws ClassNotFoundException, NoSuchFieldException, 
     IllegalAccessException, Throwable
@@ -1001,7 +1035,23 @@
       }
   }
 
-  // Used by @file ov-java.cc only.
+  //! Assign value @c value to the field with name @c name of object @c target. 
+  //! The field may be either static or a member field. 
+  //!
+  //! Used by octave_java::do_java_set (void*, std::string&, octave_value&) 
+  //! defined in @file ov-java.cc only.
+  //!
+  //! @param target
+  //!    an object with field @c name which shall not be @c null.
+  //! @param name
+  //!    the name of the field of @c target
+  //!    which shall not be @c null.
+  //! @param value
+  //!    the value to assign to the given field.
+  //! @throws NoSuchFieldException
+  //!    if @c target has no field with the given name.
+  //! @throws IllegalAccessException
+  //!    if the field @c name of object @c target is not accessible.
   public static void setField (Object target, String name, Object value)
     throws NoSuchFieldException, IllegalAccessException
   {
@@ -1011,8 +1061,26 @@
     f.set (target, castArgument (value, value.getClass (), f.getType ()));
   }
 
-  // based on loader
-  // Used by @file ov-java.cc only.
+  //! Assign value @c value to the static field
+  //! of class @c cls loaded by #loader with name @c name.
+  //!
+  //! Used by 
+  //! octave_java::do_java_set (void*,std::string&,std::string&,octave_value&) 
+  //! defined in @file ov-java.cc only.
+  //!
+  //! @param cls
+  //!    the name of the class of the static field @c name.
+  //! @param name
+  //!    the name of the field to be written.
+  //! @param value
+  //!    the value to assign to the given field.
+  //! @throws ClassNotFoundException
+  //!    if #loader could not find the class @c cls.
+  //! @throws NoSuchFieldException
+  //!    if class @c cls has no field with the given name.
+  //! @throws IllegalAccessException
+  //!    if the field @c name of class @c cls is not accessible.
+
   public static void setStaticField (String cls, String name, Object value)
     throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException
   {
@@ -1023,9 +1091,30 @@
     f.set (null, castArgument (value, value.getClass (), f.getType ()));
   }
 
-  private static boolean isCallableFrom (Method m, Class[] argTypes)
+  //! Return whether @c exe can be called
+  //! with arguments with given types @c argTypes, 
+  //! possibly after a cast 
+  //! given by ::castArguments(Object[], Class[], Class[]).
+  //!
+  //! @param exe
+  //!    some executable 
+  //! @param argTypes
+  //!    a parameter list.
+  //! @return
+  //!    whether @c exe can be called
+  //!    with arguments with given types @c argTypes.
+  //!    This is true if the number of entries fits
+  //!    and each parameter fits according to ::isCallableFrom(Class, Class).
+  // used by findMethod and findConstructor only
+  private static boolean isCallableFrom (Executable exe, Class[] argTypes)
   {
-    Class[] expTypes = m.getParameterTypes ();
+    Class[] expTypes = exe.getParameterTypes ();
+    // CAUTION: This works only until java 1.5 without varargs
+    if (expTypes.length != argTypes.length)
+      {
+        return false;
+      }
+
     for (int i = 0; i < argTypes.length; i++)
       {
         if (!isCallableFrom (expTypes[i], argTypes[i]))
@@ -1036,18 +1125,6 @@
     return true;
   }
 
-  private static boolean isCallableFrom (Constructor c, Class[] argTypes)
-  {
-    Class[] expTypes = c.getParameterTypes ();
-    for (int i = 0; i < argTypes.length; i++)
-      {
-        if (!isCallableFrom (expTypes[i], argTypes[i]))
-          {
-            return false;
-          }
-      }
-    return true;
-  }
 
   private static boolean isCallableFrom (Class expCls, Class argCls)
   {
@@ -1122,6 +1199,23 @@
     return cls.equals (Character.class) || cls.equals (Character.TYPE);
   }
 
+  //! Cast the entries of @c args which have type @c argTypes
+  //! to types @c expTypes componentwise 
+  //! via ::castArgument(Object, Class, Class) and return the result. 
+  //!
+  //! Note that this method is invoked in a context,
+  //! where ::isCallableFrom (Executable, Class[]) ensured,
+  //! that this is possible.
+  //!
+  //! @param args
+  //!    the arguments of an executable, method or constructor.
+  //! @param argTypes
+  //!    
+  //! @param expTypes
+  //!    
+
+  // Used by invokeMethod, invokeStaticMethod, invokeConstructor
+  // @see ::isCallableFrom (Executable, Class[])
   private static Object[] castArguments (Object[] args, Class[] argTypes,
                                          Class[] expTypes)
   {
