first commit
This commit is contained in:
commit
e12f3b284d
11 changed files with 663 additions and 0 deletions
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Created by .ignore support plugin (hsz.mobi)
|
||||
### Example user template template
|
||||
### Example user template
|
||||
|
||||
# IntelliJ project files
|
||||
.idea
|
||||
*.iml
|
||||
out
|
||||
gen
|
||||
target/
|
||||
8
README.md
Normal file
8
README.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
This project is called Edie after Edie Sedgwick who was one of the artists in Andy Warhols Factory.
|
||||
The film about her life is called Factory Girl (2006).
|
||||
This project was inspired by the FactoryGirl project that was later renamed FactoryBot.
|
||||
|
||||
|
||||
* https://en.wikipedia.org/wiki/Edie_Sedgwick
|
||||
* https://www.imdb.com/title/tt0432402
|
||||
* https://hn.algolia.com/?q=factorybot
|
||||
47
pom.xml
Normal file
47
pom.xml
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>nl.sander</groupId>
|
||||
<artifactId>edie</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>info.cukes</groupId>
|
||||
<artifactId>cucumber-core</artifactId>
|
||||
<version>1.2.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.5.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0-M4</version>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>**/*Tests.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
||||
9
src/main/java/shautvast/edie/Adapter.java
Normal file
9
src/main/java/shautvast/edie/Adapter.java
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
package shautvast.edie;
|
||||
|
||||
/**
|
||||
* An Adapter lambda is used to alter instances after creation according to the template.
|
||||
* @param <T>
|
||||
*/
|
||||
public interface Adapter<T> {
|
||||
public void adapt(T input);
|
||||
}
|
||||
127
src/main/java/shautvast/edie/Definition.java
Normal file
127
src/main/java/shautvast/edie/Definition.java
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
package shautvast.edie;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Contains the specification for creating instances. They are either Supplier lambda or a Constructor instance.
|
||||
*/
|
||||
public class Definition<T> {
|
||||
|
||||
/* contains the class instances for creating elements in a List */
|
||||
private final List<Class<?>> typesInList = new ArrayList<>();
|
||||
|
||||
/* type of the object that will be created*/
|
||||
private Class<T> type;
|
||||
|
||||
/* constructor class for creating instances*/
|
||||
private Constructor<T> constructor;
|
||||
|
||||
/* lambda that can be used to create instances*/
|
||||
private Supplier<T> template;
|
||||
|
||||
/*
|
||||
* Constructor that takes a type. The constructor member variable must be added later on.
|
||||
*
|
||||
* @param type Type of the instances this Definition will create.
|
||||
*/
|
||||
Definition(Class<T> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor that takes a Supplier lambda to create instances.
|
||||
*
|
||||
* @param supplier
|
||||
*/
|
||||
Definition(Supplier<T> supplier) {
|
||||
this.template = supplier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to create the instance, once the definition is constructed.
|
||||
* Can be called directly, or via the Factory.build() method
|
||||
*
|
||||
* @return a new instance by calling the supplier or a constructor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T build() {
|
||||
if (template != null) {
|
||||
return template.get();
|
||||
} else if (constructor != null) {
|
||||
if (!typesInList.isEmpty()) {
|
||||
return (T) newInstance(new Object[]{
|
||||
typesInList.stream()
|
||||
.map(Factory::build)
|
||||
.collect(Collectors.toList())});
|
||||
} else {
|
||||
Object[] args = Arrays.stream(constructor.getParameterTypes())
|
||||
.map(Factory::build)
|
||||
.collect(Collectors.toList()).toArray(new Object[]{});
|
||||
return (T) newInstance(args);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException("Template and constructor cannot both be empty");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build method that takes an adapter lambda for customizing the final object
|
||||
* Example:
|
||||
* Definition<Person> personDef = define(Person.class, () -> new Person("Sander", 48));
|
||||
* Person person = personDef.build(p -> {
|
||||
* p.setName("Harry");
|
||||
* return p;
|
||||
* });
|
||||
* @param adapter
|
||||
* @return
|
||||
*/
|
||||
public T build(Adapter<T> adapter) {
|
||||
T instance = template.get();
|
||||
adapter.adapt(instance);
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Object newInstance(Object[] args) {
|
||||
try {
|
||||
return constructor.newInstance(args);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Example:
|
||||
* Definition<Employee> employeeDef = Factory.define(Employee.class).withConstructorArgs(Person.class);
|
||||
* Can be used given that Employee has a constructor with one parameterof type Person
|
||||
* This will use this constructor to create instances.
|
||||
*
|
||||
* @param parameterTypes varargs argument for the parameters of the constructor to look up.
|
||||
*
|
||||
* @return a Definition with the correct constructor
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Definition<T> withConstructorArgs(Class... parameterTypes) {
|
||||
try {
|
||||
this.constructor = type.getConstructor(parameterTypes);
|
||||
return this;
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Definition<T> withConstructorArgs(List<Class<?>> typesToConstruct) {
|
||||
try {
|
||||
this.constructor = type.getConstructor(List.class);
|
||||
this.typesInList.addAll(typesToConstruct);
|
||||
return this;
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
100
src/main/java/shautvast/edie/Factory.java
Normal file
100
src/main/java/shautvast/edie/Factory.java
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
package shautvast.edie;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
@SuppressWarnings({"rawtypes","unchecked"})
|
||||
public class Factory {
|
||||
|
||||
private static final ConcurrentMap<Class<?>, Definition> definitions = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Creates a definition for the given type, using a Supplier that will create that type every time build() is called.
|
||||
*
|
||||
* @param type Class that specifies what type must be created
|
||||
* @param supplier Lambda that creates the given type
|
||||
* @param <T> Generic type of the created Definition
|
||||
* @return A Definition that can be called directly to create Type instances
|
||||
*/
|
||||
public static <T> Definition<T> define(Class<T> type, Supplier<T> supplier) {
|
||||
Definition<T> definition = new Definition<>(supplier);
|
||||
definitions.put(type, definition);
|
||||
return definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a definition for the given type.
|
||||
* when using this method, the resulting definition is not complete yet. See Definition.withConstructor.
|
||||
*
|
||||
* @param type Class that specifies what type must be created
|
||||
* @param <T> Generic type of the created Definition
|
||||
* @return A Definition that can be called directly to create Type instances
|
||||
*/
|
||||
public static <T> Definition<T> define(Class<T> type) {
|
||||
Definition<T> definition = new Definition<>(type);
|
||||
definitions.put(type, definition);
|
||||
return definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the instance for the specified type, using an Adapter lambda that can alter specific attributes if needed.
|
||||
* It's logic is delegated to the Definition for the type.
|
||||
* <p>
|
||||
* Example:
|
||||
* Definition<Person> personDef = define(Person.class, () -> new Person("Sander", 48));
|
||||
* <p>
|
||||
* Person person = personDef.build(p -> {
|
||||
* p.setName("Harry");
|
||||
* return p;
|
||||
* });
|
||||
* <p>
|
||||
* The template name is 'Sander' but the person instance has a different name.
|
||||
*
|
||||
* @param type Class to denote the type to create.
|
||||
* @param adapter Can be used to change the type after creation
|
||||
* @return an instance of the given type using template and adapter
|
||||
*/
|
||||
public static <T> T build(Class<T> type, Adapter<T> adapter) {
|
||||
return getDefinition(type).build(adapter);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds the instance for the specified type.
|
||||
* It's logic is delegated to the Definition for the type.
|
||||
* <p>
|
||||
* Example:
|
||||
* Definition<Person> personDef = define(Person.class, () -> new Person("Sander", 48));
|
||||
* <p>
|
||||
* Person person = personDef.build()
|
||||
* will always yields a new instance
|
||||
*
|
||||
* @param type Class to denote the type to create.
|
||||
* @return an instance of the given type using template and adapter
|
||||
*/
|
||||
public static <T> T build(Class<T> type) {
|
||||
return getDefinition(type).build();
|
||||
}
|
||||
|
||||
private static <T> Definition<T> getDefinition(Class<T> type) {
|
||||
Definition<T> definition = definitions.get(type);
|
||||
if (definition == null) {
|
||||
throw new IllegalStateException("definition not found for " + type);
|
||||
} else {
|
||||
return definition;
|
||||
}
|
||||
}
|
||||
|
||||
static void checkTypes(Class<?>[] typesToConstruct) {
|
||||
if (Arrays.stream(typesToConstruct)
|
||||
.anyMatch(type -> !definitions.containsKey(type))) {
|
||||
throw new IllegalStateException("not all parameters bound to definition");
|
||||
}
|
||||
}
|
||||
}
|
||||
106
src/main/java/shautvast/edie/FactoryHelper.java
Normal file
106
src/main/java/shautvast/edie/FactoryHelper.java
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
package shautvast.edie;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
|
||||
public class FactoryHelper {
|
||||
|
||||
/* unnamed counter */
|
||||
private static LongAdder globalCounter = new LongAdder();
|
||||
/* contains named counters */
|
||||
private static ConcurrentMap<String, LongAdder> namedCounters = new ConcurrentHashMap<>();
|
||||
/* util for random numbers*/
|
||||
private static Random random = new Random();
|
||||
|
||||
/**
|
||||
* Values that need an index can be created with this helper method.
|
||||
* <p>
|
||||
* Example:
|
||||
* Factory.define(Person.class, () -> new Person("person[" + increment()+"]", 33));
|
||||
*
|
||||
* @return a number that increments on every invocation of the type supplier.
|
||||
*/
|
||||
public static long increment() {
|
||||
return incrementAndGet(globalCounter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an named incrementer that is called every time the Factory creates the object.
|
||||
* <p>
|
||||
* Example:
|
||||
* Factory.define(Person.class, () -> new Person("person[" + increment("personIndex")+"]", 33));
|
||||
*
|
||||
* @param name the name of the incrementer
|
||||
* @return a number that increments every time this method is called with the same name.
|
||||
*/
|
||||
public static long increment(String name) {
|
||||
return incrementAndGet(namedCounters.computeIfAbsent(name, k -> new LongAdder()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random 64 bit integer number.
|
||||
* <p>
|
||||
* Example:
|
||||
* define(Person.class, () -> new Person("Sander", randomLong()));
|
||||
*
|
||||
* @return a random number on every invocation
|
||||
*/
|
||||
public static long randomLong() {
|
||||
return random.nextLong();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random 32 bit integer number.
|
||||
* <p>
|
||||
* Example:
|
||||
* define(Person.class, () -> new Person("Sander", randomInt()));
|
||||
*
|
||||
* @return a random number on every invocation
|
||||
*/
|
||||
public static int randomInt() {
|
||||
return random.nextInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random 32 bit integer number below an upper bound.
|
||||
* <p>
|
||||
* Example:
|
||||
* define(Person.class, () -> new Person("Sander", randomInt(100)));
|
||||
*
|
||||
* @param bound exlusive upper bound
|
||||
* @return a random number on every invocation
|
||||
*/
|
||||
public static int randomInt(int bound) {
|
||||
return random.nextInt(bound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random 64 bit floating point number below an upper bound.
|
||||
*
|
||||
* @return a random number on every invocation
|
||||
*/
|
||||
public static double randomDouble() {
|
||||
return random.nextDouble();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for the creation of factory types within a list.
|
||||
*
|
||||
* @param typesToConstruct Any types (should be known in Factory) that are to be elements in a List
|
||||
* @return A List of the same types. See
|
||||
*/
|
||||
public static List<Class<?>> listOf(Class<?>... typesToConstruct) {
|
||||
Factory.checkTypes(typesToConstruct);
|
||||
return Arrays.asList(typesToConstruct);
|
||||
}
|
||||
|
||||
private static long incrementAndGet(LongAdder longAdder) {
|
||||
long value = longAdder.longValue();
|
||||
longAdder.increment();
|
||||
return value;
|
||||
}
|
||||
}
|
||||
143
src/test/java/shautvast/edie/FactoryTests.java
Normal file
143
src/test/java/shautvast/edie/FactoryTests.java
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
package shautvast.edie;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import shautvast.edie.testdomain.Company;
|
||||
import shautvast.edie.testdomain.Employee;
|
||||
import shautvast.edie.testdomain.Person;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@DisplayName("Assertions for the factory and definitions")
|
||||
public class FactoryTests {
|
||||
@Test
|
||||
@DisplayName("Should build instance with definition.build()")
|
||||
public void simpleTemplate() {
|
||||
Definition<Person> personDef = Factory.define(Person.class, () -> new Person("Sander", 48));
|
||||
|
||||
Person person = personDef.build();
|
||||
|
||||
Assertions.assertEquals("Sander", person.getName());
|
||||
Assertions.assertEquals(48, person.getAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should build instance with Factory.build()")
|
||||
public void simpleTemplateStatic() {
|
||||
Factory.define(Person.class, () -> new Person("Sander", 48));
|
||||
|
||||
Person person = Factory.build(Person.class);
|
||||
|
||||
Assertions.assertEquals("Sander", person.getName());
|
||||
Assertions.assertEquals(48, person.getAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should build a customized instance while the other attributes are according to the template")
|
||||
public void simpleTemplateAlteration() {
|
||||
Factory.define(Person.class, () -> new Person("Sander", 48));
|
||||
|
||||
Person person = Factory.build(Person.class, p -> p.setName("Harry"));
|
||||
|
||||
Assertions.assertEquals("Harry", person.getName());
|
||||
Assertions.assertEquals(48, person.getAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should create different values for an attribute for every instance")
|
||||
public void counters() {
|
||||
Definition<Person> personDef = Factory.define(Person.class, () -> new Person("Sander", 48));
|
||||
|
||||
Person person = personDef.build(p ->
|
||||
p.setName("Harry" + FactoryHelper.increment())
|
||||
);
|
||||
|
||||
Assertions.assertEquals("Harry0", person.getName());
|
||||
Assertions.assertEquals(48, person.getAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should lookup a constructor with a nested type definition and create nested instances")
|
||||
public void nestedDefinitionsWithConstructor() {
|
||||
Factory.define(Person.class, () -> new Person("Sander", FactoryHelper.randomInt(100)));
|
||||
Definition<Employee> employeeDef = Factory.define(Employee.class).withConstructorArgs(Person.class);
|
||||
|
||||
Employee employee = employeeDef.build();
|
||||
|
||||
Assertions.assertEquals("Sander", employee.getPerson().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should create nested instances using only suppliers")
|
||||
public void nestedDefinitionsWithoutReflection() {
|
||||
Definition<Person> personDef = Factory.define(Person.class, () -> new Person("Sander", FactoryHelper.randomInt(100)));
|
||||
Definition<Employee> employeeDef = Factory.define(Employee.class, () -> new Employee(personDef.build()));
|
||||
|
||||
Employee employee = employeeDef.build();
|
||||
|
||||
Assertions.assertEquals("Sander", employee.getPerson().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should create random attributes for every instance")
|
||||
public void randomInts() {
|
||||
Definition<Person> personDef = Factory.define(Person.class, () -> new Person("Sander", FactoryHelper.randomInt(100)));
|
||||
|
||||
Person person = personDef.build();
|
||||
|
||||
Assertions.assertEquals("Sander", person.getName());
|
||||
assertTrue(person.getAge() < 100);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should create an object with a list of factory produced elements")
|
||||
public void definitionsList() {
|
||||
Factory.define(Person.class, () -> new Person("Sander" + FactoryHelper.increment(), FactoryHelper.randomInt(100)));
|
||||
Factory.define(Employee.class).withConstructorArgs(Person.class);
|
||||
Factory.define(Company.class).withConstructorArgs(FactoryHelper.listOf(Employee.class, Employee.class));
|
||||
|
||||
Company company = Factory.build(Company.class);
|
||||
|
||||
Assertions.assertEquals(2, company.getEmployees().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should create an object with a list of factory produced elements without reflection")
|
||||
public void definitionsListWithoutReflection() {
|
||||
Factory.define(Person.class, () -> new Person("Sander", 10));
|
||||
Factory.define(Employee.class).withConstructorArgs(Person.class);
|
||||
Factory.define(Company.class, () -> new Company(Arrays.asList(Factory.build(Employee.class), Factory.build(Employee.class))));
|
||||
|
||||
Company company = Factory.build(Company.class);
|
||||
|
||||
Assertions.assertEquals(2, company.getEmployees().size());
|
||||
Assertions.assertTrue(company.getEmployees().contains(new Employee(new Person("Sander", 10))));
|
||||
Assertions.assertTrue(company.getEmployees().contains(new Employee(new Person("Sander", 10))));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should create a list with two elements")
|
||||
public void definitionsListWithIncrementInNestedDefinition() {
|
||||
Factory.define(Person.class, () -> new Person("Sander" + FactoryHelper.increment("sander"), 10));
|
||||
Factory.define(Employee.class).withConstructorArgs(Person.class);
|
||||
Factory.define(Company.class, () -> new Company(Arrays.asList(Factory.build(Employee.class), Factory.build(Employee.class))));
|
||||
|
||||
Company company = Factory.build(Company.class);
|
||||
|
||||
Assertions.assertEquals(2, company.getEmployees().size());
|
||||
Assertions.assertTrue(company.getEmployees().contains(new Employee(new Person("Sander0", 10))));
|
||||
Assertions.assertTrue(company.getEmployees().contains(new Employee(new Person("Sander1", 10))));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Method withConstructor for a constructor with the wrong types should raise an exception")
|
||||
public void constructorNotFound() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class, () ->
|
||||
Factory.define(Person.class).withConstructorArgs(String.class));
|
||||
}
|
||||
}
|
||||
23
src/test/java/shautvast/edie/testdomain/Company.java
Normal file
23
src/test/java/shautvast/edie/testdomain/Company.java
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
package shautvast.edie.testdomain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Company {
|
||||
private final List<Employee> employees=new ArrayList<>();
|
||||
|
||||
public Company(List<Employee> employees) {
|
||||
this.employees.addAll(employees);
|
||||
}
|
||||
|
||||
public List<Employee> getEmployees() {
|
||||
return employees;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Company{" +
|
||||
"employees=" + employees +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
39
src/test/java/shautvast/edie/testdomain/Employee.java
Normal file
39
src/test/java/shautvast/edie/testdomain/Employee.java
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
package shautvast.edie.testdomain;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Employee {
|
||||
private Person person;
|
||||
|
||||
public Employee(Person person) {
|
||||
this.person = person;
|
||||
}
|
||||
|
||||
public Person getPerson() {
|
||||
return person;
|
||||
}
|
||||
|
||||
public void setPerson(Person person) {
|
||||
this.person = person;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Employee employee = (Employee) o;
|
||||
return Objects.equals(person, employee.person);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(person);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Employee{" +
|
||||
"person=" + person +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
51
src/test/java/shautvast/edie/testdomain/Person.java
Normal file
51
src/test/java/shautvast/edie/testdomain/Person.java
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
package shautvast.edie.testdomain;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Person {
|
||||
private String name;
|
||||
private int age;
|
||||
|
||||
public Person(String name, int age) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Person person = (Person) o;
|
||||
return age == person.age &&
|
||||
Objects.equals(name, person.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, age);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Person{" +
|
||||
"name='" + name + '\'' +
|
||||
", age=" + age +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue