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