Skip to content

Commit

Permalink
v1.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
LemmoTresto committed Aug 10, 2019
1 parent fe4cb3e commit ccddd3a
Show file tree
Hide file tree
Showing 10 changed files with 365 additions and 15 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
2. [Maven](https://github.com/LemmoTresto/Migrational/wiki#maven)
3. [Gradle](https://github.com/LemmoTresto/Migrational/wiki#gradle)
4. [Examples](https://github.com/LemmoTresto/Migrational/wiki#examples)
5. [Support](#support)
5. [Documentation](https://migrational.lemmotresto.com/javadocs)
6. [Support](#support)



Expand Down
11 changes: 10 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

<groupId>me.max</groupId>
<artifactId>migrational</artifactId>
<version>1.0.0</version>
<version>1.1.0</version>

<name>Migrational</name>

Expand All @@ -48,6 +48,7 @@

<build>
<finalName>${project.name}-${project.version}</finalName>
<defaultGoal>clean package</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
Expand All @@ -71,4 +72,12 @@
</plugins>
</build>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>

</project>
65 changes: 53 additions & 12 deletions src/main/java/me/max/migrational/Migrator.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* This class will manage migration of one class and one data map.
* You can instantiate this class multiple times.
* This will always make a new instance of the on migration.
* This will always make a new instance of the class on migration unless {@link Migrator#migrateToMap()} is used.
*
* @author Max Berkelmans
* @see Migratable
Expand Down Expand Up @@ -98,11 +99,12 @@ public Migrator(Class<?> clazz) {

//Create a list of the migratable fields.
List<Field> migratableFields = new ArrayList<>();
//Loop over the declared fields and check if it is a field we migrate
//Loop over the declared fields and check if it is a field we migrateToClass
for (Field field : clazz.getDeclaredFields()) {
if (!field.isAnnotationPresent(Migratable.class) && !clazz.isAnnotationPresent(Migratable.class))
continue; //Needs to be our annotation
if (field.isAnnotationPresent(Exempt.class)) continue; //If the field is exempted then do not migrate.
if (field.isAnnotationPresent(Exempt.class))
continue; //If the field is exempted then do not migrateToClass.
if (Modifier.isPrivate(field.getModifiers())) field.setAccessible(true); //Allow us to access private fields
migratableFields.add(field);
}
Expand All @@ -120,30 +122,69 @@ public Migrator(Class<?> clazz) {
* @throws InvocationTargetException see {@link Constructor#newInstance(Object...)}
* @throws InstantiationException see {@link Constructor#newInstance(Object...)}
* @throws InvalidConstructorException if the constructor is null this will be thrown.
*
* @apiNote This method was renamed in version 1.0.0 -> 1.1.0 due to it being more consistent with other method namings
*
* @since 1.1.0
*/
public Object migrate() throws IllegalAccessException, InvocationTargetException, InstantiationException {
public Object migrateToClass() throws IllegalAccessException, InvocationTargetException, InstantiationException {
//Check if the constructor is null due to not being found on instantiation
if (constructor == null)
throw new InvalidConstructorException("Constructor provided was null, no matching constructor was found on instantiation make sure to set one.", constructor);

//Create a new instance of the object
lastMigratedObject = constructor.newInstance();

Map<String, Object> migratedMap = migrateToMap();
for (Field field : migratableFields) {
Migratable migratable = getAnnotationFromField(field); //Get the annotation
//Get correct key
String key = (migratable.key().isEmpty()) ? field.getName() : migratable.key();
field.set(lastMigratedObject, migratedMap.get(key));
}

return lastMigratedObject;
}

/**
* This method migrates to a map rather than straight to an object instance.
* This can be used to instantiate the object yourself with or without reflection.
*
* @return a map of migrated data
* @since 1.1.0
*/
public Map<String, Object> migrateToMap() {
Map<String, Object> migratedMap = new HashMap<>();

//Loop over known migratable fields.
for (Field field : migratableFields) {
Migratable migratable = field.isAnnotationPresent(Migratable.class) ? field.getAnnotation(Migratable.class) : field.getDeclaringClass().getAnnotation(Migratable.class); //Get the annotation
Migratable migratable = getAnnotationFromField(field); //Get the annotation
//Get the correct key if no key is given in the annotation use field name.
String key = (migratable.key().isEmpty()) ? field.getName() : migratable.key();
//Check if the data contains this field
if (data.containsKey(key)) {
//It does so lets set the data
field.set(lastMigratedObject, data.get(key));
migratedMap.put(key, data.get(key));
continue;
}
//It does not, so let's set the default value
field.set(lastMigratedObject, migratable.defaultValue().isEmpty() ? field.get(lastMigratedObject) : migratable.defaultValue());
migratedMap.put(key, migratable.defaultValue().isEmpty() ? data.get(key) : migratable.defaultValue());
}
return lastMigratedObject;

//Return the migrated map.
return migratedMap;
}

/**
* Retrieve the {@link Migratable} annotation from a field
* It works by checking the field for the annotation and if it exists return else get the class's annotation.
*
* @param field the field to get the annotation from
* @return the {@link Migratable} annotation
* @since 1.1.0
*/
private Migratable getAnnotationFromField(Field field) {
return field.isAnnotationPresent(Migratable.class) ? field.getAnnotation(Migratable.class) : field.getDeclaringClass().getAnnotation(Migratable.class);
}

/**
Expand All @@ -166,13 +207,13 @@ public Constructor<?> getConstructor() {
}

/**
* Set the constructor to be used to migrate.
* Set the constructor to be used to migrateToClass.
*
* @param constructor the constructor to use
* @throws InvalidConstructorException if the constructor is null or has parameters or is not of the correct class
*/
public void setConstructor(Constructor<?> constructor) throws InvalidConstructorException {
if (constructor == null) throw new InvalidConstructorException("Constructor provided was null", constructor);
if (constructor == null) throw new InvalidConstructorException("Constructor provided was null", null);
if (!constructor.getDeclaringClass().equals(migratableFields[0].getDeclaringClass()))
throw new InvalidConstructorException("The provided constructor was not from the correct class", constructor);
if (constructor.getParameterCount() != 0)
Expand All @@ -183,7 +224,7 @@ public void setConstructor(Constructor<?> constructor) throws InvalidConstructor
/**
* Get the data which will be migrated
*
* @return the data to migrate
* @return the data to migrateToClass
*/
public Map<String, Object> getData() {
return data;
Expand All @@ -192,7 +233,7 @@ public Map<String, Object> getData() {
/**
* Set the data to be migrated
*
* @param data the data to migrate
* @param data the data to migrateToClass
*/
public void setData(Map<String, Object> data) {
this.data = data;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
/**
* The exception to be thrown when the provided constructor is invalid
* Cases of this happening is when the constructor was not found during instantiation
* Calling {@link me.max.migrational.Migrator#migrate()} will then throw this exception
* Calling {@link me.max.migrational.Migrator#migrateToClass()} will then throw this exception
* Another case is if the provided constructor in {@link me.max.migrational.Migrator#setConstructor(java.lang.reflect.Constructor)} has parameters
* If this constructor is not of class which was passed on in instantiation it will also throw this exception.
*
Expand Down
1 change: 1 addition & 0 deletions src/main/java/me/max/migrational/package-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
/**
* This is the root package of the Migrational libary
* {@link me.max.migrational.annotations} for all annotations
* {@link me.max.migrational.exceptions} for all exceptions
* {@link me.max.migrational.Migrator} should be instantiated to use this library
*
* @author Max Berkelmans
Expand Down
82 changes: 82 additions & 0 deletions src/test/java/me/max/migrational/ClassMigrationTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
*
* * Copyright 2019 Max Berkelmans
* *
* * 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 me.max.migrational;

import me.max.migrational.testobjects.ClassObject;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

/**
* This is test class and will check if migration is still working correctly
* This was made to not need to manually test if it still works after making changes
*
* @author Max Berkelmans
* @since 1.1.0
*/
public class ClassMigrationTest {

private static ClassObject testObject;

@BeforeClass
public static void setUp() throws IllegalAccessException, InstantiationException, InvocationTargetException {
Map<String, Object> data = new HashMap<>();
data.put("name", "Stijn");

testObject = (ClassObject) new Migrator(ClassObject.class, data).migrateToClass();

}

@AfterClass
public static void tearDown() {
testObject = null;
}

@Test
public void migrate_Name_ReturnsStijn() {
final String expected = "Stijn";

final String actual = testObject.getName();

assertEquals(expected, actual);
}

@Test
public void migrate_Age_ReturnsTwentySeven() {
final int expected = 27;

final int actual = testObject.getAge();

assertEquals(expected, actual);
}

@Test
public void migrate_IsCool_ReturnsTrue() {
final boolean actual = testObject.isCool();

assertTrue(actual);
}
}
82 changes: 82 additions & 0 deletions src/test/java/me/max/migrational/FieldMigrationTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
*
* * Copyright 2019 Max Berkelmans
* *
* * 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 me.max.migrational;

import me.max.migrational.testobjects.FieldObject;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import static org.junit.Assert.assertEquals;

/**
* This test class will check for migration of {@link me.max.migrational.annotations.Migratable} {@link java.lang.reflect.Field}s.
*
* @author Max Berkelmans
* @since 1.1.0
*/
public class FieldMigrationTest {

private static FieldObject testObject;

@BeforeClass
public static void setUp() throws IllegalAccessException, InstantiationException, InvocationTargetException {
Map<String, Object> data = new HashMap<>();
data.put("name", "Stijn");
data.put("age", 20);

testObject = (FieldObject) new Migrator(FieldObject.class, data).migrateToClass();
}

@AfterClass
public static void tearDown() {
testObject = null;
}

@Test
public void migrate_Name_ReturnsStijn() {
final String expected = "Stijn";

final String actual = testObject.getName();

assertEquals(expected, actual);
}

@Test
public void migrate_Age_ReturnsTwenty() {
final int expected = 20;

final int actual = testObject.getAge();

assertEquals(expected, actual);
}

@Test
public void migrate_Country_ReturnsNetherlands() {
final String expected = "Netherlands";

final String actual = testObject.getCountry();

assertEquals(expected, actual);
}
}
29 changes: 29 additions & 0 deletions src/test/java/me/max/migrational/package-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
*
* * Copyright 2019 Max Berkelmans
* *
* * 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.
*
*/

/**
* This is the root package for testing migrational.
* This package contains all tests for migrating.
* These classes are made to not have to manually check if migration is still working.
* <p>
* The package {@link me.max.migrational.testobjects} contains all the test objects used by the test classes.
*
* @author Max Berkelmans
* @since 1.1.0
*/
package me.max.migrational;
Loading

0 comments on commit ccddd3a

Please sign in to comment.