BUG-6238: Remove char[]-based union instantiation path
[mdsal.git] / binding / mdsal-binding-dom-codec / src / main / java / org / opendaylight / yangtools / binding / data / codec / impl / UnionTypeCodec.java
index 00702f07296d5e92d886d9020a746f9d67e3bd3a..ee161a9b537a9cb1288e540ec621da799cd10523 100644 (file)
@@ -8,76 +8,55 @@
 package org.opendaylight.yangtools.binding.data.codec.impl;
 
 import com.google.common.collect.ImmutableSet;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.Set;
 import java.util.concurrent.Callable;
 import org.opendaylight.yangtools.concepts.Codec;
 import org.opendaylight.yangtools.yang.binding.BindingMapping;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
-import org.opendaylight.yangtools.yang.model.util.UnionType;
 
 final class UnionTypeCodec extends ReflectionBasedCodec {
-
     private final ImmutableSet<UnionValueOptionContext> typeCodecs;
-    private final Constructor<?> charConstructor;
 
     private UnionTypeCodec(final Class<?> unionCls,final Set<UnionValueOptionContext> codecs) {
         super(unionCls);
-        try {
-            charConstructor = unionCls.getConstructor(char[].class);
-            typeCodecs = ImmutableSet.copyOf(codecs);
-        } catch (NoSuchMethodException | SecurityException e) {
-           throw new IllegalStateException("Required constructor is not available.",e);
-        }
+        typeCodecs = ImmutableSet.copyOf(codecs);
     }
 
-    static Callable<UnionTypeCodec> loader(final Class<?> unionCls, final UnionTypeDefinition unionType) {
-        return new Callable<UnionTypeCodec>() {
-            @Override
-            public UnionTypeCodec call() throws NoSuchMethodException, SecurityException {
-                Set<UnionValueOptionContext> values = new HashSet<>();
-                for(TypeDefinition<?> subtype : unionType.getTypes()) {
-                    String methodName = "get" + BindingMapping.getClassName(subtype.getQName());
-                    Method valueGetter = unionCls.getMethod(methodName);
-                    Class<?> valueType = valueGetter.getReturnType();
-                    Codec<Object, Object> valueCodec = UnionTypeCodec.getCodecForType(valueType, subtype);
-                    values.add(new UnionValueOptionContext(valueType,valueGetter, valueCodec));
-                }
-                return new UnionTypeCodec(unionCls, values);
+    static Callable<UnionTypeCodec> loader(final Class<?> unionCls, final UnionTypeDefinition unionType,
+                                           final BindingCodecContext bindingCodecContext) {
+        return () -> {
+            final Set<UnionValueOptionContext> values = new LinkedHashSet<>();
+            for (TypeDefinition<?> subtype : unionType.getTypes()) {
+                Method valueGetter = unionCls.getMethod("get" + BindingMapping.getClassName(subtype.getQName()));
+                Class<?> valueType = valueGetter.getReturnType();
+                Codec<Object, Object> valueCodec = bindingCodecContext.getCodec(valueType, subtype);
+                values.add(new UnionValueOptionContext(unionCls, valueType, valueGetter, valueCodec));
             }
+            return new UnionTypeCodec(unionCls, values);
         };
     }
 
-    private static Codec<Object, Object> getCodecForType(final Class<?> valueType, final TypeDefinition<?> subtype) {
-        if (subtype.getBaseType() instanceof UnionType) {
-            try {
-                return UnionTypeCodec.loader(valueType, (UnionType) subtype.getBaseType()).call();
-            } catch (final Exception e) {
-                throw new IllegalStateException("Could not construct Union Type Codec");
-            }
-        } else {
-            return ValueTypeCodec.getCodecFor(valueType, subtype);
-        }
-    }
-
     @Override
     public Object deserialize(final Object input) {
-        try {
-            return charConstructor.newInstance((input.toString().toCharArray()));
-        } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
-            throw new IllegalStateException("Could not construct instance",e);
+        for (UnionValueOptionContext member : typeCodecs) {
+            final Object ret = member.deserializeUnion(input);
+            if (ret != null) {
+                return ret;
+            }
         }
+
+        throw new IllegalArgumentException(String.format("Failed to construct instance of %s for input %s",
+            getTypeClass(), input));
     }
 
     @Override
     public Object serialize(final Object input) {
         if (input != null) {
             for (UnionValueOptionContext valCtx : typeCodecs) {
-                Object domValue = valCtx.serialize(input);
+                final Object domValue = valCtx.serialize(input);
                 if (domValue != null) {
                     return domValue;
                 }
@@ -85,5 +64,4 @@ final class UnionTypeCodec extends ReflectionBasedCodec {
         }
         return null;
     }
-
 }