From 02ea05eaf6524fba5efee8b1a68c26c9b632d91b Mon Sep 17 00:00:00 2001 From: andreoss Date: Wed, 2 Sep 2020 16:30:45 -0400 Subject: [PATCH] (#179) Handle multiple constructors correctly --- .../com/jcabi/http/request/BaseRequest.java | 120 ++++++++++++------ 1 file changed, 81 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/jcabi/http/request/BaseRequest.java b/src/main/java/com/jcabi/http/request/BaseRequest.java index 6273f429..dc488a39 100644 --- a/src/main/java/com/jcabi/http/request/BaseRequest.java +++ b/src/main/java/com/jcabi/http/request/BaseRequest.java @@ -280,45 +280,11 @@ public Response fetch(final InputStream stream) throws IOException { } @Override - public Request through(final Class type, - final Object... args) { - Constructor ctor = null; - for (final Constructor opt : type.getDeclaredConstructors()) { - final Class[] types = opt.getParameterTypes(); - if (types.length == args.length + 1) { - boolean match = true; - for (int i = 1; i < types.length && match; i++) { - Class arg = types[i]; - if (types[i].isPrimitive()) { - arg = ClassUtil.wrapperType(arg); - } - match = arg.isAssignableFrom(args[i - 1].getClass()); - } - if (match) { - ctor = opt; - break; - } - } - } - if (ctor == null) { - throw new IllegalArgumentException( - String.format( - "class %s doesn't have a ctor with %d argument(s)", - type.getName(), args.length - ) - ); - } - final Object[] params = new Object[args.length + 1]; - params[0] = this.wire; - System.arraycopy(args, 0, params, 1, args.length); - final Wire decorated; - try { - decorated = Wire.class.cast(ctor.newInstance(params)); - } catch (final InstantiationException - | IllegalAccessException | InvocationTargetException ex) { - throw new IllegalStateException(ex); - } - return this.through(decorated); + public Request through( + final Class type, + final Object... args + ) { + return this.through(this.mkWire(type, args)); } @Override @@ -358,6 +324,32 @@ public String toString() { .toString(); } + /** + * Create an instance of Wire. + * + * @param type Type of Wire. + * @param args Ctor arguments. + * @param Type of Wire. + * @return An instance of Wire + */ + private Wire mkWire( + final Class type, + final Object... args + ) { + final Constructor ctor = BaseRequest.findCtor(type, args); + final Object[] params = new Object[args.length + 1]; + params[0] = this.wire; + System.arraycopy(args, 0, params, 1, args.length); + final Wire decorated; + try { + decorated = Wire.class.cast(ctor.newInstance(params)); + } catch (final InstantiationException + | IllegalAccessException | InvocationTargetException ex) { + throw new IllegalStateException(ex); + } + return decorated; + } + /** * Fetch response from server. * @param stream The content to send. @@ -403,6 +395,56 @@ private static URI createUri(final String uri) { return addr; } + /** + * Find a ctor which match arguments. + * @param type A type. + * @param args Ctor arguments. + * @param Type of object + * @return A proper ctor for args. + */ + private static Constructor findCtor( + final Class type, final Object... args + ) { + Constructor ctor = null; + for (final Constructor opt : type.getDeclaredConstructors()) { + final Class[] types = opt.getParameterTypes(); + if (types.length == args.length + 1) { + boolean match = true; + for (int inx = 1; inx < types.length && match; ++inx) { + match = BaseRequest + .wrappedIfNeeded(types[inx]) + .isAssignableFrom(args[inx - 1].getClass()); + } + if (match) { + ctor = opt; + break; + } + } + } + if (ctor == null) { + throw new IllegalArgumentException( + String.format( + "class %s doesn't have a ctor with %d argument(s)", + type.getName(), args.length + ) + ); + } + return ctor; + } + + /** + * Wrap primitive types. + * @param type A type which could be primitive + * @return Wrapped type if it was a primitive + */ + private static Class wrappedIfNeeded(final Class type) { + Class arg = type; + if (arg.isPrimitive()) { + arg = ClassUtil.wrapperType(arg); + } + return arg; + } + /** * Base URI. *