# HG changeset patch
# User Ernst Reissner <rei3ner@arcor.de>
# Date 1471007519 -7200
#      Fri Aug 12 15:11:59 2016 +0200
# Node ID 29510aa439e3fbef8a8ce60b3334e3b5cd566e3c
# Parent  25476410e25ec2cc2c3fe6fd43207de48b3bc5c3
fixed bugs 48724 and 48740, at least for java objects and classnames,
except for -full the inheritance info is not provided.

diff -r 25476410e25e -r 29510aa439e3 scripts/general/fieldnames.m
--- a/scripts/general/fieldnames.m	Fri Aug 12 02:09:59 2016 +0200
+++ b/scripts/general/fieldnames.m	Fri Aug 12 15:11:59 2016 +0200
@@ -21,35 +21,54 @@
 ## @deftypefnx {} {@var{names} =} fieldnames (@var{obj})
 ## @deftypefnx {} {@var{names} =} fieldnames (@var{javaobj})
 ## @deftypefnx {} {@var{names} =} fieldnames ("@var{javaclassname}")
-## Return a cell array of strings with the names of the fields in the
+## @deftypefnx {} {} methods (@dots{}, @code{'-full'})
+## Return a cell array of strings describing the 'fields' in the
 ## specified input.
 ##
-## When the input is a structure @var{struct}, the names are the elements of
-## the structure.
+## When the input is a structure @var{struct}, the descriptions 
+## are the names are the elements of the structure.
 ##
-## When the input is an Octave object @var{obj}, the names are the public
+## When the input is an Octave object @var{obj}, the 'fields' are the public
 ## properties of the object.
 ##
 ## When the input is a Java object @var{javaobj} or a string containing the
-## name of a Java class @var{javaclassname}, the names are the public fields
+## name of a Java class @var{javaclassname}, the 'fields' are the public fields
 ## (data members) of the object or class.
+##
+## With the argument @code{'-full'},
+## the full declarations are given, except the @code{public} modifier;
+## otherwise only the names.
 ## @seealso{numfields, isfield, orderfields, struct, methods}
 ## @end deftypefn
 
-function names = fieldnames (obj)
+function names = fieldnames (obj, sfull)
 
-  if (nargin != 1)
-    print_usage ();
-  endif
+  switch (nargin)
+    case 1
+      isfull = false;
+    case 2
+      if !isequal(sfull,'-full')
+        print_usage ();
+      endif
+      isfull = true;
+    otherwise
+      print_usage ();
+  endswitch
 
   if (isstruct (obj) || isobject (obj))
     ## Call internal C++ function for structs or Octave objects
     names = __fieldnames__ (obj);
+  elseif (ischar (obj))
+    ## matlab cannot treat this. 
+    ## So we decided that class names always refer to Java classes, 
+    ## never to Octave classes. 
+    ## This is unlike for methods.m for which Matlab allows both 
+    names_str = javaMethod ("getFieldsCls", 
+                            "org.octave.ClassHelper", obj, isfull);
+    names = ostrsplit (names_str, ';');
   elseif (isjava (obj))
-    names_str = javaMethod ("getFieldsObj", "org.octave.ClassHelper", obj);
-    names = ostrsplit (names_str, ';');
-  elseif (ischar (obj))
-    names_str = javaMethod ("getFieldsCls", "org.octave.ClassHelper", obj);
+    names_str = javaMethod ("getFieldsObj", 
+                            "org.octave.ClassHelper", obj, isfull);
     names = ostrsplit (names_str, ';');
   else
     error ("fieldnames: Invalid input argument");
diff -r 25476410e25e -r 29510aa439e3 scripts/general/methods.m
--- a/scripts/general/methods.m	Fri Aug 12 02:09:59 2016 +0200
+++ b/scripts/general/methods.m	Fri Aug 12 15:11:59 2016 +0200
@@ -19,12 +19,18 @@
 ## -*- texinfo -*-
 ## @deftypefn  {} {} methods (@var{obj})
 ## @deftypefnx {} {} methods ("@var{classname}")
+## @deftypefnx {} {} methods (@dots{}, @code{'-full'})
 ## @deftypefnx {} {@var{mtds} =} methods (@dots{})
-## List the names of the public methods for the object @var{obj} or the
-## named class @var{classname}.
+## List the the public methods for the object @var{obj} or the
+## named class @var{classname}, whether inherited or not.
 ##
 ## @var{obj} may be an Octave class object or a Java object.
-## @var{classname} may be the name of an Octave class or a Java class.
+## @var{classname} may be the name of an Octave class or of a Java
+## class.
+##
+## With the argument @code{'-full'},
+## the full signatures are given, except the @code{public} modifier;
+## otherwise only the names.
 ##
 ## When called with no output arguments, @code{methods} prints the list of
 ## method names to the screen.  Otherwise, the output argument @var{mtds}
