58d38dacd5de6b0123b176223fde172f132780a8
[yangtools.git] / code-generator / binding-generator-impl / src / main / java / org / opendaylight / yangtools / sal / binding / generator / impl / AbstractTransformerGenerator.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.sal.binding.generator.impl;
9
10 import com.google.common.base.Preconditions;
11
12 import java.util.Map;
13 import java.util.concurrent.Callable;
14 import java.util.concurrent.ConcurrentHashMap;
15
16 import javassist.ClassPool;
17
18 import org.eclipse.xtext.xbase.lib.Extension;
19 import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
20 import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
21 import org.opendaylight.yangtools.yang.binding.BindingCodec;
22 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
23 import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils;
24 import org.opendaylight.yangtools.yang.common.QName;
25 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
26 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
27
28 /**
29  * Abstract base class which defines the baseline for the real {@link TransformerGenerator}.
30  * This class exists to expose the basic interface and common interactions with the rest
31  * of the package.
32  */
33 abstract class AbstractTransformerGenerator {
34     private static final Map<SchemaPath, InstanceIdentifier<?>> PATH_TO_BINDING_IDENTIFIER = new ConcurrentHashMap<>();
35
36     /*
37      * The generator has to always use this strategy, otherwise we may end up
38      * will VerificationErrors.
39      */
40     @Extension
41     protected static final ClassLoadingStrategy CLASS_LOADING_STRATEGY = GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy();
42     @Extension
43     protected final TypeResolver typeResolver;
44     @Extension
45     protected final JavassistUtils javAssist;
46
47     /*
48      * This is effectively final, but we have an implementation circle, where this
49      * class notifies LazyGeneratedCodecRegistry and it calls our methods. The
50      * listener is initialized to non-null before it is exposed.
51      */
52     private GeneratorListener listener;
53
54     protected AbstractTransformerGenerator(final TypeResolver typeResolver, final ClassPool pool) {
55         this.typeResolver = Preconditions.checkNotNull(typeResolver);
56         this.javAssist = JavassistUtils.forClassPool(pool);
57     }
58
59     protected final GeneratorListener getListener() {
60         if (listener == null) {
61             synchronized (this) {
62                 Preconditions.checkState(listener != null, "Implementation not fully initialized");
63             }
64         }
65
66         return listener;
67     }
68
69     synchronized final void setListener(final GeneratorListener listener) {
70         Preconditions.checkState(this.listener == null, "Implementation already initialized");
71         this.listener = Preconditions.checkNotNull(listener);
72     }
73
74     protected final <V> V runOnClassLoader(final ClassLoader cls, final Callable<V> function) throws Exception {
75         synchronized (javAssist) {
76             javAssist.appendClassLoaderIfMissing(cls);
77             return ClassLoaderUtils.withClassLoader(cls, function);
78         }
79     }
80
81     protected final InstanceIdentifier<?> getBindingIdentifierByPath(final SchemaPath path) {
82         return PATH_TO_BINDING_IDENTIFIER.get(path);
83     }
84
85     protected final void putPathToBindingIdentifier(final SchemaPath path, final InstanceIdentifier<?> bindingIdentifier) {
86         PATH_TO_BINDING_IDENTIFIER.put(path, bindingIdentifier);
87     }
88
89     protected final InstanceIdentifier<?> putPathToBindingIdentifier(final SchemaPath path,
90             final InstanceIdentifier<?> bindingIdentifier, final Class<?> childClass) {
91         @SuppressWarnings({ "unchecked", "rawtypes" })
92         InstanceIdentifier<?> newId = bindingIdentifier.builder().child((Class) childClass).build();
93         PATH_TO_BINDING_IDENTIFIER.put(path, newId);
94         return newId;
95     }
96
97     protected abstract Class<? extends BindingCodec<Map<QName, Object>, Object>> augmentationTransformerForImpl(Class<?> inputType);
98     protected abstract Class<? extends BindingCodec<Object, Object>> caseCodecForImpl(Class<?> inputType, ChoiceCaseNode node);
99     protected abstract Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifiableImpl(Class<?> parentType);
100     protected abstract Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifierImpl(Class<?> inputType);
101     protected abstract Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerForImpl(Class<?> inputType);
102
103     // Called from LazyGeneratedCodecRegistry
104     final Class<? extends BindingCodec<Map<QName, Object>, Object>> augmentationTransformerFor(final Class<?> inputType) throws TransformerGeneratorException {
105         try {
106             return augmentationTransformerForImpl(inputType);
107         } catch (Exception e) {
108             throw TransformerGeneratorException.wrap(inputType, e);
109         }
110     }
111
112     final Class<? extends BindingCodec<Object, Object>> caseCodecFor(final Class<?> inputType, final ChoiceCaseNode node) throws TransformerGeneratorException {
113         try {
114             return caseCodecForImpl(inputType, node);
115         } catch (Exception e) {
116             throw TransformerGeneratorException.wrap(inputType, e);
117         }
118     }
119
120     final Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifiable(final Class<?> parentType) throws TransformerGeneratorException {
121         try {
122             return keyTransformerForIdentifiableImpl(parentType);
123         } catch (Exception e) {
124             throw TransformerGeneratorException.wrap(parentType, e);
125         }
126     }
127
128     final Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifier(final Class<?> inputType) throws TransformerGeneratorException {
129         try {
130             return keyTransformerForIdentifierImpl(inputType);
131         } catch (Exception e) {
132             throw TransformerGeneratorException.wrap(inputType, e);
133         }
134     }
135
136     final Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(final Class<?> inputType) throws TransformerGeneratorException {
137         try {
138             return transformerForImpl(inputType);
139         } catch (Exception e) {
140             throw TransformerGeneratorException.wrap(inputType, e);
141         }
142     }
143 }