diff --git a/src/main/java/org/icgc/argo/program_service/converter/ProgramConverter.java b/src/main/java/org/icgc/argo/program_service/converter/ProgramConverter.java index 569fbfad..cfff827a 100644 --- a/src/main/java/org/icgc/argo/program_service/converter/ProgramConverter.java +++ b/src/main/java/org/icgc/argo/program_service/converter/ProgramConverter.java @@ -1,466 +1,468 @@ -/* - * Copyright (c) 2020 The Ontario Institute for Cancer Research. All rights reserved - * - * This program and the accompanying materials are made available under the terms of the GNU Affero General Public License v3.0. - * You should have received a copy of the GNU Affero General Public License along with - * this program. If not, see . - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - */ - -package org.icgc.argo.program_service.converter; - -import static java.util.stream.Collectors.toList; - -import com.google.protobuf.BoolValue; -import com.google.protobuf.StringValue; -import java.util.Collection; -import java.util.Optional; -import java.util.UUID; -import lombok.NonNull; -import lombok.val; -import org.icgc.argo.program_service.model.entity.*; -import org.icgc.argo.program_service.model.entity.JoinProgramInviteEntity; -import org.icgc.argo.program_service.model.entity.ProgramEntity; -import org.icgc.argo.program_service.proto.*; -import org.icgc.argo.program_service.services.ego.model.entity.EgoUser; -import org.mapstruct.AfterMapping; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.MappingTarget; - -@Mapper( - config = ConverterConfig.class, - uses = {CommonConverter.class}) -public interface ProgramConverter { - ProgramConverter INSTANCE = new ProgramConverterImpl(CommonConverter.INSTANCE); - - @Mapping(target = "id", ignore = true) - @Mapping(target = "updatedAt", ignore = true) - @Mapping(target = "createdAt", ignore = true) - @Mapping(target = "programCancers", ignore = true) - @Mapping(target = "programPrimarySites", ignore = true) - @Mapping(target = "programInstitutions", ignore = true) - @Mapping(target = "programCountries", ignore = true) - @Mapping(target = "programRegions", ignore = true) - @Mapping(target = "active", constant = "true") - @Mapping(target = "legacyShortName", ignore = true) - ProgramEntity programToProgramEntity(Program p); - - @Mapping(target = "id", ignore = true) - @Mapping(target = "shortName", ignore = true) - @Mapping(target = "createdAt", ignore = true) - @Mapping(target = "updatedAt", ignore = true) - @Mapping(target = "programCancers", ignore = true) - @Mapping(target = "programPrimarySites", ignore = true) - @Mapping(target = "programInstitutions", ignore = true) - @Mapping(target = "programCountries", ignore = true) - @Mapping(target = "programRegions", ignore = true) - void updateProgram(ProgramEntity updatingProgram, @MappingTarget ProgramEntity programToUpdate); - - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "mergeShortName", ignore = true) - @Mapping(target = "mergeDescription", ignore = true) - @Mapping(target = "mergeName", ignore = true) - @Mapping(target = "mergeMembershipType", ignore = true) - @Mapping(target = "mergeCommitmentDonors", ignore = true) - @Mapping(target = "mergeSubmittedDonors", ignore = true) - @Mapping(target = "mergeGenomicDonors", ignore = true) - @Mapping(target = "mergeWebsite", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - @Mapping(target = "allFields", ignore = true) - @Mapping(target = "cancerTypesList", ignore = true) - @Mapping(target = "primarySitesList", ignore = true) - @Mapping(target = "institutionsList", ignore = true) - @Mapping(target = "countriesList", ignore = true) - @Mapping(target = "regionsList", ignore = true) - Program programEntityToProgram(ProgramEntity entity); - - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "mergeName", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - @Mapping(target = "allFields", ignore = true) - @Mapping(target = "mergeId", ignore = true) - Cancer cancerEntityToCancer(CancerEntity entity); - - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "mergeName", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - @Mapping(target = "allFields", ignore = true) - @Mapping(target = "mergeId", ignore = true) - PrimarySite primarySiteEntityToPrimarySite(PrimarySiteEntity entity); - - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "mergeName", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - @Mapping(target = "allFields", ignore = true) - @Mapping(target = "mergeId", ignore = true) - Country countryEntityToCountry(CountryEntity entity); - - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "mergeName", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - @Mapping(target = "allFields", ignore = true) - @Mapping(target = "mergeId", ignore = true) - Region regionEntityToRegion(RegionEntity entity); - - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "mergeName", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - @Mapping(target = "allFields", ignore = true) - @Mapping(target = "mergeId", ignore = true) - Institution institutionEntityToInstitution(InstitutionEntity entity); - - @AfterMapping - default void updateProgramFromEntity( - @NonNull ProgramEntity entity, @NonNull @MappingTarget Program.Builder programBuilder) { - programBuilder - .addAllCancerTypes(entity.listCancerTypes()) - .addAllPrimarySites(entity.listPrimarySites()) - .addAllInstitutions(entity.listInstitutions()) - .addAllCountries(entity.listCountries()) - .addAllRegions(entity.listRegions()); - } - - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - @Mapping(target = "allFields", ignore = true) - @Mapping(target = "mergeCreatedAt", ignore = true) - CreateProgramResponse programEntityToCreateProgramResponse(ProgramEntity p); - - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "allFields", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - @Mapping(target = "mergeUpdatedAt", ignore = true) - UpdateProgramResponse programEntityToUpdateProgramResponse(ProgramEntity p); - - default ProgramDetails programEntityToProgramDetails(ProgramEntity value) { - val program = programEntityToProgram(value); - val metadata = programEntityToMetadata(value); - val legacyDetails = programEntityToLegacyData(value); - return ProgramDetails.newBuilder() - .setProgram(program) - .setMetadata(metadata) - .mergeLegacy(legacyDetails) - .build(); - } - - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "removePrograms", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - @Mapping(target = "allFields", ignore = true) - @Mapping(target = "programsOrBuilderList", ignore = true) - @Mapping(target = "programsBuilderList", ignore = true) - // TODO: [rtisma] this is a hack for a bug in mapstruct when mapping an iterable to a wrapper - // (non-iterable) - // https://github.com/mapstruct/mapstruct/issues/607#issuecomment-309547739 - @Mapping(target = "programsList", source = "programEntities") - ListProgramsResponse programEntitiesToListProgramsResponse( - Integer dummy, Collection programEntities); - - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "mergeMessage", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - @Mapping(target = "allFields", ignore = true) - RemoveUserResponse toRemoveUserResponse(String message); - - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "mergeCreatedAt", ignore = true) - @Mapping(target = "mergeUpdatedAt", ignore = true) - @Mapping(target = "allFields", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - Metadata programEntityToMetadata(ProgramEntity programEntity); - - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "mergeLegacyShortName", ignore = true) - @Mapping(target = "allFields", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - LegacyDetails programEntityToLegacyData(ProgramEntity programEntity); - - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "mergeEmail", ignore = true) - @Mapping(target = "mergeFirstName", ignore = true) - @Mapping(target = "mergeLastName", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - @Mapping(target = "allFields", ignore = true) - @Mapping(target = "mergeRole", ignore = true) - User egoUserToUser(EgoUser egoUser); - - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "mergeUser", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - @Mapping(target = "allFields", ignore = true) - @Mapping(target = "user", source = "egoUser") - JoinProgramResponse egoUserToJoinProgramResponse(Integer dummy, EgoUser egoUser); - - @Mapping(target = "id", ignore = true) - @Mapping(target = "type", ignore = true) - @Mapping(target = "status", ignore = true) - @Mapping(target = "email", source = "userEmail") - EgoUser joinProgramInviteToEgoUser(JoinProgramInviteEntity invite); - - default JoinProgramResponse egoUserToJoinProgramResponse(EgoUser egoUser) { - return egoUserToJoinProgramResponse(0, egoUser); - } - - default UserRoleValue boxUserValue(@NonNull UserRole role) { - return UserRoleValue.newBuilder().setValue(role).build(); - } - - default ListProgramsResponse programEntitiesToListProgramsResponse( - Collection programEntities) { - return programEntitiesToListProgramsResponse(0, programEntities); - } - - default ListCancersResponse cancerEntitiesToListCancersResponse( - Collection cancerEntities) { - return ListCancersResponse.newBuilder() - .addAllCancers(cancerEntities.stream().map(this::cancerEntityToCancer).collect(toList())) - .build(); - } - - default ListPrimarySitesResponse primarySiteEntitiesToListPrimarySitesResponse( - Collection primarySiteEntities) { - return ListPrimarySitesResponse.newBuilder() - .addAllPrimarySites( - primarySiteEntities.stream() - .map(this::primarySiteEntityToPrimarySite) - .collect(toList())) - .build(); - } - - default ListCountriesResponse countryEntitiesToListCountriesResponse( - Collection countryEntities) { - return ListCountriesResponse.newBuilder() - .addAllCountries( - countryEntities.stream().map(this::countryEntityToCountry).collect(toList())) - .build(); - } - - default ListRegionsResponse regionEntitiesToListRegionsResponse( - Collection regionEntities) { - return ListRegionsResponse.newBuilder() - .addAllRegions(regionEntities.stream().map(this::regionEntityToRegion).collect(toList())) - .build(); - } - - default ListInstitutionsResponse institutionEntitiesToListInstitutionsResponse( - Collection institutionEntities) { - return ListInstitutionsResponse.newBuilder() - .addAllInstitutions( - institutionEntities.stream() - .map(this::institutionEntityToInstitution) - .collect(toList())) - .build(); - } - - default AddInstitutionsResponse institutionsToAddInstitutionsResponse( - Collection institutionEntities) { - return AddInstitutionsResponse.newBuilder() - .addAllInstitutions( - institutionEntities.stream() - .map(this::institutionEntityToInstitution) - .collect(toList())) - .build(); - } - - default InviteUserResponse inviteIdToInviteUserResponse(@NonNull UUID inviteId) { - return InviteUserResponse.newBuilder().setInviteId(StringValue.of(inviteId.toString())).build(); - } - - /** Enum Boxing Converters */ - default MembershipTypeValue boxMembershipType(MembershipType m) { - return MembershipTypeValue.newBuilder().setValue(m).build(); - } - - default MembershipType unboxMembershipTypeValue(@NonNull MembershipTypeValue v) { - return v.getValue(); - } - - default InviteStatusValue JoinProgramInviteStatusToInviteStatus( - JoinProgramInviteEntity.Status status) { - switch (status) { - case ACCEPTED: - return InviteStatusValue.newBuilder().setValue(InviteStatus.ACCEPTED).build(); - case EXPIRED: - return InviteStatusValue.newBuilder().setValue(InviteStatus.EXPIRED).build(); - case PENDING: - return InviteStatusValue.newBuilder().setValue(InviteStatus.PENDING).build(); - case INVALID: - return InviteStatusValue.newBuilder().build(); - case REVOKED: - return InviteStatusValue.newBuilder().build(); - } - return InviteStatusValue.newBuilder().build(); - } - - default InviteStatus unboxInviteStatusValue(InviteStatusValue status) { - return status.getValue(); - } - - default InviteStatusValue boxInviteStatus(InviteStatus status) { - return InviteStatusValue.newBuilder().setValue(status).build(); - } - - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "mergeEmail", ignore = true) - @Mapping(target = "mergeFirstName", ignore = true) - @Mapping(target = "mergeLastName", ignore = true) - @Mapping(target = "mergeRole", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - @Mapping(target = "allFields", ignore = true) - @Mapping(target = "email", source = "userEmail") - User JoinProgramInviteToUser(JoinProgramInviteEntity invitation); - - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "mergeUser", ignore = true) - @Mapping(target = "mergeStatus", ignore = true) - @Mapping(target = "mergeAcceptedAt", ignore = true) - @Mapping(target = "mergeDacoApproved", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - @Mapping(target = "allFields", ignore = true) - @Mapping(target = "user", source = "invitation") - @Mapping(target = "dacoApproved", source = "dacoApproved") - UserDetails joinProgramInviteToUserDetails( - Integer dummy, JoinProgramInviteEntity invitation, boolean dacoApproved); - - default UserDetails joinProgramInviteToUserDetails(JoinProgramInviteEntity invitation) { - return joinProgramInviteToUserDetails(0, invitation, false); - } - - default UserDetails joinProgramInviteToUserDetails( - JoinProgramInviteEntity invitation, boolean dacoApproved) { - return joinProgramInviteToUserDetails(0, invitation, dacoApproved); - } - - default UserDetails userWithOptionalJoinProgramInviteToUserDetails( - User user, Optional invite, boolean dacoApproved) { - val builder = UserDetails.newBuilder(); - builder.setUser(user).setDacoApproved(BoolValue.of((dacoApproved))); - - if (invite.isEmpty()) { - return builder.build(); - } - - val status = JoinProgramInviteStatusToInviteStatus(invite.get().getStatus()); - val builder2 = builder.setStatus(boxInviteStatus(status.getValue())); - - if (status.getValue() == InviteStatus.PENDING) { - return builder2.build(); - } - - val accepted = CommonConverter.INSTANCE.localDateTimeToTimestamp(invite.get().getAcceptedAt()); - if (accepted != null) { - return builder2.setAcceptedAt(accepted).build(); - } - return builder2.build(); - } - - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "removeUserDetails", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - @Mapping(target = "allFields", ignore = true) - @Mapping(target = "userDetailsOrBuilderList", ignore = true) - @Mapping(target = "userDetailsBuilderList", ignore = true) - @Mapping(target = "userDetailsList", source = "invitations") - ListUsersResponse invitationsToListUsersResponse( - Integer dummy, Collection invitations); - - default ListUsersResponse invitationsToListUsersResponse( - Collection invitations) { - return invitationsToListUsersResponse(0, invitations); - } - - @Mapping(target = "mergeFrom", ignore = true) - @Mapping(target = "clearField", ignore = true) - @Mapping(target = "clearOneof", ignore = true) - @Mapping(target = "mergeId", ignore = true) - @Mapping(target = "mergeCreatedAt", ignore = true) - @Mapping(target = "mergeExpiresAt", ignore = true) - @Mapping(target = "mergeAcceptedAt", ignore = true) - @Mapping(target = "mergeProgram", ignore = true) - @Mapping(target = "mergeEmailSent", ignore = true) - @Mapping(target = "statusValue", ignore = true) - @Mapping(target = "unknownFields", ignore = true) - @Mapping(target = "mergeUnknownFields", ignore = true) - @Mapping(target = "allFields", ignore = true) - @Mapping(target = "user", ignore = true) - @Mapping(target = "mergeUser", ignore = true) - JoinProgramInvite joinProgramInviteEntityToJoinProgramInvite(JoinProgramInviteEntity entity); - - @AfterMapping - default void setUser( - @NonNull JoinProgramInviteEntity entity, - @NonNull @MappingTarget JoinProgramInvite.Builder joinProgramInvite) { - val userRole = UserRoleValue.newBuilder().setValue(entity.getRole()); - val user = - User.newBuilder() - .setEmail(StringValue.of(entity.getUserEmail())) - .setFirstName(StringValue.of(entity.getFirstName())) - .setLastName(StringValue.of(entity.getLastName())) - .setRole(userRole) - .build(); - joinProgramInvite.setUser(user); - } -} +/* + * Copyright (c) 2020 The Ontario Institute for Cancer Research. All rights reserved + * + * This program and the accompanying materials are made available under the terms of the GNU Affero General Public License v3.0. + * You should have received a copy of the GNU Affero General Public License along with + * this program. If not, see . + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + */ + +package org.icgc.argo.program_service.converter; + +import static java.util.stream.Collectors.toList; + +import com.google.protobuf.BoolValue; +import com.google.protobuf.StringValue; +import java.util.Collection; +import java.util.Optional; +import java.util.UUID; +import lombok.NonNull; +import lombok.val; +import org.icgc.argo.program_service.model.entity.*; +import org.icgc.argo.program_service.model.entity.JoinProgramInviteEntity; +import org.icgc.argo.program_service.model.entity.ProgramEntity; +import org.icgc.argo.program_service.proto.*; +import org.icgc.argo.program_service.services.ego.model.entity.EgoUser; +import org.mapstruct.AfterMapping; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; + +@Mapper( + config = ConverterConfig.class, + uses = {CommonConverter.class}) +public interface ProgramConverter { + ProgramConverter INSTANCE = new ProgramConverterImpl(CommonConverter.INSTANCE); + + @Mapping(target = "id", ignore = true) + @Mapping(target = "updatedAt", ignore = true) + @Mapping(target = "createdAt", ignore = true) + @Mapping(target = "programCancers", ignore = true) + @Mapping(target = "programPrimarySites", ignore = true) + @Mapping(target = "programInstitutions", ignore = true) + @Mapping(target = "programCountries", ignore = true) + @Mapping(target = "programRegions", ignore = true) + @Mapping(target = "active", constant = "true") + @Mapping(target = "legacyShortName", ignore = true) + @Mapping(target = "dataCenterId", ignore = true) + ProgramEntity programToProgramEntity(Program p); + + @Mapping(target = "id", ignore = true) + @Mapping(target = "shortName", ignore = true) + @Mapping(target = "createdAt", ignore = true) + @Mapping(target = "updatedAt", ignore = true) + @Mapping(target = "programCancers", ignore = true) + @Mapping(target = "programPrimarySites", ignore = true) + @Mapping(target = "programInstitutions", ignore = true) + @Mapping(target = "programCountries", ignore = true) + @Mapping(target = "programRegions", ignore = true) + void updateProgram(ProgramEntity updatingProgram, @MappingTarget ProgramEntity programToUpdate); + + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "mergeShortName", ignore = true) + @Mapping(target = "mergeDescription", ignore = true) + @Mapping(target = "mergeName", ignore = true) + @Mapping(target = "mergeMembershipType", ignore = true) + @Mapping(target = "mergeCommitmentDonors", ignore = true) + @Mapping(target = "mergeSubmittedDonors", ignore = true) + @Mapping(target = "mergeGenomicDonors", ignore = true) + @Mapping(target = "mergeWebsite", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "allFields", ignore = true) + @Mapping(target = "cancerTypesList", ignore = true) + @Mapping(target = "primarySitesList", ignore = true) + @Mapping(target = "institutionsList", ignore = true) + @Mapping(target = "countriesList", ignore = true) + @Mapping(target = "regionsList", ignore = true) + @Mapping(target = "mergeDataCenterId", ignore = true) + Program programEntityToProgram(ProgramEntity entity); + + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "mergeName", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "allFields", ignore = true) + @Mapping(target = "mergeId", ignore = true) + Cancer cancerEntityToCancer(CancerEntity entity); + + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "mergeName", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "allFields", ignore = true) + @Mapping(target = "mergeId", ignore = true) + PrimarySite primarySiteEntityToPrimarySite(PrimarySiteEntity entity); + + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "mergeName", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "allFields", ignore = true) + @Mapping(target = "mergeId", ignore = true) + Country countryEntityToCountry(CountryEntity entity); + + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "mergeName", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "allFields", ignore = true) + @Mapping(target = "mergeId", ignore = true) + Region regionEntityToRegion(RegionEntity entity); + + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "mergeName", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "allFields", ignore = true) + @Mapping(target = "mergeId", ignore = true) + Institution institutionEntityToInstitution(InstitutionEntity entity); + + @AfterMapping + default void updateProgramFromEntity( + @NonNull ProgramEntity entity, @NonNull @MappingTarget Program.Builder programBuilder) { + programBuilder + .addAllCancerTypes(entity.listCancerTypes()) + .addAllPrimarySites(entity.listPrimarySites()) + .addAllInstitutions(entity.listInstitutions()) + .addAllCountries(entity.listCountries()) + .addAllRegions(entity.listRegions()); + } + + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "allFields", ignore = true) + @Mapping(target = "mergeCreatedAt", ignore = true) + CreateProgramResponse programEntityToCreateProgramResponse(ProgramEntity p); + + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "allFields", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "mergeUpdatedAt", ignore = true) + UpdateProgramResponse programEntityToUpdateProgramResponse(ProgramEntity p); + + default ProgramDetails programEntityToProgramDetails(ProgramEntity value) { + val program = programEntityToProgram(value); + val metadata = programEntityToMetadata(value); + val legacyDetails = programEntityToLegacyData(value); + return ProgramDetails.newBuilder() + .setProgram(program) + .setMetadata(metadata) + .mergeLegacy(legacyDetails) + .build(); + } + + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "removePrograms", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "allFields", ignore = true) + @Mapping(target = "programsOrBuilderList", ignore = true) + @Mapping(target = "programsBuilderList", ignore = true) + // TODO: [rtisma] this is a hack for a bug in mapstruct when mapping an iterable to a wrapper + // (non-iterable) + // https://github.com/mapstruct/mapstruct/issues/607#issuecomment-309547739 + @Mapping(target = "programsList", source = "programEntities") + ListProgramsResponse programEntitiesToListProgramsResponse( + Integer dummy, Collection programEntities); + + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "mergeMessage", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "allFields", ignore = true) + RemoveUserResponse toRemoveUserResponse(String message); + + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "mergeCreatedAt", ignore = true) + @Mapping(target = "mergeUpdatedAt", ignore = true) + @Mapping(target = "allFields", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + Metadata programEntityToMetadata(ProgramEntity programEntity); + + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "mergeLegacyShortName", ignore = true) + @Mapping(target = "allFields", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + LegacyDetails programEntityToLegacyData(ProgramEntity programEntity); + + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "mergeEmail", ignore = true) + @Mapping(target = "mergeFirstName", ignore = true) + @Mapping(target = "mergeLastName", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "allFields", ignore = true) + @Mapping(target = "mergeRole", ignore = true) + User egoUserToUser(EgoUser egoUser); + + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "mergeUser", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "allFields", ignore = true) + @Mapping(target = "user", source = "egoUser") + JoinProgramResponse egoUserToJoinProgramResponse(Integer dummy, EgoUser egoUser); + + @Mapping(target = "id", ignore = true) + @Mapping(target = "type", ignore = true) + @Mapping(target = "status", ignore = true) + @Mapping(target = "email", source = "userEmail") + EgoUser joinProgramInviteToEgoUser(JoinProgramInviteEntity invite); + + default JoinProgramResponse egoUserToJoinProgramResponse(EgoUser egoUser) { + return egoUserToJoinProgramResponse(0, egoUser); + } + + default UserRoleValue boxUserValue(@NonNull UserRole role) { + return UserRoleValue.newBuilder().setValue(role).build(); + } + + default ListProgramsResponse programEntitiesToListProgramsResponse( + Collection programEntities) { + return programEntitiesToListProgramsResponse(0, programEntities); + } + + default ListCancersResponse cancerEntitiesToListCancersResponse( + Collection cancerEntities) { + return ListCancersResponse.newBuilder() + .addAllCancers(cancerEntities.stream().map(this::cancerEntityToCancer).collect(toList())) + .build(); + } + + default ListPrimarySitesResponse primarySiteEntitiesToListPrimarySitesResponse( + Collection primarySiteEntities) { + return ListPrimarySitesResponse.newBuilder() + .addAllPrimarySites( + primarySiteEntities.stream() + .map(this::primarySiteEntityToPrimarySite) + .collect(toList())) + .build(); + } + + default ListCountriesResponse countryEntitiesToListCountriesResponse( + Collection countryEntities) { + return ListCountriesResponse.newBuilder() + .addAllCountries( + countryEntities.stream().map(this::countryEntityToCountry).collect(toList())) + .build(); + } + + default ListRegionsResponse regionEntitiesToListRegionsResponse( + Collection regionEntities) { + return ListRegionsResponse.newBuilder() + .addAllRegions(regionEntities.stream().map(this::regionEntityToRegion).collect(toList())) + .build(); + } + + default ListInstitutionsResponse institutionEntitiesToListInstitutionsResponse( + Collection institutionEntities) { + return ListInstitutionsResponse.newBuilder() + .addAllInstitutions( + institutionEntities.stream() + .map(this::institutionEntityToInstitution) + .collect(toList())) + .build(); + } + + default AddInstitutionsResponse institutionsToAddInstitutionsResponse( + Collection institutionEntities) { + return AddInstitutionsResponse.newBuilder() + .addAllInstitutions( + institutionEntities.stream() + .map(this::institutionEntityToInstitution) + .collect(toList())) + .build(); + } + + default InviteUserResponse inviteIdToInviteUserResponse(@NonNull UUID inviteId) { + return InviteUserResponse.newBuilder().setInviteId(StringValue.of(inviteId.toString())).build(); + } + + /** Enum Boxing Converters */ + default MembershipTypeValue boxMembershipType(MembershipType m) { + return MembershipTypeValue.newBuilder().setValue(m).build(); + } + + default MembershipType unboxMembershipTypeValue(@NonNull MembershipTypeValue v) { + return v.getValue(); + } + + default InviteStatusValue JoinProgramInviteStatusToInviteStatus( + JoinProgramInviteEntity.Status status) { + switch (status) { + case ACCEPTED: + return InviteStatusValue.newBuilder().setValue(InviteStatus.ACCEPTED).build(); + case EXPIRED: + return InviteStatusValue.newBuilder().setValue(InviteStatus.EXPIRED).build(); + case PENDING: + return InviteStatusValue.newBuilder().setValue(InviteStatus.PENDING).build(); + case INVALID: + return InviteStatusValue.newBuilder().build(); + case REVOKED: + return InviteStatusValue.newBuilder().build(); + } + return InviteStatusValue.newBuilder().build(); + } + + default InviteStatus unboxInviteStatusValue(InviteStatusValue status) { + return status.getValue(); + } + + default InviteStatusValue boxInviteStatus(InviteStatus status) { + return InviteStatusValue.newBuilder().setValue(status).build(); + } + + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "mergeEmail", ignore = true) + @Mapping(target = "mergeFirstName", ignore = true) + @Mapping(target = "mergeLastName", ignore = true) + @Mapping(target = "mergeRole", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "allFields", ignore = true) + @Mapping(target = "email", source = "userEmail") + User JoinProgramInviteToUser(JoinProgramInviteEntity invitation); + + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "mergeUser", ignore = true) + @Mapping(target = "mergeStatus", ignore = true) + @Mapping(target = "mergeAcceptedAt", ignore = true) + @Mapping(target = "mergeDacoApproved", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "allFields", ignore = true) + @Mapping(target = "user", source = "invitation") + @Mapping(target = "dacoApproved", source = "dacoApproved") + UserDetails joinProgramInviteToUserDetails( + Integer dummy, JoinProgramInviteEntity invitation, boolean dacoApproved); + + default UserDetails joinProgramInviteToUserDetails(JoinProgramInviteEntity invitation) { + return joinProgramInviteToUserDetails(0, invitation, false); + } + + default UserDetails joinProgramInviteToUserDetails( + JoinProgramInviteEntity invitation, boolean dacoApproved) { + return joinProgramInviteToUserDetails(0, invitation, dacoApproved); + } + + default UserDetails userWithOptionalJoinProgramInviteToUserDetails( + User user, Optional invite, boolean dacoApproved) { + val builder = UserDetails.newBuilder(); + builder.setUser(user).setDacoApproved(BoolValue.of((dacoApproved))); + + if (invite.isEmpty()) { + return builder.build(); + } + + val status = JoinProgramInviteStatusToInviteStatus(invite.get().getStatus()); + val builder2 = builder.setStatus(boxInviteStatus(status.getValue())); + + if (status.getValue() == InviteStatus.PENDING) { + return builder2.build(); + } + + val accepted = CommonConverter.INSTANCE.localDateTimeToTimestamp(invite.get().getAcceptedAt()); + if (accepted != null) { + return builder2.setAcceptedAt(accepted).build(); + } + return builder2.build(); + } + + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "removeUserDetails", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "allFields", ignore = true) + @Mapping(target = "userDetailsOrBuilderList", ignore = true) + @Mapping(target = "userDetailsBuilderList", ignore = true) + @Mapping(target = "userDetailsList", source = "invitations") + ListUsersResponse invitationsToListUsersResponse( + Integer dummy, Collection invitations); + + default ListUsersResponse invitationsToListUsersResponse( + Collection invitations) { + return invitationsToListUsersResponse(0, invitations); + } + + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "mergeId", ignore = true) + @Mapping(target = "mergeCreatedAt", ignore = true) + @Mapping(target = "mergeExpiresAt", ignore = true) + @Mapping(target = "mergeAcceptedAt", ignore = true) + @Mapping(target = "mergeProgram", ignore = true) + @Mapping(target = "mergeEmailSent", ignore = true) + @Mapping(target = "statusValue", ignore = true) + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "allFields", ignore = true) + @Mapping(target = "user", ignore = true) + @Mapping(target = "mergeUser", ignore = true) + JoinProgramInvite joinProgramInviteEntityToJoinProgramInvite(JoinProgramInviteEntity entity); + + @AfterMapping + default void setUser( + @NonNull JoinProgramInviteEntity entity, + @NonNull @MappingTarget JoinProgramInvite.Builder joinProgramInvite) { + val userRole = UserRoleValue.newBuilder().setValue(entity.getRole()); + val user = + User.newBuilder() + .setEmail(StringValue.of(entity.getUserEmail())) + .setFirstName(StringValue.of(entity.getFirstName())) + .setLastName(StringValue.of(entity.getLastName())) + .setRole(userRole) + .build(); + joinProgramInvite.setUser(user); + } +} diff --git a/src/main/java/org/icgc/argo/program_service/exception/ExceptionHandlers.java b/src/main/java/org/icgc/argo/program_service/exception/ExceptionHandlers.java index 298212b5..b6ad80be 100644 --- a/src/main/java/org/icgc/argo/program_service/exception/ExceptionHandlers.java +++ b/src/main/java/org/icgc/argo/program_service/exception/ExceptionHandlers.java @@ -1,29 +1,26 @@ package org.icgc.argo.program_service.exception; +import static org.springframework.http.HttpStatus.*; + +import java.util.Date; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import lombok.val; import org.icgc.argo.program_service.model.exceptions.ForbiddenException; -import org.icgc.argo.program_service.model.exceptions.NotFoundException; import org.icgc.argo.program_service.model.exceptions.UnauthorizedException; import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.MissingRequestHeaderException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; -import javax.servlet.http.HttpServletRequest; -import java.util.Date; -import java.util.Map; - -import static org.springframework.http.HttpStatus.*; - @Slf4j @ControllerAdvice public class ExceptionHandlers { @ExceptionHandler(ForbiddenException.class) public ResponseEntity handleForbiddenException( - HttpServletRequest req, ForbiddenException ex) { + HttpServletRequest req, ForbiddenException ex) { val message = ex.getMessage(); log.error(message); return new ResponseEntity( @@ -33,7 +30,7 @@ public ResponseEntity handleForbiddenException( "path", req.getServletPath(), "error", FORBIDDEN.getReasonPhrase()), new HttpHeaders(), - FORBIDDEN); + FORBIDDEN); } @ExceptionHandler(UnauthorizedException.class) diff --git a/src/main/java/org/icgc/argo/program_service/model/dto/ProgramsDTO.java b/src/main/java/org/icgc/argo/program_service/model/dto/ProgramsDTO.java index 2ab5d5dd..69a86984 100644 --- a/src/main/java/org/icgc/argo/program_service/model/dto/ProgramsDTO.java +++ b/src/main/java/org/icgc/argo/program_service/model/dto/ProgramsDTO.java @@ -1,13 +1,10 @@ package org.icgc.argo.program_service.model.dto; +import java.util.List; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; -import org.icgc.argo.program_service.proto.MembershipTypeValue; - -import java.util.List; -import java.util.Set; @Data @NoArgsConstructor @@ -32,5 +29,4 @@ public class ProgramsDTO { private List cancerTypes; private List primarySites; - } diff --git a/src/main/java/org/icgc/argo/program_service/model/entity/DataCenterEntity.java b/src/main/java/org/icgc/argo/program_service/model/entity/DataCenterEntity.java new file mode 100644 index 00000000..65826da6 --- /dev/null +++ b/src/main/java/org/icgc/argo/program_service/model/entity/DataCenterEntity.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2020 The Ontario Institute for Cancer Research. All rights reserved + * + * This program and the accompanying materials are made available under the terms of the GNU Affero General Public License v3.0. + * You should have received a copy of the GNU Affero General Public License along with + * this program. If not, see . + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + */ + +package org.icgc.argo.program_service.model.entity; + +import static org.icgc.argo.program_service.utils.CollectionUtils.mapToList; + +import java.util.List; +import java.util.Set; +import java.util.TreeSet; +import java.util.UUID; +import javax.persistence.*; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; +import lombok.experimental.FieldNameConstants; +import org.hibernate.annotations.GenericGenerator; +import org.hibernate.validator.constraints.URL; +import org.icgc.argo.program_service.model.enums.SqlFields; +import org.icgc.argo.program_service.model.enums.Tables; + +@Entity +@Table(name = Tables.DATA_CENTER) +@Data +@Accessors(chain = true) +@FieldNameConstants +public class DataCenterEntity implements NameableEntity { + + @Id + @ToString.Exclude + @EqualsAndHashCode.Exclude + @Column(name = SqlFields.ID) + @GenericGenerator(name = "datacenter_uuid", strategy = "org.hibernate.id.UUIDGenerator") + @GeneratedValue(generator = "datacenter_uuid") + private UUID id; + + @NotNull + @Column(name = SqlFields.SHORTNAME) + private String shortName; + + @NotNull + @Column(name = SqlFields.NAME) + private String name; + + @NotNull + @Column(name = SqlFields.ORGANIZATION) + private String organization; + + @NotNull + @Email + @Column(name = SqlFields.EMAIL) + private String email; + + @NotNull + @URL + @Column(name = SqlFields.UI_URL) + private String uiUrl; + + @NotNull + @URL + @Column(name = SqlFields.GATEWAY_URL) + private String gatewayUrl; + + @NotNull + @Column(name = SqlFields.ANALYSIS_SONG_CODE) + private String analysisSongCode; + + @NotNull + @URL + @Column(name = SqlFields.ANALYSIS_SONG_URL) + private String analysisSongUrl; + + @NotNull + @URL + @Column(name = SqlFields.ANALYSIS_SCORE_URL) + private String analysisScoreUrl; + + @NotNull + @Column(name = SqlFields.SUBMISSION_SONG_CODE) + private String submissionSongCode; + + @NotNull + @URL + @Column(name = SqlFields.SUBMISSION_SONG_URL) + private String submissionSongUrl; + + @NotNull + @URL + @Column(name = SqlFields.SUBMISSION_SCORE_URL) + private String submissionScoreUrl; + + @ToString.Exclude + @EqualsAndHashCode.Exclude + @OneToMany( + mappedBy = ProgramEntity.Fields.dataCenterId, + cascade = CascadeType.ALL, + fetch = FetchType.LAZY, + orphanRemoval = true) + private Set programEntites = new TreeSet<>(); + + public List listPrograms() { + return mapToList(getProgramEntites(), i -> i.getName()); + } +} diff --git a/src/main/java/org/icgc/argo/program_service/model/entity/ProgramEntity.java b/src/main/java/org/icgc/argo/program_service/model/entity/ProgramEntity.java index 3b3577d6..13cc483f 100644 --- a/src/main/java/org/icgc/argo/program_service/model/entity/ProgramEntity.java +++ b/src/main/java/org/icgc/argo/program_service/model/entity/ProgramEntity.java @@ -1,184 +1,187 @@ -/* - * Copyright (c) 2020 The Ontario Institute for Cancer Research. All rights reserved - * - * This program and the accompanying materials are made available under the terms of the GNU Affero General Public License v3.0. - * You should have received a copy of the GNU Affero General Public License along with - * this program. If not, see . - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - */ - -package org.icgc.argo.program_service.model.entity; - -import static org.icgc.argo.program_service.utils.CollectionUtils.mapToList; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; -import java.util.UUID; -import javax.persistence.*; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.PastOrPresent; -import javax.validation.constraints.PositiveOrZero; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import lombok.experimental.Accessors; -import lombok.experimental.FieldNameConstants; -import org.hibernate.annotations.GenericGenerator; -import org.hibernate.validator.constraints.URL; -import org.icgc.argo.program_service.model.enums.SqlFields; -import org.icgc.argo.program_service.model.enums.Tables; -import org.icgc.argo.program_service.model.join.*; -import org.icgc.argo.program_service.proto.MembershipType; -import org.icgc.argo.program_service.validation.ProgramShortName; - -@Entity -@Table(name = Tables.PROGRAM) -@Data -@Accessors(chain = true) -@FieldNameConstants -public class ProgramEntity implements NameableEntity { - - @Id - @ToString.Exclude - @EqualsAndHashCode.Exclude - @Column(name = SqlFields.ID) - @GenericGenerator(name = "program_uuid", strategy = "org.hibernate.id.UUIDGenerator") - @GeneratedValue(generator = "program_uuid") - private UUID id; - - @NotNull - @Column(name = SqlFields.SHORTNAME) - @ProgramShortName - private String shortName; - - @NotNull - @Column(name = SqlFields.NAME) - private String name; - - @NotNull - @Enumerated(EnumType.STRING) - @Column(name = SqlFields.MEMBERSHIPTYPE) - private MembershipType membershipType; - - @NotNull - @PositiveOrZero - @Column(name = SqlFields.COMMITMENTDONORS) - private Integer commitmentDonors; - - @NotNull - @PositiveOrZero - @Column(name = SqlFields.SUBMITTEDDONORS) - private Integer submittedDonors; - - @NotNull - @PositiveOrZero - @Column(name = SqlFields.GENOMICDONORS) - private Integer genomicDonors; - - @NotNull - @URL - @Column(name = SqlFields.WEBSITE) - private String website; - - @NotNull - @EqualsAndHashCode.Exclude - @PastOrPresent - @Column(name = SqlFields.CREATEDAT) - private LocalDateTime createdAt; - - @NotNull - @EqualsAndHashCode.Exclude - @PastOrPresent - @Column(name = SqlFields.UPDATEDAT) - private LocalDateTime updatedAt; - - @Column(name = SqlFields.DESCRIPTION) - private String description; - - @Column(name = SqlFields.IS_ACTIVE) - private Boolean active; - - @Column(name = SqlFields.LEGACY_SHORTNAME) - private String legacyShortName; - - @NotNull - @ToString.Exclude - @EqualsAndHashCode.Exclude - @OneToMany( - mappedBy = ProgramInstitution.Fields.program, - cascade = CascadeType.ALL, - fetch = FetchType.LAZY, - orphanRemoval = true) - private Set programInstitutions = new TreeSet<>(); - - @NotNull - @ToString.Exclude - @EqualsAndHashCode.Exclude - @OneToMany( - mappedBy = ProgramCountry.Fields.program, - cascade = CascadeType.ALL, - fetch = FetchType.LAZY, - orphanRemoval = true) - private Set programCountries = new TreeSet<>(); - - @NotNull - @ToString.Exclude - @EqualsAndHashCode.Exclude - @OneToMany( - mappedBy = ProgramRegion.Fields.program, - cascade = CascadeType.ALL, - fetch = FetchType.LAZY, - orphanRemoval = true) - private Set programRegions = new TreeSet<>(); - - @ToString.Exclude - @EqualsAndHashCode.Exclude - @OneToMany( - mappedBy = ProgramCancer.Fields.program, - cascade = CascadeType.ALL, - fetch = FetchType.LAZY, - orphanRemoval = true) - private Set<@NotNull ProgramCancer> programCancers = new TreeSet<>(); - - @ToString.Exclude - @EqualsAndHashCode.Exclude - @OneToMany( - mappedBy = ProgramPrimarySite.Fields.program, - cascade = CascadeType.ALL, - fetch = FetchType.LAZY, - orphanRemoval = true) - private Set<@NotNull ProgramPrimarySite> programPrimarySites = new TreeSet<>(); - - public List listCancerTypes() { - return mapToList(getProgramCancers(), c -> c.getCancer().getName()); - } - - public List listPrimarySites() { - return mapToList(getProgramPrimarySites(), p -> p.getPrimarySite().getName()); - } - - public List listInstitutions() { - return mapToList(getProgramInstitutions(), i -> i.getInstitution().getName()); - } - - public List listCountries() { - return mapToList(getProgramCountries(), c -> c.getCountry().getName()); - } - - public List listRegions() { - return mapToList(getProgramRegions(), r -> r.getRegion().getName()); - } -} +/* + * Copyright (c) 2020 The Ontario Institute for Cancer Research. All rights reserved + * + * This program and the accompanying materials are made available under the terms of the GNU Affero General Public License v3.0. + * You should have received a copy of the GNU Affero General Public License along with + * this program. If not, see . + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + */ + +package org.icgc.argo.program_service.model.entity; + +import static org.icgc.argo.program_service.utils.CollectionUtils.mapToList; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; +import java.util.UUID; +import javax.persistence.*; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.PastOrPresent; +import javax.validation.constraints.PositiveOrZero; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; +import lombok.experimental.FieldNameConstants; +import org.hibernate.annotations.GenericGenerator; +import org.hibernate.validator.constraints.URL; +import org.icgc.argo.program_service.model.enums.SqlFields; +import org.icgc.argo.program_service.model.enums.Tables; +import org.icgc.argo.program_service.model.join.*; +import org.icgc.argo.program_service.proto.MembershipType; +import org.icgc.argo.program_service.validation.ProgramShortName; + +@Entity +@Table(name = Tables.PROGRAM) +@Data +@Accessors(chain = true) +@FieldNameConstants +public class ProgramEntity implements NameableEntity { + + @Id + @ToString.Exclude + @EqualsAndHashCode.Exclude + @Column(name = SqlFields.ID) + @GenericGenerator(name = "program_uuid", strategy = "org.hibernate.id.UUIDGenerator") + @GeneratedValue(generator = "program_uuid") + private UUID id; + + @NotNull + @Column(name = SqlFields.SHORTNAME) + @ProgramShortName + private String shortName; + + @NotNull + @Column(name = SqlFields.NAME) + private String name; + + @Column(name = SqlFields.DATA_CENTER_ID) + private UUID dataCenterId; + + @NotNull + @Enumerated(EnumType.STRING) + @Column(name = SqlFields.MEMBERSHIPTYPE) + private MembershipType membershipType; + + @NotNull + @PositiveOrZero + @Column(name = SqlFields.COMMITMENTDONORS) + private Integer commitmentDonors; + + @NotNull + @PositiveOrZero + @Column(name = SqlFields.SUBMITTEDDONORS) + private Integer submittedDonors; + + @NotNull + @PositiveOrZero + @Column(name = SqlFields.GENOMICDONORS) + private Integer genomicDonors; + + @NotNull + @URL + @Column(name = SqlFields.WEBSITE) + private String website; + + @NotNull + @EqualsAndHashCode.Exclude + @PastOrPresent + @Column(name = SqlFields.CREATEDAT) + private LocalDateTime createdAt; + + @NotNull + @EqualsAndHashCode.Exclude + @PastOrPresent + @Column(name = SqlFields.UPDATEDAT) + private LocalDateTime updatedAt; + + @Column(name = SqlFields.DESCRIPTION) + private String description; + + @Column(name = SqlFields.IS_ACTIVE) + private Boolean active; + + @Column(name = SqlFields.LEGACY_SHORTNAME) + private String legacyShortName; + + @NotNull + @ToString.Exclude + @EqualsAndHashCode.Exclude + @OneToMany( + mappedBy = ProgramInstitution.Fields.program, + cascade = CascadeType.ALL, + fetch = FetchType.LAZY, + orphanRemoval = true) + private Set programInstitutions = new TreeSet<>(); + + @NotNull + @ToString.Exclude + @EqualsAndHashCode.Exclude + @OneToMany( + mappedBy = ProgramCountry.Fields.program, + cascade = CascadeType.ALL, + fetch = FetchType.LAZY, + orphanRemoval = true) + private Set programCountries = new TreeSet<>(); + + @NotNull + @ToString.Exclude + @EqualsAndHashCode.Exclude + @OneToMany( + mappedBy = ProgramRegion.Fields.program, + cascade = CascadeType.ALL, + fetch = FetchType.LAZY, + orphanRemoval = true) + private Set programRegions = new TreeSet<>(); + + @ToString.Exclude + @EqualsAndHashCode.Exclude + @OneToMany( + mappedBy = ProgramCancer.Fields.program, + cascade = CascadeType.ALL, + fetch = FetchType.LAZY, + orphanRemoval = true) + private Set<@NotNull ProgramCancer> programCancers = new TreeSet<>(); + + @ToString.Exclude + @EqualsAndHashCode.Exclude + @OneToMany( + mappedBy = ProgramPrimarySite.Fields.program, + cascade = CascadeType.ALL, + fetch = FetchType.LAZY, + orphanRemoval = true) + private Set<@NotNull ProgramPrimarySite> programPrimarySites = new TreeSet<>(); + + public List listCancerTypes() { + return mapToList(getProgramCancers(), c -> c.getCancer().getName()); + } + + public List listPrimarySites() { + return mapToList(getProgramPrimarySites(), p -> p.getPrimarySite().getName()); + } + + public List listInstitutions() { + return mapToList(getProgramInstitutions(), i -> i.getInstitution().getName()); + } + + public List listCountries() { + return mapToList(getProgramCountries(), c -> c.getCountry().getName()); + } + + public List listRegions() { + return mapToList(getProgramRegions(), r -> r.getRegion().getName()); + } +} diff --git a/src/main/java/org/icgc/argo/program_service/model/enums/SqlFields.java b/src/main/java/org/icgc/argo/program_service/model/enums/SqlFields.java index 644162a4..26d69173 100644 --- a/src/main/java/org/icgc/argo/program_service/model/enums/SqlFields.java +++ b/src/main/java/org/icgc/argo/program_service/model/enums/SqlFields.java @@ -1,48 +1,59 @@ -/* - * Copyright (c) 2020 The Ontario Institute for Cancer Research. All rights reserved - * - * This program and the accompanying materials are made available under the terms of the GNU Affero General Public License v3.0. - * You should have received a copy of the GNU Affero General Public License along with - * this program. If not, see . - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - */ - -package org.icgc.argo.program_service.model.enums; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class SqlFields { - - public static final String ID = "id"; - public static final String SHORTNAME = "short_name"; - public static final String NAME = "name"; - public static final String DESCRIPTION = "description"; - public static final String MEMBERSHIPTYPE = "membership_type"; - public static final String COMMITMENTDONORS = "commitment_donors"; - public static final String SUBMITTEDDONORS = "submitted_donors"; - public static final String GENOMICDONORS = "genomic_donors"; - public static final String WEBSITE = "website"; - public static final String CREATEDAT = "created_at"; - public static final String UPDATEDAT = "updated_at"; - public static final String PROGRAMID_JOIN = "program_id"; - public static final String CANCERID_JOIN = "cancer_id"; - public static final String SITEID_JOIN = "primary_site_id"; - public static final String COUNTRYID_JOIN = "country_id"; - public static final String INSTITUTIONID_JOIN = "institution_id"; - public static final String REGIONID_JOIN = "region_id"; - public static final String LEGACY_SHORTNAME = "legacy_short_name"; - public static final String IS_ACTIVE = "active"; -} +/* + * Copyright (c) 2020 The Ontario Institute for Cancer Research. All rights reserved + * + * This program and the accompanying materials are made available under the terms of the GNU Affero General Public License v3.0. + * You should have received a copy of the GNU Affero General Public License along with + * this program. If not, see . + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + */ + +package org.icgc.argo.program_service.model.enums; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class SqlFields { + + public static final String ID = "id"; + public static final String SHORTNAME = "short_name"; + public static final String NAME = "name"; + public static final String DESCRIPTION = "description"; + public static final String MEMBERSHIPTYPE = "membership_type"; + public static final String COMMITMENTDONORS = "commitment_donors"; + public static final String SUBMITTEDDONORS = "submitted_donors"; + public static final String GENOMICDONORS = "genomic_donors"; + public static final String WEBSITE = "website"; + public static final String CREATEDAT = "created_at"; + public static final String UPDATEDAT = "updated_at"; + public static final String PROGRAMID_JOIN = "program_id"; + public static final String CANCERID_JOIN = "cancer_id"; + public static final String SITEID_JOIN = "primary_site_id"; + public static final String COUNTRYID_JOIN = "country_id"; + public static final String INSTITUTIONID_JOIN = "institution_id"; + public static final String REGIONID_JOIN = "region_id"; + public static final String LEGACY_SHORTNAME = "legacy_short_name"; + public static final String IS_ACTIVE = "active"; + public static final String ORGANIZATION = "organization"; + public static final String EMAIL = "email"; + public static final String UI_URL = "ui_url"; + public static final String GATEWAY_URL = "gateway_url"; + public static final String ANALYSIS_SONG_CODE = "analysis_song_code"; + public static final String ANALYSIS_SONG_URL = "analysis_song_url"; + public static final String ANALYSIS_SCORE_URL = "analysis_score_url"; + public static final String SUBMISSION_SONG_CODE = "submission_song_code"; + public static final String SUBMISSION_SONG_URL = "submission_song_url"; + public static final String SUBMISSION_SCORE_URL = "submission_score_url"; + public static final String DATA_CENTER_ID = "data_center_id"; +} diff --git a/src/main/java/org/icgc/argo/program_service/model/enums/Tables.java b/src/main/java/org/icgc/argo/program_service/model/enums/Tables.java index a867d53d..c51d9f5e 100644 --- a/src/main/java/org/icgc/argo/program_service/model/enums/Tables.java +++ b/src/main/java/org/icgc/argo/program_service/model/enums/Tables.java @@ -1,43 +1,44 @@ -/* - * Copyright (c) 2020 The Ontario Institute for Cancer Research. All rights reserved - * - * This program and the accompanying materials are made available under the terms of the GNU Affero General Public License v3.0. - * You should have received a copy of the GNU Affero General Public License along with - * this program. If not, see . - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - */ - -package org.icgc.argo.program_service.model.enums; - -import static lombok.AccessLevel.PRIVATE; - -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = PRIVATE) -public class Tables { - - public static final String PROGRAM = "program"; - public static final String CANCER = "cancer"; - public static final String SITE = "primary_site"; - public static final String COUNTRY = "country"; - public static final String INSTITUTION = "institution"; - public static final String REGION = "region"; - public static final String PROGRAM_CANCER = "program_cancer"; - public static final String PROGRAM_PRIMARY_SITE = "program_primary_site"; - public static final String PROGRAM_EGO_GROUP = "program_ego_group"; - public static final String JOIN_PROGRAM_INVITE = "join_program_invite"; - public static final String PROGRAM_COUNTRY = "program_country"; - public static final String PROGRAM_INSTITUTION = "program_institution"; - public static final String PROGRAM_REGION = "program_region"; -} +/* + * Copyright (c) 2020 The Ontario Institute for Cancer Research. All rights reserved + * + * This program and the accompanying materials are made available under the terms of the GNU Affero General Public License v3.0. + * You should have received a copy of the GNU Affero General Public License along with + * this program. If not, see . + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + */ + +package org.icgc.argo.program_service.model.enums; + +import static lombok.AccessLevel.PRIVATE; + +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = PRIVATE) +public class Tables { + + public static final String PROGRAM = "program"; + public static final String CANCER = "cancer"; + public static final String SITE = "primary_site"; + public static final String COUNTRY = "country"; + public static final String INSTITUTION = "institution"; + public static final String REGION = "region"; + public static final String PROGRAM_CANCER = "program_cancer"; + public static final String PROGRAM_PRIMARY_SITE = "program_primary_site"; + public static final String PROGRAM_EGO_GROUP = "program_ego_group"; + public static final String JOIN_PROGRAM_INVITE = "join_program_invite"; + public static final String PROGRAM_COUNTRY = "program_country"; + public static final String PROGRAM_INSTITUTION = "program_institution"; + public static final String PROGRAM_REGION = "program_region"; + public static final String DATA_CENTER = "data_center"; +} diff --git a/src/main/java/org/icgc/argo/program_service/model/exceptions/ForbiddenException.java b/src/main/java/org/icgc/argo/program_service/model/exceptions/ForbiddenException.java index f4fee7ed..7e3c0c9f 100644 --- a/src/main/java/org/icgc/argo/program_service/model/exceptions/ForbiddenException.java +++ b/src/main/java/org/icgc/argo/program_service/model/exceptions/ForbiddenException.java @@ -17,11 +17,11 @@ package org.icgc.argo.program_service.model.exceptions; +import static org.springframework.http.HttpStatus.FORBIDDEN; + import lombok.NonNull; import org.springframework.web.bind.annotation.ResponseStatus; -import static org.springframework.http.HttpStatus.FORBIDDEN; - @ResponseStatus(FORBIDDEN) public class ForbiddenException extends RuntimeException { diff --git a/src/main/java/org/icgc/argo/program_service/model/exceptions/UnauthorizedException.java b/src/main/java/org/icgc/argo/program_service/model/exceptions/UnauthorizedException.java index 971cc69e..96afa776 100644 --- a/src/main/java/org/icgc/argo/program_service/model/exceptions/UnauthorizedException.java +++ b/src/main/java/org/icgc/argo/program_service/model/exceptions/UnauthorizedException.java @@ -17,11 +17,11 @@ package org.icgc.argo.program_service.model.exceptions; +import static org.springframework.http.HttpStatus.UNAUTHORIZED; + import lombok.NonNull; import org.springframework.web.bind.annotation.ResponseStatus; -import static org.springframework.http.HttpStatus.UNAUTHORIZED; - @ResponseStatus(UNAUTHORIZED) public class UnauthorizedException extends RuntimeException { diff --git a/src/main/java/org/icgc/argo/program_service/swagger/SwaggerConfig.java b/src/main/java/org/icgc/argo/program_service/swagger/SwaggerConfig.java index 46662a06..96ea42c3 100644 --- a/src/main/java/org/icgc/argo/program_service/swagger/SwaggerConfig.java +++ b/src/main/java/org/icgc/argo/program_service/swagger/SwaggerConfig.java @@ -1,16 +1,14 @@ package org.icgc.argo.program_service.swagger; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.info.License; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; import org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties; import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType; @@ -28,21 +26,22 @@ public class SwaggerConfig { private SecurityScheme createAPIKeyScheme() { - return new SecurityScheme().type(SecurityScheme.Type.HTTP) - .bearerFormat("JWT") - .scheme("bearer"); + return new SecurityScheme().type(SecurityScheme.Type.HTTP).bearerFormat("JWT").scheme("bearer"); } @Bean public OpenAPI openAPI() { - return new OpenAPI().addSecurityItem(new SecurityRequirement(). - addList("Bearer Authentication")) - .components(new Components().addSecuritySchemes - ("Bearer Authentication", createAPIKeyScheme())) - .info(new Info().title("Program Service REST API") - .description("Program API for the central point to create and manage programs and maintain their metadata.") - .version("1.0") - .license(new License().name("AGPL-3.0 license"))); + return new OpenAPI() + .addSecurityItem(new SecurityRequirement().addList("Bearer Authentication")) + .components( + new Components().addSecuritySchemes("Bearer Authentication", createAPIKeyScheme())) + .info( + new Info() + .title("Program Service REST API") + .description( + "Program API for the central point to create and manage programs and maintain their metadata.") + .version("1.0") + .license(new License().name("AGPL-3.0 license"))); } /*private ApiInfo apiInfo() { diff --git a/src/main/proto/ProgramService.proto b/src/main/proto/ProgramService.proto index dfe6180e..df4618cd 100644 --- a/src/main/proto/ProgramService.proto +++ b/src/main/proto/ProgramService.proto @@ -1,306 +1,307 @@ -// Copyright (c) 2019. Ontario Institute for Cancer Research -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -syntax = "proto3"; - -package program_service; - -import "google/protobuf/wrappers.proto"; -import "google/protobuf/timestamp.proto"; -import "google/protobuf/empty.proto"; - -option java_multiple_files = true; -option java_package = "org.icgc.argo.program_service.proto"; -option java_outer_classname = "ProgramServiceProto"; -option objc_class_prefix = "PSP"; - -service ProgramService { - - rpc CreateProgram(CreateProgramRequest) returns (CreateProgramResponse); - rpc RemoveProgram(RemoveProgramRequest) returns (google.protobuf.Empty); - rpc UpdateProgram(UpdateProgramRequest) returns (UpdateProgramResponse); - rpc ListPrograms(google.protobuf.Empty) returns (ListProgramsResponse); - rpc GetProgram(GetProgramRequest) returns (GetProgramResponse); - rpc ActivateProgram(ActivateProgramRequest) returns (GetProgramResponse); - - rpc InviteUser(InviteUserRequest) returns (InviteUserResponse); - rpc GetJoinProgramInvite(GetJoinProgramInviteRequest) returns (GetJoinProgramInviteResponse); - rpc JoinProgram(JoinProgramRequest) returns (JoinProgramResponse); - - rpc RemoveUser(RemoveUserRequest) returns (RemoveUserResponse); - rpc ListUsers(ListUsersRequest) returns (ListUsersResponse); - rpc UpdateUser(UpdateUserRequest) returns (google.protobuf.Empty); - - rpc ListCancers (google.protobuf.Empty) returns (ListCancersResponse); - rpc ListPrimarySites (google.protobuf.Empty) returns (ListPrimarySitesResponse); - rpc ListCountries (google.protobuf.Empty) returns (ListCountriesResponse); - rpc ListRegions (google.protobuf.Empty) returns (ListRegionsResponse); - rpc ListInstitutions (google.protobuf.Empty) returns (ListInstitutionsResponse); - rpc AddInstitutions (AddInstitutionsRequest) returns (AddInstitutionsResponse); - -} - -message Program { - google.protobuf.StringValue short_name = 1; - google.protobuf.StringValue description = 2; - google.protobuf.StringValue name = 3; - MembershipTypeValue membership_type = 4; - google.protobuf.Int32Value commitment_donors = 5; - google.protobuf.Int32Value submitted_donors = 6; - google.protobuf.Int32Value genomic_donors = 7; - google.protobuf.StringValue website = 8; - repeated string cancer_types = 12; - repeated string primary_sites = 13; - repeated string institutions = 14; - repeated string countries = 15; - repeated string regions = 16; -} - -message Cancer { - google.protobuf.StringValue id = 1; - google.protobuf.StringValue name = 2; -} - -message PrimarySite { - google.protobuf.StringValue id = 1; - google.protobuf.StringValue name = 2; -} - -message Country { - google.protobuf.StringValue id = 1; - google.protobuf.StringValue name = 2; -} - -message Region { - google.protobuf.StringValue id = 1; - google.protobuf.StringValue name = 2; -} - -message Institution { - google.protobuf.StringValue id = 1; - google.protobuf.StringValue name = 2; -} - -enum MembershipType { - FULL = 0; - ASSOCIATE = 1; -} - -message MembershipTypeValue { - MembershipType value = 1; -} - -enum UserRole { - COLLABORATOR = 0; - ADMIN = 1; - CURATOR = 2; - SUBMITTER = 3; - BANNED = 4; -} - -message UserRoleValue { - UserRole value = 1; -} - -message User { - google.protobuf.StringValue email = 1; - google.protobuf.StringValue first_name = 2; - google.protobuf.StringValue last_name = 3; - UserRoleValue role = 4; -} - -enum InviteStatus { - REVOKED = 0; - PENDING = 1; - ACCEPTED = 2; - EXPIRED = 3; -} - -message InviteStatusValue { - InviteStatus value = 1; -} - -message UserDetails { - User user = 1; - InviteStatusValue status = 2; - google.protobuf.Timestamp accepted_at = 3; - google.protobuf.BoolValue daco_approved = 4; -} - -message LegacyDetails { - google.protobuf.StringValue legacy_short_name = 1; -} - -message CreateProgramRequest { - Program program = 1; - repeated User admins = 3; -} - -message CreateProgramResponse { - google.protobuf.Timestamp created_at = 1; -} - -message UpdateProgramRequest { - Program program = 1; -} - -message UpdateProgramResponse { - google.protobuf.Timestamp updated_at = 1; -} - -message ProgramDetails { - Program program = 1; - Metadata metadata = 2; - LegacyDetails legacy = 3; -} - -message Metadata { - google.protobuf.Timestamp created_at = 1; - google.protobuf.Timestamp updated_at = 2; -} - -message GetProgramRequest { - google.protobuf.StringValue short_name = 1; -} - -message GetProgramResponse { - ProgramDetails program = 1; -} - -message ActivateProgramRequest { - google.protobuf.StringValue original_short_name = 1; - google.protobuf.StringValue updated_short_name = 2; - repeated User admins = 3; -} - -message ListProgramsResponse { - repeated ProgramDetails programs = 1; -} - -message RemoveUserRequest { - google.protobuf.StringValue user_email = 1; - google.protobuf.StringValue program_short_name = 2; -} - -message RemoveUserResponse { - google.protobuf.StringValue message = 1; -} - -message ListUsersRequest { - google.protobuf.StringValue program_short_name = 1; -} - -message ListUsersResponse { - repeated UserDetails userDetails = 1; -} - -message UpdateUserRequest { - google.protobuf.StringValue user_email= 1; - UserRoleValue role = 2; - google.protobuf.StringValue short_name = 3; -} - -message InviteUserRequest { - google.protobuf.StringValue program_short_name = 1; - google.protobuf.StringValue first_name = 2; - google.protobuf.StringValue last_name = 3; - google.protobuf.StringValue email = 4; - - // Role of the user - UserRoleValue role = 5; -} - -message InviteUserResponse { - // The invite id of the invitation which is - // sent to the user by email - google.protobuf.StringValue invite_id = 1; -} - -message JoinProgramRequest { - // The invitation id which is received by the user from email - google.protobuf.StringValue join_program_invitation_id = 1; - - // The institute where the user belong - google.protobuf.StringValue institute = 2; - - // First name of the affiliate principal investigator - google.protobuf.StringValue affiliate_pi_first_name = 3; - - // last name name of the affiliate principal investigator - google.protobuf.StringValue affiliate_pi_last_name = 4; - - // The department of the user - google.protobuf.StringValue department = 5; -} - -message Invitation { - google.protobuf.StringValue id = 1; -} - -message JoinProgramResponse { - User user = 1; -} - -message RemoveProgramRequest { - google.protobuf.StringValue program_short_name = 1; -} - -message ListCancersResponse { - repeated Cancer cancers = 1; -} - -message ListPrimarySitesResponse { - repeated PrimarySite primary_sites = 1; -} - -message ListCountriesResponse { - repeated Country countries = 1; -} - -message ListRegionsResponse { - repeated Region regions = 1; -} - -message ListInstitutionsResponse { - repeated Institution institutions = 1; -} - -message AddInstitutionsRequest { - repeated google.protobuf.StringValue names = 1; -} - -message AddInstitutionsResponse { - repeated Institution institutions = 1; -} - - -message GetJoinProgramInviteRequest { - google.protobuf.StringValue invite_id = 1; -} - -message JoinProgramInvite { - google.protobuf.StringValue id = 1; - google.protobuf.Timestamp created_at = 2; - google.protobuf.Timestamp expires_at = 3; - google.protobuf.Timestamp accepted_at = 4; - Program program = 5; - User user = 6; - google.protobuf.BoolValue email_sent = 7; - InviteStatus status = 8; -} - -message GetJoinProgramInviteResponse { - JoinProgramInvite invitation = 1; -} +// Copyright (c) 2019. Ontario Institute for Cancer Research +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +syntax = "proto3"; + +package program_service; + +import "google/protobuf/wrappers.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/empty.proto"; + +option java_multiple_files = true; +option java_package = "org.icgc.argo.program_service.proto"; +option java_outer_classname = "ProgramServiceProto"; +option objc_class_prefix = "PSP"; + +service ProgramService { + + rpc CreateProgram(CreateProgramRequest) returns (CreateProgramResponse); + rpc RemoveProgram(RemoveProgramRequest) returns (google.protobuf.Empty); + rpc UpdateProgram(UpdateProgramRequest) returns (UpdateProgramResponse); + rpc ListPrograms(google.protobuf.Empty) returns (ListProgramsResponse); + rpc GetProgram(GetProgramRequest) returns (GetProgramResponse); + rpc ActivateProgram(ActivateProgramRequest) returns (GetProgramResponse); + + rpc InviteUser(InviteUserRequest) returns (InviteUserResponse); + rpc GetJoinProgramInvite(GetJoinProgramInviteRequest) returns (GetJoinProgramInviteResponse); + rpc JoinProgram(JoinProgramRequest) returns (JoinProgramResponse); + + rpc RemoveUser(RemoveUserRequest) returns (RemoveUserResponse); + rpc ListUsers(ListUsersRequest) returns (ListUsersResponse); + rpc UpdateUser(UpdateUserRequest) returns (google.protobuf.Empty); + + rpc ListCancers (google.protobuf.Empty) returns (ListCancersResponse); + rpc ListPrimarySites (google.protobuf.Empty) returns (ListPrimarySitesResponse); + rpc ListCountries (google.protobuf.Empty) returns (ListCountriesResponse); + rpc ListRegions (google.protobuf.Empty) returns (ListRegionsResponse); + rpc ListInstitutions (google.protobuf.Empty) returns (ListInstitutionsResponse); + rpc AddInstitutions (AddInstitutionsRequest) returns (AddInstitutionsResponse); + +} + +message Program { + google.protobuf.StringValue short_name = 1; + google.protobuf.StringValue description = 2; + google.protobuf.StringValue name = 3; + google.protobuf.StringValue data_center_id = 4; + MembershipTypeValue membership_type = 5; + google.protobuf.Int32Value commitment_donors = 6; + google.protobuf.Int32Value submitted_donors = 7; + google.protobuf.Int32Value genomic_donors = 8; + google.protobuf.StringValue website = 9; + repeated string cancer_types = 10; + repeated string primary_sites = 11; + repeated string institutions = 12; + repeated string countries = 13; + repeated string regions = 14; +} + +message Cancer { + google.protobuf.StringValue id = 1; + google.protobuf.StringValue name = 2; +} + +message PrimarySite { + google.protobuf.StringValue id = 1; + google.protobuf.StringValue name = 2; +} + +message Country { + google.protobuf.StringValue id = 1; + google.protobuf.StringValue name = 2; +} + +message Region { + google.protobuf.StringValue id = 1; + google.protobuf.StringValue name = 2; +} + +message Institution { + google.protobuf.StringValue id = 1; + google.protobuf.StringValue name = 2; +} + +enum MembershipType { + FULL = 0; + ASSOCIATE = 1; +} + +message MembershipTypeValue { + MembershipType value = 1; +} + +enum UserRole { + COLLABORATOR = 0; + ADMIN = 1; + CURATOR = 2; + SUBMITTER = 3; + BANNED = 4; +} + +message UserRoleValue { + UserRole value = 1; +} + +message User { + google.protobuf.StringValue email = 1; + google.protobuf.StringValue first_name = 2; + google.protobuf.StringValue last_name = 3; + UserRoleValue role = 4; +} + +enum InviteStatus { + REVOKED = 0; + PENDING = 1; + ACCEPTED = 2; + EXPIRED = 3; +} + +message InviteStatusValue { + InviteStatus value = 1; +} + +message UserDetails { + User user = 1; + InviteStatusValue status = 2; + google.protobuf.Timestamp accepted_at = 3; + google.protobuf.BoolValue daco_approved = 4; +} + +message LegacyDetails { + google.protobuf.StringValue legacy_short_name = 1; +} + +message CreateProgramRequest { + Program program = 1; + repeated User admins = 3; +} + +message CreateProgramResponse { + google.protobuf.Timestamp created_at = 1; +} + +message UpdateProgramRequest { + Program program = 1; +} + +message UpdateProgramResponse { + google.protobuf.Timestamp updated_at = 1; +} + +message ProgramDetails { + Program program = 1; + Metadata metadata = 2; + LegacyDetails legacy = 3; +} + +message Metadata { + google.protobuf.Timestamp created_at = 1; + google.protobuf.Timestamp updated_at = 2; +} + +message GetProgramRequest { + google.protobuf.StringValue short_name = 1; +} + +message GetProgramResponse { + ProgramDetails program = 1; +} + +message ActivateProgramRequest { + google.protobuf.StringValue original_short_name = 1; + google.protobuf.StringValue updated_short_name = 2; + repeated User admins = 3; +} + +message ListProgramsResponse { + repeated ProgramDetails programs = 1; +} + +message RemoveUserRequest { + google.protobuf.StringValue user_email = 1; + google.protobuf.StringValue program_short_name = 2; +} + +message RemoveUserResponse { + google.protobuf.StringValue message = 1; +} + +message ListUsersRequest { + google.protobuf.StringValue program_short_name = 1; +} + +message ListUsersResponse { + repeated UserDetails userDetails = 1; +} + +message UpdateUserRequest { + google.protobuf.StringValue user_email= 1; + UserRoleValue role = 2; + google.protobuf.StringValue short_name = 3; +} + +message InviteUserRequest { + google.protobuf.StringValue program_short_name = 1; + google.protobuf.StringValue first_name = 2; + google.protobuf.StringValue last_name = 3; + google.protobuf.StringValue email = 4; + + // Role of the user + UserRoleValue role = 5; +} + +message InviteUserResponse { + // The invite id of the invitation which is + // sent to the user by email + google.protobuf.StringValue invite_id = 1; +} + +message JoinProgramRequest { + // The invitation id which is received by the user from email + google.protobuf.StringValue join_program_invitation_id = 1; + + // The institute where the user belong + google.protobuf.StringValue institute = 2; + + // First name of the affiliate principal investigator + google.protobuf.StringValue affiliate_pi_first_name = 3; + + // last name name of the affiliate principal investigator + google.protobuf.StringValue affiliate_pi_last_name = 4; + + // The department of the user + google.protobuf.StringValue department = 5; +} + +message Invitation { + google.protobuf.StringValue id = 1; +} + +message JoinProgramResponse { + User user = 1; +} + +message RemoveProgramRequest { + google.protobuf.StringValue program_short_name = 1; +} + +message ListCancersResponse { + repeated Cancer cancers = 1; +} + +message ListPrimarySitesResponse { + repeated PrimarySite primary_sites = 1; +} + +message ListCountriesResponse { + repeated Country countries = 1; +} + +message ListRegionsResponse { + repeated Region regions = 1; +} + +message ListInstitutionsResponse { + repeated Institution institutions = 1; +} + +message AddInstitutionsRequest { + repeated google.protobuf.StringValue names = 1; +} + +message AddInstitutionsResponse { + repeated Institution institutions = 1; +} + + +message GetJoinProgramInviteRequest { + google.protobuf.StringValue invite_id = 1; +} + +message JoinProgramInvite { + google.protobuf.StringValue id = 1; + google.protobuf.Timestamp created_at = 2; + google.protobuf.Timestamp expires_at = 3; + google.protobuf.Timestamp accepted_at = 4; + Program program = 5; + User user = 6; + google.protobuf.BoolValue email_sent = 7; + InviteStatus status = 8; +} + +message GetJoinProgramInviteResponse { + JoinProgramInvite invitation = 1; +} diff --git a/src/main/resources/flyway/sql/V17__create_data_center.sql b/src/main/resources/flyway/sql/V17__create_data_center.sql new file mode 100644 index 00000000..2ba380e0 --- /dev/null +++ b/src/main/resources/flyway/sql/V17__create_data_center.sql @@ -0,0 +1,24 @@ +CREATE TABLE data_center +( + id UUID PRIMARY KEY, + name VARCHAR(255) UNIQUE NOT NULL, + short_name VARCHAR(255) UNIQUE NOT NULL, + organization VARCHAR(255) NULL DEFAULT '', + email VARCHAR(255) NOT NULL, + ui_url VARCHAR(255) NOT NULL, + gateway_url VARCHAR(255) NOT NULL, + analysis_song_code VARCHAR(255) NOT NULL, + analysis_song_url VARCHAR(255) NOT NULL, + analysis_score_url VARCHAR(255) NOT NULL, + submission_song_code VARCHAR(255) NOT NULL, + submission_song_url VARCHAR(255) NOT NULL, + submission_score_url VARCHAR(255) NOT NULL +); + +INSERT INTO data_center (id, name, short_name, organization, email, ui_url, gateway_url, analysis_song_code, analysis_song_url, analysis_score_url, submission_song_code, submission_song_url, submission_score_url) VALUES + (uuid_generate_v4(), 'DataCenter1', 'DC1', '', 'abc@example.com', 'https://example.com', 'https://example.com', 'ABC', 'https://example.com', 'https://example.com', 'XYZ', 'https://example.com', 'https://example.com'); +ALTER TABLE program +ADD COLUMN data_center_id UUID NULL, +ADD CONSTRAINT program_data_center_fkey FOREIGN KEY(data_center_id) REFERENCES data_center(id); + +UPDATE program set data_center_id = (Select id from data_center); \ No newline at end of file diff --git a/src/test/java/org/icgc/argo/program_service/grpc/ProgramServiceGrpcIT.java b/src/test/java/org/icgc/argo/program_service/grpc/ProgramServiceGrpcIT.java index 0303b838..60b676b0 100644 --- a/src/test/java/org/icgc/argo/program_service/grpc/ProgramServiceGrpcIT.java +++ b/src/test/java/org/icgc/argo/program_service/grpc/ProgramServiceGrpcIT.java @@ -35,6 +35,7 @@ import io.grpc.testing.GrpcCleanupRule; import java.io.IOException; import java.util.List; +import java.util.UUID; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import lombok.val; @@ -138,6 +139,7 @@ public void createProgramAndGet() { .setShortName(shortName) .setMembershipType(membershipTypeValue(ASSOCIATE)) .setWebsite(stringValue("http://site.org")) + .setDataCenterId(StringValue.of(UUID.randomUUID().toString())) .addInstitutions("Ontario Institute for Cancer Research") .addRegions("Canada") .setName(stringValue(RandomString.make(15))) @@ -212,6 +214,7 @@ public void joinAndLeaveProgram() { Program.newBuilder() .setShortName(name) .setMembershipType(membershipTypeValue(ASSOCIATE)) + .setDataCenterId(StringValue.of(UUID.randomUUID().toString())) .setWebsite(stringValue("http://site.org")) .addInstitutions("Ontario Institute for Cancer Research") .addRegions("Canada") @@ -249,7 +252,6 @@ public void joinAndLeaveProgram() { assertFalse(isEmpty(inviteUserResponse.getInviteId().getValue())); } - String randomProgramName() { return randomAlphabetic(7).toUpperCase() + "-CA"; } @@ -360,6 +362,7 @@ public void updateProgramAddNewInstitution() { .setShortName(name) .setMembershipType(membershipTypeValue(ASSOCIATE)) .setWebsite(stringValue("http://site.org")) + .setDataCenterId(StringValue.of(UUID.randomUUID().toString())) .addInstitutions("Ontario Institute for Cancer Research") .addRegions("Canada") .setName(stringValue(RandomString.make(15))) diff --git a/src/test/java/org/icgc/argo/program_service/services/ValidationServiceTest.java b/src/test/java/org/icgc/argo/program_service/services/ValidationServiceTest.java index dd0c10a8..5bf159da 100644 --- a/src/test/java/org/icgc/argo/program_service/services/ValidationServiceTest.java +++ b/src/test/java/org/icgc/argo/program_service/services/ValidationServiceTest.java @@ -1,280 +1,282 @@ -/* - * Copyright (c) 2020 The Ontario Institute for Cancer Research. All rights reserved - * - * This program and the accompanying materials are made available under the terms of the GNU Affero General Public License v3.0. - * You should have received a copy of the GNU Affero General Public License along with - * this program. If not, see . - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - */ - -package org.icgc.argo.program_service.services; - -import static java.lang.String.format; -import static org.icgc.argo.program_service.utils.CollectionUtils.join; -import static org.icgc.argo.program_service.utils.CollectionUtils.mapToList; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.google.protobuf.Int32Value; -import com.google.protobuf.StringValue; -import java.util.List; -import lombok.val; -import org.icgc.argo.program_service.model.entity.CancerEntity; -import org.icgc.argo.program_service.model.entity.CountryEntity; -import org.icgc.argo.program_service.model.entity.PrimarySiteEntity; -import org.icgc.argo.program_service.model.entity.RegionEntity; -import org.icgc.argo.program_service.properties.ValidationProperties; -import org.icgc.argo.program_service.proto.*; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -class ValidationServiceTest { - private final int _init = init(); - ProgramService programService; - ValidationService validationService; - - int init() { - this.programService = mock(ProgramService.class); - when(programService.listCancers()) - .thenReturn(cancers("Blood cancer", "Brain cancer", "Renal cancer")); - when(programService.listPrimarySites()).thenReturn(primarySites("Blood", "Brain", "Liver")); - when(programService.listCountries()).thenReturn(countries("Canada", "Denmark")); - when(programService.listRegions()).thenReturn(regions("North America", "Europe")); - - this.validationService = - new ValidationService(programService, new ValidationProperties().factory()); - - return 1; - } - - private List cancers(String... names) { - return mapToList( - names, - s -> { - val c = new CancerEntity(); - c.setName(s); - return c; - }); - } - - private List primarySites(String... names) { - return mapToList( - names, - s -> { - val c = new PrimarySiteEntity(); - c.setName(s); - return c; - }); - } - - private List countries(String... names) { - return mapToList( - names, - s -> { - val c = new CountryEntity(); - c.setName(s); - return c; - }); - } - - private List regions(String... names) { - return mapToList( - names, - s -> { - val c = new RegionEntity(); - c.setName(s); - return c; - }); - } - - private List admins(String... emails) { - return mapToList( - emails, - email -> { - return User.newBuilder() - .setEmail(StringValue.of(email)) - .setFirstName(StringValue.of("Not")) - .setLastName(StringValue.of("Important")) - .setRole(UserRoleValue.newBuilder().setValue(UserRole.ADMIN).build()) - .build(); - }); - } - - private Program goodProgram() { - return Program.newBuilder() - .setCommitmentDonors(Int32Value.of(1000)) - .setGenomicDonors(Int32Value.of(0)) - .setMembershipType( - MembershipTypeValue.newBuilder().setValueValue(MembershipType.ASSOCIATE_VALUE).build()) - .setName(StringValue.of("A wonderful research program")) - .setShortName(StringValue.of("TEST-CA")) - .setWebsite(StringValue.of("http://www.site.com")) - .setSubmittedDonors(Int32Value.of(0)) - .addAllCancerTypes(List.of("Blood cancer", "Renal cancer")) - .addAllPrimarySites(List.of("Blood", "Liver")) - .addAllCountries(List.of("Canada", "Denmark")) - .addAllRegions(List.of("North America", "Europe")) - .addAllInstitutions(List.of("OICR", "New Institute of Novel Innovations")) - .build(); - } - - void createProgramExpectingErrorMessage(CreateProgramRequest request, String expectedMessage) { - String result = ""; - try { - val errors = validationService.validateCreateProgramRequest(request); - result = join(errors, ", "); - } catch (Exception ex) { - fail(format("Threw exception %s", ex.getMessage())); - } - assertEquals("Incorrect error message", expectedMessage, result); - } - - @Test - void createProgramEmptyRequest() { - val request = CreateProgramRequest.newBuilder().build(); - createProgramExpectingErrorMessage( - request, - "No program in the CreateProgram request, A program must have at least one administrator"); - } - - @Test - void createProgramNoAdmins() { - val request = - CreateProgramRequest.newBuilder().setProgram(goodProgram()).addAllAdmins(admins()).build(); - - createProgramExpectingErrorMessage(request, "A program must have at least one administrator"); - } - - @Test - void createProgramInvalidEmail() { - val request = - CreateProgramRequest.newBuilder() - .setProgram(goodProgram()) - .addAllAdmins(admins("invalid")) - .build(); - createProgramExpectingErrorMessage( - request, "Invalid email address 'invalid' for admin 'Not Important'"); - } - - @Test - void createProgramEmptyProgram() { - val program = Program.newBuilder().build(); - - val request = - CreateProgramRequest.newBuilder() - .setProgram(program) - .addAllAdmins(admins("valid@test.com")) - .build(); - - createProgramExpectingErrorMessage( - request, - "commitmentDonors must not be null, " - + "genomicDonors must not be null, membershipType must not be null, name must not be null, " - + "shortName must not be null, submittedDonors must not be null, website must not be null, " - + "Must include at least one cancerType, Must include at least one primarySite, " - + "Must include at least one region, Must include at least one country"); - } - - @Test - void createProgramInvalidShortName() { - val program = goodProgram().toBuilder().setShortName(StringValue.of("invalid")).build(); - - val request = - CreateProgramRequest.newBuilder() - .setProgram(program) - .addAllAdmins(admins("valid@test.com")) - .build(); - - createProgramExpectingErrorMessage(request, "shortName is invalid"); - } - - @Test - void createProgramInvalidWebSite() { - val program = goodProgram().toBuilder().setWebsite(StringValue.of("bad.com")).build(); - - val request = - CreateProgramRequest.newBuilder() - .setProgram(program) - .addAllAdmins(admins("valid@test.com")) - .build(); - - createProgramExpectingErrorMessage(request, "website must be a valid URL"); - } - - @Test - void createProgramBadCancerTypes() { - val program = - goodProgram().toBuilder().addAllCancerTypes(List.of("Not cancer", "Bad name")).build(); - - val request = - CreateProgramRequest.newBuilder() - .setProgram(program) - .addAllAdmins(admins("valid@test.com")) - .build(); - createProgramExpectingErrorMessage( - request, "Invalid cancerType 'Bad name', Invalid cancerType 'Not cancer'"); - } - - @Test - void createProgramBadPrimarySites() { - val program = - goodProgram() - .toBuilder() - .clearPrimarySites() - .addAllPrimarySites(List.of("Brain", "Blood", "Invalid", "Liver", "Onions")) - .build(); - - val request = - CreateProgramRequest.newBuilder() - .setProgram(program) - .addAllAdmins(admins("valid@test.com")) - .build(); - createProgramExpectingErrorMessage( - request, "Invalid primarySite 'Invalid', Invalid primarySite 'Onions'"); - } - - @Test - void createProgramBadCountries() { - val program = - goodProgram() - .toBuilder() - .clearCountries() - .addAllCountries(List.of("Canada", "New Freedonia", "Denmark")) - .build(); - - val request = - CreateProgramRequest.newBuilder() - .setProgram(program) - .addAllAdmins(admins("valid@test.com")) - .build(); - createProgramExpectingErrorMessage(request, "Invalid country 'New Freedonia'"); - } - - @Test - void createProgramBadRegions() { - val program = - goodProgram().toBuilder().addAllRegions(List.of("North America", "Europa")).build(); - - val request = - CreateProgramRequest.newBuilder() - .setProgram(program) - .addAllAdmins(admins("valid@test.com")) - .build(); - createProgramExpectingErrorMessage(request, "Invalid region 'Europa'"); - } -} +/* + * Copyright (c) 2020 The Ontario Institute for Cancer Research. All rights reserved + * + * This program and the accompanying materials are made available under the terms of the GNU Affero General Public License v3.0. + * You should have received a copy of the GNU Affero General Public License along with + * this program. If not, see . + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + */ + +package org.icgc.argo.program_service.services; + +import static java.lang.String.format; +import static org.icgc.argo.program_service.utils.CollectionUtils.join; +import static org.icgc.argo.program_service.utils.CollectionUtils.mapToList; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.protobuf.Int32Value; +import com.google.protobuf.StringValue; +import java.util.List; +import java.util.UUID; +import lombok.val; +import org.icgc.argo.program_service.model.entity.CancerEntity; +import org.icgc.argo.program_service.model.entity.CountryEntity; +import org.icgc.argo.program_service.model.entity.PrimarySiteEntity; +import org.icgc.argo.program_service.model.entity.RegionEntity; +import org.icgc.argo.program_service.properties.ValidationProperties; +import org.icgc.argo.program_service.proto.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class ValidationServiceTest { + private final int _init = init(); + ProgramService programService; + ValidationService validationService; + + int init() { + this.programService = mock(ProgramService.class); + when(programService.listCancers()) + .thenReturn(cancers("Blood cancer", "Brain cancer", "Renal cancer")); + when(programService.listPrimarySites()).thenReturn(primarySites("Blood", "Brain", "Liver")); + when(programService.listCountries()).thenReturn(countries("Canada", "Denmark")); + when(programService.listRegions()).thenReturn(regions("North America", "Europe")); + + this.validationService = + new ValidationService(programService, new ValidationProperties().factory()); + + return 1; + } + + private List cancers(String... names) { + return mapToList( + names, + s -> { + val c = new CancerEntity(); + c.setName(s); + return c; + }); + } + + private List primarySites(String... names) { + return mapToList( + names, + s -> { + val c = new PrimarySiteEntity(); + c.setName(s); + return c; + }); + } + + private List countries(String... names) { + return mapToList( + names, + s -> { + val c = new CountryEntity(); + c.setName(s); + return c; + }); + } + + private List regions(String... names) { + return mapToList( + names, + s -> { + val c = new RegionEntity(); + c.setName(s); + return c; + }); + } + + private List admins(String... emails) { + return mapToList( + emails, + email -> { + return User.newBuilder() + .setEmail(StringValue.of(email)) + .setFirstName(StringValue.of("Not")) + .setLastName(StringValue.of("Important")) + .setRole(UserRoleValue.newBuilder().setValue(UserRole.ADMIN).build()) + .build(); + }); + } + + private Program goodProgram() { + return Program.newBuilder() + .setCommitmentDonors(Int32Value.of(1000)) + .setDataCenterId(StringValue.of(UUID.randomUUID().toString())) + .setGenomicDonors(Int32Value.of(0)) + .setMembershipType( + MembershipTypeValue.newBuilder().setValueValue(MembershipType.ASSOCIATE_VALUE).build()) + .setName(StringValue.of("A wonderful research program")) + .setShortName(StringValue.of("TEST-CA")) + .setWebsite(StringValue.of("http://www.site.com")) + .setSubmittedDonors(Int32Value.of(0)) + .addAllCancerTypes(List.of("Blood cancer", "Renal cancer")) + .addAllPrimarySites(List.of("Blood", "Liver")) + .addAllCountries(List.of("Canada", "Denmark")) + .addAllRegions(List.of("North America", "Europe")) + .addAllInstitutions(List.of("OICR", "New Institute of Novel Innovations")) + .build(); + } + + void createProgramExpectingErrorMessage(CreateProgramRequest request, String expectedMessage) { + String result = ""; + try { + val errors = validationService.validateCreateProgramRequest(request); + result = join(errors, ", "); + } catch (Exception ex) { + fail(format("Threw exception %s", ex.getMessage())); + } + assertEquals("Incorrect error message", expectedMessage, result); + } + + @Test + void createProgramEmptyRequest() { + val request = CreateProgramRequest.newBuilder().build(); + createProgramExpectingErrorMessage( + request, + "No program in the CreateProgram request, A program must have at least one administrator"); + } + + @Test + void createProgramNoAdmins() { + val request = + CreateProgramRequest.newBuilder().setProgram(goodProgram()).addAllAdmins(admins()).build(); + + createProgramExpectingErrorMessage(request, "A program must have at least one administrator"); + } + + @Test + void createProgramInvalidEmail() { + val request = + CreateProgramRequest.newBuilder() + .setProgram(goodProgram()) + .addAllAdmins(admins("invalid")) + .build(); + createProgramExpectingErrorMessage( + request, "Invalid email address 'invalid' for admin 'Not Important'"); + } + + @Test + void createProgramEmptyProgram() { + val program = Program.newBuilder().build(); + + val request = + CreateProgramRequest.newBuilder() + .setProgram(program) + .addAllAdmins(admins("valid@test.com")) + .build(); + + createProgramExpectingErrorMessage( + request, + "commitmentDonors must not be null, " + + "genomicDonors must not be null, membershipType must not be null, name must not be null, " + + "shortName must not be null, submittedDonors must not be null, website must not be null, " + + "Must include at least one cancerType, Must include at least one primarySite, " + + "Must include at least one region, Must include at least one country"); + } + + @Test + void createProgramInvalidShortName() { + val program = goodProgram().toBuilder().setShortName(StringValue.of("invalid")).build(); + + val request = + CreateProgramRequest.newBuilder() + .setProgram(program) + .addAllAdmins(admins("valid@test.com")) + .build(); + + createProgramExpectingErrorMessage(request, "shortName is invalid"); + } + + @Test + void createProgramInvalidWebSite() { + val program = goodProgram().toBuilder().setWebsite(StringValue.of("bad.com")).build(); + + val request = + CreateProgramRequest.newBuilder() + .setProgram(program) + .addAllAdmins(admins("valid@test.com")) + .build(); + + createProgramExpectingErrorMessage(request, "website must be a valid URL"); + } + + @Test + void createProgramBadCancerTypes() { + val program = + goodProgram().toBuilder().addAllCancerTypes(List.of("Not cancer", "Bad name")).build(); + + val request = + CreateProgramRequest.newBuilder() + .setProgram(program) + .addAllAdmins(admins("valid@test.com")) + .build(); + createProgramExpectingErrorMessage( + request, "Invalid cancerType 'Bad name', Invalid cancerType 'Not cancer'"); + } + + @Test + void createProgramBadPrimarySites() { + val program = + goodProgram() + .toBuilder() + .clearPrimarySites() + .addAllPrimarySites(List.of("Brain", "Blood", "Invalid", "Liver", "Onions")) + .build(); + + val request = + CreateProgramRequest.newBuilder() + .setProgram(program) + .addAllAdmins(admins("valid@test.com")) + .build(); + createProgramExpectingErrorMessage( + request, "Invalid primarySite 'Invalid', Invalid primarySite 'Onions'"); + } + + @Test + void createProgramBadCountries() { + val program = + goodProgram() + .toBuilder() + .clearCountries() + .addAllCountries(List.of("Canada", "New Freedonia", "Denmark")) + .build(); + + val request = + CreateProgramRequest.newBuilder() + .setProgram(program) + .addAllAdmins(admins("valid@test.com")) + .build(); + createProgramExpectingErrorMessage(request, "Invalid country 'New Freedonia'"); + } + + @Test + void createProgramBadRegions() { + val program = + goodProgram().toBuilder().addAllRegions(List.of("North America", "Europa")).build(); + + val request = + CreateProgramRequest.newBuilder() + .setProgram(program) + .addAllAdmins(admins("valid@test.com")) + .build(); + createProgramExpectingErrorMessage(request, "Invalid region 'Europa'"); + } +}