diff --git a/src/main/java/fr/abes/sudoc/component/BaseXmlFunctionsCaller.java b/src/main/java/fr/abes/sudoc/component/BaseXmlFunctionsCaller.java index 3e424bb..719b8a5 100644 --- a/src/main/java/fr/abes/sudoc/component/BaseXmlFunctionsCaller.java +++ b/src/main/java/fr/abes/sudoc/component/BaseXmlFunctionsCaller.java @@ -5,7 +5,6 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; -import java.sql.SQLRecoverableException; import java.util.List; @Slf4j @@ -40,4 +39,29 @@ public List doiToPpn(String doi) throws UncategorizedSQLException { request.append("'"); return baseXmlJdbcTemplate.queryForList(request.toString(), String.class); } + + public List datToPpn(Integer date, String auteur, String titre) throws UncategorizedSQLException { + if (titre == null || titre.isEmpty()) { + throw new IllegalArgumentException("Le titre ne peut pas être null"); + } + StringBuilder request = new StringBuilder("SELECT DISTINCT a.PPN"); + if (date != null) { + request.append(" FROM AUTORITES.biblio_table_generale a"); + request.append(" JOIN AUTORITES.bib_100$a b"); + request.append(" ON a.ppn=b.ppn"); + if (auteur != null) { + request.append(" WHERE a.typerecord != 'd' and a.biblevel='l' and a.typecontrol = 'm' and CONTAINS(a.citation1, '(").append(titre).append(") AND (").append(auteur).append(")')>0 and (substr(b.datas,10,4) = '").append(date).append("' or substr(b.datas,14,4)='").append(date).append("')"); + } else { + request.append(" WHERE a.typerecord != 'd' and a.biblevel='l' and a.typecontrol = 'm' and CONTAINS(a.citation1, '(").append(titre).append(")')>0 and (substr(b.datas,10,4) = '").append(date).append("' or substr(b.datas,14,4)='").append(date).append("')"); + } + } else { + request.append(" FROM biblio_table_generale a"); + if (auteur != null) { + request.append(" WHERE a.typerecord != 'd' and a.biblevel='l' and a.typecontrol = 'm' and CONTAINS(a.citation1, '(").append(titre).append(") AND (").append(auteur).append(")')>0"); + } else { + request.append(" WHERE a.typerecord != 'd' and a.biblevel='l' and a.typecontrol = 'm' and CONTAINS(a.citation1, '(").append(titre).append(")')>0"); + } + } + return baseXmlJdbcTemplate.queryForList(request.toString(), String.class); + } } diff --git a/src/main/java/fr/abes/sudoc/configuration/BaseXMLOracleConfig.java b/src/main/java/fr/abes/sudoc/configuration/BaseXMLOracleConfig.java index 5be1eb6..3927df9 100644 --- a/src/main/java/fr/abes/sudoc/configuration/BaseXMLOracleConfig.java +++ b/src/main/java/fr/abes/sudoc/configuration/BaseXMLOracleConfig.java @@ -1,21 +1,9 @@ package fr.abes.sudoc.configuration; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.cache.annotation.EnableCaching; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.orm.jpa.JpaTransactionManager; -import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; -import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; -import org.springframework.transaction.PlatformTransactionManager; - -import javax.sql.DataSource; -import java.util.HashMap; @Configuration @EnableCaching diff --git a/src/main/java/fr/abes/sudoc/controller/SudocController.java b/src/main/java/fr/abes/sudoc/controller/SudocController.java index f94bb6b..86024d9 100644 --- a/src/main/java/fr/abes/sudoc/controller/SudocController.java +++ b/src/main/java/fr/abes/sudoc/controller/SudocController.java @@ -26,13 +26,13 @@ public class SudocController { private final IdentifiantFactory factory; - private final SudocService service; + private final DatService service; private final NoticeService noticeService; private final ProviderService providerService; - public SudocController(IdentifiantFactory factory, SudocService service, NoticeService noticeService, ProviderService providerService) { + public SudocController(IdentifiantFactory factory, DatService service, NoticeService noticeService, ProviderService providerService) { this.factory = factory; this.service = service; this.noticeService = noticeService; @@ -128,7 +128,7 @@ public ResultWsDto printIdentifier2Ppn(@PathVariable String type, @PathVariable @GetMapping(value = {"/doi_identifier_2_ppn"}, produces = MediaType.APPLICATION_JSON_VALUE) - public ResultWsDto doiIdentifier2Ppn(@RequestParam(name = "doi") String doi_identifier, @RequestParam(name = "provider") Optional provider) throws IOException { + public ResultWsDto doiIdentifier2Ppn(@RequestParam(name = "doi") String doi_identifier, @RequestParam(name = "provider") Optional provider) throws IOException, ZoneNotFoundException, IllegalPpnException { log.debug("DOI IDENTIFIER 2 PPN"); log.debug("RequestParam doi : {}, provider : {}", doi_identifier, provider); ResultWsDto resultat = new ResultWsDto(); @@ -192,13 +192,11 @@ public ResultWsDto datToPpn(@Valid @RequestBody SearchDatWebDto request) throws log.debug("dat2ppn : date : {} / auteur : {} / titre : {} <-> ppn n° {}", request.getDate(), request.getAuteur(), request.getTitre(), ppn); feedResultatWithNotice(resultat, providerDto, ppn); } - } catch (CBSException | ZoneNotFoundException ex) { + } catch (IllegalPpnException | ZoneNotFoundException ex) { resultat.addErreur(ex.getMessage()); } catch (IOException ex) { log.error("Erreur dans la récupération de la notice correspondant à l'identifiant"); throw new IOException(ex); - } catch (IllegalPpnException e) { - throw new IOException("Aucun identifiant ne correspond à la notice"); } return resultat; } diff --git a/src/main/java/fr/abes/sudoc/service/DatService.java b/src/main/java/fr/abes/sudoc/service/DatService.java new file mode 100644 index 0000000..c090062 --- /dev/null +++ b/src/main/java/fr/abes/sudoc/service/DatService.java @@ -0,0 +1,31 @@ +package fr.abes.sudoc.service; + +import fr.abes.sudoc.component.BaseXmlFunctionsCaller; +import fr.abes.sudoc.exception.IllegalPpnException; +import fr.abes.sudoc.utils.Utilitaire; +import org.springframework.jdbc.UncategorizedSQLException; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.util.List; + +@Service +public class DatService { + private final BaseXmlFunctionsCaller caller; + + public DatService(BaseXmlFunctionsCaller caller) { + this.caller = caller; + } + + public List getPpnFromDat(Integer date, String auteur, String titre) throws IllegalPpnException, IOException { + try { + List result = caller.datToPpn(date, Utilitaire.formatString(auteur), Utilitaire.formatString(titre)); + if (result.isEmpty()) + throw new IllegalPpnException("Aucune notice ne correspond à la recherche sur " + date + " , " + auteur + " , " + titre); + return result; + } catch (UncategorizedSQLException ex) { + throw new IOException("Incident technique lors de l'accès à la base de données"); + } + } + +} diff --git a/src/main/java/fr/abes/sudoc/service/DoiService.java b/src/main/java/fr/abes/sudoc/service/DoiService.java index 65ee36d..466a77d 100644 --- a/src/main/java/fr/abes/sudoc/service/DoiService.java +++ b/src/main/java/fr/abes/sudoc/service/DoiService.java @@ -1,18 +1,12 @@ package fr.abes.sudoc.service; -import com.fasterxml.jackson.core.JsonProcessingException; import fr.abes.sudoc.component.BaseXmlFunctionsCaller; import fr.abes.sudoc.exception.IllegalPpnException; -import fr.abes.sudoc.utils.Utilitaire; -import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.UncategorizedSQLException; import org.springframework.stereotype.Service; import java.io.IOException; -import java.sql.SQLRecoverableException; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.List; @Service diff --git a/src/main/java/fr/abes/sudoc/service/SudocService.java b/src/main/java/fr/abes/sudoc/service/SudocService.java deleted file mode 100644 index 0fb9c74..0000000 --- a/src/main/java/fr/abes/sudoc/service/SudocService.java +++ /dev/null @@ -1,61 +0,0 @@ -package fr.abes.sudoc.service; - -import fr.abes.cbs.exception.CBSException; -import fr.abes.cbs.process.ProcessCBS; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -@Service -@Slf4j -public class SudocService { - @Value("${sudoc.serveur}") - private String serveurCbs; - @Value("${sudoc.port}") - private String port; - @Value("${sudoc.login}") - private String loginCbs; - @Value("${sudoc.passwd}") - private String passCbs; - - @Getter - private String query; - - public List getPpnFromDat(Integer annee, String auteur, String titre) throws CBSException { - ProcessCBS cbs = new ProcessCBS(); - try { - log.debug("serveur : " + this.serveurCbs + " / port : " + this.port); - cbs.authenticate(this.serveurCbs, this.port, this.loginCbs, this.passCbs); - if (annee != null && auteur != null) { - this.query = "tno t ; apu " + annee + " ; che aut " + auteur + " et mti " + titre; - } else if (annee != null) { - this.query = "tno t ; apu " + annee + " ; che mti " + titre; - } else { - if (auteur != null) { - this.query = "tno t ; che aut " + auteur + " et mti " + titre; - } else { - if (titre != null) - this.query = "tno t ; che mti " + titre; - else return new ArrayList<>(); - - } - } - - log.debug("requête : {}", this.query); - cbs.search(this.query); - return switch (cbs.getNbNotices()) { - case 0 -> new ArrayList<>(); - case 1 -> Collections.singletonList(cbs.getPpnEncours()); - default -> Arrays.asList(cbs.getListePpn().toString().split(";")); - }; - } finally { - cbs.disconnect(); - } - } -} diff --git a/src/main/java/fr/abes/sudoc/utils/Utilitaire.java b/src/main/java/fr/abes/sudoc/utils/Utilitaire.java index 2ea2f92..5f3d61e 100644 --- a/src/main/java/fr/abes/sudoc/utils/Utilitaire.java +++ b/src/main/java/fr/abes/sudoc/utils/Utilitaire.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; import java.util.List; @@ -93,6 +94,32 @@ public static String replaceDiacritics(String src) { return result.toString(); } + public static String formatString(String chaine) { + if (chaine != null && !chaine.isEmpty()) { + return suppReservedWords(suppCaracters(chaine)); + } + return chaine; + } + + private static String suppCaracters(String chaine) { + // Liste des caractères à supprimer + List charsToRemove = Arrays.asList('&', ',', '=', '?', '{', '}', '\\', '(', ')', '[', ']', '-', '~', '|', '$', '!', '>', '*', '_', '%'); + + // Construire une expression régulière avec les caractères à supprimer + String regex = "[" + charsToRemove.stream() + .map(c -> "\\" + c) // Échapper les caractères spéciaux si nécessaire + .reduce("", (acc, c) -> acc + c) + "]"; + return chaine.replaceAll(regex, ""); + } + + private static String suppReservedWords(String chaine) { + List wordsToRemove = Arrays.asList("ABOUT", "ACCUM", "AND", "BT", "BTG", "BTI", "BTP", "EQUIV", "FUZZY", "HASPATH", "INPATH", "MDATA", "MINUS", "NEAR", "NOT", "NT", "NTG", "NTI", "NTP", "OR", "PATTERN", "PT", "RT", "SQE", "SYN", "TR", "TRSYN", "TT", "WITHIN"); + // Construire une expression régulière avec les caractères à supprimer + String regex = "\\b(" + String.join("|", wordsToRemove) + ")\\b"; + return chaine.replaceAll("(?i)" + regex, "").replaceAll("\\s+", " ").trim(); + + } + } diff --git a/src/test/java/fr/abes/sudoc/controller/SudocControllerTest.java b/src/test/java/fr/abes/sudoc/controller/SudocControllerTest.java index 6e14c90..d7b6363 100644 --- a/src/test/java/fr/abes/sudoc/controller/SudocControllerTest.java +++ b/src/test/java/fr/abes/sudoc/controller/SudocControllerTest.java @@ -32,7 +32,6 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; -import java.util.Objects; import java.util.Optional; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -40,7 +39,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@SpringBootTest(classes = {SudocController.class, SudocService.class, ExceptionControllerHandler.class}) +@SpringBootTest(classes = {SudocController.class, DatService.class, ExceptionControllerHandler.class}) @ContextConfiguration(classes = {IdentifiantFactory.class}) class SudocControllerTest { @@ -54,7 +53,7 @@ class SudocControllerTest { IdentifiantFactory factory; @MockBean - SudocService service; + DatService service; @MockBean NoticeService noticeService; @@ -153,9 +152,9 @@ void datToPpnTryCatchNotWorks() throws Exception { ObjectMapper objectMapper = new ObjectMapper(); String jsonRequest = objectMapper.writeValueAsString(searchDatRequest); - CBSException cbsException = new CBSException("404", "La rechercher n'a pas donné de résultat"); + IllegalPpnException illegalPpnException = new IllegalPpnException("La rechercher n'a pas donné de résultat"); - Mockito.when(service.getPpnFromDat(searchDatRequest.getDate(), searchDatRequest.getAuteur(), searchDatRequest.getTitre())).thenThrow(cbsException); + Mockito.when(service.getPpnFromDat(searchDatRequest.getDate(), searchDatRequest.getAuteur(), searchDatRequest.getTitre())).thenThrow(illegalPpnException); this.mockMvc.perform(post("/api/v1/dat2ppn") .accept(MediaType.APPLICATION_JSON_VALUE).characterEncoding(StandardCharsets.UTF_8) diff --git a/src/test/java/fr/abes/sudoc/utils/UtilitaireTest.java b/src/test/java/fr/abes/sudoc/utils/UtilitaireTest.java index 0883ba4..a016a5b 100644 --- a/src/test/java/fr/abes/sudoc/utils/UtilitaireTest.java +++ b/src/test/java/fr/abes/sudoc/utils/UtilitaireTest.java @@ -106,4 +106,11 @@ void testReplaceDiacritics() { chaine = "çüûùöôïîëêèéäâà"; Assertions.assertEquals("cuuuooiieeeeaaa", Utilitaire.replaceDiacritics(chaine)); } + + @Test + @DisplayName("test reformatage chaine DAT") + void testReformatageChaineDat() { + Assertions.assertEquals("Assez de ces fichus TU", Utilitaire.formatString("Assez ! de _ ces ~fichus *TU")); + Assertions.assertEquals("Je suis content", Utilitaire.formatString("Je AND suis! WITHIN content")); + } }