Compare commits

...

15 Commits

Author SHA1 Message Date
Timo Bejan
bc4a517514 RED-4799 2022-07-29 10:22:11 +02:00
Timo Bejan
d616dc9a57 Pull request #440: RED-4799
Merge in RED/redaction-service from RED-4799-33x-release-fix to release/3.107.x

* commit '4289dfee2ddc1acf673ce7d16569ab514d1bbe6e':
  RED-4799
2022-07-27 12:00:20 +02:00
Timo Bejan
4289dfee2d RED-4799 2022-07-27 12:56:52 +03:00
Dominique Eiflaender
05834865ec Pull request #428: RED-4686: Added jackson-commons to fix InvalidDefinitionException: Java 8 date/time type java.time.OffsetDateTime
Merge in RED/redaction-service from RED-4686-bp2 to release/3.107.x

* commit '2e5ba30b3205f32dcbf10de4765b1aad2ee46cbe':
  RED-4686: Added jackson-commons to fix InvalidDefinitionException: Java 8 date/time type java.time.OffsetDateTime
2022-07-22 15:08:22 +02:00
deiflaender
2e5ba30b32 RED-4686: Added jackson-commons to fix InvalidDefinitionException: Java 8 date/time type java.time.OffsetDateTime 2022-07-22 15:04:07 +02:00
Dominique Eiflaender
17783c7e1d Pull request #427: RED-4686: Stream objects to storage
Merge in RED/redaction-service from RED-4686-backport to release/3.107.x

* commit 'bb433a09974d048291a362d7fb9f6e3cf431543d':
  RED-4686: Stream objects to storage
2022-07-22 14:19:34 +02:00
deiflaender
bb433a0997 RED-4686: Stream objects to storage 2022-07-22 14:14:59 +02:00
Ali Oezyetimoglu
2564136407 Pull request #423: RED-4548: Create SIMPLIFIED_TEXT.json from TEXT.json (for NER-service)
Merge in RED/redaction-service from RED-4548-rs2PORT to release/3.107.x

* commit '15676ba13ad5cb4741092c2ad72fe582b3465cc2':
  RED-4548: Create SIMPLIFIED_TEXT.json from TEXT.json (for NER-service)
2022-07-14 17:09:20 +02:00
Ali Oezyetimoglu
15676ba13a RED-4548: Create SIMPLIFIED_TEXT.json from TEXT.json (for NER-service) 2022-07-14 17:04:29 +02:00
Ali Oezyetimoglu
a76eedb4cf Pull request #421: RED-4548: PORT: Create SIMPLIFIED_TEXT.json from TEXT.json (for NER-service)
Merge in RED/redaction-service from RED-4548-rs1PORT to release/3.107.x

* commit '8eef6ab3faa92da5f4d510131805614abda14c9a':
  RED-4548: PORT: Create SIMPLIFIED_TEXT.json from TEXT.json (for NER-service)
2022-07-14 11:53:53 +02:00
Ali Oezyetimoglu
8eef6ab3fa RED-4548: PORT: Create SIMPLIFIED_TEXT.json from TEXT.json (for NER-service) 2022-07-14 11:50:51 +02:00
Dominique Eiflaender
637f7bc502 Pull request #410: RED-4218: Do not perform surrounding text analysis for resize redactions with value = null
Merge in RED/redaction-service from RED-4218 to release/3.107.x

* commit '3c09f0a63f9e0010ce65d9d6281606c6118365d3':
  RED-4218: Do not perform surrounding text analysis for resize redactions with value = null
2022-06-13 12:32:05 +02:00
deiflaender
3c09f0a63f RED-4218: Do not perform surrounding text analysis for resize redactions with value = null 2022-06-13 12:28:24 +02:00
Dominique Eiflaender
166a30bcc9 Pull request #391: RED-4075: Add legalBasis if Rule Entity overrides Ai Recommendation
Merge in RED/redaction-service from RED-4075-backport to release/3.107.x

* commit 'f4281bf40a6ff15bfeceb6eeacb64bfa6fc49c4f':
  RED-4075: Add legalBasis if Rule Entity overrides Ai Recommendation
2022-05-23 14:24:34 +02:00
deiflaender
f4281bf40a RED-4075: Add legalBasis if Rule Entity overrides Ai Recommendation 2022-05-23 14:19:17 +02:00
10 changed files with 153 additions and 17 deletions

View File

@ -32,7 +32,7 @@
<dependency> <dependency>
<groupId>com.iqser.red</groupId> <groupId>com.iqser.red</groupId>
<artifactId>platform-commons-dependency</artifactId> <artifactId>platform-commons-dependency</artifactId>
<version>1.11.0</version> <version>1.15.0</version>
<scope>import</scope> <scope>import</scope>
<type>pom</type> <type>pom</type>
</dependency> </dependency>

View File

@ -12,7 +12,7 @@
<artifactId>redaction-service-api-v1</artifactId> <artifactId>redaction-service-api-v1</artifactId>
<properties> <properties>
<persistence-service.version>1.143.0</persistence-service.version> <persistence-service.version>1.156.20</persistence-service.version>
</properties> </properties>
<dependencies> <dependencies>

View File

@ -20,6 +20,11 @@
</properties> </properties>
<dependencies> <dependencies>
<dependency>
<groupId>com.iqser.red.commons</groupId>
<artifactId>jackson-commons</artifactId>
<version>1.0.0</version>
</dependency>
<dependency> <dependency>
<groupId>com.iqser.red.commons</groupId> <groupId>com.iqser.red.commons</groupId>
<artifactId>storage-commons</artifactId> <artifactId>storage-commons</artifactId>

View File

@ -0,0 +1,18 @@
package com.iqser.red.service.redaction.v1.server.classification.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SimplifiedSectionText {
private int sectionNumber;
private String text;
}

View File

@ -0,0 +1,20 @@
package com.iqser.red.service.redaction.v1.server.classification.model;
import java.util.ArrayList;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SimplifiedText {
private int numberOfPages;
private List<SimplifiedSectionText> sectionTexts = new ArrayList<>();
}

View File

@ -2,10 +2,12 @@ package com.iqser.red.service.redaction.v1.server.redaction.service;
import static com.iqser.red.service.redaction.v1.server.redaction.service.ImportedRedactionService.IMPORTED_REDACTION_TYPE; import static com.iqser.red.service.redaction.v1.server.redaction.service.ImportedRedactionService.IMPORTED_REDACTION_TYPE;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -30,6 +32,8 @@ import com.iqser.red.service.redaction.v1.model.SectionGrid;
import com.iqser.red.service.redaction.v1.model.StructureAnalyzeRequest; import com.iqser.red.service.redaction.v1.model.StructureAnalyzeRequest;
import com.iqser.red.service.redaction.v1.server.classification.model.Document; import com.iqser.red.service.redaction.v1.server.classification.model.Document;
import com.iqser.red.service.redaction.v1.server.classification.model.SectionText; import com.iqser.red.service.redaction.v1.server.classification.model.SectionText;
import com.iqser.red.service.redaction.v1.server.classification.model.SimplifiedSectionText;
import com.iqser.red.service.redaction.v1.server.classification.model.SimplifiedText;
import com.iqser.red.service.redaction.v1.server.classification.model.Text; import com.iqser.red.service.redaction.v1.server.classification.model.Text;
import com.iqser.red.service.redaction.v1.server.client.LegalBasisClient; import com.iqser.red.service.redaction.v1.server.client.LegalBasisClient;
import com.iqser.red.service.redaction.v1.server.client.model.NerEntities; import com.iqser.red.service.redaction.v1.server.client.model.NerEntities;
@ -104,8 +108,9 @@ public class AnalyzeService {
.map(SectionArea::getPage) .map(SectionArea::getPage)
.collect(Collectors.toSet()), sectionText.getSectionAreas()))); .collect(Collectors.toSet()), sectionText.getSectionAreas())));
log.info("Store text and section grid for file {} in dossier {}", analyzeRequest.getFileId(), analyzeRequest.getDossierId()); log.info("Store text, simplified text and section grid for file {} in dossier {}", analyzeRequest.getFileId(), analyzeRequest.getDossierId());
redactionStorageService.storeObject(analyzeRequest.getDossierId(), analyzeRequest.getFileId(), FileType.TEXT, text); redactionStorageService.storeObject(analyzeRequest.getDossierId(), analyzeRequest.getFileId(), FileType.TEXT, text);
redactionStorageService.storeObject(analyzeRequest.getDossierId(), analyzeRequest.getFileId(), FileType.SIMPLIFIED_TEXT, convert(text));
redactionStorageService.storeObject(analyzeRequest.getDossierId(), analyzeRequest.getFileId(), FileType.SECTION_GRID, classifiedDoc.getSectionGrid()); redactionStorageService.storeObject(analyzeRequest.getDossierId(), analyzeRequest.getFileId(), FileType.SECTION_GRID, classifiedDoc.getSectionGrid());
return AnalyzeResult.builder() return AnalyzeResult.builder()
@ -310,4 +315,16 @@ public class AnalyzeService {
} }
} }
private SimplifiedText convert(Text text) {
List<SimplifiedSectionText> sectionTexts = new ArrayList<>();
int numberOfPages = 0;
if (text != null) {
numberOfPages = text.getNumberOfPages();
text.getSectionTexts().stream().filter(Objects::nonNull).forEach(st -> sectionTexts.add(new SimplifiedSectionText(st.getSectionNumber(), st.getText())));
}
return SimplifiedText.builder().numberOfPages(numberOfPages).sectionTexts(sectionTexts).build();
}
} }

