From af1db31e5a955fd3919e65179d4820966383402b Mon Sep 17 00:00:00 2001 From: Junv Date: Mon, 6 May 2013 14:25:45 +0800 Subject: [PATCH] initial project --- Elk-ioc | 1 - Elk-ioc/.gitignore | 3 + Elk-ioc/README.md | 16 ++ Elk-ioc/pom.xml | 126 +++++++++++++ .../elk/container/ConfigFileParser.java | 43 +++++ .../elk/container/ConfigXmlParser.java | 108 +++++++++++ .../elk/container/ElkContainer.java | 172 ++++++++++++++++++ .../thoughtworks/elk/container/Property.java | 25 +++ .../exception/ElkContainerException.java | 15 ++ .../exception/ElkParseException.java | 14 ++ .../elk/injection/ConstructorInjection.java | 19 ++ .../thoughtworks/elk/injection/Injection.java | 10 + .../elk/injection/SetterInjection.java | 26 +++ .../src/main/resources/elkContainer.property | 0 Elk-ioc/src/main/resources/elkContainer.xml | 8 + .../container/test/ConfigFileParserTest.java | 21 +++ .../container/test/ConfigXmlParserTest.java | 81 +++++++++ .../elk/container/test/ElkContainerTest.java | 146 +++++++++++++++ .../container/test/ScopedContainerTest.java | 55 ++++++ .../test/ConstructorInjectionTest.java | 30 +++ .../injection/test/SetterInjectionTest.java | 31 ++++ .../com/thoughtworks/elk/movie/Company.java | 4 + .../com/thoughtworks/elk/movie/Director.java | 14 ++ .../elk/movie/DirectorSetter.java | 14 ++ .../com/thoughtworks/elk/movie/Hollywood.java | 4 + .../com/thoughtworks/elk/movie/Movie.java | 4 + .../com/thoughtworks/elk/movie/Titanic.java | 4 + .../elk/movie/test/DirectorSetterTest.java | 20 ++ .../elk/movie/test/DirectorTest.java | 19 ++ .../com/thoughtworks/elk/movie/test/Hero.java | 8 + .../testConstructorInjection.property | 4 + .../resources/testConstructorInjection.xml | 17 ++ .../resources/testSetterInjection.property | 3 + .../test/resources/testSetterInjection.xml | 16 ++ 34 files changed, 1080 insertions(+), 1 deletion(-) delete mode 160000 Elk-ioc create mode 100644 Elk-ioc/.gitignore create mode 100644 Elk-ioc/README.md create mode 100644 Elk-ioc/pom.xml create mode 100644 Elk-ioc/src/main/java/com/thoughtworks/elk/container/ConfigFileParser.java create mode 100644 Elk-ioc/src/main/java/com/thoughtworks/elk/container/ConfigXmlParser.java create mode 100644 Elk-ioc/src/main/java/com/thoughtworks/elk/container/ElkContainer.java create mode 100644 Elk-ioc/src/main/java/com/thoughtworks/elk/container/Property.java create mode 100644 Elk-ioc/src/main/java/com/thoughtworks/elk/container/exception/ElkContainerException.java create mode 100644 Elk-ioc/src/main/java/com/thoughtworks/elk/container/exception/ElkParseException.java create mode 100644 Elk-ioc/src/main/java/com/thoughtworks/elk/injection/ConstructorInjection.java create mode 100644 Elk-ioc/src/main/java/com/thoughtworks/elk/injection/Injection.java create mode 100644 Elk-ioc/src/main/java/com/thoughtworks/elk/injection/SetterInjection.java create mode 100644 Elk-ioc/src/main/resources/elkContainer.property create mode 100644 Elk-ioc/src/main/resources/elkContainer.xml create mode 100644 Elk-ioc/src/test/java/com/thoughtworks/elk/container/test/ConfigFileParserTest.java create mode 100644 Elk-ioc/src/test/java/com/thoughtworks/elk/container/test/ConfigXmlParserTest.java create mode 100644 Elk-ioc/src/test/java/com/thoughtworks/elk/container/test/ElkContainerTest.java create mode 100644 Elk-ioc/src/test/java/com/thoughtworks/elk/container/test/ScopedContainerTest.java create mode 100644 Elk-ioc/src/test/java/com/thoughtworks/elk/injection/test/ConstructorInjectionTest.java create mode 100644 Elk-ioc/src/test/java/com/thoughtworks/elk/injection/test/SetterInjectionTest.java create mode 100644 Elk-ioc/src/test/java/com/thoughtworks/elk/movie/Company.java create mode 100644 Elk-ioc/src/test/java/com/thoughtworks/elk/movie/Director.java create mode 100644 Elk-ioc/src/test/java/com/thoughtworks/elk/movie/DirectorSetter.java create mode 100644 Elk-ioc/src/test/java/com/thoughtworks/elk/movie/Hollywood.java create mode 100644 Elk-ioc/src/test/java/com/thoughtworks/elk/movie/Movie.java create mode 100644 Elk-ioc/src/test/java/com/thoughtworks/elk/movie/Titanic.java create mode 100644 Elk-ioc/src/test/java/com/thoughtworks/elk/movie/test/DirectorSetterTest.java create mode 100644 Elk-ioc/src/test/java/com/thoughtworks/elk/movie/test/DirectorTest.java create mode 100644 Elk-ioc/src/test/java/com/thoughtworks/elk/movie/test/Hero.java create mode 100644 Elk-ioc/src/test/resources/testConstructorInjection.property create mode 100644 Elk-ioc/src/test/resources/testConstructorInjection.xml create mode 100644 Elk-ioc/src/test/resources/testSetterInjection.property create mode 100644 Elk-ioc/src/test/resources/testSetterInjection.xml diff --git a/Elk-ioc b/Elk-ioc deleted file mode 160000 index 32d3cbf..0000000 --- a/Elk-ioc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 32d3cbf057c7c05133e1533497e24b22aaa29927 diff --git a/Elk-ioc/.gitignore b/Elk-ioc/.gitignore new file mode 100644 index 0000000..4a6573f --- /dev/null +++ b/Elk-ioc/.gitignore @@ -0,0 +1,3 @@ +.idea +Elk-ioc.iml +target/ diff --git a/Elk-ioc/README.md b/Elk-ioc/README.md new file mode 100644 index 0000000..d9785a9 --- /dev/null +++ b/Elk-ioc/README.md @@ -0,0 +1,16 @@ +Elk +=== + +TODO List +- [X] implement constructor injection +- [ ] more tests for container +- [ ] refactor code (Xiaolong) +- [ ] add some exception handlers (Junv) +- [X] implement setter injection +- [ ] implement scoped container +- [ ] Option:implement factory injection +- [ ] Option:implement annotation + +License +==== +MIT License diff --git a/Elk-ioc/pom.xml b/Elk-ioc/pom.xml new file mode 100644 index 0000000..f5e8614 --- /dev/null +++ b/Elk-ioc/pom.xml @@ -0,0 +1,126 @@ + + + 4.0.0 + + com.toozhao + Elk-ioc + 0.0.1-SNAPSHOT + Elk IOC container + jar + Yet another Ioc container + https://github.com/szpyxlwoni/Elk + + com.toozhao + Elk + 0.0.1-SNAPSHOT + + + + MIT Licence + MIT Licence + repo + + + + https://github.com/szpyxlwoni/Elk.git + git@github.com:szpyxlwoni/Elk.git + + + + junv + Junv + wahyd4@gmail.com + + + szpyxlwoni + szpyxlwoni + szpyxlwoni@gmail.com + + + + + com.google.guava + guava + 14.0 + + + com.google.code.findbugs + jsr305 + 2.0.1 + provided + + + junit + junit + 4.11 + + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + verify + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.4 + + + sign-artifacts + verify + + sign + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.7 + 1.7 + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9 + + private + true + + + + attach-javadocs + + jar + + + + + + + + + nexus-oss + https://oss.sonatype.org/content/repositories/snapshots + + + + \ No newline at end of file diff --git a/Elk-ioc/src/main/java/com/thoughtworks/elk/container/ConfigFileParser.java b/Elk-ioc/src/main/java/com/thoughtworks/elk/container/ConfigFileParser.java new file mode 100644 index 0000000..b8ace45 --- /dev/null +++ b/Elk-ioc/src/main/java/com/thoughtworks/elk/container/ConfigFileParser.java @@ -0,0 +1,43 @@ +package com.thoughtworks.elk.container; + +import com.thoughtworks.elk.container.exception.ElkParseException; +import com.thoughtworks.elk.injection.ConstructorInjection; +import com.thoughtworks.elk.injection.Injection; +import com.thoughtworks.elk.injection.SetterInjection; + +import java.util.HashSet; +import java.util.Scanner; + +import static com.google.common.collect.Sets.newHashSet; + +public class ConfigFileParser { + private String injection; + private final Scanner scanner; + + public ConfigFileParser(String configFilePath) { + scanner = new Scanner(this.getClass().getClassLoader().getResourceAsStream(configFilePath)); + if (scanner.hasNext()) { + injection = scanner.next(); + } + } + + + public Injection getInjection() { + if (injection.equals("constructor")) { + return new ConstructorInjection(); + } + return new SetterInjection(); + } + + public HashSet getClassList() { + HashSet classes = newHashSet(); + while (scanner.hasNext()) { + try { + classes.add(Class.forName(scanner.next())); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + return classes; + } +} diff --git a/Elk-ioc/src/main/java/com/thoughtworks/elk/container/ConfigXmlParser.java b/Elk-ioc/src/main/java/com/thoughtworks/elk/container/ConfigXmlParser.java new file mode 100644 index 0000000..9c74f21 --- /dev/null +++ b/Elk-ioc/src/main/java/com/thoughtworks/elk/container/ConfigXmlParser.java @@ -0,0 +1,108 @@ +package com.thoughtworks.elk.container; + +import com.google.common.base.Function; +import javax.annotation.Nullable; +import com.thoughtworks.elk.container.exception.ElkContainerException; +import com.thoughtworks.elk.container.exception.ElkParseException; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import static com.google.common.collect.Lists.newArrayList; +import static com.google.common.collect.Lists.transform; + +public class ConfigXmlParser { + + private Document doc; + + public ConfigXmlParser(String configFilePath) throws ElkParseException { + InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(configFilePath); + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + try { + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + doc = dBuilder.parse(resourceAsStream); + } catch (Exception e) { + throw new ElkParseException(e.getMessage()); + } + } + + public Node getNode(String beanId) { + NodeList nodeList = doc.getElementsByTagName("bean"); + for (int i = 0; i < nodeList.getLength(); i++) { + Node node = nodeList.item(i); + if (node.getAttributes().getNamedItem("id").getNodeValue().equals(beanId)) { + return node; + } + } + return null; + } + + public ArrayList getChildNodes(String parentId, String childName) { + NodeList nodeList = getNode(parentId).getChildNodes(); + ArrayList nodeArrayList = newArrayList(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node node = nodeList.item(i); + if (node.getNodeName().equals(childName)) { + nodeArrayList.add(node); + } + } + return nodeArrayList; + } + + private String getAttribute(String beanId, String attributeName) { + return getNode(beanId).getAttributes().getNamedItem(attributeName).getNodeValue(); + } + + public String getBeanClass(String beanId) { + return getAttribute(beanId, "class"); + } + + public List getConstructorDependenciesClass(String beanId) { + return getChildNodeAttribute(beanId, "constructor-arg", "type"); + } + + public List getConstructorDependenciesName(String beanId) { + return getChildNodeAttribute(beanId, "constructor-arg", "ref"); + } + + private List getChildNodeAttribute(String beanId, String childName, final String attribute) { + ArrayList childNodes = getChildNodes(beanId, childName); + return transform(childNodes, new Function() { + @Override + public Object apply(@Nullable Node node) { + return node.getAttributes().getNamedItem(attribute).getNodeValue(); + } + }); + } + + public List getProperties(String beanId) { + List propertyName = getChildNodeAttribute(beanId, "property", "name"); + List propertyRef = getChildNodeAttribute(beanId, "property", "ref"); + List propertyType = getChildNodeAttribute(beanId, "property", "type"); + List properties = newArrayList(); + for (int i = 0; i < propertyName.size(); i++) { + properties.add(new Property(propertyName.get(i), propertyRef.get(i), propertyType.get(i))); + } + return properties; + } + + Class[] getDependenciesClass(List dependencies) { + return (Class[]) transform(dependencies, new Function() { + @Override + public Object apply(@Nullable Object o) { + try { + return Class.forName((String) o); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + return null; + } + }).toArray(new Class[0]); + } +} diff --git a/Elk-ioc/src/main/java/com/thoughtworks/elk/container/ElkContainer.java b/Elk-ioc/src/main/java/com/thoughtworks/elk/container/ElkContainer.java new file mode 100644 index 0000000..3d6dcb6 --- /dev/null +++ b/Elk-ioc/src/main/java/com/thoughtworks/elk/container/ElkContainer.java @@ -0,0 +1,172 @@ +package com.thoughtworks.elk.container; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import javax.annotation.Nullable; +import com.thoughtworks.elk.container.exception.ElkContainerException; +import com.thoughtworks.elk.container.exception.ElkParseException; +import com.thoughtworks.elk.injection.ConstructorInjection; +import com.thoughtworks.elk.injection.Injection; +import com.thoughtworks.elk.injection.SetterInjection; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.util.*; + +import static com.google.common.collect.Lists.transform; +import static com.google.common.collect.Maps.newHashMap; +import static com.google.common.collect.Sets.filter; +import static com.google.common.collect.Sets.newHashSet; + +public class ElkContainer { + private final ConfigFileParser configParser; + private final Injection injection; + private final HashSet classList; + private HashMap beanList = newHashMap(); + + private HashSet children = null; + private ElkContainer parent = null; + + public ElkContainer(Injection injection) { + this.injection = injection; + configParser = null; + classList = newHashSet(); + } + + public ElkContainer(String configFilePath) { + configParser = new ConfigFileParser(configFilePath); + injection = configParser.getInjection(); + classList = configParser.getClassList(); + } + + public void register(Class clazz) { + classList.add(clazz); + } + + public T getBean(final Class clazz) throws ElkContainerException, IllegalAccessException, InvocationTargetException, InstantiationException { + if (!validScope(clazz)) return null; + + if (clazz.isInterface()) return (T) getBean(findOneImplementClass(clazz)); + + if (beanList.get(clazz) == null) { + T instance = injection.buildBeanWithDependencies(clazz, this); + beanList.put(clazz, instance); + return instance; + } + + return (T) beanList.get(clazz); + } + + public Class findOneImplementClass(final Class clazz) { + return visit(this, new ContainerVisitor() { + @Override + public boolean isAppropriateContainer(ElkContainer container) { + return isImplementHaveBeenContained(clazz, container.classList); + } + + @Override + public Class returnWhenAppropriateContainerFound(ElkContainer container) { + return (Class) findImplementClasses(clazz, container.classList).toArray()[0]; + } + + @Override + public Class returnWhenNoMoreParentContainer() { + return null; + } + }); + } + + private boolean isImplementHaveBeenContained(Class clazz, HashSet currentList) { + return findImplementClasses(clazz, currentList).size() == 1; + } + + private Set findImplementClasses(final Class clazz, HashSet currentList) { + return filter(currentList, new Predicate() { + @Override + public boolean apply(@Nullable Class clazzInContainer) { + return Arrays.asList(clazzInContainer.getInterfaces()).contains(clazz); + } + }); + } + + public boolean isParameterAllInClassList(Class[] parameterTypes) { + for (int i = 0; i < parameterTypes.length; i++) { + if (!validScope(parameterTypes[i])) { + return false; + } + } + return true; + } + + public boolean validScope(final Class clazz) { + return visit(this, new ContainerVisitor() { + @Override + public boolean isAppropriateContainer(ElkContainer container) { + return isClassHaveBeenContained(clazz, container.classList) + || isImplementHaveBeenContained(clazz, container.classList); + } + + @Override + public Boolean returnWhenAppropriateContainerFound(ElkContainer container) { + return true; + } + + @Override + public Boolean returnWhenNoMoreParentContainer() { + return false; + } + }); + } + + private T visit(ElkContainer container, ContainerVisitor visitor) { + ElkContainer currentContainer = container; + while (currentContainer != null) { + if (visitor.isAppropriateContainer(currentContainer)) { + return visitor.returnWhenAppropriateContainerFound(currentContainer); + } + if (currentContainer.parent == null) { + return visitor.returnWhenNoMoreParentContainer(); + } + currentContainer = currentContainer.parent; + } + return visitor.returnWhenNoMoreParentContainer(); + } + + interface ContainerVisitor { + boolean isAppropriateContainer(ElkContainer container); + RETURN_TYPE returnWhenAppropriateContainerFound(ElkContainer container); + RETURN_TYPE returnWhenNoMoreParentContainer(); + } + + private boolean isClassHaveBeenContained(final Class clazz, HashSet currentList) { + return filter(currentList, new Predicate() { + @Override + public boolean apply(@Nullable Class clazzInContainer) { + return clazzInContainer == clazz; + } + }).size() == 1; + } + + public Object[] getDependenciesObject(Class[] classes) { + return transform(Arrays.asList(classes), new Function() { + @Override + public Object apply(@Nullable Object o) { + try { + return getBean((Class) o); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + }).toArray(); + } + + public void addChildContainer(ElkContainer childContainer) { + if (children == null) { + children = new HashSet(); + } + children.add(childContainer); + childContainer.parent = this; + } +} diff --git a/Elk-ioc/src/main/java/com/thoughtworks/elk/container/Property.java b/Elk-ioc/src/main/java/com/thoughtworks/elk/container/Property.java new file mode 100644 index 0000000..63d294b --- /dev/null +++ b/Elk-ioc/src/main/java/com/thoughtworks/elk/container/Property.java @@ -0,0 +1,25 @@ +package com.thoughtworks.elk.container; + +public class Property { + private String name; + private String ref; + private String type; + + public Property(String name, String ref, String type) { + this.name = name; + this.ref = ref; + this.type = type; + } + + public String getName() { + return name; + } + + public String getRef() { + return ref; + } + + public String getType() { + return type; + } +} diff --git a/Elk-ioc/src/main/java/com/thoughtworks/elk/container/exception/ElkContainerException.java b/Elk-ioc/src/main/java/com/thoughtworks/elk/container/exception/ElkContainerException.java new file mode 100644 index 0000000..0483f5a --- /dev/null +++ b/Elk-ioc/src/main/java/com/thoughtworks/elk/container/exception/ElkContainerException.java @@ -0,0 +1,15 @@ +package com.thoughtworks.elk.container.exception; + + +public class ElkContainerException extends Exception { + private String messgae; + + public ElkContainerException(String message) { + this.messgae = message; + } + + @Override + public String toString() { + return super.toString(); + } +} diff --git a/Elk-ioc/src/main/java/com/thoughtworks/elk/container/exception/ElkParseException.java b/Elk-ioc/src/main/java/com/thoughtworks/elk/container/exception/ElkParseException.java new file mode 100644 index 0000000..7816800 --- /dev/null +++ b/Elk-ioc/src/main/java/com/thoughtworks/elk/container/exception/ElkParseException.java @@ -0,0 +1,14 @@ +package com.thoughtworks.elk.container.exception; + + +public class ElkParseException extends Exception { + private String message; + + public ElkParseException() { + + } + + public ElkParseException(String message) { + this.message = message; + } +} diff --git a/Elk-ioc/src/main/java/com/thoughtworks/elk/injection/ConstructorInjection.java b/Elk-ioc/src/main/java/com/thoughtworks/elk/injection/ConstructorInjection.java new file mode 100644 index 0000000..e7c3b9c --- /dev/null +++ b/Elk-ioc/src/main/java/com/thoughtworks/elk/injection/ConstructorInjection.java @@ -0,0 +1,19 @@ +package com.thoughtworks.elk.injection; + +import com.thoughtworks.elk.container.ElkContainer; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +public class ConstructorInjection implements Injection { + public T buildBeanWithDependencies(Class clazz, ElkContainer elkContainer) + throws InstantiationException, IllegalAccessException, InvocationTargetException { + Constructor[] constructors = clazz.getConstructors(); + for (int i = 0; i < constructors.length; i++) { + if (elkContainer.isParameterAllInClassList(constructors[i].getParameterTypes())) { + return (T) constructors[i].newInstance(elkContainer.getDependenciesObject(constructors[i].getParameterTypes())); + } + } + return null; + } +} diff --git a/Elk-ioc/src/main/java/com/thoughtworks/elk/injection/Injection.java b/Elk-ioc/src/main/java/com/thoughtworks/elk/injection/Injection.java new file mode 100644 index 0000000..e46c0fc --- /dev/null +++ b/Elk-ioc/src/main/java/com/thoughtworks/elk/injection/Injection.java @@ -0,0 +1,10 @@ +package com.thoughtworks.elk.injection; + +import com.thoughtworks.elk.container.ElkContainer; + +import java.lang.reflect.InvocationTargetException; + +public interface Injection { + public T buildBeanWithDependencies(Class clazz, ElkContainer elkContainer) + throws InstantiationException, IllegalAccessException, InvocationTargetException; +} diff --git a/Elk-ioc/src/main/java/com/thoughtworks/elk/injection/SetterInjection.java b/Elk-ioc/src/main/java/com/thoughtworks/elk/injection/SetterInjection.java new file mode 100644 index 0000000..e77f26f --- /dev/null +++ b/Elk-ioc/src/main/java/com/thoughtworks/elk/injection/SetterInjection.java @@ -0,0 +1,26 @@ +package com.thoughtworks.elk.injection; + +import com.thoughtworks.elk.container.ElkContainer; +import com.thoughtworks.elk.container.exception.ElkContainerException; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class SetterInjection implements Injection { + @Override + public T buildBeanWithDependencies(Class clazz, ElkContainer elkContainer) + throws InstantiationException, IllegalAccessException, InvocationTargetException { + Method[] methods = clazz.getMethods(); + T instance = clazz.newInstance(); + for (int i = 0; i < methods.length; i++) { + if (methods[i].getName().startsWith("set") && elkContainer.isParameterAllInClassList(methods[i].getParameterTypes())) { + try { + methods[i].invoke(instance, elkContainer.getBean(methods[i].getParameterTypes()[0])); + } catch (ElkContainerException e) { + e.printStackTrace(); + } + } + } + return instance; + } +} diff --git a/Elk-ioc/src/main/resources/elkContainer.property b/Elk-ioc/src/main/resources/elkContainer.property new file mode 100644 index 0000000..e69de29 diff --git a/Elk-ioc/src/main/resources/elkContainer.xml b/Elk-ioc/src/main/resources/elkContainer.xml new file mode 100644 index 0000000..19891f7 --- /dev/null +++ b/Elk-ioc/src/main/resources/elkContainer.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/Elk-ioc/src/test/java/com/thoughtworks/elk/container/test/ConfigFileParserTest.java b/Elk-ioc/src/test/java/com/thoughtworks/elk/container/test/ConfigFileParserTest.java new file mode 100644 index 0000000..b74a8a6 --- /dev/null +++ b/Elk-ioc/src/test/java/com/thoughtworks/elk/container/test/ConfigFileParserTest.java @@ -0,0 +1,21 @@ +package com.thoughtworks.elk.container.test; + +import com.thoughtworks.elk.container.ConfigFileParser; +import com.thoughtworks.elk.injection.ConstructorInjection; +import com.thoughtworks.elk.injection.Injection; +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsInstanceOf.instanceOf; + +public class ConfigFileParserTest { + @Test + public void should_get_injection() { + ConfigFileParser configFileParser = new ConfigFileParser("testConstructorInjection.property"); + + Injection injection = configFileParser.getInjection(); + + assertThat(injection, is(instanceOf(ConstructorInjection.class))); + } +} diff --git a/Elk-ioc/src/test/java/com/thoughtworks/elk/container/test/ConfigXmlParserTest.java b/Elk-ioc/src/test/java/com/thoughtworks/elk/container/test/ConfigXmlParserTest.java new file mode 100644 index 0000000..d188256 --- /dev/null +++ b/Elk-ioc/src/test/java/com/thoughtworks/elk/container/test/ConfigXmlParserTest.java @@ -0,0 +1,81 @@ +package com.thoughtworks.elk.container.test; + +import com.thoughtworks.elk.container.ConfigXmlParser; +import com.thoughtworks.elk.container.Property; +import com.thoughtworks.elk.container.exception.ElkParseException; +import org.junit.Before; +import org.junit.Test; +import org.w3c.dom.Node; + +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; + +public class ConfigXmlParserTest { + + private ConfigXmlParser configConstructorXmlParser; + private ConfigXmlParser configSetterXmlParser; + + @Before + public void setUp() throws Exception, ElkParseException { + configConstructorXmlParser = new ConfigXmlParser("testConstructorInjection.xml"); + configSetterXmlParser = new ConfigXmlParser("testSetterInjection.xml"); + } + + @Test(expected = ElkParseException.class) + public void shouldSThrowElkParseException() throws ElkParseException { + new ConfigXmlParser("fake_file.xml"); + } + + @Test + public void should_return_a_node_given_bean_id() { + Node company = configConstructorXmlParser.getNode("company"); + + assertThat(company, notNullValue()); + assertThat(company.getNodeName(), is("bean")); + } + + @Test + public void should_return_a_node_given_parent_bean_id_and_child_node_name() { + ArrayList nodeArrayList = configConstructorXmlParser.getChildNodes("company", "description"); + + assertThat(nodeArrayList.size(), is(1)); + assertThat(nodeArrayList.get(0).getChildNodes().item(0).getNodeValue(), is("test")); + } + + @Test + public void should_get_class_name_given_a_bean_id() { + String attribute = configConstructorXmlParser.getBeanClass("company"); + + assertThat(attribute, is("com.thoughtworks.elk.movie.Hollywood")); + } + + @Test + public void should_get_constructor_dependencies_class_given_a_bean_id() { + List constructorDependencies = configConstructorXmlParser.getConstructorDependenciesClass("director"); + + assertThat(constructorDependencies.get(0), is("com.thoughtworks.elk.movie.Movie")); + assertThat(constructorDependencies.size(), is(2)); + } + + @Test + public void should_get_constructor_dependencies_name_given_a_bean_id() { + List constructorDependencies = configConstructorXmlParser.getConstructorDependenciesName("director"); + + assertThat(constructorDependencies.get(0), is("movie")); + assertThat(constructorDependencies.size(), is(2)); + } + + @Test + public void should_get_properties_name_given_a_bean_id() { + List properties = configSetterXmlParser.getProperties("director"); + + assertThat(properties.get(0).getName(), is("movie")); + assertThat(properties.get(0).getRef(), is("movie")); + assertThat(properties.get(0).getType(), is("com.thoughtworks.elk.movie.Movie")); + assertThat(properties.size(), is(1)); + } +} \ No newline at end of file diff --git a/Elk-ioc/src/test/java/com/thoughtworks/elk/container/test/ElkContainerTest.java b/Elk-ioc/src/test/java/com/thoughtworks/elk/container/test/ElkContainerTest.java new file mode 100644 index 0000000..30abc3b --- /dev/null +++ b/Elk-ioc/src/test/java/com/thoughtworks/elk/container/test/ElkContainerTest.java @@ -0,0 +1,146 @@ +package com.thoughtworks.elk.container.test; + +import com.thoughtworks.elk.container.ElkContainer; +import com.thoughtworks.elk.container.exception.ElkContainerException; +import com.thoughtworks.elk.injection.ConstructorInjection; +import com.thoughtworks.elk.injection.SetterInjection; +import com.thoughtworks.elk.movie.*; +import com.thoughtworks.elk.movie.test.Hero; +import org.junit.Before; +import org.junit.Test; + +import java.lang.reflect.InvocationTargetException; + +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNull.notNullValue; + +public class ElkContainerTest { + + private ElkContainer elkContainer; + private ElkContainer elkContainerSetter; + + @Before + public void setUp() throws Exception { + elkContainer = new ElkContainer(new ConstructorInjection()); + elkContainerSetter = new ElkContainer(new SetterInjection()); + elkContainer.register(Hollywood.class); + elkContainer.register(Director.class); + elkContainerSetter.register(Titanic.class); + elkContainerSetter.register(Director.class); + } + + @Test + public void should_add_bean_and_get_bean_through_class() throws Exception { + Hollywood hollywood = elkContainer.getBean(Hollywood.class); + Titanic titanic = elkContainerSetter.getBean(Titanic.class); + + assertThat(hollywood, notNullValue()); + assertThat(titanic, notNullValue()); + } + + @Test + public void should_get_bean_added_all_dependencies() throws Exception { + elkContainer.register(Titanic.class); + + Director director = elkContainer.getBean(Director.class); + + assertThat(director, notNullValue()); + } + + @Test + public void should_find_implement_class_in_current_container() throws InvocationTargetException, ElkContainerException, InstantiationException, IllegalAccessException { + elkContainer.register(Titanic.class); + + assertThat(elkContainer.getBean(Movie.class), instanceOf(Movie.class)); + assertThat(elkContainer.getBean(Movie.class), notNullValue()); + assertThat(elkContainerSetter.getBean(Movie.class), notNullValue()); + } + + @Test + public void should_find_implement_class_in_parent_container() throws InvocationTargetException, ElkContainerException, InstantiationException, IllegalAccessException { + elkContainer.register(Titanic.class); + ElkContainer childContainer = new ElkContainer(new ConstructorInjection()); + elkContainer.addChildContainer(childContainer); + + assertThat(childContainer.getBean(Movie.class), instanceOf(Movie.class)); + assertThat(childContainer.getBean(Movie.class), notNullValue()); + } + + @Test + public void should_parameter_can_not_be_found_given_not_enough_bean() throws Exception { + boolean parameterAllInBeanList = elkContainer.isParameterAllInClassList(Director.class.getConstructor(Movie.class, Company.class).getParameterTypes()); + + assertFalse(parameterAllInBeanList); + } + + @Test + public void should_parameter_can_be_found_given_enough_bean() throws Exception { + elkContainer.register(Titanic.class); + + boolean parameterAllInBeanList = elkContainer.isParameterAllInClassList(Director.class.getConstructor(Movie.class, Company.class).getParameterTypes()); + + assertTrue(parameterAllInBeanList); + } + + @Test + public void should_get_implement_class_given_interface() throws Exception { + Class implementClass = elkContainer.findOneImplementClass(Company.class); + + assertThat(implementClass.toString(), is("class com.thoughtworks.elk.movie.Hollywood")); + } + + @Test + public void should_not_get_duplicate_bean() throws InvocationTargetException, ElkContainerException, InstantiationException, IllegalAccessException { + elkContainer.register(Titanic.class); + Movie movie = elkContainer.getBean(Movie.class); + Director director = elkContainer.getBean(Director.class); + + assertThat(movie, notNullValue()); + assertThat(director.getMovie(), is(movie)); + } + + @Test + public void should_add_bean_through_property_file() throws InvocationTargetException, ElkContainerException, InstantiationException, IllegalAccessException { + ElkContainer aElkContainer = new ElkContainer("testConstructorInjection.property"); + ElkContainer aElkContainerSetter = new ElkContainer("testSetterInjection.property"); + + assertThat(aElkContainer.getBean(Movie.class), notNullValue()); + assertThat(aElkContainerSetter.getBean(Movie.class), notNullValue()); + } + + @Test + public void should_get_bean_with_dependencies_through_property_file() throws InvocationTargetException, ElkContainerException, InstantiationException, IllegalAccessException { + ElkContainer aElkContainer = new ElkContainer("testConstructorInjection.property"); + ElkContainer aElkContainerSetter = new ElkContainer("testSetterInjection.property"); + + assertThat(aElkContainer.getBean(Movie.class), notNullValue()); + assertThat(aElkContainer.getBean(Director.class), notNullValue()); + assertThat(aElkContainer.getBean(Director.class).getMovie(), notNullValue()); + assertThat(aElkContainerSetter.getBean(DirectorSetter.class), notNullValue()); + assertThat(aElkContainerSetter.getBean(DirectorSetter.class).getMovie(), notNullValue()); + } + + @Test + public void shouldNotGetABeanWithoutAdded() throws InvocationTargetException, InstantiationException, IllegalAccessException, ElkContainerException { + elkContainer.register(Titanic.class); + + assertThat(elkContainer.getBean(Titanic.class), is(instanceOf(Titanic.class))); + assertThat(elkContainer.getBean(Hero.class), is(nullValue())); + } + + @Test + public void parentShouldContainsHero() { + ElkContainer container = new ElkContainer(new ConstructorInjection()); + container.register(Hero.class); + ElkContainer childContainer = new ElkContainer(new ConstructorInjection()); + container.addChildContainer(childContainer); + ElkContainer grandsonContainer = new ElkContainer(new ConstructorInjection()); + childContainer.addChildContainer(grandsonContainer); + assertThat(grandsonContainer.validScope(Hero.class), is(true)); + } +} diff --git a/Elk-ioc/src/test/java/com/thoughtworks/elk/container/test/ScopedContainerTest.java b/Elk-ioc/src/test/java/com/thoughtworks/elk/container/test/ScopedContainerTest.java new file mode 100644 index 0000000..a60fa32 --- /dev/null +++ b/Elk-ioc/src/test/java/com/thoughtworks/elk/container/test/ScopedContainerTest.java @@ -0,0 +1,55 @@ +package com.thoughtworks.elk.container.test; + + +import com.thoughtworks.elk.container.ElkContainer; +import com.thoughtworks.elk.container.exception.ElkContainerException; +import com.thoughtworks.elk.injection.ConstructorInjection; +import com.thoughtworks.elk.movie.Company; +import com.thoughtworks.elk.movie.Hollywood; +import com.thoughtworks.elk.movie.Titanic; +import com.thoughtworks.elk.movie.test.Hero; +import org.hamcrest.core.IsInstanceOf; +import org.junit.Before; +import org.junit.Test; + +import java.lang.reflect.InvocationTargetException; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNull.notNullValue; +import static org.hamcrest.core.IsNull.nullValue; +import static org.junit.Assert.assertThat; + +public class ScopedContainerTest { + private ElkContainer elkContainer; + private ElkContainer childContainer; + + @Before + public void before() { + elkContainer = new ElkContainer(new ConstructorInjection()); + childContainer = new ElkContainer(new ConstructorInjection()); + } + + @Test + public void shouldGenerateChildContainer() throws InvocationTargetException, ElkContainerException, InstantiationException, IllegalAccessException { + + elkContainer.register(Titanic.class); + elkContainer.addChildContainer(childContainer); + childContainer.register(Hero.class); + assertThat(childContainer.getBean(Titanic.class), is(IsInstanceOf.instanceOf(Titanic.class))); + assertThat(elkContainer.getBean(Hero.class), nullValue()); + } + + @Test + public void testAddChildContainer() throws InvocationTargetException, ElkContainerException, InstantiationException, IllegalAccessException { + ElkContainer parentContainer = new ElkContainer(new ConstructorInjection()); + ElkContainer childContainer = new ElkContainer(new ConstructorInjection()); + parentContainer.addChildContainer(childContainer); + parentContainer.register(Hollywood.class); + parentContainer.register(Company.class); + childContainer.register(Hero.class); + assertThat(childContainer.validScope(Company.class),is(true)); + assertThat(childContainer.getBean(Company.class), notNullValue()); + assertThat(parentContainer.getBean(Hero.class), is(nullValue())); + + } +} diff --git a/Elk-ioc/src/test/java/com/thoughtworks/elk/injection/test/ConstructorInjectionTest.java b/Elk-ioc/src/test/java/com/thoughtworks/elk/injection/test/ConstructorInjectionTest.java new file mode 100644 index 0000000..0d45a67 --- /dev/null +++ b/Elk-ioc/src/test/java/com/thoughtworks/elk/injection/test/ConstructorInjectionTest.java @@ -0,0 +1,30 @@ +package com.thoughtworks.elk.injection.test; + +import com.thoughtworks.elk.container.ElkContainer; +import com.thoughtworks.elk.injection.Injection; +import com.thoughtworks.elk.injection.ConstructorInjection; +import com.thoughtworks.elk.movie.Director; +import com.thoughtworks.elk.movie.Hollywood; +import com.thoughtworks.elk.movie.Titanic; +import org.junit.Test; + +import java.lang.reflect.InvocationTargetException; + +import static org.hamcrest.core.IsNull.notNullValue; +import static org.junit.Assert.assertThat; + +public class ConstructorInjectionTest { + @Test + public void should_build_a_bean_with_dependencies() + throws IllegalAccessException, InstantiationException, InvocationTargetException { + Injection injection = new ConstructorInjection(); + ElkContainer elkContainer = new ElkContainer(injection); + elkContainer.register(Titanic.class); + elkContainer.register(Hollywood.class); + elkContainer.register(Director.class); + + Director director = injection.buildBeanWithDependencies(Director.class, elkContainer); + + assertThat(director, notNullValue()); + } +} diff --git a/Elk-ioc/src/test/java/com/thoughtworks/elk/injection/test/SetterInjectionTest.java b/Elk-ioc/src/test/java/com/thoughtworks/elk/injection/test/SetterInjectionTest.java new file mode 100644 index 0000000..96d71ca --- /dev/null +++ b/Elk-ioc/src/test/java/com/thoughtworks/elk/injection/test/SetterInjectionTest.java @@ -0,0 +1,31 @@ +package com.thoughtworks.elk.injection.test; + +import com.thoughtworks.elk.container.ElkContainer; +import com.thoughtworks.elk.injection.Injection; +import com.thoughtworks.elk.injection.SetterInjection; +import com.thoughtworks.elk.movie.DirectorSetter; +import com.thoughtworks.elk.movie.Hollywood; +import com.thoughtworks.elk.movie.Titanic; +import org.junit.Test; + +import java.lang.reflect.InvocationTargetException; + +import static org.hamcrest.core.IsNull.notNullValue; +import static org.junit.Assert.assertThat; + +public class SetterInjectionTest { + @Test + public void should_build_a_bean_with_dependencies() + throws IllegalAccessException, InvocationTargetException, InstantiationException { + Injection injection = new SetterInjection(); + ElkContainer elkContainer = new ElkContainer(injection); + elkContainer.register(Titanic.class); + elkContainer.register(Hollywood.class); + elkContainer.register(DirectorSetter.class); + + DirectorSetter director = injection.buildBeanWithDependencies(DirectorSetter.class, elkContainer); + + assertThat(director, notNullValue()); + assertThat(director.getMovie(), notNullValue()); + } +} diff --git a/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/Company.java b/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/Company.java new file mode 100644 index 0000000..8e9528f --- /dev/null +++ b/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/Company.java @@ -0,0 +1,4 @@ +package com.thoughtworks.elk.movie; + +public interface Company { +} diff --git a/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/Director.java b/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/Director.java new file mode 100644 index 0000000..0dc4f63 --- /dev/null +++ b/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/Director.java @@ -0,0 +1,14 @@ +package com.thoughtworks.elk.movie; + +public class Director { + + private Movie movie; + + public Director(Movie movie, Company company) { + this.movie = movie; + } + + public Movie getMovie() { + return movie; + } +} diff --git a/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/DirectorSetter.java b/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/DirectorSetter.java new file mode 100644 index 0000000..9d93819 --- /dev/null +++ b/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/DirectorSetter.java @@ -0,0 +1,14 @@ +package com.thoughtworks.elk.movie; + +public class DirectorSetter { + + private Movie movie; + + public void setMovie(Movie movie) { + this.movie = movie; + } + + public Movie getMovie() { + return movie; + } +} diff --git a/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/Hollywood.java b/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/Hollywood.java new file mode 100644 index 0000000..f2fbd54 --- /dev/null +++ b/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/Hollywood.java @@ -0,0 +1,4 @@ +package com.thoughtworks.elk.movie; + +public class Hollywood implements Company { +} diff --git a/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/Movie.java b/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/Movie.java new file mode 100644 index 0000000..59ed2d0 --- /dev/null +++ b/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/Movie.java @@ -0,0 +1,4 @@ +package com.thoughtworks.elk.movie; + +public interface Movie { +} diff --git a/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/Titanic.java b/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/Titanic.java new file mode 100644 index 0000000..2b52bf5 --- /dev/null +++ b/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/Titanic.java @@ -0,0 +1,4 @@ +package com.thoughtworks.elk.movie; + +public class Titanic implements Movie { +} diff --git a/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/test/DirectorSetterTest.java b/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/test/DirectorSetterTest.java new file mode 100644 index 0000000..d09a3fd --- /dev/null +++ b/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/test/DirectorSetterTest.java @@ -0,0 +1,20 @@ +package com.thoughtworks.elk.movie.test; + +import com.thoughtworks.elk.movie.DirectorSetter; +import com.thoughtworks.elk.movie.Titanic; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsNull.notNullValue; + +public class DirectorSetterTest { + @Test + public void should_get_movie() { + DirectorSetter directorSetter = new DirectorSetter(); + + directorSetter.setMovie(new Titanic()); + + assertThat(directorSetter.getMovie(), notNullValue()); + } +} diff --git a/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/test/DirectorTest.java b/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/test/DirectorTest.java new file mode 100644 index 0000000..0aea7b3 --- /dev/null +++ b/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/test/DirectorTest.java @@ -0,0 +1,19 @@ +package com.thoughtworks.elk.movie.test; + +import com.thoughtworks.elk.movie.Director; +import com.thoughtworks.elk.movie.Hollywood; +import com.thoughtworks.elk.movie.Movie; +import com.thoughtworks.elk.movie.Titanic; +import org.junit.Test; + +import static org.hamcrest.core.IsNull.notNullValue; +import static org.junit.Assert.assertThat; + +public class DirectorTest { + @Test + public void should_get_his_movie() { + Director director = new Director(new Titanic(), new Hollywood()); + Movie movie = director.getMovie(); + assertThat(movie, notNullValue()); + } +} diff --git a/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/test/Hero.java b/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/test/Hero.java new file mode 100644 index 0000000..e4e6aa0 --- /dev/null +++ b/Elk-ioc/src/test/java/com/thoughtworks/elk/movie/test/Hero.java @@ -0,0 +1,8 @@ +package com.thoughtworks.elk.movie.test; + + +import com.thoughtworks.elk.movie.Movie; + +public class Hero implements Movie { + +} diff --git a/Elk-ioc/src/test/resources/testConstructorInjection.property b/Elk-ioc/src/test/resources/testConstructorInjection.property new file mode 100644 index 0000000..f95877f --- /dev/null +++ b/Elk-ioc/src/test/resources/testConstructorInjection.property @@ -0,0 +1,4 @@ +constructor +com.thoughtworks.elk.movie.Titanic +com.thoughtworks.elk.movie.Hollywood +com.thoughtworks.elk.movie.Director \ No newline at end of file diff --git a/Elk-ioc/src/test/resources/testConstructorInjection.xml b/Elk-ioc/src/test/resources/testConstructorInjection.xml new file mode 100644 index 0000000..1414dd6 --- /dev/null +++ b/Elk-ioc/src/test/resources/testConstructorInjection.xml @@ -0,0 +1,17 @@ + + + + + test + + + + + + + + + + + \ No newline at end of file diff --git a/Elk-ioc/src/test/resources/testSetterInjection.property b/Elk-ioc/src/test/resources/testSetterInjection.property new file mode 100644 index 0000000..5304d38 --- /dev/null +++ b/Elk-ioc/src/test/resources/testSetterInjection.property @@ -0,0 +1,3 @@ +setter +com.thoughtworks.elk.movie.Titanic +com.thoughtworks.elk.movie.DirectorSetter \ No newline at end of file diff --git a/Elk-ioc/src/test/resources/testSetterInjection.xml b/Elk-ioc/src/test/resources/testSetterInjection.xml new file mode 100644 index 0000000..c2ab578 --- /dev/null +++ b/Elk-ioc/src/test/resources/testSetterInjection.xml @@ -0,0 +1,16 @@ + + + + + test + + + + + + + + + + \ No newline at end of file