From 64daa7fd98796351e87e8d1107e6a88d5b28ee3a Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Sun, 14 Feb 2021 14:38:42 +0100 Subject: [PATCH] Add AbstractCodecFactory.LeafrefResolver The context provided by SchemaNode is rather not nice, as it implies access through SchemaNode.getPath(). The only use case for it is leafref resolution -- hence encapsulate it, so that users can do their own thing if need be. JIRA: YANGTOOLS-1232 Change-Id: I385dceac4796e138130df32a5dad578e9ceceed1 Signed-off-by: Robert Varga --- .../data/codec/gson/JSONCodecFactory.java | 10 +++++ .../yang/data/codec/xml/XmlCodecFactory.java | 10 +++++ .../src/main/java/module-info.java | 4 ++ .../data/util/codec/AbstractCodecFactory.java | 41 +++++++++++++------ 4 files changed, 52 insertions(+), 13 deletions(-) diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodecFactory.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodecFactory.java index aaa6730195..e3fee0126e 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodecFactory.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONCodecFactory.java @@ -7,6 +7,8 @@ */ package org.opendaylight.yangtools.yang.data.codec.gson; +import static com.google.common.base.Verify.verifyNotNull; + import com.google.common.annotations.Beta; import java.util.List; import org.eclipse.jdt.annotation.NonNull; @@ -22,6 +24,7 @@ import org.opendaylight.yangtools.yang.data.util.codec.AbstractCodecFactory; import org.opendaylight.yangtools.yang.data.util.codec.CodecCache; import org.opendaylight.yangtools.yang.data.util.codec.LazyCodecCache; import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; +import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode; import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition; @@ -41,6 +44,7 @@ import org.opendaylight.yangtools.yang.model.api.type.Uint64TypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.Uint8TypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.UnknownTypeDefinition; +import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil; /** * Factory for creating JSON equivalents of codecs. Each instance of this object is bound to @@ -163,4 +167,10 @@ public abstract class JSONCodecFactory extends AbstractCodecFactory abstract JSONCodec wrapDecimalCodec(DecimalStringCodec decimalCodec); abstract JSONCodec wrapIntegerCodec(AbstractIntegerStringCodec integerCodec); + + final JSONCodec codecFor(final TypedDataSchemaNode currentNode) { + return codecFor(currentNode, type -> verifyNotNull( + SchemaContextUtil.getBaseTypeForLeafRef(type, getEffectiveModelContext(), currentNode), + "Unable to find base type for leafref node %s type %s.", currentNode, type)); + } } diff --git a/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/XmlCodecFactory.java b/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/XmlCodecFactory.java index c63009f8f9..18a2d4c4da 100644 --- a/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/XmlCodecFactory.java +++ b/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/XmlCodecFactory.java @@ -8,6 +8,7 @@ package org.opendaylight.yangtools.yang.data.codec.xml; +import static com.google.common.base.Verify.verifyNotNull; import static java.util.Objects.requireNonNull; import com.google.common.annotations.Beta; @@ -25,6 +26,8 @@ import org.opendaylight.yangtools.yang.data.impl.codec.StringStringCodec; import org.opendaylight.yangtools.yang.data.util.codec.AbstractCodecFactory; import org.opendaylight.yangtools.yang.data.util.codec.SharedCodecCache; import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; +import org.opendaylight.yangtools.yang.model.api.SchemaNode; +import org.opendaylight.yangtools.yang.model.api.TypeAware; import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition; @@ -44,6 +47,7 @@ import org.opendaylight.yangtools.yang.model.api.type.Uint64TypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.Uint8TypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.UnknownTypeDefinition; +import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil; /** * A thread-safe factory for instantiating {@link XmlCodec}s. @@ -175,4 +179,10 @@ public final class XmlCodecFactory extends AbstractCodecFactory> { protected XmlCodec unknownCodec(final UnknownTypeDefinition type) { return NullXmlCodec.INSTANCE; } + + XmlCodec codecFor(final T currentNode) { + return codecFor(currentNode, type -> verifyNotNull( + SchemaContextUtil.getBaseTypeForLeafRef(type, getEffectiveModelContext(), currentNode), + "Unable to find base type for leafref node %s type %s.", currentNode, type)); + } } diff --git a/yang/yang-data-util/src/main/java/module-info.java b/yang/yang-data-util/src/main/java/module-info.java index 8622745076..10d1095687 100644 --- a/yang/yang-data-util/src/main/java/module-info.java +++ b/yang/yang-data-util/src/main/java/module-info.java @@ -13,8 +13,12 @@ module org.opendaylight.yangtools.yang.data.util { requires transitive org.opendaylight.yangtools.rfc7952.data.api; requires transitive org.opendaylight.yangtools.rfc8528.data.api; + requires com.google.common; requires org.opendaylight.yangtools.yang.model.spi; requires org.opendaylight.yangtools.yang.model.util; requires org.opendaylight.yangtools.util; requires org.slf4j; + + // Annotations + requires static org.eclipse.jdt.annotation; } diff --git a/yang/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/codec/AbstractCodecFactory.java b/yang/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/codec/AbstractCodecFactory.java index 22e4d82cbc..d5103ae6a3 100644 --- a/yang/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/codec/AbstractCodecFactory.java +++ b/yang/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/codec/AbstractCodecFactory.java @@ -10,6 +10,7 @@ package org.opendaylight.yangtools.yang.data.util.codec; import static com.google.common.base.Verify.verifyNotNull; import static java.util.Objects.requireNonNull; +import com.google.common.annotations.Beta; import java.util.ArrayList; import java.util.List; import org.eclipse.jdt.annotation.NonNull; @@ -39,7 +40,6 @@ import org.opendaylight.yangtools.yang.model.api.type.Uint8TypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.UnknownTypeDefinition; import org.opendaylight.yangtools.yang.model.spi.AbstractEffectiveModelContextProvider; -import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -53,6 +53,21 @@ import org.slf4j.LoggerFactory; */ public abstract class AbstractCodecFactory> extends AbstractEffectiveModelContextProvider { + /** + * Helper interface aiding resolution of leafref chains. + */ + @Beta + @FunctionalInterface + public interface LeafrefResolver { + /** + * Resolve specified {@link LeafrefTypeDefinition}. + * + * @param type leafref definition + * @return Resolved type + */ + @NonNull TypeDefinition resolveLeafref(@NonNull LeafrefTypeDefinition type); + } + private static final Logger LOG = LoggerFactory.getLogger(AbstractCodecFactory.class); private final @NonNull CodecCache cache; @@ -63,7 +78,8 @@ public abstract class AbstractCodecFactory> this.cache = requireNonNull(cache); } - public final @NonNull T codecFor(final S schema) { + public final @NonNull T codecFor(final S schema, + final LeafrefResolver resolver) { /* * There are many trade-offs to be made here. We need the common case being as fast as possible while reusing * codecs as much as possible. @@ -96,7 +112,7 @@ public abstract class AbstractCodecFactory> } // ... and complex types afterwards - ret = createComplexCodecFor(schema, type); + ret = createComplexCodecFor(schema, type, resolver); LOG.trace("Type {} miss complex {}", type, ret); return cache.getComplex(schema, ret); } @@ -208,16 +224,14 @@ public abstract class AbstractCodecFactory> return true; } - private T createComplexCodecFor(final SchemaNode schema, final TypeDefinition type) { + private T createComplexCodecFor(final SchemaNode schema, final TypeDefinition type, + final LeafrefResolver resolver) { if (type instanceof UnionTypeDefinition) { - return createComplexUnion(schema, (UnionTypeDefinition) type); + return createComplexUnion(schema, (UnionTypeDefinition) type, resolver); } else if (type instanceof LeafrefTypeDefinition) { - final TypeDefinition target = SchemaContextUtil.getBaseTypeForLeafRef((LeafrefTypeDefinition) type, - getEffectiveModelContext(), schema); - verifyNotNull(target, "Unable to find base type for leafref node %s type %s.", schema, target); - + final TypeDefinition target = resolver.resolveLeafref((LeafrefTypeDefinition) type); final T ret = getSimpleCodecFor(target); - return ret != null ? ret : createComplexCodecFor(schema, target); + return ret != null ? ret : createComplexCodecFor(schema, target, resolver); } else if (type instanceof IdentityrefTypeDefinition) { return identityRefCodec((IdentityrefTypeDefinition) type, schema.getQName().getModule()); } else { @@ -241,7 +255,8 @@ public abstract class AbstractCodecFactory> return unionCodec(union, codecs); } - private T createComplexUnion(final SchemaNode schema, final UnionTypeDefinition union) { + private T createComplexUnion(final SchemaNode schema, final UnionTypeDefinition union, + final LeafrefResolver resolver) { final List> types = union.getTypes(); final List codecs = new ArrayList<>(types.size()); @@ -250,11 +265,11 @@ public abstract class AbstractCodecFactory> if (codec == null) { codec = getSimpleCodecFor(type); if (codec == null) { - codec = createComplexCodecFor(schema, type); + codec = createComplexCodecFor(schema, type, resolver); } } - codecs.add(verifyNotNull(codec, "Schema %s subtype %s has no codec", schema, type)); + codecs.add(verifyNotNull(codec, "Type %s has no codec", schema, type)); } return unionCodec(union, codecs); -- 2.36.6