# HG changeset patch
# User Ernst Reissner <rei3ner@arcor.de>
# Date 1471270382 -7200
#      Mon Aug 15 16:13:02 2016 +0200
# Node ID eaa3863b3e71fa69bd65de549f8b3ba775c39a9c
# Parent  085b35f14eb757f01b5e7d65fe9201b41fd2f415
patch #9085: added function constructors

added file scripts/java/constructors.m defining the function,
added according entry in scripts/java/module.mk
added methods getConstructors, getConstructorsCls and getConstructorsObj
in file scripts/java/org/octave/ClassHelper.java

diff -r 085b35f14eb7 -r eaa3863b3e71 scripts/java/constructors.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/java/constructors.m	Mon Aug 15 16:13:02 2016 +0200
@@ -0,0 +1,64 @@
+## Copyright (C) 2007, 2013 Michael Goffioul
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {} {@var{constr} =} constructors (@var{classname})
+## @deftypefnx {} {@var{constr} =} constructors (@var{obj})
+##
+## Return a cell array of strings describing the constructors of the
+## class specified by a java object or by java class name. 
+##
+## @example
+## Both, 
+## @group
+## o=javaObject('java.lang.Double', 42);
+## constructors(o);
+## @end group
+## and 
+## @group
+## constructors('java.lang.Double');
+## @end group
+## yield 
+## @group
+## ans = 
+## {
+##   [1,1] = (double)
+##   [1,2] = (java.lang.String) throws java.lang.NumberFormatException
+## }
+## @end group
+## @end example
+## @seealso{fieldnames, methods}
+## @end deftypefn
+
+function retval = constructors (obj)
+
+  if (nargin ~=1)
+    print_usage ();
+  endif
+
+  if  (ischar (obj))
+    retval = javaMethod ("getConstructorsCls", "org.octave.ClassHelper", obj);
+    retval = ostrsplit (retval, ';');
+  elseif (isjava (obj))
+    retval = javaMethod ("getConstructorsObj", "org.octave.ClassHelper", obj);
+    retval = ostrsplit (retval, ';');
+  else
+    error ("constructors: Invalid input argument");
+  endif
+endfunction
+
diff -r 085b35f14eb7 -r eaa3863b3e71 scripts/java/module.mk
--- a/scripts/java/module.mk	Fri Aug 12 23:51:22 2016 +0200
+++ b/scripts/java/module.mk	Mon Aug 15 16:13:02 2016 +0200
@@ -1,6 +1,7 @@
 FCN_FILE_DIRS += scripts/java
 
 scripts_java_FCN_FILES = \
+  scripts/java/constructors.m \
   scripts/java/java_get.m \
   scripts/java/java_set.m \
   scripts/java/javaArray.m \
diff -r 085b35f14eb7 -r eaa3863b3e71 scripts/java/org/octave/ClassHelper.java
--- a/scripts/java/org/octave/ClassHelper.java	Fri Aug 12 23:51:22 2016 +0200
+++ b/scripts/java/org/octave/ClassHelper.java	Mon Aug 15 16:13:02 2016 +0200
@@ -265,7 +265,6 @@
   //! 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.
@@ -275,6 +274,8 @@
   //! @param isFull
   //!    indicates whether the representation of the methods
   //!    comprises more than the name (see ::getMethods(Class, boolean)).
+  //! @return
+  //!    see ::getMethods(Class, boolean).
   //! @throws ClassNotFoundException
   //!    if #loader cannot find @c obj's class.
   //!    Since all objects are created by reflection
@@ -303,14 +304,14 @@
   //!    including the modifiers except @c public, the return type, 
   //!    the name, the parameter list and the declared throwables. 
   //! @return
