Fix checkstyle in mdsal-binding-dom-codec
[mdsal.git] / binding / mdsal-binding-dom-codec / src / main / java / org / opendaylight / mdsal / binding / dom / codec / impl / DataContainerCodecPrototype.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.mdsal.binding.dom.codec.impl;
9
10 import com.google.common.collect.Iterables;
11 import javax.annotation.concurrent.GuardedBy;
12 import org.opendaylight.mdsal.binding.dom.codec.impl.NodeCodecContext.CodecContextFactory;
13 import org.opendaylight.yangtools.yang.binding.DataRoot;
14 import org.opendaylight.yangtools.yang.binding.Identifiable;
15 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
16 import org.opendaylight.yangtools.yang.common.QNameModule;
17 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
21 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
22 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
23 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
24 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
25 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
26 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
27 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
28 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
29
30 final class DataContainerCodecPrototype<T> implements NodeContextSupplier {
31
32     private final T schema;
33     private final QNameModule namespace;
34     private final CodecContextFactory factory;
35     private final Class<?> bindingClass;
36     private final InstanceIdentifier.Item<?> bindingArg;
37     private final YangInstanceIdentifier.PathArgument yangArg;
38     private volatile DataContainerCodecContext<?,T> instance = null;
39
40     @SuppressWarnings({"rawtypes", "unchecked"})
41     private DataContainerCodecPrototype(final Class<?> cls, final YangInstanceIdentifier.PathArgument arg,
42             final T nodeSchema, final CodecContextFactory factory) {
43         this.bindingClass = cls;
44         this.yangArg = arg;
45         this.schema = nodeSchema;
46         this.factory = factory;
47         this.bindingArg = new InstanceIdentifier.Item(bindingClass);
48
49         if (arg instanceof AugmentationIdentifier) {
50             this.namespace = Iterables.getFirst(((AugmentationIdentifier) arg).getPossibleChildNames(), null)
51                     .getModule();
52         } else {
53             this.namespace = arg.getNodeType().getModule();
54         }
55     }
56
57     static DataContainerCodecPrototype<SchemaContext> rootPrototype(final CodecContextFactory factory) {
58         final SchemaContext schema = factory.getRuntimeContext().getSchemaContext();
59         final NodeIdentifier arg = NodeIdentifier.create(schema.getQName());
60         return new DataContainerCodecPrototype<>(DataRoot.class, arg, schema, factory);
61     }
62
63     @SuppressWarnings({ "unchecked", "rawtypes" })
64     static <T extends DataSchemaNode> DataContainerCodecPrototype<T> from(final Class<?> cls, final T schema,
65             final CodecContextFactory factory) {
66         return new DataContainerCodecPrototype(cls, NodeIdentifier.create(schema.getQName()), schema, factory);
67     }
68
69     @SuppressWarnings({ "rawtypes", "unchecked" })
70     static DataContainerCodecPrototype<?> from(final Class<?> augClass, final AugmentationIdentifier arg,
71             final AugmentationSchema schema, final CodecContextFactory factory) {
72         return new DataContainerCodecPrototype(augClass, arg, schema, factory);
73     }
74
75     static DataContainerCodecPrototype<NotificationDefinition> from(final Class<?> augClass,
76             final NotificationDefinition schema, final CodecContextFactory factory) {
77         final PathArgument arg = NodeIdentifier.create(schema.getQName());
78         return new DataContainerCodecPrototype<>(augClass,arg, schema, factory);
79     }
80
81     protected T getSchema() {
82         return schema;
83     }
84
85     protected QNameModule getNamespace() {
86         return namespace;
87     }
88
89     protected CodecContextFactory getFactory() {
90         return factory;
91     }
92
93     protected Class<?> getBindingClass() {
94         return bindingClass;
95     }
96
97     protected InstanceIdentifier.Item<?> getBindingArg() {
98         return bindingArg;
99     }
100
101     protected YangInstanceIdentifier.PathArgument getYangArg() {
102         return yangArg;
103     }
104
105     @Override
106     public DataContainerCodecContext<?,T> get() {
107         DataContainerCodecContext<?,T> tmp = instance;
108         if (tmp == null) {
109             synchronized (this) {
110                 tmp = instance;
111                 if (tmp == null) {
112                     tmp = createInstance();
113                     instance = tmp;
114                 }
115             }
116         }
117
118         return tmp;
119     }
120
121     @GuardedBy("this")
122     @SuppressWarnings({ "rawtypes", "unchecked" })
123     private DataContainerCodecContext<?,T> createInstance() {
124         // FIXME: make protected abstract
125         if (schema instanceof ContainerSchemaNode) {
126             return new ContainerNodeCodecContext(this);
127         } else if (schema instanceof ListSchemaNode) {
128             if (Identifiable.class.isAssignableFrom(getBindingClass())) {
129                 return new KeyedListNodeCodecContext(this);
130             } else {
131                 return new ListNodeCodecContext(this);
132             }
133         } else if (schema instanceof ChoiceSchemaNode) {
134             return new ChoiceNodeCodecContext(this);
135         } else if (schema instanceof AugmentationSchema) {
136             return new AugmentationNodeContext(this);
137         } else if (schema instanceof ChoiceCaseNode) {
138             return new CaseNodeCodecContext(this);
139         }
140         throw new IllegalArgumentException("Unsupported type " + bindingClass + " " + schema);
141     }
142
143     boolean isChoice() {
144         return schema instanceof ChoiceSchemaNode;
145     }
146 }