de.fischer.thotti.core.configuration.ConfigDenormalizer.java Source code

Java tutorial

Introduction

Here is the source code for de.fischer.thotti.core.configuration.ConfigDenormalizer.java

Source

/*
 * Copyright 2011 Oliver B. Fischer
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.fischer.thotti.core.configuration;

import de.fischer.thotti.core.annotations.DistributedTestJob;
import de.fischer.thotti.core.annotations.HadoopJobFlow;
import de.fischer.thotti.core.annotations.JVMArgs;
import de.fischer.thotti.core.annotations.NDTest;
import de.fischer.thotti.core.annotations.ParamGrp;
import de.fischer.thotti.core.annotations.ParamSet;
import de.fischer.thotti.core.annotations.ParamVal;
import de.fischer.thotti.core.annotations.Run;
import de.fischer.thotti.ec2.core.ThottiRuntimeException;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.Collection;

import static org.apache.commons.lang3.StringUtils.isNotEmpty;

/**
 * @author Oliver B. Fischer
 */
public class ConfigDenormalizer {

    public void denormalize(Configuration config, ConfigurationWriter writer) {

        Collection<ThottiAnnotationHolder<NDTest>> ndTests = config.getAllNDTests();
        Collection<ThottiAnnotationHolder<HadoopJobFlow>> hjFlows = config.getAllHadoopJobFlows();

        if (!ndTests.isEmpty() && !hjFlows.isEmpty()) {
            // @todo Throw something better
            throw new ThottiRuntimeException("Either NDtests or HDtests!");
        }

        // @todo What to do if both are empty

        if (!ndTests.isEmpty()) {
            for (ThottiAnnotationHolder<NDTest> test : ndTests) {
                denormalizeNDTest(test, config, writer);
            }
        }

        if (!hjFlows.isEmpty()) {
            denormalizeHJFlows(hjFlows, config, writer);
        }

    }

    protected void denormalizeHJFlows(Collection<ThottiAnnotationHolder<HadoopJobFlow>> hjFlows,
            Configuration config, ConfigurationWriter writer) {

        writer.startDistributedTestSuite();

        for (ThottiAnnotationHolder<HadoopJobFlow> holder : hjFlows) {

            createHDTests(holder, config, writer);

        }

        writer.finishDistributedTestSuite();
    }

    private void createHDTests(ThottiAnnotationHolder<HadoopJobFlow> flowHolder, Configuration config,
            ConfigurationWriter writer) {

        writer.startFlow();
        writer.withFlowName(flowHolder.getAnnotation().id());

        // find all tests in the same package or subpackages
        Package pack = getPackageOfJobFlow(flowHolder);
        String packageName = pack.getName();

        Collection<ThottiAnnotationHolder<DistributedTestJob>> allDistributedTestJobs = config
                .getAllDistributedTestJobs();

        for (ThottiAnnotationHolder<DistributedTestJob> dtholder : allDistributedTestJobs) {
            Package packageOfDTJ = getPackageOfDTJ(dtholder);
            String clazz = getFQCNFromHolderOfDTJ(dtholder);

            String packageNameOfDTJ = packageOfDTJ.getName();

            if (packageNameOfDTJ.startsWith(packageName)) {
                writer.startTestStep().withTestStepJobClass(clazz).withTestStepID(dtholder.getAnnotation().id())
                        .withActionOnFailure(dtholder.getAnnotation().onFailure());

                for (String argument : dtholder.getAnnotation().jobArguments()) {
                    writer.addTestStepArgument(argument);
                }

                writer.finishTestStep();
            }
        }

        writer.finishFlow();
    }

    private Package getPackageOfDTJ(ThottiAnnotationHolder<DistributedTestJob> holder) {
        AnnotatedElement origin = holder.getOrigin();

        return ((Class) origin).getPackage();
    }

    private Package getPackageOfJobFlow(ThottiAnnotationHolder<HadoopJobFlow> holder) {
        AnnotatedElement origin = holder.getOrigin();

        return ((Class) origin).getPackage();
    }

    void denormalizeNDTest(ThottiAnnotationHolder<NDTest> holder, Configuration config,
            ConfigurationWriter writer) {
        NDTest ndTest = holder.getAnnotation();
        String fqcn = getFQCNFromHolder(holder);
        String method = getMethodNameFromHolder(holder);

        JVMArgs[] jvmArgs = getJVMArgsForTest(ndTest, config);
        ParamSet parameters = getParameterSetForText(ndTest, config);

        if (jvmArgs != null) {
            createNDTestSection(writer, ndTest, fqcn, method, parameters, jvmArgs);
        } else {
            createNDTestSection(writer, ndTest, fqcn, method, parameters, null);
        }

        writer.finishNDTestSection();
    }

