Specialize CompositeValueCodec
[mdsal.git] / binding / mdsal-binding-dom-codec / src / main / java / org / opendaylight / mdsal / binding / dom / codec / impl / CompositeValueCodec.java
index ee780257fb9afe769a6765c6363c6407aa6930d4..50ff799ed774694627a49c0b3f609024851caf13 100644 (file)
@@ -7,37 +7,85 @@
  */
 package org.opendaylight.mdsal.binding.dom.codec.impl;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import static java.util.Objects.requireNonNull;
 
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.concepts.AbstractIllegalArgumentCodec;
-import org.opendaylight.yangtools.concepts.IllegalArgumentCodec;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 
-final class CompositeValueCodec extends AbstractIllegalArgumentCodec<Object, Object> {
-    private final EncapsulatedValueCodec typeObjectCodec;
-    @SuppressWarnings("rawtypes")
-    // FIXME: specialize for the two possibilities
-    private final IllegalArgumentCodec valueCodec;
+// FIXME: sealed once we have JDK17+
+abstract class CompositeValueCodec extends AbstractIllegalArgumentCodec<Object, Object> {
+    static final class OfIdentity extends CompositeValueCodec {
+        private final IdentityCodec valueCodec;
 
-    CompositeValueCodec(final Class<?> valueType, final IdentityCodec codec) {
-        typeObjectCodec = EncapsulatedValueCodec.ofUnchecked(valueType);
-        valueCodec = requireNonNull(codec);
+        OfIdentity(final Class<?> valueType, final IdentityCodec codec) {
+            super(valueType);
+            valueCodec = requireNonNull(codec);
+        }
+
+        @Override
+        Object bindingToDom(final Object bindingValue) {
+            checkArgument(bindingValue instanceof Class, "Unexpected Binding value %s", bindingValue);
+            final Class<? extends BaseIdentity> identity;
+            try {
+                identity = ((Class<?>) bindingValue).asSubclass(BaseIdentity.class);
+            } catch (ClassCastException e) {
+                throw new IllegalArgumentException("Unexpected Binding value " + bindingValue, e);
+            }
+            return valueCodec.fromBinding(identity);
+        }
+
+        @Override
+        Object domToBinding(final Object domValue) {
+            checkArgument(domValue instanceof QName, "Unexpected DOM value %s", domValue);
+            return valueCodec.toBinding((QName) domValue);
+        }
     }
 
-    CompositeValueCodec(final Class<?> valueType, final InstanceIdentifierCodec codec) {
+    static final class OfInstanceIdentifier extends CompositeValueCodec {
+        private final InstanceIdentifierCodec valueCodec;
+
+        OfInstanceIdentifier(final Class<?> valueType, final InstanceIdentifierCodec codec) {
+            super(valueType);
+            valueCodec = requireNonNull(codec);
+        }
+
+        @Override
+        Object domToBinding(final Object domValue) {
+            checkArgument(domValue instanceof YangInstanceIdentifier, "Unexpected DOM value %s", domValue);
+            final var binding = valueCodec.toBinding((YangInstanceIdentifier) domValue);
+            checkArgument(binding != null, "Cannot represent %s in binding", domValue);
+            return binding;
+        }
+
+        @Override
+        Object bindingToDom(final Object bindingValue) {
+            checkArgument(bindingValue instanceof InstanceIdentifier, "Unexpected Binding value %s", bindingValue);
+            return valueCodec.fromBinding((InstanceIdentifier<?>) bindingValue);
+        }
+    }
+
+    private final EncapsulatedValueCodec typeObjectCodec;
+
+    private CompositeValueCodec(final Class<?> valueType) {
         typeObjectCodec = EncapsulatedValueCodec.ofUnchecked(valueType);
-        valueCodec = requireNonNull(codec);
     }
 
-    @SuppressWarnings("unchecked")
     @Override
     protected Object deserializeImpl(final Object input) {
-        // FIXME: throws NPE on unrepresentable InstanceIdentifierCodec
-        return typeObjectCodec.deserialize(valueCodec.deserialize(input));
+        return typeObjectCodec.deserialize(domToBinding(input));
     }
 
-    @SuppressWarnings("unchecked")
+    abstract @NonNull Object domToBinding(@NonNull Object domValue);
+
     @Override
     protected Object serializeImpl(final Object input) {
-        return valueCodec.serialize(typeObjectCodec.serialize(input));
+        return bindingToDom(typeObjectCodec.serialize(input));
     }
+
+    abstract @NonNull Object bindingToDom(@NonNull Object bindingValue);
 }