Bug 13027 fixed: There was no autowrap into array in JIMS 78/13078/2
Calixte DENIZET [Mon, 4 Nov 2013 20:16:15 +0000 (21:16 +0100)]
Change-Id: I4e830dab042f1bf6eb833d3eae28482cd06463f3

scilab/CHANGES_5.5.X
scilab/modules/external_objects_java/src/java/org/scilab/modules/external_objects_java/FunctionArguments.java
scilab/modules/external_objects_java/src/java/org/scilab/modules/external_objects_java/ScilabJavaArray.java
scilab/modules/external_objects_java/src/java/org/scilab/modules/external_objects_java/ScilabJavaMethod.java
scilab/modules/external_objects_java/tests/unit_tests/array_wrapping.dia.ref [new file with mode: 0644]
scilab/modules/external_objects_java/tests/unit_tests/array_wrapping.tst [new file with mode: 0644]

index 6a63a49..1bccb2b 100644 (file)
@@ -107,6 +107,8 @@ Scilab Bug Fixes
 
 * Bug #13022 fixed - Vectorial export did not clip large segments.
 
+* Bug #13027 fixed - There was no autowrap into array in JIMS.
+
 * Bug #13032 fixed - Fixed CMATVIEW help example and created one for CMAT3D.
 
 * Bug #13033 fixed - -1 could not be used as nax argument in plot2d.
index 8d4706d..e364c72 100644 (file)
@@ -13,6 +13,7 @@
 package org.scilab.modules.external_objects_java;
 
 import java.beans.MethodDescriptor;
+import java.lang.reflect.Array;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
@@ -57,6 +58,19 @@ public final class FunctionArguments {
             }
         });
 
+        // Converter to convert a double[] to an int[]
+        registerConverter(new Converter() {
+            @Override
+            public Object convert(Object original, Class<?> to) {
+                return ScilabJavaArray.toIntArray((double[]) original);
+            }
+
+            @Override
+            public boolean canConvert(Class<?> from, Class<?> to) {
+                return (to == int[].class) && (from == double[].class);
+            }
+        });
+
         // Converter to convert a double[] to a Double[] (or an other primitive type)
         registerConverter(new Converter() {
             @Override
@@ -100,6 +114,45 @@ public final class FunctionArguments {
                 return String.class.isAssignableFrom(from) && to.isEnum();
             }
         });