@@ -32,26 +38,40 @@
 ## @seealso{fieldnames}
 ## @end deftypefn
 
-function mtds = methods (obj)
+function mtds = methods (obj, sfull)
 
-  if (nargin != 1)
-    print_usage ();
-  endif
+  switch (nargin)
+    case 1
+      isfull = false;
+    case 2
+      if !isequal(sfull,'-full')
+        print_usage ();
+      endif
+      isfull = true;
+    otherwise
+      print_usage ();
+  endswitch
 
   if (isobject (obj))
     ## Call internal C++ function for Octave objects
+    ## FIXME: '-full' for Octave objects. 
     mtds_list = __methods__ (obj);
   elseif (ischar (obj))
     ## Could be a classname for an Octave class or Java class.
+    ## Matlab reference does not give any precedence. 
     ## Try Octave class first.
+    ## FIXME: '-full' for Octave class names. 
+    ## FIXME: Bug: if obj is an octave classname without methods. 
     mtds_list = __methods__ (obj);
     if (isempty (mtds_list))
       ## assume that obj refers to a java class 
-      mtds_str = javaMethod ("getMethodsCls", "org.octave.ClassHelper", obj);
+      mtds_str = javaMethod ("getMethodsCls", 
+                             "org.octave.ClassHelper", obj, isfull);
       mtds_list = ostrsplit (mtds_str, ';');
     endif
   elseif (isjava (obj))
-    mtds_str = javaMethod ("getMethodsObj", "org.octave.ClassHelper", obj);
+    mtds_str = javaMethod ("getMethodsObj", 
+                           "org.octave.ClassHelper", obj, isfull);
     mtds_list = strsplit (mtds_str, ';');
   else
     error ("methods: Invalid input argument");
diff -r 25476410e25e -r 29510aa439e3 scripts/java/org/octave/ClassHelper.java
--- a/scripts/java/org/octave/ClassHelper.java	Fri Aug 12 02:09:59 2016 +0200
+++ b/scripts/java/org/octave/ClassHelper.java	Fri Aug 12 15:11:59 2016 +0200
@@ -33,7 +33,7 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Array;
 import java.lang.reflect.InvocationTargetException;
-//import java.lang.reflect.Modifier;
+import java.lang.reflect.Modifier;
 
 //! Collection of methods being the core of the octave functions
 //! forming Octave's Java Interface.
@@ -46,10 +46,10 @@
 //! #getClassPath() used by @file javaclasspath.m defining @c javaclasspath
 //! to obtain the dynamic classpath.
 //! @arg
-//! #getMethods(String), #getMethods(Object) and #getMethods(Class)
+//! #getMethodsCls(String, boolean) and #getMethods(Object, boolean) 
 //! used by @file methods.m defining @c methods.
 //! @arg
-//! #getFields(Class), #getFields(String) and #getFields(Object)
+//! #getFieldsCls(String, boolean) and #getFieldsObj(Object, boolean)
 //! used by @file fieldnames.m defining @c fieldnames.
 //! @arg
 //! #invokeMethod(Object, String, Object[], Class[]) and
@@ -238,44 +238,58 @@
   }
 
   // new -MH-
-  //! Return a list of public methods
+  //! Return a list of string representations of public methods
   //! of the class with the given class name @c classname
-  //! loaded with #loader.
-  //! This method is based on ::getMethods(Class).
+  //! loaded with #loader, where @c isFull determines 
+  //! whether that representation comprises more than the mere name.
+  //!
+  //! This method is based on ::getMethods(Class, boolean).
   //! Used by @file methods.m only.
   //!
   //! @param classname
   //!    the name of the class under consideration.
+  //! @param isFull
+  //!    indicates whether the representation of the methods
+  //!    comprises more than the name (see ::getMethods(Class, boolean)).
   //! @return
-  //!    see ::getMethods(Class).
+  //!    see ::getMethods(Class, boolean).
   //! @throws ClassNotFoundException
   //!    if #loader cannot find a class with name @c classname.
-  public static String getMethodsCls (String classname)
+  public static String getMethodsCls (String classname, boolean isFull)
     throws ClassNotFoundException
   {
-    return getMethods (Class.forName (classname, true, loader));
+    return getMethods (Class.forName (classname, true, loader), isFull);
   }
 
   // new -MH-
-  //! Return a list of public methods
-  //! of the class of the instance @c obj.
+  //! Return a list of string representations of all of public methods
+  //! of the class of the instance @c obj, where @c isFull determines 
+  //! whether that representation comprises more than the mere name.
+  //! Used by @file methods.m only.
+  //!
+  //! This method is based on ::getMethods(Class, boolean).
   //! Used by @file methods.m only.
   //!
   //! @param obj
   //!    the object under consideration. This shall not be @c null.
