1fafb40ac4a1408a3d0c2656c934b8bde16a1b92
[yangtools.git] / code-generator / binding-data-codec / src / main / java / org / opendaylight / yangtools / binding / data / codec / impl / SchemaRootCodecContext.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.binding.data.codec.impl;
9
10 import com.google.common.base.Optional;
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 org.opendaylight.yangtools.util.ClassLoaderUtils;
16 import org.opendaylight.yangtools.yang.binding.ChildOf;
17 import org.opendaylight.yangtools.yang.binding.DataRoot;
18 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
19 import org.opendaylight.yangtools.yang.common.QName;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
21 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
22 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
23 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
24 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
25 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
26
27 class SchemaRootCodecContext extends DataContainerCodecContext<SchemaContext> {
28
29     private final LoadingCache<Class<?>, DataContainerCodecContext<?>> childrenByClass = CacheBuilder.newBuilder().build(
30             new CacheLoader<Class<?>, DataContainerCodecContext<?>>() {
31                 @Override
32                 public DataContainerCodecContext<?> load(final Class<?> key) {
33                     Class<Object> parent = ClassLoaderUtils.findFirstGenericArgument(key, ChildOf.class);
34                     Preconditions.checkArgument(DataRoot.class.isAssignableFrom(parent));
35                     QName qname = BindingReflections.findQName(key);
36                     DataSchemaNode childSchema = schema().getDataChildByName(qname);
37                     return DataContainerCodecPrototype.from(key, childSchema, factory()).get();
38                 }
39             });
40
41     private final LoadingCache<QName, DataContainerCodecContext<?>> childrenByQName = CacheBuilder.newBuilder().build(
42         new CacheLoader<QName, DataContainerCodecContext<?>>() {
43             @Override
44             public DataContainerCodecContext<?> load(final QName qname) {
45                 final DataSchemaNode childSchema = schema().getDataChildByName(qname);
46                 Preconditions.checkArgument(childSchema != null, "Argument %s is not valid child of %s", qname, schema());
47
48                 if (childSchema instanceof DataNodeContainer || childSchema instanceof ChoiceNode) {
49                     final Class<?> childCls = factory().getRuntimeContext().getClassForSchema(childSchema);
50                     return getStreamChild(childCls);
51                 } else {
52                     throw new UnsupportedOperationException("Unsupported child type " + childSchema.getClass());
53                 }
54             }
55         });
56
57     private SchemaRootCodecContext(final DataContainerCodecPrototype<SchemaContext> dataPrototype) {
58         super(dataPrototype);
59     }
60
61     /**
62      * Creates RootNode from supplied CodecContextFactory.
63      *
64      * @param factory
65      *            CodecContextFactory
66      * @return
67      */
68     static SchemaRootCodecContext create(final CodecContextFactory factory) {
69         DataContainerCodecPrototype<SchemaContext> prototype = DataContainerCodecPrototype.rootPrototype(factory);
70         return new SchemaRootCodecContext(prototype);
71     }
72
73     @Override
74     protected DataContainerCodecContext<?> getStreamChild(final Class<?> childClass) {
75         return childrenByClass.getUnchecked(childClass);
76     }
77
78     @Override
79     protected Optional<DataContainerCodecContext<?>> getPossibleStreamChild(final Class<?> childClass) {
80         throw new UnsupportedOperationException("Not supported");
81     }
82
83     @Override
84     protected PathArgument getDomPathArgument() {
85         throw new UnsupportedOperationException();
86     }
87
88     @Override
89     protected NodeCodecContext getYangIdentifierChild(final PathArgument arg) {
90         return childrenByQName.getUnchecked(arg.getNodeType());
91     }
92
93     @Override
94     protected Object dataFromNormalizedNode(final NormalizedNode<?, ?> normalizedNode) {
95         throw new UnsupportedOperationException("Could not create Binding data representation for root");
96     }
97 }