+
+        // Converter to convert double[][] to double[]
+        registerConverter(new Converter() {
+            @Override
+            public Object convert(Object original, Class<?> to) {
+                return ScilabJavaArray.toOneDim(original);
+            }
+
+            @Override
+            public boolean canConvert(Class<?> from, Class<?> to) {
+                return to.isArray() && from.isArray() && from.getComponentType().isArray() && to.getComponentType() == from.getComponentType().getComponentType();
+            }
+        });
+
+        // Converter to convert double[] to double[][]
+        registerConverter(new Converter() {
+            @Override
+            public Object convert(Object original, Class<?> to) {
+                return ScilabJavaArray.toBiDim(original);
+            }
+
+            @Override
+            public boolean canConvert(Class<?> from, Class<?> to) {
+                return to.isArray() && from.isArray() && to.getComponentType().isArray() && from.getComponentType() == to.getComponentType().getComponentType();
+            }
+        });
+
+        // Converter to convert double to double[]
+        registerConverter(new Converter() {
+            @Override
+            public Object convert(Object original, Class<?> to) {
+                return ScilabJavaArray.singleToOneDim(to.getComponentType(), original);
+            }
+
+            @Override
+            public boolean canConvert(Class<?> from, Class<?> to) {
+                return to.isArray() && from == to.getComponentType();
+            }
+        });
     }
 
     /**
@@ -190,18 +243,29 @@ public final class FunctionArguments {
             if (toConvert != null && !toConvert.isEmpty()) {
                 // Contains int.class arguments and we passed double.class args
                 Class[] types = better.getParameterTypes();
+                Class base = types[types.length - 1].getComponentType();
                 for (Map.Entry<Integer, Converter> entry : toConvert.entrySet()) {
                     int i = entry.getKey();
-                    argsClass[i] = types[i];
-                    args[i] = entry.getValue().convert(args[i], types[i]);
+                    if (i >= 0) {
+                        argsClass[i] = types[i];
+                        args[i] = entry.getValue().convert(args[i], types[i]);
+                    } else {
+                        i = -i - 1;
+                        args[i] = entry.getValue().convert(args[i], base);
+                    }
                 }
             }
 
             if (isVarArgs) {
                 // Variable arguments
                 Class[] types = better.getParameterTypes();
-                Object[] o = new Object[args.length - types.length + 1];
-                System.arraycopy(args, types.length - 1, o, 0, args.length - types.length + 1);
+                Class base = types[types.length - 1].getComponentType();
+                Object o = Array.newInstance(base, args.length - types.length + 1);
+
+                // Don't use System.arraycopy since it does not handle unboxing
+                for (int i = 0; i < args.length - types.length + 1; i++) {
+                    Array.set(o, i, args[i + types.length - 1]);
+                }
 
                 Object[] newArgs = new Object[types.length];
                 System.arraycopy(args, 0, newArgs, 0, types.length - 1);
@@ -258,17 +322,28 @@ public final class FunctionArguments {
             if (toConvert != null && !toConvert.isEmpty()) {
                 // Contains int.class arguments and we passed double.class args
                 Class[] types = better.getParameterTypes();
+                Class base = types[types.length - 1].getComponentType();
                 for (Map.Entry<Integer, Converter> entry : toConvert.entrySet()) {
                     int i = entry.getKey();
-                    argsClass[i] = types[i];
-                    args[i] = entry.getValue().convert(args[i], types[i]);
+                    if (i >= 0) {
+                        argsClass[i] = types[i];
+                        args[i] = entry.getValue().convert(args[i], types[i]);
+                    } else {
+                        i = -i - 1;
+                        args[i] = entry.getValue().convert(args[i], base);
+                    }
                 }
             }
             if (isVarArgs) {
                 // Variable arguments
                 Class[] types = better.getParameterTypes();
-                Object[] o = new Object[args.length - types.length + 1];
-                System.arraycopy(args, types.length - 1, o, 0, args.length - types.length + 1);
+                Class base = types[types.length - 1].getComponentType();
+                Object o = Array.newInstance(base, args.length - types.length + 1);
+
+                // Don't use System.arraycopy since it does not handle unboxing
+                for (int i = 0; i < args.length - types.length + 1; i++) {
+                    Array.set(o, i, args[i + types.length - 1]);
+                }
 
                 Object[] newArgs = new Object[types.length];
                 System.arraycopy(args, 0, newArgs, 0, types.length - 1);
@@ -298,11 +373,31 @@ public final class FunctionArguments {
 
         long s = 0;
         int end = A.length;
-        if (A.length > 0 && ((A.length < B.length && A[A.length - 1] == Object[].class) || (A.length == B.length && A.length == 1 && A[0] == Object[].class && B[0] != Object[].class))) {
+        if (A.length > 0 && A[A.length - 1].isArray() && (A.length < B.length || (A.length == 1 && B.length == 1 && !B[0].isArray()))) {
+            Class base = A[A.length - 1].getComponentType();
             // this is a variable arguments method
             bools[0] = true;
             end--;
             s = 1 << 40;
+
+            for (int i = A.length - 1; i < B.length; i++) {
+                long d = dist(base, B[i]);
+                if (d == -1) {
+                    for (Converter converter : converters) {
+                        if (converter.canConvert(B[i], base)) {
+                            d = 2048;
+                            toConvert.put(-i - 1, converter);
+                            break;
+                        }
+                    }
+
+                    if (d != 2048) {
+                        return Long.MIN_VALUE;
+                    }
+                }
+                // s is the sum of the square of the distance
+                s += d * d;
+            }
         } else if (A.length < B.length) {
             return Long.MIN_VALUE;
         }
index 71f95a4..457b287 100644 (file)
@@ -346,6 +346,15 @@ public final class ScilabJavaArray {
         return o;
     }
 
+    public static int[] toIntArray(double[] o) {
+        int[] ret = new int[o.length];
+        for (int i = 0; i < o.length; i++) {
+            ret[i] = (int) o[i];
+        }
+
+        return ret;
+    }
+
     /**
      * Box a double array
      * @param a an array
@@ -516,6 +525,11 @@ public final class ScilabJavaArray {
         return o;
     }
 
+    /**
+     * Get array base type
+     * @param c the Class
+     * @return the base
+     */
     public static Class getArrayBaseType(Class c) {
         Class base = c;
         while (base.isArray()) {
@@ -526,6 +540,22 @@ public final class ScilabJavaArray {
     }
 
     /**
+     * Get array info: base Class and number of dimensions
+     * @param c the Class
+     * @return info
+     */
+    public static Object[] getArrayInfo(Class c) {
+        Class base = c;
+        int dims = 0;
+        while (base.isArray()) {
+            base = base.getComponentType();
+            dims++;
+        }
+
+        return new Object[] {base, new Integer(dims)};
+    }
+
+    /**
      * Get an array of primitive arrays classes. For example, double[][][][] will give {Double[], Double[][], Double[][][]}.
      * @param c the base class
      * @return an array of classes
@@ -583,6 +613,194 @@ public final class ScilabJavaArray {
         return cl;
     }
 
+    /**
+     * Convert a bi-dimensional array into one-dim one
+     * @param x the bi-dim array
+     * @return a one-dim array
+     */
+    public static byte[] toOneDim(byte[][] x) {
+        if (x.length == 0 || x[0].length == 0) {
+            return new byte[0];
+        }
+
+        final int len = x[0].length;
+        final byte[] ret = new byte[x.length * len];
+        for (int i = 0, s = 0; i < x.length; i++, s += len) {
+            System.arraycopy(x[i], 0, ret, s, len);
+        }
+
+        return ret;
+    }
+
+    /**
+     * Convert a bi-dimensional array into one-dim one
+     * @param x the bi-dim array
+     * @return a one-dim array
+     */
+    public static short[] toOneDim(short[][] x) {
+        if (x.length == 0 || x[0].length == 0) {
+            return new short[0];
+        }
+
+        final int len = x[0].length;
+        final short[] ret = new short[x.length * len];
+        for (int i = 0, s = 0; i < x.length; i++, s += len) {
+            System.arraycopy(x[i], 0, ret, s, len);
+        }
+
+        return ret;
+    }
+
+    /**
+     * Convert a bi-dimensional array into one-dim one
+     * @param x the bi-dim array
+     * @return a one-dim array
+     */
+    public static int[] toOneDim(int[][] x) {
+        if (x.length == 0 || x[0].length == 0) {
+            return new int[0];
+        }
+
+        final int len = x[0].length;
+        final int[] ret = new int[x.length * len];
+        for (int i = 0, s = 0; i < x.length; i++, s += len) {
+            System.arraycopy(x[i], 0, ret, s, len);
+        }
+
+        return ret;
+    }
+
+    /**
+     * Convert a bi-dimensional array into one-dim one
+     * @param x the bi-dim array
+     * @return a one-dim array
+     */
+    public static long[] toOneDim(long[][] x) {
+        if (x.length == 0 || x[0].length == 0) {
+            return new long[0];
+        }
+
+        final int len = x[0].length;
+        final long[] ret = new long[x.length * len];
+        for (int i = 0, s = 0; i < x.length; i++, s += len) {
+            System.arraycopy(x[i], 0, ret, s, len);
+        }
+
+        return ret;
+    }
+
+    /**
+     * Convert a bi-dimensional array into one-dim one
+     * @param x the bi-dim array
+     * @return a one-dim array
+     */
+    public static float[] toOneDim(float[][] x) {
+        if (x.length == 0 || x[0].length == 0) {
+            return new float[0];
+        }
+
+        final int len = x[0].length;
+        final float[] ret = new float[x.length * len];
+        for (int i = 0, s = 0; i < x.length; i++, s += len) {
+            System.arraycopy(x[i], 0, ret, s, len);
+        }
+
+        return ret;
+    }
+
+    /**
+     * Convert a bi-dimensional array into one-dim one
+     * @param x the bi-dim array
+     * @return a one-dim array
+     */
+    public static double[] toOneDim(double[][] x) {
+        if (x.length == 0 || x[0].length == 0) {
+            return new double[0];
+        }
+
+        final int len = x[0].length;
+        final double[] ret = new double[x.length * len];
+        for (int i = 0, s = 0; i < x.length; i++, s += len) {
+            System.arraycopy(x[i], 0, ret, s, len);
+        }
+
+        return ret;
+    }
+
+    /**
+     * Convert a bi-dimensional array into one-dim one
+     * @param x the bi-dim array
+     * @return a one-dim array
+     */
+    public static char[] toOneDim(char[][] x) {
+        if (x.length == 0 || x[0].length == 0) {
+            return new char[0];
+        }
+
+        final int len = x[0].length;
+        final char[] ret = new char[x.length * len];
+        for (int i = 0, s = 0; i < x.length; i++, s += len) {
+            System.arraycopy(x[i], 0, ret, s, len);
+        }
+
+        return ret;
+    }
+
+    /**
+     * Convert a bi-dimensional array into one-dim one
+     * @param x the bi-dim array
+     * @return a one-dim array
+     */
+    static Object toOneDim(Object x) {
+        Class base = getArrayBaseType(x.getClass());
+
+        if (base.isPrimitive()) {
+            try {
+                Method m = ScilabJavaArray.class.getDeclaredMethod("toOneDim", x.getClass());
+                return m.invoke(null, x);
+            } catch (Exception e) {
+                return null;
+            }
+        } else {
+            Object[][] xx = (Object[][]) x;
+
+            if (xx.length == 0 || xx[0].length == 0) {
+                return Array.newInstance(base, 0);
+            }
+
+            final int len = xx[0].length;
+            final Object ret = Array.newInstance(base, xx.length * len);
+            for (int i = 0, s = 0; i < xx.length; i++, s += len) {
+                System.arraycopy(xx[i], 0, ret, s, len);
+            }
+
+            return ret;
+        }
+    }
+
+    /**
+     * Convert a one-dimensional array into bi-dim one
+     * @param x the one-dim array
+     * @return a bi-dim array
+     */
+    static Object toBiDim(Object x) {
+        Object ret = Array.newInstance(x.getClass(), 1);
+        Array.set(ret, 0, x);
+
+        return ret;
+    }
+
+    /**
+     * Convert a one-dimensional array into bi-dim one
+     * @param x the one-dim array
+     * @return a bi-dim array
+     */
+    static Object singleToOneDim(Class base, Object x) {
+        Object ret = Array.newInstance(base, 1);
+        Array.set(ret, 0, x);
+
+        return ret;
+    }
 
     /**
      * Convert a list to an array of primitive type
index d110f29..5669c4d 100644 (file)
@@ -149,6 +149,7 @@ public final class ScilabJavaMethod {
         } catch (IllegalAccessException e) {
             throw new ScilabJavaException("Illegal access to the method " + name + ".");
         } catch (IllegalArgumentException e) {
+            e.printStackTrace();
             throw new ScilabJavaException("Illegal argument in the method " + name + ": \n" + e.getMessage());
         } catch (NullPointerException e) {
             throw new ScilabJavaException("The method " + name + " is called on a null object.");
diff --git a/scilab/modules/external_objects_java/tests/unit_tests/array_wrapping.dia.ref b/scilab/modules/external_objects_java/tests/unit_tests/array_wrapping.dia.ref
new file mode 100644 (file)
index 0000000..0805ea2
--- /dev/null
@@ -0,0 +1,43 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2013 - Scilab Enterprises - Calixte DENIZET
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+c = jcompile("Test", ["public class Test {"
+"public static double foo(double[] x) {"
+" double s = 0;"
+" for (int i = 0; i < x.length; i++) s += x[i];"
+" return s;"
+"}"
+"public static double foo(String[] x) {"
+" double s = 0;"
+" for (int i = 0; i < x.length; i++) s += x[i].length();"
+" return s;"
+"}"
+"public static double bar(int[] x) {"
+" double s = 0;"
+" for (int i = 0; i < x.length; i++) s += x[i];"
+" return s;"
+"}"
+"}"
+]);
+jimport Test;
+x = 123;
+assert_checkequal(Test.foo(x), x);
+x = rand(1,100);
+assert_checkequal(Test.foo(x), sum(x));
+x = rand(100,100);
+assert_checkequal(Test.foo(x), sum(x));
+assert_checkequal(Test.foo(1,2,3,4,5,6), sum(1:6));
+x = "hello";
+assert_checkequal(Test.foo(x), length(x));
+x = string(rand(1,100));
+assert_checkequal(Test.foo(x), sum(length(x)));
+x = string(rand(100,100));
+assert_checkequal(Test.foo(x), sum(length(x)));
+x = 123;
+assert_checkequal(Test.bar(x), x);
+x = floor(123 * rand(1,100));
+assert_checkequal(Test.bar(x), sum(x));
+assert_checkequal(Test.bar(1,2,3,4,5,6), sum(1:6));
diff --git a/scilab/modules/external_objects_java/tests/unit_tests/array_wrapping.tst b/scilab/modules/external_objects_java/tests/unit_tests/array_wrapping.tst
new file mode 100644 (file)
index 0000000..696368e
--- /dev/null
@@ -0,0 +1,54 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2013 - Scilab Enterprises - Calixte DENIZET
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+
+c = jcompile("Test", ["public class Test {"
+"public static double foo(double[] x) {"
+" double s = 0;"
+" for (int i = 0; i < x.length; i++) s += x[i];"
+" return s;"
+"}"
+"public static double foo(String[] x) {"
+" double s = 0;"
+" for (int i = 0; i < x.length; i++) s += x[i].length();"
+" return s;"
+"}"
+"public static double bar(int[] x) {"
+" double s = 0;"
+" for (int i = 0; i < x.length; i++) s += x[i];"
+" return s;"
+"}"
+"}"
+]);
+jimport Test;
+
+x = 123;
+assert_checkequal(Test.foo(x), x);
+
+x = rand(1,100);
+assert_checkequal(Test.foo(x), sum(x));
+
+x = rand(100,100);
+assert_checkequal(Test.foo(x), sum(x));
+
+assert_checkequal(Test.foo(1,2,3,4,5,6), sum(1:6));
+
+x = "hello";
+assert_checkequal(Test.foo(x), length(x));
+
+x = string(rand(1,100));
+assert_checkequal(Test.foo(x), sum(length(x)));
+
+x = string(rand(100,100));
+assert_checkequal(Test.foo(x), sum(length(x)));
+
+x = 123;
+assert_checkequal(Test.bar(x), x);
+
+x = floor(123 * rand(1,100));
+assert_checkequal(Test.bar(x), sum(x));
+
+assert_checkequal(Test.bar(1,2,3,4,5,6), sum(1:6));
\ No newline at end of file