/* * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.yangtools.sal.binding.generator.impl; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.Lock; import javassist.ClassPool; import org.eclipse.xtext.xbase.lib.Extension; import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy; import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils; import org.opendaylight.yangtools.yang.binding.BindingCodec; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; import org.opendaylight.yangtools.yang.model.api.SchemaPath; import com.google.common.base.Preconditions; /** * Abstract base class which defines the baseline for the real {@link TransformerGenerator}. * This class exists to expose the basic interface and common interactions with the rest * of the package. */ abstract class AbstractTransformerGenerator { private static final Map> PATH_TO_BINDING_IDENTIFIER = new ConcurrentHashMap<>(); /* * The generator has to always use this strategy, otherwise we may end up * will VerificationErrors. */ @Extension protected static final ClassLoadingStrategy CLASS_LOADING_STRATEGY = GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy(); @Extension protected final TypeResolver typeResolver; @Extension protected final JavassistUtils javAssist; /* * This is effectively final, but we have an implementation circle, where this * class notifies LazyGeneratedCodecRegistry and it calls our methods. The * listener is initialized to non-null before it is exposed. */ private GeneratorListener listener; protected AbstractTransformerGenerator(final TypeResolver typeResolver, final ClassPool pool) { this.typeResolver = Preconditions.checkNotNull(typeResolver); this.javAssist = JavassistUtils.forClassPool(pool); } protected final GeneratorListener getListener() { if (listener == null) { synchronized (this) { Preconditions.checkState(listener != null, "Implementation not fully initialized"); } } return listener; } synchronized final void setListener(final GeneratorListener listener) { Preconditions.checkState(this.listener == null, "Implementation already initialized"); this.listener = Preconditions.checkNotNull(listener); } protected final V runOnClassLoader(final ClassLoader cls, final Callable function) throws Exception { final Lock lock = javAssist.getLock(); lock.lock(); try { javAssist.appendClassLoaderIfMissing(cls); return ClassLoaderUtils.withClassLoader(cls, function); } finally { lock.unlock(); } } protected final InstanceIdentifier getBindingIdentifierByPath(final SchemaPath path) { return PATH_TO_BINDING_IDENTIFIER.get(path); } protected final void putPathToBindingIdentifier(final SchemaPath path, final InstanceIdentifier bindingIdentifier) { PATH_TO_BINDING_IDENTIFIER.put(path, bindingIdentifier); } protected final InstanceIdentifier putPathToBindingIdentifier(final SchemaPath path, final InstanceIdentifier bindingIdentifier, final Class childClass) { @SuppressWarnings({ "unchecked", "rawtypes" }) InstanceIdentifier newId = bindingIdentifier.builder().child((Class) childClass).build(); PATH_TO_BINDING_IDENTIFIER.put(path, newId); return newId; } protected abstract Class, Object>> augmentationTransformerForImpl(Class inputType); protected abstract Class> caseCodecForImpl(Class inputType, ChoiceCaseNode node); protected abstract Class, Object>> keyTransformerForIdentifiableImpl(Class parentType); protected abstract Class, Object>> keyTransformerForIdentifierImpl(Class inputType); protected abstract Class, Object>> transformerForImpl(Class inputType); // Called from LazyGeneratedCodecRegistry final Class, Object>> augmentationTransformerFor(final Class inputType) throws TransformerGeneratorException { try { return augmentationTransformerForImpl(inputType); } catch (Exception e) { throw TransformerGeneratorException.wrap(inputType, e); } } final Class> caseCodecFor(final Class inputType, final ChoiceCaseNode node) throws TransformerGeneratorException { try { return caseCodecForImpl(inputType, node); } catch (Exception e) { throw TransformerGeneratorException.wrap(inputType, e); } } final Class, Object>> keyTransformerForIdentifiable(final Class parentType) throws TransformerGeneratorException { try { return keyTransformerForIdentifiableImpl(parentType); } catch (Exception e) { throw TransformerGeneratorException.wrap(parentType, e); } } final Class, Object>> keyTransformerForIdentifier(final Class inputType) throws TransformerGeneratorException { try { return keyTransformerForIdentifierImpl(inputType); } catch (Exception e) { throw TransformerGeneratorException.wrap(inputType, e); } } final Class, Object>> transformerFor(final Class inputType) throws TransformerGeneratorException { try { return transformerForImpl(inputType); } catch (Exception e) { throw TransformerGeneratorException.wrap(inputType, e); } } }