X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=binding%2Fmdsal-binding-dom-codec%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fbinding%2Fdom%2Fcodec%2Fimpl%2FBitsCodec.java;h=a9adc30bdb2abbe8b2c7ddf6e85b524e12f54edb;hb=0d3b1b5bf1eb3e28b198496facb03d1653a92d22;hp=700986738d2db70beda3ed9fd566fbbc66c0ac6c;hpb=c241dcfa5322ac10810a1068ccd2eb57f6f2dbb2;p=mdsal.git diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BitsCodec.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BitsCodec.java index 700986738d..a9adc30bdb 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BitsCodec.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BitsCodec.java @@ -7,7 +7,11 @@ */ package org.opendaylight.mdsal.binding.dom.codec.impl; -import com.google.common.base.Preconditions; +import static com.google.common.base.Preconditions.checkArgument; +import static java.util.Objects.requireNonNull; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import java.lang.invoke.MethodHandle; @@ -23,36 +27,49 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; -import java.util.concurrent.Callable; -import org.opendaylight.mdsal.binding.dom.codec.impl.ValueTypeCodec.SchemaUnawareCodec; +import java.util.concurrent.ExecutionException; +import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.mdsal.binding.spec.naming.BindingMapping; import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit; -final class BitsCodec extends ReflectionBasedCodec implements SchemaUnawareCodec { +// FIXME: 'SchemaUnawareCodec' is not correct: we use BitsTypeDefinition in construction +final class BitsCodec extends ValueTypeCodec implements SchemaUnawareCodec { + /* + * Use identity comparison for keys and allow classes to be GCd themselves. + * + * Since codecs can (and typically do) hold a direct or indirect strong reference to the class, they need to be also + * accessed via reference. Using a weak reference could be problematic, because the codec would quite often be only + * weakly reachable. We therefore use a soft reference, whose implementation guidance is suitable to our use case: + * + * "Virtual machine implementations are, however, encouraged to bias against clearing recently-created or + * recently-used soft references." + */ + private static final Cache, @NonNull BitsCodec> CACHE = CacheBuilder.newBuilder().weakKeys().softValues() + .build(); private static final MethodType CONSTRUCTOR_INVOKE_TYPE = MethodType.methodType(Object.class, Boolean[].class); // Ordered by position - private final Map getters; + private final ImmutableMap getters; // Ordered by lexical name - private final Set ctorArgs; + private final ImmutableSet ctorArgs; private final MethodHandle ctor; - private BitsCodec(final Class typeClass, final MethodHandle ctor, final Set ctorArgs, - final Map getters) { - super(typeClass); - this.ctor = Preconditions.checkNotNull(ctor); + private BitsCodec(final MethodHandle ctor, final Set ctorArgs, final Map getters) { + this.ctor = requireNonNull(ctor); this.ctorArgs = ImmutableSet.copyOf(ctorArgs); this.getters = ImmutableMap.copyOf(getters); } - static Callable loader(final Class returnType, final BitsTypeDefinition rootType) { - return () -> { + static @NonNull BitsCodec of(final Class returnType, final BitsTypeDefinition rootType) + throws ExecutionException { + return CACHE.get(returnType, () -> { final Map getters = new LinkedHashMap<>(); final Set ctorArgs = new TreeSet<>(); for (Bit bit : rootType.getBits()) { - final Method valueGetter = returnType.getMethod("is" + BindingMapping.getClassName(bit.getName())); + final Method valueGetter = returnType.getMethod(BindingMapping.GETTER_PREFIX + + BindingMapping.getClassName(bit.getName())); ctorArgs.add(bit.getName()); getters.put(bit.getName(), valueGetter); } @@ -65,14 +82,14 @@ final class BitsCodec extends ReflectionBasedCodec implements SchemaUnawareCodec final MethodHandle ctor = MethodHandles.publicLookup().unreflectConstructor(constructor) .asSpreader(Boolean[].class, ctorArgs.size()).asType(CONSTRUCTOR_INVOKE_TYPE); - return new BitsCodec(returnType, ctor, ctorArgs, getters); - }; + return new BitsCodec(ctor, ctorArgs, getters); + }); } @Override @SuppressWarnings("checkstyle:illegalCatch") public Object deserialize(final Object input) { - Preconditions.checkArgument(input instanceof Set); + checkArgument(input instanceof Set); @SuppressWarnings("unchecked") final Set casted = (Set) input;