2 * Copyright (c) 2017 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.base.Preconditions;
11 import com.google.common.base.Stopwatch;
12 import com.google.common.cache.CacheBuilder;
13 import com.google.common.cache.CacheLoader;
14 import com.google.common.cache.LoadingCache;
16 import javax.annotation.concurrent.ThreadSafe;
17 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
18 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
19 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
20 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
21 import org.opendaylight.yangtools.yang.model.api.TypedSchemaNode;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
26 * Pre-computed JSONCodecFactory. All possible codecs are created upfront at instantiation time, after which they
27 * are available for the cost of a constant lookup.
29 * @author Robert Varga
32 final class EagerJSONCodecFactory extends JSONCodecFactory {
33 private static final Logger LOG = LoggerFactory.getLogger(EagerJSONCodecFactory.class);
35 // Weak keys to retire the entry when SchemaContext goes away
36 private static final LoadingCache<SchemaContext, EagerJSONCodecFactory> CACHE = CacheBuilder.newBuilder()
37 .weakKeys().build(new CacheLoader<SchemaContext, EagerJSONCodecFactory>() {
39 public EagerJSONCodecFactory load(final SchemaContext key) {
40 final Stopwatch sw = Stopwatch.createStarted();
41 final LazyJSONCodecFactory lazy = new LazyJSONCodecFactory(key);
42 final int visitedLeaves = requestCodecsForChildren(lazy, key);
45 final Map<TypeDefinition<?>, JSONCodec<?>> simple = lazy.getSimpleCodecs();
46 final Map<TypedSchemaNode, JSONCodec<?>> complex = lazy.getComplexCodecs();
48 LOG.debug("{} leaf nodes resulted in {} simple and {} complex codecs in {}", visitedLeaves,
49 simple.size(), complex.size(), sw);
50 return new EagerJSONCodecFactory(key, simple, complex);
54 private final Map<TypeDefinition<?>, JSONCodec<?>> simpleCodecs;
55 private final Map<TypedSchemaNode, JSONCodec<?>> complexCodecs;
57 private EagerJSONCodecFactory(final SchemaContext context, final Map<TypeDefinition<?>, JSONCodec<?>> simpleCodecs,
58 final Map<TypedSchemaNode, JSONCodec<?>> complexCodecs) {
60 this.simpleCodecs = Preconditions.checkNotNull(simpleCodecs);
61 this.complexCodecs = Preconditions.checkNotNull(complexCodecs);
64 static EagerJSONCodecFactory get(final SchemaContext context) {
65 return CACHE.getUnchecked(context);
68 static EagerJSONCodecFactory getIfPresent(final SchemaContext context) {
69 return CACHE.getIfPresent(context);
73 JSONCodec<?> lookupComplex(final TypedSchemaNode schema) {
74 final JSONCodec<?> ret = complexCodecs.get(schema);
75 Preconditions.checkArgument(ret != null, "No codec available for schema %s", schema);
80 JSONCodec<?> lookupSimple(final TypeDefinition<?> type) {
81 return simpleCodecs.get(type);
85 JSONCodec<?> getComplex(final TypedSchemaNode schema, final JSONCodec<?> codec) {
86 throw new IllegalStateException("Uncached codec for " + schema);
90 JSONCodec<?> getSimple(final TypeDefinition<?> type, final JSONCodec<?> codec) {
91 throw new IllegalStateException("Uncached codec for " + type);
94 static int requestCodecsForChildren(final LazyJSONCodecFactory lazy, final DataNodeContainer parent) {
96 for (DataSchemaNode child : parent.getChildNodes()) {
97 if (child instanceof TypedSchemaNode) {
98 lazy.codecFor((TypedSchemaNode) child);
100 } else if (child instanceof DataNodeContainer) {
101 ret += requestCodecsForChildren(lazy, (DataNodeContainer) child);