diff --git a/core/src/main/java/org/gbif/vocabulary/persistence/handlers/LocalDateTimeTypeHandler.java b/core/src/main/java/org/gbif/vocabulary/persistence/handlers/LocalDateTimeTypeHandler.java deleted file mode 100644 index a76ca249..00000000 --- a/core/src/main/java/org/gbif/vocabulary/persistence/handlers/LocalDateTimeTypeHandler.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 org.gbif.vocabulary.persistence.handlers; - -import java.sql.CallableStatement; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.time.LocalDateTime; - -import org.apache.ibatis.type.BaseTypeHandler; -import org.apache.ibatis.type.JdbcType; - -public class LocalDateTimeTypeHandler extends BaseTypeHandler { - - @Override - public void setNonNullParameter( - PreparedStatement ps, int i, LocalDateTime parameter, JdbcType jdbcType) throws SQLException { - ps.setTimestamp(i, Timestamp.valueOf(parameter)); - } - - @Override - public LocalDateTime getNullableResult(ResultSet rs, String columnName) throws SQLException { - Timestamp timestamp = rs.getTimestamp(columnName); - return getLocalDateTime(timestamp); - } - - @Override - public LocalDateTime getNullableResult(ResultSet rs, int columnIndex) throws SQLException { - Timestamp timestamp = rs.getTimestamp(columnIndex); - return getLocalDateTime(timestamp); - } - - @Override - public LocalDateTime getNullableResult(CallableStatement cs, int columnIndex) - throws SQLException { - Timestamp timestamp = cs.getTimestamp(columnIndex); - return getLocalDateTime(timestamp); - } - - private static LocalDateTime getLocalDateTime(Timestamp timestamp) { - if (timestamp != null) { - return timestamp.toLocalDateTime(); - } - return null; - } -} diff --git a/core/src/main/java/org/gbif/vocabulary/persistence/handlers/ZonedDateTimeTypeHandler.java b/core/src/main/java/org/gbif/vocabulary/persistence/handlers/ZonedDateTimeTypeHandler.java new file mode 100644 index 00000000..ac5bcf83 --- /dev/null +++ b/core/src/main/java/org/gbif/vocabulary/persistence/handlers/ZonedDateTimeTypeHandler.java @@ -0,0 +1,49 @@ +package org.gbif.vocabulary.persistence.handlers; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import org.apache.ibatis.type.BaseTypeHandler; +import org.apache.ibatis.type.JdbcType; + +/** + * @author Tomas Rohovsky + */ +public class ZonedDateTimeTypeHandler extends BaseTypeHandler { + + @Override + public void setNonNullParameter( + PreparedStatement ps, int i, ZonedDateTime parameter, JdbcType jdbcType) throws SQLException { + ps.setTimestamp(i, Timestamp.from(parameter.toInstant())); + } + + @Override + public ZonedDateTime getNullableResult(ResultSet rs, String columnName) throws SQLException { + Timestamp timestamp = rs.getTimestamp(columnName); + return getZonedDateTime(timestamp); + } + + @Override + public ZonedDateTime getNullableResult(ResultSet rs, int columnIndex) throws SQLException { + Timestamp timestamp = rs.getTimestamp(columnIndex); + return getZonedDateTime(timestamp); + } + + @Override + public ZonedDateTime getNullableResult(CallableStatement cs, int columnIndex) + throws SQLException { + Timestamp timestamp = cs.getTimestamp(columnIndex); + return getZonedDateTime(timestamp); + } + + private static ZonedDateTime getZonedDateTime(Timestamp timestamp) { + if (timestamp != null) { + return ZonedDateTime.ofInstant(timestamp.toInstant(), ZoneId.systemDefault()); + } + return null; + } +} diff --git a/core/src/main/java/org/gbif/vocabulary/service/impl/DefaultExportService.java b/core/src/main/java/org/gbif/vocabulary/service/impl/DefaultExportService.java index 6b4f924f..eaa4e49f 100644 --- a/core/src/main/java/org/gbif/vocabulary/service/impl/DefaultExportService.java +++ b/core/src/main/java/org/gbif/vocabulary/service/impl/DefaultExportService.java @@ -13,6 +13,29 @@ */ package org.gbif.vocabulary.service.impl; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.ZonedDateTime; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.annotation.Nullable; +import javax.validation.constraints.NotBlank; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; import org.gbif.api.model.common.paging.Pageable; import org.gbif.api.model.common.paging.PagingRequest; import org.gbif.api.model.common.paging.PagingResponse; @@ -35,39 +58,11 @@ import org.gbif.vocabulary.service.ExportService; import org.gbif.vocabulary.service.VocabularyService; import org.gbif.vocabulary.service.export.ReleasePersister; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.time.LocalDateTime; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.annotation.Nullable; -import javax.validation.constraints.NotBlank; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.annotation.Secured; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; - -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; - /** Default implementation for {@link ExportService}. */ @Service @Validated @@ -126,7 +121,7 @@ public Path exportVocabulary(@NotBlank String vocabularyName, String version) { // write metadata ExportMetadata metadata = new ExportMetadata(); - metadata.setCreatedDate(LocalDateTime.now()); + metadata.setCreatedDate(ZonedDateTime.now()); if (!Strings.isNullOrEmpty(version)) { metadata.setVersion(version); } diff --git a/core/src/test/java/org/gbif/vocabulary/service/ExportServiceTest.java b/core/src/test/java/org/gbif/vocabulary/service/ExportServiceTest.java index 05244292..15add5b6 100644 --- a/core/src/test/java/org/gbif/vocabulary/service/ExportServiceTest.java +++ b/core/src/test/java/org/gbif/vocabulary/service/ExportServiceTest.java @@ -13,6 +13,22 @@ */ package org.gbif.vocabulary.service; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.when; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import java.io.IOException; +import java.nio.file.Path; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import org.gbif.api.model.common.paging.PagingRequest; import org.gbif.api.model.common.paging.PagingResponse; import org.gbif.vocabulary.model.Concept; @@ -26,31 +42,12 @@ import org.gbif.vocabulary.model.export.Export; import org.gbif.vocabulary.model.export.VocabularyExportView; import org.gbif.vocabulary.persistence.mappers.VocabularyReleaseMapper; - -import java.io.IOException; -import java.nio.file.Path; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.test.context.support.WithMockUser; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.when; - /** Tests the {@link ExportService}. */ public class ExportServiceTest extends MockServiceBaseTest { @@ -109,7 +106,7 @@ private void mockVocabulary(String vocabularyName) { c1.setKey(1L); c1.setName("c1"); c1.setVocabularyKey(vocabulary.getKey()); - c1.setCreated(LocalDateTime.now()); + c1.setCreated(ZonedDateTime.now()); // tags Tag tag1 = new Tag(); diff --git a/core/src/test/java/org/gbif/vocabulary/service/VocabularyEntityServiceBaseTest.java b/core/src/test/java/org/gbif/vocabulary/service/VocabularyEntityServiceBaseTest.java index d95a4be6..c23ba5be 100644 --- a/core/src/test/java/org/gbif/vocabulary/service/VocabularyEntityServiceBaseTest.java +++ b/core/src/test/java/org/gbif/vocabulary/service/VocabularyEntityServiceBaseTest.java @@ -13,24 +13,21 @@ */ package org.gbif.vocabulary.service; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.when; + +import java.time.ZonedDateTime; +import javax.validation.ConstraintViolationException; import org.gbif.vocabulary.model.UserRoles; import org.gbif.vocabulary.model.VocabularyEntity; import org.gbif.vocabulary.persistence.mappers.BaseMapper; - -import java.time.LocalDateTime; - -import javax.validation.ConstraintViolationException; - import org.junit.jupiter.api.Test; import org.springframework.beans.BeanUtils; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.test.context.support.WithMockUser; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.when; - /** * Base class to test a {@link BaseService} that can be reused for all the implemenations. * @@ -119,7 +116,7 @@ public void deprecatingWhenUpdatingTest() { public void restoringDeprecatedWhenUpdatingTest() { T entityDB = createNewEntity("e1"); entityDB.setKey(TEST_KEY); - entityDB.setDeprecated(LocalDateTime.now()); + entityDB.setDeprecated(ZonedDateTime.now()); entityDB.setDeprecatedBy("test"); T updatedEntity = createNewEntity("e1"); BeanUtils.copyProperties(entityDB, updatedEntity); diff --git a/model/src/main/java/org/gbif/vocabulary/model/AbstractVocabularyEntity.java b/model/src/main/java/org/gbif/vocabulary/model/AbstractVocabularyEntity.java index f4903631..13f269f1 100644 --- a/model/src/main/java/org/gbif/vocabulary/model/AbstractVocabularyEntity.java +++ b/model/src/main/java/org/gbif/vocabulary/model/AbstractVocabularyEntity.java @@ -14,12 +14,10 @@ package org.gbif.vocabulary.model; import java.net.URI; -import java.time.LocalDateTime; +import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.List; - import javax.validation.constraints.NotBlank; - import lombok.Data; /** @@ -36,12 +34,12 @@ public abstract class AbstractVocabularyEntity implements VocabularyEntity { // deprecation fields Long replacedByKey; - LocalDateTime deprecated; + ZonedDateTime deprecated; String deprecatedBy; // audit fields - LocalDateTime created; + ZonedDateTime created; String createdBy; - LocalDateTime modified; + ZonedDateTime modified; String modifiedBy; } diff --git a/model/src/main/java/org/gbif/vocabulary/model/Auditable.java b/model/src/main/java/org/gbif/vocabulary/model/Auditable.java index 06755f09..0c0e53ac 100644 --- a/model/src/main/java/org/gbif/vocabulary/model/Auditable.java +++ b/model/src/main/java/org/gbif/vocabulary/model/Auditable.java @@ -13,22 +13,22 @@ */ package org.gbif.vocabulary.model; -import java.time.LocalDateTime; +import java.time.ZonedDateTime; /** Defines the minimum fields that an entity must have in order to be auditable. */ public interface Auditable { - LocalDateTime getCreated(); + ZonedDateTime getCreated(); - void setCreated(LocalDateTime created); + void setCreated(ZonedDateTime created); String getCreatedBy(); void setCreatedBy(String createdBy); - LocalDateTime getModified(); + ZonedDateTime getModified(); - void setModified(LocalDateTime modified); + void setModified(ZonedDateTime modified); String getModifiedBy(); diff --git a/model/src/main/java/org/gbif/vocabulary/model/Definition.java b/model/src/main/java/org/gbif/vocabulary/model/Definition.java index 2e35634c..e548312f 100644 --- a/model/src/main/java/org/gbif/vocabulary/model/Definition.java +++ b/model/src/main/java/org/gbif/vocabulary/model/Definition.java @@ -13,16 +13,13 @@ */ package org.gbif.vocabulary.model; -import org.gbif.vocabulary.model.utils.LenientEquals; - -import java.time.LocalDateTime; +import java.time.ZonedDateTime; import java.util.Objects; - import javax.validation.constraints.NotNull; - import lombok.Builder; import lombok.Data; import lombok.extern.jackson.Jacksonized; +import org.gbif.vocabulary.model.utils.LenientEquals; @Data @Builder @@ -33,9 +30,9 @@ public class Definition implements ValueEntity, Auditable, LenientEquals { private Long key; private String value; private String createdBy; - private LocalDateTime created; + private ZonedDateTime created; @Override public boolean lenientEquals(HiddenLabel other) { diff --git a/model/src/main/java/org/gbif/vocabulary/model/Label.java b/model/src/main/java/org/gbif/vocabulary/model/Label.java index 19695bba..9fa11fba 100644 --- a/model/src/main/java/org/gbif/vocabulary/model/Label.java +++ b/model/src/main/java/org/gbif/vocabulary/model/Label.java @@ -13,16 +13,13 @@ */ package org.gbif.vocabulary.model; -import org.gbif.vocabulary.model.utils.LenientEquals; - -import java.time.LocalDateTime; +import java.time.ZonedDateTime; import java.util.Objects; - import javax.validation.constraints.NotNull; - import lombok.Builder; import lombok.Data; import lombok.extern.jackson.Jacksonized; +import org.gbif.vocabulary.model.utils.LenientEquals; @Data @Builder @@ -33,7 +30,7 @@ public class Label implements LabelEntity, LenientEquals