2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.data.codec.gson;
10 import com.google.common.annotations.Beta;
11 import com.google.common.base.Preconditions;
12 import com.google.common.cache.CacheBuilder;
13 import com.google.common.cache.CacheLoader;
14 import com.google.common.cache.LoadingCache;
15 import com.google.gson.stream.JsonWriter;
16 import java.io.IOException;
17 import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
18 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
19 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
20 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
21 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
22 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
23 import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
24 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
25 import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
26 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
27 import org.opendaylight.yangtools.yang.model.util.DerivedType;
28 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
33 * Factory for creating JSON equivalents of codecs. Each instance of this object is bound to
34 * a particular {@link SchemaContext}, but can be reused by multiple {@link JSONNormalizedNodeStreamWriter}s.
37 public final class JSONCodecFactory {
38 private static final Logger LOG = LoggerFactory.getLogger(JSONCodecFactory.class);
39 private static final JSONCodec<Object> NULL_CODEC = new JSONCodec<Object>() {
41 public Object deserialize(final String input) {
46 public String serialize(final Object input) {
51 public boolean needQuotes() {
56 public void serializeToWriter(final JsonWriter writer, final Object value) throws IOException {
57 // NOOP since codec is unkwown.
58 LOG.warn("Call of the serializeToWriter method on JSONCodecFactory.NULL_CODEC object. No operation performed.");
62 private final LoadingCache<DataSchemaNode, JSONCodec<Object>> codecs =
63 CacheBuilder.newBuilder().softValues().build(new CacheLoader<DataSchemaNode, JSONCodec<Object>>() {
65 public JSONCodec<Object> load(final DataSchemaNode key) throws Exception {
66 final TypeDefinition<?> type;
67 if (key instanceof LeafSchemaNode) {
68 type = ((LeafSchemaNode) key).getType();
69 } else if (key instanceof LeafListSchemaNode) {
70 type = ((LeafListSchemaNode) key).getType();
72 throw new IllegalArgumentException("Not supported node type " + key.getClass().getName());
74 return createCodec(key,type);
78 private final SchemaContext schemaContext;
79 private final JSONCodec<?> iidCodec;
81 private JSONCodecFactory(final SchemaContext context) {
82 this.schemaContext = Preconditions.checkNotNull(context);
83 iidCodec = new JSONStringInstanceIdentifierCodec(context);
87 * Instantiate a new codec factory attached to a particular context.
89 * @param context SchemaContext to which the factory should be bound
90 * @return A codec factory instance.
92 public static JSONCodecFactory create(final SchemaContext context) {
93 return new JSONCodecFactory(context);
96 @SuppressWarnings("unchecked")
97 private JSONCodec<Object> createCodec(final DataSchemaNode key, final TypeDefinition<?> type) {
98 final TypeDefinition<?> normalizedType = DerivedType.from(type);
99 if (normalizedType instanceof LeafrefTypeDefinition) {
100 return createReferencedTypeCodec(key, (LeafrefTypeDefinition) normalizedType);
101 } else if (normalizedType instanceof IdentityrefTypeDefinition) {
102 final JSONCodec<?> jsonStringIdentityrefCodec =
103 new JSONStringIdentityrefCodec(schemaContext, key.getQName().getModule());
104 return (JSONCodec<Object>) jsonStringIdentityrefCodec;
106 return createFromSimpleType(normalizedType);
109 private JSONCodec<Object> createReferencedTypeCodec(final DataSchemaNode schema,
110 final LeafrefTypeDefinition type) {
111 // FIXME: Verify if this does indeed support leafref of leafref
112 final TypeDefinition<?> referencedType =
113 SchemaContextUtil.getBaseTypeForLeafRef(type, getSchemaContext(), schema);
114 return createCodec(schema, referencedType);
117 @SuppressWarnings("unchecked")
118 private JSONCodec<Object> createFromSimpleType(final TypeDefinition<?> type) {
119 if (type instanceof InstanceIdentifierTypeDefinition) {
120 return (JSONCodec<Object>) iidCodec;
122 if (type instanceof EmptyTypeDefinition) {
123 return (JSONCodec<Object>) JSONEmptyCodec.INSTANCE;
126 final TypeDefinitionAwareCodec<Object, ?> codec = TypeDefinitionAwareCodec.from(type);
128 LOG.debug("Codec for type \"{}\" is not implemented yet.", type.getQName()
132 return (JSONCodec<Object>) AbstractJSONCodec.create(codec);
135 SchemaContext getSchemaContext() {
136 return schemaContext;
139 JSONCodec<Object> codecFor(final DataSchemaNode schema) {
140 return codecs.getUnchecked(schema);