diff --git a/apps/challenge-service/.openapi-generator-ignore b/apps/challenge-service/.openapi-generator-ignore index 4152c21127..96bd1a073f 100644 --- a/apps/challenge-service/.openapi-generator-ignore +++ b/apps/challenge-service/.openapi-generator-ignore @@ -26,6 +26,3 @@ README.md **/application.properties **/model/dto/*AllOf*.java **/OpenApiGeneratorApplication.java - -# The template of this file has a bug: the Dto suffix is not included -**/EnumConverterConfiguration.java \ No newline at end of file diff --git a/apps/challenge-service/.openapi-generator/FILES b/apps/challenge-service/.openapi-generator/FILES index a9ac0326b0..a42c3999fc 100644 --- a/apps/challenge-service/.openapi-generator/FILES +++ b/apps/challenge-service/.openapi-generator/FILES @@ -9,6 +9,7 @@ src/main/java/org/sagebionetworks/challenge/configuration/HomeController.java src/main/java/org/sagebionetworks/challenge/configuration/SpringDocConfiguration.java src/main/java/org/sagebionetworks/challenge/model/dto/BasicErrorDto.java src/main/java/org/sagebionetworks/challenge/model/dto/ChallengeCreateRequestDto.java +src/main/java/org/sagebionetworks/challenge/model/dto/ChallengeDifficultyDto.java src/main/java/org/sagebionetworks/challenge/model/dto/ChallengeDto.java src/main/java/org/sagebionetworks/challenge/model/dto/ChallengeStatusDto.java src/main/java/org/sagebionetworks/challenge/model/dto/ChallengesPageDto.java diff --git a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/api/ChallengeApi.java b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/api/ChallengeApi.java index 5141c46bc5..efb4699776 100644 --- a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/api/ChallengeApi.java +++ b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/api/ChallengeApi.java @@ -15,6 +15,7 @@ import javax.validation.Valid; import javax.validation.constraints.*; import org.sagebionetworks.challenge.model.dto.BasicErrorDto; +import org.sagebionetworks.challenge.model.dto.ChallengeDifficultyDto; import org.sagebionetworks.challenge.model.dto.ChallengeStatusDto; import org.sagebionetworks.challenge.model.dto.ChallengesPageDto; import org.springframework.http.ResponseEntity; @@ -35,7 +36,9 @@ default ChallengeApiDelegate getDelegate() { * * @param pageNumber The page number (optional, default to 0) * @param pageSize The number of items in a single page (optional, default to 100) - * @param status Array of challenge status used to filter the results. (optional) + * @param status An array of challenge status used to filter the results. (optional) + * @param difficulty An array of challenge difficulty levels used to filter the results. + * (optional) * @return Success (status code 200) or Invalid request (status code 400) or The request cannot be * fulfilled due to an unexpected server error (status code 500) */ @@ -95,10 +98,16 @@ default ResponseEntity listChallenges( Integer pageSize, @Parameter( name = "status", - description = "Array of challenge status used to filter the results.") + description = "An array of challenge status used to filter the results.") @Valid @RequestParam(value = "status", required = false) - List status) { - return getDelegate().listChallenges(pageNumber, pageSize, status); + List status, + @Parameter( + name = "difficulty", + description = "An array of challenge difficulty levels used to filter the results.") + @Valid + @RequestParam(value = "difficulty", required = false) + List difficulty) { + return getDelegate().listChallenges(pageNumber, pageSize, status, difficulty); } } diff --git a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/api/ChallengeApiDelegate.java b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/api/ChallengeApiDelegate.java index c8c7a422c4..ff7325dade 100644 --- a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/api/ChallengeApiDelegate.java +++ b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/api/ChallengeApiDelegate.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.Optional; import javax.annotation.Generated; +import org.sagebionetworks.challenge.model.dto.ChallengeDifficultyDto; import org.sagebionetworks.challenge.model.dto.ChallengeStatusDto; import org.sagebionetworks.challenge.model.dto.ChallengesPageDto; import org.springframework.http.HttpStatus; @@ -26,13 +27,18 @@ default Optional getRequest() { * * @param pageNumber The page number (optional, default to 0) * @param pageSize The number of items in a single page (optional, default to 100) - * @param status Array of challenge status used to filter the results. (optional) + * @param status An array of challenge status used to filter the results. (optional) + * @param difficulty An array of challenge difficulty levels used to filter the results. + * (optional) * @return Success (status code 200) or Invalid request (status code 400) or The request cannot be * fulfilled due to an unexpected server error (status code 500) * @see ChallengeApi#listChallenges */ default ResponseEntity listChallenges( - Integer pageNumber, Integer pageSize, List status) { + Integer pageNumber, + Integer pageSize, + List status, + List difficulty) { getRequest() .ifPresent( request -> { diff --git a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/api/ChallengeApiDelegateImpl.java b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/api/ChallengeApiDelegateImpl.java index 0a37927ecb..8dd64ddbcf 100644 --- a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/api/ChallengeApiDelegateImpl.java +++ b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/api/ChallengeApiDelegateImpl.java @@ -1,6 +1,7 @@ package org.sagebionetworks.challenge.api; import java.util.List; +import org.sagebionetworks.challenge.model.dto.ChallengeDifficultyDto; import org.sagebionetworks.challenge.model.dto.ChallengeStatusDto; import org.sagebionetworks.challenge.model.dto.ChallengesPageDto; import org.sagebionetworks.challenge.service.ChallengeService; @@ -15,8 +16,12 @@ public class ChallengeApiDelegateImpl implements ChallengeApiDelegate { @Override public ResponseEntity listChallenges( - Integer pageNumber, Integer pageSize, List status) { - return ResponseEntity.ok(challengeService.listChallenges(pageNumber, pageSize, status)); + Integer pageNumber, + Integer pageSize, + List status, + List difficulty) { + return ResponseEntity.ok( + challengeService.listChallenges(pageNumber, pageSize, status, difficulty)); } // @Override diff --git a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/configuration/EnumConverterConfiguration.java b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/configuration/EnumConverterConfiguration.java index 87dd8eef1a..5893480ed3 100644 --- a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/configuration/EnumConverterConfiguration.java +++ b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/configuration/EnumConverterConfiguration.java @@ -1,5 +1,6 @@ package org.sagebionetworks.challenge.configuration; +import org.sagebionetworks.challenge.model.dto.ChallengeDifficultyDto; import org.sagebionetworks.challenge.model.dto.ChallengeStatusDto; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -8,6 +9,16 @@ @Configuration public class EnumConverterConfiguration { + @Bean + Converter challengeDifficultyConverter() { + return new Converter() { + @Override + public ChallengeDifficultyDto convert(String source) { + return ChallengeDifficultyDto.fromValue(source); + } + }; + } + @Bean Converter challengeStatusConverter() { return new Converter() { diff --git a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/dto/ChallengeCreateRequestDto.java b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/dto/ChallengeCreateRequestDto.java index e4ab3945c0..1600059c2f 100644 --- a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/dto/ChallengeCreateRequestDto.java +++ b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/dto/ChallengeCreateRequestDto.java @@ -22,6 +22,9 @@ public class ChallengeCreateRequestDto { @JsonProperty("status") private ChallengeStatusDto status; + @JsonProperty("difficulty") + private ChallengeDifficultyDto difficulty; + public ChallengeCreateRequestDto name(String name) { this.name = name; return this; @@ -64,6 +67,26 @@ public void setStatus(ChallengeStatusDto status) { this.status = status; } + public ChallengeCreateRequestDto difficulty(ChallengeDifficultyDto difficulty) { + this.difficulty = difficulty; + return this; + } + + /** + * Get difficulty + * + * @return difficulty + */ + @Valid + @Schema(name = "difficulty", required = false) + public ChallengeDifficultyDto getDifficulty() { + return difficulty; + } + + public void setDifficulty(ChallengeDifficultyDto difficulty) { + this.difficulty = difficulty; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -74,12 +97,13 @@ public boolean equals(Object o) { } ChallengeCreateRequestDto challengeCreateRequest = (ChallengeCreateRequestDto) o; return Objects.equals(this.name, challengeCreateRequest.name) - && Objects.equals(this.status, challengeCreateRequest.status); + && Objects.equals(this.status, challengeCreateRequest.status) + && Objects.equals(this.difficulty, challengeCreateRequest.difficulty); } @Override public int hashCode() { - return Objects.hash(name, status); + return Objects.hash(name, status, difficulty); } @Override @@ -88,6 +112,7 @@ public String toString() { sb.append("class ChallengeCreateRequestDto {\n"); sb.append(" name: ").append(toIndentedString(name)).append("\n"); sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append(" difficulty: ").append(toIndentedString(difficulty)).append("\n"); sb.append("}"); return sb.toString(); } diff --git a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/dto/ChallengeDifficultyDto.java b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/dto/ChallengeDifficultyDto.java new file mode 100644 index 0000000000..aaf3635c47 --- /dev/null +++ b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/dto/ChallengeDifficultyDto.java @@ -0,0 +1,43 @@ +package org.sagebionetworks.challenge.model.dto; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.*; +import javax.annotation.Generated; +import javax.validation.constraints.*; + +/** The difficulty level of a challenge. */ +@Generated(value = "org.openapitools.codegen.languages.SpringCodegen") +public enum ChallengeDifficultyDto { + GOOD_FOR_BEGINNERS("good_for_beginners"), + + INTERMEDIATE("intermediate"), + + ADVANCED("advanced"); + + private String value; + + ChallengeDifficultyDto(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static ChallengeDifficultyDto fromValue(String value) { + for (ChallengeDifficultyDto b : ChallengeDifficultyDto.values()) { + if (b.value.equals(value)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected value '" + value + "'"); + } +} diff --git a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/dto/ChallengeDto.java b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/dto/ChallengeDto.java index 078b1ca231..7f35bd68a4 100644 --- a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/dto/ChallengeDto.java +++ b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/dto/ChallengeDto.java @@ -24,6 +24,9 @@ public class ChallengeDto { @JsonProperty("status") private ChallengeStatusDto status; + @JsonProperty("difficulty") + private ChallengeDifficultyDto difficulty; + @JsonProperty("id") private Long id; @@ -77,6 +80,26 @@ public void setStatus(ChallengeStatusDto status) { this.status = status; } + public ChallengeDto difficulty(ChallengeDifficultyDto difficulty) { + this.difficulty = difficulty; + return this; + } + + /** + * Get difficulty + * + * @return difficulty + */ + @Valid + @Schema(name = "difficulty", required = false) + public ChallengeDifficultyDto getDifficulty() { + return difficulty; + } + + public void setDifficulty(ChallengeDifficultyDto difficulty) { + this.difficulty = difficulty; + } + public ChallengeDto id(Long id) { this.id = id; return this; @@ -154,6 +177,7 @@ public boolean equals(Object o) { ChallengeDto challenge = (ChallengeDto) o; return Objects.equals(this.name, challenge.name) && Objects.equals(this.status, challenge.status) + && Objects.equals(this.difficulty, challenge.difficulty) && Objects.equals(this.id, challenge.id) && Objects.equals(this.createdAt, challenge.createdAt) && Objects.equals(this.updatedAt, challenge.updatedAt); @@ -161,7 +185,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(name, status, id, createdAt, updatedAt); + return Objects.hash(name, status, difficulty, id, createdAt, updatedAt); } @Override @@ -170,6 +194,7 @@ public String toString() { sb.append("class ChallengeDto {\n"); sb.append(" name: ").append(toIndentedString(name)).append("\n"); sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append(" difficulty: ").append(toIndentedString(difficulty)).append("\n"); sb.append(" id: ").append(toIndentedString(id)).append("\n"); sb.append(" createdAt: ").append(toIndentedString(createdAt)).append("\n"); sb.append(" updatedAt: ").append(toIndentedString(updatedAt)).append("\n"); diff --git a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/entity/ChallengeEntity.java b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/entity/ChallengeEntity.java index 837f764bcd..c70f961d7e 100644 --- a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/entity/ChallengeEntity.java +++ b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/entity/ChallengeEntity.java @@ -32,6 +32,9 @@ public class ChallengeEntity { @Column(nullable = false) private String status; + @Column(nullable = false) + private String difficulty; + // @Column(nullable = false) // private String email; diff --git a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/mapper/ChallengeMapper.java b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/mapper/ChallengeMapper.java index 81cb57bfab..f44a5d873e 100644 --- a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/mapper/ChallengeMapper.java +++ b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/mapper/ChallengeMapper.java @@ -1,5 +1,6 @@ package org.sagebionetworks.challenge.model.mapper; +import org.sagebionetworks.challenge.model.dto.ChallengeDifficultyDto; import org.sagebionetworks.challenge.model.dto.ChallengeDto; import org.sagebionetworks.challenge.model.dto.ChallengeStatusDto; import org.sagebionetworks.challenge.model.entity.ChallengeEntity; @@ -22,6 +23,7 @@ public ChallengeDto convertToDto(ChallengeEntity entity, Object... args) { if (entity != null) { BeanUtils.copyProperties(entity, user); user.setStatus(ChallengeStatusDto.fromValue(entity.getStatus())); + user.setDifficulty(ChallengeDifficultyDto.fromValue(entity.getDifficulty())); } return user; } diff --git a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/repository/ChallengeFilter.java b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/repository/ChallengeFilter.java new file mode 100644 index 0000000000..45c24dbca1 --- /dev/null +++ b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/repository/ChallengeFilter.java @@ -0,0 +1,16 @@ +package org.sagebionetworks.challenge.model.repository; + +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ChallengeFilter { + private List status; + private List difficulty; +} diff --git a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/repository/ChallengeRepository.java b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/repository/ChallengeRepository.java index cd63d49188..10366b1f72 100644 --- a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/repository/ChallengeRepository.java +++ b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/repository/ChallengeRepository.java @@ -5,7 +5,4 @@ import org.springframework.data.querydsl.QuerydslPredicateExecutor; public interface ChallengeRepository - extends JpaRepository, QuerydslPredicateExecutor { - - // Optional findByLogin(String login); -} + extends JpaRepository, QuerydslPredicateExecutor {} diff --git a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/repository/ChallengeRepositoryCustom.java b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/repository/ChallengeRepositoryCustom.java new file mode 100644 index 0000000000..47bff51ed0 --- /dev/null +++ b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/repository/ChallengeRepositoryCustom.java @@ -0,0 +1,10 @@ +package org.sagebionetworks.challenge.model.repository; + +import org.sagebionetworks.challenge.model.entity.ChallengeEntity; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +public interface ChallengeRepositoryCustom { + + Page findAll(Pageable pageable, ChallengeFilter filter); +} diff --git a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/repository/ChallengeRepositoryCustomImpl.java b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/repository/ChallengeRepositoryCustomImpl.java new file mode 100644 index 0000000000..621cdad7fc --- /dev/null +++ b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/model/repository/ChallengeRepositoryCustomImpl.java @@ -0,0 +1,44 @@ +package org.sagebionetworks.challenge.model.repository; + +import com.querydsl.core.QueryResults; +import com.querydsl.jpa.JPQLQuery; +import org.sagebionetworks.challenge.model.entity.ChallengeEntity; +import org.sagebionetworks.challenge.model.entity.QChallengeEntity; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport; +import org.springframework.stereotype.Repository; + +@Repository +public class ChallengeRepositoryCustomImpl extends QuerydslRepositorySupport + implements ChallengeRepositoryCustom { + + public ChallengeRepositoryCustomImpl() { + super(ChallengeEntity.class); + } + + @Override + public Page findAll(Pageable pageable, ChallengeFilter filter) { + QChallengeEntity challenge = QChallengeEntity.challengeEntity; + + JPQLQuery query = from(challenge); + + if (filter.getStatus() != null && filter.getStatus().size() > 0) { + query = query.where(challenge.status.in(filter.getStatus())); + } + + if (filter.getDifficulty() != null && filter.getDifficulty().size() > 0) { + query = query.where(challenge.difficulty.in(filter.getDifficulty())); + } + + query = super.getQuerydsl().applyPagination(pageable, query); + + // SearchResults entitys = query.listResults(QEmployees.employees); + // return new PageImpl(entitys.getResults(), pageable, entitys.getTotal()); + // SearchResults + QueryResults results = query.fetchResults(); + + return new PageImpl(results.getResults(), pageable, results.getTotal()); + } +} diff --git a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/service/ChallengeService.java b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/service/ChallengeService.java index ec9e70fcc4..9073986282 100644 --- a/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/service/ChallengeService.java +++ b/apps/challenge-service/src/main/java/org/sagebionetworks/challenge/service/ChallengeService.java @@ -1,18 +1,20 @@ package org.sagebionetworks.challenge.service; -import com.querydsl.core.types.dsl.BooleanExpression; import java.util.List; import lombok.extern.slf4j.Slf4j; +import org.sagebionetworks.challenge.model.dto.ChallengeDifficultyDto; import org.sagebionetworks.challenge.model.dto.ChallengeDto; import org.sagebionetworks.challenge.model.dto.ChallengeStatusDto; import org.sagebionetworks.challenge.model.dto.ChallengesPageDto; import org.sagebionetworks.challenge.model.entity.ChallengeEntity; -import org.sagebionetworks.challenge.model.entity.QChallengeEntity; import org.sagebionetworks.challenge.model.mapper.ChallengeMapper; +import org.sagebionetworks.challenge.model.repository.ChallengeFilter; import org.sagebionetworks.challenge.model.repository.ChallengeRepository; +import org.sagebionetworks.challenge.model.repository.ChallengeRepositoryCustom; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -21,19 +23,30 @@ public class ChallengeService { @Autowired private ChallengeRepository challengeRepository; + @Autowired private ChallengeRepositoryCustom challengeRepositoryCustom; private ChallengeMapper challengeMapper = new ChallengeMapper(); @Transactional(readOnly = true) public ChallengesPageDto listChallenges( - Integer pageNumber, Integer pageSize, List status) { + Integer pageNumber, + Integer pageSize, + List status, + List difficulty) { log.info("status {}", status); - QChallengeEntity qChallenge = QChallengeEntity.challengeEntity; - BooleanExpression q = qChallenge.status.in(status.stream().map(s -> s.toString()).toList()); + log.info("difficulty {}", difficulty); + + Pageable pageable = PageRequest.of(pageNumber, pageSize); + ChallengeFilter filter = + ChallengeFilter.builder() + .difficulty(difficulty.stream().map(d -> d.toString()).toList()) + .status(status.stream().map(s -> s.toString()).toList()) + .build(); Page challengeEntitiesPage = - challengeRepository.findAll(q, PageRequest.of(pageNumber, pageSize)); + challengeRepositoryCustom.findAll(pageable, filter); + log.info("challengeRepositoryCustom {}", challengeEntitiesPage); List challenges = challengeMapper.convertToDtoList(challengeEntitiesPage.getContent()); diff --git a/apps/challenge-service/src/main/resources/db/migration/V1.0.0__create_challenge_table.sql b/apps/challenge-service/src/main/resources/db/migration/V1.0.0__create_challenge_table.sql index 7086537e65..71eef62441 100644 --- a/apps/challenge-service/src/main/resources/db/migration/V1.0.0__create_challenge_table.sql +++ b/apps/challenge-service/src/main/resources/db/migration/V1.0.0__create_challenge_table.sql @@ -5,6 +5,7 @@ CREATE TABLE `challenge` `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `status` ENUM('upcoming', 'active', 'completed'), + `difficulty` ENUM('good_for_beginners', 'intermediate', 'advanced'), -- `email` varchar(255) DEFAULT NULL, -- `login` varchar(255) UNIQUE, -- `avatar_url` varchar(255) DEFAULT NULL, diff --git a/apps/challenge-service/src/main/resources/db/migration/V1.0.1__temp_data.sql b/apps/challenge-service/src/main/resources/db/migration/V1.0.1__temp_data.sql index 0fdc659c59..54cde1ec07 100644 --- a/apps/challenge-service/src/main/resources/db/migration/V1.0.1__temp_data.sql +++ b/apps/challenge-service/src/main/resources/db/migration/V1.0.1__temp_data.sql @@ -1,12 +1,19 @@ -INSERT INTO challenge (id, name, status) +INSERT INTO challenge (id, name, status, difficulty) VALUES ( '1', 'The Digital Mammography DREAM Challenge', - 'upcoming' + 'upcoming', + 'good_for_beginners' ), ( '2', 'Patient Mortality EHR DREAM Challenge', - 'active' + 'active', + 'intermediate' ), - ('3', 'COVID-19 EHR DREAM Challenge', 'completed'); \ No newline at end of file + ( + '3', + 'COVID-19 EHR DREAM Challenge', + 'completed', + 'advanced' + ); \ No newline at end of file diff --git a/apps/challenge-service/src/main/resources/openapi.yaml b/apps/challenge-service/src/main/resources/openapi.yaml index 9aa00864cd..e19fa4821f 100644 --- a/apps/challenge-service/src/main/resources/openapi.yaml +++ b/apps/challenge-service/src/main/resources/openapi.yaml @@ -43,7 +43,7 @@ paths: minimum: 1 type: integer style: form - - description: Array of challenge status used to filter the results. + - description: An array of challenge status used to filter the results. explode: true in: query name: status @@ -53,6 +53,16 @@ paths: $ref: '#/components/schemas/ChallengeStatus' type: array style: form + - description: An array of challenge difficulty levels used to filter the results. + explode: true + in: query + name: difficulty + required: false + schema: + items: + $ref: '#/components/schemas/ChallengeDifficulty' + type: array + style: form responses: "200": content: @@ -106,7 +116,7 @@ components: type: integer style: form status: - description: Array of challenge status used to filter the results. + description: An array of challenge status used to filter the results. explode: true in: query name: status @@ -116,6 +126,17 @@ components: $ref: '#/components/schemas/ChallengeStatus' type: array style: form + difficulty: + description: An array of challenge difficulty levels used to filter the results. + explode: true + in: query + name: difficulty + required: false + schema: + items: + $ref: '#/components/schemas/ChallengeDifficulty' + type: array + style: form responses: BadRequest: content: @@ -138,6 +159,14 @@ components: - completed example: active type: string + ChallengeDifficulty: + description: The difficulty level of a challenge. + enum: + - good_for_beginners + - intermediate + - advanced + example: intermediate + type: string PageMetadata: description: The metadata of a page. properties: @@ -187,6 +216,8 @@ components: type: string status: $ref: '#/components/schemas/ChallengeStatus' + difficulty: + $ref: '#/components/schemas/ChallengeDifficulty' required: - name - status diff --git a/apps/challenge-service/templates/converter.mustache b/apps/challenge-service/templates/converter.mustache new file mode 100644 index 0000000000..7a7005e398 --- /dev/null +++ b/apps/challenge-service/templates/converter.mustache @@ -0,0 +1,34 @@ +package {{configPackage}}; + +{{#models}} + {{#model}} + {{#isEnum}} +import {{modelPackage}}.{{classname}}; + {{/isEnum}} + {{/model}} +{{/models}} + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.convert.converter.Converter; + +@Configuration +public class EnumConverterConfiguration { + +{{#models}} +{{#model}} +{{#isEnum}} + @Bean + Converter<{{{dataType}}}, {{classname}}> {{classVarName}}Converter() { + return new Converter<{{{dataType}}}, {{classname}}>() { + @Override + public {{classname}} convert({{{dataType}}} source) { + return {{classname}}.fromValue(source); + } + }; + } +{{/isEnum}} +{{/model}} +{{/models}} + +} diff --git a/apps/challenge-service/templates/v6.2.1/converter.mustache b/apps/challenge-service/templates/v6.2.1/converter.mustache new file mode 100644 index 0000000000..a331ded633 --- /dev/null +++ b/apps/challenge-service/templates/v6.2.1/converter.mustache @@ -0,0 +1,34 @@ +package {{configPackage}}; + +{{#models}} + {{#model}} + {{#isEnum}} +import {{modelPackage}}.{{name}}; + {{/isEnum}} + {{/model}} +{{/models}} + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.convert.converter.Converter; + +@Configuration +public class EnumConverterConfiguration { + +{{#models}} +{{#model}} +{{#isEnum}} + @Bean + Converter<{{{dataType}}}, {{name}}> {{classVarName}}Converter() { + return new Converter<{{{dataType}}}, {{name}}>() { + @Override + public {{name}} convert({{{dataType}}} source) { + return {{name}}.fromValue(source); + } + }; + } +{{/isEnum}} +{{/model}} +{{/models}} + +} diff --git a/apps/challenge-service/tools/pull-templates.sh b/apps/challenge-service/tools/pull-templates.sh index c21352cd28..e82d8c5838 100755 --- a/apps/challenge-service/tools/pull-templates.sh +++ b/apps/challenge-service/tools/pull-templates.sh @@ -8,4 +8,6 @@ mkdir -p "${destinationFolder}" curl -O --output-dir "${destinationFolder}" \ "https://raw.githubusercontent.com/OpenAPITools/openapi-generator/${openapiGeneratorVersion}/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/openapi2SpringBoot.mustache" curl -O --output-dir "${destinationFolder}" \ - "https://raw.githubusercontent.com/OpenAPITools/openapi-generator/${openapiGeneratorVersion}/modules/openapi-generator/src/main/resources/JavaSpring/pojo.mustache" \ No newline at end of file + "https://raw.githubusercontent.com/OpenAPITools/openapi-generator/${openapiGeneratorVersion}/modules/openapi-generator/src/main/resources/JavaSpring/pojo.mustache" +curl -O --output-dir "${destinationFolder}" \ + "https://raw.githubusercontent.com/OpenAPITools/openapi-generator/${openapiGeneratorVersion}/modules/openapi-generator/src/main/resources/JavaSpring/converter.mustache" \ No newline at end of file diff --git a/libs/api-spec/build/challenge.openapi.yaml b/libs/api-spec/build/challenge.openapi.yaml index 6751b84a92..4c4f831bc8 100644 --- a/libs/api-spec/build/challenge.openapi.yaml +++ b/libs/api-spec/build/challenge.openapi.yaml @@ -27,6 +27,7 @@ paths: - $ref: '#/components/parameters/pageNumber' - $ref: '#/components/parameters/pageSize' - $ref: '#/components/parameters/status' + - $ref: '#/components/parameters/difficulty' responses: '200': content: @@ -60,13 +61,22 @@ components: minimum: 1 status: name: status - description: Array of challenge status used to filter the results. + description: An array of challenge status used to filter the results. in: query required: false schema: type: array items: $ref: '#/components/schemas/ChallengeStatus' + difficulty: + name: difficulty + description: An array of challenge difficulty levels used to filter the results. + in: query + required: false + schema: + type: array + items: + $ref: '#/components/schemas/ChallengeDifficulty' schemas: ChallengeStatus: description: The status of the challenge. @@ -76,6 +86,14 @@ components: - active - completed example: active + ChallengeDifficulty: + description: The difficulty level of a challenge. + type: string + enum: + - good_for_beginners + - intermediate + - advanced + example: intermediate PageMetadata: type: object description: The metadata of a page. @@ -126,6 +144,8 @@ components: example: Example challenge status: $ref: '#/components/schemas/ChallengeStatus' + difficulty: + $ref: '#/components/schemas/ChallengeDifficulty' required: - name - status diff --git a/libs/api-spec/build/openapi.yaml b/libs/api-spec/build/openapi.yaml index 4652e1a467..1a725174f0 100644 --- a/libs/api-spec/build/openapi.yaml +++ b/libs/api-spec/build/openapi.yaml @@ -31,6 +31,7 @@ paths: - $ref: '#/components/parameters/pageNumber' - $ref: '#/components/parameters/pageSize' - $ref: '#/components/parameters/status' + - $ref: '#/components/parameters/difficulty' responses: '200': content: @@ -177,6 +178,14 @@ components: - active - completed example: active + ChallengeDifficulty: + description: The difficulty level of a challenge. + type: string + enum: + - good_for_beginners + - intermediate + - advanced + example: intermediate PageMetadata: type: object description: The metadata of a page. @@ -227,6 +236,8 @@ components: example: Example challenge status: $ref: '#/components/schemas/ChallengeStatus' + difficulty: + $ref: '#/components/schemas/ChallengeDifficulty' required: - name - status @@ -546,13 +557,22 @@ components: minimum: 1 status: name: status - description: Array of challenge status used to filter the results. + description: An array of challenge status used to filter the results. in: query required: false schema: type: array items: $ref: '#/components/schemas/ChallengeStatus' + difficulty: + name: difficulty + description: An array of challenge difficulty levels used to filter the results. + in: query + required: false + schema: + type: array + items: + $ref: '#/components/schemas/ChallengeDifficulty' organizationLogin: name: organizationLogin in: path diff --git a/libs/api-spec/src/components/parameters/query/challenge/difficulty.yaml b/libs/api-spec/src/components/parameters/query/challenge/difficulty.yaml new file mode 100644 index 0000000000..7349a24fc9 --- /dev/null +++ b/libs/api-spec/src/components/parameters/query/challenge/difficulty.yaml @@ -0,0 +1,8 @@ +name: difficulty +description: An array of challenge difficulty levels used to filter the results. +in: query +required: false +schema: + type: array + items: + $ref: ../../../schemas/ChallengeDifficulty.yaml diff --git a/libs/api-spec/src/paths/parameters/challenge/incentiveTypes.yaml b/libs/api-spec/src/components/parameters/query/challenge/incentiveTypes.yaml similarity index 64% rename from libs/api-spec/src/paths/parameters/challenge/incentiveTypes.yaml rename to libs/api-spec/src/components/parameters/query/challenge/incentiveTypes.yaml index 1ea4439630..603cbd681f 100644 --- a/libs/api-spec/src/paths/parameters/challenge/incentiveTypes.yaml +++ b/libs/api-spec/src/components/parameters/query/challenge/incentiveTypes.yaml @@ -1,8 +1,8 @@ name: incentiveTypes -description: Array of challenge incentive types used to filter the results +description: Array of challenge incentive types used to filter the results. in: query required: false schema: type: array items: - $ref: ../../../components/schemas/ChallengeIncentiveType.yaml + $ref: ../../../schemas/ChallengeIncentiveType.yaml diff --git a/libs/api-spec/src/paths/parameters/challenge/platformIds.yaml b/libs/api-spec/src/components/parameters/query/challenge/platformIds.yaml similarity index 66% rename from libs/api-spec/src/paths/parameters/challenge/platformIds.yaml rename to libs/api-spec/src/components/parameters/query/challenge/platformIds.yaml index fc7024a0f1..2fca068b6f 100644 --- a/libs/api-spec/src/paths/parameters/challenge/platformIds.yaml +++ b/libs/api-spec/src/components/parameters/query/challenge/platformIds.yaml @@ -1,8 +1,8 @@ name: platformIds -description: Array of challenge platform ids used to filter the results +description: Array of challenge platform ids used to filter the results. in: query required: false schema: type: array items: - $ref: ../../../components/schemas/ChallengePlatformId.yaml + $ref: ../../../schemas/ChallengePlatformId.yaml diff --git a/libs/api-spec/src/components/parameters/query/challenge/status.yaml b/libs/api-spec/src/components/parameters/query/challenge/status.yaml index 3739d4a3de..ee27a5059c 100644 --- a/libs/api-spec/src/components/parameters/query/challenge/status.yaml +++ b/libs/api-spec/src/components/parameters/query/challenge/status.yaml @@ -1,5 +1,5 @@ name: status -description: Array of challenge status used to filter the results. +description: An array of challenge status used to filter the results. in: query required: false schema: diff --git a/libs/api-spec/src/components/schemas/ChallengeCreateRequest.yaml b/libs/api-spec/src/components/schemas/ChallengeCreateRequest.yaml index 87766b120a..bec86058c1 100644 --- a/libs/api-spec/src/components/schemas/ChallengeCreateRequest.yaml +++ b/libs/api-spec/src/components/schemas/ChallengeCreateRequest.yaml @@ -20,24 +20,24 @@ properties: # format: url status: $ref: ChallengeStatus.yaml -# startDate: -# type: string -# format: date -# nullable: true -# endDate: -# type: string -# format: date -# nullable: true -# incentiveTypes: -# type: array -# items: -# $ref: ChallengeIncentiveType.yaml -# nullable: true -# platformId: -# $ref: ChallengePlatformId.yaml -# nullable: true -# difficulty: -# $ref: ChallengeDifficulty.yaml + # startDate: + # type: string + # format: date + # nullable: true + # endDate: + # type: string + # format: date + # nullable: true + # incentiveTypes: + # type: array + # items: + # $ref: ChallengeIncentiveType.yaml + # nullable: true + # platformId: + # $ref: ChallengePlatformId.yaml + # nullable: true + difficulty: + $ref: ChallengeDifficulty.yaml # submissionTypes: # type: array # items: diff --git a/libs/api-spec/src/components/schemas/ChallengeDifficulty.yaml b/libs/api-spec/src/components/schemas/ChallengeDifficulty.yaml index 2505616380..44dc702d11 100644 --- a/libs/api-spec/src/components/schemas/ChallengeDifficulty.yaml +++ b/libs/api-spec/src/components/schemas/ChallengeDifficulty.yaml @@ -1,7 +1,7 @@ -description: The difficulty level of a challenge +description: The difficulty level of a challenge. type: string enum: - - GoodForBeginners - - Intermediate - - Advanced -example: Intermediate + - good_for_beginners + - intermediate + - advanced +example: intermediate diff --git a/libs/api-spec/src/components/schemas/ChallengeIncentiveType.yaml b/libs/api-spec/src/components/schemas/ChallengeIncentiveType.yaml index 52f7988d85..955884a837 100644 --- a/libs/api-spec/src/components/schemas/ChallengeIncentiveType.yaml +++ b/libs/api-spec/src/components/schemas/ChallengeIncentiveType.yaml @@ -1,8 +1,8 @@ -description: The incentive type of the challenge +description: The incentive type of the challenge. type: string enum: - - Monetary - - Publication - - SpeakingEngagement - - Other -example: Monetary + - monetary + - publication + - speaking_engagement + - other +example: publication diff --git a/libs/api-spec/src/paths/challenges.yaml b/libs/api-spec/src/paths/challenges.yaml index 4e9835ac75..a8eaadd3b2 100644 --- a/libs/api-spec/src/paths/challenges.yaml +++ b/libs/api-spec/src/paths/challenges.yaml @@ -37,18 +37,18 @@ get: parameters: - $ref: ../components/parameters/query/pageNumber.yaml - $ref: ../components/parameters/query/pageSize.yaml - # - $ref: parameters/limit.yaml - # - $ref: parameters/offset.yaml # - $ref: parameters/sort.yaml # - $ref: parameters/direction.yaml # - $ref: parameters/searchTerms.yaml # - $ref: parameters/topics.yaml # - $ref: parameters/inputDataTypes.yaml - $ref: ../components/parameters/query/challenge/status.yaml - # - $ref: parameters/challenge/platformIds.yaml - # - $ref: parameters/challenge/difficulty.yaml + # - $ref: ../components/parameters/query/challenge/platformIds.yaml + - $ref: ../components/parameters/query/challenge/difficulty.yaml # - $ref: parameters/challenge/submissionTypes.yaml - # - $ref: parameters/challenge/incentiveTypes.yaml + + # - $ref: ../components/parameters/query/challenge/incentiveTypes.yaml + # - $ref: parameters/challenge/startDateRange.yaml # - $ref: parameters/challenge/orgIds.yaml # - $ref: parameters/challenge/organizerIds.yaml diff --git a/libs/api-spec/src/paths/parameters/challenge/difficulty.yaml b/libs/api-spec/src/paths/parameters/challenge/difficulty.yaml deleted file mode 100644 index da5fdd860e..0000000000 --- a/libs/api-spec/src/paths/parameters/challenge/difficulty.yaml +++ /dev/null @@ -1,8 +0,0 @@ -name: difficulty -description: Array of challenge difficulty levels used to filter the results -in: query -required: false -schema: - type: array - items: - $ref: ../../../components/schemas/ChallengeDifficulty.yaml diff --git a/libs/api-spec/src/paths/parameters/challenge/status.yaml b/libs/api-spec/src/paths/parameters/challenge/status.yaml deleted file mode 100644 index 0f4dfcfd1b..0000000000 --- a/libs/api-spec/src/paths/parameters/challenge/status.yaml +++ /dev/null @@ -1,8 +0,0 @@ -name: status -description: Array of challenge status used to filter the results -in: query -required: false -schema: - type: array - items: - $ref: ../../../components/schemas/ChallengeStatus.yaml diff --git a/libs/api-spec/src/paths/parameters/limit.yaml b/libs/api-spec/src/paths/parameters/limit.yaml deleted file mode 100644 index 299f2b32d9..0000000000 --- a/libs/api-spec/src/paths/parameters/limit.yaml +++ /dev/null @@ -1,9 +0,0 @@ -name: limit -description: Maximum number of results returned -in: query -required: false -schema: - type: integer - default: 10 - minimum: 10 - maximum: 100 diff --git a/libs/api-spec/src/paths/parameters/offset.yaml b/libs/api-spec/src/paths/parameters/offset.yaml deleted file mode 100644 index 3734500213..0000000000 --- a/libs/api-spec/src/paths/parameters/offset.yaml +++ /dev/null @@ -1,8 +0,0 @@ -name: offset -description: Index of the first result that must be returned -in: query -required: false -schema: - type: integer - default: 0 - minimum: 0