Skip to content

Commit

Permalink
Merge pull request #1449 from MSaguer/historyGenerator
Browse files Browse the repository at this point in the history
Add generation timestamp in history file
  • Loading branch information
pascalgrimaud authored May 6, 2022
2 parents ddef5fa + db85c35 commit 843eee9
Show file tree
Hide file tree
Showing 27 changed files with 396 additions and 86 deletions.
2 changes: 2 additions & 0 deletions src/main/java/tech/jhipster/lite/common/domain/JsonUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.fasterxml.jackson.core.PrettyPrinter;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import com.fasterxml.jackson.databind.node.ObjectNode;
Expand All @@ -25,6 +26,7 @@ public static ObjectMapper getObjectMapper() {
return objectMapper;
}
objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
customPrettyPrinter = new CustomPrettyPrinter();
return objectMapper;
}
Expand Down
21 changes: 21 additions & 0 deletions src/main/java/tech/jhipster/lite/common/domain/TimeUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package tech.jhipster.lite.common.domain;

import java.time.Clock;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class TimeUtils {

private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");

private TimeUtils() {}

public static String getDateString(Clock clock) {
return getDateString(clock, 0);
}

public static String getDateString(Clock clock, int plusSecond) {
LocalDateTime localDateTime = LocalDateTime.now(clock).plusSeconds(plusSecond);
return localDateTime.format(DATE_TIME_FORMATTER);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ public void addHistoryValue(Project project, GeneratorHistoryValue generatorHist

public List<GeneratorHistoryValue> getValues(Project project) {
Assert.notNull("project", project);
return generatorHistoryRepository.getHistoryData(project).getValues();
return generatorHistoryRepository.getHistoryData(project).values();
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,5 @@
package tech.jhipster.lite.generator.history.domain;

import java.util.ArrayList;
import java.util.List;

public class GeneratorHistoryData {

private final List<GeneratorHistoryValue> values = new ArrayList<>();

public List<GeneratorHistoryValue> getValues() {
return values;
}

@Override
public String toString() {
return "GeneratorHistoryData{" + "values=" + values + '}';
}
}
public record GeneratorHistoryData(List<GeneratorHistoryValue> values) {}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package tech.jhipster.lite.generator.history.domain;

public record GeneratorHistoryValue(String serviceId) {}
import java.time.Instant;

public record GeneratorHistoryValue(String serviceId, Instant timestamp) {}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package tech.jhipster.lite.generator.history.infrastructure.primary;

import java.time.Clock;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
Expand All @@ -15,17 +16,19 @@
public class GeneratorHistoryInterceptor {

private final GeneratorHistoryApplicationService generatorHistoryApplicationService;
private Clock clock;

public GeneratorHistoryInterceptor(GeneratorHistoryApplicationService generatorHistoryApplicationService) {
public GeneratorHistoryInterceptor(GeneratorHistoryApplicationService generatorHistoryApplicationService, Clock clock) {
this.generatorHistoryApplicationService = generatorHistoryApplicationService;
this.clock = clock;
}

@AfterReturning(value = "@annotation(generatorStep)")
public void addInHistory(JoinPoint joinPoint, GeneratorStep generatorStep) {
String serviceId = generatorStep.id();
ProjectDTO projectDTO = (ProjectDTO) joinPoint.getArgs()[0];
Project project = ProjectDTO.toProject(projectDTO);
GeneratorHistoryValue generatorHistoryValue = new GeneratorHistoryValue(serviceId);
GeneratorHistoryValue generatorHistoryValue = new GeneratorHistoryValue(serviceId, clock.instant());
generatorHistoryApplicationService.addHistoryValue(project, generatorHistoryValue);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import tech.jhipster.lite.generator.history.application.GeneratorHistoryApplicationService;
import tech.jhipster.lite.generator.history.domain.GeneratorHistoryValue;
import tech.jhipster.lite.generator.history.infrastructure.primary.dto.HistoryDTO;
import tech.jhipster.lite.generator.project.domain.Project;

Expand All @@ -24,13 +26,23 @@ public HistoryResource(GeneratorHistoryApplicationService generatorHistoryApplic
this.generatorHistoryApplicationService = generatorHistoryApplicationService;
}

@Operation(summary = "Get project service Id history")
@ApiResponse(responseCode = "500", description = "An error occurred while getting service id history project")
@GetMapping("/serviceIds")
public ResponseEntity<HistoryDTO> serviceIds(
@Parameter(description = "Project path to get history") @RequestParam(value = "folder") String folder
) {
Project project = Project.builder().folder(folder).build();
return ResponseEntity.ok(HistoryDTO.from(generatorHistoryApplicationService.getValues(project)));
}

@Operation(summary = "Get project history")
@ApiResponse(responseCode = "500", description = "An error occurred while getting history project")
@GetMapping
public ResponseEntity<HistoryDTO> get(
public ResponseEntity<List<GeneratorHistoryValue>> history(
@Parameter(description = "Project path to get history") @RequestParam(value = "folder") String folder
) {
Project project = Project.builder().folder(folder).build();
return ResponseEntity.ok(HistoryDTO.from(generatorHistoryApplicationService.getValues(project)));
return ResponseEntity.ok(generatorHistoryApplicationService.getValues(project));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ public static HistoryDTO from(List<GeneratorHistoryValue> serviceIds) {
if (serviceIds == null) {
return new HistoryDTO(Collections.emptyList());
}
return new HistoryDTO(serviceIds.stream().map(GeneratorHistoryValue::serviceId).toList());
}

public Collection<String> getServiceIds() {
return serviceIds;
return new HistoryDTO(serviceIds.stream().map(GeneratorHistoryValue::serviceId).distinct().sorted().toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@

import com.fasterxml.jackson.core.JsonProcessingException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Repository;
import tech.jhipster.lite.common.domain.FileUtils;
import tech.jhipster.lite.common.domain.JsonUtils;
import tech.jhipster.lite.error.domain.GeneratorException;
import tech.jhipster.lite.generator.history.domain.GeneratorHistoryData;
import tech.jhipster.lite.generator.history.domain.GeneratorHistoryRepository;
import tech.jhipster.lite.generator.history.domain.GeneratorHistoryValue;
import tech.jhipster.lite.generator.history.infrastructure.secondary.dto.GeneratorHistoryDataDTO;
import tech.jhipster.lite.generator.history.infrastructure.secondary.dto.GeneratorHistoryValueDTO;
import tech.jhipster.lite.generator.project.domain.Project;
import tech.jhipster.lite.generator.project.domain.ProjectRepository;

Expand All @@ -34,28 +38,30 @@ public GeneratorHistoryData getHistoryData(Project project) {
} catch (IOException e) {
throw new GeneratorException("Error on file " + filePath + " : " + e.getMessage());
}
return deserializeHistoryFile(filePath, historyFileContent);
return GeneratorHistoryDataDTO.to(deserializeHistoryFile(filePath, historyFileContent));
}

@Override
public void addHistoryValue(Project project, GeneratorHistoryValue generatorHistoryValue) {
String filePath = getHistoryFilePath(project);
GeneratorHistoryData generatorHistoryData;
List<GeneratorHistoryValueDTO> generatorHistoryValueDTOs = new ArrayList<>();
try {
String historyFileContent = FileUtils.read(filePath);
generatorHistoryData = deserializeHistoryFile(filePath, historyFileContent);
generatorHistoryValueDTOs.addAll(deserializeHistoryFile(filePath, historyFileContent));
} catch (IOException e) {
// The file does not exist
createHistoryFile(project);
generatorHistoryData = getHistoryData(project);
GeneratorHistoryData data = getHistoryData(project);
generatorHistoryValueDTOs.addAll(GeneratorHistoryDataDTO.from(data.values()).values());
}

generatorHistoryData.getValues().add(generatorHistoryValue);
generatorHistoryValueDTOs.add(GeneratorHistoryValueDTO.from(generatorHistoryValue));
GeneratorHistoryDataDTO generatorHistoryDataDTO = new GeneratorHistoryDataDTO(generatorHistoryValueDTOs);
String newHistoryFileContent;
try {
newHistoryFileContent = JsonUtils.getObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(generatorHistoryData);
newHistoryFileContent = JsonUtils.getObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(generatorHistoryDataDTO);
} catch (JsonProcessingException e) {
throw new GeneratorException("Cannot serialize the history data " + generatorHistoryData + " : " + e.getMessage());
throw new GeneratorException("Cannot serialize the history data " + generatorHistoryDataDTO + " : " + e.getMessage());
}
try {
FileUtils.write(filePath, newHistoryFileContent, project.getEndOfLine());
Expand All @@ -72,9 +78,9 @@ private String getHistoryFilePath(Project project) {
return FileUtils.getPath(project.getFolder(), HISTORY_FOLDER_PATH_DEST, HISTORY_FILE_NAME);
}

private GeneratorHistoryData deserializeHistoryFile(String filePath, String historyFileContent) {
private List<GeneratorHistoryValueDTO> deserializeHistoryFile(String filePath, String historyFileContent) {
try {
return JsonUtils.getObjectMapper().readValue(historyFileContent, GeneratorHistoryData.class);
return JsonUtils.getObjectMapper().readValue(historyFileContent, GeneratorHistoryDataDTO.class).values();
} catch (JsonProcessingException e) {
throw new GeneratorException("Cannot deserialize JSON of file " + filePath + " : " + e.getMessage());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package tech.jhipster.lite.generator.history.infrastructure.secondary.dto;

import com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer;
import java.time.Instant;
import java.time.format.DateTimeFormatter;

@SuppressWarnings("java:S110")
public class DefaultInstantDeserializer extends InstantDeserializer<Instant> {

public DefaultInstantDeserializer() {
super(
Instant.class,
DateTimeFormatter.ISO_INSTANT,
Instant::from,
a -> Instant.ofEpochMilli(a.value),
a -> Instant.ofEpochSecond(a.integer, a.fraction),
null,
true // yes, replace zero offset with Z
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package tech.jhipster.lite.generator.history.infrastructure.secondary.dto;

import java.util.Collections;
import java.util.List;
import tech.jhipster.lite.generator.history.domain.GeneratorHistoryData;
import tech.jhipster.lite.generator.history.domain.GeneratorHistoryValue;

public record GeneratorHistoryDataDTO(List<GeneratorHistoryValueDTO> values) {
public static GeneratorHistoryDataDTO from(List<GeneratorHistoryValue> values) {
if (values == null) {
return new GeneratorHistoryDataDTO(Collections.emptyList());
}
return new GeneratorHistoryDataDTO(values.stream().map(GeneratorHistoryValueDTO::from).distinct().toList());
}

public static GeneratorHistoryData to(List<GeneratorHistoryValueDTO> values) {
if (values == null) {
return new GeneratorHistoryData(Collections.emptyList());
}
return new GeneratorHistoryData(values.stream().map(GeneratorHistoryValueDTO::to).distinct().toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package tech.jhipster.lite.generator.history.infrastructure.secondary.dto;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializer;
import java.time.Instant;
import tech.jhipster.lite.generator.history.domain.GeneratorHistoryValue;

public record GeneratorHistoryValueDTO(
String serviceId,

@JsonSerialize(using = InstantSerializer.class) @JsonDeserialize(using = DefaultInstantDeserializer.class) Instant timestamp
) {
public static GeneratorHistoryValueDTO from(GeneratorHistoryValue value) {
return new GeneratorHistoryValueDTO(value.serviceId(), value.timestamp());
}

public static GeneratorHistoryValue to(GeneratorHistoryValueDTO value) {
return new GeneratorHistoryValue(value.serviceId, value.timestamp);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
import static tech.jhipster.lite.generator.server.springboot.dbmigration.flyway.domain.Flyway.DEFAULT_SQL_FILES_FOLDER;

import java.time.Clock;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.TreeMap;
import tech.jhipster.lite.common.domain.TimeUtils;
import tech.jhipster.lite.error.domain.GeneratorException;
import tech.jhipster.lite.generator.buildtool.generic.domain.BuildToolService;
import tech.jhipster.lite.generator.project.domain.Project;
Expand All @@ -22,8 +21,6 @@ public class FlywayDomainService implements FlywayService {
private static final String SQL_INIT_FILE_NAME = "V%s__init.sql";
private static final String SQL_USER_AUTHORITY_FILE_NAME = "V%s__create_user_authority_tables.sql";

private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");

private final BuildToolService buildToolService;
private final ProjectRepository projectRepository;
private final SpringBootCommonService springBootCommonService;
Expand Down Expand Up @@ -110,9 +107,7 @@ private TreeMap<String, Object> getFlywayProperties() {
}

private String buildFileNameWithTimestamp(String fileNameFormat, int idxScript) {
LocalDateTime localDateTime = LocalDateTime.now(clock).plusSeconds(idxScript);
String formattedDate = localDateTime.format(DATE_TIME_FORMATTER);
return fileNameFormat.formatted(formattedDate);
return fileNameFormat.formatted(TimeUtils.getDateString(clock, idxScript));
}

private boolean isDatabaseUseSequences(Project project) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
import static tech.jhipster.lite.generator.server.springboot.dbmigration.liquibase.domain.Liquibase.NEEDLE_LIQUIBASE;

import java.time.Clock;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import tech.jhipster.lite.common.domain.TimeUtils;
import tech.jhipster.lite.generator.buildtool.generic.domain.BuildToolService;
import tech.jhipster.lite.generator.buildtool.generic.domain.Dependency;
import tech.jhipster.lite.generator.project.domain.Project;
Expand All @@ -28,7 +27,6 @@ public class LiquibaseDomainService implements LiquibaseService {
public static final String CONFIG_LIQUIBASE = "config/liquibase";
public static final String CHANGELOG = CONFIG_LIQUIBASE + "/changelog";
public static final String DATA = CONFIG_LIQUIBASE + "/data";
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");

private final ProjectRepository projectRepository;
private final BuildToolService buildToolService;
Expand Down Expand Up @@ -131,7 +129,7 @@ public void addUserAuthorityChangelog(Project project) {

private void addSqlSequenceUserChangelog(Project project) {
if (isDatabaseWhichNeedsSequenceStrategy(project)) {
String sequenceUserChangelog = getTimestamp() + "_added_sequence_User.xml";
String sequenceUserChangelog = TimeUtils.getDateString(clock) + "_added_sequence_User.xml";
addChangelogXml(project, "", sequenceUserChangelog);
projectRepository.template(
project,
Expand All @@ -144,7 +142,7 @@ private void addSqlSequenceUserChangelog(Project project) {
}

private void addSqlUserChangelog(Project project) {
String userChangelog = getTimestamp() + "_added_entity_User.xml";
String userChangelog = TimeUtils.getDateString(clock) + "_added_entity_User.xml";
addChangelogXml(project, "", userChangelog);
String userXmlFile = "user.xml";
if (springBootCommonService.isSetWithMySQLOrMariaDBDatabase(project)) {
Expand All @@ -156,7 +154,7 @@ private void addSqlUserChangelog(Project project) {

private void addSqlUserAuthorityChangelog(Project project) {
// Update liquibase master file
String authorityChangelog = getTimestamp() + "_added_entity_Authority.xml";
String authorityChangelog = TimeUtils.getDateString(clock) + "_added_entity_Authority.xml";
addChangelogXml(project, "", authorityChangelog);

// Copy liquibase files
Expand All @@ -169,11 +167,6 @@ private String getUserResourcePath() {
return getPath(SOURCE, "resources/user");
}

private String getTimestamp() {
LocalDateTime localDateTime = LocalDateTime.now(clock);
return localDateTime.format(DATE_TIME_FORMATTER);
}

private boolean isDatabaseWhichNeedsSequenceStrategy(Project project) {
return !springBootCommonService.isSetWithMySQLOrMariaDBDatabase(project);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import tech.jhipster.lite.IntegrationTest;
import tech.jhipster.lite.generator.client.tools.cypress.domain.CypressDomainService;
import tech.jhipster.lite.generator.client.tools.playwright.domain.PlaywrightDomainService;

@IntegrationTest
Expand Down
Loading

0 comments on commit 843eee9

Please sign in to comment.