dba5ed7d24638c4f757622911725a75ff8d84ff9
[yangtools.git] / yang / yang-data-codec-gson / src / main / java / org / opendaylight / yangtools / yang / data / codec / gson / CodecFactory.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.cache.CacheBuilder;
12 import com.google.common.cache.CacheLoader;
13 import com.google.common.cache.LoadingCache;
14
15 import org.opendaylight.yangtools.concepts.Codec;
16 import org.opendaylight.yangtools.yang.data.api.codec.LeafrefCodec;
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  * This class is implementation-internal and subject to change. Please do not use it.
28  */
29 @Beta
30 final class CodecFactory {
31     private static final Logger LOG = LoggerFactory.getLogger(CodecFactory.class);
32     private static final Codec<?, ?> LEAFREF_DEFAULT_CODEC = new LeafrefCodec<String>() {
33         @Override
34         public String serialize(final Object data) {
35             return String.valueOf(data);
36         }
37
38         @Override
39         public Object deserialize(final String data) {
40             return data;
41         }
42     };
43     private static final Codec<?, ?> NULL_CODEC = new Codec<Object, Object>() {
44         @Override
45         public Object deserialize(final Object input) {
46             return null;
47         }
48
49         @Override
50         public Object serialize(final Object input) {
51             return null;
52         }
53     };
54
55
56     private static TypeDefinition<?> resolveBaseTypeFrom(final TypeDefinition<?> type) {
57         TypeDefinition<?> superType = type;
58         while (superType.getBaseType() != null) {
59             superType = superType.getBaseType();
60         }
61         return superType;
62     }
63
64     private final LoadingCache<TypeDefinition<?>, Codec<?, ?>> codecs =
65             CacheBuilder.newBuilder().softValues().build(new CacheLoader<TypeDefinition<?>, Codec<?, ?>>() {
66         @Override
67         public Codec<?, ?> load(final TypeDefinition<?> key) throws Exception {
68             final TypeDefinition<?> type = resolveBaseTypeFrom(key);
69
70             if (type instanceof InstanceIdentifierType) {
71                 return iidCodec;
72             }
73             if (type instanceof IdentityrefType) {
74                 return idrefCodec;
75             }
76             if (type instanceof LeafrefTypeDefinition) {
77                 return LEAFREF_DEFAULT_CODEC;
78             }
79
80             final TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> codec = TypeDefinitionAwareCodec.from(type);
81             if (codec == null) {
82                 LOG.debug("Codec for type \"{}\" is not implemented yet.", type.getQName().getLocalName());
83                 return NULL_CODEC;
84             }
85
86             return codec;
87         }
88     });
89
90     private final Codec<?, ?> iidCodec;
91     private final Codec<?, ?> idrefCodec;
92
93     private CodecFactory(final SchemaContext context) {
94         iidCodec = new JSONStringInstanceIdentifierCodec(context);
95         idrefCodec = new JSONStringIdentityrefCodec(context);
96     }
97
98     public static CodecFactory create(final SchemaContext context) {
99         return new CodecFactory(context);
100     }
101
102     @SuppressWarnings("unchecked")
103     public final Codec<Object, Object> codecFor(final TypeDefinition<?> typeDefinition) {
104         return (Codec<Object, Object>) codecs.getUnchecked(typeDefinition);
105     }
106 }