Skip to content

Commit

Permalink
add experimental java records support
Browse files Browse the repository at this point in the history
  • Loading branch information
g0ddest committed Oct 13, 2024
1 parent 33c9b59 commit 8742a70
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 5 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,24 @@ There is a `startsWith` parameter for easy-to-use identifying the class to deser

This class will be initialized just once and cached.

## Java records support

There is an experimental support of Java 14+ records with no breaking of Java 8 support.

Just annotate record's constructor as follows:

```java
record Employee (
@FixedField(offset = 1, length = 10, align = Align.LEFT)
String firstName,

@FixedField(offset = 10, length = 10, align = Align.LEFT)
String lastName
){}
```

and it works the same way as annotated class.

## Benchmark

There is a benchmark, you can run it with `gradle jmh` command. Also, you can change running parameters of it in file `src/jmh/java/name/velikodniy/vitaliy/fixedlength/benchmark/BenchmarkRunner.java`.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ plugins {
}

group 'name.velikodniy.vitaliy'
version '0.11'
version '0.12'

repositories {
mavenLocal()
Expand Down
26 changes: 23 additions & 3 deletions src/main/java/name/velikodniy/vitaliy/fixedlength/FixedLength.java
Original file line number Diff line number Diff line change
Expand Up @@ -245,11 +245,13 @@ private FixedFormatRecord fixedFormatLine(String line) {
private T lineToObject(FixedFormatRecord fixedFormatRecord) {
Class<? extends T> clazz = fixedFormatRecord.fixedFormatLine.clazz;
String line = fixedFormatRecord.rawLine;
T lineAsObject;
T lineAsObject = null;
boolean useEmptyConstructor = true;
try {
lineAsObject = clazz.getDeclaredConstructor().newInstance();
} catch (NoSuchMethodException e) {
throw new FixedLengthException("No empty constructor in class", e);
LOGGER.fine("No empty constructor in class");
useEmptyConstructor = false;
} catch (IllegalAccessException
| InstantiationException
| InvocationTargetException e) {
Expand All @@ -258,6 +260,8 @@ private T lineToObject(FixedFormatRecord fixedFormatRecord) {
);
}

Object[] args = new Object[fixedFormatRecord.fixedFormatLine.fixedFormatFields.size()];
int index = 0;
for (FixedFormatField fixedFormatField : fixedFormatRecord.fixedFormatLine.fixedFormatFields) {
FixedField fieldAnnotation = fixedFormatField.getFixedFieldAnnotation();
Field field = fixedFormatField.getField();
Expand All @@ -271,7 +275,23 @@ private T lineToObject(FixedFormatRecord fixedFormatRecord) {
endOfFieldIndex
), fieldAnnotation.padding());
if (acceptFieldContent(str, fieldAnnotation)) {
fillField(field, lineAsObject, str, fieldAnnotation);
if (useEmptyConstructor) {
fillField(field, lineAsObject, str, fieldAnnotation);
} else {
args[index++] = Formatter.instance(FORMATTERS, field.getType()).asObject(str, fieldAnnotation);
}
}
}
if (!useEmptyConstructor) {
try {
if (clazz.getDeclaredConstructors().length != 1) {
throw new FixedLengthException("There should be only one matching constructor");
}
lineAsObject = (T) clazz.getDeclaredConstructors()[0].newInstance(args);
} catch (IllegalAccessException
| InstantiationException
| InvocationTargetException e) {
throw new FixedLengthException("Unable to instantiate " + clazz.getName(), e);
}
}
return lineAsObject;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Retention(RUNTIME)
@Target(ElementType.FIELD)
@Target({ElementType.FIELD, ElementType.PARAMETER})
public @interface FixedField {
/**
* Offset of the field
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package name.velikodniy.vitaliy.fixedlength;

import name.velikodniy.vitaliy.fixedlength.annotation.FixedField;

import java.math.BigDecimal;
import java.time.LocalDate;

/**
* this class emulates built java 14+'s record as follows
* record EmployeeRecord(
* @FixedField(offset = 1, length = 10, align = Align.LEFT)
* String firstName,
* @FixedField(offset = 11, length = 10, align = Align.LEFT)
* String lastName,
* @FixedField(offset = 21, length = 10, align = Align.LEFT)
* String title,
* @FixedField(offset = 31, length = 6, padding = '0')
* BigDecimal salary,
* @FixedField(offset = 37, length = 8, format = "MMddyyyy")
* LocalDate hireDate
* ){}
*/
class EmployeeRecord{
@FixedField(offset = 1, length = 10, align = Align.LEFT)
public String firstName;
@FixedField(offset = 11, length = 10, align = Align.LEFT)
public String lastName;
@FixedField(offset = 21, length = 10, align = Align.LEFT)
public String title;
@FixedField(offset = 31, length = 6, padding = '0')
public BigDecimal salary;
@FixedField(offset = 37, length = 8, format = "MMddyyyy")
public LocalDate hireDate;

public EmployeeRecord(String firstName, String lastName, String title, BigDecimal salary, LocalDate hireDate) {
this.firstName = firstName;
this.lastName = lastName;
this.title = title;
this.salary = salary;
this.hireDate = hireDate;
}
}
14 changes: 14 additions & 0 deletions src/test/java/name/velikodniy/vitaliy/fixedlength/ParserTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,20 @@ void testParseInheritedOneLineType() throws FixedLengthException {
});
}

@Test
@DisplayName("Parse as input stream with default charset and one line type with record emulation class")
void testParseInheritedOneLineTypeRecord() throws FixedLengthException {
List<EmployeeRecord> parse = new FixedLength<EmployeeRecord>()
.registerLineType(EmployeeRecord.class)
.parse(new ByteArrayInputStream(singleTypeExample.getBytes()));

assertEquals(2, parse.size());
parse.forEach(e -> {
assertNotNull(e.firstName);
assertNotNull(e.lastName);
});
}

@Test
@DisplayName("Parse as input stream with default charset and one line type")
void testParseOneLineType() throws FixedLengthException {
Expand Down

0 comments on commit 8742a70

Please sign in to comment.