X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-data-codec-gson%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fdata%2Fcodec%2Fgson%2FJSONCodecFactory.java;h=aaa67301959ca07ec457108de875cd5a8f889889;hb=5280e8d0efe5177e5bd9fa15bfd2bdc01e222d1b;hp=c5840cff986b359c5f4271a29c8a5fa6829e0eb6;hpb=3f09a1e6f8819533a043cf3c6677f4b4b546bc29;p=yangtools.git 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 c5840cff98..aaa6730195 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 @@ -8,140 +8,159 @@ package org.opendaylight.yangtools.yang.data.codec.gson; import com.google.common.annotations.Beta; -import com.google.common.base.Preconditions; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.gson.stream.JsonWriter; -import java.io.IOException; -import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec; -import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; -import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; -import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; -import org.opendaylight.yangtools.yang.model.api.TypeDefinition; -import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition; -import org.opendaylight.yangtools.yang.model.util.IdentityrefType; -import org.opendaylight.yangtools.yang.model.util.InstanceIdentifierType; -import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import java.util.List; +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.data.impl.codec.AbstractIntegerStringCodec; +import org.opendaylight.yangtools.yang.data.impl.codec.BinaryStringCodec; +import org.opendaylight.yangtools.yang.data.impl.codec.BitsStringCodec; +import org.opendaylight.yangtools.yang.data.impl.codec.BooleanStringCodec; +import org.opendaylight.yangtools.yang.data.impl.codec.DecimalStringCodec; +import org.opendaylight.yangtools.yang.data.impl.codec.EnumStringCodec; +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.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.type.BinaryTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.Int16TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.Int32TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.Int64TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.Int8TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.Uint16TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.Uint32TypeDefinition; +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; /** * Factory for creating JSON equivalents of codecs. Each instance of this object is bound to - * a particular {@link SchemaContext}, but can be reused by multiple {@link JSONNormalizedNodeStreamWriter}s. + * a particular {@link EffectiveModelContext}, but can be reused by multiple {@link JSONNormalizedNodeStreamWriter}s. */ @Beta -public final class JSONCodecFactory { - private static final Logger LOG = LoggerFactory.getLogger(JSONCodecFactory.class); - private static final JSONCodec NULL_CODEC = new JSONCodec() { - @Override - public Object deserialize(final String input) { - return null; - } - - @Override - public String serialize(final Object input) { - return null; - } - - @Override - public boolean needQuotes() { - return false; - } - - @Override - public void serializeToWriter(JsonWriter writer, Object value) throws IOException { - // NOOP since codec is unkwown. - LOG.warn("Call of the serializeToWriter method on JSONCodecFactory.NULL_CODEC object. No operation performed."); - } - }; - - private final LoadingCache> codecs = - CacheBuilder.newBuilder().softValues().build(new CacheLoader>() { - @Override - public JSONCodec load(final DataSchemaNode key) throws Exception { - final TypeDefinition type; - if (key instanceof LeafSchemaNode) { - type = ((LeafSchemaNode) key).getType(); - } else if (key instanceof LeafListSchemaNode) { - type = ((LeafListSchemaNode) key).getType(); - } else { - throw new IllegalArgumentException("Not supported node type " + key.getClass().getName()); - } - return createCodec(key,type); - } - }); - - private final SchemaContext schemaContext; - private final JSONCodec iidCodec; - private final JSONCodec idrefCodec; - - private JSONCodecFactory(final SchemaContext context) { - this.schemaContext = Preconditions.checkNotNull(context); - iidCodec = new JSONStringInstanceIdentifierCodec(context); - idrefCodec = new JSONStringIdentityrefCodec(context); - } - - /** - * Instantiate a new codec factory attached to a particular context. - * - * @param context SchemaContext to which the factory should be bound - * @return A codec factory instance. - */ - public static JSONCodecFactory create(final SchemaContext context) { - return new JSONCodecFactory(context); - } - - private static TypeDefinition resolveBaseTypeFrom(final TypeDefinition type) { - TypeDefinition superType = type; - while (superType.getBaseType() != null) { - superType = superType.getBaseType(); - } - return superType; - } - - private JSONCodec createCodec(DataSchemaNode key, TypeDefinition type) { - TypeDefinition baseType = resolveBaseTypeFrom(type); - if (baseType instanceof LeafrefTypeDefinition) { - return createReferencedTypeCodec(key, (LeafrefTypeDefinition) baseType); - } - return createFromSimpleType(type); - } - - private JSONCodec createReferencedTypeCodec(DataSchemaNode schema, - LeafrefTypeDefinition type) { - // FIXME: Verify if this does indeed support leafref of leafref - TypeDefinition referencedType = - SchemaContextUtil.getBaseTypeForLeafRef(type, getSchemaContext(), schema); - return createFromSimpleType(referencedType); - } - - @SuppressWarnings("unchecked") - private JSONCodec createFromSimpleType(TypeDefinition type) { - final TypeDefinition baseType = resolveBaseTypeFrom(type); - if (baseType instanceof InstanceIdentifierType) { - return (JSONCodec) iidCodec; - } - if (baseType instanceof IdentityrefType) { - return (JSONCodec) idrefCodec; - } - - final TypeDefinitionAwareCodec codec = TypeDefinitionAwareCodec.from(type); - if (codec == null) { - LOG.debug("Codec for type \"{}\" is not implemented yet.", type.getQName() - .getLocalName()); - return NULL_CODEC; - } - return (JSONCodec) AbstractJSONCodec.create(codec); - } - - SchemaContext getSchemaContext() { - return schemaContext; - } - - JSONCodec codecFor(DataSchemaNode schema) { - return codecs.getUnchecked(schema); +public abstract class JSONCodecFactory extends AbstractCodecFactory> { + JSONCodecFactory(final @NonNull EffectiveModelContext context, final @NonNull CodecCache> cache) { + super(context, cache); } + @Override + protected final JSONCodec binaryCodec(final BinaryTypeDefinition type) { + return new QuotedJSONCodec<>(BinaryStringCodec.from(type)); + } + + @Override + protected final JSONCodec booleanCodec(final BooleanTypeDefinition type) { + return new BooleanJSONCodec(BooleanStringCodec.from(type)); + } + + @Override + protected final JSONCodec bitsCodec(final BitsTypeDefinition type) { + return new QuotedJSONCodec<>(BitsStringCodec.from(type)); + } + + @Override + protected final JSONCodec decimalCodec(final DecimalTypeDefinition type) { + return wrapDecimalCodec(DecimalStringCodec.from(type)); + } + + @Override + protected final JSONCodec emptyCodec(final EmptyTypeDefinition type) { + return EmptyJSONCodec.INSTANCE; + } + + @Override + protected final JSONCodec enumCodec(final EnumTypeDefinition type) { + return new QuotedJSONCodec<>(EnumStringCodec.from(type)); + } + + @Override + protected final JSONCodec identityRefCodec(final IdentityrefTypeDefinition type, final QNameModule module) { + return new IdentityrefJSONCodec(getEffectiveModelContext(), module); + } + + @Override + protected final JSONCodec int8Codec(final Int8TypeDefinition type) { + return new NumberJSONCodec<>(AbstractIntegerStringCodec.from(type)); + } + + @Override + protected final JSONCodec int16Codec(final Int16TypeDefinition type) { + return new NumberJSONCodec<>(AbstractIntegerStringCodec.from(type)); + } + + @Override + protected final JSONCodec int32Codec(final Int32TypeDefinition type) { + return new NumberJSONCodec<>(AbstractIntegerStringCodec.from(type)); + } + + @Override + protected final JSONCodec int64Codec(final Int64TypeDefinition type) { + return wrapIntegerCodec(AbstractIntegerStringCodec.from(type)); + } + + @Override + protected final JSONCodec stringCodec(final StringTypeDefinition type) { + return new QuotedJSONCodec<>(StringStringCodec.from(type)); + } + + @Override + protected final JSONCodec uint8Codec(final Uint8TypeDefinition type) { + return new NumberJSONCodec<>(AbstractIntegerStringCodec.from(type)); + } + + @Override + protected final JSONCodec uint16Codec(final Uint16TypeDefinition type) { + return new NumberJSONCodec<>(AbstractIntegerStringCodec.from(type)); + } + + @Override + protected final JSONCodec uint32Codec(final Uint32TypeDefinition type) { + return new NumberJSONCodec<>(AbstractIntegerStringCodec.from(type)); + } + + @Override + protected final JSONCodec uint64Codec(final Uint64TypeDefinition type) { + return wrapIntegerCodec(AbstractIntegerStringCodec.from(type)); + } + + @Override + protected final JSONCodec unionCodec(final UnionTypeDefinition type, final List> codecs) { + return UnionJSONCodec.create(type, codecs); + } + + @Override + protected final JSONCodec unknownCodec(final UnknownTypeDefinition type) { + return NullJSONCodec.INSTANCE; + } + + @Override + protected abstract JSONCodec instanceIdentifierCodec(InstanceIdentifierTypeDefinition type); + + // Returns a one-off factory for the purposes of normalizing an anydata tree. + // + // FIXME: 7.0.0: this is really ugly, as we should be able to tell if the new context is the same as ours and + // whether our cache is thread-safe -- in which case we should just return this. + // The supplier/cache/factory layout needs to be reworked so that this call ends up being equivalent + // to JSONCodecFactorySupplier.getShared() in case this factory is not thread safe. + // + // The above is not currently possible, as we cannot reference JSONCodecFactorySupplier from the + // factory due to that potentially creating a circular reference. + final JSONCodecFactory rebaseTo(final EffectiveModelContext newSchemaContext) { + return rebaseTo(newSchemaContext, new LazyCodecCache<>()); + } + + abstract JSONCodecFactory rebaseTo(EffectiveModelContext newSchemaContext, CodecCache> newCache); + + abstract JSONCodec wrapDecimalCodec(DecimalStringCodec decimalCodec); + + abstract JSONCodec wrapIntegerCodec(AbstractIntegerStringCodec integerCodec); }