Compare commits
70
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44768045a7 | ||
|
|
75c918acd0 | ||
|
|
44c77685a4 | ||
|
|
9818ca7224 | ||
|
|
bea9abc30c | ||
|
|
8a763edc2b | ||
|
|
b45432d9cd | ||
|
|
7780f5197c | ||
|
|
1431727f0e | ||
|
|
48c100c25a | ||
|
|
8250714e32 | ||
|
|
dc02e58283 | ||
|
|
17fa161d77 | ||
|
|
8709e1645f | ||
|
|
310d864647 | ||
|
|
07d59c6353 | ||
|
|
4900e526fb | ||
|
|
6e4c2f244d | ||
|
|
1b925b3afa | ||
|
|
c49f85916b | ||
|
|
4a0896e24b | ||
|
|
dbf848d37d | ||
|
|
806eeac19e | ||
|
|
77de5770b9 | ||
|
|
0f7cc50e40 | ||
|
|
4e87e188ee | ||
|
|
891bff8536 | ||
|
|
9f01217d3b | ||
|
|
ca04c78724 | ||
|
|
699cad7666 | ||
|
|
46e7c83153 | ||
|
|
b41bbe7406 | ||
|
|
001bdf4774 | ||
|
|
90456602b0 | ||
|
|
ec86a1106b | ||
|
|
7a7733b8e4 | ||
|
|
952a00b19c | ||
|
|
dd585a13fd | ||
|
|
2d305bd6fe | ||
|
|
9650ff75ca | ||
|
|
b2acdc646d | ||
|
|
dc2508d0d0 | ||
|
|
e5099f321e | ||
|
|
de2282bc24 | ||
|
|
b1f73fb5b1 | ||
|
|
fe737108e7 | ||
|
|
fe95224471 | ||
|
|
ff7166ed96 | ||
|
|
30715cdcb8 | ||
|
|
d21ce3f495 | ||
|
|
4bdca5644a | ||
|
|
779f5c725c | ||
|
|
b08cdd3a07 | ||
|
|
af1fb03025 | ||
|
|
a1e9dbb3da | ||
|
|
cf12e58c77 | ||
|
|
77ece8b0d6 | ||
|
|
6c375b5b7a | ||
|
|
289077e5e3 | ||
|
|
2c4c52d891 | ||
|
|
0832ea15c0 | ||
|
|
62f755c416 | ||
|
|
00dd6b9008 | ||
|
|
d5bb55166d | ||
|
|
da14646cb7 | ||
|
|
22531168f0 | ||
|
|
26e73121e9 | ||
|
|
25e5594750 | ||
|
|
d2ffb09987 | ||
|
|
1ac294fc01 |
@@ -93,6 +93,11 @@ public class PlanSpec {
|
||||
.description("Resultparser")
|
||||
.resultDirectories("**/test-reports/*.xml, **/target/surefire-reports/*.xml, **/target/failsafe-reports/*.xml")
|
||||
.enabled(true),
|
||||
new ScriptTask()
|
||||
.description("Sonar")
|
||||
.location(Location.FILE)
|
||||
.fileFromPath("bamboo-specs/src/main/resources/scripts/sonar-java.sh")
|
||||
.argument(SERVICE_NAME),
|
||||
new InjectVariablesTask()
|
||||
.description("Inject git Tag")
|
||||
.path("git.tag")
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
SERVICE_NAME=$1
|
||||
|
||||
echo "dependency-check:aggregate"
|
||||
${bamboo_capability_system_builder_mvn3_Maven_3}/bin/mvn \
|
||||
--no-transfer-progress \
|
||||
-f ${bamboo_build_working_directory}/$SERVICE_NAME-v1/pom.xml \
|
||||
org.owasp:dependency-check-maven:aggregate
|
||||
|
||||
if [[ -z "${bamboo_repository_pr_key}" ]]
|
||||
then
|
||||
echo "Sonar Scan for branch: ${bamboo_planRepository_1_branch}"
|
||||
${bamboo_capability_system_builder_mvn3_Maven_3}/bin/mvn \
|
||||
--no-transfer-progress \
|
||||
-f ${bamboo_build_working_directory}/$SERVICE_NAME-v1/pom.xml \
|
||||
sonar:sonar \
|
||||
-Dsonar.projectKey=RED_$SERVICE_NAME \
|
||||
-Dsonar.host.url=https://sonarqube.iqser.com \
|
||||
-Dsonar.login=${bamboo_sonarqube_api_token_secret} \
|
||||
-Dsonar.branch.name=${bamboo_planRepository_1_branch} \
|
||||
-Dsonar.dependencyCheck.jsonReportPath=target/dependency-check-report.json \
|
||||
-Dsonar.dependencyCheck.xmlReportPath=target/dependency-check-report.xml \
|
||||
-Dsonar.dependencyCheck.htmlReportPath=target/dependency-check-report.html
|
||||
|
||||
else
|
||||
echo "Sonar Scan for PR with key1: ${bamboo_repository_pr_key}"
|
||||
${bamboo_capability_system_builder_mvn3_Maven_3}/bin/mvn \
|
||||
--no-transfer-progress \
|
||||
-f ${bamboo_build_working_directory}/$SERVICE_NAME-v1/pom.xml \
|
||||
sonar:sonar \
|
||||
-Dsonar.projectKey=RED_$SERVICE_NAME \
|
||||
-Dsonar.host.url=https://sonarqube.iqser.com \
|
||||
-Dsonar.login=${bamboo_sonarqube_api_token_secret} \
|
||||
-Dsonar.pullrequest.key=${bamboo_repository_pr_key} \
|
||||
-Dsonar.pullrequest.branch=${bamboo_repository_pr_sourceBranch} \
|
||||
-Dsonar.pullrequest.base=${bamboo_repository_pr_targetBranch} \
|
||||
-Dsonar.dependencyCheck.jsonReportPath=target/dependency-check-report.json \
|
||||
-Dsonar.dependencyCheck.xmlReportPath=target/dependency-check-report.xml \
|
||||
-Dsonar.dependencyCheck.htmlReportPath=target/dependency-check-report.html
|
||||
fi
|
||||
@@ -13,6 +13,7 @@ RUN apt-get update \
|
||||
wget cabextract xfonts-utils fonts-liberation \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN curl http://ftp.br.debian.org/debian/pool/contrib/m/msttcorefonts/ttf-mscorefonts-installer_3.8_all.deb -o /tmp/ttf-mscorefonts-installer_3.8_all.deb \
|
||||
RUN curl http://ftp.debian.org/debian/pool/contrib/m/msttcorefonts/ttf-mscorefonts-installer_3.8_all.deb -o /tmp/ttf-mscorefonts-installer_3.8_all.deb \
|
||||
&& dpkg -i /tmp/ttf-mscorefonts-installer_3.8_all.deb \
|
||||
&& rm /tmp/ttf-mscorefonts-installer_3.8_all.deb \
|
||||
|
||||
|
||||
+6
-3
@@ -7,9 +7,8 @@ import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@Data
|
||||
@@ -24,7 +23,11 @@ public class AnalyzeRequest {
|
||||
private boolean reanalyseOnlyIfPossible;
|
||||
private ManualRedactions manualRedactions;
|
||||
private OffsetDateTime lastProcessed;
|
||||
private Set<Integer> excludedPages;
|
||||
|
||||
@Builder.Default
|
||||
private Set<Integer> excludedPages = new HashSet<>();
|
||||
@Builder.Default
|
||||
private Set<Integer> sectionsToReanalyse = new HashSet<>();
|
||||
|
||||
@Builder.Default
|
||||
private List<FileAttribute> fileAttributes = new ArrayList<>();
|
||||
|
||||
+2
-4
@@ -15,10 +15,6 @@ public class AnalyzeResult {
|
||||
private String fileId;
|
||||
private long duration;
|
||||
private int numberOfPages;
|
||||
private boolean hasHints;
|
||||
private boolean hasRequests;
|
||||
private boolean hasRedactions;
|
||||
private boolean hasImages;
|
||||
private boolean hasUpdates;
|
||||
private long dictionaryVersion;
|
||||
private long dossierDictionaryVersion;
|
||||
@@ -27,6 +23,8 @@ public class AnalyzeResult {
|
||||
|
||||
private boolean wasReanalyzed;
|
||||
|
||||
private int analysisVersion;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -17,6 +17,8 @@ public class ManualLegalBasisChange {
|
||||
private String user;
|
||||
private Status status;
|
||||
private String legalBasis;
|
||||
private String section;
|
||||
private String value;
|
||||
|
||||
private OffsetDateTime requestDate;
|
||||
private OffsetDateTime processedDate;
|
||||
|
||||
+2
-3
@@ -23,11 +23,10 @@ public class ManualRedactionEntry {
|
||||
private String legalBasis;
|
||||
private List<Rectangle> positions = new ArrayList<>();
|
||||
private Status status;
|
||||
private boolean addToDictionary;
|
||||
|
||||
private String section;
|
||||
private int sectionNumber;
|
||||
private boolean rectangle;
|
||||
|
||||
private boolean addToDictionary;
|
||||
private boolean addToDossierDictionary;
|
||||
|
||||
private OffsetDateTime requestDate;
|
||||
|
||||
+7
@@ -10,6 +10,13 @@ import java.util.List;
|
||||
@AllArgsConstructor
|
||||
public class RedactionLog {
|
||||
|
||||
|
||||
/**
|
||||
* Version 0 Redaction Logs have manual redactions merged inside them
|
||||
* Version 1 Redaction Logs only contain system ( rule/dictionary ) redactions. Manual Redactions are merged in at runtime.
|
||||
*/
|
||||
private long analysisVersion;
|
||||
|
||||
private List<RedactionLogEntry> redactionLogEntry;
|
||||
private List<LegalBasisMapping> legalBasis;
|
||||
|
||||
|
||||
+9
@@ -9,6 +9,8 @@ import lombok.NoArgsConstructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@@ -20,6 +22,7 @@ public class RedactionLogEntry {
|
||||
private String type;
|
||||
private String value;
|
||||
private String reason;
|
||||
private boolean rectangle;
|
||||
private int matchedRule;
|
||||
private String legalBasis;
|
||||
private boolean redacted;
|
||||
@@ -28,12 +31,18 @@ public class RedactionLogEntry {
|
||||
private String section;
|
||||
private float[] color;
|
||||
|
||||
private boolean hasBeenRecategorized;
|
||||
private boolean hasLegalBasisChanged;
|
||||
private boolean hasBeenForced;
|
||||
private boolean hasBeenRemovedByManualOverride;
|
||||
|
||||
@Builder.Default
|
||||
private List<Rectangle> positions = new ArrayList<>();
|
||||
private int sectionNumber;
|
||||
private boolean manual;
|
||||
private Status status;
|
||||
private ManualRedactionType manualRedactionType;
|
||||
private String manualRedactionUserId;
|
||||
private boolean isDictionaryEntry;
|
||||
|
||||
private String textBefore;
|
||||
|
||||
+7
@@ -1,5 +1,8 @@
|
||||
package com.iqser.red.service.redaction.v1.model;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@@ -15,4 +18,8 @@ public class RedactionRequest {
|
||||
private String fileId;
|
||||
private String dossierTemplateId;
|
||||
private ManualRedactions manualRedactions;
|
||||
@Builder.Default
|
||||
private Set<Integer> excludedPages = new HashSet<>();
|
||||
|
||||
private boolean withSectionDataForManualRedactions;
|
||||
}
|
||||
|
||||
+5
-1
@@ -27,7 +27,11 @@ public class SectionArea {
|
||||
private String header;
|
||||
|
||||
public boolean contains(Rectangle other) {
|
||||
return page == other.getPage() && this.topLeft.getX() <= other.getTopLeft().getX() && this.topLeft.getX() + this.getWidth() >= other.getTopLeft().getX() + other.getWidth() && this.getTopLeft().getY() <= other.getTopLeft().getY() && this.getTopLeft().getY() + this.getHeight() >= other.getTopLeft().getY() + other.getHeight();
|
||||
return page == other.getPage()
|
||||
&& topLeft.getX() <= other.getTopLeft().getX()
|
||||
&& topLeft.getX() + getWidth() >= other.getTopLeft().getX() + other.getWidth()
|
||||
&& getTopLeft().getY() <= other.getTopLeft().getY()
|
||||
&& getTopLeft().getY() + getHeight() >= other.getTopLeft().getY() + other.getHeight();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+14
-3
@@ -3,10 +3,9 @@ package com.iqser.red.service.redaction.v1.model;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@@ -15,4 +14,16 @@ public class SectionGrid {
|
||||
|
||||
private Map<Integer, List<SectionRectangle>> rectanglesPerPage = new HashMap<>();
|
||||
|
||||
private List<SectionGridSection> sections = new ArrayList<>();
|
||||
|
||||
@Data
|
||||
@RequiredArgsConstructor
|
||||
public static class SectionGridSection {
|
||||
|
||||
private final int sectionNumber;
|
||||
private final String headline;
|
||||
private final Set<Integer> pages;
|
||||
private final List<SectionArea> sectionAreas;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+9
-5
@@ -1,10 +1,6 @@
|
||||
package com.iqser.red.service.redaction.v1.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -30,4 +26,12 @@ public class SectionRectangle {
|
||||
private int numberOfParts;
|
||||
|
||||
private List<CellRectangle> tableCells;
|
||||
|
||||
public boolean contains(Rectangle other) {
|
||||
return topLeft.getX() <= other.getTopLeft().getX()
|
||||
&& topLeft.getX() + getWidth() >= other.getTopLeft().getX() + other.getWidth()
|
||||
&& getTopLeft().getY() <= other.getTopLeft().getY()
|
||||
&& getTopLeft().getY() + getHeight() >= other.getTopLeft().getY() + other.getHeight();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+1
-8
@@ -8,10 +8,6 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
public interface RedactionResource {
|
||||
|
||||
String RULE_SET_PARAMETER_NAME = "dossierTemplateId";
|
||||
String RULE_SET_PATH_VARIABLE = "/{" + RULE_SET_PARAMETER_NAME + "}";
|
||||
|
||||
|
||||
@PostMapping(value = "/annotate", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
AnnotateResponse annotate(@RequestBody AnnotateRequest annotateRequest);
|
||||
|
||||
@@ -24,13 +20,10 @@ public interface RedactionResource {
|
||||
@PostMapping(value = "/debug/htmlTables", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
RedactionResult htmlTables(@RequestBody RedactionRequest redactionRequest);
|
||||
|
||||
@PostMapping(value = "/rules/update" + RULE_SET_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
void updateRules(@PathVariable(RULE_SET_PARAMETER_NAME) String dossierTemplateId);
|
||||
|
||||
@PostMapping(value = "/rules/test", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
void testRules(@RequestBody String rules);
|
||||
|
||||
@PostMapping(value = "/redaction-log/preview", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
RedactionLog getRedactionLogPreview(@RequestBody RedactionRequest redactionRequest);
|
||||
RedactionLog getRedactionLog(@RequestBody RedactionRequest redactionRequest);
|
||||
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<dependency>
|
||||
<groupId>com.iqser.red.service</groupId>
|
||||
<artifactId>file-management-service-api-v1</artifactId>
|
||||
<version>2.25.0</version>
|
||||
<version>2.80.15</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.iqser.red.service</groupId>
|
||||
|
||||
+56
-18
@@ -1,5 +1,7 @@
|
||||
package com.iqser.red.service.redaction.v1.server.classification.service;
|
||||
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
|
||||
import com.iqser.red.service.redaction.v1.server.classification.model.FloatFrequencyCounter;
|
||||
import com.iqser.red.service.redaction.v1.server.classification.model.Orientation;
|
||||
import com.iqser.red.service.redaction.v1.server.classification.model.Page;
|
||||
@@ -16,6 +18,7 @@ import com.iqser.red.service.redaction.v1.server.tableextraction.model.Table;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
@@ -25,9 +28,12 @@ public class BlockificationService {
|
||||
|
||||
static final float THRESHOLD = 1f;
|
||||
|
||||
|
||||
public Page blockify(List<TextPositionSequence> textPositions, List<Ruling> horizontalRulingLines,
|
||||
List<Ruling> verticalRulingLines) {
|
||||
|
||||
sortRotatedSequences(textPositions);
|
||||
|
||||
List<TextPositionSequence> chunkWords = new ArrayList<>();
|
||||
List<AbstractTextContainer> chunkBlockList1 = new ArrayList<>();
|
||||
|
||||
@@ -50,7 +56,7 @@ public class BlockificationService {
|
||||
if (prev != null && (lineSeparation || startFromTop || splitByX || newLineAfterSplit || splittedByRuling)) {
|
||||
|
||||
Orientation prevOrientation = null;
|
||||
if(!chunkBlockList1.isEmpty()) {
|
||||
if (!chunkBlockList1.isEmpty()) {
|
||||
prevOrientation = chunkBlockList1.get(chunkBlockList1.size() - 1).getOrientation();
|
||||
}
|
||||
|
||||
@@ -62,15 +68,11 @@ public class BlockificationService {
|
||||
wasSplitted = true;
|
||||
cb1.setOrientation(Orientation.LEFT);
|
||||
splitX1 = word.getX1();
|
||||
} else
|
||||
|
||||
if (newLineAfterSplit && !splittedByRuling) {
|
||||
} else if (newLineAfterSplit && !splittedByRuling) {
|
||||
wasSplitted = false;
|
||||
cb1.setOrientation(Orientation.RIGHT);
|
||||
splitX1 = null;
|
||||
} else
|
||||
|
||||
if(prevOrientation != null && prevOrientation.equals(Orientation.RIGHT) && (lineSeparation || !startFromTop || !splitByX || !newLineAfterSplit || !splittedByRuling)){
|
||||
} else if (prevOrientation != null && prevOrientation.equals(Orientation.RIGHT) && (lineSeparation || !startFromTop || !splitByX || !newLineAfterSplit || !splittedByRuling)) {
|
||||
cb1.setOrientation(Orientation.LEFT);
|
||||
}
|
||||
|
||||
@@ -110,16 +112,18 @@ public class BlockificationService {
|
||||
while (itty.hasNext()) {
|
||||
TextBlock block = (TextBlock) itty.next();
|
||||
|
||||
if(previousLeft != null && block.getOrientation().equals(Orientation.LEFT)){
|
||||
if (previousLeft.getMinY() > block.getMinY() && block.getMaxY() + block.getMostPopularWordHeight() > previousLeft.getMinY()){
|
||||
if (previousLeft != null && block.getOrientation().equals(Orientation.LEFT)) {
|
||||
if (previousLeft.getMinY() > block.getMinY() && block.getMaxY() + block.getMostPopularWordHeight() > previousLeft
|
||||
.getMinY()) {
|
||||
previousLeft.add(block);
|
||||
itty.remove();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(previousRight != null && block.getOrientation().equals(Orientation.RIGHT)){
|
||||
if (previousRight.getMinY() > block.getMinY() && block.getMaxY() + block.getMostPopularWordHeight() > previousRight.getMinY()){
|
||||
if (previousRight != null && block.getOrientation().equals(Orientation.RIGHT)) {
|
||||
if (previousRight.getMinY() > block.getMinY() && block.getMaxY() + block.getMostPopularWordHeight() > previousRight
|
||||
.getMinY()) {
|
||||
previousRight.add(block);
|
||||
itty.remove();
|
||||
continue;
|
||||
@@ -133,16 +137,16 @@ public class BlockificationService {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
itty = chunkBlockList1.iterator();
|
||||
TextBlock previous = null;
|
||||
while (itty.hasNext()) {
|
||||
TextBlock block = (TextBlock) itty.next();
|
||||
|
||||
if(previous != null && previous.getOrientation().equals(Orientation.LEFT) && block.getOrientation().equals(Orientation.LEFT) && equalsWithThreshold(block.getMaxY(), previous
|
||||
.getMaxY())||
|
||||
previous != null && previous.getOrientation().equals(Orientation.LEFT) && block.getOrientation().equals(Orientation.RIGHT) && equalsWithThreshold(block.getMaxY(), previous
|
||||
.getMaxY())){
|
||||
if (previous != null && previous.getOrientation().equals(Orientation.LEFT) && block.getOrientation()
|
||||
.equals(Orientation.LEFT) && equalsWithThreshold(block.getMaxY(), previous.getMaxY()) || previous != null && previous
|
||||
.getOrientation()
|
||||
.equals(Orientation.LEFT) && block.getOrientation()
|
||||
.equals(Orientation.RIGHT) && equalsWithThreshold(block.getMaxY(), previous.getMaxY())) {
|
||||
previous.add(block);
|
||||
itty.remove();
|
||||
continue;
|
||||
@@ -151,11 +155,12 @@ public class BlockificationService {
|
||||
previous = block;
|
||||
}
|
||||
|
||||
|
||||
return new Page(chunkBlockList1);
|
||||
}
|
||||
|
||||
private boolean equalsWithThreshold(float f1, float f2){
|
||||
|
||||
private boolean equalsWithThreshold(float f1, float f2) {
|
||||
|
||||
return Math.abs(f1 - f2) < THRESHOLD;
|
||||
}
|
||||
|
||||
@@ -197,6 +202,13 @@ public class BlockificationService {
|
||||
textBlock.setHighestFontSize(fontSizeFrequencyCounter.getHighest());
|
||||
}
|
||||
|
||||
if (textBlock != null && textBlock.getSequences() != null && textBlock.getSequences()
|
||||
.stream()
|
||||
.map(t -> round(t.getY1(), 3))
|
||||
.collect(toSet())
|
||||
.size() == 1) {
|
||||
textBlock.getSequences().sort(Comparator.comparing(TextPositionSequence::getX1));
|
||||
}
|
||||
return textBlock;
|
||||
}
|
||||
|
||||
@@ -291,4 +303,30 @@ public class BlockificationService {
|
||||
return new Rectangle(minY, minX, maxX - minX, maxY - minY);
|
||||
}
|
||||
|
||||
|
||||
private void sortRotatedSequences(List<TextPositionSequence> sequences) {
|
||||
|
||||
List<TextPositionSequence> rotatedWords = new ArrayList<>();
|
||||
Iterator<TextPositionSequence> itty = sequences.iterator();
|
||||
while (itty.hasNext()) {
|
||||
var pos = itty.next();
|
||||
if (pos.getTextPositions().get(0).getDir() == 270) {
|
||||
rotatedWords.add(pos);
|
||||
itty.remove();
|
||||
}
|
||||
}
|
||||
|
||||
if (!rotatedWords.isEmpty() && !sequences.isEmpty()) {
|
||||
rotatedWords.sort(Comparator.comparing(TextPositionSequence::getX1));
|
||||
}
|
||||
sequences.addAll(rotatedWords);
|
||||
}
|
||||
|
||||
|
||||
private double round(float value, int decimalPoints) {
|
||||
|
||||
var d = Math.pow(10, decimalPoints);
|
||||
return Math.round(value * d) / d;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-3
@@ -73,8 +73,10 @@ public class ClassificationService {
|
||||
}
|
||||
} else if (PositionUtils.isWithinBodyTextFrame(bodyTextFrame, textBlock) && textBlock.getMostPopularWordFontSize() > document
|
||||
.getFontSizeCounter()
|
||||
.getMostPopular() && PositionUtils.getApproxLineCount(textBlock) < 4.9 && textBlock.getMostPopularWordStyle()
|
||||
.equals("bold")) {
|
||||
.getMostPopular() && PositionUtils.getApproxLineCount(textBlock) < 4.9 && (textBlock.getMostPopularWordStyle()
|
||||
.equals("bold") || !document.getFontStyleCounter().getCountPerValue().containsKey("bold") && textBlock.getMostPopularWordFontSize() > document
|
||||
.getFontSizeCounter()
|
||||
.getMostPopular() + 1) && textBlock.getSequences().get(0).getTextPositions().get(0).getFontSizeInPt() >= textBlock.getMostPopularWordFontSize()) {
|
||||
|
||||
for (int i = 1; i <= headlineFontSizes.size(); i++) {
|
||||
if (textBlock.getMostPopularWordFontSize() == headlineFontSizes.get(i - 1)) {
|
||||
@@ -86,7 +88,7 @@ public class ClassificationService {
|
||||
.startsWith("Figure ") && PositionUtils.isWithinBodyTextFrame(bodyTextFrame, textBlock) && textBlock.getMostPopularWordStyle()
|
||||
.equals("bold") && !document.getFontStyleCounter()
|
||||
.getMostPopular()
|
||||
.equals("bold") && PositionUtils.getApproxLineCount(textBlock) < 2.9) {
|
||||
.equals("bold") && PositionUtils.getApproxLineCount(textBlock) < 2.9 && textBlock.getSequences().get(0).getTextPositions().get(0).getFontSizeInPt() >= textBlock.getMostPopularWordFontSize()) {
|
||||
textBlock.setClassification("H " + (headlineFontSizes.size() + 1));
|
||||
document.setHeadlines(true);
|
||||
} else if (PositionUtils.isWithinBodyTextFrame(bodyTextFrame, textBlock) && textBlock.getMostPopularWordFontSize() == document
|
||||
|
||||
+8
@@ -1,6 +1,7 @@
|
||||
package com.iqser.red.service.redaction.v1.server.controller;
|
||||
|
||||
import com.iqser.red.commons.spring.ErrorMessage;
|
||||
import com.iqser.red.service.redaction.v1.server.exception.RedactionLogNotFoundException;
|
||||
import com.iqser.red.service.redaction.v1.server.exception.RulesValidationException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -17,6 +18,13 @@ public class ControllerAdvice {
|
||||
|
||||
/* error handling */
|
||||
|
||||
@ResponseBody
|
||||
@ResponseStatus(value = HttpStatus.NOT_FOUND)
|
||||
@ExceptionHandler(value = RedactionLogNotFoundException.class)
|
||||
public ErrorMessage handleRedactionLogNotFoundException(RedactionLogNotFoundException e) {
|
||||
return new ErrorMessage(OffsetDateTime.now(), e.getMessage());
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
@ExceptionHandler(value = NullPointerException.class)
|
||||
|
||||
+39
-19
@@ -1,19 +1,16 @@
|
||||
package com.iqser.red.service.redaction.v1.server.controller;
|
||||
|
||||
import com.iqser.red.service.file.management.v1.api.model.FileType;
|
||||
import com.iqser.red.service.redaction.v1.model.AnnotateRequest;
|
||||
import com.iqser.red.service.redaction.v1.model.AnnotateResponse;
|
||||
import com.iqser.red.service.redaction.v1.model.RedactionLog;
|
||||
import com.iqser.red.service.redaction.v1.model.RedactionRequest;
|
||||
import com.iqser.red.service.redaction.v1.model.RedactionResult;
|
||||
import com.iqser.red.service.redaction.v1.model.*;
|
||||
import com.iqser.red.service.redaction.v1.resources.RedactionResource;
|
||||
import com.iqser.red.service.redaction.v1.server.classification.model.Document;
|
||||
import com.iqser.red.service.redaction.v1.server.classification.model.Page;
|
||||
import com.iqser.red.service.redaction.v1.server.exception.RedactionException;
|
||||
import com.iqser.red.service.redaction.v1.server.exception.RedactionLogNotFoundException;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.service.AnnotationService;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.service.DictionaryService;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.service.DroolsExecutionService;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.service.RedactionLogCreatorService;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.service.RedactionLogMergeService;
|
||||
import com.iqser.red.service.redaction.v1.server.segmentation.PdfSegmentationService;
|
||||
import com.iqser.red.service.redaction.v1.server.storage.RedactionStorageService;
|
||||
import com.iqser.red.service.redaction.v1.server.tableextraction.model.AbstractTextContainer;
|
||||
@@ -23,12 +20,12 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.pdfbox.io.MemoryUsageSetting;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@@ -41,7 +38,7 @@ public class RedactionController implements RedactionResource {
|
||||
private final AnnotationService annotationService;
|
||||
private final PdfSegmentationService pdfSegmentationService;
|
||||
private final RedactionStorageService redactionStorageService;
|
||||
private final RedactionLogCreatorService redactionLogCreatorService;
|
||||
private final RedactionLogMergeService redactionLogMergeService;
|
||||
|
||||
public AnnotateResponse annotate(@RequestBody AnnotateRequest annotateRequest) {
|
||||
|
||||
@@ -143,14 +140,6 @@ public class RedactionController implements RedactionResource {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateRules(@PathVariable(RULE_SET_PARAMETER_NAME) String dossierTemplateId) {
|
||||
|
||||
droolsExecutionService.updateRules(dossierTemplateId);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void testRules(@RequestBody String rules) {
|
||||
|
||||
@@ -158,15 +147,46 @@ public class RedactionController implements RedactionResource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RedactionLog getRedactionLogPreview(RedactionRequest redactionRequest) {
|
||||
public RedactionLog getRedactionLog(@RequestBody RedactionRequest redactionRequest) {
|
||||
|
||||
log.info("Requested preview for: {}", redactionRequest);
|
||||
dictionaryService.updateDictionary(redactionRequest.getDossierTemplateId(), redactionRequest.getDossierId());
|
||||
|
||||
SectionGrid sectionGrid = null;
|
||||
var redactionLog = redactionStorageService.getRedactionLog(redactionRequest.getDossierId(), redactionRequest.getFileId());
|
||||
return redactionLogCreatorService.getRedactionLogPreview(redactionLog, redactionRequest.getDossierTemplateId(), redactionRequest.getManualRedactions());
|
||||
}
|
||||
|
||||
if (redactionLog == null) {
|
||||
throw new RedactionLogNotFoundException();
|
||||
}
|
||||
|
||||
|
||||
if (redactionRequest.isWithSectionDataForManualRedactions()) {
|
||||
sectionGrid = redactionStorageService.getSectionGrid(redactionRequest.getDossierId(), redactionRequest.getFileId());
|
||||
if (sectionGrid.getSections().isEmpty()) {
|
||||
|
||||
log.info("SectionGrid does not have headlines set. Computing headlines now!");
|
||||
var text = redactionStorageService.getText(redactionRequest.getDossierId(), redactionRequest.getFileId());
|
||||
|
||||
// enhance section grid with headline data
|
||||
for (var sectionText : text.getSectionTexts()) {
|
||||
sectionGrid.getSections().add(new SectionGrid.SectionGridSection(sectionText.getSectionNumber(),
|
||||
sectionText.getHeadline(),
|
||||
sectionText.getSectionAreas().stream().map(SectionArea::getPage).collect(Collectors.toSet()),
|
||||
sectionText.getSectionAreas()));
|
||||
}
|
||||
redactionStorageService.storeObject(redactionRequest.getDossierId(), redactionRequest.getFileId(), FileType.SECTION_GRID, sectionGrid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
log.info("Loaded redaction log with computationalVersion: {}", redactionLog.getAnalysisVersion());
|
||||
if (redactionLog.getAnalysisVersion() == 0) {
|
||||
// old redaction logs are returned directly
|
||||
return redactionLog;
|
||||
} else {
|
||||
return redactionLogMergeService.mergeRedactionLogData(redactionLog, sectionGrid, redactionRequest.getDossierTemplateId(), redactionRequest.getManualRedactions(), redactionRequest.getExcludedPages());
|
||||
}
|
||||
}
|
||||
|
||||
private RedactionResult convert(PDDocument document, int numberOfPages) throws IOException {
|
||||
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.iqser.red.service.redaction.v1.server.exception;
|
||||
|
||||
public class RedactionLogNotFoundException extends RuntimeException {
|
||||
|
||||
public RedactionLogNotFoundException() {
|
||||
super("RedactionLog not found!");
|
||||
}
|
||||
|
||||
}
|
||||
+82
-32
@@ -1,16 +1,33 @@
|
||||
package com.iqser.red.service.redaction.v1.server.parsing;
|
||||
|
||||
import com.iqser.red.service.redaction.v1.server.parsing.model.TextPositionSequence;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.model.PdfImage;
|
||||
import com.iqser.red.service.redaction.v1.server.tableextraction.model.Ruling;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||
import org.apache.pdfbox.contentstream.operator.Operator;
|
||||
import org.apache.pdfbox.contentstream.operator.OperatorName;
|
||||
import org.apache.pdfbox.contentstream.operator.color.*;
|
||||
import org.apache.pdfbox.contentstream.operator.state.*;
|
||||
import org.apache.pdfbox.contentstream.operator.color.SetNonStrokingColor;
|
||||
import org.apache.pdfbox.contentstream.operator.color.SetNonStrokingColorN;
|
||||
import org.apache.pdfbox.contentstream.operator.color.SetNonStrokingColorSpace;
|
||||
import org.apache.pdfbox.contentstream.operator.color.SetNonStrokingDeviceCMYKColor;
|
||||
import org.apache.pdfbox.contentstream.operator.color.SetNonStrokingDeviceGrayColor;
|
||||
import org.apache.pdfbox.contentstream.operator.color.SetNonStrokingDeviceRGBColor;
|
||||
import org.apache.pdfbox.contentstream.operator.color.SetStrokingColor;
|
||||
import org.apache.pdfbox.contentstream.operator.color.SetStrokingColorN;
|
||||
import org.apache.pdfbox.contentstream.operator.color.SetStrokingColorSpace;
|
||||
import org.apache.pdfbox.contentstream.operator.color.SetStrokingDeviceCMYKColor;
|
||||
import org.apache.pdfbox.contentstream.operator.color.SetStrokingDeviceGrayColor;
|
||||
import org.apache.pdfbox.contentstream.operator.color.SetStrokingDeviceRGBColor;
|
||||
import org.apache.pdfbox.contentstream.operator.state.SetFlatness;
|
||||
import org.apache.pdfbox.contentstream.operator.state.SetLineCapStyle;
|
||||
import org.apache.pdfbox.contentstream.operator.state.SetLineDashPattern;
|
||||
import org.apache.pdfbox.contentstream.operator.state.SetLineJoinStyle;
|
||||
import org.apache.pdfbox.contentstream.operator.state.SetLineMiterLimit;
|
||||
import org.apache.pdfbox.contentstream.operator.state.SetLineWidth;
|
||||
import org.apache.pdfbox.contentstream.operator.state.SetRenderingIntent;
|
||||
import org.apache.pdfbox.contentstream.operator.text.SetFontAndSize;
|
||||
import org.apache.pdfbox.cos.COSBase;
|
||||
import org.apache.pdfbox.cos.COSName;
|
||||
@@ -23,12 +40,14 @@ import org.apache.pdfbox.text.PDFTextStripper;
|
||||
import org.apache.pdfbox.text.TextPosition;
|
||||
import org.apache.pdfbox.util.Matrix;
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.iqser.red.service.redaction.v1.server.parsing.model.RedTextPosition;
|
||||
import com.iqser.red.service.redaction.v1.server.parsing.model.TextPositionSequence;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.model.PdfImage;
|
||||
import com.iqser.red.service.redaction.v1.server.tableextraction.model.Ruling;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class PDFLinesTextStripper extends PDFTextStripper {
|
||||
@@ -189,16 +208,19 @@ public class PDFLinesTextStripper extends PDFTextStripper {
|
||||
COSName objectName = (COSName) arguments.get(0);
|
||||
PDXObject xobject = getResources().getXObject(objectName);
|
||||
if (xobject instanceof PDImageXObject) {
|
||||
PDImageXObject image = (PDImageXObject)xobject;
|
||||
PDImageXObject image = (PDImageXObject) xobject;
|
||||
Matrix ctmNew = getGraphicsState().getCurrentTransformationMatrix();
|
||||
|
||||
Rectangle2D rect = new Rectangle2D.Float(ctmNew.getTranslateX(), ctmNew.getTranslateY(), ctmNew.getScaleX(), ctmNew.getScaleY());
|
||||
Rectangle2D rect = new Rectangle2D.Float(ctmNew.getTranslateX(), ctmNew.getTranslateY(), ctmNew.getScaleX(), ctmNew
|
||||
.getScaleY());
|
||||
|
||||
// Memory Hack - sofReference kills me
|
||||
FieldUtils.writeField(image, "cachedImageSubsampling", -1, true);
|
||||
|
||||
if (rect.getHeight() > 2 && rect.getWidth() > 2) {
|
||||
this.images.add(new PdfImage(image.getImage(), rect, pageNumber, image.getImage().getColorModel().hasAlpha()));
|
||||
this.images.add(new PdfImage(image.getImage(), rect, pageNumber, image.getImage()
|
||||
.getColorModel()
|
||||
.hasAlpha()));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@@ -207,8 +229,6 @@ public class PDFLinesTextStripper extends PDFTextStripper {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private float floatValue(COSBase value) {
|
||||
|
||||
if (value instanceof COSNumber) {
|
||||
@@ -247,8 +267,16 @@ public class PDFLinesTextStripper extends PDFTextStripper {
|
||||
public void writeString(String text, List<TextPosition> textPositions) throws IOException {
|
||||
|
||||
int startIndex = 0;
|
||||
RedTextPosition previous = null;
|
||||
|
||||
for (int i = 0; i <= textPositions.size() - 1; i++) {
|
||||
|
||||
if (!textPositionSequences.isEmpty()) {
|
||||
previous = textPositionSequences.get(textPositionSequences.size() - 1)
|
||||
.getTextPositions()
|
||||
.get(textPositionSequences.get(textPositionSequences.size() - 1).getTextPositions().size() - 1);
|
||||
}
|
||||
|
||||
int charWidth = (int) textPositions.get(i).getWidthDirAdj();
|
||||
if (charWidth < minCharWidth) {
|
||||
minCharWidth = charWidth;
|
||||
@@ -267,42 +295,54 @@ public class PDFLinesTextStripper extends PDFTextStripper {
|
||||
|
||||
if (i == 0 && (textPositions.get(i).getUnicode().equals(" ") || textPositions.get(i)
|
||||
.getUnicode()
|
||||
.equals("\u00A0"))) {
|
||||
.equals("\u00A0") || textPositions.get(i)
|
||||
.getUnicode()
|
||||
.equals("\t"))) {
|
||||
startIndex++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Strange but sometimes this is happening, for example: Metolachlor2.pdf
|
||||
if (i > 0 && textPositions.get(i).getX() < textPositions.get(i - 1).getX()) {
|
||||
if (i > 0 && textPositions.get(i).getXDirAdj() < textPositions.get(i - 1).getXDirAdj()) {
|
||||
List<TextPosition> sublist = textPositions.subList(startIndex, i);
|
||||
if (!(sublist.isEmpty() || sublist.size() == 1 && (sublist.get(0)
|
||||
.getUnicode()
|
||||
.equals(" ") || sublist.get(0).getUnicode().equals("\u00A0")))) {
|
||||
.equals(" ") || sublist.get(0).getUnicode().equals("\u00A0") || sublist.get(0).getUnicode().equals("\t")))) {
|
||||
textPositionSequences.add(new TextPositionSequence(sublist, pageNumber));
|
||||
}
|
||||
startIndex = i;
|
||||
}
|
||||
|
||||
|
||||
if (textPositions.get(i).getRotation() == 0 && i > 0 && textPositions.get(i).getX() > textPositions.get(i - 1).getEndX() + 1) {
|
||||
if (textPositions.get(i).getRotation() == 0 && i > 0 && textPositions.get(i)
|
||||
.getX() > textPositions.get(i - 1).getEndX() + 1) {
|
||||
List<TextPosition> sublist = textPositions.subList(startIndex, i);
|
||||
if (!(sublist.isEmpty() || sublist.size() == 1 && (sublist.get(0)
|
||||
.getUnicode()
|
||||
.equals(" ") || sublist.get(0).getUnicode().equals("\u00A0")))) {
|
||||
.equals(" ") || sublist.get(0).getUnicode().equals("\u00A0") || sublist.get(0).getUnicode().equals("\t")))) {
|
||||
textPositionSequences.add(new TextPositionSequence(sublist, pageNumber));
|
||||
}
|
||||
startIndex = i;
|
||||
}
|
||||
|
||||
|
||||
if (i > 0 && (textPositions.get(i).getUnicode().equals(" ") || textPositions.get(i)
|
||||
.getUnicode()
|
||||
.equals("\u00A0")) && i <= textPositions.size() - 2) {
|
||||
.equals("\u00A0") || textPositions.get(i)
|
||||
.getUnicode()
|
||||
.equals("\t")) && i <= textPositions.size() - 2) {
|
||||
List<TextPosition> sublist = textPositions.subList(startIndex, i);
|
||||
if (!(sublist.isEmpty() || sublist.size() == 1 && (sublist.get(0)
|
||||
.getUnicode()
|
||||
.equals(" ") || sublist.get(0).getUnicode().equals("\u00A0")))) {
|
||||
textPositionSequences.add(new TextPositionSequence(sublist, pageNumber));
|
||||
.equals(" ") || sublist.get(0).getUnicode().equals("\u00A0") || sublist.get(0).getUnicode().equals("\t")))) {
|
||||
|
||||
// Remove false sequence ends (whitespaces)
|
||||
if (previous != null && sublist.get(0).getYDirAdj() == previous.getYDirAdj() && sublist.get(0)
|
||||
.getXDirAdj() - (previous.getXDirAdj() + previous.getWidthDirAdj()) < 0.01) {
|
||||
for (TextPosition t : sublist) {
|
||||
textPositionSequences.get(textPositionSequences.size() - 1).add(t);
|
||||
}
|
||||
} else {
|
||||
textPositionSequences.add(new TextPositionSequence(sublist, pageNumber));
|
||||
}
|
||||
}
|
||||
startIndex = i + 1;
|
||||
}
|
||||
@@ -311,13 +351,23 @@ public class PDFLinesTextStripper extends PDFTextStripper {
|
||||
List<TextPosition> sublist = textPositions.subList(startIndex, textPositions.size());
|
||||
if (!sublist.isEmpty() && (sublist.get(sublist.size() - 1)
|
||||
.getUnicode()
|
||||
.equals(" ") || sublist.get(sublist.size() - 1).getUnicode().equals("\u00A0"))) {
|
||||
.equals(" ") || sublist.get(sublist.size() - 1).getUnicode().equals("\u00A0") || sublist.get(sublist.size() - 1).getUnicode().equals("\t"))) {
|
||||
sublist = sublist.subList(0, sublist.size() - 1);
|
||||
}
|
||||
|
||||
if (!(sublist.isEmpty() || sublist.size() == 1 && (sublist.get(0).getUnicode().equals(" ") || sublist.get(0)
|
||||
.getUnicode()
|
||||
.equals("\u00A0")))) {
|
||||
textPositionSequences.add(new TextPositionSequence(sublist, pageNumber));
|
||||
.equals("\u00A0") || sublist.get(0)
|
||||
.getUnicode()
|
||||
.equals("\t")))) {
|
||||
if (previous != null && sublist.get(0).getYDirAdj() == previous.getYDirAdj() && sublist.get(0)
|
||||
.getXDirAdj() - (previous.getXDirAdj() + previous.getWidthDirAdj()) < 0.01) {
|
||||
for (TextPosition t : sublist) {
|
||||
textPositionSequences.get(textPositionSequences.size() - 1).add(t);
|
||||
}
|
||||
} else {
|
||||
textPositionSequences.add(new TextPositionSequence(sublist, pageNumber));
|
||||
}
|
||||
}
|
||||
super.writeString(text);
|
||||
}
|
||||
|
||||
+2
@@ -21,6 +21,8 @@ public class RedTextPosition {
|
||||
private float YDirAdj;
|
||||
private float width;
|
||||
private float heightDir;
|
||||
private float widthDirAdj;
|
||||
private float dir;
|
||||
|
||||
// not used in reanalysis
|
||||
@JsonIgnore
|
||||
|
||||
+34
-3
@@ -1,5 +1,7 @@
|
||||
package com.iqser.red.service.redaction.v1.server.parsing.model;
|
||||
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.iqser.red.service.redaction.v1.model.Point;
|
||||
@@ -136,6 +138,13 @@ public class TextPositionSequence implements CharSequence {
|
||||
}
|
||||
|
||||
|
||||
@JsonIgnore
|
||||
public float getRotationAdjustedX() {
|
||||
|
||||
return textPositions.get(0).getXDirAdj();
|
||||
}
|
||||
|
||||
|
||||
@JsonIgnore
|
||||
public float getY1() {
|
||||
|
||||
@@ -233,7 +242,7 @@ public class TextPositionSequence implements CharSequence {
|
||||
float posYInit;
|
||||
float posYEnd;
|
||||
|
||||
if (textPositions.get(0).getRotation() == 90) {
|
||||
if (textPositions.get(0).getRotation() == 90 && textPositions.get(0).getDir() != 0.0f) {
|
||||
posXEnd = textPositions.get(0).getYDirAdj() + 2;
|
||||
posYInit = getY1();
|
||||
posYEnd = textPositions.get(textPositions.size() - 1).getXDirAdj() - height + 4;
|
||||
@@ -244,9 +253,31 @@ public class TextPositionSequence implements CharSequence {
|
||||
posXInit = textPositions.get(0).getPageWidth() - textPositions.get(0).getYDirAdj() - 2;
|
||||
posXEnd = textPositions.get(0).getPageWidth() - textPositions.get(textPositions.size() - 1)
|
||||
.getYDirAdj() + height;
|
||||
} else {
|
||||
} else if(textPositions.get(0).getRotation() == 0 && textPositions.get(0).getDir() == 270f) {
|
||||
posYInit = textPositions.get(0).getPageHeight() - getX1();
|
||||
posYEnd = textPositions.get(0).getPageHeight() - getX2() - textPositions.get(0)
|
||||
.getWidthDirAdj() - textPositions.get(textPositions.size() - 1).getWidthDirAdj() - 3;
|
||||
posXInit = textPositions.get(0).getPageWidth() - textPositions.get(0).getYDirAdj() - 2;
|
||||
posXEnd = textPositions.get(0).getPageWidth() - textPositions.get(textPositions.size() - 1)
|
||||
.getYDirAdj() + height;
|
||||
} else if(textPositions.get(0).getRotation() == 90 && textPositions.get(0).getDir() == 0.0f){
|
||||
posXInit = textPositions.get(textPositions.size() - 1)
|
||||
.getXDirAdj() + textPositions.get(textPositions.size() - 1).getHeightDir();
|
||||
posXEnd = textPositions.get(0).getXDirAdj();
|
||||
posYInit = textPositions.get(0).getPageHeight() - textPositions.get(0).getYDirAdj() - 2;
|
||||
posYEnd = textPositions.get(0).getPageHeight() - textPositions.get(textPositions.size() - 1)
|
||||
.getYDirAdj() + 2;
|
||||
} else if(textPositions.get(0).getRotation() == 0 && textPositions.get(0).getDir() == 90f){
|
||||
posYInit = getX1();
|
||||
posYEnd = getX2() + textPositions.get(0)
|
||||
.getWidthDirAdj() - textPositions.get(textPositions.size() - 1).getWidthDirAdj() - 3;
|
||||
posXInit = textPositions.get(0).getYDirAdj() + 2;
|
||||
posXEnd = textPositions.get(textPositions.size() - 1)
|
||||
.getYDirAdj() - height;
|
||||
}
|
||||
else {
|
||||
posXEnd = textPositions.get(textPositions.size() - 1)
|
||||
.getXDirAdj() + textPositions.get(textPositions.size() - 1).getWidth() + 1;
|
||||
.getXDirAdj() + textPositions.get(textPositions.size() - 1).getWidthDirAdj() + 1;
|
||||
posYInit = textPositions.get(0).getPageHeight() - textPositions.get(0).getYDirAdj() - 2;
|
||||
posYEnd = textPositions.get(0).getPageHeight() - textPositions.get(textPositions.size() - 1)
|
||||
.getYDirAdj() + 2;
|
||||
|
||||
+36
@@ -72,6 +72,19 @@ public class Section {
|
||||
}
|
||||
|
||||
|
||||
public boolean fileAttributeByIdEqualsIgnoreCase(String id, String value){
|
||||
return fileAttributes != null && fileAttributes.stream().filter(attribute -> id.equals(attribute.getId()) && value.equalsIgnoreCase(attribute.getValue())).findFirst().isPresent();
|
||||
}
|
||||
|
||||
public boolean fileAttributeByPlaceholderEqualsIgnoreCase(String placeholder, String value){
|
||||
return fileAttributes != null && fileAttributes.stream().filter(attribute -> placeholder.equals(attribute.getPlaceholder()) && value.equalsIgnoreCase(attribute.getValue())).findFirst().isPresent();
|
||||
}
|
||||
|
||||
public boolean fileAttributeByLabelEqualsIgnoreCase(String label, String value){
|
||||
return fileAttributes != null && fileAttributes.stream().filter(attribute -> label.equals(attribute.getLabel()) && value.equalsIgnoreCase(attribute.getValue())).findFirst().isPresent();
|
||||
}
|
||||
|
||||
|
||||
public boolean rowEquals(String headerName, String value) {
|
||||
|
||||
String cleanHeaderName = headerName.replaceAll("\n", "").replaceAll(" ", "").replaceAll("-", "");
|
||||
@@ -108,6 +121,16 @@ public class Section {
|
||||
|
||||
|
||||
public void expandByRegEx(String type, String pattern, boolean patternCaseInsensitive, int group) {
|
||||
expandByRegEx(type, pattern, patternCaseInsensitive, group, null);
|
||||
}
|
||||
|
||||
|
||||
public void expandByRegEx(String type, String pattern, boolean patternCaseInsensitive, int group, String withoutPattern) {
|
||||
|
||||
Pattern compiledWithoutPattern = null;
|
||||
if (withoutPattern != null) {
|
||||
compiledWithoutPattern = Patterns.getCompiledPattern(withoutPattern, patternCaseInsensitive);
|
||||
}
|
||||
|
||||
Pattern compiledPattern = Patterns.getCompiledPattern(pattern, patternCaseInsensitive);
|
||||
|
||||
@@ -118,11 +141,19 @@ public class Section {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(withoutPattern != null) {
|
||||
Matcher matcherWithout = compiledWithoutPattern.matcher(entity.getWord());
|
||||
if (matcherWithout.find()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Matcher matcher = compiledPattern.matcher(entity.getTextAfter());
|
||||
|
||||
while (matcher.find()) {
|
||||
String match = matcher.group(group);
|
||||
if (StringUtils.isNotBlank(match)) {
|
||||
|
||||
expanded.addAll(findEntities(entity.getWord() + match, type, false, entity.isRedaction(), entity.getMatchedRule(), entity
|
||||
.getRedactionReason(), entity.getLegalBasis()));
|
||||
|
||||
@@ -191,6 +222,11 @@ public class Section {
|
||||
}
|
||||
|
||||
|
||||
public void ignore(String type){
|
||||
entities.removeIf(entity -> entity.getType().equals(type));
|
||||
}
|
||||
|
||||
|
||||
public void expandToHintAnnotationByRegEx(String type, String pattern, boolean patternCaseInsensitive, int group,
|
||||
String asType) {
|
||||
|
||||
|
||||
+7
-25
@@ -5,35 +5,20 @@ import com.iqser.red.service.redaction.v1.model.RedactionChangeLog;
|
||||
import com.iqser.red.service.redaction.v1.model.RedactionLog;
|
||||
import com.iqser.red.service.redaction.v1.model.RedactionLogEntry;
|
||||
|
||||
import com.iqser.red.service.redaction.v1.server.settings.RedactionServiceSettings;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AnalyzeResponseService {
|
||||
|
||||
private final RedactionServiceSettings redactionServiceSettings;
|
||||
|
||||
public AnalyzeResult createAnalyzeResponse(String dossierId, String fileId, long duration, int pageCount,
|
||||
RedactionLog redactionLog, RedactionChangeLog redactionChangeLog) {
|
||||
|
||||
boolean hasHints = redactionLog.getRedactionLogEntry()
|
||||
.stream()
|
||||
.filter(entry -> !entry.isExcluded())
|
||||
.anyMatch(entry -> entry.isHint() && !entry.getType().equals("false_positive"));
|
||||
|
||||
boolean hasRequests = redactionLog.getRedactionLogEntry()
|
||||
.stream()
|
||||
.filter(entry -> !entry.isExcluded())
|
||||
.anyMatch(entry -> entry.isManual() && entry.getStatus()
|
||||
.equals(com.iqser.red.service.redaction.v1.model.Status.REQUESTED));
|
||||
|
||||
boolean hasRedactions = redactionLog.getRedactionLogEntry()
|
||||
.stream()
|
||||
.filter(entry -> !entry.isExcluded())
|
||||
.anyMatch(entry -> entry.isRedacted() && !entry.isManual() || entry.isManual() && entry.getStatus()
|
||||
.equals(com.iqser.red.service.redaction.v1.model.Status.APPROVED));
|
||||
|
||||
boolean hasImages = redactionLog.getRedactionLogEntry()
|
||||
.stream()
|
||||
.filter(entry -> !entry.isExcluded())
|
||||
.anyMatch(entry -> entry.isHint() && entry.getType().equals("image") || entry.isImage());
|
||||
|
||||
boolean hasUpdates = redactionChangeLog != null && redactionChangeLog.getRedactionLogEntry() != null && !redactionChangeLog
|
||||
.getRedactionLogEntry()
|
||||
@@ -46,11 +31,8 @@ public class AnalyzeResponseService {
|
||||
.fileId(fileId)
|
||||
.duration(duration)
|
||||
.numberOfPages(pageCount)
|
||||
.hasHints(hasHints)
|
||||
.hasRedactions(hasRedactions)
|
||||
.hasRequests(hasRequests)
|
||||
.hasImages(hasImages)
|
||||
.hasUpdates(hasUpdates)
|
||||
.analysisVersion(redactionServiceSettings.getAnalysisVersion())
|
||||
.rulesVersion(redactionLog.getRulesVersion())
|
||||
.dictionaryVersion(redactionLog.getDictionaryVersion())
|
||||
.legalBasisVersion(redactionLog.getLegalBasisVersion())
|
||||
|
||||
+2
-2
@@ -212,13 +212,13 @@ public class DictionaryService {
|
||||
dossierDictionaryVersion = dossierRepresentation.getDictionaryVersion();
|
||||
}
|
||||
|
||||
return new Dictionary(copy, DictionaryVersion.builder().dossierTemplateVersion(dossierTemplateRepresentation.getDictionaryVersion()).dossierVersion(dossierDictionaryVersion).build());
|
||||
return new Dictionary(copy.stream().sorted(Comparator.comparingInt(DictionaryModel::getRank).reversed()).collect(Collectors.toList()), DictionaryVersion.builder().dossierTemplateVersion(dossierTemplateRepresentation.getDictionaryVersion()).dossierVersion(dossierDictionaryVersion).build());
|
||||
}
|
||||
|
||||
|
||||
public float[] getRequestRemoveColor(String dossierTemplateId) {
|
||||
|
||||
return dictionariesByDossierTemplate.get(dossierTemplateId).getRequestAddColor();
|
||||
return dictionariesByDossierTemplate.get(dossierTemplateId).getRequestRemoveColor();
|
||||
}
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -63,7 +63,7 @@ public class DroolsExecutionService {
|
||||
rulesVersion = -1L;
|
||||
}
|
||||
|
||||
if (version > rulesVersion.longValue()) {
|
||||
if (version > rulesVersion) {
|
||||
rulesVersionPerDossierTemplateId.put(dossierTemplateId, version);
|
||||
return createOrUpdateKieContainer(dossierTemplateId);
|
||||
}
|
||||
@@ -128,7 +128,7 @@ public class DroolsExecutionService {
|
||||
if (rulesVersion == null) {
|
||||
return -1;
|
||||
}
|
||||
return rulesVersion.longValue();
|
||||
return rulesVersion;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+68
-87
@@ -1,13 +1,6 @@
|
||||
package com.iqser.red.service.redaction.v1.server.redaction.service;
|
||||
|
||||
import com.iqser.red.service.redaction.v1.model.FileAttribute;
|
||||
import com.iqser.red.service.redaction.v1.model.ManualImageRecategorization;
|
||||
import com.iqser.red.service.redaction.v1.model.ManualRedactionEntry;
|
||||
import com.iqser.red.service.redaction.v1.model.ManualRedactions;
|
||||
import com.iqser.red.service.redaction.v1.model.Point;
|
||||
import com.iqser.red.service.redaction.v1.model.Rectangle;
|
||||
import com.iqser.red.service.redaction.v1.model.SectionArea;
|
||||
import com.iqser.red.service.redaction.v1.model.Status;
|
||||
import com.iqser.red.service.redaction.v1.model.*;
|
||||
import com.iqser.red.service.redaction.v1.server.classification.model.*;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.model.Dictionary;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.model.*;
|
||||
@@ -15,10 +8,8 @@ import com.iqser.red.service.redaction.v1.server.redaction.utils.EntitySearchUti
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.utils.IdBuilder;
|
||||
import com.iqser.red.service.redaction.v1.server.tableextraction.model.Cell;
|
||||
import com.iqser.red.service.redaction.v1.server.tableextraction.model.Table;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.kie.api.runtime.KieContainer;
|
||||
@@ -52,35 +43,13 @@ public class EntityRedactionService {
|
||||
|
||||
if (dictionary.hasLocalEntries()) {
|
||||
|
||||
Map<Integer, Set<Entity>> hintsPerSectionNumber = new HashMap<>();
|
||||
documentEntities.stream().forEach(entity -> {
|
||||
if (dictionary.isHint(entity.getType()) && entity.isDictionaryEntry()) {
|
||||
hintsPerSectionNumber.computeIfAbsent(entity.getSectionNumber(), (x) -> new HashSet<>())
|
||||
.add(entity);
|
||||
}
|
||||
});
|
||||
|
||||
Map<Integer, Set<Entity>> hintsPerSectionNumber = getHintsPerSection(documentEntities, dictionary);
|
||||
Set<Entity> foundByLocal = findEntities(classifiedDoc, container, manualRedactions, dictionary, true, hintsPerSectionNumber, fileAttributes);
|
||||
EntitySearchUtils.addEntitiesWithHigherRank(documentEntities, foundByLocal, dictionary);
|
||||
EntitySearchUtils.removeEntitiesContainedInLarger(documentEntities);
|
||||
}
|
||||
|
||||
for (Entity entity : documentEntities) {
|
||||
Map<Integer, List<EntityPositionSequence>> sequenceOnPage = new HashMap<>();
|
||||
for (EntityPositionSequence entityPositionSequence : entity.getPositionSequences()) {
|
||||
sequenceOnPage.computeIfAbsent(entityPositionSequence.getPageNumber(), (x) -> new ArrayList<>())
|
||||
.add(entityPositionSequence);
|
||||
}
|
||||
|
||||
for (Map.Entry<Integer, List<EntityPositionSequence>> entry : sequenceOnPage.entrySet()) {
|
||||
classifiedDoc.getEntities()
|
||||
.computeIfAbsent(entry.getKey(), (x) -> new ArrayList<>())
|
||||
.add(new Entity(entity.getWord(), entity.getType(), entity.isRedaction(), entity.getRedactionReason(), entry
|
||||
.getValue(), entity.getHeadline(), entity.getMatchedRule(), entity.getSectionNumber(), entity
|
||||
.getLegalBasis(), entity.isDictionaryEntry(), entity.getTextBefore(), entity.getTextAfter(), entity
|
||||
.getStart(), entity.getEnd(), entity.isDossierDictionaryEntry()));
|
||||
}
|
||||
}
|
||||
classifiedDoc.setEntities(convertToEnititesPerPage(documentEntities));
|
||||
|
||||
dictionaryService.updateExternalDictionary(dictionary, dossierTemplateId);
|
||||
|
||||
@@ -89,6 +58,39 @@ public class EntityRedactionService {
|
||||
}
|
||||
|
||||
|
||||
public Map<Integer, List<Entity>> convertToEnititesPerPage(Set<Entity> entities){
|
||||
Map<Integer, List<Entity>> entitiesPerPage = new HashMap<>();
|
||||
for (Entity entity : entities) {
|
||||
Map<Integer, List<EntityPositionSequence>> sequenceOnPage = new HashMap<>();
|
||||
for (EntityPositionSequence entityPositionSequence : entity.getPositionSequences()) {
|
||||
sequenceOnPage.computeIfAbsent(entityPositionSequence.getPageNumber(), (x) -> new ArrayList<>())
|
||||
.add(entityPositionSequence);
|
||||
}
|
||||
|
||||
for (Map.Entry<Integer, List<EntityPositionSequence>> entry : sequenceOnPage.entrySet()) {
|
||||
entitiesPerPage
|
||||
.computeIfAbsent(entry.getKey(), (x) -> new ArrayList<>())
|
||||
.add(new Entity(entity.getWord(), entity.getType(), entity.isRedaction(), entity.getRedactionReason(), entry
|
||||
.getValue(), entity.getHeadline(), entity.getMatchedRule(), entity.getSectionNumber(), entity
|
||||
.getLegalBasis(), entity.isDictionaryEntry(), entity.getTextBefore(), entity.getTextAfter(), entity
|
||||
.getStart(), entity.getEnd(), entity.isDossierDictionaryEntry()));
|
||||
}
|
||||
}
|
||||
return entitiesPerPage;
|
||||
}
|
||||
|
||||
|
||||
public Map<Integer, Set<Entity>> getHintsPerSection(Set<Entity> entities, Dictionary dictionary){
|
||||
Map<Integer, Set<Entity>> hintsPerSectionNumber = new HashMap<>();
|
||||
entities.stream().forEach(entity -> {
|
||||
if (dictionary.isHint(entity.getType()) && entity.isDictionaryEntry()) {
|
||||
hintsPerSectionNumber.computeIfAbsent(entity.getSectionNumber(), (x) -> new HashSet<>())
|
||||
.add(entity);
|
||||
}
|
||||
});
|
||||
return hintsPerSectionNumber;
|
||||
}
|
||||
|
||||
private Set<Entity> findEntities(Document classifiedDoc, KieContainer kieContainer,
|
||||
ManualRedactions manualRedactions, Dictionary dictionary, boolean local,
|
||||
Map<Integer, Set<Entity>> hintsPerSectionNumber,
|
||||
@@ -103,9 +105,9 @@ public class EntityRedactionService {
|
||||
List<Table> tables = paragraph.getTables();
|
||||
for (Table table : tables) {
|
||||
if (table.getColCount() == 2) {
|
||||
sectionSearchableTextPairs.addAll(processTableAsOneText(classifiedDoc, table, manualRedactions, sectionNumber, dictionary, local, hintsPerSectionNumber, fileAttributes));
|
||||
sectionSearchableTextPairs.addAll(processTableAsOneText(classifiedDoc, table, sectionNumber, dictionary, local, hintsPerSectionNumber, fileAttributes));
|
||||
} else {
|
||||
sectionSearchableTextPairs.addAll(processTablePerRow(classifiedDoc, table, manualRedactions, sectionNumber, dictionary, local, hintsPerSectionNumber, fileAttributes));
|
||||
sectionSearchableTextPairs.addAll(processTablePerRow(classifiedDoc, table, sectionNumber, dictionary, local, hintsPerSectionNumber, fileAttributes));
|
||||
}
|
||||
sectionNumber.incrementAndGet();
|
||||
}
|
||||
@@ -132,44 +134,47 @@ public class EntityRedactionService {
|
||||
}
|
||||
|
||||
sectionSearchableTextPairs.forEach(sectionSearchableTextPair -> {
|
||||
Section analysedRowSection = droolsExecutionService.executeRules(kieContainer, sectionSearchableTextPair.getSection());
|
||||
documentEntities.addAll(analysedRowSection.getEntities());
|
||||
Section analysedSection = droolsExecutionService.executeRules(kieContainer, sectionSearchableTextPair.getSection());
|
||||
documentEntities.addAll(analysedSection.getEntities());
|
||||
|
||||
for (Image image : analysedRowSection.getImages()) {
|
||||
for (Image image : analysedSection.getImages()) {
|
||||
classifiedDoc.getImages().computeIfAbsent(image.getPage(), (a) -> new HashSet<>()).add(image);
|
||||
}
|
||||
|
||||
analysedRowSection.getLocalDictionaryAdds().keySet().forEach(key -> {
|
||||
if (dictionary.isRecommendation(key)) {
|
||||
analysedRowSection.getLocalDictionaryAdds().get(key).forEach(value -> {
|
||||
if (!dictionary.containsValue(key, value)) {
|
||||
dictionary.getLocalAccessMap().get(key).getLocalEntries().add(value);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
analysedRowSection.getLocalDictionaryAdds().get(key).forEach(value -> {
|
||||
|
||||
if (dictionary.getLocalAccessMap().get(key) == null) {
|
||||
log.warn("Dictionary {} is null", key);
|
||||
}
|
||||
|
||||
if (dictionary.getLocalAccessMap().get(key).getLocalEntries() == null) {
|
||||
log.warn("Dictionary {} localEntries is null", key);
|
||||
}
|
||||
|
||||
dictionary.getLocalAccessMap().get(key).getLocalEntries().add(value);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
addLocalValuesToDictionary(analysedSection, dictionary);
|
||||
});
|
||||
|
||||
return documentEntities;
|
||||
}
|
||||
|
||||
|
||||
public void addLocalValuesToDictionary(Section analysedSection, Dictionary dictionary){
|
||||
analysedSection.getLocalDictionaryAdds().keySet().forEach(key -> {
|
||||
if (dictionary.isRecommendation(key)) {
|
||||
analysedSection.getLocalDictionaryAdds().get(key).forEach(value -> {
|
||||
if (!dictionary.containsValue(key, value)) {
|
||||
dictionary.getLocalAccessMap().get(key).getLocalEntries().add(value);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
analysedSection.getLocalDictionaryAdds().get(key).forEach(value -> {
|
||||
|
||||
if (dictionary.getLocalAccessMap().get(key) == null) {
|
||||
log.warn("Dictionary {} is null", key);
|
||||
}
|
||||
|
||||
if (dictionary.getLocalAccessMap().get(key).getLocalEntries() == null) {
|
||||
log.warn("Dictionary {} localEntries is null", key);
|
||||
}
|
||||
|
||||
dictionary.getLocalAccessMap().get(key).getLocalEntries().add(value);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private List<SectionSearchableTextPair> processTablePerRow(Document classifiedDoc, Table table,
|
||||
ManualRedactions manualRedactions,
|
||||
AtomicInteger sectionNumber, Dictionary dictionary,
|
||||
boolean local,
|
||||
Map<Integer, Set<Entity>> hintsPerSectionNumber,
|
||||
@@ -198,7 +203,6 @@ public class EntityRedactionService {
|
||||
sectionText.getSectionAreas().add(sectionArea);
|
||||
sectionText.getTextBlocks().addAll(cell.getTextBlocks());
|
||||
|
||||
addSectionToManualRedactions(cell.getTextBlocks(), manualRedactions, table.getHeadline(), sectionNumber.intValue());
|
||||
int cellStart = start;
|
||||
|
||||
if (!cell.isHeaderCell()) {
|
||||
@@ -259,7 +263,6 @@ public class EntityRedactionService {
|
||||
|
||||
|
||||
private List<SectionSearchableTextPair> processTableAsOneText(Document classifiedDoc, Table table,
|
||||
ManualRedactions manualRedactions,
|
||||
AtomicInteger sectionNumber, Dictionary dictionary,
|
||||
boolean local,
|
||||
Map<Integer, Set<Entity>> hintsPerSectionNumber,
|
||||
@@ -288,7 +291,6 @@ public class EntityRedactionService {
|
||||
for (TextBlock textBlock : cell.getTextBlocks()) {
|
||||
entireTableText.addAll(textBlock.getSequences());
|
||||
}
|
||||
addSectionToManualRedactions(cell.getTextBlocks(), manualRedactions, table.getHeadline(), sectionNumber.intValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,7 +350,6 @@ public class EntityRedactionService {
|
||||
classifiedDoc.getSectionText().add(sectionText);
|
||||
}
|
||||
|
||||
addSectionToManualRedactions(paragraphTextBlocks, manualRedactions, headline, sectionNumber.intValue());
|
||||
Set<Entity> entities = findEntities(searchableText, headline, sectionNumber.intValue(), dictionary, local);
|
||||
surroundingWordsService.addSurroundingText(entities, searchableText, dictionary);
|
||||
|
||||
@@ -396,26 +397,6 @@ public class EntityRedactionService {
|
||||
}
|
||||
|
||||
|
||||
private void addSectionToManualRedactions(List<TextBlock> textBlocks, ManualRedactions manualRedactions,
|
||||
String section, int sectionNumber) {
|
||||
|
||||
if (manualRedactions == null || manualRedactions.getEntriesToAdd().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (TextBlock textBlock : textBlocks) {
|
||||
for (ManualRedactionEntry manualRedactionEntry : manualRedactions.getEntriesToAdd()) {
|
||||
for (Rectangle rectangle : manualRedactionEntry.getPositions()) {
|
||||
if (textBlock.contains(rectangle)) {
|
||||
manualRedactionEntry.setSection(section);
|
||||
manualRedactionEntry.setSectionNumber(sectionNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Image convertAndRecategorize(PdfImage pdfImage, int sectionNumber, String headline, ManualRedactions manualRedactions) {
|
||||
|
||||
Image image = Image.builder()
|
||||
|
||||
+109
-138
@@ -1,55 +1,29 @@
|
||||
package com.iqser.red.service.redaction.v1.server.redaction.service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.kie.api.runtime.KieContainer;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
import com.iqser.red.service.file.management.v1.api.model.FileType;
|
||||
import com.iqser.red.service.redaction.v1.model.AnalyzeRequest;
|
||||
import com.iqser.red.service.redaction.v1.model.AnalyzeResult;
|
||||
import com.iqser.red.service.redaction.v1.model.Comment;
|
||||
import com.iqser.red.service.redaction.v1.model.IdRemoval;
|
||||
import com.iqser.red.service.redaction.v1.model.ManualForceRedact;
|
||||
import com.iqser.red.service.redaction.v1.model.ManualImageRecategorization;
|
||||
import com.iqser.red.service.redaction.v1.model.ManualLegalBasisChange;
|
||||
import com.iqser.red.service.redaction.v1.model.ManualRedactionEntry;
|
||||
import com.iqser.red.service.redaction.v1.model.ManualRedactions;
|
||||
import com.iqser.red.service.redaction.v1.model.Rectangle;
|
||||
import com.iqser.red.service.redaction.v1.model.RedactionLog;
|
||||
import com.iqser.red.service.redaction.v1.model.RedactionLogEntry;
|
||||
import com.iqser.red.service.redaction.v1.model.SectionArea;
|
||||
import com.iqser.red.service.redaction.v1.model.Status;
|
||||
import com.iqser.red.service.redaction.v1.model.*;
|
||||
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.Text;
|
||||
import com.iqser.red.service.redaction.v1.server.client.LegalBasisClient;
|
||||
import com.iqser.red.service.redaction.v1.server.exception.RedactionException;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.model.Dictionary;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.model.DictionaryIncrement;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.model.DictionaryVersion;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.model.Entity;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.model.EntityPositionSequence;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.model.Image;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.model.RedRectangle2D;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.model.Section;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.model.SectionSearchableTextPair;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.model.*;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.utils.EntitySearchUtils;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.utils.IdBuilder;
|
||||
import com.iqser.red.service.redaction.v1.server.segmentation.PdfSegmentationService;
|
||||
import com.iqser.red.service.redaction.v1.server.settings.RedactionServiceSettings;
|
||||
import com.iqser.red.service.redaction.v1.server.storage.RedactionStorageService;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.kie.api.runtime.KieContainer;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@@ -66,6 +40,7 @@ public class ReanalyzeService {
|
||||
private final RedactionChangeLogService redactionChangeLogService;
|
||||
private final AnalyzeResponseService analyzeResponseService;
|
||||
private final LegalBasisClient legalBasisClient;
|
||||
private final RedactionServiceSettings redactionServiceSettings;
|
||||
|
||||
|
||||
public AnalyzeResult analyze(AnalyzeRequest analyzeRequest) {
|
||||
@@ -87,13 +62,12 @@ public class ReanalyzeService {
|
||||
|
||||
entityRedactionService.processDocument(classifiedDoc, analyzeRequest.getDossierTemplateId(), analyzeRequest.getManualRedactions(), analyzeRequest
|
||||
.getDossierId(), analyzeRequest.getFileAttributes());
|
||||
redactionLogCreatorService.createRedactionLog(classifiedDoc, pageCount, analyzeRequest.getManualRedactions(), analyzeRequest
|
||||
.getDossierTemplateId());
|
||||
redactionLogCreatorService.createRedactionLog(classifiedDoc, pageCount, analyzeRequest.getDossierTemplateId());
|
||||
|
||||
log.info("Redaction analysis successful...");
|
||||
|
||||
var legalBasis = legalBasisClient.getLegalBasisMapping(analyzeRequest.getDossierTemplateId());
|
||||
var redactionLog = new RedactionLog(classifiedDoc.getRedactionLogEntities(), legalBasis, classifiedDoc.getDictionaryVersion()
|
||||
var redactionLog = new RedactionLog(redactionServiceSettings.getAnalysisVersion(), classifiedDoc.getRedactionLogEntities(), legalBasis, classifiedDoc.getDictionaryVersion()
|
||||
.getDossierTemplateVersion(), classifiedDoc.getDictionaryVersion()
|
||||
.getDossierVersion(), classifiedDoc.getRulesVersion(), legalBasisClient.getVersion(analyzeRequest.getDossierTemplateId()));
|
||||
|
||||
@@ -108,6 +82,15 @@ public class ReanalyzeService {
|
||||
redactionStorageService.storeObject(analyzeRequest.getDossierId(), analyzeRequest.getFileId(), FileType.REDACTION_LOG, redactionLog);
|
||||
redactionStorageService.storeObject(analyzeRequest.getDossierId(), analyzeRequest.getFileId(), FileType.TEXT, new Text(pageCount, classifiedDoc
|
||||
.getSectionText()));
|
||||
|
||||
// enhance section grid with headline data
|
||||
classifiedDoc.getSectionText().forEach(sectionText -> {
|
||||
classifiedDoc
|
||||
.getSectionGrid().getSections().add(new SectionGrid.SectionGridSection(sectionText.getSectionNumber(),
|
||||
sectionText.getHeadline(),
|
||||
sectionText.getSectionAreas().stream().map(SectionArea::getPage).collect(Collectors.toSet()),
|
||||
sectionText.getSectionAreas()));
|
||||
});
|
||||
redactionStorageService.storeObject(analyzeRequest.getDossierId(), analyzeRequest.getFileId(), FileType.SECTION_GRID, classifiedDoc
|
||||
.getSectionGrid());
|
||||
|
||||
@@ -132,20 +115,66 @@ public class ReanalyzeService {
|
||||
DictionaryIncrement dictionaryIncrement = dictionaryService.getDictionaryIncrements(analyzeRequest.getDossierTemplateId(), new DictionaryVersion(redactionLog
|
||||
.getDictionaryVersion(), redactionLog.getDossierDictionaryVersion()), analyzeRequest.getDossierId());
|
||||
|
||||
Set<String> manualForceAndRemoveIds = getForceAndRemoveIds(analyzeRequest.getManualRedactions());
|
||||
Map<String, List<Comment>> comments = null;
|
||||
Set<ManualRedactionEntry> manualAdds = null;
|
||||
Set<Integer> sectionsToReanalyse = !analyzeRequest.getSectionsToReanalyse().isEmpty() ? analyzeRequest.getSectionsToReanalyse() :
|
||||
findSectionsToReanalyse(dictionaryIncrement, redactionLog, text, analyzeRequest);
|
||||
|
||||
if (analyzeRequest.getManualRedactions() != null) {
|
||||
// TODO comments will be removed from redactionLog, so we ignore this first.
|
||||
comments = analyzeRequest.getManualRedactions().getComments();
|
||||
manualAdds = analyzeRequest.getManualRedactions().getEntriesToAdd();
|
||||
if (sectionsToReanalyse.isEmpty()) {
|
||||
return finalizeAnalysis(analyzeRequest, startTime, redactionLog, text, dictionaryIncrement);
|
||||
}
|
||||
|
||||
List<SectionText> reanalysisSections = text.getSectionTexts()
|
||||
.stream()
|
||||
.filter(sectionText -> sectionsToReanalyse.contains(sectionText.getSectionNumber()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
KieContainer kieContainer = droolsExecutionService.updateRules(analyzeRequest.getDossierTemplateId());
|
||||
|
||||
Dictionary dictionary = dictionaryService.getDeepCopyDictionary(analyzeRequest.getDossierTemplateId(), analyzeRequest
|
||||
.getDossierId());
|
||||
|
||||
Map<Integer, Set<Image>> imagesPerPage = new HashMap<>();
|
||||
Set<Entity> entities = findEntities(reanalysisSections, dictionary, kieContainer, analyzeRequest, false, null, imagesPerPage);
|
||||
|
||||
if (dictionary.hasLocalEntries()) {
|
||||
Map<Integer, Set<Entity>> hintsPerSectionNumber = entityRedactionService.getHintsPerSection(entities, dictionary);
|
||||
Set<Entity> foundByLocal = findEntities(reanalysisSections, dictionary, kieContainer, analyzeRequest, true, hintsPerSectionNumber, imagesPerPage);
|
||||
EntitySearchUtils.addEntitiesWithHigherRank(entities, foundByLocal, dictionary);
|
||||
EntitySearchUtils.removeEntitiesContainedInLarger(entities);
|
||||
}
|
||||
|
||||
Map<Integer, List<Entity>> entitiesPerPage = entityRedactionService.convertToEnititesPerPage(entities);
|
||||
|
||||
List<RedactionLogEntry> newRedactionLogEntries = new ArrayList<>();
|
||||
for (int page = 1; page <= text.getNumberOfPages(); page++) {
|
||||
if (entitiesPerPage.get(page) != null) {
|
||||
newRedactionLogEntries.addAll(redactionLogCreatorService.addEntries(entitiesPerPage, page, analyzeRequest
|
||||
.getDossierTemplateId()));
|
||||
}
|
||||
|
||||
if (imagesPerPage.get(page) != null) {
|
||||
newRedactionLogEntries.addAll(redactionLogCreatorService.addImageEntries(imagesPerPage, page, analyzeRequest
|
||||
.getDossierTemplateId()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
redactionLog.getRedactionLogEntry().removeIf(entry -> sectionsToReanalyse.contains(entry.getSectionNumber()));
|
||||
redactionLog.getRedactionLogEntry().addAll(newRedactionLogEntries);
|
||||
AnalyzeResult analyzeResult = finalizeAnalysis(analyzeRequest, startTime, redactionLog, text, dictionaryIncrement);
|
||||
analyzeResult.setWasReanalyzed(true);
|
||||
return analyzeResult;
|
||||
}
|
||||
|
||||
|
||||
private Set<Integer> findSectionsToReanalyse(DictionaryIncrement dictionaryIncrement, RedactionLog redactionLog,
|
||||
Text text, AnalyzeRequest analyzeRequest) {
|
||||
|
||||
Set<String> relevantManuallyModifiedAnnotationIds = getRelevantManuallyModifiedAnnotationIds(analyzeRequest.getManualRedactions());
|
||||
|
||||
Set<Integer> sectionsToReanalyse = new HashSet<>();
|
||||
Map<Integer, Set<Image>> imageEntries = new HashMap<>();
|
||||
for (RedactionLogEntry entry : redactionLog.getRedactionLogEntry()) {
|
||||
if (entry.isManual() || manualForceAndRemoveIds.contains(entry.getId())) {
|
||||
if (entry.isManual() || relevantManuallyModifiedAnnotationIds.contains(entry.getId())) {
|
||||
sectionsToReanalyse.add(entry.getSectionNumber());
|
||||
}
|
||||
if (entry.isImage() || entry.getType().equals("image")) {
|
||||
@@ -159,47 +188,24 @@ public class ReanalyzeService {
|
||||
sectionsToReanalyse.add(sectionText.getSectionNumber());
|
||||
}
|
||||
|
||||
if (manualAdds != null) {
|
||||
for (SectionArea sectionArea : sectionText.getSectionAreas()) {
|
||||
for (ManualRedactionEntry manualAdd : manualAdds) {
|
||||
for (Rectangle manualPosition : manualAdd.getPositions()) {
|
||||
if (sectionArea.contains(manualPosition)) {
|
||||
manualAdd.setSection(sectionText.getHeadline());
|
||||
manualAdd.setSectionNumber(sectionText.getSectionNumber());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.info("Should reanalyze {} sections for request: {}", sectionsToReanalyse.size(), analyzeRequest);
|
||||
|
||||
if (sectionsToReanalyse.isEmpty() && (manualAdds == null || manualAdds.isEmpty())) {
|
||||
return finalizeAnalysis(analyzeRequest, startTime, redactionLog, text, dictionaryIncrement);
|
||||
}
|
||||
return sectionsToReanalyse;
|
||||
}
|
||||
|
||||
List<SectionText> reanalysisSections = new ArrayList<>();
|
||||
|
||||
for (SectionText sectionText : text.getSectionTexts()) {
|
||||
|
||||
if (sectionsToReanalyse.contains(sectionText.getSectionNumber())) {
|
||||
reanalysisSections.add(sectionText);
|
||||
}
|
||||
}
|
||||
|
||||
//--
|
||||
|
||||
KieContainer kieContainer = droolsExecutionService.updateRules(analyzeRequest.getDossierTemplateId());
|
||||
|
||||
Dictionary dictionary = dictionaryService.getDeepCopyDictionary(analyzeRequest.getDossierTemplateId(), analyzeRequest
|
||||
.getDossierId());
|
||||
private Set<Entity> findEntities(List<SectionText> reanalysisSections, Dictionary dictionary,
|
||||
KieContainer kieContainer, AnalyzeRequest analyzeRequest, boolean local,
|
||||
Map<Integer, Set<Entity>> hintsPerSectionNumber,
|
||||
Map<Integer, Set<Image>> imagesPerPage) {
|
||||
|
||||
List<SectionSearchableTextPair> sectionSearchableTextPairs = new ArrayList<>();
|
||||
for (SectionText reanalysisSection : reanalysisSections) {
|
||||
|
||||
Set<Entity> entities = entityRedactionService.findEntities(reanalysisSection.getSearchableText(), reanalysisSection
|
||||
.getHeadline(), reanalysisSection.getSectionNumber(), dictionary, false);
|
||||
.getHeadline(), reanalysisSection.getSectionNumber(), dictionary, local);
|
||||
if (reanalysisSection.getCellStarts() != null && !reanalysisSection.getCellStarts().isEmpty()) {
|
||||
surroundingWordsService.addSurroundingText(entities, reanalysisSection.getSearchableText(), dictionary, reanalysisSection
|
||||
.getCellStarts());
|
||||
@@ -207,14 +213,15 @@ public class ReanalyzeService {
|
||||
surroundingWordsService.addSurroundingText(entities, reanalysisSection.getSearchableText(), dictionary);
|
||||
}
|
||||
|
||||
if (reanalysisSection.getImages() != null && !reanalysisSection.getImages()
|
||||
if (!local && reanalysisSection.getImages() != null && !reanalysisSection.getImages()
|
||||
.isEmpty() && analyzeRequest.getManualRedactions() != null && analyzeRequest.getManualRedactions()
|
||||
.getImageRecategorizations() != null) {
|
||||
for (Image image : reanalysisSection.getImages()) {
|
||||
String imageId = IdBuilder.buildId(image.getPosition(), image.getPage());
|
||||
for(ManualImageRecategorization imageRecategorization: analyzeRequest.getManualRedactions()
|
||||
.getImageRecategorizations()){
|
||||
if(imageRecategorization.getStatus().equals(Status.APPROVED) && imageRecategorization.getId().equals(imageId)){
|
||||
for (ManualImageRecategorization imageRecategorization : analyzeRequest.getManualRedactions()
|
||||
.getImageRecategorizations()) {
|
||||
if (imageRecategorization.getStatus().equals(Status.APPROVED) && imageRecategorization.getId()
|
||||
.equals(imageId)) {
|
||||
image.setType(imageRecategorization.getType());
|
||||
}
|
||||
}
|
||||
@@ -224,7 +231,10 @@ public class ReanalyzeService {
|
||||
sectionSearchableTextPairs.add(new SectionSearchableTextPair(Section.builder()
|
||||
.isLocal(false)
|
||||
.dictionaryTypes(dictionary.getTypes())
|
||||
.entities(entities)
|
||||
.entities(hintsPerSectionNumber != null && hintsPerSectionNumber.containsKey(reanalysisSection.getSectionNumber()) ? Stream
|
||||
.concat(entities.stream(), hintsPerSectionNumber.get(reanalysisSection.getSectionNumber())
|
||||
.stream())
|
||||
.collect(Collectors.toSet()) : entities)
|
||||
.text(reanalysisSection.getSearchableText().getAsStringWithLinebreaks())
|
||||
.searchText(reanalysisSection.getSearchableText().toString())
|
||||
.headline(reanalysisSection.getHeadline())
|
||||
@@ -238,56 +248,19 @@ public class ReanalyzeService {
|
||||
}
|
||||
|
||||
Set<Entity> entities = new HashSet<>();
|
||||
Map<Integer, Set<Image>> imagesPerPage = new HashMap<>();
|
||||
sectionSearchableTextPairs.forEach(sectionSearchableTextPair -> {
|
||||
Section analysedRowSection = droolsExecutionService.executeRules(kieContainer, sectionSearchableTextPair.getSection());
|
||||
entities.addAll(analysedRowSection.getEntities());
|
||||
Section analysedSection = droolsExecutionService.executeRules(kieContainer, sectionSearchableTextPair.getSection());
|
||||
entities.addAll(analysedSection.getEntities());
|
||||
EntitySearchUtils.removeEntitiesContainedInLarger(entities);
|
||||
|
||||
for (Image image : analysedRowSection.getImages()) {
|
||||
for (Image image : analysedSection.getImages()) {
|
||||
imagesPerPage.computeIfAbsent(image.getPage(), (a) -> new HashSet<>()).add(image);
|
||||
}
|
||||
|
||||
entityRedactionService.addLocalValuesToDictionary(analysedSection, dictionary);
|
||||
});
|
||||
|
||||
Map<Integer, List<Entity>> entitiesPerPage = new HashMap<>();
|
||||
for (Entity entity : entities) {
|
||||
Map<Integer, List<EntityPositionSequence>> sequenceOnPage = new HashMap<>();
|
||||
for (EntityPositionSequence entityPositionSequence : entity.getPositionSequences()) {
|
||||
sequenceOnPage.computeIfAbsent(entityPositionSequence.getPageNumber(), (x) -> new ArrayList<>())
|
||||
.add(entityPositionSequence);
|
||||
}
|
||||
|
||||
for (Map.Entry<Integer, List<EntityPositionSequence>> entry : sequenceOnPage.entrySet()) {
|
||||
entitiesPerPage.computeIfAbsent(entry.getKey(), (x) -> new ArrayList<>())
|
||||
.add(new Entity(entity.getWord(), entity.getType(), entity.isRedaction(), entity.getRedactionReason(), entry
|
||||
.getValue(), entity.getHeadline(), entity.getMatchedRule(), entity.getSectionNumber(), entity
|
||||
.getLegalBasis(), entity.isDictionaryEntry(), entity.getTextBefore(), entity.getTextAfter(), entity
|
||||
.getStart(), entity.getEnd(), entity.isDossierDictionaryEntry()));
|
||||
}
|
||||
}
|
||||
|
||||
List<RedactionLogEntry> newRedactionLogEntries = new ArrayList<>();
|
||||
for (int page = 1; page <= text.getNumberOfPages(); page++) {
|
||||
if (entitiesPerPage.get(page) != null) {
|
||||
newRedactionLogEntries.addAll(redactionLogCreatorService.addEntries(entitiesPerPage, analyzeRequest.getManualRedactions(), page, analyzeRequest
|
||||
.getDossierTemplateId()));
|
||||
}
|
||||
|
||||
if (imagesPerPage.get(page) != null) {
|
||||
newRedactionLogEntries.addAll(redactionLogCreatorService.addImageEntries(imagesPerPage, analyzeRequest.getManualRedactions(), page, analyzeRequest
|
||||
.getDossierTemplateId()));
|
||||
}
|
||||
|
||||
newRedactionLogEntries.addAll(redactionLogCreatorService.addManualAddEntries(manualAdds, comments, page, analyzeRequest
|
||||
.getDossierTemplateId()));
|
||||
}
|
||||
|
||||
redactionLog.getRedactionLogEntry().removeIf(entry -> sectionsToReanalyse.contains(entry.getSectionNumber()));
|
||||
redactionLog.getRedactionLogEntry().addAll(newRedactionLogEntries);
|
||||
AnalyzeResult analyzeResult = finalizeAnalysis(analyzeRequest, startTime, redactionLog, text, dictionaryIncrement);
|
||||
analyzeResult.setWasReanalyzed(true);
|
||||
return analyzeResult;
|
||||
return entities;
|
||||
}
|
||||
|
||||
|
||||
@@ -310,19 +283,19 @@ public class ReanalyzeService {
|
||||
}
|
||||
|
||||
|
||||
private Set<String> getForceAndRemoveIds(ManualRedactions manualRedactions) {
|
||||
private Set<String> getRelevantManuallyModifiedAnnotationIds(ManualRedactions manualRedactions) {
|
||||
|
||||
if (manualRedactions == null) {
|
||||
return new HashSet<>();
|
||||
}
|
||||
|
||||
return Stream.concat(manualRedactions.getManualLegalBasisChanges()
|
||||
.stream()
|
||||
.map(ManualLegalBasisChange::getId), Stream.concat(manualRedactions.getImageRecategorizations()
|
||||
.stream()
|
||||
.map(ManualImageRecategorization::getId), Stream.concat(manualRedactions.getIdsToRemove()
|
||||
.stream()
|
||||
.map(IdRemoval::getId), manualRedactions.getForceRedacts().stream().map(ManualForceRedact::getId))))
|
||||
.stream()
|
||||
.map(ManualLegalBasisChange::getId), Stream.concat(manualRedactions.getImageRecategorizations()
|
||||
.stream()
|
||||
.map(ManualImageRecategorization::getId), Stream.concat(manualRedactions.getIdsToRemove()
|
||||
.stream()
|
||||
.map(IdRemoval::getId), manualRedactions.getForceRedacts().stream().map(ManualForceRedact::getId))))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@@ -345,15 +318,13 @@ public class ReanalyzeService {
|
||||
|
||||
private void excludeExcludedPages(RedactionLog redactionLog, Set<Integer> excludedPages) {
|
||||
|
||||
redactionLog.getRedactionLogEntry().forEach(entry -> {
|
||||
entry.getPositions().forEach(pos -> {
|
||||
if (excludedPages != null && excludedPages.contains(pos.getPage())) {
|
||||
if (excludedPages != null && !excludedPages.isEmpty()) {
|
||||
redactionLog.getRedactionLogEntry().forEach(entry -> entry.getPositions().forEach(pos -> {
|
||||
if (excludedPages.contains(pos.getPage())) {
|
||||
entry.setExcluded(true);
|
||||
} else {
|
||||
entry.setExcluded(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+69
-524
@@ -1,6 +1,20 @@
|
||||
package com.iqser.red.service.redaction.v1.server.redaction.service;
|
||||
|
||||
import com.iqser.red.service.redaction.v1.model.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.iqser.red.service.redaction.v1.model.CellRectangle;
|
||||
import com.iqser.red.service.redaction.v1.model.Point;
|
||||
import com.iqser.red.service.redaction.v1.model.Rectangle;
|
||||
import com.iqser.red.service.redaction.v1.model.RedactionLogEntry;
|
||||
import com.iqser.red.service.redaction.v1.model.SectionRectangle;
|
||||
import com.iqser.red.service.redaction.v1.server.classification.model.Document;
|
||||
import com.iqser.red.service.redaction.v1.server.classification.model.Paragraph;
|
||||
import com.iqser.red.service.redaction.v1.server.classification.model.TextBlock;
|
||||
@@ -9,18 +23,12 @@ import com.iqser.red.service.redaction.v1.server.parsing.model.TextPositionSeque
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.model.Entity;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.model.EntityPositionSequence;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.model.Image;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.model.ReasonHolder;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.utils.IdBuilder;
|
||||
import com.iqser.red.service.redaction.v1.server.tableextraction.model.AbstractTextContainer;
|
||||
import com.iqser.red.service.redaction.v1.server.tableextraction.model.Cell;
|
||||
import com.iqser.red.service.redaction.v1.server.tableextraction.model.Table;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@@ -29,10 +37,7 @@ public class RedactionLogCreatorService {
|
||||
private final DictionaryService dictionaryService;
|
||||
|
||||
|
||||
public void createRedactionLog(Document classifiedDoc, int numberOfPages, ManualRedactions manualRedactions,
|
||||
String dossierTemplateId) {
|
||||
|
||||
Set<Integer> manualRedactionPages = getManualRedactionPages(manualRedactions);
|
||||
public void createRedactionLog(Document classifiedDoc, int numberOfPages, String dossierTemplateId) {
|
||||
|
||||
for (int page = 1; page <= numberOfPages; page++) {
|
||||
|
||||
@@ -40,24 +45,19 @@ public class RedactionLogCreatorService {
|
||||
|
||||
if (classifiedDoc.getEntities().get(page) != null) {
|
||||
classifiedDoc.getRedactionLogEntities()
|
||||
.addAll(addEntries(classifiedDoc.getEntities(), manualRedactions, page, dossierTemplateId));
|
||||
}
|
||||
|
||||
if (manualRedactionPages.contains(page)) {
|
||||
classifiedDoc.getRedactionLogEntities()
|
||||
.addAll(addManualAddEntries(manualRedactions.getEntriesToAdd(), manualRedactions.getComments(), page, dossierTemplateId));
|
||||
.addAll(addEntries(classifiedDoc.getEntities(), page, dossierTemplateId));
|
||||
}
|
||||
|
||||
if (classifiedDoc.getImages().get(page) != null && !classifiedDoc.getImages().get(page).isEmpty()) {
|
||||
classifiedDoc.getRedactionLogEntities()
|
||||
.addAll(addImageEntries(classifiedDoc.getImages(), manualRedactions, page, dossierTemplateId));
|
||||
.addAll(addImageEntries(classifiedDoc.getImages(), page, dossierTemplateId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List<RedactionLogEntry> addImageEntries(Map<Integer, Set<Image>> images, ManualRedactions manualRedactions,
|
||||
int pageNumber, String dossierTemplateId) {
|
||||
public List<RedactionLogEntry> addImageEntries(Map<Integer, Set<Image>> images, int pageNumber,
|
||||
String dossierTemplateId) {
|
||||
|
||||
List<RedactionLogEntry> redactionLogEntities = new ArrayList<>();
|
||||
|
||||
@@ -67,7 +67,7 @@ public class RedactionLogCreatorService {
|
||||
|
||||
RedactionLogEntry redactionLogEntry = RedactionLogEntry.builder()
|
||||
.id(id)
|
||||
.color(getColorForImage(image.getType(), dossierTemplateId, false, image.isRedaction()))
|
||||
.color(getColor(image.getType(), dossierTemplateId, image.isRedaction()))
|
||||
.isImage(true)
|
||||
.type(image.getType())
|
||||
.redacted(image.isRedaction())
|
||||
@@ -82,147 +82,20 @@ public class RedactionLogCreatorService {
|
||||
.getX(), (float) image.getPosition().getY()), (float) image.getPosition()
|
||||
.getWidth(), (float) image.getPosition().getHeight(), pageNumber)))
|
||||
.sectionNumber(image.getSectionNumber())
|
||||
.section(image.getSection())
|
||||
//.section(image.getSection())
|
||||
// RED-2622
|
||||
.section("Image:" + image.getType())
|
||||
.imageHasTransparency(image.isHasTransparency())
|
||||
.build();
|
||||
|
||||
processImageEntry(manualRedactions, dossierTemplateId, image, redactionLogEntry);
|
||||
|
||||
redactionLogEntities.add(redactionLogEntry);
|
||||
}
|
||||
|
||||
return redactionLogEntities;
|
||||
}
|
||||
|
||||
private void processImageEntry(ManualRedactions manualRedactions, String dossierTemplateId, ReasonHolder image, RedactionLogEntry redactionLogEntry) {
|
||||
if (manualRedactions != null && !manualRedactions.getImageRecategorizations().isEmpty()) {
|
||||
for (ManualImageRecategorization recategorization : manualRedactions.getImageRecategorizations()) {
|
||||
if (recategorization.getId().equals(redactionLogEntry.getId())) {
|
||||
String manualOverrideReason = null;
|
||||
if (recategorization.getStatus().equals(Status.APPROVED)) {
|
||||
redactionLogEntry.setStatus(Status.APPROVED);
|
||||
redactionLogEntry.setType(recategorization.getType());
|
||||
manualOverrideReason = mergeReasonIfNecessary(image.getRedactionReason(), ", recategorized by manual override");
|
||||
} else if (recategorization.getStatus().equals(Status.REQUESTED)) {
|
||||
manualOverrideReason = mergeReasonIfNecessary(image.getRedactionReason(), ", requested to recategorize");
|
||||
redactionLogEntry.setStatus(Status.REQUESTED);
|
||||
redactionLogEntry.setColor(getColorForImage(redactionLogEntry.getType(), dossierTemplateId, true, redactionLogEntry.isRedacted()));
|
||||
redactionLogEntry.setRecategorizationType(recategorization.getType());
|
||||
} else {
|
||||
redactionLogEntry.setStatus(Status.DECLINED);
|
||||
}
|
||||
|
||||
image.setRedactionReason(manualOverrideReason != null ? manualOverrideReason : image.getRedactionReason());
|
||||
redactionLogEntry.setReason(manualOverrideReason);
|
||||
redactionLogEntry.setManual(true);
|
||||
redactionLogEntry.setManualRedactionType(ManualRedactionType.RECATEGORIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (manualRedactions != null && !manualRedactions.getIdsToRemove().isEmpty()) {
|
||||
for (IdRemoval manualRemoval : manualRedactions.getIdsToRemove()) {
|
||||
if (manualRemoval.getId().equals(redactionLogEntry.getId())) {
|
||||
String manualOverrideReason = null;
|
||||
if (manualRemoval.getStatus().equals(Status.APPROVED)) {
|
||||
image.setRedaction(false);
|
||||
redactionLogEntry.setRedacted(false);
|
||||
redactionLogEntry.setStatus(Status.APPROVED);
|
||||
manualOverrideReason = mergeReasonIfNecessary(image.getRedactionReason(), ", removed by manual override");
|
||||
redactionLogEntry.setColor(getColorForImage(redactionLogEntry.getType(), dossierTemplateId, false, redactionLogEntry.isRedacted()));
|
||||
} else if (manualRemoval.getStatus().equals(Status.REQUESTED)) {
|
||||
manualOverrideReason = mergeReasonIfNecessary(image.getRedactionReason(), ", requested to remove");
|
||||
redactionLogEntry.setStatus(Status.REQUESTED);
|
||||
redactionLogEntry.setColor(getColorForImage(redactionLogEntry.getType(), dossierTemplateId, true, redactionLogEntry.isRedacted()));
|
||||
} else {
|
||||
redactionLogEntry.setStatus(Status.DECLINED);
|
||||
}
|
||||
|
||||
image.setRedactionReason(manualOverrideReason != null ? manualOverrideReason : image.getRedactionReason());
|
||||
redactionLogEntry.setReason(manualOverrideReason);
|
||||
redactionLogEntry.setManual(true);
|
||||
redactionLogEntry.setManualRedactionType(ManualRedactionType.REMOVE);
|
||||
redactionLogEntry.setDictionaryEntry(manualRemoval.isRemoveFromDictionary());
|
||||
redactionLogEntry.setDossierDictionaryEntry(manualRemoval.isRemoveFromDictionary());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (manualRedactions != null && !manualRedactions.getForceRedacts().isEmpty()) {
|
||||
for (ManualForceRedact manualForceRedact : manualRedactions.getForceRedacts()) {
|
||||
if (manualForceRedact.getId().equals(redactionLogEntry.getId())) {
|
||||
String manualOverrideReason = null;
|
||||
if (manualForceRedact.getStatus().equals(Status.APPROVED)) {
|
||||
image.setRedaction(true);
|
||||
redactionLogEntry.setRedacted(true);
|
||||
redactionLogEntry.setStatus(Status.APPROVED);
|
||||
redactionLogEntry.setColor(getColorForImage(redactionLogEntry.getType(), dossierTemplateId, false, redactionLogEntry.isRedacted()));
|
||||
manualOverrideReason = mergeReasonIfNecessary(image.getRedactionReason(), ", forced by manual override");
|
||||
redactionLogEntry.setLegalBasis(manualForceRedact.getLegalBasis());
|
||||
} else if (manualForceRedact.getStatus().equals(Status.REQUESTED)) {
|
||||
manualOverrideReason = mergeReasonIfNecessary(image.getRedactionReason(), ", requested to force redact");
|
||||
redactionLogEntry.setStatus(Status.REQUESTED);
|
||||
redactionLogEntry.setColor(getColorForImage(redactionLogEntry.getType(), dossierTemplateId, true, redactionLogEntry.isRedacted()));
|
||||
redactionLogEntry.setLegalBasis(manualForceRedact.getLegalBasis());
|
||||
} else {
|
||||
redactionLogEntry.setStatus(Status.DECLINED);
|
||||
}
|
||||
|
||||
image.setRedactionReason(manualOverrideReason != null ? manualOverrideReason : image.getRedactionReason());
|
||||
redactionLogEntry.setReason(manualOverrideReason);
|
||||
redactionLogEntry.setManual(true);
|
||||
redactionLogEntry.setManualRedactionType(ManualRedactionType.FORCE_REDACT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (manualRedactions != null && !manualRedactions.getManualLegalBasisChanges().isEmpty()) {
|
||||
for (ManualLegalBasisChange manualLegalBasisChange : manualRedactions.getManualLegalBasisChanges()) {
|
||||
if (manualLegalBasisChange.getId().equals(redactionLogEntry.getId())) {
|
||||
String manualOverrideReason = null;
|
||||
if (manualLegalBasisChange.getStatus().equals(Status.APPROVED)) {
|
||||
redactionLogEntry.setStatus(Status.APPROVED);
|
||||
manualOverrideReason = mergeReasonIfNecessary(image.getRedactionReason(), ", legal basis was manually changed");
|
||||
redactionLogEntry.setLegalBasis(manualLegalBasisChange.getLegalBasis());
|
||||
} else if (manualLegalBasisChange.getStatus().equals(Status.REQUESTED)) {
|
||||
manualOverrideReason = mergeReasonIfNecessary(image.getRedactionReason(), ", legal basis change requested");
|
||||
redactionLogEntry.setStatus(Status.REQUESTED);
|
||||
redactionLogEntry.setColor(getColorForImage(redactionLogEntry.getType(), dossierTemplateId, true, redactionLogEntry.isRedacted()));
|
||||
redactionLogEntry.setLegalBasisChangeValue(manualLegalBasisChange.getLegalBasis());
|
||||
} else {
|
||||
redactionLogEntry.setStatus(Status.DECLINED);
|
||||
}
|
||||
|
||||
image.setRedactionReason(manualOverrideReason != null ? manualOverrideReason : image.getRedactionReason());
|
||||
redactionLogEntry.setReason(manualOverrideReason);
|
||||
redactionLogEntry.setManual(true);
|
||||
redactionLogEntry.setManualRedactionType(ManualRedactionType.LEGAL_BASIS_CHANGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Set<Integer> getManualRedactionPages(ManualRedactions manualRedactions) {
|
||||
|
||||
Set<Integer> manualRedactionPages = new HashSet<>();
|
||||
|
||||
if (manualRedactions == null) {
|
||||
return manualRedactionPages;
|
||||
}
|
||||
|
||||
manualRedactions.getEntriesToAdd().forEach(entry -> {
|
||||
entry.getPositions().forEach(pos -> {
|
||||
manualRedactionPages.add(pos.getPage());
|
||||
});
|
||||
});
|
||||
return manualRedactionPages;
|
||||
}
|
||||
|
||||
|
||||
public List<RedactionLogEntry> addEntries(Map<Integer, List<Entity>> entities, ManualRedactions manualRedactions,
|
||||
int page, String dossierTemplateId) {
|
||||
public List<RedactionLogEntry> addEntries(Map<Integer, List<Entity>> entities, int page, String dossierTemplateId) {
|
||||
|
||||
List<RedactionLogEntry> redactionLogEntities = new ArrayList<>();
|
||||
|
||||
@@ -232,7 +105,6 @@ public class RedactionLogCreatorService {
|
||||
entityLoop:
|
||||
for (Entity entity : entities.get(page)) {
|
||||
|
||||
|
||||
for (EntityPositionSequence entityPositionSequence : entity.getPositionSequences()) {
|
||||
|
||||
RedactionLogEntry redactionLogEntry = createRedactionLogEntry(entity, dossierTemplateId);
|
||||
@@ -245,7 +117,6 @@ public class RedactionLogCreatorService {
|
||||
}
|
||||
|
||||
redactionLogEntry.setId(entityPositionSequence.getId());
|
||||
processRedactionLogEntry(manualRedactions, dossierTemplateId, redactionLogEntry, entity);
|
||||
|
||||
if (CollectionUtils.isNotEmpty(entityPositionSequence.getSequences())) {
|
||||
List<Rectangle> rectanglesPerLine = getRectanglesPerLine(entityPositionSequence.getSequences()
|
||||
@@ -253,12 +124,10 @@ public class RedactionLogCreatorService {
|
||||
.flatMap(seq -> seq.getTextPositions().stream())
|
||||
.collect(Collectors.toList()), page);
|
||||
|
||||
|
||||
redactionLogEntry.getPositions().addAll(rectanglesPerLine);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// FIXME ids should never be null. Figure out why this happens.
|
||||
if (redactionLogEntry.getId() != null) {
|
||||
redactionLogEntities.add(redactionLogEntry);
|
||||
@@ -269,112 +138,6 @@ public class RedactionLogCreatorService {
|
||||
return redactionLogEntities;
|
||||
}
|
||||
|
||||
private void processRedactionLogEntry(ManualRedactions manualRedactions, String dossierTemplateId, RedactionLogEntry redactionLogEntry, ReasonHolder reasonHolder) {
|
||||
|
||||
List<Comment> comments = null;
|
||||
|
||||
if (manualRedactions != null && !manualRedactions.getIdsToRemove().isEmpty()) {
|
||||
for (IdRemoval manualRemoval : manualRedactions.getIdsToRemove()) {
|
||||
if (manualRemoval.getId().equals(redactionLogEntry.getId())) {
|
||||
comments = manualRedactions.getComments().get(manualRemoval.getId());
|
||||
String manualOverrideReason = null;
|
||||
if (manualRemoval.getStatus().equals(Status.APPROVED)) {
|
||||
reasonHolder.setRedaction(false);
|
||||
redactionLogEntry.setRedacted(false);
|
||||
redactionLogEntry.setStatus(Status.APPROVED);
|
||||
manualOverrideReason = mergeReasonIfNecessary(reasonHolder.getRedactionReason(), ", removed by manual override");
|
||||
redactionLogEntry.setColor(getColor(redactionLogEntry.getType(), dossierTemplateId, false, redactionLogEntry.isRedacted()));
|
||||
} else if (manualRemoval.getStatus().equals(Status.REQUESTED)) {
|
||||
manualOverrideReason = mergeReasonIfNecessary(reasonHolder.getRedactionReason(), ", requested to remove");
|
||||
redactionLogEntry.setStatus(Status.REQUESTED);
|
||||
redactionLogEntry.setColor(getColor(redactionLogEntry.getType(), dossierTemplateId, true, redactionLogEntry.isRedacted()));
|
||||
} else {
|
||||
redactionLogEntry.setStatus(Status.DECLINED);
|
||||
}
|
||||
|
||||
reasonHolder.setRedactionReason(manualOverrideReason != null ? manualOverrideReason : reasonHolder.getRedactionReason());
|
||||
redactionLogEntry.setReason(manualOverrideReason);
|
||||
redactionLogEntry.setManual(true);
|
||||
redactionLogEntry.setManualRedactionType(ManualRedactionType.REMOVE);
|
||||
redactionLogEntry.setDictionaryEntry(manualRemoval.isRemoveFromDictionary());
|
||||
redactionLogEntry.setDossierDictionaryEntry(manualRemoval.isRemoveFromDictionary());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (manualRedactions != null && !manualRedactions.getForceRedacts().isEmpty()) {
|
||||
for (ManualForceRedact manualForceRedact : manualRedactions.getForceRedacts()) {
|
||||
if (manualForceRedact.getId().equals(redactionLogEntry.getId())) {
|
||||
String manualOverrideReason = null;
|
||||
if (manualForceRedact.getStatus().equals(Status.APPROVED)) {
|
||||
reasonHolder.setRedaction(true);
|
||||
redactionLogEntry.setRedacted(true);
|
||||
redactionLogEntry.setStatus(Status.APPROVED);
|
||||
redactionLogEntry.setColor(getColor(redactionLogEntry.getType(), dossierTemplateId, false, redactionLogEntry.isRedacted()));
|
||||
manualOverrideReason = mergeReasonIfNecessary(reasonHolder.getRedactionReason(), ", forced by manual override");
|
||||
redactionLogEntry.setLegalBasis(manualForceRedact.getLegalBasis());
|
||||
} else if (manualForceRedact.getStatus().equals(Status.REQUESTED)) {
|
||||
manualOverrideReason = mergeReasonIfNecessary(reasonHolder.getRedactionReason(), ", requested to force redact");
|
||||
redactionLogEntry.setStatus(Status.REQUESTED);
|
||||
redactionLogEntry.setColor(getColor(redactionLogEntry.getType(), dossierTemplateId, true, redactionLogEntry.isRedacted()));
|
||||
redactionLogEntry.setLegalBasis(manualForceRedact.getLegalBasis());
|
||||
} else {
|
||||
redactionLogEntry.setStatus(Status.DECLINED);
|
||||
}
|
||||
|
||||
reasonHolder.setRedactionReason(manualOverrideReason != null ? manualOverrideReason : reasonHolder.getRedactionReason());
|
||||
redactionLogEntry.setReason(manualOverrideReason);
|
||||
redactionLogEntry.setManual(true);
|
||||
redactionLogEntry.setManualRedactionType(ManualRedactionType.FORCE_REDACT);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (manualRedactions != null && !manualRedactions.getManualLegalBasisChanges().isEmpty()) {
|
||||
for (ManualLegalBasisChange manualLegalBasisChange : manualRedactions.getManualLegalBasisChanges()) {
|
||||
if (manualLegalBasisChange.getId().equals(redactionLogEntry.getId())) {
|
||||
String manualOverrideReason = null;
|
||||
if (manualLegalBasisChange.getStatus().equals(Status.APPROVED)) {
|
||||
redactionLogEntry.setStatus(Status.APPROVED);
|
||||
manualOverrideReason = mergeReasonIfNecessary(reasonHolder.getRedactionReason(), ", legal basis was manually changed");
|
||||
redactionLogEntry.setLegalBasis(manualLegalBasisChange.getLegalBasis());
|
||||
} else if (manualLegalBasisChange.getStatus().equals(Status.REQUESTED)) {
|
||||
manualOverrideReason = mergeReasonIfNecessary(reasonHolder.getRedactionReason(), ", legal basis change requested");
|
||||
redactionLogEntry.setStatus(Status.REQUESTED);
|
||||
redactionLogEntry.setColor(getColor(redactionLogEntry.getType(), dossierTemplateId, true, redactionLogEntry.isRedacted()));
|
||||
redactionLogEntry.setLegalBasisChangeValue(manualLegalBasisChange.getLegalBasis());
|
||||
} else {
|
||||
redactionLogEntry.setStatus(Status.DECLINED);
|
||||
}
|
||||
|
||||
reasonHolder.setRedactionReason(manualOverrideReason != null ? manualOverrideReason : reasonHolder.getRedactionReason());
|
||||
redactionLogEntry.setReason(manualOverrideReason);
|
||||
redactionLogEntry.setManual(true);
|
||||
redactionLogEntry.setManualRedactionType(ManualRedactionType.LEGAL_BASIS_CHANGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (manualRedactions != null) {
|
||||
comments = manualRedactions.getComments().get(redactionLogEntry.getId());
|
||||
}
|
||||
|
||||
redactionLogEntry.setComments(comments);
|
||||
}
|
||||
|
||||
private String mergeReasonIfNecessary(String currentReason, String addition) {
|
||||
if (currentReason != null) {
|
||||
if (!currentReason.contains(addition)) {
|
||||
return currentReason + addition;
|
||||
}
|
||||
return currentReason;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private List<Rectangle> getRectanglesPerLine(List<RedTextPosition> textPositions, int page) {
|
||||
|
||||
@@ -382,16 +145,27 @@ public class RedactionLogCreatorService {
|
||||
if (textPositions.size() == 1) {
|
||||
rectangles.add(TextPositionSequence.fromData(textPositions, page).getRectangle());
|
||||
} else {
|
||||
float x = textPositions.get(0).getXDirAdj();
|
||||
float y = textPositions.get(0).getYDirAdj();
|
||||
float width = textPositions.get(0).getWidth();
|
||||
float height = textPositions.get(0).getHeightDir();
|
||||
int startIndex = 0;
|
||||
|
||||
for (int i = 1; i < textPositions.size(); i++) {
|
||||
float xDirAdj = textPositions.get(i).getXDirAdj();
|
||||
float yDirAdj = textPositions.get(i).getYDirAdj();
|
||||
if (yDirAdj != y) {
|
||||
float widthDir = textPositions.get(i).getWidth();
|
||||
float heightDir = textPositions.get(i).getHeightDir();
|
||||
|
||||
if (!(isCharInSameLine(y, yDirAdj, height, heightDir) && isCharClose(x, xDirAdj, width))) {
|
||||
rectangles.add(TextPositionSequence.fromData(textPositions.subList(startIndex, i), page)
|
||||
.getRectangle());
|
||||
y = yDirAdj;
|
||||
width = widthDir;
|
||||
height = heightDir;
|
||||
startIndex = i;
|
||||
}
|
||||
x = xDirAdj;
|
||||
}
|
||||
if (startIndex != textPositions.size()) {
|
||||
rectangles.add(TextPositionSequence.fromData(textPositions.subList(startIndex, textPositions.size()), page)
|
||||
@@ -403,73 +177,38 @@ public class RedactionLogCreatorService {
|
||||
}
|
||||
|
||||
|
||||
public List<RedactionLogEntry> addManualAddEntries(Set<ManualRedactionEntry> manualAdds,
|
||||
Map<String, List<Comment>> comments, int page,
|
||||
String dossierTemplateId) {
|
||||
private boolean isCharClose(float x, float xDirAdj, float width) {
|
||||
|
||||
List<RedactionLogEntry> redactionLogEntities = new ArrayList<>();
|
||||
|
||||
if (manualAdds == null) {
|
||||
return redactionLogEntities;
|
||||
float max = x + (5 * width);
|
||||
if (xDirAdj < max) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (ManualRedactionEntry manualRedactionEntry : manualAdds) {
|
||||
|
||||
String id = manualRedactionEntry.getId();
|
||||
|
||||
RedactionLogEntry redactionLogEntry = createRedactionLogEntry(manualRedactionEntry, id, dossierTemplateId);
|
||||
|
||||
List<Rectangle> rectanglesOnPage = new ArrayList<>();
|
||||
for (Rectangle rectangle : manualRedactionEntry.getPositions()) {
|
||||
if (page == rectangle.getPage()) {
|
||||
rectanglesOnPage.add(rectangle);
|
||||
redactionLogEntry.getPositions().add(rectangle);
|
||||
}
|
||||
}
|
||||
|
||||
redactionLogEntry.setComments(comments.get(id));
|
||||
if (!rectanglesOnPage.isEmpty() && !approvedAndShouldBeInDictionary(manualRedactionEntry)) {
|
||||
redactionLogEntities.add(redactionLogEntry);
|
||||
}
|
||||
}
|
||||
|
||||
return redactionLogEntities;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private boolean approvedAndShouldBeInDictionary(ManualRedactionEntry manualRedactionEntry) {
|
||||
private boolean isCharInSameLine(float y, float yCompare, float height, float heightCompare) {
|
||||
|
||||
return manualRedactionEntry.getStatus().equals(Status.APPROVED) && manualRedactionEntry.isAddToDictionary();
|
||||
}
|
||||
float offsetHeight = height / 2;
|
||||
float minHeight = height - offsetHeight;
|
||||
float maxHeight = height + offsetHeight;
|
||||
|
||||
float offsetY = height / 10;
|
||||
float minY = y - offsetY;
|
||||
float maxY = y + offsetY;
|
||||
|
||||
private RedactionLogEntry createRedactionLogEntry(ManualRedactionEntry manualRedactionEntry, String id,
|
||||
String dossierTemplateId) {
|
||||
if (yCompare > minY && yCompare < maxY && heightCompare > minHeight && heightCompare < maxHeight) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return RedactionLogEntry.builder()
|
||||
.id(id)
|
||||
.color(getColorForManualAdd(manualRedactionEntry.getType(), dossierTemplateId, manualRedactionEntry.getStatus()))
|
||||
.reason(manualRedactionEntry.getReason())
|
||||
.legalBasis(manualRedactionEntry.getLegalBasis())
|
||||
.value(manualRedactionEntry.getValue())
|
||||
.type(manualRedactionEntry.getType())
|
||||
.redacted(true)
|
||||
.isHint(false)
|
||||
.section(manualRedactionEntry.getSection())
|
||||
.sectionNumber(manualRedactionEntry.getSectionNumber())
|
||||
.manual(true)
|
||||
.status(manualRedactionEntry.getStatus())
|
||||
.manualRedactionType(ManualRedactionType.ADD)
|
||||
.isDictionaryEntry(false)
|
||||
.isDossierDictionaryEntry(manualRedactionEntry.isAddToDossierDictionary())
|
||||
.build();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private RedactionLogEntry createRedactionLogEntry(Entity entity, String dossierTemplateId) {
|
||||
|
||||
return RedactionLogEntry.builder()
|
||||
.color(getColor(entity.getType(), dossierTemplateId, false, entity.isRedaction()))
|
||||
.color(getColor(entity.getType(), dossierTemplateId, entity.isRedaction()))
|
||||
.reason(entity.getRedactionReason())
|
||||
.legalBasis(entity.getLegalBasis())
|
||||
.value(entity.getWord())
|
||||
@@ -490,59 +229,6 @@ public class RedactionLogCreatorService {
|
||||
}
|
||||
|
||||
|
||||
private float[] getColor(String type, String dossierTemplateId, boolean requestedToRemove, boolean isRedaction) {
|
||||
|
||||
if (requestedToRemove) {
|
||||
return dictionaryService.getRequestRemoveColor(dossierTemplateId);
|
||||
}
|
||||
if (!isRedaction && !isHint(type, dossierTemplateId)) {
|
||||
return dictionaryService.getNotRedactedColor(dossierTemplateId);
|
||||
}
|
||||
return dictionaryService.getColor(type, dossierTemplateId);
|
||||
}
|
||||
|
||||
|
||||
private float[] getColorForManualAdd(String type, String dossierTemplateId, Status status) {
|
||||
|
||||
if (status.equals(Status.REQUESTED)) {
|
||||
return dictionaryService.getRequestAddColor(dossierTemplateId);
|
||||
} else if (status.equals(Status.DECLINED)) {
|
||||
return dictionaryService.getNotRedactedColor(dossierTemplateId);
|
||||
}
|
||||
return getColor(type, dossierTemplateId);
|
||||
}
|
||||
|
||||
|
||||
private float[] getColor(String type, String dossierTemplateId) {
|
||||
|
||||
return dictionaryService.getColor(type, dossierTemplateId);
|
||||
}
|
||||
|
||||
|
||||
private float[] getColorForImage(String type, String dossierTemplateId, boolean requestedToRemove, boolean isRedaction) {
|
||||
|
||||
if (requestedToRemove) {
|
||||
return dictionaryService.getRequestRemoveColor(dossierTemplateId);
|
||||
}
|
||||
if (!isRedaction && !dictionaryService.isHint(type, dossierTemplateId)) {
|
||||
return dictionaryService.getNotRedactedColor(dossierTemplateId);
|
||||
}
|
||||
return dictionaryService.getColor(type, dossierTemplateId);
|
||||
}
|
||||
|
||||
|
||||
private boolean isHint(String type, String dossierTemplateId) {
|
||||
|
||||
return dictionaryService.isHint(type, dossierTemplateId);
|
||||
}
|
||||
|
||||
|
||||
private boolean isRecommendation(String type, String dossierTemplateId) {
|
||||
|
||||
return dictionaryService.isRecommendation(type, dossierTemplateId);
|
||||
}
|
||||
|
||||
|
||||
private void addSectionGrid(Document classifiedDoc, int page) {
|
||||
|
||||
for (Paragraph paragraph : classifiedDoc.getParagraphs()) {
|
||||
@@ -560,8 +246,8 @@ public class RedactionLogCreatorService {
|
||||
classifiedDoc.getSectionGrid()
|
||||
.getRectanglesPerPage()
|
||||
.computeIfAbsent(page, (x) -> new ArrayList<>())
|
||||
.add(new SectionRectangle(new Point(textBlock.getMinX(), textBlock.getMinY()), textBlock.getWidth(), textBlock
|
||||
.getHeight(), i + 1, paragraph.getPageBlocks().size()));
|
||||
.add(new SectionRectangle(new Point(textBlock.getMinX(), textBlock.getMinY()), textBlock.getWidth(), textBlock.getHeight(), i + 1, paragraph.getPageBlocks()
|
||||
.size()));
|
||||
|
||||
} else if (textBlock instanceof Table) {
|
||||
|
||||
@@ -569,8 +255,7 @@ public class RedactionLogCreatorService {
|
||||
for (List<Cell> row : ((Table) textBlock).getRows()) {
|
||||
for (Cell cell : row) {
|
||||
if (cell != null) {
|
||||
cellRectangles.add(new CellRectangle(new Point((float) cell.getX(), (float) cell.getY()), (float) cell
|
||||
.getWidth(), (float) cell.getHeight()));
|
||||
cellRectangles.add(new CellRectangle(new Point((float) cell.getX(), (float) cell.getY()), (float) cell.getWidth(), (float) cell.getHeight()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -578,173 +263,33 @@ public class RedactionLogCreatorService {
|
||||
classifiedDoc.getSectionGrid()
|
||||
.getRectanglesPerPage()
|
||||
.computeIfAbsent(page, (x) -> new ArrayList<>())
|
||||
.add(new SectionRectangle(new Point(textBlock.getMinX(), textBlock.getMinY()), textBlock.getWidth(), textBlock
|
||||
.getHeight(), i + 1, paragraph.getPageBlocks().size(), cellRectangles));
|
||||
.add(new SectionRectangle(new Point(textBlock.getMinX(), textBlock.getMinY()), textBlock.getWidth(), textBlock.getHeight(), i + 1, paragraph.getPageBlocks()
|
||||
.size(), cellRectangles));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RedactionLog getRedactionLogPreview(RedactionLog redactionLog, String dossierTemplateId, ManualRedactions manualRedactions) {
|
||||
|
||||
private float[] getColor(String type, String dossierTemplateId, boolean isRedaction) {
|
||||
|
||||
var manualRedactionPages = getManualRedactionPages(manualRedactions);
|
||||
|
||||
// generate all manual entries
|
||||
var manualRedactionLogEntries = new HashMap<String, RedactionLogEntry>();
|
||||
for (var page : manualRedactionPages) {
|
||||
|
||||
var pageEntries = addManualAddEntries(manualRedactions.getEntriesToAdd(), manualRedactions.getComments(), page, dossierTemplateId);
|
||||
|
||||
for (var entry : pageEntries) {
|
||||
manualRedactionLogEntries.put(entry.getId(), entry);
|
||||
}
|
||||
if (!isRedaction && !isHint(type, dossierTemplateId)) {
|
||||
return dictionaryService.getNotRedactedColor(dossierTemplateId);
|
||||
}
|
||||
|
||||
for (var manualEntry : manualRedactionLogEntries.values()) {
|
||||
var existingEntry = redactionLog.getRedactionLogEntry().stream().filter(e -> e.getId().equals(manualEntry.getId())).findAny();
|
||||
if (existingEntry.isPresent()) {
|
||||
// if it has already been processed of sorts, update it
|
||||
BeanUtils.copyProperties(manualEntry, existingEntry.get());
|
||||
} else {
|
||||
// not yet in the redaction-log - add it
|
||||
redactionLog.getRedactionLogEntry().add(manualEntry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Set<String> entriesToRemoveBecauseOfUndoActions = new HashSet<>();
|
||||
for (RedactionLogEntry entry : redactionLog.getRedactionLogEntry()) {
|
||||
|
||||
var reasonHolder = new PreviewReasonHolder(entry);
|
||||
|
||||
if (entry.isImage()) {
|
||||
processImageEntry(manualRedactions, dossierTemplateId, reasonHolder, entry);
|
||||
}
|
||||
|
||||
processRedactionLogEntry(manualRedactions, dossierTemplateId, entry, reasonHolder);
|
||||
var shouldRemove = postProcessRedactionLogEntryForDeletedManualRedactions(manualRedactions, entry);
|
||||
if (shouldRemove) {
|
||||
entriesToRemoveBecauseOfUndoActions.add(entry.getId());
|
||||
}
|
||||
|
||||
|
||||
entry.setComments(manualRedactions.getComments().get(entry.getId()));
|
||||
}
|
||||
|
||||
redactionLog.setRedactionLogEntry(redactionLog.getRedactionLogEntry()
|
||||
.stream().filter(entry -> !entriesToRemoveBecauseOfUndoActions.contains(entry.getId())).collect(Collectors.toList()));
|
||||
|
||||
|
||||
handleAddToDictionary(redactionLog, manualRedactions, dossierTemplateId);
|
||||
|
||||
return redactionLog;
|
||||
}
|
||||
|
||||
private boolean postProcessRedactionLogEntryForDeletedManualRedactions(ManualRedactions manualRedactions, RedactionLogEntry entry) {
|
||||
if (entry.isManual()) {
|
||||
|
||||
if (entry.getManualRedactionType() == ManualRedactionType.ADD) {
|
||||
var manualRedactionExists = manualRedactions.getEntriesToAdd().stream().anyMatch(entryToAdd -> entryToAdd.getId().equalsIgnoreCase(entry.getId()));
|
||||
return !manualRedactionExists;
|
||||
}
|
||||
|
||||
if (entry.getManualRedactionType() == ManualRedactionType.FORCE_REDACT) {
|
||||
var forceRedactExists = manualRedactions.getForceRedacts().stream().anyMatch(entryToAdd -> entryToAdd.getId().equalsIgnoreCase(entry.getId()));
|
||||
if (!forceRedactExists) {
|
||||
entry.setRedacted(false);
|
||||
entry.setManual(false);
|
||||
entry.setStatus(null);
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.getManualRedactionType() == ManualRedactionType.REMOVE) {
|
||||
var removeIdExists = manualRedactions.getIdsToRemove().stream().anyMatch(entryToAdd -> entryToAdd.getId().equalsIgnoreCase(entry.getId()));
|
||||
if (!removeIdExists) {
|
||||
entry.setRedacted(true);
|
||||
entry.setManual(false);
|
||||
entry.setStatus(null);
|
||||
}
|
||||
}
|
||||
|
||||
// Cannot undo Already Approved change because UI won't allow it for now
|
||||
if (Status.REQUESTED.equals(entry.getStatus())) {
|
||||
if (entry.getManualRedactionType() == ManualRedactionType.RECATEGORIZE) {
|
||||
var recategorizeExists = manualRedactions.getImageRecategorizations().stream().anyMatch(entryToAdd -> entryToAdd.getId().equalsIgnoreCase(entry.getId()));
|
||||
if (!recategorizeExists) {
|
||||
entry.setManual(false);
|
||||
entry.setStatus(null);
|
||||
entry.setRecategorizationType(null);
|
||||
}
|
||||
}
|
||||
if (entry.getManualRedactionType() == ManualRedactionType.LEGAL_BASIS_CHANGE) {
|
||||
var legalBasisChangeExists = manualRedactions.getImageRecategorizations().stream().anyMatch(entryToAdd -> entryToAdd.getId().equalsIgnoreCase(entry.getId()));
|
||||
if (!legalBasisChangeExists) {
|
||||
entry.setManual(false);
|
||||
entry.setStatus(null);
|
||||
entry.setLegalBasisChangeValue(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return dictionaryService.getColor(type, dossierTemplateId);
|
||||
}
|
||||
|
||||
|
||||
private void handleAddToDictionary(RedactionLog redactionLog, ManualRedactions manualRedactions, String dossierTemplateId) {
|
||||
private boolean isHint(String type, String dossierTemplateId) {
|
||||
|
||||
for (var manualRedaction : manualRedactions.getEntriesToAdd()) {
|
||||
|
||||
// not yet processed, and dictionary modifying, show in redaction-log preview
|
||||
if (manualRedaction.getProcessedDate() == null && manualRedaction.isAddToDictionary() || manualRedaction.isAddToDossierDictionary()) {
|
||||
var redactionLogEntry = createRedactionLogEntry(manualRedaction, manualRedaction.getId(), dossierTemplateId);
|
||||
redactionLogEntry.setDictionaryEntry(manualRedaction.isAddToDictionary());
|
||||
redactionLogEntry.setDossierDictionaryEntry(manualRedaction.isAddToDossierDictionary());
|
||||
redactionLogEntry.setPositions(manualRedaction.getPositions());
|
||||
|
||||
|
||||
var found = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getId().equalsIgnoreCase(redactionLogEntry.getId())).findAny();
|
||||
if (found.isPresent()) {
|
||||
found.get().setDictionaryEntry(manualRedaction.isAddToDictionary());
|
||||
found.get().setDossierDictionaryEntry(manualRedaction.isAddToDossierDictionary());
|
||||
found.get().setPositions(manualRedaction.getPositions());
|
||||
} else {
|
||||
redactionLog.getRedactionLogEntry().add(redactionLogEntry);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
return dictionaryService.isHint(type, dossierTemplateId);
|
||||
}
|
||||
|
||||
public static class PreviewReasonHolder implements ReasonHolder {
|
||||
|
||||
private final RedactionLogEntry entry;
|
||||
private boolean isRecommendation(String type, String dossierTemplateId) {
|
||||
|
||||
public PreviewReasonHolder(RedactionLogEntry entry) {
|
||||
this.entry = entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRedactionReason() {
|
||||
return entry.getReason();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRedactionReason(String reason) {
|
||||
entry.setReason(reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRedaction() {
|
||||
return entry.isRedacted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRedaction(boolean value) {
|
||||
entry.setRedacted(value);
|
||||
}
|
||||
return dictionaryService.isRecommendation(type, dossierTemplateId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+341
@@ -0,0 +1,341 @@
|
||||
package com.iqser.red.service.redaction.v1.server.redaction.service;
|
||||
|
||||
import com.iqser.red.service.redaction.v1.model.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class RedactionLogMergeService {
|
||||
|
||||
private final DictionaryService dictionaryService;
|
||||
private final SectionTextService sectionTextService;
|
||||
|
||||
public RedactionLog mergeRedactionLogData(RedactionLog redactionLog, SectionGrid sectionGrid, String dossierTemplateId,
|
||||
ManualRedactions manualRedactions, Set<Integer> excludedPages) {
|
||||
|
||||
log.info("Merging Redaction log with manual redactions {}", manualRedactions);
|
||||
if (manualRedactions != null) {
|
||||
|
||||
var manualRedactionLogEntries = addManualAddEntries(sectionGrid, manualRedactions.getEntriesToAdd(), manualRedactions.getComments(), dossierTemplateId);
|
||||
|
||||
redactionLog.getRedactionLogEntry().addAll(manualRedactionLogEntries);
|
||||
|
||||
var manualRedactionWrappers = createManualRedactionWrappers(manualRedactions);
|
||||
|
||||
for (RedactionLogEntry entry : redactionLog.getRedactionLogEntry()) {
|
||||
|
||||
processRedactionLogEntry(manualRedactionWrappers.stream()
|
||||
.filter(mr -> entry.getId().equals(mr.getId()))
|
||||
.collect(Collectors.toList()), dossierTemplateId, entry);
|
||||
|
||||
entry.setComments(manualRedactions.getComments().get(entry.getId()));
|
||||
|
||||
if (excludedPages != null && !excludedPages.isEmpty()) {
|
||||
entry.getPositions().forEach(pos -> {
|
||||
if (excludedPages.contains(pos.getPage())) {
|
||||
entry.setExcluded(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Set<String> processedIds = new HashSet<>();
|
||||
redactionLog.getRedactionLogEntry().removeIf(entry -> {
|
||||
if(processedIds.contains(entry.getId())){
|
||||
return true;
|
||||
}
|
||||
processedIds.add(entry.getId());
|
||||
return false;
|
||||
});
|
||||
return redactionLog;
|
||||
}
|
||||
|
||||
|
||||
private List<ManualRedactionWrapper> createManualRedactionWrappers(ManualRedactions manualRedactions) {
|
||||
|
||||
List<ManualRedactionWrapper> manualRedactionWrappers = new ArrayList<>();
|
||||
|
||||
manualRedactions.getImageRecategorizations().forEach(item -> {
|
||||
if (item.getSoftDeletedTime() == null) {
|
||||
manualRedactionWrappers.add(new ManualRedactionWrapper(item.getId(), item.getRequestDate(), item));
|
||||
}
|
||||
});
|
||||
|
||||
manualRedactions.getIdsToRemove().forEach(item -> {
|
||||
if (item.getSoftDeletedTime() == null) {
|
||||
manualRedactionWrappers.add(new ManualRedactionWrapper(item.getId(), item.getRequestDate(), item));
|
||||
}
|
||||
});
|
||||
|
||||
manualRedactions.getForceRedacts().forEach(item -> {
|
||||
if (item.getSoftDeletedTime() == null) {
|
||||
manualRedactionWrappers.add(new ManualRedactionWrapper(item.getId(), item.getRequestDate(), item));
|
||||
}
|
||||
});
|
||||
|
||||
manualRedactions.getManualLegalBasisChanges().forEach(item -> {
|
||||
if (item.getSoftDeletedTime() == null) {
|
||||
manualRedactionWrappers.add(new ManualRedactionWrapper(item.getId(), item.getRequestDate(), item));
|
||||
}
|
||||
});
|
||||
|
||||
Collections.sort(manualRedactionWrappers);
|
||||
|
||||
return manualRedactionWrappers;
|
||||
}
|
||||
|
||||
|
||||
private void processRedactionLogEntry(List<ManualRedactionWrapper> manualRedactionWrappers,
|
||||
String dossierTemplateId, RedactionLogEntry redactionLogEntry) {
|
||||
|
||||
manualRedactionWrappers.forEach(mrw -> {
|
||||
|
||||
if (mrw.getItem() instanceof ManualImageRecategorization) {
|
||||
var imageRecategorization = (ManualImageRecategorization) mrw.getItem();
|
||||
String manualOverrideReason = null;
|
||||
if (imageRecategorization.getStatus().equals(Status.APPROVED)) {
|
||||
redactionLogEntry.setStatus(Status.APPROVED);
|
||||
redactionLogEntry.setType(imageRecategorization.getType());
|
||||
redactionLogEntry.setHasBeenRecategorized(true);
|
||||
// RED-2622
|
||||
redactionLogEntry.setSection("Image:" + redactionLogEntry.getType());
|
||||
manualOverrideReason = mergeReasonIfNecessary(redactionLogEntry.getReason(), ", recategorized by manual override");
|
||||
} else if (imageRecategorization.getStatus().equals(Status.REQUESTED)) {
|
||||
manualOverrideReason = mergeReasonIfNecessary(redactionLogEntry.getReason(), ", requested to recategorize");
|
||||
redactionLogEntry.setStatus(Status.REQUESTED);
|
||||
redactionLogEntry.setColor(getColor(redactionLogEntry.getType(), dossierTemplateId, false, redactionLogEntry
|
||||
.isRedacted(), false));
|
||||
redactionLogEntry.setRecategorizationType(imageRecategorization.getType());
|
||||
} else {
|
||||
redactionLogEntry.setStatus(Status.DECLINED);
|
||||
}
|
||||
|
||||
redactionLogEntry.setManualRedactionUserId(imageRecategorization.getUser());
|
||||
redactionLogEntry.setReason(manualOverrideReason);
|
||||
redactionLogEntry.setManual(true);
|
||||
redactionLogEntry.setManualRedactionType(ManualRedactionType.RECATEGORIZE);
|
||||
}
|
||||
|
||||
if (mrw.getItem() instanceof IdRemoval) {
|
||||
var manualRemoval = (IdRemoval) mrw.getItem();
|
||||
String manualOverrideReason = null;
|
||||
if (manualRemoval.getStatus().equals(Status.APPROVED)) {
|
||||
redactionLogEntry.setRedacted(false);
|
||||
redactionLogEntry.setStatus(Status.APPROVED);
|
||||
manualOverrideReason = mergeReasonIfNecessary(redactionLogEntry.getReason(), ", removed by manual override");
|
||||
redactionLogEntry.setColor(getColor(redactionLogEntry.getType(), dossierTemplateId, false, redactionLogEntry
|
||||
.isRedacted(), true));
|
||||
redactionLogEntry.setHasBeenRemovedByManualOverride(true);
|
||||
} else if (manualRemoval.getStatus().equals(Status.REQUESTED)) {
|
||||
manualOverrideReason = mergeReasonIfNecessary(redactionLogEntry.getReason(), ", requested to remove");
|
||||
redactionLogEntry.setStatus(Status.REQUESTED);
|
||||
redactionLogEntry.setColor(getColor(redactionLogEntry.getType(), dossierTemplateId, true, redactionLogEntry
|
||||
.isRedacted(), false));
|
||||
} else {
|
||||
redactionLogEntry.setStatus(Status.DECLINED);
|
||||
}
|
||||
|
||||
redactionLogEntry.setReason(manualOverrideReason);
|
||||
redactionLogEntry.setManual(true);
|
||||
redactionLogEntry.setManualRedactionUserId(manualRemoval.getUser());
|
||||
redactionLogEntry.setManualRedactionType(ManualRedactionType.REMOVE);
|
||||
redactionLogEntry.setDictionaryEntry(manualRemoval.isRemoveFromDictionary());
|
||||
redactionLogEntry.setDossierDictionaryEntry(manualRemoval.isRemoveFromDictionary());
|
||||
}
|
||||
|
||||
if (mrw.getItem() instanceof ManualForceRedact) {
|
||||
var manualForceRedact = (ManualForceRedact) mrw.getItem();
|
||||
String manualOverrideReason = null;
|
||||
if (manualForceRedact.getStatus().equals(Status.APPROVED)) {
|
||||
redactionLogEntry.setRedacted(true);
|
||||
redactionLogEntry.setStatus(Status.APPROVED);
|
||||
redactionLogEntry.setColor(getColor(redactionLogEntry.getType(), dossierTemplateId, false, redactionLogEntry
|
||||
.isRedacted(), false));
|
||||
manualOverrideReason = mergeReasonIfNecessary(redactionLogEntry.getReason(), ", forced by manual override");
|
||||
redactionLogEntry.setLegalBasis(manualForceRedact.getLegalBasis());
|
||||
redactionLogEntry.setHasBeenForced(true);
|
||||
} else if (manualForceRedact.getStatus().equals(Status.REQUESTED)) {
|
||||
manualOverrideReason = mergeReasonIfNecessary(redactionLogEntry.getReason(), ", requested to force redact");
|
||||
redactionLogEntry.setStatus(Status.REQUESTED);
|
||||
redactionLogEntry.setColor(getColor(redactionLogEntry.getType(), dossierTemplateId, true, redactionLogEntry
|
||||
.isRedacted(), false));
|
||||
redactionLogEntry.setLegalBasis(manualForceRedact.getLegalBasis());
|
||||
} else {
|
||||
redactionLogEntry.setStatus(Status.DECLINED);
|
||||
}
|
||||
|
||||
redactionLogEntry.setManualRedactionUserId(manualForceRedact.getUser());
|
||||
redactionLogEntry.setReason(manualOverrideReason);
|
||||
redactionLogEntry.setManual(true);
|
||||
redactionLogEntry.setManualRedactionType(ManualRedactionType.FORCE_REDACT);
|
||||
|
||||
}
|
||||
|
||||
if (mrw.getItem() instanceof ManualLegalBasisChange) {
|
||||
var manualLegalBasisChange = (ManualLegalBasisChange) mrw.getItem();
|
||||
String manualOverrideReason = null;
|
||||
if (manualLegalBasisChange.getStatus().equals(Status.APPROVED)) {
|
||||
redactionLogEntry.setStatus(Status.APPROVED);
|
||||
redactionLogEntry.setRedacted(true);
|
||||
manualOverrideReason = mergeReasonIfNecessary(redactionLogEntry.getReason(), ", legal basis was manually changed");
|
||||
redactionLogEntry.setLegalBasis(manualLegalBasisChange.getLegalBasis());
|
||||
if (manualLegalBasisChange.getSection() != null) {
|
||||
redactionLogEntry.setSection(manualLegalBasisChange.getSection());
|
||||
}
|
||||
if (redactionLogEntry.isRectangle() && manualLegalBasisChange.getValue() != null) {
|
||||
redactionLogEntry.setValue(manualLegalBasisChange.getValue());
|
||||
}
|
||||
redactionLogEntry.setHasLegalBasisChanged(true);
|
||||
} else if (manualLegalBasisChange.getStatus().equals(Status.REQUESTED)) {
|
||||
manualOverrideReason = mergeReasonIfNecessary(redactionLogEntry.getReason(), ", legal basis change requested");
|
||||
redactionLogEntry.setStatus(Status.REQUESTED);
|
||||
redactionLogEntry.setColor(getColor(redactionLogEntry.getType(), dossierTemplateId, true, redactionLogEntry
|
||||
.isRedacted(), false));
|
||||
redactionLogEntry.setLegalBasisChangeValue(manualLegalBasisChange.getLegalBasis());
|
||||
} else {
|
||||
redactionLogEntry.setStatus(Status.DECLINED);
|
||||
}
|
||||
|
||||
|
||||
redactionLogEntry.setManualRedactionUserId(manualLegalBasisChange.getUser());
|
||||
redactionLogEntry.setReason(manualOverrideReason);
|
||||
redactionLogEntry.setManual(true);
|
||||
redactionLogEntry.setManualRedactionType(ManualRedactionType.LEGAL_BASIS_CHANGE);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
private String mergeReasonIfNecessary(String currentReason, String addition) {
|
||||
|
||||
if (currentReason != null) {
|
||||
if (!currentReason.contains(addition)) {
|
||||
return currentReason + addition;
|
||||
}
|
||||
return currentReason;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private List<RedactionLogEntry> addManualAddEntries(SectionGrid sectionGrid,
|
||||
Set<ManualRedactionEntry> manualAdds,
|
||||
Map<String, List<Comment>> comments, String dossierTemplateId) {
|
||||
|
||||
List<RedactionLogEntry> redactionLogEntries = new ArrayList<>();
|
||||
|
||||
for (ManualRedactionEntry manualRedactionEntry : manualAdds) {
|
||||
|
||||
if (!approvedAndShouldBeInDictionary(manualRedactionEntry)) {
|
||||
|
||||
RedactionLogEntry redactionLogEntry = createRedactionLogEntry(manualRedactionEntry, manualRedactionEntry
|
||||
.getId(), dossierTemplateId);
|
||||
redactionLogEntry.setComments(comments.get(manualRedactionEntry.getId()));
|
||||
|
||||
sectionTextService.handleSectionText(sectionGrid, redactionLogEntry);
|
||||
|
||||
redactionLogEntries.add(redactionLogEntry);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return redactionLogEntries;
|
||||
}
|
||||
|
||||
|
||||
private boolean approvedAndShouldBeInDictionary(ManualRedactionEntry manualRedactionEntry) {
|
||||
|
||||
return manualRedactionEntry.getStatus()
|
||||
.equals(Status.APPROVED) && (manualRedactionEntry.isAddToDictionary() || manualRedactionEntry.isAddToDossierDictionary());
|
||||
}
|
||||
|
||||
|
||||
private RedactionLogEntry createRedactionLogEntry(ManualRedactionEntry manualRedactionEntry, String id,
|
||||
String dossierTemplateId) {
|
||||
|
||||
return RedactionLogEntry.builder()
|
||||
.id(id)
|
||||
.color(getColorForManualAdd(manualRedactionEntry.getType(), dossierTemplateId, manualRedactionEntry.getStatus()))
|
||||
.reason(manualRedactionEntry.getReason())
|
||||
.isDictionaryEntry(manualRedactionEntry.isAddToDictionary())
|
||||
.isDossierDictionaryEntry(manualRedactionEntry.isAddToDossierDictionary())
|
||||
.legalBasis(manualRedactionEntry.getLegalBasis())
|
||||
.value(manualRedactionEntry.getValue())
|
||||
.section(manualRedactionEntry.getSection())
|
||||
.type(manualRedactionEntry.getType())
|
||||
.rectangle(manualRedactionEntry.isRectangle())
|
||||
.redacted(true)
|
||||
.isHint(false)
|
||||
.sectionNumber(-1)
|
||||
.manual(true)
|
||||
.status(manualRedactionEntry.getStatus())
|
||||
.manualRedactionType(ManualRedactionType.ADD)
|
||||
.positions(manualRedactionEntry.getPositions())
|
||||
.manualRedactionUserId(manualRedactionEntry.getUser())
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
private float[] getColor(String type, String dossierTemplateId, boolean requested, boolean isRedaction,
|
||||
boolean skipped) {
|
||||
|
||||
if (requested) {
|
||||
return dictionaryService.getRequestRemoveColor(dossierTemplateId);
|
||||
}
|
||||
if (skipped || !isRedaction && !dictionaryService.isHint(type, dossierTemplateId)) {
|
||||
return dictionaryService.getNotRedactedColor(dossierTemplateId);
|
||||
}
|
||||
return dictionaryService.getColor(type, dossierTemplateId);
|
||||
}
|
||||
|
||||
|
||||
private float[] getColorForManualAdd(String type, String dossierTemplateId, Status status) {
|
||||
|
||||
if (status.equals(Status.REQUESTED)) {
|
||||
return dictionaryService.getRequestAddColor(dossierTemplateId);
|
||||
} else if (status.equals(Status.DECLINED)) {
|
||||
return dictionaryService.getNotRedactedColor(dossierTemplateId);
|
||||
}
|
||||
return getColor(type, dossierTemplateId);
|
||||
}
|
||||
|
||||
|
||||
private float[] getColor(String type, String dossierTemplateId) {
|
||||
|
||||
return dictionaryService.getColor(type, dossierTemplateId);
|
||||
}
|
||||
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
private static class ManualRedactionWrapper implements Comparable<ManualRedactionWrapper> {
|
||||
|
||||
private String id;
|
||||
private OffsetDateTime date;
|
||||
private Object item;
|
||||
|
||||
|
||||
@Override
|
||||
public int compareTo(ManualRedactionWrapper o) {
|
||||
|
||||
return this.date.compareTo(o.date);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package com.iqser.red.service.redaction.v1.server.redaction.service;
|
||||
|
||||
import com.iqser.red.service.redaction.v1.model.RedactionLogEntry;
|
||||
import com.iqser.red.service.redaction.v1.model.SectionGrid;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class SectionTextService {
|
||||
|
||||
|
||||
public void handleSectionText(SectionGrid sectionGrid, RedactionLogEntry redactionLogEntry) {
|
||||
|
||||
log.info("Handling manual redaction match for sections: {} and entry section: {}, positions: {}",
|
||||
sectionGrid != null ? sectionGrid.getSections().size() : "null", redactionLogEntry.getSection(), redactionLogEntry.getPositions());
|
||||
|
||||
if (redactionLogEntry.getSection() != null) {
|
||||
// set by UI
|
||||
return;
|
||||
}
|
||||
|
||||
if (sectionGrid != null) {
|
||||
var firstPosition = !redactionLogEntry.getPositions().isEmpty() ? redactionLogEntry.getPositions().iterator().next() : null;
|
||||
|
||||
if (firstPosition != null) {
|
||||
|
||||
for (var section : sectionGrid.getSections()) {
|
||||
if (section.getPages().contains(firstPosition.getPage())) {
|
||||
for (var sectionArea : section.getSectionAreas()) {
|
||||
if (sectionArea.contains(firstPosition)) {
|
||||
redactionLogEntry.setSection(section.getHeadline());
|
||||
redactionLogEntry.setSectionNumber(section.getSectionNumber());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -12,7 +12,7 @@ public class TextNormalizationUtilities {
|
||||
* @return Text without line-break hyphenation.
|
||||
*/
|
||||
public static String removeHyphenLineBreaks(String text) {
|
||||
return text.replaceAll("([^\\s\\d\\-]{2,})[\\-\\u00AD]\\R|\n\r(.+ )", "$1$2");
|
||||
return text.replaceAll("([^\\s\\d\\-]{2,})[\\-\\u00AD]\\R", "$1");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
@@ -15,4 +15,6 @@ public class RedactionServiceSettings {
|
||||
|
||||
private float maxImageCropboxRatio = 0.9f;
|
||||
|
||||
private int analysisVersion = 1;
|
||||
|
||||
}
|
||||
|
||||
-1
@@ -83,7 +83,6 @@ public class RedactionStorageService {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public enum StorageType {
|
||||
PARSED_DOCUMENT(".json");
|
||||
|
||||
+137
-47
@@ -18,8 +18,11 @@ import com.iqser.red.service.redaction.v1.server.redaction.utils.ResourceLoader;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.utils.TextNormalizationUtilities;
|
||||
import com.iqser.red.service.redaction.v1.server.storage.RedactionStorageService;
|
||||
import com.iqser.red.storage.commons.service.StorageService;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
@@ -84,7 +87,6 @@ public class RedactionIntegrationTest {
|
||||
|
||||
private static final String PII = "PII";
|
||||
|
||||
|
||||
@Autowired
|
||||
private RedactionController redactionController;
|
||||
|
||||
@@ -127,6 +129,7 @@ public class RedactionIntegrationTest {
|
||||
private final Map<String, Integer> rankTypeMap = new HashMap<>();
|
||||
private final Colors colors = new Colors();
|
||||
private final Map<String, Long> reanlysisVersions = new HashMap<>();
|
||||
private final Set<String> deleted = new HashSet<>();
|
||||
|
||||
private final static String TEST_DOSSIER_TEMPLATE_ID = "123";
|
||||
private final static String TEST_DOSSIER_ID = "123";
|
||||
@@ -152,18 +155,20 @@ public class RedactionIntegrationTest {
|
||||
return kieServices.newKieContainer(kieModule.getReleaseId());
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public StorageService inmemoryStorage() {
|
||||
|
||||
return new FileSystemBackedStorageService();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@After
|
||||
public void cleanupStorage() {
|
||||
|
||||
if (this.storageService instanceof FileSystemBackedStorageService) {
|
||||
((FileSystemBackedStorageService) this.storageService).clearStorage();
|
||||
}
|
||||
@@ -179,7 +184,8 @@ public class RedactionIntegrationTest {
|
||||
loadDictionaryForTest();
|
||||
loadTypeForTest();
|
||||
when(dictionaryClient.getVersion(TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(0L);
|
||||
when(dictionaryClient.getAllTypes(TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(TypeResponse.builder()
|
||||
when(dictionaryClient.getAllTypes(TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(TypeResponse
|
||||
.builder()
|
||||
.types(getTypeResponse())
|
||||
.build());
|
||||
|
||||
@@ -188,7 +194,7 @@ public class RedactionIntegrationTest {
|
||||
.types(List.of(TypeResult.builder()
|
||||
.type(DOSSIER_REDACTIONS)
|
||||
.dossierTemplateId(TEST_DOSSIER_TEMPLATE_ID)
|
||||
.hexColor( "#ffe187")
|
||||
.hexColor("#ffe187")
|
||||
.isHint(hintTypeMap.get(DOSSIER_REDACTIONS))
|
||||
.isCaseInsensitive(caseInSensitiveMap.get(DOSSIER_REDACTIONS))
|
||||
.isRecommendation(recommendationTypeMap.get(DOSSIER_REDACTIONS))
|
||||
@@ -196,26 +202,42 @@ public class RedactionIntegrationTest {
|
||||
.build()))
|
||||
.build());
|
||||
|
||||
when(dictionaryClient.getDictionaryForType(VERTEBRATE, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(VERTEBRATE, false));
|
||||
when(dictionaryClient.getDictionaryForType(ADDRESS, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(ADDRESS, false));
|
||||
when(dictionaryClient.getDictionaryForType(AUTHOR, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(AUTHOR, false));
|
||||
when(dictionaryClient.getDictionaryForType(SPONSOR, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(SPONSOR, false));
|
||||
when(dictionaryClient.getDictionaryForType(NO_REDACTION_INDICATOR, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(NO_REDACTION_INDICATOR, false));
|
||||
when(dictionaryClient.getDictionaryForType(REDACTION_INDICATOR, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(REDACTION_INDICATOR, false));
|
||||
when(dictionaryClient.getDictionaryForType(HINT_ONLY, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(HINT_ONLY, false));
|
||||
when(dictionaryClient.getDictionaryForType(MUST_REDACT, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(MUST_REDACT, false));
|
||||
when(dictionaryClient.getDictionaryForType(PUBLISHED_INFORMATION, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(PUBLISHED_INFORMATION, false));
|
||||
when(dictionaryClient.getDictionaryForType(TEST_METHOD, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(TEST_METHOD, false));
|
||||
when(dictionaryClient.getDictionaryForType(VERTEBRATE, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER))
|
||||
.thenReturn(getDictionaryResponse(VERTEBRATE, false));
|
||||
when(dictionaryClient.getDictionaryForType(ADDRESS, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER))
|
||||
.thenReturn(getDictionaryResponse(ADDRESS, false));
|
||||
when(dictionaryClient.getDictionaryForType(AUTHOR, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER))
|
||||
.thenReturn(getDictionaryResponse(AUTHOR, false));
|
||||
when(dictionaryClient.getDictionaryForType(SPONSOR, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER))
|
||||
.thenReturn(getDictionaryResponse(SPONSOR, false));
|
||||
when(dictionaryClient.getDictionaryForType(NO_REDACTION_INDICATOR, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER))
|
||||
.thenReturn(getDictionaryResponse(NO_REDACTION_INDICATOR, false));
|
||||
when(dictionaryClient.getDictionaryForType(REDACTION_INDICATOR, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER))
|
||||
.thenReturn(getDictionaryResponse(REDACTION_INDICATOR, false));
|
||||
when(dictionaryClient.getDictionaryForType(HINT_ONLY, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER))
|
||||
.thenReturn(getDictionaryResponse(HINT_ONLY, false));
|
||||
when(dictionaryClient.getDictionaryForType(MUST_REDACT, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER))
|
||||
.thenReturn(getDictionaryResponse(MUST_REDACT, false));
|
||||
when(dictionaryClient.getDictionaryForType(PUBLISHED_INFORMATION, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER))
|
||||
.thenReturn(getDictionaryResponse(PUBLISHED_INFORMATION, false));
|
||||
when(dictionaryClient.getDictionaryForType(TEST_METHOD, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER))
|
||||
.thenReturn(getDictionaryResponse(TEST_METHOD, false));
|
||||
when(dictionaryClient.getDictionaryForType(PII, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(PII, false));
|
||||
when(dictionaryClient.getDictionaryForType(RECOMMENDATION_AUTHOR, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(RECOMMENDATION_AUTHOR, false));
|
||||
when(dictionaryClient.getDictionaryForType(RECOMMENDATION_ADDRESS, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(RECOMMENDATION_ADDRESS, false));
|
||||
when(dictionaryClient.getDictionaryForType(FALSE_POSITIVE, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(FALSE_POSITIVE, false));
|
||||
when(dictionaryClient.getDictionaryForType(PURITY, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(PURITY, false));
|
||||
when(dictionaryClient.getDictionaryForType(RECOMMENDATION_AUTHOR, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER))
|
||||
.thenReturn(getDictionaryResponse(RECOMMENDATION_AUTHOR, false));
|
||||
when(dictionaryClient.getDictionaryForType(RECOMMENDATION_ADDRESS, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER))
|
||||
.thenReturn(getDictionaryResponse(RECOMMENDATION_ADDRESS, false));
|
||||
when(dictionaryClient.getDictionaryForType(FALSE_POSITIVE, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER))
|
||||
.thenReturn(getDictionaryResponse(FALSE_POSITIVE, false));
|
||||
when(dictionaryClient.getDictionaryForType(PURITY, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER))
|
||||
.thenReturn(getDictionaryResponse(PURITY, false));
|
||||
when(dictionaryClient.getDictionaryForType(IMAGE, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(IMAGE, false));
|
||||
when(dictionaryClient.getDictionaryForType(OCR, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(OCR, false));
|
||||
when(dictionaryClient.getDictionaryForType(LOGO, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(LOGO, false));
|
||||
when(dictionaryClient.getDictionaryForType(SIGNATURE, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(SIGNATURE, false));
|
||||
when(dictionaryClient.getDictionaryForType(FORMULA, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(FORMULA, false));
|
||||
when(dictionaryClient.getDictionaryForType(SIGNATURE, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER))
|
||||
.thenReturn(getDictionaryResponse(SIGNATURE, false));
|
||||
when(dictionaryClient.getDictionaryForType(FORMULA, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER))
|
||||
.thenReturn(getDictionaryResponse(FORMULA, false));
|
||||
when(dictionaryClient.getDictionaryForType(DOSSIER_REDACTIONS, TEST_DOSSIER_TEMPLATE_ID, TEST_DOSSIER_ID)).thenReturn(getDictionaryResponse(DOSSIER_REDACTIONS, true));
|
||||
when(dictionaryClient.getColors(TEST_DOSSIER_TEMPLATE_ID)).thenReturn(colors);
|
||||
}
|
||||
@@ -477,7 +499,8 @@ public class RedactionIntegrationTest {
|
||||
|
||||
return DictionaryResponse.builder()
|
||||
.hexColor(typeColorMap.get(type))
|
||||
.entries(isDossierDictionary ? toDictionaryEntry(dossierDictionary.get(type)) : toDictionaryEntry(dictionary.get(type)))
|
||||
.entries(isDossierDictionary ? toDictionaryEntry(dossierDictionary.get(type)) : toDictionaryEntry(dictionary
|
||||
.get(type)))
|
||||
.isHint(hintTypeMap.get(type))
|
||||
.isCaseInsensitive(caseInSensitiveMap.get(type))
|
||||
.isRecommendation(recommendationTypeMap.get(type))
|
||||
@@ -490,7 +513,8 @@ public class RedactionIntegrationTest {
|
||||
|
||||
List<DictionaryEntry> dictionaryEntries = new ArrayList<>();
|
||||
entries.forEach(entry -> {
|
||||
dictionaryEntries.add(new DictionaryEntry(entry, reanlysisVersions.containsKey(entry) ? reanlysisVersions.get(entry) : 0L, false));
|
||||
dictionaryEntries.add(new DictionaryEntry(entry, reanlysisVersions.containsKey(entry) ? reanlysisVersions.get(entry) : 0L, deleted
|
||||
.contains(entry) ? true : false));
|
||||
});
|
||||
return dictionaryEntries;
|
||||
}
|
||||
@@ -498,6 +522,7 @@ public class RedactionIntegrationTest {
|
||||
|
||||
@Test
|
||||
public void test270Rotated() {
|
||||
|
||||
AnalyzeRequest request = prepareStorage("files/Minimal Examples/270Rotated.pdf");
|
||||
MemoryStats.printMemoryStats();
|
||||
AnalyzeResult result = reanalyzeService.analyze(request);
|
||||
@@ -508,12 +533,14 @@ public class RedactionIntegrationTest {
|
||||
@Test
|
||||
@Ignore
|
||||
public void testLargeScannedFileOOM() {
|
||||
|
||||
AnalyzeRequest request = prepareStorage("scanned/VV-377031.pdf");
|
||||
MemoryStats.printMemoryStats();
|
||||
AnalyzeResult result = reanalyzeService.analyze(request);
|
||||
assertThat(result).isNotNull();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMergedImages() throws IOException {
|
||||
|
||||
@@ -543,7 +570,7 @@ public class RedactionIntegrationTest {
|
||||
.fileId(TEST_FILE_ID)
|
||||
.build());
|
||||
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream("/tmp/Annotated3.pdf")) {
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/Annotated3.pdf")) {
|
||||
fileOutputStream.write(annotateResponse.getDocument());
|
||||
}
|
||||
long rstart = System.currentTimeMillis();
|
||||
@@ -552,14 +579,13 @@ public class RedactionIntegrationTest {
|
||||
long rend = System.currentTimeMillis();
|
||||
System.out.println("reanalysis analysis duration: " + (rend - rstart));
|
||||
|
||||
|
||||
long end = System.currentTimeMillis();
|
||||
|
||||
System.out.println("duration: " + (end - start));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void noExceptionShouldBeThrownForAnyFiles() throws IOException {
|
||||
@@ -631,11 +657,16 @@ public class RedactionIntegrationTest {
|
||||
public void redactionTest() throws IOException {
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
ClassPathResource pdfFileResource = new ClassPathResource("files/new/Single Study - Oral (Gavage) Mouse.pdf");
|
||||
ClassPathResource pdfFileResource = new ClassPathResource("files/new/VV-919901.pdf");
|
||||
AnalyzeRequest request = prepareStorage(pdfFileResource.getInputStream());
|
||||
request.setExcludedPages(Set.of(1));
|
||||
|
||||
request.setFileAttributes(List.of(FileAttribute.builder().id("fileAttributeId").label("Vertebrate Study").placeholder("{fileattributes.vertebrateStudy}").value("true").build()));
|
||||
request.setFileAttributes(List.of(FileAttribute.builder()
|
||||
.id("fileAttributeId")
|
||||
.label("Vertebrate Study")
|
||||
.placeholder("{fileattributes.vertebrateStudy}")
|
||||
.value("true")
|
||||
.build()));
|
||||
|
||||
AnalyzeResult result = reanalyzeService.analyze(request);
|
||||
|
||||
@@ -652,7 +683,7 @@ public class RedactionIntegrationTest {
|
||||
|
||||
System.out.println("first analysis duration: " + (end - start));
|
||||
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream("/tmp/Test.json")) {
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/Test.json")) {
|
||||
fileOutputStream.write(objectMapper.writeValueAsBytes(redactionStorageService.getText(TEST_DOSSIER_ID, TEST_FILE_ID)));
|
||||
}
|
||||
|
||||
@@ -683,12 +714,18 @@ public class RedactionIntegrationTest {
|
||||
dictionary.get(AUTHOR).add("physical");
|
||||
reanlysisVersions.put("physical", 2L);
|
||||
|
||||
// dictionary.get(VERTEBRATE).add("s-metolachlor");
|
||||
// reanlysisVersions.put("s-metolachlor", 3L);
|
||||
deleted.add("David Chubb");
|
||||
|
||||
dictionary.get(FALSE_POSITIVE).add("David Chubb");
|
||||
reanlysisVersions.put("David Chubb", 3L);
|
||||
|
||||
when(dictionaryClient.getVersion(TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(3L);
|
||||
|
||||
when(dictionaryClient.getDictionaryForType(VERTEBRATE, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER)).thenReturn(getDictionaryResponse(VERTEBRATE, false));
|
||||
when(dictionaryClient.getDictionaryForType(VERTEBRATE, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER))
|
||||
.thenReturn(getDictionaryResponse(VERTEBRATE, false));
|
||||
|
||||
when(dictionaryClient.getDictionaryForType(FALSE_POSITIVE, TEST_DOSSIER_TEMPLATE_ID, DictionaryResource.GLOBAL_DOSSIER))
|
||||
.thenReturn(getDictionaryResponse(FALSE_POSITIVE, false));
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
|
||||
@@ -702,10 +739,8 @@ public class RedactionIntegrationTest {
|
||||
|
||||
request.setManualRedactions(manualRedactions);
|
||||
|
||||
|
||||
AnalyzeResult reanalyzeResult = reanalyzeService.reanalyze(request);
|
||||
|
||||
|
||||
redactionLog = redactionStorageService.getRedactionLog(TEST_DOSSIER_ID, TEST_FILE_ID);
|
||||
|
||||
end = System.currentTimeMillis();
|
||||
@@ -716,7 +751,7 @@ public class RedactionIntegrationTest {
|
||||
.fileId(TEST_FILE_ID)
|
||||
.build());
|
||||
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream("/tmp/Annotated.pdf")) {
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/Annotated.pdf")) {
|
||||
fileOutputStream.write(annotateResponse.getDocument());
|
||||
}
|
||||
|
||||
@@ -737,7 +772,7 @@ public class RedactionIntegrationTest {
|
||||
.fileId(TEST_FILE_ID)
|
||||
.build());
|
||||
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream("/tmp/Annotated.pdf")) {
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/Annotated.pdf")) {
|
||||
fileOutputStream.write(annotateResponse.getDocument());
|
||||
}
|
||||
long end = System.currentTimeMillis();
|
||||
@@ -747,6 +782,32 @@ public class RedactionIntegrationTest {
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testIgnoreDossierRedactionIfConfidential() throws IOException {
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
AnalyzeRequest request = prepareStorage("files/new/VV-919901.pdf");
|
||||
AnalyzeResult result = reanalyzeService.analyze(request);
|
||||
|
||||
AnnotateResponse annotateResponse = redactionController.annotate(AnnotateRequest.builder()
|
||||
.dossierId(TEST_DOSSIER_ID)
|
||||
.fileId(TEST_FILE_ID)
|
||||
.build());
|
||||
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/Annotated.pdf")) {
|
||||
fileOutputStream.write(annotateResponse.getDocument());
|
||||
}
|
||||
long end = System.currentTimeMillis();
|
||||
|
||||
System.out.println("duration: " + (end - start));
|
||||
System.out.println("numberOfPages: " + result.getNumberOfPages());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testManualRedaction() throws IOException {
|
||||
|
||||
@@ -775,7 +836,6 @@ public class RedactionIntegrationTest {
|
||||
.status(Status.APPROVED)
|
||||
.build()));
|
||||
|
||||
|
||||
manualRedactions.getComments().put("e5be0f1d941bbb92a068e198648d06c4", List.of(comment));
|
||||
manualRedactions.getComments().put("0836727c3508a0b2ea271da69c04cc2f", List.of(comment));
|
||||
manualRedactions.getComments().put(manualAddId, List.of(comment));
|
||||
@@ -790,12 +850,10 @@ public class RedactionIntegrationTest {
|
||||
|
||||
// manualRedactions.getEntriesToAdd().add(manualRedactionEntry);
|
||||
|
||||
|
||||
AnalyzeRequest request = prepareStorage(pdfFileResource.getInputStream());
|
||||
request.setManualRedactions(manualRedactions);
|
||||
AnalyzeResult result = reanalyzeService.analyze(request);
|
||||
|
||||
|
||||
manualRedactions.getEntriesToAdd().add(manualRedactionEntry);
|
||||
manualRedactions.setIdsToRemove(Set.of(IdRemoval.builder()
|
||||
.id("5b940b2cb401ed9f5be6fc24f6e77bcf")
|
||||
@@ -816,8 +874,7 @@ public class RedactionIntegrationTest {
|
||||
.fileId(TEST_FILE_ID)
|
||||
.build());
|
||||
|
||||
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream("/tmp/Annotated.pdf")) {
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/Annotated.pdf")) {
|
||||
fileOutputStream.write(annotateResponse.getDocument());
|
||||
}
|
||||
long end = System.currentTimeMillis();
|
||||
@@ -833,7 +890,6 @@ public class RedactionIntegrationTest {
|
||||
System.out.println("classificationTest");
|
||||
ClassPathResource pdfFileResource = new ClassPathResource("files/new/Single Study - Oral (Gavage) Mouse.pdf");
|
||||
|
||||
|
||||
AnalyzeRequest request = prepareStorage(pdfFileResource.getInputStream());
|
||||
|
||||
RedactionRequest redactionRequest = RedactionRequest.builder()
|
||||
@@ -844,7 +900,7 @@ public class RedactionIntegrationTest {
|
||||
|
||||
RedactionResult result = redactionController.classify(redactionRequest);
|
||||
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream("/tmp/Classified.pdf")) {
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/Classified.pdf")) {
|
||||
fileOutputStream.write(result.getDocument());
|
||||
}
|
||||
}
|
||||
@@ -866,7 +922,7 @@ public class RedactionIntegrationTest {
|
||||
|
||||
RedactionResult result = redactionController.sections(redactionRequest);
|
||||
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream("/tmp/Sections.pdf")) {
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/Sections.pdf")) {
|
||||
fileOutputStream.write(result.getDocument());
|
||||
}
|
||||
}
|
||||
@@ -888,7 +944,7 @@ public class RedactionIntegrationTest {
|
||||
|
||||
RedactionResult result = redactionController.htmlTables(redactionRequest);
|
||||
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream("/tmp/Tables.html")) {
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/Tables.html")) {
|
||||
fileOutputStream.write(result.getDocument());
|
||||
}
|
||||
}
|
||||
@@ -910,7 +966,7 @@ public class RedactionIntegrationTest {
|
||||
|
||||
RedactionResult result = redactionController.htmlTables(redactionRequest);
|
||||
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream("/tmp/Tables.html")) {
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/Tables.html")) {
|
||||
fileOutputStream.write(result.getDocument());
|
||||
}
|
||||
}
|
||||
@@ -934,8 +990,10 @@ public class RedactionIntegrationTest {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
private AnalyzeRequest prepareStorage(String file) {
|
||||
|
||||
ClassPathResource pdfFileResource = new ClassPathResource(file);
|
||||
|
||||
return prepareStorage(pdfFileResource.getInputStream());
|
||||
@@ -967,7 +1025,6 @@ public class RedactionIntegrationTest {
|
||||
long start = System.currentTimeMillis();
|
||||
ClassPathResource pdfFileResource = new ClassPathResource("files/Minimal Examples/sponsor_companies.pdf");
|
||||
|
||||
|
||||
AnalyzeRequest request = prepareStorage(pdfFileResource.getInputStream());
|
||||
|
||||
AnalyzeResult result = reanalyzeService.analyze(request);
|
||||
@@ -977,7 +1034,31 @@ public class RedactionIntegrationTest {
|
||||
.fileId(TEST_FILE_ID)
|
||||
.build());
|
||||
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream("/tmp/Annotated.pdf")) {
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/Annotated.pdf")) {
|
||||
fileOutputStream.write(annotateResponse.getDocument());
|
||||
}
|
||||
long end = System.currentTimeMillis();
|
||||
|
||||
System.out.println("duration: " + (end - start));
|
||||
System.out.println("numberOfPages: " + result.getNumberOfPages());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testExpandByRegEx() throws IOException {
|
||||
|
||||
System.out.println("expandByRegex");
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
AnalyzeRequest request = prepareStorage("files/Metolachlor/S-Metolachlor_RAR_02_Volume_2_2018-09-06.pdf");
|
||||
AnalyzeResult result = reanalyzeService.analyze(request);
|
||||
|
||||
AnnotateResponse annotateResponse = redactionController.annotate(AnnotateRequest.builder()
|
||||
.dossierId(TEST_DOSSIER_ID)
|
||||
.fileId(TEST_FILE_ID)
|
||||
.build());
|
||||
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/Annotated.pdf")) {
|
||||
fileOutputStream.write(annotateResponse.getDocument());
|
||||
}
|
||||
long end = System.currentTimeMillis();
|
||||
@@ -1005,4 +1086,13 @@ public class RedactionIntegrationTest {
|
||||
}
|
||||
}
|
||||
|
||||
private static String getTemporaryDirectory() {
|
||||
|
||||
String tmpdir = System.getProperty("java.io.tmpdir");
|
||||
if (StringUtils.isNotBlank(tmpdir)) {
|
||||
return tmpdir;
|
||||
}
|
||||
return "/tmp";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package com.iqser.red.service.redaction.v1.server.redaction.utils;
|
||||
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.iqser.red.service.redaction.v1.model.ManualRedactions;
|
||||
import com.iqser.red.service.redaction.v1.model.RedactionLog;
|
||||
import com.iqser.red.service.redaction.v1.model.SectionGrid;
|
||||
import com.iqser.red.service.redaction.v1.server.Application;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.service.DictionaryService;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.service.RedactionLogMergeService;
|
||||
import com.iqser.red.service.redaction.v1.server.redaction.service.SectionTextService;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.commons.compress.utils.Lists;
|
||||
import org.assertj.core.util.Sets;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.MOCK)
|
||||
@Import(SectionTextServiceTest.TestConfiguration.class)
|
||||
public class SectionTextServiceTest {
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Autowired
|
||||
private SectionTextService service;
|
||||
|
||||
@Autowired
|
||||
private RedactionLogMergeService redactionLogMergeService;
|
||||
|
||||
@MockBean
|
||||
private DictionaryService dictionaryService;
|
||||
|
||||
@MockBean
|
||||
private AmazonS3 amazonS3;
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration(exclude = {RabbitAutoConfiguration.class})
|
||||
public static class TestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
public void testMerge() {
|
||||
|
||||
when(dictionaryService.getColor(Mockito.anyString(), Mockito.anyString())).thenReturn(new float[]{0, 0, 0});
|
||||
|
||||
ManualRedactions manualRedactions = objectMapper.readValue(new ClassPathResource("contains/manual-redactions.json").getInputStream(), ManualRedactions.class);
|
||||
|
||||
RedactionLog redactionLog = new RedactionLog(1, Lists.newArrayList(), Lists.newArrayList(), 1, 1, 1, 1);
|
||||
SectionGrid sectionGrid = objectMapper.readValue(new ClassPathResource("contains/sections.json").getInputStream(), SectionGrid.class);
|
||||
RedactionLog merged = redactionLogMergeService.mergeRedactionLogData(redactionLog, sectionGrid, "1", manualRedactions, Sets.newHashSet());
|
||||
|
||||
assertThat(merged.getRedactionLogEntry().isEmpty()).isFalse();
|
||||
|
||||
assertThat(merged.getRedactionLogEntry().iterator().next().getSection()).isEqualTo("NOTIFICATION OF AN ACTIVE\n" +
|
||||
"SUBSTANCE UNDER COMMISSION\n" +
|
||||
"REGULATION (EU) 844/2012");
|
||||
assertThat(merged.getRedactionLogEntry().iterator().next().getSectionNumber()).isEqualTo(7);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"idsToRemove": [],
|
||||
"entriesToAdd": [
|
||||
{
|
||||
"id": "d5fd9fd9690557703a22d8ab22832c7f",
|
||||
"user": "7adf30b4-a0d8-4abb-adbb-760b1211098f",
|
||||
"type": "manual",
|
||||
"value": "DOCUMENT M-CA, Section 10\nSupplement",
|
||||
"reason": "names and addresses of persons involved in testing on vertebrate animals",
|
||||
"legalBasis": "[Reg (EC) No 1107/2009 Art. 63 (2g)]",
|
||||
"section": null,
|
||||
"positions": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 190.92,
|
||||
"y": 376.7999
|
||||
},
|
||||
"width": 227.49368,
|
||||
"height": 14.974969,
|
||||
"page": 1
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 258.96,
|
||||
"y": 358.31992
|
||||
},
|
||||
"width": 91.47408,
|
||||
"height": 14.974969,
|
||||
"page": 1
|
||||
}
|
||||
],
|
||||
"status": "APPROVED",
|
||||
"addToDictionary": false,
|
||||
"addToDossierDictionary": false,
|
||||
"requestDate": "2021-11-03T15:01:45Z",
|
||||
"processedDate": "2021-11-03T15:01:45Z",
|
||||
"softDeletedTime": null
|
||||
}
|
||||
],
|
||||
"forceRedactions": [],
|
||||
"imageRecategorization": [],
|
||||
"legalBasisChanges": [],
|
||||
"comments": {
|
||||
"d5fd9fd9690557703a22d8ab22832c7f": [
|
||||
{
|
||||
"id": "56c1a675-0d64-4190-b76c-6af9d0b361a9",
|
||||
"date": "2021-11-03T15:01:45Z",
|
||||
"text": "test",
|
||||
"user": "7adf30b4-a0d8-4abb-adbb-760b1211098f",
|
||||
"softDeletedTime": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+877
@@ -0,0 +1,877 @@
|
||||
{
|
||||
"rectanglesPerPage": {
|
||||
"1": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 251.4,
|
||||
"y": 550.32
|
||||
},
|
||||
"width": 107.763336,
|
||||
"height": 12.02002,
|
||||
"part": 1,
|
||||
"numberOfParts": 1,
|
||||
"tableCells": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 159.24,
|
||||
"y": 280.92004
|
||||
},
|
||||
"width": 291.92004,
|
||||
"height": 212.29996,
|
||||
"part": 1,
|
||||
"numberOfParts": 3,
|
||||
"tableCells": null
|
||||
}
|
||||
],
|
||||
"2": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 70.92,
|
||||
"y": 735.36
|
||||
},
|
||||
"width": 105.64288,
|
||||
"height": 9.02002,
|
||||
"part": 2,
|
||||
"numberOfParts": 3,
|
||||
"tableCells": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.56436,
|
||||
"y": 719.9557
|
||||
},
|
||||
"width": 478.4686,
|
||||
"height": -110.91278,
|
||||
"part": 3,
|
||||
"numberOfParts": 3,
|
||||
"tableCells": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.56436,
|
||||
"y": 684.47955
|
||||
},
|
||||
"width": 83.35573,
|
||||
"height": 35.476135
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 148.92009,
|
||||
"y": 684.47955
|
||||
},
|
||||
"width": 255.12016,
|
||||
"height": 35.476135
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 404.04025,
|
||||
"y": 684.47955
|
||||
},
|
||||
"width": 139.9927,
|
||||
"height": 35.476135
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.56436,
|
||||
"y": 659.27954
|
||||
},
|
||||
"width": 83.35573,
|
||||
"height": 25.200012
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 148.92009,
|
||||
"y": 659.27954
|
||||
},
|
||||
"width": 255.12016,
|
||||
"height": 25.200012
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 404.04025,
|
||||
"y": 659.27954
|
||||
},
|
||||
"width": 139.9927,
|
||||
"height": 25.200012
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.56436,
|
||||
"y": 634.20074
|
||||
},
|
||||
"width": 83.35573,
|
||||
"height": 25.078796
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 148.92009,
|
||||
"y": 634.20074
|
||||
},
|
||||
"width": 255.12016,
|
||||
"height": 25.078796
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 404.04025,
|
||||
"y": 634.20074
|
||||
},
|
||||
"width": 139.9927,
|
||||
"height": 25.078796
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.56436,
|
||||
"y": 609.0429
|
||||
},
|
||||
"width": 83.35573,
|
||||
"height": 25.157837
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 148.92009,
|
||||
"y": 609.0429
|
||||
},
|
||||
"width": 255.12016,
|
||||
"height": 25.157837
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 404.04025,
|
||||
"y": 609.0429
|
||||
},
|
||||
"width": 139.9927,
|
||||
"height": 25.157837
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"3": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 70.92,
|
||||
"y": 691.2
|
||||
},
|
||||
"width": 468.76624,
|
||||
"height": 53.179993,
|
||||
"part": 1,
|
||||
"numberOfParts": 3,
|
||||
"tableCells": null
|
||||
}
|
||||
],
|
||||
"4": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 71.04,
|
||||
"y": 555.48
|
||||
},
|
||||
"width": 461.24002,
|
||||
"height": 188.78003,
|
||||
"part": 2,
|
||||
"numberOfParts": 3,
|
||||
"tableCells": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.68587,
|
||||
"y": 540.55756
|
||||
},
|
||||
"width": 478.58698,
|
||||
"height": -365.55508,
|
||||
"part": 3,
|
||||
"numberOfParts": 3,
|
||||
"tableCells": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.68587,
|
||||
"y": 515.4003
|
||||
},
|
||||
"width": 125.808716,
|
||||
"height": 25.157227
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 191.49458,
|
||||
"y": 515.4003
|
||||
},
|
||||
"width": 352.77826,
|
||||
"height": 25.157227
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.68587,
|
||||
"y": 404.75992
|
||||
},
|
||||
"width": 125.808716,
|
||||
"height": 110.64041
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 191.49458,
|
||||
"y": 404.75992
|
||||
},
|
||||
"width": 352.77826,
|
||||
"height": 110.64041
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.68587,
|
||||
"y": 379.68002
|
||||
},
|
||||
"width": 125.808716,
|
||||
"height": 25.079895
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 191.49458,
|
||||
"y": 379.68002
|
||||
},
|
||||
"width": 352.77826,
|
||||
"height": 25.079895
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.68587,
|
||||
"y": 335.8798
|
||||
},
|
||||
"width": 125.808716,
|
||||
"height": 43.800232
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 191.49458,
|
||||
"y": 335.8798
|
||||
},
|
||||
"width": 352.77826,
|
||||
"height": 43.800232
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.68587,
|
||||
"y": 310.68
|
||||
},
|
||||
"width": 125.808716,
|
||||
"height": 25.199799
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 191.49458,
|
||||
"y": 310.68
|
||||
},
|
||||
"width": 352.77826,
|
||||
"height": 25.199799
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.68587,
|
||||
"y": 281.2798
|
||||
},
|
||||
"width": 125.808716,
|
||||
"height": 29.400208
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 191.49458,
|
||||
"y": 281.2798
|
||||
},
|
||||
"width": 352.77826,
|
||||
"height": 29.400208
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.68587,
|
||||
"y": 218.76001
|
||||
},
|
||||
"width": 125.808716,
|
||||
"height": 62.519775
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 191.49458,
|
||||
"y": 218.76001
|
||||
},
|
||||
"width": 352.77826,
|
||||
"height": 62.519775
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.68587,
|
||||
"y": 175.00247
|
||||
},
|
||||
"width": 125.808716,
|
||||
"height": 43.757538
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 191.49458,
|
||||
"y": 175.00247
|
||||
},
|
||||
"width": 352.77826,
|
||||
"height": 43.757538
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"sections": [
|
||||
{
|
||||
"sectionNumber": 1,
|
||||
"headline": "",
|
||||
"pages": [
|
||||
1
|
||||
],
|
||||
"sectionAreas": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 251.4,
|
||||
"y": 550.32
|
||||
},
|
||||
"width": 107.763336,
|
||||
"height": 12.02002,
|
||||
"page": 1,
|
||||
"header": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionNumber": 2,
|
||||
"headline": "Table in: NOTIFICATION OF AN ACTIVE\nSUBSTANCE UNDER COMMISSION\nREGULATION (EU) 844/2012",
|
||||
"pages": [
|
||||
2
|
||||
],
|
||||
"sectionAreas": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.56436,
|
||||
"y": 684.47955
|
||||
},
|
||||
"width": 83.35573,
|
||||
"height": 35.476135,
|
||||
"page": 2,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 148.92009,
|
||||
"y": 684.47955
|
||||
},
|
||||
"width": 255.12016,
|
||||
"height": 35.476135,
|
||||
"page": 2,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 404.04025,
|
||||
"y": 684.47955
|
||||
},
|
||||
"width": 139.9927,
|
||||
"height": 35.476135,
|
||||
"page": 2,
|
||||
"header": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionNumber": 3,
|
||||
"headline": "Table in: NOTIFICATION OF AN ACTIVE\nSUBSTANCE UNDER COMMISSION\nREGULATION (EU) 844/2012",
|
||||
"pages": [],
|
||||
"sectionAreas": []
|
||||
},
|
||||
{
|
||||
"sectionNumber": 4,
|
||||
"headline": "Table in: NOTIFICATION OF AN ACTIVE\nSUBSTANCE UNDER COMMISSION\nREGULATION (EU) 844/2012",
|
||||
"pages": [],
|
||||
"sectionAreas": []
|
||||
},
|
||||
{
|
||||
"sectionNumber": 5,
|
||||
"headline": "Table in: NOTIFICATION OF AN ACTIVE\nSUBSTANCE UNDER COMMISSION\nREGULATION (EU) 844/2012",
|
||||
"pages": [
|
||||
2
|
||||
],
|
||||
"sectionAreas": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.56436,
|
||||
"y": 609.0429
|
||||
},
|
||||
"width": 83.35573,
|
||||
"height": 25.157837,
|
||||
"page": 2,
|
||||
"header": "Date"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionNumber": 7,
|
||||
"headline": "NOTIFICATION OF AN ACTIVE\nSUBSTANCE UNDER COMMISSION\nREGULATION (EU) 844/2012",
|
||||
"pages": [
|
||||
1,
|
||||
2
|
||||
],
|
||||
"sectionAreas": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 159.24,
|
||||
"y": 280.92004
|
||||
},
|
||||
"width": 291.92004,
|
||||
"height": 212.29996,
|
||||
"page": 1,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 70.92,
|
||||
"y": 735.36
|
||||
},
|
||||
"width": 105.64288,
|
||||
"height": 9.02002,
|
||||
"page": 2,
|
||||
"header": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionNumber": 8,
|
||||
"headline": "Table in: Table of Contents",
|
||||
"pages": [
|
||||
4
|
||||
],
|
||||
"sectionAreas": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.68587,
|
||||
"y": 515.4003
|
||||
},
|
||||
"width": 125.808716,
|
||||
"height": 25.157227,
|
||||
"page": 4,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 191.49458,
|
||||
"y": 515.4003
|
||||
},
|
||||
"width": 352.77826,
|
||||
"height": 25.157227,
|
||||
"page": 4,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.68587,
|
||||
"y": 404.75992
|
||||
},
|
||||
"width": 125.808716,
|
||||
"height": 110.64041,
|
||||
"page": 4,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.68587,
|
||||
"y": 379.68002
|
||||
},
|
||||
"width": 125.808716,
|
||||
"height": 25.079895,
|
||||
"page": 4,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 191.49458,
|
||||
"y": 379.68002
|
||||
},
|
||||
"width": 352.77826,
|
||||
"height": 25.079895,
|
||||
"page": 4,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.68587,
|
||||
"y": 335.8798
|
||||
},
|
||||
"width": 125.808716,
|
||||
"height": 43.800232,
|
||||
"page": 4,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 191.49458,
|
||||
"y": 335.8798
|
||||
},
|
||||
"width": 352.77826,
|
||||
"height": 43.800232,
|
||||
"page": 4,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.68587,
|
||||
"y": 310.68
|
||||
},
|
||||
"width": 125.808716,
|
||||
"height": 25.199799,
|
||||
"page": 4,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 191.49458,
|
||||
"y": 310.68
|
||||
},
|
||||
"width": 352.77826,
|
||||
"height": 25.199799,
|
||||
"page": 4,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.68587,
|
||||
"y": 281.2798
|
||||
},
|
||||
"width": 125.808716,
|
||||
"height": 29.400208,
|
||||
"page": 4,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 191.49458,
|
||||
"y": 281.2798
|
||||
},
|
||||
"width": 352.77826,
|
||||
"height": 29.400208,
|
||||
"page": 4,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.68587,
|
||||
"y": 218.76001
|
||||
},
|
||||
"width": 125.808716,
|
||||
"height": 62.519775,
|
||||
"page": 4,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 191.49458,
|
||||
"y": 218.76001
|
||||
},
|
||||
"width": 352.77826,
|
||||
"height": 62.519775,
|
||||
"page": 4,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 65.68587,
|
||||
"y": 175.00247
|
||||
},
|
||||
"width": 125.808716,
|
||||
"height": 43.757538,
|
||||
"page": 4,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 191.49458,
|
||||
"y": 175.00247
|
||||
},
|
||||
"width": 352.77826,
|
||||
"height": 43.757538,
|
||||
"page": 4,
|
||||
"header": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionNumber": 9,
|
||||
"headline": "Table of Contents",
|
||||
"pages": [
|
||||
3,
|
||||
4
|
||||
],
|
||||
"sectionAreas": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 70.92,
|
||||
"y": 691.2
|
||||
},
|
||||
"width": 468.76624,
|
||||
"height": 53.179993,
|
||||
"page": 3,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 71.04,
|
||||
"y": 555.48
|
||||
},
|
||||
"width": 461.24002,
|
||||
"height": 188.78003,
|
||||
"page": 4,
|
||||
"header": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionNumber": 10,
|
||||
"headline": "Header",
|
||||
"pages": [
|
||||
1
|
||||
],
|
||||
"sectionAreas": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 70.92,
|
||||
"y": 799.08
|
||||
},
|
||||
"width": 469.31543,
|
||||
"height": 6.799988,
|
||||
"page": 1,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 534.72,
|
||||
"y": 783.84
|
||||
},
|
||||
"width": 5.470215,
|
||||
"height": 6.0200195,
|
||||
"page": 1,
|
||||
"header": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionNumber": 11,
|
||||
"headline": "Header",
|
||||
"pages": [
|
||||
2
|
||||
],
|
||||
"sectionAreas": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 70.92,
|
||||
"y": 799.08
|
||||
},
|
||||
"width": 469.31543,
|
||||
"height": 6.799988,
|
||||
"page": 2,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 534.72,
|
||||
"y": 783.84
|
||||
},
|
||||
"width": 5.470215,
|
||||
"height": 6.0200195,
|
||||
"page": 2,
|
||||
"header": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionNumber": 12,
|
||||
"headline": "Header",
|
||||
"pages": [
|
||||
3
|
||||
],
|
||||
"sectionAreas": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 70.92,
|
||||
"y": 799.08
|
||||
},
|
||||
"width": 469.31543,
|
||||
"height": 6.799988,
|
||||
"page": 3,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 534.72,
|
||||
"y": 783.84
|
||||
},
|
||||
"width": 5.470215,
|
||||
"height": 6.0200195,
|
||||
"page": 3,
|
||||
"header": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionNumber": 13,
|
||||
"headline": "Header",
|
||||
"pages": [
|
||||
4
|
||||
],
|
||||
"sectionAreas": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 71.04,
|
||||
"y": 798.96
|
||||
},
|
||||
"width": 469.70926,
|
||||
"height": 6.799988,
|
||||
"page": 4,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 534.84,
|
||||
"y": 783.72
|
||||
},
|
||||
"width": 5.488098,
|
||||
"height": 6.036072,
|
||||
"page": 4,
|
||||
"header": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionNumber": 14,
|
||||
"headline": "Footer",
|
||||
"pages": [
|
||||
1
|
||||
],
|
||||
"sectionAreas": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 70.92,
|
||||
"y": 37.080017
|
||||
},
|
||||
"width": 93.19173,
|
||||
"height": 6.0200005,
|
||||
"page": 1,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 468.0,
|
||||
"y": 37.080017
|
||||
},
|
||||
"width": 71.701416,
|
||||
"height": 6.0200005,
|
||||
"page": 1,
|
||||
"header": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionNumber": 15,
|
||||
"headline": "Footer",
|
||||
"pages": [
|
||||
2
|
||||
],
|
||||
"sectionAreas": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 70.92,
|
||||
"y": 37.440002
|
||||
},
|
||||
"width": 93.19173,
|
||||
"height": 6.0200005,
|
||||
"page": 2,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 468.0,
|
||||
"y": 37.440002
|
||||
},
|
||||
"width": 71.701416,
|
||||
"height": 6.0200005,
|
||||
"page": 2,
|
||||
"header": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionNumber": 16,
|
||||
"headline": "Footer",
|
||||
"pages": [
|
||||
3
|
||||
],
|
||||
"sectionAreas": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 70.92,
|
||||
"y": 37.440002
|
||||
},
|
||||
"width": 468.78143,
|
||||
"height": 6.0200005,
|
||||
"page": 3,
|
||||
"header": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"sectionNumber": 17,
|
||||
"headline": "Footer",
|
||||
"pages": [
|
||||
4
|
||||
],
|
||||
"sectionAreas": [
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 71.04,
|
||||
"y": 37.320007
|
||||
},
|
||||
"width": 93.3805,
|
||||
"height": 6.0360794,
|
||||
"page": 4,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 468.12,
|
||||
"y": 37.320007
|
||||
},
|
||||
"width": 71.984375,
|
||||
"height": 6.0360794,
|
||||
"page": 4,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 71.04,
|
||||
"y": 140.16003
|
||||
},
|
||||
"width": 254.69507,
|
||||
"height": 7.5200043,
|
||||
"page": 4,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 71.04,
|
||||
"y": 115.56
|
||||
},
|
||||
"width": 65.564415,
|
||||
"height": 7.5199966,
|
||||
"page": 4,
|
||||
"header": null
|
||||
},
|
||||
{
|
||||
"topLeft": {
|
||||
"x": 71.04,
|
||||
"y": 90.599976
|
||||
},
|
||||
"width": 424.84805,
|
||||
"height": 7.5199966,
|
||||
"page": 4,
|
||||
"header": null
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
-1
@@ -1676,7 +1676,6 @@ da Silva Rejane
|
||||
Das R
|
||||
Das, R.
|
||||
Daughtry, CST
|
||||
David Chubb
|
||||
David Chubb|Lorraine Britton
|
||||
David Clarke
|
||||
Davies
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
Amendment 1
|
||||
Report Number: 33168
|
||||
Page
|
||||
Report Number: BFI0714
|
||||
Tesh Consultants International
|
||||
|
||||
+2
-1
@@ -1 +1,2 @@
|
||||
Difenoconazole
|
||||
Difenoconazole
|
||||
FENPROPIDIN
|
||||
+2
-1
@@ -235,4 +235,5 @@ N/A
|
||||
No details reported
|
||||
Not available
|
||||
Test facility
|
||||
TBD
|
||||
TBD
|
||||
David Chubb
|
||||
+10
-2
@@ -7,12 +7,20 @@ global Section section
|
||||
|
||||
// --------------------------------------- CBI rules -------------------------------------------------------------------
|
||||
|
||||
//rule "0: Expand CBI Authors with firstname initials"
|
||||
// when
|
||||
// Section(matchesType("CBI_author") || matchesType("recommendation_CBI_author"))
|
||||
// then
|
||||
// section.expandByRegEx("CBI_author", "(,? [A-Z]\\.?( ?[A-Z]\\.?)?( ?[A-Z]\\.?)?\\b\\.?)", false, 1);
|
||||
// section.expandByRegEx("recommendation_CBI_author", "(,? [A-Z]\\.?( ?[A-Z]\\.?)?( ?[A-Z]\\.?)?\\b\\.?)", false, 1);
|
||||
// end
|
||||
|
||||
rule "0: Expand CBI Authors with firstname initials"
|
||||
when
|
||||
Section(matchesType("CBI_author") || matchesType("recommendation_CBI_author"))
|
||||
then
|
||||
section.expandByRegEx("CBI_author", "(,? [A-Z]\\.?( ?[A-Z]\\.?)?( ?[A-Z]\\.?)?\\b\\.?)", false, 1);
|
||||
section.expandByRegEx("recommendation_CBI_author", "(,? [A-Z]\\.?( ?[A-Z]\\.?)?( ?[A-Z]\\.?)?\\b\\.?)", false, 1);
|
||||
section.expandByRegEx("CBI_author", "(,? [A-Z]\\.?( ?[A-Z]\\.?)?( ?[A-Z]\\.?)?\\b\\.?)", false, 1, "[^\\s]+");
|
||||
section.expandByRegEx("recommendation_CBI_author", "(,? [A-Z]\\.?( ?[A-Z]\\.?)?( ?[A-Z]\\.?)?\\b\\.?)", false, 1, "[^\\s]+");
|
||||
end
|
||||
|
||||
|
||||
|
||||
+18
-3
@@ -7,12 +7,20 @@ global Section section
|
||||
|
||||
// --------------------------------------- CBI rules -------------------------------------------------------------------
|
||||
|
||||
//rule "0: Expand CBI Authors with firstname initials"
|
||||
// when
|
||||
// Section(matchesType("CBI_author") || matchesType("recommendation_CBI_author"))
|
||||
// then
|
||||
// section.expandByRegEx("CBI_author", "(,? [A-Z]\\.?( ?[A-Z]\\.?)?( ?[A-Z]\\.?)?\\b\\.?)", false, 1);
|
||||
// section.expandByRegEx("recommendation_CBI_author", "(,? [A-Z]\\.?( ?[A-Z]\\.?)?( ?[A-Z]\\.?)?\\b\\.?)", false, 1);
|
||||
// end
|
||||
|
||||
rule "0: Expand CBI Authors with firstname initials"
|
||||
when
|
||||
Section(matchesType("CBI_author") || matchesType("recommendation_CBI_author"))
|
||||
then
|
||||
section.expandByRegEx("CBI_author", "(,? [A-Z]\\.?( ?[A-Z]\\.?)?( ?[A-Z]\\.?)?\\b\\.?)", false, 1);
|
||||
section.expandByRegEx("recommendation_CBI_author", "(,? [A-Z]\\.?( ?[A-Z]\\.?)?( ?[A-Z]\\.?)?\\b\\.?)", false, 1);
|
||||
section.expandByRegEx("CBI_author", "(,? [A-Z]\\.?( ?[A-Z]\\.?)?( ?[A-Z]\\.?)?\\b\\.?)", false, 1, "[^\\s]+");
|
||||
section.expandByRegEx("recommendation_CBI_author", "(,? [A-Z]\\.?( ?[A-Z]\\.?)?( ?[A-Z]\\.?)?\\b\\.?)", false, 1, "[^\\s]+");
|
||||
end
|
||||
|
||||
|
||||
@@ -336,4 +344,11 @@ rule "29: Redact Dossier Redactions"
|
||||
Section(matchesType("dossier_redactions"))
|
||||
then
|
||||
section.redact("dossier_redactions", 29, "Dossier Redaction found", "Article 39(1)(2) of Regulation (EC) No 178/2002");
|
||||
end
|
||||
end
|
||||
|
||||
rule "30: Ignore dossier_redactions if confidential"
|
||||
when
|
||||
Section(!fileAttributeByLabelEqualsIgnoreCase("Confidentiality","confidential") && matchesType("dossier_redactions"));
|
||||
then
|
||||
section.ignore("dossier_redactions");
|
||||
end
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Reference in New Issue
Block a user