org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGeneratorTest.java Source code

Java tutorial

Introduction

Here is the source code for org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGeneratorTest.java

Source

/*
 * Copyright (c) 2013 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.controller.config.yangjmxgenerator.plugin;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.io.Files;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.commons.io.FileUtils;
import org.apache.maven.project.MavenProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.DependencyResolverFactory;
import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
import org.opendaylight.controller.config.api.annotations.Description;
import org.opendaylight.controller.config.api.annotations.RequireInterface;
import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
import org.opendaylight.controller.config.spi.AbstractModule;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
import org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants;
import org.opendaylight.controller.config.yangjmxgenerator.PackageTranslatorTest;
import org.opendaylight.controller.config.yangjmxgenerator.ServiceInterfaceEntryTest;
import org.osgi.framework.BundleContext;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

//TODO: refactor
public class JMXGeneratorTest extends AbstractGeneratorTest {

    JMXGenerator jmxGenerator;

    protected final HashMap<String, String> map = Maps.newHashMap();
    protected File outputBaseDir;
    File generatedResourcesDir;

    private static final List<String> expectedModuleFileNames = ServiceInterfaceEntryTest.toFileNames(
            "[AbstractAsyncEventBusModule.java, AbstractAsyncEventBusModuleFactory.java, AbstractDynamicThreadPoolModule.java, AbstractDynamicThreadPoolModuleFactory.java, AbstractEventBusModule.java, AbstractEventBusModuleFactory.java, AbstractNamingThreadFactoryModule.java, AbstractNamingThreadFactoryModuleFactory.java, AbstractThreadPoolRegistryImplModule.java, AbstractThreadPoolRegistryImplModuleFactory.java, AsyncEventBusModule.java, AsyncEventBusModuleFactory.java, AsyncEventBusModuleMXBean.java, AsyncEventBusRuntimeMXBean.java, AsyncEventBusRuntimeRegistration.java, AsyncEventBusRuntimeRegistrator.java, DynamicThreadPoolModule.java, DynamicThreadPoolModuleFactory.java, DynamicThreadPoolModuleMXBean.java, DynamicThreadPoolRuntimeMXBean.java, DynamicThreadPoolRuntimeRegistration.java, DynamicThreadPoolRuntimeRegistrator.java, EventBusModule.java, EventBusModuleFactory.java, EventBusModuleMXBean.java, EventRuntimeMXBean.java, EventRuntimeRegistration.java, FromGrouping.java, InnerStreamList.java, NamingThreadFactoryModule.java, NamingThreadFactoryModuleFactory.java, NamingThreadFactoryModuleMXBean.java, NamingThreadFactoryRuntimeMXBean.java, NamingThreadFactoryRuntimeRegistration.java, NamingThreadFactoryRuntimeRegistrator.java, Peer.java, StreamRuntimeMXBean.java, StreamRuntimeRegistration.java, ThreadPoolRegistryImplModule.java, ThreadPoolRegistryImplModuleFactory.java, ThreadPoolRegistryImplModuleMXBean.java, ThreadRuntimeMXBean.java, ThreadRuntimeRegistration.java, ThreadStreamRuntimeMXBean.java, ThreadStreamRuntimeRegistration.java]");

    private static final List<String> expectedBGPNames = ServiceInterfaceEntryTest
            .toFileNames("[AbstractBgpListenerImplModule.java, " + "AbstractBgpListenerImplModuleFactory.java, "
                    + "BgpListenerImplModule.java, " + "BgpListenerImplModuleFactory.java, "
                    + "BgpListenerImplModuleMXBean.java, Peers.java]");

    private static final List<String> expectedNetconfNames = ServiceInterfaceEntryTest
            .toFileNames("[AbstractNetconfTestImplModule.java, " + "AbstractNetconfTestImplModuleFactory.java, "
                    + "AbstractTestImplModule.java, " + "AbstractTestImplModuleFactory.java, "
                    + "AutoCloseableServiceInterface.java, "
                    + "ComplexDtoBInner.java, ComplexList.java, Deep.java, "
                    + "DtoA.java, DtoA1.java, DtoAInner.java, DtoAInnerInner.java, DtoB.java, DtoC.java,"
                    + "NetconfTestImplModule.java, NetconfTestImplModuleFactory.java,"
                    + "NetconfTestImplModuleMXBean.java, Peer.java, SimpleList.java, TestImplModule.java, "
                    + "TestImplModuleFactory.java," + " TestImplModuleMXBean.java" + "]");
    private static final List<String> expectedTestFiles = ServiceInterfaceEntryTest
            .toFileNames("[AbstractNetconfTestFileImplModule.java, AbstractNetconfTestFileImplModuleFactory.java, "
                    + "AbstractNetconfTestFiles1ImplModule.java, AbstractNetconfTestFiles1ImplModuleFactory.java, "
                    + "AbstractTestFileImplModule.java, AbstractTestFileImplModuleFactory.java, "
                    + "AbstractTestFiles1ImplModule.java, AbstractTestFiles1ImplModuleFactory.java, DtoA.java, "
                    + "DtoA.java, NetconfTestFileImplModuleMXBean.java, NetconfTestFileImplRuntimeMXBean.java, "
                    + "NetconfTestFileImplRuntimeRegistration.java, NetconfTestFileImplRuntimeRegistrator.java, "
                    + "NetconfTestFiles1ImplModule.java, NetconfTestFiles1ImplModuleFactory.java, "
                    + "NetconfTestFiles1ImplModuleMXBean.java, NetconfTestFiles1ImplRuntimeMXBean.java, "
                    + "NetconfTestFiles1ImplRuntimeRegistration.java, NetconfTestFiles1ImplRuntimeRegistrator.java, TestFileImplModule.java, TestFileImplModuleFactory.java, TestFileImplModuleMXBean.java, TestFileImplRuntimeMXBean.java, TestFileImplRuntimeRegistration.java, TestFileImplRuntimeRegistrator.java, TestFiles1ImplModule.java, TestFiles1ImplModuleFactory.java, TestFiles1ImplModuleMXBean.java, TestFiles1ImplRuntimeMXBean.java, TestFiles1ImplRuntimeRegistration.java, TestFiles1ImplRuntimeRegistrator.java]");
    private static final List<String> expectedAllFileNames = ServiceInterfaceEntryTest.toFileNames(
            "[AbstractAsyncEventBusModule.java, AbstractAsyncEventBusModuleFactory.java, AbstractBgpListenerImplModule.java, AbstractBgpListenerImplModuleFactory.java, AbstractDynamicThreadPoolModule.java, AbstractDynamicThreadPoolModuleFactory.java, AbstractEventBusModule.java, AbstractEventBusModuleFactory.java, AbstractNamingThreadFactoryModule.java, AbstractNamingThreadFactoryModuleFactory.java, AbstractNetconfTestFileImplModule.java, AbstractNetconfTestFileImplModuleFactory.java, AbstractNetconfTestFiles1ImplModule.java, AbstractNetconfTestFiles1ImplModuleFactory.java, AbstractNetconfTestImplModule.java, AbstractNetconfTestImplModuleFactory.java, AbstractTestFileImplModule.java, AbstractTestFileImplModuleFactory.java, AbstractTestFiles1ImplModule.java, AbstractTestFiles1ImplModuleFactory.java, AbstractTestImplModule.java, AbstractTestImplModuleFactory.java, AbstractThreadPoolRegistryImplModule.java, AbstractThreadPoolRegistryImplModuleFactory.java, AsyncEventBusModule.java, AsyncEventBusModuleFactory.java, AsyncEventBusModuleMXBean.java, AsyncEventBusRuntimeMXBean.java, AsyncEventBusRuntimeRegistration.java, AsyncEventBusRuntimeRegistrator.java, AutoCloseableServiceInterface.java, BgpListenerImplModule.java, BgpListenerImplModuleFactory.java, BgpListenerImplModuleMXBean.java, BgpListenerImplRuntimeMXBean.java, BgpListenerImplRuntimeRegistration.java, BgpListenerImplRuntimeRegistrator.java, ComplexDtoBInner.java, ComplexList.java, Deep.java, DtoA.java, DtoA.java, DtoA.java, DtoA1.java, DtoAInner.java, DtoAInnerInner.java, DtoB.java, DtoC.java, DynamicThreadPoolModule.java, DynamicThreadPoolModuleFactory.java, DynamicThreadPoolModuleMXBean.java, DynamicThreadPoolRuntimeMXBean.java, DynamicThreadPoolRuntimeRegistration.java, DynamicThreadPoolRuntimeRegistrator.java, EventBusModule.java, EventBusModuleFactory.java, EventBusModuleMXBean.java, EventBusServiceInterface.java, EventRuntimeMXBean.java, EventRuntimeRegistration.java, FromGrouping.java, InnerStreamList.java, NamingThreadFactoryModule.java, NamingThreadFactoryModuleFactory.java, NamingThreadFactoryModuleMXBean.java, NamingThreadFactoryRuntimeMXBean.java, NamingThreadFactoryRuntimeRegistration.java, NamingThreadFactoryRuntimeRegistrator.java, NetconfTestFileImplModule.java, NetconfTestFileImplModuleFactory.java, NetconfTestFileImplModuleMXBean.java, NetconfTestFileImplRuntimeMXBean.java, NetconfTestFileImplRuntimeRegistration.java, NetconfTestFileImplRuntimeRegistrator.java, NetconfTestFiles1ImplModule.java, NetconfTestFiles1ImplModuleFactory.java, NetconfTestFiles1ImplModuleMXBean.java, NetconfTestFiles1ImplRuntimeMXBean.java, NetconfTestFiles1ImplRuntimeRegistration.java, NetconfTestFiles1ImplRuntimeRegistrator.java, NetconfTestImplModule.java, NetconfTestImplModuleFactory.java, NetconfTestImplModuleMXBean.java, NetconfTestImplRuntimeMXBean.java, NetconfTestImplRuntimeRegistration.java, NetconfTestImplRuntimeRegistrator.java, Peer.java, Peer.java, PeersRuntimeMXBean.java, PeersRuntimeRegistration.java, ScheduledThreadPoolServiceInterface.java, SimpleList.java, StreamRuntimeMXBean.java, StreamRuntimeRegistration.java, TestFileImplModule.java, TestFileImplModuleFactory.java, TestFileImplModuleMXBean.java, TestFileImplRuntimeMXBean.java, TestFileImplRuntimeRegistration.java, TestFileImplRuntimeRegistrator.java, TestFiles1ImplModule.java, TestFiles1ImplModuleFactory.java, TestFiles1ImplModuleMXBean.java, TestFiles1ImplRuntimeMXBean.java, TestFiles1ImplRuntimeRegistration.java, TestFiles1ImplRuntimeRegistrator.java, TestImplModule.java, TestImplModuleFactory.java, TestImplModuleMXBean.java, TestImplRuntimeMXBean.java, TestImplRuntimeRegistration.java, TestImplRuntimeRegistrator.java, ThreadFactoryServiceInterface.java, ThreadPoolRegistryImplModule.java, ThreadPoolRegistryImplModuleFactory.java, ThreadPoolRegistryImplModuleMXBean.java, ThreadPoolServiceInterface.java, ThreadRuntimeMXBean.java, ThreadRuntimeRegistration.java, ThreadStreamRuntimeMXBean.java, ThreadStreamRuntimeRegistration.java]");
    private static final List<String> expectedGenerateMBEsListNames = ServiceInterfaceEntryTest.toFileNames(
            "[AbstractBgpListenerImplModule.java, AbstractBgpListenerImplModuleFactory.java, BgpListenerImplModule.java, BgpListenerImplModuleFactory.java, BgpListenerImplModuleMXBean.java, BgpListenerImplRuntimeMXBean.java, BgpListenerImplRuntimeRegistration.java, BgpListenerImplRuntimeRegistrator.java, PeersRuntimeMXBean.java, PeersRuntimeRegistration.java]");

    @Before
    public void setUp() {
        map.put(JMXGenerator.NAMESPACE_TO_PACKAGE_PREFIX + "1", ConfigConstants.CONFIG_NAMESPACE
                + JMXGenerator.NAMESPACE_TO_PACKAGE_DIVIDER + PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX);
        map.put(JMXGenerator.MODULE_FACTORY_FILE_BOOLEAN, "false");
        jmxGenerator = new JMXGenerator(new CodeWriter());
        jmxGenerator.setAdditionalConfig(map);
        File targetDir = new File(generatorOutputPath, "target");
        generatedResourcesDir = new File(targetDir, "generated-resources");
        jmxGenerator.setResourceBaseDir(generatedResourcesDir);
        MavenProject project = mock(MavenProject.class);
        doReturn(generatorOutputPath).when(project).getBasedir();
        jmxGenerator.setMavenProject(project);
        outputBaseDir = JMXGenerator.concatFolders(targetDir, "generated-sources", "config");
    }

    @Test
    public void generateSIsMBsTest() {
        Collection<File> files = jmxGenerator.generateSources(context, outputBaseDir, context.getModules());
        List<String> expectedFileNames = new ArrayList<>();
        expectedFileNames.addAll(ServiceInterfaceEntryTest.expectedSIEFileNames);
        expectedFileNames.addAll(expectedModuleFileNames);

        expectedFileNames.addAll(expectedBGPNames);
        expectedFileNames.addAll(expectedNetconfNames);
        expectedFileNames.addAll(expectedTestFiles);
        Collections.sort(expectedFileNames);
        // TODO: separate expectedAllFileNames into expectedBGPNames,
        // expectedNetconfNames
        assertEquals(expectedAllFileNames, toFileNames(files));

        verifyModuleFactoryFile(false);
    }

    private void verifyModuleFactoryFile(final boolean shouldBePresent) {
        File factoryFile = new File(generatedResourcesDir,
                "META-INF" + File.separator + "services" + File.separator + ModuleFactory.class.getName());
        if (!shouldBePresent) {
            assertFalse("Factory file should not be generated", factoryFile.exists());
        } else {
            assertTrue("Factory file should be generated", factoryFile.exists());
        }
    }

    public static List<String> toFileNames(final Collection<File> files) {
        List<String> result = new ArrayList<>();
        for (File f : files) {
            result.add(f.getName());
        }
        Collections.sort(result);
        return result;
    }

    @Test
    public void generateSIEsTest() throws IOException {
        Collection<File> files = jmxGenerator.generateSources(context, outputBaseDir,
                Sets.newHashSet(threadsModule));
        assertEquals(ServiceInterfaceEntryTest.expectedSIEFileNames, toFileNames(files));

        Map<String, ASTVisitor> verifiers = Maps.newHashMap();

        for (File file : files) {
            verifiers.put(file.getName(), new SieASTVisitor());
        }

        processGeneratedCode(files, verifiers);

        for (File file : files) {
            String fileName = file.getName();
            SieASTVisitor verifier = (SieASTVisitor) verifiers.get(fileName);

            assertEquals(fileName.substring(0, fileName.length() - 5), verifier.type);
            assertThat(verifier.extnds,
                    containsString("org.opendaylight.controller.config.api.annotations.AbstractServiceInterface"));
            assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + ".threads", verifier.packageName);
            assertNotNull(verifier.javadoc);

            if ("ThreadPoolServiceInterface.java".equals(fileName)) {
                assertContains(verifier.descriptionAnotValue, "A simple pool of threads able to execute work.");
                assertContains(verifier.sieAnnotValue, "threadpool");
                assertContains(verifier.sieAnnotOsgiRegistrationType,
                        PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + ".threadpool.ThreadPool.class");
            } else if ("ScheduledThreadPoolServiceInterface.java".equals(fileName)) {
                assertContains(verifier.extnds,
                        PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + ".threads.ThreadPoolServiceInterface");
                assertContains(verifier.descriptionAnotValue,
                        "An extension of the simple pool of threads able to schedule work to be executed at some point in time.");
                assertContains(verifier.sieAnnotValue, "scheduled-threadpool");
                assertContains(verifier.sieAnnotOsgiRegistrationType,
                        PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + ".threadpool.ScheduledThreadPool.class");
            } else if ("EventBusServiceInterface.java".equals(fileName)) {
                assertContains(verifier.descriptionAnotValue,
                        "Service representing an event bus. The service acts as message router between event producers and event consumers");
                assertContains(verifier.sieAnnotValue, "eventbus");
                assertContains(verifier.sieAnnotOsgiRegistrationType, "com.google.common.eventbus.EventBus.class");
            } else if ("ThreadFactoryServiceInterface.java".equals(fileName)) {
                assertContains(verifier.descriptionAnotValue,
                        "Service representing a ThreadFactory instance. It is directly useful in Java world, where various library pieces need to create threads and you may want to inject a customized thread implementation.");
                assertContains(verifier.sieAnnotValue, "threadfactory");
                assertContains(verifier.sieAnnotOsgiRegistrationType, "java.util.concurrent.ThreadFactory.class");

            } else if ("ScheduledExecutorServiceServiceInterface.java".equals(fileName)) {
                assertContains(verifier.sieAnnotOsgiRegistrationType,
                        "java.util.concurrent.ScheduledExecutorService.class");
            } else {
                fail("Unknown generated sie " + fileName);
            }
        }
    }

    @Test
    public void generateMBEsListTest() throws Exception {
        // default value for module factory file is true
        map.put(JMXGenerator.MODULE_FACTORY_FILE_BOOLEAN, "randomValue");
        jmxGenerator.setAdditionalConfig(map);

        Collection<File> files = jmxGenerator.generateSources(context, outputBaseDir,
                Sets.newHashSet(bgpListenerJavaModule));

        assertEquals(expectedGenerateMBEsListNames, toFileNames(files));
    }

    @Test
    public void generateMBEsTest() throws Exception {
        // default value for module factory file is true
        map.put(JMXGenerator.MODULE_FACTORY_FILE_BOOLEAN, "randomValue");
        jmxGenerator.setAdditionalConfig(map);

        Collection<File> files = jmxGenerator.generateSources(context, outputBaseDir,
                Sets.newHashSet(threadsJavaModule));

        assertEquals(expectedModuleFileNames, toFileNames(files));

        Map<String, ASTVisitor> verifiers = Maps.newHashMap();

        Collection<File> xmlFiles = Collections2.filter(files, new Predicate<File>() {

            @Override
            public boolean apply(final File input) {
                return input.getName().endsWith("xml");
            }
        });

        Collection<File> javaFiles = Collections2.filter(files, new Predicate<File>() {

            @Override
            public boolean apply(final File input) {
                return input.getName().endsWith("java");
            }
        });

        MbeASTVisitor abstractDynamicThreadPoolModuleVisitor = null;
        MbeASTVisitor asyncEventBusModuleMXBeanVisitor = null;
        MbeASTVisitor abstractNamingThreadFactoryModuleFactoryVisitor = null;
        MbeASTVisitor asyncEventBusModuleVisitor = null;
        MbeASTVisitor eventBusModuleFactoryVisitor = null;

        for (File file : javaFiles) {
            String name = file.getName();
            MbeASTVisitor visitor = new MbeASTVisitor();
            verifiers.put(name, visitor);
            if (name.equals("AbstractDynamicThreadPoolModule.java")) {
                abstractDynamicThreadPoolModuleVisitor = visitor;
            }
            if (name.equals("AsyncEventBusModuleMXBean.java")) {
                asyncEventBusModuleMXBeanVisitor = visitor;
            }
            if (name.equals("AbstractNamingThreadFactoryModuleFactory.java")) {
                abstractNamingThreadFactoryModuleFactoryVisitor = visitor;
            }
            if (name.equals("AsyncEventBusModule.java")) {
                asyncEventBusModuleVisitor = visitor;
            }
            if (name.equals("EventBusModuleFactory.java")) {
                eventBusModuleFactoryVisitor = visitor;
            }
        }

        processGeneratedCode(javaFiles, verifiers);

        assertAbstractDynamicThreadPoolModule(abstractDynamicThreadPoolModuleVisitor);
        assertAsyncEventBusModuleMXBean(asyncEventBusModuleMXBeanVisitor);
        assertAbstractNamingThreadFactoryModuleFactory(abstractNamingThreadFactoryModuleFactoryVisitor);
        assertAsyncEventBusModule(asyncEventBusModuleVisitor);
        assertEventBusModuleFactory(eventBusModuleFactoryVisitor);

        verifyXmlFiles(xmlFiles);
        // verify ModuleFactory file
        File moduleFactoryFile = JMXGenerator.concatFolders(generatedResourcesDir, "META-INF", "services",
                ModuleFactory.class.getName());
        assertThat(moduleFactoryFile.exists(), is(true));
        Set<String> lines = Sets.newHashSet(FileUtils.readLines(moduleFactoryFile));
        Set<String> expectedLines = Sets.newHashSet(//
                PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + ".threads.java.EventBusModuleFactory", //
                PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + ".threads.java.AsyncEventBusModuleFactory", //
                PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + ".threads.java.DynamicThreadPoolModuleFactory", //
                PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + ".threads.java.NamingThreadFactoryModuleFactory", //
                PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
                        + ".threads.java.ThreadPoolRegistryImplModuleFactory");

        assertThat(lines, equalTo(expectedLines));

    }

    private void verifyXmlFiles(final Collection<File> xmlFiles) throws Exception {
        ErrorHandler errorHandler = new ErrorHandler() {

            @Override
            public void warning(final SAXParseException exception) throws SAXException {
                fail("Generated blueprint xml is not well formed " + exception.getMessage());
            }

            @Override
            public void fatalError(final SAXParseException exception) throws SAXException {
                fail("Generated blueprint xml is not well formed " + exception.getMessage());
            }

            @Override
            public void error(final SAXParseException exception) throws SAXException {
                fail("Generated blueprint xml is not well formed " + exception.getMessage());
            }
        };

        for (File file : xmlFiles) {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setValidating(false);
            factory.setNamespaceAware(true);

            DocumentBuilder builder = factory.newDocumentBuilder();

            builder.setErrorHandler(errorHandler);
            builder.parse(new InputSource(file.getPath()));
        }

    }

    private void assertEventBusModuleFactory(final MbeASTVisitor visitor) {
        assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + ".threads.java", visitor.packageName);
        assertEquals("EventBusModuleFactory", visitor.type);
        assertContains(visitor.extnds,
                PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + ".threads.java.AbstractEventBusModuleFactory");

        assertEquals(0, visitor.fieldDeclarations.size());

        assertEquals("Incorrenct number of generated methods", 0, visitor.methods.size());
        assertEquals("Incorrenct number of generated constructors", 0, visitor.constructors.size());
        assertEquals("Incorrenct number of generated method descriptions", 0, visitor.methodDescriptions.size());
        assertEquals("Incorrenct number of generated method javadoc", 0, visitor.methodJavadoc.size());
    }

    private void assertAsyncEventBusModule(final MbeASTVisitor visitor) {
        assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + ".threads.java", visitor.packageName);
        assertEquals("AsyncEventBusModule", visitor.type);
        assertContains(visitor.extnds,
                PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + ".threads.java.AbstractAsyncEventBusModule");

        assertEquals(0, visitor.fieldDeclarations.size());

        assertEquals("Incorrenct number of generated methods", 2, visitor.methods.size());
        assertEquals("Incorrenct number of generated constructors", 2, visitor.constructors.size());
        assertEquals("Incorrenct number of generated method descriptions", 0, visitor.methodDescriptions.size());
        assertEquals("Incorrenct number of generated method javadoc", 0, visitor.methodJavadoc.size());
    }

    private void assertAbstractNamingThreadFactoryModuleFactory(final MbeASTVisitor visitor) {
        assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + ".threads.java", visitor.packageName);
        assertEquals("AbstractNamingThreadFactoryModuleFactory", visitor.type);
        assertContains(visitor.implmts, "org.opendaylight.controller.config.spi.ModuleFactory");
        Set<String> fieldDeclarations = visitor.fieldDeclarations;
        assertDeclaredField(fieldDeclarations,
                "public static final java.lang.String NAME=\"threadfactory-naming\"");
        assertDeclaredField(fieldDeclarations,
                "private static final java.util.Set<Class<? extends org.opendaylight.controller.config.api.annotations.AbstractServiceInterface>> serviceIfcs");

        assertEquals(2, fieldDeclarations.size());

        assertFactoryMethods(visitor.methods, 9);
        assertEquals("Incorrenct number of generated method descriptions", 0, visitor.methodDescriptions.size());
        assertEquals("Incorrenct number of generated method javadoc", 0, visitor.methodJavadoc.size());

    }

    private void assertFactoryMethods(final Set<String> methods, final int expectedSize) {

        List<ArgumentAssertion> args = Lists.newArrayList();
        ArgumentAssertion oldInstanceArg = new ArgumentAssertion(DynamicMBeanWithInstance.class.getCanonicalName(),
                "old");
        ArgumentAssertion instanceNameArg = new ArgumentAssertion(String.class.getSimpleName(), "instanceName");
        ArgumentAssertion dependencyResolverArg = new ArgumentAssertion(DependencyResolver.class.getCanonicalName(),
                "dependencyResolver");
        ArgumentAssertion bundleContextArg = new ArgumentAssertion(BundleContext.class.getCanonicalName(),
                "bundleContext");

        assertMethodPresent(methods, new MethodAssertion(String.class.getSimpleName(), "getImplementationName"));

        args.add(instanceNameArg);
        args.add(dependencyResolverArg);
        args.add(bundleContextArg);
        assertMethodPresent(methods, new MethodAssertion(Module.class.getCanonicalName(), "createModule", args));

        args.add(2, oldInstanceArg);
        assertMethodPresent(methods, new MethodAssertion(Module.class.getCanonicalName(), "createModule", args));

        args.clear();
        args.add(oldInstanceArg);
        assertMethodPresent(methods,
                new MethodAssertion("org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule",
                        "handleChangedClass", args));

        args.clear();
        args.add(instanceNameArg);
        args.add(dependencyResolverArg);
        args.add(bundleContextArg);
        assertMethodPresent(methods,
                new MethodAssertion("org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule",
                        "instantiateModule", args));

        args.add(2, new ArgumentAssertion(
                "org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule", "oldModule"));
        args.add(3, new ArgumentAssertion(AutoCloseable.class.getCanonicalName(), "oldInstance"));
        assertMethodPresent(methods,
                new MethodAssertion("org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule",
                        "instantiateModule", args));

        args.clear();
        args.add(new ArgumentAssertion(DependencyResolverFactory.class.getCanonicalName(),
                "dependencyResolverFactory"));
        args.add(bundleContextArg);
        assertMethodPresent(methods,
                new MethodAssertion(
                        "java.util.Set<org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule>",
                        "getDefaultModules", args));

        args.clear();
        args.add(new ArgumentAssertion(
                "Class<? extends org.opendaylight.controller.config.api.annotations.AbstractServiceInterface>",
                "serviceInterface"));
        assertMethodPresent(methods, new MethodAssertion("boolean", "isModuleImplementingServiceInterface", args));

        assertEquals(methods.size(), expectedSize);

    }

    private void assertMethodPresent(final Set<String> methods, final MethodAssertion methodAssertion) {
        assertTrue(String.format("Generated methods did not contain %s, generated methods: %s",
                methodAssertion.toString(), methods), methods.contains(methodAssertion.toString()));
    }

    private void assertAsyncEventBusModuleMXBean(final MbeASTVisitor visitor) {
        assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + ".threads.java", visitor.packageName);
        assertEquals("AsyncEventBusModuleMXBean", visitor.type);

        assertEquals("Incorrenct number of generated methods", 4, visitor.methods.size());

    }

    private void assertAbstractDynamicThreadPoolModule(final MbeASTVisitor visitor) {
        assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + ".threads.java", visitor.packageName);
        assertNotNull(visitor.javadoc);
        assertContains(visitor.descriptionAnotValue, "threadpool-dynamic description");
        assertEquals("AbstractDynamicThreadPoolModule", visitor.type);
        assertContains(visitor.implmts,
                PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + ".threads.java.DynamicThreadPoolModuleMXBean",
                PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + ".threads.ScheduledThreadPoolServiceInterface",
                PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + ".threads.ThreadPoolServiceInterface");
        assertContains(visitor.extnds, AbstractModule.class.getCanonicalName());
        assertEquals(2, visitor.constructors.size());
        Set<String> fieldDeclarations = visitor.fieldDeclarations;
        assertDeclaredField(fieldDeclarations, "private java.lang.Long maximumSize");
        assertDeclaredField(fieldDeclarations, "private javax.management.ObjectName threadfactory");
        assertDeclaredField(fieldDeclarations,
                "private java.util.concurrent.ThreadFactory threadfactoryDependency");
        assertDeclaredField(fieldDeclarations, "private java.lang.Long keepAlive=new java.lang.Long(\"10\")");
        assertDeclaredField(fieldDeclarations, "private java.lang.Long coreSize");
        assertDeclaredField(fieldDeclarations, "private byte[] binary");
        assertEquals(17, fieldDeclarations.size());

        assertEquals(1, visitor.requireIfc.size());
        String reqIfc = visitor.requireIfc.get("setThreadfactory");
        assertNotNull("Missing generated setter for threadfactory", reqIfc);
        assertContains(reqIfc,
                PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX + ".threads.ThreadFactoryServiceInterface");

        assertEquals("Incorrenct number of generated methods", 26, visitor.methods.size());
        assertEquals("Incorrenct number of generated method descriptions", 3, visitor.methodDescriptions.size());
        assertEquals("Incorrenct number of generated method javadoc", 3, visitor.methodJavadoc.size());
        assertNotNull("Missing javadoc for setMaximumSize method " + visitor.methodJavadoc,
                visitor.methodJavadoc.get("void setMaximumSize(java.lang.Long maximumSize)"));
    }

    private void assertDeclaredField(final Set<String> fieldDeclarations, final String declaration) {
        assertTrue("Missing field " + declaration + ", got: " + fieldDeclarations,
                fieldDeclarations.contains(declaration + ";\n"));
    }

    private static class SieASTVisitor extends ASTVisitor {
        protected String packageName, descriptionAnotValue, sieAnnotValue, sieAnnotOsgiRegistrationType, type,
                extnds, javadoc;
        protected Map<String, String> methodDescriptions = Maps.newHashMap();

        @Override
        public boolean visit(final PackageDeclaration node) {
            packageName = node.getName().toString();
            return super.visit(node);
        }

        @Override
        public boolean visit(final NormalAnnotation node) {
            if (node.getTypeName().toString().equals(Description.class.getCanonicalName())) {
                if (node.getParent() instanceof TypeDeclaration) {
                    descriptionAnotValue = node.values().get(0).toString();
                } else if (node.getParent() instanceof MethodDeclaration) {
                    String descr = node.values().get(0).toString();
                    methodDescriptions.put(((MethodDeclaration) node.getParent()).getName().toString(), descr);
                }
            } else if (node.getTypeName().toString().equals(ServiceInterfaceAnnotation.class.getCanonicalName())) {
                String text1 = node.values().get(0).toString();
                String text2 = node.values().get(1).toString();
                if (text1.contains("value")) {
                    sieAnnotValue = text1;
                    sieAnnotOsgiRegistrationType = text2;
                } else {
                    sieAnnotValue = text2;
                    sieAnnotOsgiRegistrationType = text1;
                }
            }
            return super.visit(node);
        }

        @Override
        public boolean visit(final TypeDeclaration node) {
            javadoc = node.getJavadoc() == null ? null : node.getJavadoc().toString();
            type = node.getName().toString();
            List<?> superIfcs = node.superInterfaceTypes();
            extnds = superIfcs != null && !superIfcs.isEmpty() ? superIfcs.toString() : null;
            return super.visit(node);
        }
    }

    private static class MbeASTVisitor extends SieASTVisitor {
        private String implmts;
        private final Set<String> fieldDeclarations = Sets.newHashSet();
        private final Set<String> constructors = Sets.newHashSet();
        private final Set<String> methods = new HashSet<String>();
        private final Map<String, String> requireIfc = Maps.newHashMap();
        private final Map<String, String> methodJavadoc = Maps.newHashMap();

        @Override
        public boolean visit(final NormalAnnotation node) {
            boolean result = super.visit(node);
            if (node.getTypeName().toString().equals(RequireInterface.class.getCanonicalName())
                    && node.getParent() instanceof MethodDeclaration) {
                // remember only top level description annotation
                String reqVal = node.values().get(0).toString();
                requireIfc.put(((MethodDeclaration) node.getParent()).getName().toString(), reqVal);
            }
            return result;
        }

        @Override
        public boolean visit(final FieldDeclaration node) {
            fieldDeclarations.add(node.toString());
            return super.visit(node);
        }

        @Override
        public boolean visit(final MethodDeclaration node) {
            if (node.isConstructor()) {
                constructors.add(node.toString());
            } else {
                String methodSignature = node.getReturnType2() + " " + node.getName() + "(";
                boolean first = true;
                for (Object o : node.parameters()) {
                    if (first) {
                        first = false;
                    } else {
                        methodSignature += ",";
                    }
                    methodSignature += o.toString();
                }
                methodSignature += ")";
                methods.add(methodSignature);
                if (node.getJavadoc() != null) {
                    methodJavadoc.put(methodSignature, node.getJavadoc().toString());
                }
            }
            return super.visit(node);
        }

        @Override
        public boolean visit(final TypeDeclaration node) {
            boolean visit = super.visit(node);
            List<?> superIfcs = node.superInterfaceTypes();
            implmts = superIfcs != null && !superIfcs.isEmpty() ? superIfcs.toString() : null;
            extnds = node.getSuperclassType() == null ? null : node.getSuperclassType().toString();
            return visit;
        }

    }

    private void assertContains(final String source, final String... contained) {
        for (String string : contained) {
            assertThat(source, containsString(string));
        }
    }

    private void processGeneratedCode(final Collection<File> files, final Map<String, ASTVisitor> verifiers)
            throws IOException {
        ASTParser parser = ASTParser.newParser(AST.JLS3);
        Map<?, ?> options = JavaCore.getOptions();
        JavaCore.setComplianceOptions(JavaCore.VERSION_1_7, options);
        parser.setCompilerOptions(options);

        parser.setKind(ASTParser.K_COMPILATION_UNIT);

        for (File file : files) {
            char[] source = readFileAsChars(file);
            parser.setSource(source);
            parser.setResolveBindings(true);

            CompilationUnit cu = (CompilationUnit) parser.createAST(null);
            // Check for compilation problems in generated file
            for (IProblem c : cu.getProblems()) {
                // 1610613332 = Syntax error, annotations are only available if
                // source level is 5.0
                if (c.getID() == 1610613332) {
                    continue;
                }
                // 1610613332 = Syntax error, parameterized types are only
                // available if source level is 5.0
                if (c.getID() == 1610613329) {
                    continue;
                }
                if (c.getID() == 1610613328) {
                    continue;
                }
                fail("Error in generated source code " + file + ":" + c.getSourceLineNumber() + " id: " + c.getID()
                        + " message:" + c.toString());
            }

            ASTVisitor visitor = verifiers.get(file.getName());
            if (visitor == null) {
                fail("Unknown generated file " + file.getName());
            }
            cu.accept(visitor);

        }
    }

    public static char[] readFileAsChars(final File file) throws IOException {
        List<String> readLines = Files.readLines(file, Charset.forName("utf-8"));
        char[] retVal = new char[0];
        for (String string : readLines) {
            char[] line = string.toCharArray();
            int beforeLength = retVal.length;
            retVal = Arrays.copyOf(retVal, retVal.length + line.length + 1);
            System.arraycopy(line, 0, retVal, beforeLength, line.length);
            retVal[retVal.length - 1] = '\n';
        }
        return retVal;
    }

    private static class MethodAssertion extends ArgumentAssertion {

        private final List<ArgumentAssertion> arguments;

        MethodAssertion(final String type, final String name, final List<ArgumentAssertion> arguments) {
            super(type, name);
            this.arguments = arguments;
        }

        MethodAssertion(final String type, final String name) {
            this(type, name, Collections.<ArgumentAssertion>emptyList());
        }

        @Override
        public String toString() {
            final StringBuffer sb = new StringBuffer();
            sb.append(type).append(' ');
            sb.append(name).append('(');

            int i = 0;
            for (ArgumentAssertion argument : arguments) {
                sb.append(argument.type).append(' ');
                sb.append(argument.name);
                if (++i != arguments.size()) {
                    sb.append(',');
                }
            }
            sb.append(')');
            return sb.toString();
        }
    }

    private static class ArgumentAssertion {

        protected final String type, name;

        private ArgumentAssertion(final String type, final String name) {
            this.type = type;
            this.name = name;
        }

        @Override
        public String toString() {
            final StringBuffer sb = new StringBuffer();
            sb.append(type).append(' ');
            sb.append(name);
            return sb.toString();
        }
    }
}