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%2FCodecDataObjectGenerator.java;h=2603faec760789129900be2d6d9e560947b5b2aa;hb=refs%2Fchanges%2F34%2F100534%2F1;hp=46cd63f35f0f51c7224ed2deff98647e7f5fdd03;hpb=9d0e430e7f936148bf1fe23744b7190a808f09cc;p=mdsal.git diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObjectGenerator.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObjectGenerator.java index 46cd63f35f..2603faec76 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObjectGenerator.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObjectGenerator.java @@ -10,29 +10,21 @@ package org.opendaylight.mdsal.binding.dom.codec.impl; import static com.google.common.base.Verify.verify; import static com.google.common.base.Verify.verifyNotNull; import static java.util.Objects.requireNonNull; -import static org.opendaylight.mdsal.binding.dom.codec.impl.ByteBuddyUtils.THIS; +import static net.bytebuddy.implementation.bytecode.member.MethodVariableAccess.loadThis; import static org.opendaylight.mdsal.binding.dom.codec.impl.ByteBuddyUtils.getField; import static org.opendaylight.mdsal.binding.dom.codec.impl.ByteBuddyUtils.invokeMethod; import static org.opendaylight.mdsal.binding.dom.codec.impl.ByteBuddyUtils.putField; -import com.google.common.base.MoreObjects.ToStringHelper; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.VarHandle; import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Objects; import java.util.Optional; import net.bytebuddy.ByteBuddy; import net.bytebuddy.description.field.FieldDescription; -import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDefinition; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription.ForLoadedType; @@ -40,19 +32,13 @@ import net.bytebuddy.description.type.TypeDescription.Generic; import net.bytebuddy.dynamic.DynamicType.Builder; import net.bytebuddy.dynamic.scaffold.InstrumentedType; import net.bytebuddy.implementation.Implementation; -import net.bytebuddy.implementation.Implementation.Context; -import net.bytebuddy.implementation.bytecode.Addition; import net.bytebuddy.implementation.bytecode.ByteCodeAppender; -import net.bytebuddy.implementation.bytecode.Multiplication; import net.bytebuddy.implementation.bytecode.StackManipulation; import net.bytebuddy.implementation.bytecode.assign.TypeCasting; import net.bytebuddy.implementation.bytecode.constant.ClassConstant; -import net.bytebuddy.implementation.bytecode.constant.IntegerConstant; import net.bytebuddy.implementation.bytecode.constant.TextConstant; import net.bytebuddy.implementation.bytecode.member.MethodReturn; import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess; -import net.bytebuddy.jar.asm.Label; -import net.bytebuddy.jar.asm.MethodVisitor; import net.bytebuddy.jar.asm.Opcodes; import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.mdsal.binding.dom.codec.impl.ClassGeneratorBridge.LocalNameProvider; @@ -60,6 +46,7 @@ import org.opendaylight.mdsal.binding.dom.codec.impl.ClassGeneratorBridge.NodeCo import org.opendaylight.mdsal.binding.dom.codec.loader.CodecClassLoader; import org.opendaylight.mdsal.binding.dom.codec.loader.CodecClassLoader.ClassGenerator; import org.opendaylight.mdsal.binding.dom.codec.loader.CodecClassLoader.GeneratorResult; +import org.opendaylight.mdsal.binding.spec.naming.BindingMapping; import org.opendaylight.yangtools.yang.binding.DataObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -95,7 +82,7 @@ import org.slf4j.LoggerFactory; * private static final VarHandle getBar$$$V; * private volatile Object getBar; * - * public Foo$$$codecImpl(NormalizedNodeContainer data) { + * public Foo$$$codecImpl(DistinctNodeContainer data) { * super(data); * } * @@ -165,8 +152,8 @@ import org.slf4j.LoggerFactory; */ abstract class CodecDataObjectGenerator> implements ClassGenerator { // Not reusable definition: we can inline NodeContextSuppliers without a problem - // FIXME: 6.0.0: wire this implementation, which requires that BindingRuntimeTypes provides information about types - // being generated from within a grouping + // FIXME: MDSAL-443: wire this implementation, which requires that BindingRuntimeTypes provides information about + // types being generated from within a grouping private static final class Fixed> extends CodecDataObjectGenerator implements NodeContextSupplierProvider { private final ImmutableMap properties; @@ -190,11 +177,6 @@ abstract class CodecDataObjectGenerator> implements return tmp; } - @Override - ArrayList getterMethods() { - return new ArrayList<>(properties.keySet()); - } - @Override public NodeContextSupplier resolveNodeContextSupplier(final String methodName) { final Optional> found = properties.entrySet().stream() @@ -239,14 +221,6 @@ abstract class CodecDataObjectGenerator> implements return tmp; } - @Override - ArrayList getterMethods() { - final ArrayList ret = new ArrayList<>(simpleProperties.size() + daoProperties.size()); - ret.addAll(simpleProperties.keySet()); - ret.addAll(daoProperties.keySet()); - return ret; - } - @Override public String resolveLocalName(final String methodName) { final Optional> found = simpleProperties.entrySet().stream() @@ -258,19 +232,11 @@ abstract class CodecDataObjectGenerator> implements private static final Logger LOG = LoggerFactory.getLogger(CodecDataObjectGenerator.class); private static final Generic BB_BOOLEAN = TypeDefinition.Sort.describe(boolean.class); - private static final Generic BB_DATAOBJECT = TypeDefinition.Sort.describe(DataObject.class); - private static final Generic BB_HELPER = TypeDefinition.Sort.describe(ToStringHelper.class); + private static final Generic BB_OBJECT = TypeDefinition.Sort.describe(Object.class); private static final Generic BB_INT = TypeDefinition.Sort.describe(int.class); + private static final Generic BB_STRING = TypeDefinition.Sort.describe(String.class); private static final TypeDescription BB_CDO = ForLoadedType.of(CodecDataObject.class); private static final TypeDescription BB_ACDO = ForLoadedType.of(AugmentableCodecDataObject.class); - private static final Comparator METHOD_BY_ALPHABET = Comparator.comparing(Method::getName); - - private static final StackManipulation ARRAYS_EQUALS = invokeMethod(Arrays.class, "equals", - byte[].class, byte[].class); - private static final StackManipulation OBJECTS_EQUALS = invokeMethod(Objects.class, "equals", - Object.class, Object.class); - private static final StackManipulation HELPER_ADD = invokeMethod(ToStringHelper.class, "add", - String.class, Object.class); private static final StackManipulation FIRST_ARG_REF = MethodVariableAccess.REFERENCE.loadFrom(1); @@ -310,7 +276,7 @@ abstract class CodecDataObjectGenerator> implements final Generic bindingDef = TypeDefinition.Sort.describe(bindingInterface); @SuppressWarnings("unchecked") Builder builder = (Builder) BB.subclass(Generic.Builder.parameterizedType(superClass, bindingDef).build()) - .visit(ByteBuddyUtils.computeFrames()).name(fqcn).implement(bindingDef); + .name(fqcn).implement(bindingDef); builder = generateGetters(builder); @@ -322,79 +288,46 @@ abstract class CodecDataObjectGenerator> implements new KeyMethodImplementation(methodName, retType)); } - // Index all property methods, turning them into "getFoo()" invocations, retaining order. We will be using - // those invocations in each of the three methods. Note that we do not glue the invocations to 'this', as we - // will be invoking them on 'other' in codecEquals() - final ArrayList properties = getterMethods(); - // Make sure properties are alpha-sorted - properties.sort(METHOD_BY_ALPHABET); - final ImmutableMap methods = Maps.uniqueIndex(properties, - ByteBuddyUtils::invokeMethod); - // Final bits: return GeneratorResult.of(builder // codecHashCode() ... .defineMethod("codecHashCode", BB_INT, PROT_FINAL) - .intercept(new Implementation.Simple(new CodecHashCode(methods))) - // ... codecEquals() ... - .defineMethod("codecEquals", BB_BOOLEAN, PROT_FINAL).withParameter(BB_DATAOBJECT) - .intercept(codecEquals(methods)) - // ... and codecFillToString() ... - .defineMethod("codecFillToString", BB_HELPER, PROT_FINAL).withParameter(BB_HELPER) - .intercept(codecFillToString(methods)) + .intercept(codecHashCode(bindingInterface)) + // ... equals(Object) ... + .defineMethod("codecEquals", BB_BOOLEAN, PROT_FINAL).withParameter(BB_OBJECT) + .intercept(codecEquals(bindingInterface)) + // ... toString() ... + .defineMethod("toString", BB_STRING, PUB_FINAL) + .intercept(toString(bindingInterface)) // ... and build it .make()); } abstract Builder generateGetters(Builder builder); - abstract ArrayList getterMethods(); - - private static Implementation codecEquals(final ImmutableMap properties) { - // Label for 'return false;' - final Label falseLabel = new Label(); - // Condition for 'if (!...)' - final StackManipulation ifFalse = ByteBuddyUtils.ifEq(falseLabel); - - final List manipulations = new ArrayList<>(properties.size() * 6 + 5); - for (Entry entry : properties.entrySet()) { - // if (!java.util.(Objects|Arrays).equals(getFoo(), other.getFoo())) { - // return false; - // } - manipulations.add(THIS); - manipulations.add(entry.getKey()); - manipulations.add(FIRST_ARG_REF); - manipulations.add(entry.getKey()); - manipulations.add(entry.getValue().getReturnType().isArray() ? ARRAYS_EQUALS : OBJECTS_EQUALS); - manipulations.add(ifFalse); - } - - // return true; - manipulations.add(IntegerConstant.ONE); - manipulations.add(MethodReturn.INTEGER); - // L0: return false; - manipulations.add(ByteBuddyUtils.markLabel(falseLabel)); - manipulations.add(IntegerConstant.ZERO); - manipulations.add(MethodReturn.INTEGER); - - return new Implementation.Simple(manipulations.toArray(new StackManipulation[0])); + private static Implementation codecHashCode(final Class bindingInterface) { + return new Implementation.Simple( + // return Foo.bindingHashCode(this); + loadThis(), + invokeMethod(bindingInterface, BindingMapping.BINDING_HASHCODE_NAME, bindingInterface), + MethodReturn.INTEGER); } - private static Implementation codecFillToString(final ImmutableMap properties) { - final List manipulations = new ArrayList<>(properties.size() * 4 + 2); - // push 'return helper' to stack... - manipulations.add(FIRST_ARG_REF); - for (Entry entry : properties.entrySet()) { - // .add("getFoo", getFoo()) - manipulations.add(new TextConstant(entry.getValue().getName())); - manipulations.add(THIS); - manipulations.add(entry.getKey()); - manipulations.add(HELPER_ADD); - } - // ... execute 'return helper' - manipulations.add(MethodReturn.REFERENCE); + private static Implementation codecEquals(final Class bindingInterface) { + return new Implementation.Simple( + // return Foo.bindingEquals(this, obj); + loadThis(), + FIRST_ARG_REF, + invokeMethod(bindingInterface, BindingMapping.BINDING_EQUALS_NAME, bindingInterface, Object.class), + MethodReturn.INTEGER); + } - return new Implementation.Simple(manipulations.toArray(new StackManipulation[0])); + private static Implementation toString(final Class bindingInterface) { + return new Implementation.Simple( + // return Foo.bindingToString(this); + loadThis(), + invokeMethod(bindingInterface, BindingMapping.BINDING_TO_STRING_NAME, bindingInterface), + MethodReturn.REFERENCE); } private abstract static class AbstractMethodImplementation implements Implementation { @@ -453,7 +386,7 @@ abstract class CodecDataObjectGenerator> implements public ByteCodeAppender appender(final Target implementationTarget) { return new ByteCodeAppender.Simple( // return (FooType) codecKey(getFoo$$$V); - THIS, + loadThis(), getField(implementationTarget.getInstrumentedType(), handleName), CODEC_KEY, TypeCasting.to(retType), @@ -501,7 +434,7 @@ abstract class CodecDataObjectGenerator> implements final TypeDescription instrumentedType = implementationTarget.getInstrumentedType(); return new ByteCodeAppender.Simple( // return (FooType) codecMember(getFoo$$$V, getFoo$$$S); - THIS, + loadThis(), getField(instrumentedType, handleName), getField(instrumentedType, stringName), CODEC_MEMBER, @@ -526,7 +459,7 @@ abstract class CodecDataObjectGenerator> implements public ByteCodeAppender appender(final Target implementationTarget) { return new ByteCodeAppender.Simple( // return (FooType) codecMember(getFoo$$$V, FooType.class); - THIS, + loadThis(), getField(implementationTarget.getInstrumentedType(), handleName), ClassConstant.of(TypeDefinition.Sort.describe(bindingClass).asErasure()), CODEC_MEMBER, @@ -568,7 +501,7 @@ abstract class CodecDataObjectGenerator> implements final TypeDescription instrumentedType = implementationTarget.getInstrumentedType(); return new ByteCodeAppender.Simple( // return (FooType) codecMember(getFoo$$$V, getFoo$$$C); - THIS, + loadThis(), getField(instrumentedType, handleName), getField(instrumentedType, contextName), CODEC_MEMBER, @@ -576,46 +509,4 @@ abstract class CodecDataObjectGenerator> implements MethodReturn.REFERENCE); } } - - private static final class CodecHashCode implements ByteCodeAppender { - private static final StackManipulation THIRTY_ONE = IntegerConstant.forValue(31); - private static final StackManipulation LOAD_RESULT = MethodVariableAccess.INTEGER.loadFrom(1); - private static final StackManipulation STORE_RESULT = MethodVariableAccess.INTEGER.storeAt(1); - private static final StackManipulation ARRAYS_HASHCODE = invokeMethod(Arrays.class, "hashCode", byte[].class); - private static final StackManipulation OBJECTS_HASHCODE = invokeMethod(Objects.class, "hashCode", Object.class); - - private final ImmutableMap properties; - - CodecHashCode(final ImmutableMap properties) { - this.properties = requireNonNull(properties); - } - - @Override - public Size apply(final MethodVisitor methodVisitor, final Context implementationContext, - final MethodDescription instrumentedMethod) { - final List manipulations = new ArrayList<>(properties.size() * 8 + 4); - // int result = 1; - manipulations.add(IntegerConstant.ONE); - manipulations.add(STORE_RESULT); - - for (Entry entry : properties.entrySet()) { - // result = 31 * result + java.util.(Objects,Arrays).hashCode(getFoo()); - manipulations.add(THIRTY_ONE); - manipulations.add(LOAD_RESULT); - manipulations.add(Multiplication.INTEGER); - manipulations.add(THIS); - manipulations.add(entry.getKey()); - manipulations.add(entry.getValue().getReturnType().isArray() ? ARRAYS_HASHCODE : OBJECTS_HASHCODE); - manipulations.add(Addition.INTEGER); - manipulations.add(STORE_RESULT); - } - // return result; - manipulations.add(LOAD_RESULT); - manipulations.add(MethodReturn.INTEGER); - - StackManipulation.Size operandStackSize = new StackManipulation.Compound(manipulations) - .apply(methodVisitor, implementationContext); - return new Size(operandStackSize.getMaximalSize(), instrumentedMethod.getStackSize() + 1); - } - } }