+  //! @param isFull
+  //!    indicates whether the representation of the methods
+  //!    comprises more than the name (see ::getMethods(Class, boolean)).
   //! @throws ClassNotFoundException
   //!    if #loader cannot find @c obj's class.
   //!    Since all objects are created by reflection
   //!    from classes loaded by #loader, this shall not happen.
-  public static String getMethodsObj (Object obj)
+  public static String getMethodsObj (Object obj, boolean isFull)
     throws ClassNotFoundException
   {
-    return getMethods (obj.getClass ());
+    return getMethods (obj.getClass (), isFull);
   }
 
   // new -MH-
-  //! Return list of public
-  //! methods for given class @c klass.
+  //! Return list of string representations of all public methods
+  //! of given class @c klass, where @c isFull determines 
+  //! whether that representation comprises more than the mere name.
+  //!
   //! This method is based on Class::getMethods().
   //! To obtain all methods, one could use Class::getDeclaredMethods()
   //! iterating over class and superclasses.
@@ -283,14 +297,29 @@
   //!
   //! @param klass
   //!    the class under consideration.
+  //! @param isFull
+  //!    indicates whether the representation of the methods 
+  //!    comprises more than the name, namely the complete signature 
+  //!    including the modifiers except @c public, the return type, 
+  //!    the name, the parameter list and the declared throwables. 
   //! @return
-  //!    the list of methods for given class @c klass as a string,
-  //!    the signatures of the methods separated by <code>;</code>.
-  private static String getMethods (Class klass)
+  //!    the list of string representations of methods 
+  //!    of the given class @c klass as a string,
+  //!    separated by <code>;</code>.
+  //!    For <code>isFull==false</code> this is just the name,
+  //!    otherwise the full signature including the modifiers except @c public 
+  //!    the return type, the name, the parameter list
+  //!    and the throws-declaration as e.g. 
+  //!    <code>public static void main(String[]) throws Exception</code>.
+  // FIXME: methods(...,'-full')  based on this method
+  // iin addition requires inheritance information
+  // but it is not clear in which form: matlab docs required.
+  private static String getMethods (Class klass, boolean isFull)
   {
     StringBuffer sb = new StringBuffer ();
 
     Method theMethod[] = klass.getMethods ();
+    int mod;
     for (int i = 0; i < theMethod.length; i++)
       {
         if (i > 0)
@@ -298,34 +327,50 @@
             sb.append (';');
           }
 
-        // Return type and name
-        sb.append (theMethod[i].getReturnType ().getCanonicalName ());
-        sb.append (' ');
+        if (isFull)
+          {
+            // the modifiers except 'public' 
+            mod = theMethod[i].getModifiers () ^ Modifier.PUBLIC;
+            if (mod != 0)
+              {
+                sb.append (Modifier.toString(mod));
+                sb.append (' ');
+              }
+
+            // the return type 
+            sb.append (theMethod[i].getReturnType ().getCanonicalName ());
+            sb.append (' ');
+          }
+
+        // the name 
         sb.append (theMethod[i].getName ());
 
-        // parameter list
-        sb.append ('(');
-        Class theParameter[] = theMethod[i].getParameterTypes ();
-        for (int j = 0; j < theParameter.length; j++)
+        if (isFull)
           {
-            if (j > 0)
+            // parameter list
+            sb.append ('(');
+            Class theParameter[] = theMethod[i].getParameterTypes ();
+            for (int j = 0; j < theParameter.length; j++)
               {
-                sb.append (", ");
+                if (j > 0)
+                  {
+                    sb.append (", ");
+                  }
+                sb.append (theParameter[j].getCanonicalName ());
               }
-            sb.append (theParameter[j].getCanonicalName ());
-          }
-        sb.append (')');
+            sb.append (')');
 
-        // exceptions
-        Class theExceptions[] = theMethod[i].getExceptionTypes ();
-        if (theExceptions.length > 0)
-          {
-            sb.append (" throws ");
-            sb.append (theExceptions[0].getCanonicalName ());
-            for (int j = 1; j < theExceptions.length; j++)
+            // exceptions
+            Class theExceptions[] = theMethod[i].getExceptionTypes ();
+            if (theExceptions.length > 0)
               {
-                sb.append (", ");
-                sb.append (theExceptions[j].getCanonicalName ());
+                sb.append (" throws ");
+                sb.append (theExceptions[0].getCanonicalName ());
+                for (int j = 1; j < theExceptions.length; j++)
+                  {
+                    sb.append (", ");
+                    sb.append (theExceptions[j].getCanonicalName ());
+                  }
               }
           }
       }