View File

@ -65,7 +65,7 @@ public class ManualRedactionSurroundingTextService {
var resizeItty = manualRedactions.getResizeRedactions().iterator(); var resizeItty = manualRedactions.getResizeRedactions().iterator();
while (resizeItty.hasNext()) { while (resizeItty.hasNext()) {
var manualResizeRedaction = resizeItty.next(); var manualResizeRedaction = resizeItty.next();
if (sectionContainsEntry(sectionArea, manualResizeRedaction.getPositions())) { if (manualResizeRedaction.getValue() != null && sectionContainsEntry(sectionArea, manualResizeRedaction.getPositions())) {
var surroundingText = findSurroundingText(sectionText, manualResizeRedaction.getValue(), manualResizeRedaction.getPositions()); var surroundingText = findSurroundingText(sectionText, manualResizeRedaction.getValue(), manualResizeRedaction.getPositions());
manualResizeRedaction.setTextBefore(surroundingText.getLeft()); manualResizeRedaction.setTextBefore(surroundingText.getLeft());
manualResizeRedaction.setTextAfter(surroundingText.getRight()); manualResizeRedaction.setTextAfter(surroundingText.getRight());

View File

@ -62,14 +62,16 @@ public class EntitySearchUtils {
Set<Entity> found = find(inputString, values, type.getType(), headline, sectionNumber, isDictionaryEntry, isDossierDictionary, engine, ignoreMinLength, asRecommendation ? EntityType.RECOMMENDATION : EntityType.ENTITY); Set<Entity> found = find(inputString, values, type.getType(), headline, sectionNumber, isDictionaryEntry, isDossierDictionary, engine, ignoreMinLength, asRecommendation ? EntityType.RECOMMENDATION : EntityType.ENTITY);
if(asRecommendation){ if (details.getEntityType() == EntityType.RECOMMENDATION) {
Set<Entity> falseRecommendations = find(inputString, type.getFalseRecommendationValues(), type.getType(), headline, sectionNumber, isDictionaryEntry, isDossierDictionary, engine, ignoreMinLength, EntityType.FALSE_RECOMMENDATION); Set<Entity> falseRecommendations = find(inputString, type.getFalseRecommendationsSearch(), details.withEntityType(EntityType.FALSE_RECOMMENDATION));
removeFalsePositives(found, falseRecommendations); removeFalsePositives(found, falseRecommendations);
found.addAll(falseRecommendations); // RED-4799 - false positives are no longer in redaction log
// found.addAll(falseRecommendations);
} else { } else {
Set<Entity> falsePositives = find(inputString, type.getFalsePositiveValues(), type.getType(), headline, sectionNumber, isDictionaryEntry, isDossierDictionary, engine, ignoreMinLength, EntityType.FALSE_POSITIVE); Set<Entity> falsePositives = find(inputString, type.getFalsePositiveSearch(), details.withEntityType(EntityType.FALSE_POSITIVE));
removeFalsePositives(found, falsePositives); removeFalsePositives(found, falsePositives);
found.addAll(falsePositives); // RED-4799 - false positives are no longer in redaction log
// found.addAll(falsePositives);
} }
return found; return found;
@ -164,6 +166,15 @@ public class EntitySearchUtils {
List<Entity> wordsToRemove = new ArrayList<>(); List<Entity> wordsToRemove = new ArrayList<>();
for (Entity word : entities) { for (Entity word : entities) {
for (Entity inner : entities) { for (Entity inner : entities) {
// skip cross-type false positives
if(word.getEntityType() == EntityType.FALSE_POSITIVE && inner.getEntityType() == EntityType.ENTITY && !inner.getType().equals(word.getType())){
continue;
}
// skip cross-type false reccommendations
if(word.getEntityType() == EntityType.FALSE_RECOMMENDATION && inner.getEntityType() == EntityType.RECOMMENDATION && !inner.getType().equals(word.getType())){
continue;
}
if (inner.getWord().length() < word.getWord() if (inner.getWord().length() < word.getWord()
.length() && inner.getStart() >= word.getStart() && inner.getEnd() <= word.getEnd() && word != inner && word.getSectionNumber() == inner.getSectionNumber()) { .length() && inner.getStart() >= word.getStart() && inner.getEnd() <= word.getEnd() && word != inner && word.getSectionNumber() == inner.getSectionNumber()) {
if (word.getEntityType().equals(EntityType.RECOMMENDATION) && inner.getEntityType().equals(EntityType.ENTITY)) { if (word.getEntityType().equals(EntityType.RECOMMENDATION) && inner.getEntityType().equals(EntityType.ENTITY)) {
@ -223,6 +234,9 @@ public class EntitySearchUtils {
if (existing.getType().equals(found.getType())) { if (existing.getType().equals(found.getType())) {
existing.getEngines().addAll(found.getEngines()); existing.getEngines().addAll(found.getEngines());
existing.setLegalBasis(found.getLegalBasis());
existing.setMatchedRule(found.getMatchedRule());
existing.setRedactionReason(found.getRedactionReason());
if(existing.getEntityType().equals(EntityType.RECOMMENDATION) && found.getEntityType().equals(EntityType.ENTITY) if(existing.getEntityType().equals(EntityType.RECOMMENDATION) && found.getEntityType().equals(EntityType.ENTITY)
|| existing.getEntityType().equals(EntityType.ENTITY) && found.getEntityType().equals(EntityType.RECOMMENDATION)){ || existing.getEntityType().equals(EntityType.ENTITY) && found.getEntityType().equals(EntityType.RECOMMENDATION)){
existing.setEntityType(EntityType.ENTITY); existing.setEntityType(EntityType.ENTITY);
@ -287,6 +301,9 @@ public class EntitySearchUtils {
} }
var existingEntity = existingOptional.get(); var existingEntity = existingOptional.get();
existingEntity.getEngines().addAll(toAdd.getEngines()); existingEntity.getEngines().addAll(toAdd.getEngines());
existingEntity.setLegalBasis(toAdd.getLegalBasis());
existingEntity.setMatchedRule(toAdd.getMatchedRule());
existingEntity.setRedactionReason(toAdd.getRedactionReason());
} else { } else {
existing.add(toAdd); existing.add(toAdd);
} }

View File

@ -1,5 +1,6 @@
package com.iqser.red.service.redaction.v1.server.storage; package com.iqser.red.service.redaction.v1.server.storage;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -41,7 +42,10 @@ public class RedactionStorageService {
@SneakyThrows @SneakyThrows
public void storeObject(String dossierId, String fileId, FileType fileType, Object any) { public void storeObject(String dossierId, String fileId, FileType fileType, Object any) {
storageService.storeObject(StorageIdUtils.getStorageId(dossierId, fileId, fileType), objectMapper.writeValueAsBytes(any)); try (var baos = new ByteArrayOutputStream()){
objectMapper.writeValue(baos, any);
storageService.storeObject(StorageIdUtils.getStorageId(dossierId, fileId, fileType), baos);
}
} }

View File

@ -7,18 +7,20 @@ import lombok.SneakyThrows;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.springframework.core.io.InputStreamResource; import org.springframework.core.io.InputStreamResource;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.util.HashMap; import java.io.InputStream;
import java.util.Map; import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.GZIPOutputStream;
public class FileSystemBackedStorageService extends S3StorageService { public class FileSystemBackedStorageService implements StorageService{
private final Map<String, File> dataMap = new HashMap<>(); private final Map<String, File> dataMap = new HashMap<>();
public FileSystemBackedStorageService() { public FileSystemBackedStorageService() {
super(null, null);
} }
@SneakyThrows @SneakyThrows
@ -33,16 +35,69 @@ public class FileSystemBackedStorageService extends S3StorageService {
} }
@Override
public void deleteObject(String objectId) {
dataMap.remove(objectId);
}
@Override
public boolean objectExists(String objectId) {
return dataMap.containsKey(objectId);
}
@Override
public void init() {
}
public List<String> listPaths(){
return new ArrayList<>(dataMap.keySet());
}
public List<String> listFilePaths(){
return dataMap.values().stream().map(File::getAbsolutePath).collect(Collectors.toList());
}
@SneakyThrows @SneakyThrows
@Override @Override
public void storeObject(String objectId, byte[] data) { public void storeObject(String objectId, byte[] data) {
File tempFile = File.createTempFile("test", ".tmp"); File tempFile = File.createTempFile("storage", objectId.replace("/","-"));
IOUtils.write(data, new FileOutputStream(tempFile)); try(var fileOutputStream = new FileOutputStream(tempFile)) {
IOUtils.write(data, fileOutputStream);
}
dataMap.put(objectId, tempFile); dataMap.put(objectId, tempFile);
} }
@Override
@SneakyThrows
public void storeObject(String objectId, InputStream stream) {
File tempFile = File.createTempFile("test", ".tmp");
try(var fileOutputStream = new FileOutputStream(tempFile)) {
IOUtils.copy(stream, fileOutputStream);
}
dataMap.put(objectId, tempFile);
}
@Override
@SneakyThrows
public void storeObject(String objectId, ByteArrayOutputStream stream) {
File tempFile = File.createTempFile("test", ".tmp");
try(var fileOutputStream = new FileOutputStream(tempFile)){
stream.writeTo(fileOutputStream);
}
dataMap.put(objectId, tempFile);
}
public void clearStorage() { public void clearStorage() {
this.dataMap.forEach((k, v) -> { this.dataMap.forEach((k, v) -> {
v.delete(); v.delete();