diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33e7f6f..6c1f23b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,6 +22,14 @@ jobs: with: java-version: ${{ matrix.java }} distribution: 'zulu' - cache: 'maven' + - name: Cache local Maven repository + uses: actions/cache@v4 + continue-on-error: true + with: + path: ~/.m2/repository + key: cache-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + cache-maven-${{ hashFiles('**/pom.xml') }} + cache-maven- - name: Build run: mvn --no-transfer-progress -B clean package diff --git a/pom.xml b/pom.xml index e16189d..0ea8480 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,7 @@ 17 17 - 3.1.1 + 3.2.6 7.7.0 diff --git a/src/main/java/org/modelmapper/record/RecordConstructorInjector.java b/src/main/java/org/modelmapper/record/RecordConstructorInjector.java new file mode 100644 index 0000000..1f78777 --- /dev/null +++ b/src/main/java/org/modelmapper/record/RecordConstructorInjector.java @@ -0,0 +1,31 @@ +package org.modelmapper.record; + +import java.lang.reflect.Constructor; +import java.lang.reflect.RecordComponent; +import java.util.stream.IntStream; +import org.modelmapper.ConstructorParam; +import org.modelmapper.spi.ConstructorInjector; + +import java.util.List; + +public class RecordConstructorInjector implements ConstructorInjector { + + @Override + public List getParameters(Class type) { + if (!isApplicable(type)) { + throw new IllegalArgumentException( + String.format("Type %s is not a Record type.", type.getName())); + } + Constructor constructor = type.getDeclaredConstructors()[0]; + RecordComponent[] components = type.getRecordComponents(); + return IntStream.range(0, components.length) + .mapToObj(index -> new ConstructorParam(constructor, index, components[index].getName(), + components[index].getType())) + .toList(); + } + + @Override + public boolean isApplicable(Class type) { + return Record.class.isAssignableFrom(type); + } +} diff --git a/src/main/java/org/modelmapper/record/RecordModule.java b/src/main/java/org/modelmapper/record/RecordModule.java index ed3f3b0..03da7dc 100644 --- a/src/main/java/org/modelmapper/record/RecordModule.java +++ b/src/main/java/org/modelmapper/record/RecordModule.java @@ -7,5 +7,7 @@ public class RecordModule implements Module { @Override public void setupModule(ModelMapper modelMapper) { modelMapper.getConfiguration().addValueReader(new RecordValueReader()); + modelMapper.getConfiguration().addConstructorInjector( + new RecordConstructorInjector()); } } diff --git a/src/test/java/org/modelmapper/record/RecordConstructorInjectorTest.java b/src/test/java/org/modelmapper/record/RecordConstructorInjectorTest.java new file mode 100644 index 0000000..f4ec7a7 --- /dev/null +++ b/src/test/java/org/modelmapper/record/RecordConstructorInjectorTest.java @@ -0,0 +1,45 @@ +package org.modelmapper.record; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +import org.modelmapper.ModelMapper; +import org.modelmapper.config.Configuration.AccessLevel; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** + * Tests the mapping of a POJO to a Record. + */ +@Test +public class RecordConstructorInjectorTest { + private ModelMapper modelMapper; + + record UserRecord(String userId, String userName) { + } + + static class User { + String userId; + String userName; + } + + @BeforeMethod + public void setup() { + modelMapper = new ModelMapper() + .registerModule(new RecordModule()); + modelMapper.getConfiguration() + .setFieldMatchingEnabled(true) + .setFieldAccessLevel(AccessLevel.PACKAGE_PRIVATE) + .setMethodAccessLevel(AccessLevel.PACKAGE_PRIVATE); + } + + public void shouldMapToRecord() { + User user = new User(); + user.userId = "id"; + user.userName = "name"; + + UserRecord record = modelMapper.map(user, UserRecord.class); + assertEquals(record.userId, "id"); + assertEquals(record.userName, "name"); + } +} \ No newline at end of file