- Your repositories should have a common method save() and your mappers a mapToTest() that you can define as your interface or base class. Also your test-objects should have a common interface or base class. Let's assume that you can do that. If you cannot do that, then your code inside the if-statements is too different and you could only solve that by a map with key=TestType and value=lambda-expression (or in other words, value = object of abstract classes derived from Runnable with the code inside each run-method.).
- Do you really need so much new classes and instances for each new if-statement? That means for a third if-statement you would need to write new classes Test3, Test3Mapper, Tests3Repository and need to insert additional member variables into your main method for it? I fear your code quickly becomes unmaintainable. Because of all these definitions, my code example below can not be done simpler anymore. Try to write only a few classes instead and define a factory which returns different instances of it. The code example below would be much shorter if you for example would have an array of TestRepositories (or their factory names) instead of single variables test1Repository, test2Repository etc.
- You wrote that you cannot inject repositories and mappers in your enum. But you can inject them in your main class and pass them to the enum instances.
- Your enum name is "TEST1", but in your map "body" you have stored "test1". So you must somehow map this label to the enum. For that, you need an internal static hash map inside the enum. You will not need it if you store ""TEST1" inside your map instead. But let's assume both are independent and cannot be converted via toUpperCase() etc., so we need to define the method valueOfLabel() in the enum and pass this label in the constructor.
Here is the enum:
private enum TestType {
TEST1 ("test1", test1Repository, test1Mapper),
TEST2 ("test2", test2Repository, test2Mapper);
private String label;
private TestRepository testRepository;
private TestMapper testMapper;
private static final Map<String, TestType> labelMap = new HashMap<>();
static {
for (TestType testType: values()) {
labelMap.put(testType.label, testType);
}
}
public static TestType valueOfLabel(String label) {
return labelMap.get(label);
}
TestType(String label, TestRepository testRepository, TestMapper testMapper) {
this.label = label;
this.testRepository = testRepository;
this.testMapper = testMapper;
}
public void saveInDB(Map<String, Object> body) {
Test test = testMapper.mapToTest(body);
// TODO logic here
System.out.println("test=" + test.getClass().getSimpleName() + ", this=" + this);
testRepository.save(test);
}
public String toString() {
return "TestType [label=" + label + ", testRepository=" + testRepository.getClass().getSimpleName() + ", testMapper=" + testMapper.getClass().getSimpleName() + "]";
}
}
Here is the replacement for your if-statements and testing this method:
private void test(Map<String, Object> body) {
TestType.valueOfLabel((String) body.get("type")).saveInDB(body);
}
public static void main(String[] args) {
Map<String, Object> body = new HashMap<>();
body.put("type", "test1");
new Main().test(body);
body.put("type", "test2");
new Main().test(body);
}
Here is the test console output:
test=Test1, this=TestType [label=test1, testRepository=Test1Repository, testMapper=Test1Mapper]
test=Test2, this=TestType [label=test2, testRepository=Test2Repository, testMapper=Test2Mapper]
Here is the full program with all the clases needed to run it.
Not everybody has Spring or has it set up, so to simplify the solution that everybody can run, I just created the needed classes.
Feel free to change the code to autowire them instead.
package main;
import java.util.HashMap;
import java.util.Map;
public class Main
{
// tests
static class Test {
}
static class Test1 extends Test {
}
static class Test2 extends Test {
}
// repositories
static class TestRepository {
public void save(Test test) {
// TODO save it
}
}
static class Test1Repository extends TestRepository {
}
static class Test2Repository extends TestRepository {
}
// mappers
static class TestMapper {
private Test test;
public TestMapper(Test test) {
this.test = test;
}
public Test mapToTest(Object body) {
// TODO get some data out of body and call test with it
return test;
}
}
static class Test1Mapper extends TestMapper {
public Test1Mapper(Test test) {
super(test);
}
}
static class Test2Mapper extends TestMapper {
public Test2Mapper(Test test) {
super(test);
}
}
// autowired
private static Test1Repository test1Repository = new Test1Repository();
private static Test2Repository test2Repository = new Test2Repository();
private static Test1Mapper test1Mapper = new Test1Mapper(new Test1());
private static Test2Mapper test2Mapper = new Test2Mapper(new Test2());
// enum
private enum TestType {
TEST1 ("test1", test1Repository, test1Mapper),
TEST2 ("test2", test2Repository, test2Mapper);
private String label;
private TestRepository testRepository;
private TestMapper testMapper;
private static final Map<String, TestType> labelMap = new HashMap<>();
static {
for (TestType testType: values()) {
labelMap.put(testType.label, testType);
}
}
public static TestType valueOfLabel(String label) {
return labelMap.get(label);
}
TestType(String label, TestRepository testRepository, TestMapper testMapper) {
this.label = label;
this.testRepository = testRepository;
this.testMapper = testMapper;
}
public void saveInDB(Map<String, Object> body) {
Test test = testMapper.mapToTest(body);
// TODO logic here
System.out.println("test=" + test.getClass().getSimpleName() + ", this=" + this);
testRepository.save(test);
}
public String toString() {
return "TestType [label=" + label + ", testRepository=" + testRepository.getClass().getSimpleName() + ", testMapper=" + testMapper.getClass().getSimpleName() + "]";
}
}
// test
public static void main(String[] args) {
Map<String, Object> body = new HashMap<>();
body.put("type", "test1");
new Main().test(body);
body.put("type", "test2");
new Main().test(body);
}
// method under test
private void test(Map<String, Object> body) {
TestType.valueOfLabel((String) body.get("type")).saveInDB(body);
}
}