    private void createNDTestSection(ConfigurationWriter writer, NDTest ndTest, String fqcn, String method,
            ParamSet parameters, JVMArgs[] jvmArgs) {
        writer.startNDTestSection().withID(ndTest.id()).withDescription(ndTest.description()).withTargetClass(fqcn)
                .withTargetMethod(method);

        if (jvmArgs == null) {
            // Doing this allows us to pass the loop below
            // at least once
            jvmArgs = new JVMArgs[] { null };
        }

        for (JVMArgs args : jvmArgs) {
            if (parameters != null) {
                // The current test will be executed once for every
                // parameter group contained in the given parameter set
                for (ParamGrp group : parameters.value()) {
                    writer.startTest();
                    writer.withTestID(group.name());

                    if (args != null) {
                        writer.withTestJVMArgs(args.value());
                        writer.withTestJVMArgsID(args.id());
                    }

                    for (ParamVal val : group.values()) {
                        writer.withParameter(val.name(), val.value());
                    }

                    writer.finishTest();
                }
            } else {
                writer.startTest();

                if (args != null) {
                    writer.withTestJVMArgs(args.value());
                    writer.withTestJVMArgsID(args.id());
                }

                writer.finishTest();
            }

        }

    }

    private String getFQCNFromHadoopJobFlow(ThottiAnnotationHolder<HadoopJobFlow> holder) {
        Class clazz = (Class) holder.getOrigin();

        return clazz.getName();
    }

    private String getFQCNFromHolderOfDTJ(ThottiAnnotationHolder<DistributedTestJob> holder) {
        AnnotatedElement element = holder.getOrigin();

        assert element instanceof Class : "Only methods are currently supported.";

        Class clazz = (Class) element;

        assert clazz.isInterface() == false : "Annotation of interfaces is not supported.";

        return clazz.getCanonicalName();
    }

    private String getFQCNFromHolder(ThottiAnnotationHolder<NDTest> holder) {
        AnnotatedElement element = holder.getOrigin();

        assert element instanceof Method : "Only methods are currently supported.";

        Method method = (Method) element;

        Class clazz = method.getDeclaringClass();

        assert clazz.isInterface() == false : "Annotation of interfaces is not supported.";

        return clazz.getCanonicalName();
    }

    private String getMethodNameFromHolder(ThottiAnnotationHolder<NDTest> holder) {
        AnnotatedElement element = holder.getOrigin();

        assert element instanceof Method : "Only methods are currently supported.";

        Method method = (Method) element;

        return method.getName();
    }

    private ParamSet getParameterSetForText(NDTest ndTest, Configuration config) {
        assert ndTest.run().length == 1 : "There must be one run annotation!";

        Run run = ndTest.run()[0];

        boolean contained = ArrayUtils.isNotEmpty(run.paramSet());
        boolean reference = StringUtils.isNotEmpty(run.paramSetRef());

        // assert !reference && !contained
        //         : "If a parameter set is present, it must be either contained " +
        //         "or referenced.";

        if (reference) {
            ThottiAnnotationHolder<ParamSet> param = config.getParameterSet(run.paramSetRef());

            assert param != null : "Parameter set " + run.paramSetRef() + " not found.";

            return param.getAnnotation();
        }

        if (contained)
            return run.paramSet()[0];

        // @todo it would be better to throw an exception
        // @todo evalutate has/find/get style
        return null;
    }

    private JVMArgs[] getJVMArgsForTest(NDTest ndTest, Configuration config) {
        // @todo Write unit tests for this assertion
        assert ndTest.run().length == 1 : "There must be one run annotation!";

        Run run = ndTest.run()[0];

        boolean contained = ArrayUtils.isNotEmpty(run.jvmArgs());
        boolean reference = isNotEmpty(run.jvmArgsRef());

        // @todo Add a message!
        assert (reference && !contained) || (!reference && contained);

        if (reference) {
            ThottiAnnotationHolder<JVMArgs> args = config.getJVMArgs(run.jvmArgsRef());

            assert args != null : "JVM arguments " + run.jvmArgsRef() + " not found.";

            return new JVMArgs[] { args.getAnnotation() };
        }

        return run.jvmArgs();
    }
}