@@ -334,8 +379,11 @@
   }
 
   // new -MH-
-  //! Return a list of all accessible public fields
-  //! of the given class @c klass.
+  //! Return a list of string representations of all public fields
+  //! of the given class @c klass, 
+  //! where @c isFull determines 
+  //! whether that representation comprises more than the mere name.
+  //!
   //! This method is based on Class::getFields().
   //! To obtain all fields, one could use Class::getDeclaredFields()
   //! iterating over class and superclasses.
@@ -343,21 +391,49 @@
   //!
   //! @param klass
   //!    the class under consideration.
+  //! @param isFull
+  //!    indicates whether the representation of the fields 
+  //!    comprises more than the name: 
+  //!    namely in addition the modifiers except @c public and the type. 
   //! @return
-  //!    the list of names of accessible public fields
-  //!    of the given class @c klass
-  //!    as a string, separated by <code>;</code>.
-  private static String getFields (Class klass)
+  //!    the list of string representations of public fields
+  //!    of the given class @c klass as a string,
+  //!    separated by <code>;</code>.
+  //!    For <code>isFull==false</code> this is just the name,
+  //!    otherwise in addition the modifiers except @c public and the type.
+  //!    Example: <code>public static int num</code>.
+  // FIXME: fieldnames(...,'-full') based on this method
+  // in addition requires inheritance information
+  // but it is not clear in which form: matlab docs required.
+  private static String getFields (Class klass, boolean isFull)
   {
     StringBuffer sb = new StringBuffer ();
 
     Field theField[] = klass.getFields ();
+    int mod;
     for (int i = 0; i < theField.length; i++)
       {
         if (i > 0)
           {
             sb.append (';');
           }
+
+        if (isFull)
+          {
+            // the modifiers except 'public' 
+            mod = theField[i].getModifiers () ^ Modifier.PUBLIC;
+            if (mod != 0)
+              {
+                sb.append (Modifier.toString(mod));
+                sb.append (' ');
+              }
+
+            // the type 
+            sb.append (theField[i].getType ().getCanonicalName ());
+            sb.append (' ');
+            }
+
+        // the name 
         sb.append (theField[i].getName ());
       }
 
@@ -365,40 +441,54 @@
   }
 
   // new -MH-
-  //! Return a list of all accessible public fields
+  //! Return a list of string representations of all public fields
   //! of the class with the given class name @c classname
-  //! loaded with #loader.
-  //! This method is based on ::getFields(Class).
+  //! loaded with #loader, 
+  //! where @c isFull determines 
+  //! whether that representation comprises more than the mere name.
+  //!
+  //! This method is based on ::getFields(Class, boolean).
   //! Used by @file fieldnames.m only.
   //!
   //! @param classname
   //!    the name of the class under consideration.
+  //! @param isFull
+  //!    indicates whether the representation of the fields
+  //!    comprises more than the name (see ::getFields(Class, boolean)).
   //! @return
-  //!    see ::getFields(Class).
+  //!    see ::getFields(Class, boolean).
   //! @throws ClassNotFoundException
   //!    if #loader cannot find a class with name @c classname.
-  public static String getFieldsCls (String classname)
+  public static String getFieldsCls (String classname, boolean isFull)
     throws ClassNotFoundException
   {
-    return getFields (Class.forName (classname, true, loader));
+    return getFields (Class.forName (classname, true, loader), isFull);
   }
 
   // new -MH-
-  //! Return a list of all accessible public fields
-  //! of class of the instance @c obj.
-  //! This method is based on ::getFields(Class).
+  //! Return a list of string representations of all public fields
+  //! of class of the instance @c obj, 
+  //! where @c isFull determines 
+  //! whether that representation comprises more than the mere name.
+  //!
+  //! This method is based on ::getFields(Class, boolean).
   //! Used by @file fieldnames.m only.
   //!
   //! @param obj
   //!    the object under consideration. This shall not be @c null.
+  //! @param isFull
+  //!    indicates whether the representation of the fields
+  //!    comprises more than the name (see ::getFields(Class, boolean)).
+  //! @return
+  //!    see ::getFields(Class, boolean).
   //! @throws ClassNotFoundException
   //!    if #loader cannot find @c obj's class.
   //!    Since all objects are created by reflection
   //!    from classes loaded by #loader, this shall not happen.
-  public static String getFieldsObj (Object obj)
+  public static String getFieldsObj (Object obj, boolean isFull)
     throws ClassNotFoundException
   {
-    return (getFields (obj.getClass ()));
+    return getFields (obj.getClass (), isFull);
   }
 
   //! Return the first method in class @c cls
