Java tutorial
/** * <pre> * The MIT License (MIT) * * Copyright (c) 2014 Grzegorz Kochaski * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * </pre> */ package org.itest.impl; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.itest.ITestConfig; import org.itest.ITestConstants; import org.itest.annotation.ITest; import org.itest.annotation.ITestAssignment; import org.itest.annotation.ITestRef; import org.itest.annotation.ITests; import org.itest.definition.ITestDefinition; import org.itest.definition.ITestDefinitionFactory; import org.itest.exception.ITestException; import org.itest.exception.ITestParamDefinitionException; import org.itest.impl.util.IoUtils; import org.itest.param.ITestParamState; public class ITestDefinitionFactoryImpl implements ITestDefinitionFactory { private final Map<ITestIdentifier, Collection<ITestDependency>> itestDependencyMap = new HashMap<ITestIdentifier, Collection<ITestDependency>>(); private final Map<ITestIdentifier, ITestDeclaration> itestMap = new HashMap<ITestIdentifier, ITestDeclaration>(); private final Map<ITestIdentifier, ITestDefinition> itestDefinitionMap = new HashMap<ITestIdentifier, ITestDefinition>(); private final ITestConfig iTestConfig; private final byte[] buffer = new byte[1024]; public ITestDefinitionFactoryImpl(ITestConfig iTestConfig) { this.iTestConfig = iTestConfig; } @Override public Collection<ITestDefinition> buildTestFlowDefinitions(Class<?>... classes) { for (Class<?> clazz : classes) { buildDependencies(clazz); } for (ITestIdentifier itestIdentifier : itestMap.keySet()) { buildDefinition(itestIdentifier); } return itestDefinitionMap.values(); } private void buildDefinition(ITestIdentifier itestIdentifier) { Collection<ITestDependency> children = itestDependencyMap.get(itestIdentifier); if (null != children) { for (ITestDependency child : itestDependencyMap.get(itestIdentifier)) { buildDefinition(child.itestIdentifier); } define(itestIdentifier); } } private void define(ITestIdentifier itestIdentifier) { if (null == itestDefinitionMap.get(itestIdentifier)) { ITestDeclaration itestDefinition = itestMap.get(itestIdentifier); Collection<String> transformations = new ArrayList<String>(); Collection<ITestParamState> params = new ArrayList<ITestParamState>(); for (ITestDependency child : itestDependencyMap.get(itestIdentifier)) { ITestDefinition childPathDefintion = itestDefinitionMap.get(child.itestIdentifier); transformations.add(child.transformation); ITestParamState childParams; if (null == childPathDefintion) { childParams = loadParams(child.itestIdentifier); } else { childParams = childPathDefintion.getInitParams(); } params.add(childParams); } if (0 < itestDefinition.path.init().length()) { transformations.add(""); params.add(parseInitParam(itestDefinition.method, itestDefinition.path.init())); } Map<Class<?>, Map<String, String>> iTestStaticAssignment = toITestStaticAssignment( itestDefinition.path.assignment()); ITestParamState itestParams = iTestConfig.getITestParamsMerger().merge(transformations, params); ITestDefinition res = new ITestDefinitionImpl(itestDefinition.method.getDeclaringClass(), itestDefinition.method, itestIdentifier.itestName, itestParams, parseInitParam(itestDefinition.method, itestDefinition.path.verify()), new HashMap<String, Type>(), iTestStaticAssignment); itestDefinitionMap.put(itestIdentifier, res); } } private ITestParamState loadParams(ITestIdentifier itestIdentifier) { String resourceName = new StringBuilder(128).append(itestIdentifier.itestClass.getName().replace('.', '/')) .append(".itest").toString(); InputStream is = itestIdentifier.itestClass.getClassLoader().getResourceAsStream(resourceName); if (null == is) { throw new ITestException("File (" + resourceName + ") not found."); } String init; try { init = new String(IoUtils.readBytes(is, buffer)); } catch (IOException e) { throw new RuntimeException(e); } ITestParamState initParams = parseInitParam(null, init); ITestParamState namedParams = initParams.getElement(itestIdentifier.itestName); if (null == namedParams) { throw new ITestException( "Data definition for test (" + itestIdentifier.itestName + ") not found in " + resourceName); } ITestParamStateImpl res = new ITestParamStateImpl(); res.addElement(ITestConstants.THIS, namedParams); return res; } private Map<Class<?>, Map<String, String>> toITestStaticAssignment(ITestAssignment[] assignment) { Map<Class<?>, Map<String, String>> assignmentMap = new HashMap<Class<?>, Map<String, String>>(); for (ITestAssignment iTestAssignment : assignment) { Map<String, String> fieldMap = assignmentMap.get(iTestAssignment.targetClass()); if (null == fieldMap) { fieldMap = new HashMap<String, String>(); assignmentMap.put(iTestAssignment.targetClass(), fieldMap); } fieldMap.put(iTestAssignment.targetField(), iTestAssignment.sourcePath()); } return assignmentMap; } private void buildDependencies(Class<?> clazz) { L: for (Method method : clazz.getDeclaredMethods()) { if (method.isAnnotationPresent(ITests.class)) { int methodTestCounter = 0; for (ITest path : method.getAnnotation(ITests.class).value()) { String testName = path.name(); if (0 == testName.length()) { testName = method.getName() + "#itest" + methodTestCounter; } ITestIdentifier itestIdentifier = new ITestIdentifier(clazz, testName); if (null == itestMap.get(itestIdentifier)) { itestMap.put(itestIdentifier, new ITestDeclaration(method, path)); Collection<ITestDependency> col = new ArrayList<ITestDependency>(); itestDependencyMap.put(itestIdentifier, col); for (ITestRef initRef : path.initRef()) { Class<?> refClass = initRef.useClass() == ITestRef.class ? clazz : initRef.useClass(); String refTestName = initRef.use(); col.add(new ITestDependency(initRef.assign(), new ITestIdentifier(refClass, refTestName))); if (refClass != clazz) { buildDependencies(refClass); } } } else { break L; } methodTestCounter++; } } } } private Class<?> resolveDependencyClass(Class<?> clazz, String use) { String[] uses = StringUtils.split(use, '.'); for (int i = 0; i < uses.length - 1; i++) { if (ITestConstants.THIS.equals(uses[i])) { } else { throw new RuntimeException("Not implemented yet."); } } return clazz; } static class ITestDependency { private final String transformation; private final ITestIdentifier itestIdentifier; public ITestDependency(String transform, ITestIdentifier itestIdentifier) { this.transformation = transform; this.itestIdentifier = itestIdentifier; } } static class ITestIdentifier { Class<?> itestClass; String itestName; public ITestIdentifier(Class<?> itestClass, String itestName) { this.itestClass = itestClass; this.itestName = itestName; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((itestClass == null) ? 0 : itestClass.hashCode()); result = prime * result + ((itestName == null) ? 0 : itestName.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } ITestIdentifier other = (ITestIdentifier) obj; if (itestClass == null) { if (other.itestClass != null) { return false; } } else if (!itestClass.equals(other.itestClass)) { return false; } if (itestName == null) { if (other.itestName != null) { return false; } } else if (!itestName.equals(other.itestName)) { return false; } return true; } @Override public String toString() { return itestClass.getName() + "." + itestName; } } static class ITestDeclaration { private final Method method; private final ITest path; public ITestDeclaration(Method method, ITest path) { this.method = method; this.path = path; } public Method getMethod() { return method; } public ITest getPath() { return path; } } private ITestParamState parseInitParam(Method method, String init) { try { ITestParamState res = iTestConfig.getITestParamParser().parse(init); return res; } catch (RuntimeException e) { throw new ITestParamDefinitionException(method, null, init, e); } } }