X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Futils%2Fserial%2FSerialUtils.java;h=706d579970f9456fd430d4ae2020185aa8c7ed24;hb=a359464fcf59af8abc6f69ae0e88e42adc6018df;hp=fe62d283cdceb48afc530ce239dde40ac774f06e;hpb=0988831f084e27de9927c1bb29e338e9263bfa42;p=nikiroo-utils.git diff --git a/src/be/nikiroo/utils/serial/SerialUtils.java b/src/be/nikiroo/utils/serial/SerialUtils.java index fe62d28..706d579 100644 --- a/src/be/nikiroo/utils/serial/SerialUtils.java +++ b/src/be/nikiroo/utils/serial/SerialUtils.java @@ -7,7 +7,9 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.net.URL; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UnknownFormatConversionException; @@ -64,8 +66,8 @@ public class SerialUtils { if (!SerialUtils.encode(builder, item)) { try { // use ZIP: if not - builder.append(new Exporter().append(item) - .toString(true)); + new Exporter().append(item).appendTo(builder, + true, false); } catch (NotSerializableException e) { throw new UnknownFormatConversionException(e .getMessage()); @@ -170,27 +172,68 @@ public class SerialUtils { public static Object createObject(String type) throws ClassNotFoundException, NoSuchMethodException { + String desc = null; try { Class clazz = getClass(type); String className = clazz.getName(); - Object[] args = null; + List args = new ArrayList(); + List> classes = new ArrayList>(); Constructor ctor = null; if (className.contains("$")) { - Object javaParent = createObject(className.substring(0, - className.lastIndexOf('$'))); - args = new Object[] { javaParent }; - ctor = clazz.getDeclaredConstructor(new Class[] { javaParent - .getClass() }); + for (String parentName = className.substring(0, + className.lastIndexOf('$'));; parentName = parentName + .substring(0, parentName.lastIndexOf('$'))) { + Object parent = createObject(parentName); + args.add(parent); + classes.add(parent.getClass()); + + if (!parentName.contains("$")) { + break; + } + } + + // Better error description in case there is no empty + // constructor: + desc = ""; + String end = ""; + for (Class parent = clazz; parent != null + && !parent.equals(Object.class); parent = parent + .getSuperclass()) { + if (!desc.isEmpty()) { + desc += " [:"; + end += "]"; + } + desc += parent; + } + desc += end; + // + + try { + ctor = clazz.getDeclaredConstructor(classes + .toArray(new Class[] {})); + } catch (NoSuchMethodException nsme) { + // TODO: it seems e do not always need a parameter for each + // level, so we currently try "ALL" levels or "FIRST" level + // only -> we should check the actual rule and use it + ctor = clazz.getDeclaredConstructor(classes.get(0)); + Object firstParent = args.get(0); + args.clear(); + args.add(firstParent); + } + desc = null; } else { - args = new Object[] {}; ctor = clazz.getDeclaredConstructor(); } ctor.setAccessible(true); - return ctor.newInstance(args); + return ctor.newInstance(args.toArray()); } catch (ClassNotFoundException e) { throw e; } catch (NoSuchMethodException e) { + if (desc != null) { + throw new NoSuchMethodException("Empty constructor not found: " + + desc); + } throw e; } catch (Exception e) { throw new NoSuchMethodException("Cannot instantiate: " + type); @@ -241,10 +284,8 @@ public class SerialUtils { fields = o.getClass().getDeclaredFields(); type = o.getClass().getCanonicalName(); if (type == null) { - throw new NotSerializableException( - String.format( - "Cannot find the class for this object: %s (it could be an inner class, which is not supported)", - o)); + // Anonymous inner classes support + type = o.getClass().getName(); } id = Integer.toString(hash); if (map.containsKey(hash)) { @@ -294,7 +335,13 @@ public class SerialUtils { } /** - * Encode the object into the given builder if possible (if supported). + * Encode the object into the given builder if possible and if supported. + *

+ * A supported object in this context means an object we can directly + * encode, like an Integer or a String. Custom objects and arrays are also + * considered supported, but compound objects are not supported here. + *

+ * For compound objects, you should use {@link Exporter}. * * @param builder * the builder to append to @@ -307,7 +354,9 @@ public class SerialUtils { static boolean encode(StringBuilder builder, Object value) { if (value == null) { builder.append("NULL"); - } else if (value.getClass().getCanonicalName().endsWith("[]")) { + } else if (value.getClass().getSimpleName().endsWith("[]")) { + // Simple name does support [] suffix and do not return NULL for + // inner anonymous classes return customTypes.get("[]").encode(builder, value); } else if (customTypes.containsKey(value.getClass().getCanonicalName())) { return customTypes.get(value.getClass().getCanonicalName())// @@ -343,7 +392,13 @@ public class SerialUtils { } /** - * Decode the data into an equivalent source object. + * Decode the data into an equivalent supported source object. + *

+ * A supported object in this context means an object we can directly + * encode, like an Integer or a String. Custom objects and arrays are also + * considered supported, but compound objects are not supported here. + *

+ * For compound objects, you should use {@link Importer}. * * @param encodedValue * the encoded data, cannot be NULL