-  //!    the list of string representations of methods 
+  //!    the list of string representations of the public 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>.
+  //!    <code>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.
@@ -318,10 +319,12 @@
   {
     StringBuffer sb = new StringBuffer ();
 
-    Method theMethod[] = klass.getMethods ();
+    Method[] methods = klass.getMethods ();
+    Method theMethod;
     int mod;
-    for (int i = 0; i < theMethod.length; i++)
+    for (int i = 0; i < methods.length; i++)
       {
+        theMethod = methods[i];
         if (i > 0)
           {
             sb.append (';');
@@ -330,7 +333,7 @@
         if (isFull)
           {
             // the modifiers except 'public' 
-            mod = theMethod[i].getModifiers () ^ Modifier.PUBLIC;
+            mod = theMethod.getModifiers () ^ Modifier.PUBLIC;
             if (mod != 0)
               {
                 sb.append (Modifier.toString(mod));
@@ -338,18 +341,18 @@
               }
 
             // the return type 
-            sb.append (theMethod[i].getReturnType ().getCanonicalName ());
+            sb.append (theMethod.getReturnType ().getCanonicalName ());
             sb.append (' ');
           }
 
         // the name 
-        sb.append (theMethod[i].getName ());
+        sb.append (theMethod.getName ());
 
         if (isFull)
           {
             // parameter list
             sb.append ('(');
-            Class theParameter[] = theMethod[i].getParameterTypes ();
+            Class theParameter[] = theMethod.getParameterTypes ();
             for (int j = 0; j < theParameter.length; j++)
               {
                 if (j > 0)
@@ -361,7 +364,7 @@
             sb.append (')');
 
             // exceptions
-            Class theExceptions[] = theMethod[i].getExceptionTypes ();
+            Class theExceptions[] = theMethod.getExceptionTypes ();
             if (theExceptions.length > 0)
               {
                 sb.append (" throws ");
@@ -396,7 +399,7 @@
   //!    comprises more than the name: 
   //!    namely in addition the modifiers except @c public and the type. 
   //! @return
-  //!    the list of string representations of public fields
+  //!    the list of string representations of the 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,
@@ -409,10 +412,12 @@
   {
     StringBuffer sb = new StringBuffer ();
 
-    Field theField[] = klass.getFields ();
+    Field[] fields = klass.getFields ();
+    Field theField;
     int mod;
     for (int i = 0; i < theField.length; i++)
       {
+        theField = fields[i];
         if (i > 0)
           {
             sb.append (';');
@@ -421,7 +426,7 @@
         if (isFull)
           {
             // the modifiers except 'public' 
-            mod = theField[i].getModifiers () ^ Modifier.PUBLIC;
+            mod = theField.getModifiers () ^ Modifier.PUBLIC;
             if (mod != 0)
               {
                 sb.append (Modifier.toString(mod));
@@ -429,12 +434,12 @@
               }
 
             // the type 
-            sb.append (theField[i].getType ().getCanonicalName ());
+            sb.append (theField.getType ().getCanonicalName ());
             sb.append (' ');
             }
 
         // the name 
-        sb.append (theField[i].getName ());
+        sb.append (theField.getName ());
       }
 
     return sb.toString ();
@@ -491,6 +496,120 @@
     return getFields (obj.getClass (), isFull);
   }
 
+
+  //! Return a list of string representations of all public constructors
+  //! of the given class @c klass.
+  //!
+  //! This method is based on Class::getConstructors().
+  //! To obtain all constructors, one could use Class::getDeclaredConstructors()
+  //! iterating over class and superclasses.
+  //! Used internally and by @file constructors.m only.
+  //!
+  //! @param klass
+  //!    the class under consideration.
+ //! @return
+  //!    the list of string representations of the public constructors
+  //!    of the given class @c klass as a string,
+  //!    separated by <code>;</code>.
+  //!    This is the full signature including the modifiers except @c public 
+  //!    the parameter list and the throws-declaration.
+  //!    For class <code>java.math.BigDecimal</code> this is 
+  //!    <code>(String);(double)</code>.
+
+  // all are java.lang.reflect.Member
+  private static String getConstructors (Class klass)
+  {
+    StringBuffer sb = new StringBuffer ();
+
+    Constructor[] constructors = klass.getConstructors ();
+    Constructor theConstructor;
+    int mod;
+    for (int i = 0; i < constructors.length; i++)
+      {
+        theConstructor = constructors[i];
+        if (i > 0)
+          {
+            sb.append (';');
+          }
+
+        // the modifiers except 'public' 
+        mod = theConstructor.getModifiers () ^ Modifier.PUBLIC;
+        if (mod != 0)
+          {
+            sb.append (Modifier.toString(mod));
+            sb.append (' ');
+          }
+
+
+        // parameter list
+        sb.append ('(');
+        Class theParameter[] = theConstructor.getParameterTypes ();
+        for (int j = 0; j < theParameter.length; j++)
+          {
+            if (j > 0)
+              {
+                sb.append (", ");
+              }
+            sb.append (theParameter[j].getCanonicalName ());
+          }
+        sb.append (')');
+
+        // exceptions
+        Class theExceptions[] = theConstructor.getExceptionTypes ();
+        if (theExceptions.length > 0)
+          {
+            sb.append (" throws ");
+            sb.append (theExceptions[0].getCanonicalName ());
+            for (int j = 1; j < theExceptions.length; j++)
+              {
+                sb.append (", ");
+                sb.append (theExceptions[j].getCanonicalName ());
+              }
+          }
+      }
+    return sb.toString();
+  }
+
+  //! Return a list of string representations of public constructors
+  //! of the class with the given class name @c classname
+  //! loaded with #loader.
+  //!
+  //! This method is based on ::getConstructors(Class).
+  //! Used by @file constructors.m only.
+  //!
+  //! @param classname
+  //!    the name of the class under consideration.
+  //! @return
+  //!    see ::getConstructors(Class).
+  //! @throws ClassNotFoundException
+  //!    if #loader cannot find a class with name @c classname.
+  public static String getConstructorsCls (String classname)
+    throws ClassNotFoundException
+  {
+    return getConstructors (Class.forName (classname, true, loader));
+  }
+
+  //! Return a list of string representations of all of public constructors
+  //! of the class of the instance @c obj.
+  //!
+  //! This method is based on ::getConstroctors(Class).
+  //! Used by @file methods.m only.
+  //!
+  //! @param obj
+  //!    the object under consideration. This shall not be @c null.
+  //! @return
+  //!    see ::getConstructors(Class).
+  //! @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 getConstructorsObj (Object obj)
+    throws ClassNotFoundException
+  {
+    return getConstructors (obj.getClass ());
+  }
+
+
   //! Return the first method in class @c cls
   //! with name @c name and parameter types @c argTypes
   //! or @c null if no such method is found.
