2 * Copyright (c) 2014 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.sal.binding.generator.impl;
11 import java.util.concurrent.Callable;
12 import java.util.concurrent.ConcurrentHashMap;
13 import java.util.concurrent.locks.Lock;
15 import javassist.ClassPool;
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;
27 import com.google.common.base.Preconditions;
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
34 abstract class AbstractTransformerGenerator {
35 private static final Map<SchemaPath, InstanceIdentifier<?>> PATH_TO_BINDING_IDENTIFIER = new ConcurrentHashMap<>();
38 * The generator has to always use this strategy, otherwise we may end up
39 * will VerificationErrors.
42 protected static final ClassLoadingStrategy CLASS_LOADING_STRATEGY =
43 GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy();
45 protected final TypeResolver typeResolver;
47 protected final JavassistUtils javAssist;
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.
54 private GeneratorListener listener;
56 protected AbstractTransformerGenerator(final TypeResolver typeResolver, final ClassPool pool) {
57 this.typeResolver = Preconditions.checkNotNull(typeResolver);
58 this.javAssist = JavassistUtils.forClassPool(pool);
61 protected final GeneratorListener getListener() {
62 if (listener == null) {
64 Preconditions.checkState(listener != null, "Implementation not fully initialized");
71 synchronized final void setListener(final GeneratorListener listener) {
72 Preconditions.checkState(this.listener == null, "Implementation already initialized");
73 this.listener = Preconditions.checkNotNull(listener);
76 protected final <V> V runOnClassLoader(final ClassLoader cls, final Callable<V> function) throws Exception {
77 final Lock lock = javAssist.getLock();
81 javAssist.appendClassLoaderIfMissing(cls);
82 return ClassLoaderUtils.withClassLoader(cls, function);
88 protected final InstanceIdentifier<?> getBindingIdentifierByPath(final SchemaPath path) {
89 return PATH_TO_BINDING_IDENTIFIER.get(path);
92 protected final void putPathToBindingIdentifier(final SchemaPath path, final InstanceIdentifier<?> bindingIdentifier) {
93 PATH_TO_BINDING_IDENTIFIER.put(path, bindingIdentifier);
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);
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);
110 // Called from LazyGeneratedCodecRegistry
111 final Class<? extends BindingCodec<Map<QName, Object>, Object>> augmentationTransformerFor(final Class<?> inputType) throws TransformerGeneratorException {
113 return augmentationTransformerForImpl(inputType);
114 } catch (Exception e) {
115 throw TransformerGeneratorException.wrap(inputType, e);
119 final Class<? extends BindingCodec<Object, Object>> caseCodecFor(final Class<?> inputType, final ChoiceCaseNode node) throws TransformerGeneratorException {
121 return caseCodecForImpl(inputType, node);
122 } catch (Exception e) {
123 throw TransformerGeneratorException.wrap(inputType, e);
127 final Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifiable(final Class<?> parentType) throws TransformerGeneratorException {
129 return keyTransformerForIdentifiableImpl(parentType);
130 } catch (Exception e) {
131 throw TransformerGeneratorException.wrap(parentType, e);
135 final Class<? extends BindingCodec<Map<QName, Object>, Object>> keyTransformerForIdentifier(final Class<?> inputType) throws TransformerGeneratorException {
137 return keyTransformerForIdentifierImpl(inputType);
138 } catch (Exception e) {
139 throw TransformerGeneratorException.wrap(inputType, e);
143 final Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(final Class<?> inputType) throws TransformerGeneratorException {
145 return transformerForImpl(inputType);
146 } catch (Exception e) {
147 throw TransformerGeneratorException.wrap(inputType, e);