Updated Json Stream Writer to use gson JsonWriter.
[yangtools.git] / yang / yang-data-codec-gson / src / main / java / org / opendaylight / yangtools / yang / data / codec / gson / JSONCodecFactory.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.data.codec.gson;
9
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.SchemaContext;
19 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
20 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
21 import org.opendaylight.yangtools.yang.model.util.IdentityrefType;
22 import org.opendaylight.yangtools.yang.model.util.InstanceIdentifierType;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 /**
27  * Factory for creating JSON equivalents of codecs. Each instance of this object is bound to
28  * a particular {@link SchemaContext}, but can be reused by multiple {@link JSONNormalizedNodeStreamWriter}s.
29  */
30 @Beta
31 public final class JSONCodecFactory {
32     private static final Logger LOG = LoggerFactory.getLogger(JSONCodecFactory.class);
33     private static final JSONCodec<Object> LEAFREF_DEFAULT_CODEC = new JSONLeafrefCodec();
34     private static final JSONCodec<Object> NULL_CODEC = new JSONCodec<Object>() {
35         @Override
36         public Object deserialize(final String input) {
37             return null;
38         }
39
40         @Override
41         public String serialize(final Object input) {
42             return null;
43         }
44
45         @Override
46         public boolean needQuotes() {
47             return false;
48         }
49
50         @Override
51         public void serializeToWriter(JsonWriter writer, Object value) throws IOException {
52             // NOOP since codec is unkwown.
53             LOG.warn("Call of the serializeToWriter method on JSONCodecFactory.NULL_CODEC object. No operation performed.");
54         }
55     };
56
57     private static TypeDefinition<?> resolveBaseTypeFrom(final TypeDefinition<?> type) {
58         TypeDefinition<?> superType = type;
59         while (superType.getBaseType() != null) {
60             superType = superType.getBaseType();
61         }
62         return superType;
63     }
64
65     private final LoadingCache<TypeDefinition<?>, JSONCodec<Object>> codecs =
66             CacheBuilder.newBuilder().softValues().build(new CacheLoader<TypeDefinition<?>, JSONCodec<Object>>() {
67         @SuppressWarnings("unchecked")
68         @Override
69         public JSONCodec<Object> load(final TypeDefinition<?> key) throws Exception {
70             final TypeDefinition<?> type = resolveBaseTypeFrom(key);
71
72             if (type instanceof InstanceIdentifierType) {
73                 return (JSONCodec<Object>) iidCodec;
74             }
75             if (type instanceof IdentityrefType) {
76                 return (JSONCodec<Object>) idrefCodec;
77             }
78             if (type instanceof LeafrefTypeDefinition) {
79                 return LEAFREF_DEFAULT_CODEC;
80             }
81
82             final TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> codec = TypeDefinitionAwareCodec.from(type);
83             if (codec == null) {
84                 LOG.debug("Codec for type \"{}\" is not implemented yet.", type.getQName().getLocalName());
85                 return NULL_CODEC;
86             }
87
88             return (JSONCodec<Object>) AbstractJSONCodec.create(codec);
89         }
90     });
91
92     private final SchemaContext schemaContext;
93     private final JSONCodec<?> iidCodec;
94     private final JSONCodec<?> idrefCodec;
95
96     private JSONCodecFactory(final SchemaContext context) {
97         this.schemaContext = Preconditions.checkNotNull(context);
98         iidCodec = new JSONStringInstanceIdentifierCodec(context);
99         idrefCodec = new JSONStringIdentityrefCodec(context);
100     }
101
102     /**
103      * Instantiate a new codec factory attached to a particular context.
104      *
105      * @param context SchemaContext to which the factory should be bound
106      * @return A codec factory instance.
107      */
108     public static JSONCodecFactory create(final SchemaContext context) {
109         return new JSONCodecFactory(context);
110     }
111
112     SchemaContext getSchemaContext() {
113         return schemaContext;
114     }
115
116     JSONCodec<Object> codecFor(final TypeDefinition<?> typeDefinition) {
117         return codecs.getUnchecked(typeDefinition);
118     }
119 }