Skip to content

Commit

Permalink
fix(browse-classifications): implement browse config endpoint
Browse files Browse the repository at this point in the history
Closes: MSEARCH-674
Signed-off-by: psmagin <[email protected]>
  • Loading branch information
psmagin committed Feb 21, 2024
1 parent 0b2889e commit 0366bf1
Show file tree
Hide file tree
Showing 19 changed files with 720 additions and 17 deletions.
6 changes: 6 additions & 0 deletions .jpb/jpb-settings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JpaPluginProjectSettings">
<option name="lastSelectedLanguage" value="Java" />
</component>
</project>
40 changes: 40 additions & 0 deletions descriptors/ModuleDescriptor-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,36 @@
}
]
},
{
"id": "browse-config",
"version": "1.0",
"handlers": [
{
"methods": [
"GET"
],
"pathPattern": "/browse/config/{browseType}",
"permissionsRequired": [
"browse.config.collection.get"
],
"modulePermissions": [
"user-tenants.collection.get"
]
},
{
"methods": [
"PUT"
],
"pathPattern": "/browse/config/{browseType}/{browseConfigId}",
"permissionsRequired": [
"browse.config.item.put"
],
"modulePermissions": [
"user-tenants.collection.get"
]
}
]
},
{
"id": "search-config",
"version": "0.2",
Expand Down Expand Up @@ -531,6 +561,16 @@
"permissionName": "search.config.features.item.delete",
"displayName": "Search - removes feature configuration",
"description": "Removes feature configuration"
},
{
"permissionName": "browse.config.collection.get",
"displayName": "Browse - returns configurations for browse type",
"description": "Returns configuration for browse type"
},
{
"permissionName": "browse.config.item.put",
"displayName": "Browse - updates configuration entry for browse type",
"description": "Updates configuration entry for browse type"
}
],
"launchDescriptor": {
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/org/folio/search/configuration/WebConfig.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.folio.search.configuration;

import org.folio.search.domain.dto.BrowseOptionType;
import org.folio.search.domain.dto.BrowseType;
import org.folio.search.domain.dto.CallNumberType;
import org.folio.search.domain.dto.RecordType;
import org.springframework.context.annotation.Configuration;
Expand All @@ -14,6 +16,8 @@ public class WebConfig implements WebMvcConfigurer {
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new StringToRecordTypeEnumConverter());
registry.addConverter(new StringToCallNumberTypeEnumConverter());
registry.addConverter(new StringToBrowseTypeConverter());
registry.addConverter(new StringToBrowseOptionTypeConverter());
}

private static final class StringToRecordTypeEnumConverter implements Converter<String, RecordType> {
Expand All @@ -29,4 +33,18 @@ public CallNumberType convert(String source) {
return CallNumberType.valueOf(source.toUpperCase());
}
}

private static final class StringToBrowseTypeConverter implements Converter<String, BrowseType> {
@Override
public BrowseType convert(String source) {
return BrowseType.fromValue(source.toLowerCase());
}
}

