-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enables support for java.time field types
This commit facilitates the automatic conversion of `java.time.temporal.Temporal` instances into `java.util.Date` within the report generation process. This conversion is necessary to ensure proper recognition of date cells by Excel.
- Loading branch information
Showing
3 changed files
with
296 additions
and
33 deletions.
There are no files selected for viewing
58 changes: 58 additions & 0 deletions
58
src/main/java/com/woreports/custom/TemporalToDateConverter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package com.woreports.custom; | ||
|
||
import java.sql.Date; | ||
import java.time.Instant; | ||
import java.time.LocalDate; | ||
import java.time.LocalDateTime; | ||
import java.time.ZoneId; | ||
import java.time.temporal.Temporal; | ||
import java.util.Map; | ||
import java.util.NoSuchElementException; | ||
|
||
import ar.com.fdvs.dj.domain.CustomExpression; | ||
|
||
/** | ||
* @author <a href="mailto:hprange@gmail.com">Henrique Prange</a> | ||
*/ | ||
public class TemporalToDateConverter implements CustomExpression { | ||
private final String fieldName; | ||
|
||
public TemporalToDateConverter(String fieldName) { | ||
this.fieldName = fieldName; | ||
} | ||
|
||
@Override | ||
@SuppressWarnings("rawtypes") | ||
public Object evaluate(Map fields, Map variables, Map parameters) { | ||
if (!fields.containsKey(fieldName)) { | ||
throw new NoSuchElementException(String.format("There's no field '%s' in this report.", fieldName)); | ||
} | ||
|
||
Object object = fields.get(fieldName); | ||
|
||
if (object == null) { | ||
return null; | ||
} | ||
|
||
if (!(object instanceof Temporal)) { | ||
throw new IllegalStateException(String.format("Expecting a %s, but got a %s.", Temporal.class.getName(), object.getClass().getName())); | ||
} | ||
|
||
Temporal temporal = null; | ||
|
||
if (object instanceof LocalDate) { | ||
temporal = ((LocalDate) object).atStartOfDay(ZoneId.systemDefault()); | ||
} else if (object instanceof LocalDateTime) { | ||
temporal = ((LocalDateTime) object).atZone(ZoneId.systemDefault()); | ||
} else { | ||
temporal = (Temporal) object; | ||
} | ||
|
||
return Date.from(Instant.from(temporal)); | ||
} | ||
|
||
@Override | ||
public String getClassName() { | ||
return Date.class.getName(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
177 changes: 177 additions & 0 deletions
177
src/test/java/com/woreports/custom/TestTemporalToDateConverter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
package com.woreports.custom; | ||
|
||
import static java.util.Collections.emptyMap; | ||
import static org.hamcrest.CoreMatchers.instanceOf; | ||
import static org.hamcrest.CoreMatchers.is; | ||
import static org.hamcrest.CoreMatchers.nullValue; | ||
import static org.junit.Assert.assertThat; | ||
|
||
import java.time.Instant; | ||
import java.time.LocalDate; | ||
import java.time.LocalDateTime; | ||
import java.time.OffsetDateTime; | ||
import java.time.ZoneId; | ||
import java.time.ZoneOffset; | ||
import java.time.ZonedDateTime; | ||
import java.util.Calendar; | ||
import java.util.Date; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.NoSuchElementException; | ||
|
||
import org.junit.Before; | ||
import org.junit.Rule; | ||
import org.junit.Test; | ||
import org.junit.rules.ExpectedException; | ||
|
||
/** | ||
* @author <a href="mailto:hprange@gmail.com">Henrique Prange</a> | ||
*/ | ||
public class TestTemporalToDateConverter { | ||
private static int minute(Calendar calendar) { | ||
return calendar.get(Calendar.MINUTE); | ||
} | ||
|
||
private static int hour(Calendar calendar) { | ||
return calendar.get(Calendar.HOUR_OF_DAY); | ||
} | ||
|
||
private static int day(Calendar calendar) { | ||
return calendar.get(Calendar.DAY_OF_MONTH); | ||
} | ||
|
||
private static int month(Calendar calendar) { | ||
return calendar.get(Calendar.MONTH) + 1; | ||
} | ||
|
||
private static int year(Calendar calendar) { | ||
return calendar.get(Calendar.YEAR); | ||
} | ||
|
||
private static int second(Calendar calendar) { | ||
return calendar.get(Calendar.SECOND); | ||
} | ||
|
||
private TemporalToDateConverter converter; | ||
|
||
@Rule | ||
public ExpectedException thrown = ExpectedException.none(); | ||
|
||
@Before | ||
public void setup() { | ||
converter = new TemporalToDateConverter("fieldName"); | ||
} | ||
|
||
@Test | ||
public void convertLocalDateToDateWhenEvaluatingExpression() { | ||
Map<String, Object> fields = new HashMap<>(); | ||
fields.put("fieldName", LocalDate.of(2021, 11, 4)); | ||
|
||
Object result = converter.evaluate(fields, emptyMap(), emptyMap()); | ||
|
||
assertThat(result, instanceOf(Date.class)); | ||
|
||
Calendar calendar = Calendar.getInstance(); | ||
calendar.setTime((Date) result); | ||
|
||
assertThat(year(calendar), is(2021)); | ||
assertThat(month(calendar), is(11)); | ||
assertThat(day(calendar), is(4)); | ||
assertThat(hour(calendar), is(0)); | ||
assertThat(minute(calendar), is(0)); | ||
assertThat(second(calendar), is(0)); | ||
} | ||
|
||
@Test | ||
public void convertLocalDateTimeToDateWhenEvaluatingExpression() { | ||
Map<String, Object> fields = new HashMap<>(); | ||
fields.put("fieldName", LocalDateTime.of(2021, 11, 4, 10, 56, 24)); | ||
|
||
Object result = converter.evaluate(fields, emptyMap(), emptyMap()); | ||
|
||
assertThat(result, instanceOf(Date.class)); | ||
|
||
Calendar calendar = Calendar.getInstance(); | ||
calendar.setTime((Date) result); | ||
|
||
assertThat(year(calendar), is(2021)); | ||
assertThat(month(calendar), is(11)); | ||
assertThat(day(calendar), is(4)); | ||
assertThat(hour(calendar), is(10)); | ||
assertThat(minute(calendar), is(56)); | ||
assertThat(second(calendar), is(24)); | ||
} | ||
|
||
@Test | ||
public void convertOffsetDateTimeToDateWhenEvaluatingExpression() { | ||
Map<String, Object> fields = new HashMap<>(); | ||
ZoneOffset offset = ZoneId.systemDefault().getRules().getOffset(Instant.now()); | ||
fields.put("fieldName", OffsetDateTime.of(2021, 11, 4, 10, 56, 24, 0, offset)); | ||
|
||
Object result = converter.evaluate(fields, emptyMap(), emptyMap()); | ||
|
||
assertThat(result, instanceOf(Date.class)); | ||
|
||
Calendar calendar = Calendar.getInstance(); | ||
calendar.setTime((Date) result); | ||
|
||
assertThat(year(calendar), is(2021)); | ||
assertThat(month(calendar), is(11)); | ||
assertThat(day(calendar), is(4)); | ||
assertThat(hour(calendar), is(10)); | ||
assertThat(minute(calendar), is(56)); | ||
assertThat(second(calendar), is(24)); | ||
} | ||
|
||
@Test | ||
public void convertZonedDateTimeToDateWhenEvaluatingExpression() { | ||
Map<String, Object> fields = new HashMap<>(); | ||
fields.put("fieldName", ZonedDateTime.of(2021, 11, 4, 10, 56, 24, 0, ZoneId.systemDefault())); | ||
|
||
Object result = converter.evaluate(fields, emptyMap(), emptyMap()); | ||
|
||
assertThat(result, instanceOf(Date.class)); | ||
|
||
Calendar calendar = Calendar.getInstance(); | ||
calendar.setTime((Date) result); | ||
|
||
assertThat(year(calendar), is(2021)); | ||
assertThat(month(calendar), is(11)); | ||
assertThat(day(calendar), is(4)); | ||
assertThat(hour(calendar), is(10)); | ||
assertThat(minute(calendar), is(56)); | ||
assertThat(second(calendar), is(24)); | ||
} | ||
|
||
@Test | ||
public void returnNullIfValueNullWhenEvalutatingExpression() throws Exception { | ||
Map<String, Object> fields = new HashMap<String, Object>(); | ||
fields.put("fieldName", null); | ||
|
||
Object result = converter.evaluate(fields, emptyMap(), emptyMap()); | ||
|
||
assertThat(result, nullValue()); | ||
} | ||
|
||
@Test | ||
public void throwExceptionIfFieldNotFoundWhenEvaluatingExpression() throws Exception { | ||
Map<String, Object> fields = new HashMap<>(); | ||
fields.put("unknown", LocalDate.of(2021, 11, 4)); | ||
|
||
thrown.expect(NoSuchElementException.class); | ||
thrown.expectMessage(is("There's no field 'fieldName' in this report.")); | ||
|
||
converter.evaluate(fields, emptyMap(), emptyMap()); | ||
} | ||
|
||
@Test | ||
public void throwExceptionIfValueIsNotLocalDateWhenEvaluatingExpression() throws Exception { | ||
Map<String, Object> fields = new HashMap<>(); | ||
fields.put("fieldName", "I'm a String"); | ||
|
||
thrown.expect(IllegalStateException.class); | ||
thrown.expectMessage(is("Expecting a java.time.temporal.Temporal, but got a java.lang.String.")); | ||
|
||
converter.evaluate(fields, emptyMap(), emptyMap()); | ||
} | ||
} |