private static final class StringToBrowseOptionTypeConverter implements Converter<String, BrowseOptionType> {
@Override
public BrowseOptionType convert(String source) {
return BrowseOptionType.fromValue(source.toLowerCase());
}
}
}
33 changes: 26 additions & 7 deletions src/main/java/org/folio/search/controller/ConfigController.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.folio.search.domain.dto.BrowseConfig;
import org.folio.search.domain.dto.BrowseConfigCollection;
import org.folio.search.domain.dto.BrowseOptionType;
import org.folio.search.domain.dto.BrowseType;
import org.folio.search.domain.dto.FeatureConfig;
import org.folio.search.domain.dto.FeatureConfigs;
import org.folio.search.domain.dto.LanguageConfig;
import org.folio.search.domain.dto.LanguageConfigs;
import org.folio.search.domain.dto.TenantConfiguredFeature;
import org.folio.search.rest.resource.ConfigApi;
import org.folio.search.service.consortium.BrowseConfigServiceDecorator;
import org.folio.search.service.consortium.FeatureConfigServiceDecorator;
import org.folio.search.service.consortium.LanguageConfigServiceDecorator;
import org.springframework.http.ResponseEntity;
Expand All @@ -28,6 +33,7 @@ public class ConfigController implements ConfigApi {

private final LanguageConfigServiceDecorator languageConfigService;
private final FeatureConfigServiceDecorator featureConfigService;
private final BrowseConfigServiceDecorator browseConfigService;

@Override
public ResponseEntity<LanguageConfig> createLanguageConfig(@Valid LanguageConfig languageConfig) {
Expand All @@ -36,8 +42,9 @@ public ResponseEntity<LanguageConfig> createLanguageConfig(@Valid LanguageConfig
}

@Override
public ResponseEntity<LanguageConfig> updateLanguageConfig(String code, LanguageConfig languageConfig) {
return ok(languageConfigService.update(code, languageConfig));
public ResponseEntity<Void> deleteFeatureConfigurationById(String feature) {
featureConfigService.delete(TenantConfiguredFeature.fromValue(feature));
return noContent().build();
}

@Override
Expand All @@ -47,14 +54,26 @@ public ResponseEntity<Void> deleteLanguageConfig(String code) {
return noContent().build();
}

@Override
public ResponseEntity<FeatureConfigs> getAllFeatures() {
return ok(featureConfigService.getAll());
}

@Override
public ResponseEntity<LanguageConfigs> getAllLanguageConfigs() {
return ok(languageConfigService.getAll());
}

@Override
public ResponseEntity<FeatureConfigs> getAllFeatures() {
return ok(featureConfigService.getAll());
public ResponseEntity<BrowseConfigCollection> getBrowseConfigs(BrowseType browseType) {
return ResponseEntity.ok(browseConfigService.getConfigs(browseType));
}

@Override
public ResponseEntity<Void> putBrowseConfig(BrowseType browseType, BrowseOptionType browseConfigId,
BrowseConfig browseConfig) {
browseConfigService.upsertConfig(browseType, browseConfigId, browseConfig);
return ResponseEntity.ok().build();
}

@Override
Expand All @@ -68,8 +87,8 @@ public ResponseEntity<FeatureConfig> updateFeatureConfiguration(String feature,
}

@Override
public ResponseEntity<Void> deleteFeatureConfigurationById(String feature) {
featureConfigService.delete(TenantConfiguredFeature.fromValue(feature));
return noContent().build();
public ResponseEntity<LanguageConfig> updateLanguageConfig(String code, LanguageConfig languageConfig) {
return ok(languageConfigService.update(code, languageConfig));
}

}
35 changes: 35 additions & 0 deletions src/main/java/org/folio/search/converter/BrowseConfigMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.folio.search.converter;

import java.util.List;
import org.folio.search.domain.dto.BrowseConfig;
import org.folio.search.domain.dto.BrowseConfigCollection;
import org.folio.search.domain.dto.BrowseOptionType;
import org.folio.search.domain.dto.BrowseType;
import org.folio.search.domain.dto.ShelvingOrderAlgorithmType;
import org.folio.search.model.config.BrowseConfigEntity;
import org.folio.search.model.config.BrowseConfigId;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

@Mapper(componentModel = "spring",
imports = {BrowseOptionType.class, BrowseConfigId.class, ShelvingOrderAlgorithmType.class})
public interface BrowseConfigMapper {

@Mapping(target = "configId", expression = "java(new BrowseConfigId(type.getValue(), config.getId().getValue()))")
@Mapping(target = "shelvingAlgorithm", expression = "java(config.getShelvingAlgorithm().getValue())")
BrowseConfigEntity convert(BrowseType type, BrowseConfig config);

@Mapping(target = "id", expression = "java(BrowseOptionType.fromValue(source.getConfigId().getBrowseOptionType()))")
@Mapping(target = "shelvingAlgorithm",
expression = "java(ShelvingOrderAlgorithmType.fromValue(source.getShelvingAlgorithm()))")
BrowseConfig convert(BrowseConfigEntity source);

default BrowseConfigCollection convert(List<BrowseConfigEntity> entities) {
return map(new BrowseConfigWrapper(entities));
}

@Mapping(target = "totalRecords", expression = "java(source.configs().size())")
BrowseConfigCollection map(BrowseConfigWrapper source);

record BrowseConfigWrapper(List<BrowseConfigEntity> configs) { }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.folio.search.model.config;

import jakarta.persistence.Column;
import jakarta.persistence.Convert;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.proxy.HibernateProxy;

@Getter
@Setter
@ToString
@RequiredArgsConstructor
@Entity
@Table(name = "browse_config")
public class BrowseConfigEntity {

@EmbeddedId
private BrowseConfigId configId;

@Column(name = "shelving_algorithm", nullable = false)
private String shelvingAlgorithm;

@Convert(converter = StringListConverter.class)
@Column(name = "type_ids", nullable = false)
private List<String> typeIds = new ArrayList<>();

@Override
public final int hashCode() {
return Objects.hash(configId);
}

@Override
public final boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null) {
return false;
}
Class<?> effectiveClass = o instanceof HibernateProxy
? ((HibernateProxy) o).getHibernateLazyInitializer().getPersistentClass()
: o.getClass();
Class<?> thisEffectiveClass = this instanceof HibernateProxy
? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass()
: this.getClass();
if (thisEffectiveClass != effectiveClass) {
return false;
}
BrowseConfigEntity that = (BrowseConfigEntity) o;
return getConfigId() != null && Objects.equals(getConfigId(), that.getConfigId());
}
}
48 changes: 48 additions & 0 deletions src/main/java/org/folio/search/model/config/BrowseConfigId.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package org.folio.search.model.config;

import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import java.util.Objects;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.proxy.HibernateProxy;

@Getter
@Embeddable
@NoArgsConstructor
@AllArgsConstructor
public class BrowseConfigId {

@Column(name = "browse_type")
private String browseType;
@Column(name = "browse_option_type")
private String browseOptionType;

@Override
public final int hashCode() {
return Objects.hash(browseType, browseOptionType);
}

@Override
public final boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null) {
return false;
}
Class<?> effectiveClass = o instanceof HibernateProxy
? ((HibernateProxy) o).getHibernateLazyInitializer().getPersistentClass()
: o.getClass();
Class<?> thisEffectiveClass = this instanceof HibernateProxy
? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass()
: this.getClass();
if (thisEffectiveClass != effectiveClass) {
return false;
}
BrowseConfigId that = (BrowseConfigId) o;
return browseType != null && Objects.equals(browseType, that.browseType)
&& browseOptionType != null && Objects.equals(browseOptionType, that.browseOptionType);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.folio.search.model.config;

import static java.util.Collections.emptyList;

import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
import java.util.Arrays;
import java.util.List;

@Converter
public class StringListConverter implements AttributeConverter<List<String>, String> {
private static final String SPLIT_CHAR = ";";

@Override
public String convertToDatabaseColumn(List<String> stringList) {
return stringList != null ? String.join(SPLIT_CHAR, stringList) : "";
}

@Override
public List<String> convertToEntityAttribute(String string) {
return string != null ? Arrays.asList(string.split(SPLIT_CHAR)) : emptyList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.folio.search.repository;

import java.util.List;
import org.folio.search.model.config.BrowseConfigEntity;
import org.folio.search.model.config.BrowseConfigId;
import org.springframework.data.jpa.repository.JpaRepository;

public interface BrowseConfigEntityRepository extends JpaRepository<BrowseConfigEntity, BrowseConfigId> {

List<BrowseConfigEntity> findByConfigId_BrowseType(String browseType);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.folio.search.service.config;

import lombok.RequiredArgsConstructor;
import org.folio.search.converter.BrowseConfigMapper;
import org.folio.search.domain.dto.BrowseConfig;
import org.folio.search.domain.dto.BrowseConfigCollection;
import org.folio.search.domain.dto.BrowseOptionType;
import org.folio.search.domain.dto.BrowseType;
import org.folio.search.exception.RequestValidationException;
import org.folio.search.repository.BrowseConfigEntityRepository;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class BrowseConfigService {

private static final String BODY_VALIDATION_MSG = "Body doesn't match path parameter: %s";

private final BrowseConfigEntityRepository repository;
private final BrowseConfigMapper mapper;

public BrowseConfigCollection getConfigs(BrowseType type) {
return mapper.convert(repository.findByConfigId_BrowseType(type.getValue()));
}

public void upsertConfig(BrowseType type, BrowseOptionType configId, BrowseConfig config) {
if (configId != null && configId != config.getId()) {
throw new RequestValidationException(
BODY_VALIDATION_MSG.formatted(configId.getValue()), "id", config.getId().toString());
}

var configEntity = mapper.convert(type, config);
repository.save(configEntity);
}
}
Loading

0 comments on commit 0366bf1

Please sign in to comment.