Merge branch 'feature/RED-10200' into 'master'

RED-10200: Spike performant rules update logic

Closes RED-10200

See merge request redactmanager/redaction-service!572
This commit is contained in:
Maverick Studer 2024-12-04 14:41:24 +01:00
commit a1e6361c3e
87 changed files with 3352 additions and 2241 deletions

View File

@ -9,6 +9,8 @@ import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Document;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.GenericSemanticNode;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.NodeType;
@ -17,6 +19,8 @@ import com.iqser.red.service.redaction.v1.server.model.document.nodes.Table;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.TableCell;
import com.iqser.red.service.redaction.v1.server.model.document.textblock.TextBlock;
import com.iqser.red.service.redaction.v1.server.model.document.textblock.TextBlockCollector;
import com.iqser.red.service.redaction.v1.server.utils.EntityCreationUtility;
import com.iqser.red.service.redaction.v1.server.utils.EntityEnrichmentService;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
@ -35,7 +39,7 @@ public class DocumentTree {
public DocumentTree(Document document) {
root = Entry.builder().treeId(Collections.emptyList()).children(new LinkedList<>()).node(document).build();
this.root = Entry.builder().treeId(Collections.emptyList()).children(new LinkedList<>()).node(document).build();
}
@ -358,6 +362,25 @@ public class DocumentTree {
}
public void addEntityToGraph(TextEntity entity) {
getRoot().getNode().addThisToEntityIfIntersects(entity);
TextBlock textBlock = entity.getDeepestFullyContainingNode().getTextBlock();
EntityEnrichmentService.enrichEntity(entity, textBlock);
EntityCreationUtility.addToPages(entity);
EntityCreationUtility.addEntityToNodeEntitySets(entity);
if (entity.getEntityType().equals(EntityType.TEMPORARY)) {
return;
}
entity.computeRelations();
entity.notifyEntityInserted();
}
@Builder
@Getter
@AllArgsConstructor

View File

@ -0,0 +1,32 @@
package com.iqser.red.service.redaction.v1.server.model.document;
import java.util.HashSet;
import java.util.Set;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.SemanticNode;
import lombok.Getter;
public class IntersectingNodeVisitor extends AbstractNodeVisitor {
@Getter
private Set<SemanticNode> intersectingNodes;
private final TextRange textRange;
public IntersectingNodeVisitor(TextRange textRange) {
this.textRange = textRange;
this.intersectingNodes = new HashSet<>();
}
@Override
public void visitNodeDefault(SemanticNode node) {
if (textRange.intersects(node.getTextRange())) {
intersectingNodes.add(node);
}
}
}

View File

@ -0,0 +1,20 @@
package com.iqser.red.service.redaction.v1.server.model.document.entity;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public abstract class AbstractRelation implements Relation {
protected final TextEntity a;
protected final TextEntity b;
@Override
public String toString() {
return this.getClass().getSimpleName() + "{" + "a=" + a + ", b=" + b + '}';
}
}

View File

@ -0,0 +1,18 @@
package com.iqser.red.service.redaction.v1.server.model.document.entity;
public class Containment extends Intersection {
public Containment(TextEntity container, TextEntity contained) {
super(container, contained);
}
public TextEntity getContainer() {
return a;
}
public TextEntity getContained() {
return b;
}
}

View File

@ -0,0 +1,25 @@
package com.iqser.red.service.redaction.v1.server.model.document.entity;
public interface EntityEventListener {
/**
* Invoked when an entity is inserted.
*
* @param entity The entity that was inserted.
*/
void onEntityInserted(IEntity entity);
/**
* Invoked when an entity is updated.
*
* @param entity The entity that was updated.
*/
void onEntityUpdated(IEntity entity);
/**
* Invoked when an entity is removed.
*
* @param entity The entity that was removed.
*/
void onEntityRemoved(IEntity entity);
}

View File

@ -6,5 +6,6 @@ public enum EntityType {
RECOMMENDATION,
FALSE_POSITIVE,
FALSE_RECOMMENDATION,
DICTIONARY_REMOVAL
DICTIONARY_REMOVAL,
TEMPORARY
}

View File

@ -0,0 +1,10 @@
package com.iqser.red.service.redaction.v1.server.model.document.entity;
public class Equality extends Containment {
public Equality(TextEntity a, TextEntity b) {
super(a, b);
}
}

View File

@ -339,7 +339,9 @@ public interface IEntity {
*/
default void addMatchedRule(MatchedRule matchedRule) {
boolean wasValid = valid();
getMatchedRuleList().add(matchedRule);
handleStateChange(wasValid);
}
@ -353,7 +355,53 @@ public interface IEntity {
if (getMatchedRuleList().equals(matchedRules)) {
return;
}
boolean wasValid = valid();
getMatchedRuleList().addAll(matchedRules);
handleStateChange(wasValid);
}
void addEntityEventListener(EntityEventListener listener);
void removeEntityEventListener(EntityEventListener listener);
default void notifyEntityInserted() {
for (EntityEventListener listener : getEntityEventListeners()) {
listener.onEntityInserted(this);
}
}
default void notifyEntityUpdated() {
for (EntityEventListener listener : getEntityEventListeners()) {
listener.onEntityUpdated(this);
}
}
default void notifyEntityRemoved() {
for (EntityEventListener listener : getEntityEventListeners()) {
listener.onEntityRemoved(this);
}
}
Collection<EntityEventListener> getEntityEventListeners();
default void handleStateChange(boolean wasValid) {
if (valid() == wasValid) {
return;
}
if (!removed()) {
notifyEntityUpdated();
} else {
notifyEntityRemoved();
}
}

View File

@ -0,0 +1,10 @@
package com.iqser.red.service.redaction.v1.server.model.document.entity;
public class Intersection extends AbstractRelation {
public Intersection(TextEntity a, TextEntity b) {
super(a, b);
}
}

View File

@ -0,0 +1,10 @@
package com.iqser.red.service.redaction.v1.server.model.document.entity;
public interface Relation {
TextEntity getA();
TextEntity getB();
}

View File

@ -4,6 +4,7 @@ import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
@ -11,7 +12,10 @@ import java.util.Map;
import java.util.PriorityQueue;
import java.util.Set;
import org.apache.commons.collections4.map.HashedMap;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Engine;
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.BaseAnnotation;
import com.iqser.red.service.redaction.v1.server.model.document.TextRange;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Page;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.SemanticNode;
@ -49,7 +53,8 @@ public class TextEntity implements IEntity {
@Builder.Default
final PriorityQueue<MatchedRule> matchedRuleList = new PriorityQueue<>();
final ManualChangeOverwrite manualOverwrite;
@Builder.Default
final ManualChangeOverwrite manualOverwrite = new ManualChangeOverwrite();
boolean dictionaryEntry;
boolean dossierDictionaryEntry;
@ -68,6 +73,12 @@ public class TextEntity implements IEntity {
List<SemanticNode> intersectingNodes = new LinkedList<>();
SemanticNode deepestFullyContainingNode;
@Builder.Default
Map<TextEntity, Set<Relation>> relations = new HashMap<>();
@Builder.Default
Collection<EntityEventListener> entityEventListeners = new ArrayList<>();
public static TextEntity initialEntityNode(TextRange textRange, String type, EntityType entityType, SemanticNode node) {
@ -158,12 +169,15 @@ public class TextEntity implements IEntity {
public void removeFromGraph() {
remove("FINAL.0.0", "removed completely");
intersectingNodes.forEach(node -> node.getEntities().remove(this));
pages.forEach(page -> page.getEntities().remove(this));
intersectingNodes = new LinkedList<>();
relations.keySet()
.forEach(entity -> entity.getRelations().remove(this));
relations = new HashedMap<>();
deepestFullyContainingNode = null;
pages = new HashSet<>();
remove("FINAL.0.0", "removed completely");
}
@ -251,6 +265,20 @@ public class TextEntity implements IEntity {
}
public void addManualChange(BaseAnnotation manualChange) {
manualOverwrite.addChange(manualChange);
notifyEntityUpdated();
}
public void addManualChanges(List<BaseAnnotation> manualChanges) {
manualOverwrite.addChanges(manualChanges);
notifyEntityUpdated();
}
public boolean matchesAnnotationId(String manualRedactionId) {
return getPositionsOnPagePerPage().stream()
@ -311,4 +339,42 @@ public class TextEntity implements IEntity {
.orElse(getMatchedRule().isWriteValueWithLineBreaks() ? getValueWithLineBreaks() : value);
}
@Override
public void addEntityEventListener(EntityEventListener listener) {
entityEventListeners.add(listener);
}
@Override
public void removeEntityEventListener(EntityEventListener listener) {
entityEventListeners.remove(listener);
}
public void computeRelations() {
for (TextEntity textEntity : this.getDeepestFullyContainingNode().getEntities()) {
if (this.intersects(textEntity) && !this.equals(textEntity) && !textEntity.getEntityType().equals(EntityType.TEMPORARY)) {
if (textEntity.getTextRange().equals(this.getTextRange())) {
textEntity.getRelations().computeIfAbsent(this, k -> new HashSet<>()).add(new Equality(this, textEntity));
this.getRelations().computeIfAbsent(textEntity, k -> new HashSet<>()).add(new Equality(textEntity, this));
} else if (textEntity.containedBy(this)) {
textEntity.getRelations().computeIfAbsent(this, k -> new HashSet<>()).add(new Intersection(textEntity, this));
this.getRelations().computeIfAbsent(textEntity, k -> new HashSet<>()).add(new Containment(this, textEntity));
} else if (this.containedBy(textEntity)) {
textEntity.getRelations().computeIfAbsent(this, k -> new HashSet<>()).add(new Containment(textEntity, this));
this.getRelations().computeIfAbsent(textEntity, k -> new HashSet<>()).add(new Intersection(this, textEntity));
} else {
textEntity.getRelations().computeIfAbsent(this, k -> new HashSet<>()).add(new Intersection(textEntity, this));
this.getRelations().computeIfAbsent(textEntity, k -> new HashSet<>()).add(new Intersection(this, textEntity));
}
}
}
}
}

View File

@ -39,7 +39,6 @@ public class Document extends AbstractSemanticNode {
@Builder.Default
static final SectionIdentifier sectionIdentifier = SectionIdentifier.document();
@Override
public NodeType getType() {

View File

@ -1,6 +1,8 @@
package com.iqser.red.service.redaction.v1.server.model.document.nodes;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
@ -10,6 +12,7 @@ import java.util.Set;
import com.iqser.red.service.redaction.v1.server.model.document.NodeVisitor;
import com.iqser.red.service.redaction.v1.server.model.document.TextRange;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityEventListener;
import com.iqser.red.service.redaction.v1.server.model.document.entity.IEntity;
import com.iqser.red.service.redaction.v1.server.model.document.entity.ManualChangeOverwrite;
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule;
@ -52,6 +55,9 @@ public class Image extends AbstractSemanticNode implements IEntity {
Page page;
@Builder.Default
Collection<EntityEventListener> entityEventListeners = new ArrayList<>();
@Override
public NodeType getType() {
@ -100,6 +106,21 @@ public class Image extends AbstractSemanticNode implements IEntity {
}
@Override
public void addEntityEventListener(EntityEventListener listener) {
entityEventListeners.add(listener);
}
@Override
public void removeEntityEventListener(EntityEventListener listener) {
entityEventListeners.remove(listener);
}
@Override
public String type() {

View File

@ -1,23 +1,27 @@
package com.iqser.red.service.redaction.v1.server.service.document;
package com.iqser.red.service.redaction.v1.server.utils;
import java.util.List;
import java.util.Set;
import com.iqser.red.service.redaction.v1.server.model.document.IntersectingNodeVisitor;
import com.iqser.red.service.redaction.v1.server.model.document.TextRange;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Page;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.SemanticNode;
import com.iqser.red.service.redaction.v1.server.model.document.textblock.TextBlock;
import lombok.experimental.UtilityClass;
@UtilityClass
public class EntityCreationUtility {
public static void checkIfBothStartAndEndAreEmpty(String start, String end) {
public void checkIfBothStartAndEndAreEmpty(String start, String end) {
checkIfBothStartAndEndAreEmpty(List.of(start), List.of(end));
}
public static <T> void checkIfBothStartAndEndAreEmpty(List<T> start, List<T> end) {
public <T> void checkIfBothStartAndEndAreEmpty(List<T> start, List<T> end) {
if ((start == null || start.isEmpty()) && (end == null || end.isEmpty())) {
throw new IllegalArgumentException("Start and end values are empty!");
@ -25,7 +29,7 @@ public class EntityCreationUtility {
}
public static int truncateEndIfLineBreakIsBetween(int end, int expandedEnd, TextBlock textBlock) {
public int truncateEndIfLineBreakIsBetween(int end, int expandedEnd, TextBlock textBlock) {
if (textBlock.getNextLinebreak(end) < expandedEnd) {
return end;
@ -34,7 +38,7 @@ public class EntityCreationUtility {
}
public static Set<SemanticNode> findIntersectingSubNodes(SemanticNode initialIntersectingNode, TextRange textRange) {
public Set<SemanticNode> findIntersectingSubNodes(SemanticNode initialIntersectingNode, TextRange textRange) {
IntersectingNodeVisitor visitor = new IntersectingNodeVisitor(textRange);
@ -46,7 +50,7 @@ public class EntityCreationUtility {
}
public static void addToPages(TextEntity entity) {
public void addToPages(TextEntity entity) {
Set<Page> pages = entity.getDeepestFullyContainingNode().getPages(entity.getTextRange());
entity.getPages().addAll(pages);
@ -54,14 +58,14 @@ public class EntityCreationUtility {
}
public static void addEntityToNodeEntitySets(TextEntity entity) {
public void addEntityToNodeEntitySets(TextEntity entity) {
entity.getIntersectingNodes()
.forEach(node -> node.getEntities().add(entity));
}
public static boolean allEntitiesIntersectAndHaveSameTypes(List<TextEntity> entitiesToMerge) {
public boolean allEntitiesIntersectAndHaveSameTypes(List<TextEntity> entitiesToMerge) {
if (entitiesToMerge.isEmpty()) {
return true;
@ -79,7 +83,7 @@ public class EntityCreationUtility {
}
public static TextRange toLineAfterTextRange(TextBlock textBlock, TextRange textRange) {
public TextRange toLineAfterTextRange(TextBlock textBlock, TextRange textRange) {
if (textBlock.getTextRange().end() == textRange.end()) {
return new TextRange(textRange.end(), textRange.end());

View File

@ -1,39 +1,36 @@
package com.iqser.red.service.redaction.v1.server.service.document;
package com.iqser.red.service.redaction.v1.server.utils;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import org.springframework.stereotype.Service;
import com.iqser.red.service.redaction.v1.server.RedactionServiceSettings;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.textblock.TextBlock;
import lombok.RequiredArgsConstructor;
import lombok.AccessLevel;
import lombok.experimental.FieldDefaults;
import lombok.experimental.UtilityClass;
@Service
@RequiredArgsConstructor
@UtilityClass
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class EntityEnrichmentService {
private final RedactionServiceSettings redactionServiceSettings;
int SURROUNDING_WORDS_OFFSET_WINDOW = 100;
int NUMBER_OF_SURROUNDING_WORDS = 3;
public void enrichEntity(TextEntity entity, TextBlock textBlock) {
entity.setValue(textBlock.subSequence(entity.getTextRange()).toString());
entity.setTextAfter(findTextAfter(entity.getTextRange().end(), textBlock));
entity.setTextBefore(findTextBefore(entity.getTextRange().start(), textBlock));
}
private String findTextAfter(int index, TextBlock textBlock) {
int endOffset = Math.min(index + redactionServiceSettings.getSurroundingWordsOffsetWindow(), textBlock.getTextRange().end());
int endOffset = Math.min(index + SURROUNDING_WORDS_OFFSET_WINDOW, textBlock.getTextRange().end());
String textAfter = textBlock.subSequence(index, endOffset).toString();
if (!textAfter.isBlank()) {
List<String> wordsAfter = splitToWordsAndRemoveEmptyWords(textAfter);
int numberOfWordsAfter = Math.min(wordsAfter.size(), redactionServiceSettings.getNumberOfSurroundingWords());
int numberOfWordsAfter = Math.min(wordsAfter.size(), NUMBER_OF_SURROUNDING_WORDS);
if (!wordsAfter.isEmpty()) {
return concatWordsAfter(wordsAfter.subList(0, numberOfWordsAfter), textAfter.startsWith(" "));
}
@ -41,14 +38,12 @@ public class EntityEnrichmentService {
return "";
}
private String findTextBefore(int index, TextBlock textBlock) {
int offsetBefore = Math.max(index - redactionServiceSettings.getSurroundingWordsOffsetWindow(), textBlock.getTextRange().start());
int offsetBefore = Math.max(index - SURROUNDING_WORDS_OFFSET_WINDOW, textBlock.getTextRange().start());
String textBefore = textBlock.subSequence(offsetBefore, index).toString();
if (!textBefore.isBlank()) {
List<String> wordsBefore = splitToWordsAndRemoveEmptyWords(textBefore);
int numberOfWordsBefore = Math.min(wordsBefore.size(), redactionServiceSettings.getNumberOfSurroundingWords());
int numberOfWordsBefore = Math.min(wordsBefore.size(), NUMBER_OF_SURROUNDING_WORDS);
if (!wordsBefore.isEmpty()) {
return concatWordsBefore(wordsBefore.subList(wordsBefore.size() - numberOfWordsBefore, wordsBefore.size()), textBefore.endsWith(" "));
}
@ -56,36 +51,26 @@ public class EntityEnrichmentService {
return "";
}
private static List<String> splitToWordsAndRemoveEmptyWords(String textAfter) {
return Arrays.stream(textAfter.split(" "))
private List<String> splitToWordsAndRemoveEmptyWords(String text) {
return Arrays.stream(text.split(" "))
.filter(word -> !Objects.equals("", word))
.toList();
}
private static String concatWordsBefore(List<String> words, boolean endWithSpace) {
private String concatWordsBefore(List<String> words, boolean endWithSpace) {
StringBuilder sb = new StringBuilder();
for (String word : words) {
sb.append(word).append(" ");
}
String result = sb.toString().trim();
return endWithSpace ? result + " " : result;
}
private static String concatWordsAfter(List<String> words, boolean startWithSpace) {
private String concatWordsAfter(List<String> words, boolean startWithSpace) {
StringBuilder sb = new StringBuilder();
for (String word : words) {
sb.append(word).append(" ");
}
String result = sb.toString().trim();
return startWithSpace ? " " + result : result;
}

View File

@ -12,7 +12,7 @@ plugins {
description = "redaction-service-server-v1"
val layoutParserVersion = "0.191.0"
val layoutParserVersion = "0.193.0"
val jacksonVersion = "2.15.2"
val droolsVersion = "9.44.0.Final"
val pdfBoxVersion = "3.0.0"
@ -102,6 +102,10 @@ dependencies {
group = "com.iqser.red.service",
module = "persistence-service-shared-api-v1"
)
exclude(
group = "com.knecon.fforesight",
module = "document"
)
}
testImplementation("com.pdftron:PDFNet:10.11.0")
}

View File

@ -2,6 +2,7 @@ package com.iqser.red.service.redaction.v1.server.model;
import static com.iqser.red.service.redaction.v1.server.service.NotFoundImportedEntitiesService.IMPORTED_REDACTION_TYPE;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.PriorityQueue;
@ -15,6 +16,7 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualRedactionEntry;
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualResizeRedaction;
import com.iqser.red.service.redaction.v1.server.model.document.TextRange;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityEventListener;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType;
import com.iqser.red.service.redaction.v1.server.model.document.entity.IEntity;
import com.iqser.red.service.redaction.v1.server.model.document.entity.ManualChangeOverwrite;
@ -52,7 +54,8 @@ public class PrecursorEntity implements IEntity {
@Builder.Default
PriorityQueue<MatchedRule> matchedRuleList = new PriorityQueue<>();
ManualChangeOverwrite manualOverwrite;
@Builder.Default
ManualChangeOverwrite manualOverwrite = new ManualChangeOverwrite();
public static PrecursorEntity fromManualRedactionEntry(ManualRedactionEntry manualRedactionEntry, boolean hint) {
@ -198,6 +201,28 @@ public class PrecursorEntity implements IEntity {
}
@Override
public void addEntityEventListener(EntityEventListener listener) {
throw new UnsupportedOperationException("PrecursorEntity does not support entityEventListeners");
}
@Override
public void removeEntityEventListener(EntityEventListener listener) {
throw new UnsupportedOperationException("PrecursorEntity does not support entityEventListeners");
}
@Override
public Collection<EntityEventListener> getEntityEventListeners() {
throw new UnsupportedOperationException("PrecursorEntity does not support entityEventListeners");
}
private static EntityType getEntityType(EntryType entryType) {
switch (entryType) {

View File

@ -11,6 +11,7 @@ import org.apache.commons.lang3.StringUtils;
import com.iqser.red.service.dictionarymerge.commons.DictionaryEntry;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType;
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule;
import com.iqser.red.service.redaction.v1.server.model.document.entity.Relation;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.utils.Patterns;
import com.iqser.red.service.redaction.v1.server.utils.exception.NotFoundException;
@ -44,6 +45,13 @@ public class Dictionary {
}
public boolean containsType(String type) {
Map<Level, DictionaryModel> levelMap = localAccessMap.get(type);
return !(levelMap == null || levelMap.isEmpty());
}
private Level getLevel(boolean isDossierDictionary) {
return isDossierDictionary ? Level.DOSSIER : Level.DOSSIER_TEMPLATE;

View File

@ -7,11 +7,9 @@ import org.springframework.stereotype.Service;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Engine;
import com.iqser.red.service.redaction.v1.server.model.dictionary.Dictionary;
import com.iqser.red.service.redaction.v1.server.model.dictionary.SearchImplementation;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.SemanticNode;
import com.iqser.red.service.redaction.v1.server.service.document.EntityCreationService;
import com.iqser.red.service.redaction.v1.server.service.document.EntityEnrichmentService;
import io.micrometer.observation.annotation.Observed;
import lombok.AccessLevel;
@ -25,8 +23,6 @@ import lombok.extern.slf4j.Slf4j;
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class DictionarySearchService {
EntityEnrichmentService entityEnrichmentService;
@Observed(name = "DictionarySearchService", contextualName = "add-dictionary-entries")
public void addDictionaryEntities(Dictionary dictionary, List<SemanticNode> semanticNodes) {
@ -38,7 +34,7 @@ public class DictionarySearchService {
@Observed(name = "DictionarySearchService", contextualName = "add-dictionary-entries")
public void addDictionaryEntities(Dictionary dictionary, SemanticNode node) {
EntityCreationService entityCreationService = new EntityCreationService(entityEnrichmentService);
EntityCreationService entityCreationService = new EntityCreationService();
dictionary.getDictionarySearch().getBoundaries(node.getTextBlock())
.filter(boundary -> entityCreationService.isValidEntityTextRange(node.getTextBlock(), boundary.textRange()))
.forEach(match -> {

View File

@ -14,7 +14,6 @@ import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.google.common.collect.Sets;
@ -30,7 +29,6 @@ import com.iqser.red.service.redaction.v1.server.model.document.nodes.Page;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.SemanticNode;
import com.iqser.red.service.redaction.v1.server.model.document.textblock.TextBlock;
import com.iqser.red.service.redaction.v1.server.service.document.EntityCreationService;
import com.iqser.red.service.redaction.v1.server.service.document.EntityEnrichmentService;
import com.iqser.red.service.redaction.v1.server.utils.RectangleTransformations;
import lombok.extern.slf4j.Slf4j;
@ -39,15 +37,7 @@ import lombok.extern.slf4j.Slf4j;
@Service
public class EntityFindingUtility {
EntityCreationService entityCreationService;
@Autowired
public EntityFindingUtility(EntityEnrichmentService entityEnrichmentService) {
entityCreationService = new EntityCreationService(entityEnrichmentService);
}
EntityCreationService entityCreationService = new EntityCreationService();
public Optional<TextEntity> findClosestEntityAndReturnEmptyIfNotFound(PrecursorEntity precursorEntity,
Map<String, List<TextEntity>> entitiesWithSameValue,
@ -191,7 +181,7 @@ public class EntityFindingUtility {
return textBlocks.stream()
.flatMap(searchImplementation::getBoundaries)
.map(boundary -> entityCreationService.byTextRangeWithEngine(boundary, "temp", EntityType.ENTITY, node, Collections.emptySet()))
.map(boundary -> entityCreationService.byTextRangeWithEngine(boundary, "temp", EntityType.TEMPORARY, node, Collections.emptySet()))
.filter(Optional::isPresent)
.map(Optional::get)
.distinct()
@ -218,7 +208,7 @@ public class EntityFindingUtility {
return textBlocks.stream()
.flatMap(tb -> searchImplementation.getBoundaries(tb)
.filter(textRange -> entityCreationService.isValidEntityTextRange(tb, textRange)))
.map(boundary -> entityCreationService.byTextRangeWithEngine(boundary, "temp", EntityType.ENTITY, document, Collections.emptySet()))
.map(boundary -> entityCreationService.byTextRangeWithEngine(boundary, "temp", EntityType.TEMPORARY, document, Collections.emptySet()))
.filter(Optional::isPresent)
.map(Optional::get)
.distinct()
@ -232,7 +222,7 @@ public class EntityFindingUtility {
return searchImplementation.getBoundaries(document.getTextBlock())
.filter(textRange -> entityCreationService.isValidEntityTextRange(document.getTextBlock(), textRange))
.map(boundary -> entityCreationService.byTextRangeWithEngine(boundary, "temp", EntityType.ENTITY, document, Collections.emptySet()))
.map(boundary -> entityCreationService.byTextRangeWithEngine(boundary, "temp", EntityType.TEMPORARY, document, Collections.emptySet()))
.filter(Optional::isPresent)
.map(Optional::get)
.distinct()

View File

@ -431,12 +431,11 @@ public class EntityLogCreatorService {
private static EntryType getEntryType(EntityType entityType) {
return switch (entityType) {
case ENTITY -> EntryType.ENTITY;
case ENTITY, TEMPORARY -> EntryType.ENTITY;
case HINT -> EntryType.HINT;
case FALSE_POSITIVE -> EntryType.FALSE_POSITIVE;
case FALSE_POSITIVE, DICTIONARY_REMOVAL -> EntryType.FALSE_POSITIVE;
case RECOMMENDATION -> EntryType.RECOMMENDATION;
case FALSE_RECOMMENDATION -> EntryType.FALSE_RECOMMENDATION;
case DICTIONARY_REMOVAL -> EntryType.FALSE_POSITIVE;
};
}

View File

@ -3,6 +3,7 @@ package com.iqser.red.service.redaction.v1.server.service;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -17,6 +18,8 @@ import com.google.common.collect.Sets;
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualRecategorization;
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualResizeRedaction;
import com.iqser.red.service.redaction.v1.server.model.PrecursorEntity;
import com.iqser.red.service.redaction.v1.server.model.dictionary.Dictionary;
import com.iqser.red.service.redaction.v1.server.model.dictionary.DictionaryModel;
import com.iqser.red.service.redaction.v1.server.model.document.entity.IEntity;
import com.iqser.red.service.redaction.v1.server.model.document.entity.PositionOnPage;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
@ -44,18 +47,19 @@ public class ManualChangesApplicationService {
public void recategorize(IEntity entityToBeReCategorized, ManualRecategorization manualRecategorization) {
entityToBeReCategorized.getMatchedRuleList().clear();
entityToBeReCategorized.getManualOverwrite().addChange(manualRecategorization);
if (manualRecategorization.getType() == null) {
return;
}
if (entityToBeReCategorized instanceof Image image) {
entityToBeReCategorized.getManualOverwrite().addChange(manualRecategorization);
image.setImageType(ImageType.fromString(manualRecategorization.getType()));
return;
}
if (entityToBeReCategorized instanceof TextEntity textEntity) {
textEntity.addManualChange(manualRecategorization);
textEntity.setType(manualRecategorization.getType());
}
}
@ -76,6 +80,8 @@ public class ManualChangesApplicationService {
@Deprecated
public void resizeEntityAndReinsert(TextEntity entityToBeResized, ManualResizeRedaction manualResizeRedaction) {
entityToBeResized.notifyEntityRemoved();
PositionOnPage positionOnPageToBeResized = entityToBeResized.getPositionsOnPagePerPage()
.stream()
.filter(redactionPosition -> redactionPosition.getId().equals(manualResizeRedaction.getAnnotationId()))
@ -103,7 +109,7 @@ public class ManualChangesApplicationService {
.stream()
.flatMap(Collection::stream)
.forEach(TextEntity::removeFromGraph);
return;
break;
}
possibleEntities.values()
@ -114,9 +120,15 @@ public class ManualChangesApplicationService {
if (node.hasParent()) {
node = node.getParent();
} else {
break;
node = null;
}
}
entityToBeResized.getRelations().keySet()
.forEach(textEntity -> textEntity.getRelations().remove(entityToBeResized));
entityToBeResized.setRelations(new HashMap<>());
entityToBeResized.computeRelations();
entityToBeResized.notifyEntityInserted();
}

View File

@ -1,17 +1,9 @@
package com.iqser.red.service.redaction.v1.server.service.document;
import static com.iqser.red.service.redaction.v1.server.service.document.EntityCreationUtility.addEntityToNodeEntitySets;
import static com.iqser.red.service.redaction.v1.server.service.document.EntityCreationUtility.addToPages;
import static com.iqser.red.service.redaction.v1.server.service.document.EntityCreationUtility.allEntitiesIntersectAndHaveSameTypes;
import static com.iqser.red.service.redaction.v1.server.service.document.EntityCreationUtility.checkIfBothStartAndEndAreEmpty;
import static com.iqser.red.service.redaction.v1.server.service.document.EntityCreationUtility.findIntersectingSubNodes;
import static com.iqser.red.service.redaction.v1.server.service.document.EntityCreationUtility.toLineAfterTextRange;
import static com.iqser.red.service.redaction.v1.server.service.document.EntityCreationUtility.truncateEndIfLineBreakIsBetween;
import static com.iqser.red.service.redaction.v1.server.utils.SeparatorUtils.boundaryIsSurroundedBySeparators;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
@ -21,7 +13,6 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.lang3.tuple.Pair;
import org.kie.api.runtime.KieSession;
import com.google.common.base.Functions;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Engine;
@ -38,35 +29,26 @@ import com.iqser.red.service.redaction.v1.server.model.document.nodes.SemanticNo
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Table;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.TableCell;
import com.iqser.red.service.redaction.v1.server.model.document.textblock.TextBlock;
import com.iqser.red.service.redaction.v1.server.service.drools.KieSessionUpdater;
import com.iqser.red.service.redaction.v1.server.utils.EntityCreationUtility;
import com.iqser.red.service.redaction.v1.server.utils.EntityEnrichmentService;
import com.iqser.red.service.redaction.v1.server.utils.RectangleTransformations;
import com.iqser.red.service.redaction.v1.server.utils.RedactionSearchUtility;
import com.iqser.red.service.redaction.v1.server.utils.exception.NotFoundException;
import lombok.RequiredArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RequiredArgsConstructor
@NoArgsConstructor
public class EntityCreationService {
private final EntityEnrichmentService entityEnrichmentService;
private final KieSession kieSession;
private final Set<SemanticNode> nodesInKieSession; // empty set means all nodes are in kieSession
KieSessionUpdater kieSessionUpdater;
public EntityCreationService(EntityEnrichmentService entityEnrichmentService) {
public EntityCreationService(KieSessionUpdater kieSessionUpdater) {
this.entityEnrichmentService = entityEnrichmentService;
this.kieSession = null;
this.nodesInKieSession = Collections.emptySet();
}
public EntityCreationService(EntityEnrichmentService entityEnrichmentService, KieSession kieSession) {
this.entityEnrichmentService = entityEnrichmentService;
this.kieSession = kieSession;
this.nodesInKieSession = Collections.emptySet();
this.kieSessionUpdater = kieSessionUpdater;
}
@ -83,7 +65,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> betweenStrings(String start, String stop, String type, EntityType entityType, SemanticNode node) {
checkIfBothStartAndEndAreEmpty(start, stop);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(start, stop);
List<TextRange> startTextRanges = RedactionSearchUtility.findTextRangesByString(start, node.getTextBlock());
List<TextRange> stopTextRanges = RedactionSearchUtility.findTextRangesByString(stop, node.getTextBlock());
@ -105,7 +87,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> betweenStringsIgnoreCase(String start, String stop, String type, EntityType entityType, SemanticNode node) {
checkIfBothStartAndEndAreEmpty(start, stop);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(start, stop);
List<TextRange> startBoundaries = RedactionSearchUtility.findTextRangesByStringIgnoreCase(start, node.getTextBlock());
List<TextRange> stopBoundaries = RedactionSearchUtility.findTextRangesByStringIgnoreCase(stop, node.getTextBlock());
@ -127,7 +109,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> betweenStringsIncludeStart(String start, String stop, String type, EntityType entityType, SemanticNode node) {
checkIfBothStartAndEndAreEmpty(start, stop);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(start, stop);
List<TextRange> startBoundaries = RedactionSearchUtility.findTextRangesByString(start, node.getTextBlock());
List<TextRange> stopBoundaries = RedactionSearchUtility.findTextRangesByString(stop, node.getTextBlock());
@ -154,7 +136,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> betweenStringsIncludeStartIgnoreCase(String start, String stop, String type, EntityType entityType, SemanticNode node) {
checkIfBothStartAndEndAreEmpty(start, stop);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(start, stop);
List<TextRange> startBoundaries = RedactionSearchUtility.findTextRangesByStringIgnoreCase(start, node.getTextBlock());
List<TextRange> stopBoundaries = RedactionSearchUtility.findTextRangesByStringIgnoreCase(stop, node.getTextBlock());
@ -181,7 +163,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> betweenStringsIncludeEnd(String start, String stop, String type, EntityType entityType, SemanticNode node) {
checkIfBothStartAndEndAreEmpty(start, stop);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(start, stop);
List<TextRange> startBoundaries = RedactionSearchUtility.findTextRangesByString(start, node.getTextBlock());
List<TextRange> stopBoundaries = RedactionSearchUtility.findTextRangesByString(stop, node.getTextBlock());
@ -208,7 +190,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> betweenStringsIncludeEndIgnoreCase(String start, String stop, String type, EntityType entityType, SemanticNode node) {
checkIfBothStartAndEndAreEmpty(start, stop);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(start, stop);
List<TextRange> startBoundaries = RedactionSearchUtility.findTextRangesByStringIgnoreCase(start, node.getTextBlock());
List<TextRange> stopBoundaries = RedactionSearchUtility.findTextRangesByStringIgnoreCase(stop, node.getTextBlock());
@ -235,7 +217,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> betweenStringsIncludeStartAndEnd(String start, String stop, String type, EntityType entityType, SemanticNode node) {
checkIfBothStartAndEndAreEmpty(start, stop);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(start, stop);
List<TextRange> startBoundaries = RedactionSearchUtility.findTextRangesByString(start, node.getTextBlock());
List<TextRange> stopBoundaries = RedactionSearchUtility.findTextRangesByString(stop, node.getTextBlock());
@ -266,7 +248,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> betweenStringsIncludeStartAndEndIgnoreCase(String start, String stop, String type, EntityType entityType, SemanticNode node) {
checkIfBothStartAndEndAreEmpty(start, stop);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(start, stop);
List<TextRange> startBoundaries = RedactionSearchUtility.findTextRangesByStringIgnoreCase(start, node.getTextBlock());
List<TextRange> stopBoundaries = RedactionSearchUtility.findTextRangesByStringIgnoreCase(stop, node.getTextBlock());
@ -297,7 +279,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> shortestBetweenAnyString(List<String> starts, List<String> stops, String type, EntityType entityType, SemanticNode node) {
checkIfBothStartAndEndAreEmpty(starts, stops);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(starts, stops);
List<TextRange> startTextRanges = RedactionSearchUtility.findTextRangesByList(starts, node.getTextBlock());
List<TextRange> stopTextRanges = RedactionSearchUtility.findTextRangesByList(stops, node.getTextBlock());
@ -319,7 +301,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> shortestBetweenAnyStringIgnoreCase(List<String> starts, List<String> stops, String type, EntityType entityType, SemanticNode node) {
checkIfBothStartAndEndAreEmpty(starts, stops);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(starts, stops);
List<TextRange> startTextRanges = RedactionSearchUtility.findTextRangesByListIgnoreCase(starts, node.getTextBlock());
List<TextRange> stopTextRanges = RedactionSearchUtility.findTextRangesByListIgnoreCase(stops, node.getTextBlock());
@ -342,7 +324,7 @@ public class EntityCreationService {
*/
public Stream<TextEntity> shortestBetweenAnyStringIgnoreCase(List<String> starts, List<String> stops, String type, EntityType entityType, SemanticNode node, int limit) {
checkIfBothStartAndEndAreEmpty(starts, stops);
EntityCreationUtility.checkIfBothStartAndEndAreEmpty(starts, stops);
List<TextRange> startTextRanges = RedactionSearchUtility.findTextRangesByListIgnoreCase(starts, node.getTextBlock());
List<TextRange> stopTextRanges = RedactionSearchUtility.findTextRangesByListIgnoreCase(stops, node.getTextBlock());
@ -498,7 +480,7 @@ public class EntityCreationService {
TextBlock textBlock = node.getTextBlock();
SearchImplementation searchImplementation = new SearchImplementation(strings, false);
return searchImplementation.getBoundaries(textBlock)
.map(boundary -> toLineAfterTextRange(textBlock, boundary))
.map(boundary -> EntityCreationUtility.toLineAfterTextRange(textBlock, boundary))
.filter(boundary -> isValidEntityTextRange(textBlock, boundary))
.map(boundary -> byTextRange(boundary, type, entityType, node))
.filter(Optional::isPresent)
@ -520,7 +502,7 @@ public class EntityCreationService {
TextBlock textBlock = node.getTextBlock();
SearchImplementation searchImplementation = new SearchImplementation(strings, true);
return searchImplementation.getBoundaries(textBlock)
.map(boundary -> toLineAfterTextRange(textBlock, boundary))
.map(boundary -> EntityCreationUtility.toLineAfterTextRange(textBlock, boundary))
.filter(boundary -> isValidEntityTextRange(textBlock, boundary))
.map(boundary -> byTextRange(boundary, type, entityType, node))
.filter(Optional::isPresent)
@ -542,7 +524,7 @@ public class EntityCreationService {
TextBlock textBlock = node.getTextBlock();
return RedactionSearchUtility.findTextRangesByString(string, textBlock)
.stream()
.map(boundary -> toLineAfterTextRange(textBlock, boundary))
.map(boundary -> EntityCreationUtility.toLineAfterTextRange(textBlock, boundary))
.filter(boundary -> isValidEntityTextRange(textBlock, boundary))
.map(boundary -> byTextRange(boundary, type, entityType, node))
.filter(Optional::isPresent)
@ -564,7 +546,7 @@ public class EntityCreationService {
TextBlock textBlock = node.getTextBlock();
return RedactionSearchUtility.findTextRangesByStringIgnoreCase(string, textBlock)
.stream()
.map(boundary -> toLineAfterTextRange(textBlock, boundary))
.map(boundary -> EntityCreationUtility.toLineAfterTextRange(textBlock, boundary))
.filter(boundary -> isValidEntityTextRange(textBlock, boundary))
.map(boundary -> byTextRange(boundary, type, entityType, node))
.filter(Optional::isPresent)
@ -949,7 +931,7 @@ public class EntityCreationService {
public Optional<TextEntity> bySuffixExpansionRegex(TextEntity entity, String regexPattern) {
int expandedEnd = RedactionSearchUtility.getExpandedEndByRegex(entity, regexPattern);
expandedEnd = truncateEndIfLineBreakIsBetween(entity.getTextRange().end(), expandedEnd, entity.getDeepestFullyContainingNode().getTextBlock());
expandedEnd = EntityCreationUtility.truncateEndIfLineBreakIsBetween(entity.getTextRange().end(), expandedEnd, entity.getDeepestFullyContainingNode().getTextBlock());
return byTextRange(new TextRange(entity.getTextRange().start(), expandedEnd), entity.type(), entity.getEntityType(), entity.getDeepestFullyContainingNode());
}
@ -1012,12 +994,12 @@ public class EntityCreationService {
}
return Optional.empty(); // Entity has been resized, if there are duplicates they should be treated there
}
boolean added = addEntityToGraph(entity, node.getDocumentTree());
if (!added) {
return Optional.empty();
}
addListenerToEntity(entity);
node.getDocumentTree().addEntityToGraph(entity);
entity.addEngines(engines);
insertToKieSession(entity);
return Optional.of(entity);
}
@ -1057,7 +1039,7 @@ public class EntityCreationService {
@Deprecated(forRemoval = true)
public TextEntity mergeEntitiesOfSameType(List<TextEntity> entitiesToMerge, String type, EntityType entityType, SemanticNode node) {
if (!allEntitiesIntersectAndHaveSameTypes(entitiesToMerge)) {
if (!EntityCreationUtility.allEntitiesIntersectAndHaveSameTypes(entitiesToMerge)) {
throw new IllegalArgumentException("Provided entities can not be merged, since they do not intersect or are not the same type!" + entitiesToMerge);
}
if (entitiesToMerge.isEmpty()) {
@ -1082,17 +1064,16 @@ public class EntityCreationService {
.map(TextEntity::getManualOverwrite)
.map(ManualChangeOverwrite::getManualChangeLog)
.flatMap(Collection::stream)
.forEach(manualChange -> mergedEntity.getManualOverwrite().addChange(manualChange));
.forEach(mergedEntity::addManualChange);
mergedEntity.setDictionaryEntry(entitiesToMerge.stream()
.anyMatch(TextEntity::isDictionaryEntry));
mergedEntity.setDossierDictionaryEntry(entitiesToMerge.stream()
.anyMatch(TextEntity::isDossierDictionaryEntry));
entityEnrichmentService.enrichEntity(mergedEntity, node.getTextBlock());
EntityEnrichmentService.enrichEntity(mergedEntity, node.getTextBlock());
addEntityToGraph(mergedEntity, node);
insertToKieSession(mergedEntity);
entitiesToMerge.stream()
.filter(e -> !e.equals(mergedEntity))
@ -1147,26 +1128,13 @@ public class EntityCreationService {
TextEntity newEntity = byTextRangeWithEngine(entity.getTextRange(), type, entityType, node, entity.getEngines()).orElseThrow(() -> new NotFoundException(
"No entity present!"));
newEntity.getManualOverwrite().addChanges(entity.getManualOverwrite().getManualChangeLog());
newEntity.addManualChanges(entity.getManualOverwrite().getManualChangeLog());
newEntity.setDictionaryEntry(entity.isDictionaryEntry());
newEntity.setDossierDictionaryEntry(entity.isDossierDictionaryEntry());
return newEntity;
}
/**
* Inserts a text entity into the kieSession for further processing.
*
* @param textEntity The merged text entity to insert.
*/
public void insertToKieSession(TextEntity textEntity) {
if (kieSession != null) {
kieSession.insert(textEntity);
}
}
/**
* Creates a text entity based on a Named Entity Recognition (NER) entity.
*
@ -1454,7 +1422,8 @@ public class EntityCreationService {
.ifPresent(e -> addDuplicateEntityToGraph(e, entity.getTextRange(), node));
} else {
addEntityToGraph(entity, documentTree);
addListenerToEntity(entity);
documentTree.addEntityToGraph(entity);
}
}
@ -1492,7 +1461,7 @@ public class EntityCreationService {
entityToDuplicate.setDeepestFullyContainingNode(deepestSharedNode);
Set<SemanticNode> additionalIntersectingNodes = findIntersectingSubNodes(deepestSharedNode, newTextRange);
Set<SemanticNode> additionalIntersectingNodes = EntityCreationUtility.findIntersectingSubNodes(deepestSharedNode, newTextRange);
additionalIntersectingNodes.forEach(additionalIntersectingNode -> {
if (entityToDuplicate.getIntersectingNodes().contains(additionalIntersectingNode)) {
@ -1506,23 +1475,13 @@ public class EntityCreationService {
}
private boolean addEntityToGraph(TextEntity entity, DocumentTree documentTree) {
private void addListenerToEntity(TextEntity textEntity) {
documentTree.getRoot().getNode().addThisToEntityIfIntersects(entity);
if (!nodesInKieSession.isEmpty() && entity.getIntersectingNodes()
.stream()
.anyMatch(node -> !nodesInKieSession.contains(node))) {
entity.removeFromGraph();
return false;
if(kieSessionUpdater != null) {
textEntity.addEntityEventListener(kieSessionUpdater);
}
TextBlock textBlock = entity.getDeepestFullyContainingNode().getTextBlock();
entityEnrichmentService.enrichEntity(entity, textBlock);
addToPages(entity);
addEntityToNodeEntitySets(entity);
return true;
}
}

View File

@ -2,7 +2,6 @@ package com.iqser.red.service.redaction.v1.server.service.drools;
import static com.iqser.red.service.redaction.v1.server.service.drools.ComponentDroolsExecutionService.RULES_LOGGER_GLOBAL;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
@ -29,11 +28,12 @@ import com.iqser.red.service.redaction.v1.server.logger.RulesLogger;
import com.iqser.red.service.redaction.v1.server.logger.TrackingAgendaEventListener;
import com.iqser.red.service.redaction.v1.server.model.NerEntities;
import com.iqser.red.service.redaction.v1.server.model.dictionary.Dictionary;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Document;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Image;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.SemanticNode;
import com.iqser.red.service.redaction.v1.server.service.ManualChangesApplicationService;
import com.iqser.red.service.redaction.v1.server.service.document.EntityCreationService;
import com.iqser.red.service.redaction.v1.server.service.document.EntityEnrichmentService;
import com.iqser.red.service.redaction.v1.server.service.websocket.WebSocketService;
import com.iqser.red.service.redaction.v1.server.utils.exception.DroolsTimeoutException;
@ -51,7 +51,6 @@ import lombok.extern.slf4j.Slf4j;
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class EntityDroolsExecutionService {
EntityEnrichmentService entityEnrichmentService;
ObservationRegistry observationRegistry;
ManualChangesApplicationService manualChangesApplicationService;
RedactionServiceSettings settings;
@ -95,81 +94,86 @@ public class EntityDroolsExecutionService {
KieSession kieSession = kieContainer.newKieSession();
Set<SemanticNode> nodesInKieSession = sectionsToAnalyze.size() == document.streamAllSubNodes()
.count() ? Collections.emptySet() : buildSet(sectionsToAnalyze, document);
EntityCreationService entityCreationService = new EntityCreationService(entityEnrichmentService, kieSession, nodesInKieSession);
RulesLogger logger = new RulesLogger(webSocketService, context);
if (settings.isDroolsDebug()) {
logger.enableAgendaTracking();
logger.enableObjectTracking();
}
kieSession.addEventListener(new TrackingAgendaEventListener(logger));
kieSession.addEventListener(new ObjectTrackingEventListener(logger));
kieSession.setGlobal("document", document);
kieSession.setGlobal("entityCreationService", entityCreationService);
kieSession.setGlobal("manualChangesApplicationService", manualChangesApplicationService);
kieSession.setGlobal("dictionary", dictionary);
if (hasGlobalWithName(kieSession, RULES_LOGGER_GLOBAL)) {
kieSession.setGlobal(RULES_LOGGER_GLOBAL, logger);
}
kieSession.insert(document);
document.getEntities()
.forEach(kieSession::insert);
sectionsToAnalyze.forEach(kieSession::insert);
sectionsToAnalyze.stream()
.flatMap(SemanticNode::streamAllSubNodes)
.forEach(kieSession::insert);
document.getPages()
.forEach(kieSession::insert);
fileAttributes.stream()
.filter(f -> f.getValue() != null)
.forEach(kieSession::insert);
if (manualRedactions != null) {
manualRedactions.buildAll()
.stream()
.filter(BaseAnnotation::isLocal)
.forEach(kieSession::insert);
}
kieSession.insert(nerEntities);
kieSession.getAgenda().getAgendaGroup("LOCAL_DICTIONARY_ADDS").setFocus();
CompletableFuture<Void> completableFuture = CompletableFuture.supplyAsync(() -> {
kieSession.fireAllRules();
return null;
});
try {
completableFuture.get(settings.getDroolsExecutionTimeoutSecs(document.getNumberOfPages()), TimeUnit.SECONDS);
} catch (ExecutionException e) {
logger.error(e, "Exception during rule execution");
kieSession.dispose();
if (e.getCause() instanceof TimeoutException) {
throw new DroolsTimeoutException(String.format("The file %s caused a timeout",context.getFileId()), e, false, RuleFileType.ENTITY);
KieSessionUpdater kieSessionUpdater = new KieSessionUpdater(kieSession);
EntityCreationService entityCreationService = new EntityCreationService(kieSessionUpdater);
RulesLogger logger = new RulesLogger(webSocketService, context);
if (settings.isDroolsDebug()) {
logger.enableAgendaTracking();
logger.enableObjectTracking();
}
throw new RuntimeException(e);
} catch (InterruptedException e) {
logger.error(e, "Exception during rule execution");
kieSession.dispose();
throw new RuntimeException(e);
} catch (TimeoutException e) {
throw new DroolsTimeoutException(String.format("The file %s caused a timeout",context.getFileId()), e, false, RuleFileType.ENTITY);
}
kieSession.addEventListener(new TrackingAgendaEventListener(logger));
kieSession.addEventListener(new ObjectTrackingEventListener(logger));
List<FileAttribute> resultingFileAttributes = getFileAttributes(kieSession);
kieSession.dispose();
return resultingFileAttributes;
kieSession.setGlobal("document", document);
kieSession.setGlobal("entityCreationService", entityCreationService);
kieSession.setGlobal("manualChangesApplicationService", manualChangesApplicationService);
kieSession.setGlobal("dictionary", dictionary);
if (hasGlobalWithName(kieSession, RULES_LOGGER_GLOBAL)) {
kieSession.setGlobal(RULES_LOGGER_GLOBAL, logger);
}
kieSession.insert(document);
sectionsToAnalyze.forEach(kieSession::insert);
sectionsToAnalyze.stream()
.flatMap(SemanticNode::streamAllSubNodes)
.forEach(semanticNode -> {
if (semanticNode instanceof Image image) {
image.addEntityEventListener(kieSessionUpdater);
image.notifyEntityInserted();
} else {
kieSession.insert(semanticNode);
}
});
for (TextEntity textEntity : document.getEntities()) {
textEntity.addEntityEventListener(kieSessionUpdater);
textEntity.notifyEntityInserted();
}
document.getPages()
.forEach(kieSession::insert);
fileAttributes.stream()
.filter(f -> f.getValue() != null)
.forEach(kieSession::insert);
if (manualRedactions != null) {
manualRedactions.buildAll()
.stream()
.filter(BaseAnnotation::isLocal)
.forEach(kieSession::insert);
}
kieSession.insert(nerEntities);
kieSession.getAgenda().getAgendaGroup("LOCAL_DICTIONARY_ADDS").setFocus();
CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(kieSession::fireAllRules);
try {
completableFuture.get(settings.getDroolsExecutionTimeoutSecs(document.getNumberOfPages()), TimeUnit.SECONDS);
} catch (ExecutionException e) {
logger.error(e, "Exception during rule execution");
if (e.getCause() instanceof TimeoutException) {
throw new DroolsTimeoutException(String.format("The file %s caused a timeout", context.getFileId()), e, false, RuleFileType.ENTITY);
}
throw new RuntimeException(e);
} catch (InterruptedException e) {
logger.error(e, "Exception during rule execution");
throw new RuntimeException(e);
} catch (TimeoutException e) {
throw new DroolsTimeoutException(String.format("The file %s caused a timeout", context.getFileId()), e, false, RuleFileType.ENTITY);
}
List<FileAttribute> resultingFileAttributes = getFileAttributes(kieSession);
return resultingFileAttributes;
} finally {
kieSession.dispose();
}
}

View File

@ -0,0 +1,98 @@
package com.iqser.red.service.redaction.v1.server.service.drools;
import java.util.Collection;
import java.util.Collections;
import java.util.function.Consumer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.FactHandle;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityEventListener;
import com.iqser.red.service.redaction.v1.server.model.document.entity.IEntity;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Image;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.SemanticNode;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
@RequiredArgsConstructor
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class KieSessionUpdater implements EntityEventListener {
KieSession kieSession;
@Override
public void onEntityInserted(IEntity entity) {
handleOnEntityEvent(entity, kieSession::insert);
kieSession.insert(entity);
}
@Override
public void onEntityUpdated(IEntity entity) {
handleOnEntityEvent(entity, this::updateFactIfPresent);
kieSession.update(kieSession.getFactHandle(entity), entity);
}
@Override
public void onEntityRemoved(IEntity entity) {
handleOnEntityEvent(entity, this::deleteFactIfPresent);
kieSession.delete(kieSession.getFactHandle(entity));
}
private void handleOnEntityEvent(IEntity entity, Consumer<Object> consumer) {
if (entity instanceof TextEntity textEntity) {
updateIntersectingNodes(textEntity);
textEntity.getRelations().values()
.stream()
.flatMap(Collection::stream)
.forEach(consumer);
textEntity.getRelations().keySet()
.forEach(k -> k.getRelations().getOrDefault(textEntity, Collections.emptySet())
.forEach(consumer));
}
if (entity instanceof Image image) {
SemanticNode parent = image;
while (parent.hasParent()) {
parent = parent.getParent();
kieSession.update(kieSession.getFactHandle(parent), parent);
}
}
}
private void updateIntersectingNodes(TextEntity textEntity) {
textEntity.getIntersectingNodes()
.forEach(this::updateFactIfPresent);
}
private void updateFactIfPresent(Object o) {
FactHandle factHandle = kieSession.getFactHandle(o);
if (factHandle != null) {
kieSession.update(factHandle, o);
}
}
private void deleteFactIfPresent(Object o) {
FactHandle factHandle = kieSession.getFactHandle(o);
if (factHandle != null) {
kieSession.delete(factHandle);
}
}
}

View File

@ -13,12 +13,14 @@ import java.util.stream.Stream;
import java.util.Optional;
import com.iqser.red.service.redaction.v1.server.logger.RulesLogger;
import com.iqser.red.service.redaction.v1.server.model.document.*;
import com.iqser.red.service.redaction.v1.server.model.document.TextRange;
import com.iqser.red.service.redaction.v1.server.model.document.entity.*;
import com.iqser.red.service.redaction.v1.server.model.document.entity.IEntity;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType;
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.*;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Section;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Table;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.TableCell;
@ -47,8 +49,6 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualRecategorization;
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualLegalBasisChange;
import com.iqser.red.service.redaction.v1.server.data.LayoutEngineProto.LayoutEngine;
global Document document
global EntityCreationService entityCreationService
global ManualChangesApplicationService manualChangesApplicationService
@ -1311,8 +1311,6 @@ rule "MAN.0.0: Apply manual resize redaction"
then
manualChangesApplicationService.resize($entityToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($entityToBeResized);
$entityToBeResized.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.0.1: Apply manual resize redaction"
@ -1324,8 +1322,6 @@ rule "MAN.0.1: Apply manual resize redaction"
then
manualChangesApplicationService.resizeImage($imageToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($imageToBeResized);
update($imageToBeResized.getParent());
end
@ -1336,10 +1332,8 @@ rule "MAN.1.0: Apply id removals that are valid and not in forced redactions to
$idRemoval: IdRemoval($id: annotationId, !removeFromDictionary, !removeFromAllDossiers)
$entityToBeRemoved: TextEntity(matchesAnnotationId($id))
then
$entityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($entityToBeRemoved);
$entityToBeRemoved.addManualChange($idRemoval);
retract($idRemoval);
$entityToBeRemoved.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to Image"
@ -1349,9 +1343,7 @@ rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to
$imageEntityToBeRemoved: Image($id == id)
then
$imageEntityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($imageEntityToBeRemoved);
retract($idRemoval);
update($imageEntityToBeRemoved.getParent());
end
@ -1362,9 +1354,7 @@ rule "MAN.2.0: Apply force redaction"
$force: ManualForceRedaction($id: annotationId)
$entityToForce: TextEntity(matchesAnnotationId($id))
then
$entityToForce.getManualOverwrite().addChange($force);
update($entityToForce);
$entityToForce.getIntersectingNodes().forEach(node -> update(node));
$entityToForce.addManualChange($force);
retract($force);
end
@ -1375,8 +1365,6 @@ rule "MAN.2.1: Apply force redaction to images"
$imageToForce: Image(id == $id)
then
$imageToForce.getManualOverwrite().addChange($force);
update($imageToForce);
update($imageToForce.getParent());
retract($force);
end
@ -1389,9 +1377,7 @@ rule "MAN.3.0: Apply entity recategorization"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() != $type)
then
$entityToBeRecategorized.getIntersectingNodes().forEach(node -> update(node));
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
update($entityToBeRecategorized);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -1402,7 +1388,7 @@ rule "MAN.3.1: Apply entity recategorization of same type"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() == $type)
then
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -1414,8 +1400,6 @@ rule "MAN.3.2: Apply image recategorization"
$imageToBeRecategorized: Image($id == id)
then
manualChangesApplicationService.recategorize($imageToBeRecategorized, $recategorization);
update($imageToBeRecategorized);
update($imageToBeRecategorized.getParent());
retract($recategorization);
end
@ -1436,7 +1420,6 @@ rule "MAN.4.0: Apply legal basis change"
$imageToBeRecategorized: Image($id == id)
then
$imageToBeRecategorized.getManualOverwrite().addChange($legalBasisChange);
update($imageToBeRecategorized)
retract($legalBasisChange)
end
@ -1446,8 +1429,7 @@ rule "MAN.4.1: Apply legal basis change"
$legalBasisChange: ManualLegalBasisChange($id: annotationId)
$entityToBeChanged: TextEntity(matchesAnnotationId($id))
then
$entityToBeChanged.getManualOverwrite().addChange($legalBasisChange);
update($entityToBeChanged)
$entityToBeChanged.addManualChange($legalBasisChange);
retract($legalBasisChange)
end
@ -1458,71 +1440,114 @@ rule "MAN.4.1: Apply legal basis change"
rule "X.0.0: Remove Entity contained by Entity of same type"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), !hasManualChanges())
not TextEntity(getTextRange().equals($larger.getTextRange()), type() == $type, entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY, !hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
!$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
not TextEntity(
getTextRange().equals($container.getTextRange()),
type() == $container.type(),
entityType == EntityType.DICTIONARY_REMOVAL,
engines contains Engine.DOSSIER_DICTIONARY,
!hasManualChanges()
)
then
$contained.remove("X.0.0", "remove Entity contained by Entity of same type");
retract($contained);
end
end
rule "X.0.1: Remove Entity contained by Entity of same type with manual changes"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
then
$contained.getIntersectingNodes().forEach(node -> update(node));
$contained.remove("X.0.1", "remove Entity contained by Entity of same type with manual changes");
retract($contained);
end
end
// Rule unit: X.2
rule "X.2.0: Remove Entity of type ENTITY when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.ENTITY), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.ENTITY,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
end
rule "X.2.1: Remove Entity of type HINT when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.HINT), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.HINT,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("X.2.1", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.1", "remove Entity of type HINT when contained by FALSE_POSITIVE");
end
// Rule unit: X.3
rule "X.3.0: Remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION"
rule "X.3.0: Remove RECOMMENDATION Contained by FALSE_RECOMMENDATION"
salience 64
when
$falseRecommendation: TextEntity($type: type(), entityType == EntityType.FALSE_RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($falseRecommendation), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
end
// Rule unit: X.4
rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY with same type"
salience 256
when
$entity: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(getTextRange().equals($entity.getTextRange()), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$entity.addEngines($recommendation.getEngines());
$recommendation.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
retract($recommendation);
$a.addEngines($b.getEngines());
$b.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
end
@ -1530,22 +1555,33 @@ rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY
rule "X.5.0: Remove Entity of type RECOMMENDATION when intersected by ENTITY"
salience 256
when
$entity: TextEntity((entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(intersects($entity), entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$intersection: Intersection(
$a: a,
$b: b,
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$recommendation.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
retract($recommendation);
$b.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
end
rule "X.5.1: Remove Entity of type RECOMMENDATION when contained by RECOMMENDATION"
salience 256
when
$entity: TextEntity($type: type(), entityType == EntityType.RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($entity), type() != $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$container.type() != $contained.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
end
// Rule unit: X.7
@ -1563,22 +1599,33 @@ rule "X.7.0: Remove all images"
rule "X.8.0: Remove Entity when text range and type equals to imported Entity"
salience 257
when
$entity: TextEntity($type: type(), engines contains Engine.IMPORTED, active())
$other: TextEntity(getTextRange().equals($entity.getTextRange()), this != $entity, type() == $type, engines not contains Engine.IMPORTED)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$entity.addEngines($other.getEngines());
retract($other);
$b.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$a.addEngines($b.getEngines());
end
rule "X.8.1: Remove Entity when intersected by imported Entity"
salience 256
when
$entity: TextEntity(engines contains Engine.IMPORTED, active())
$other: TextEntity(intersects($entity), this != $entity, engines not contains Engine.IMPORTED)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.1", "remove Entity when intersected by imported Entity");
retract($other);
$b.remove("X.8.1", "remove Entity when intersected by imported Entity");
end
@ -1607,11 +1654,16 @@ rule "X.10.0: remove false positives of ai"
rule "X.11.0: Remove dictionary entity which intersects with a manual entity"
salience 64
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active())
$dictionaryEntity: TextEntity(intersects($manualEntity), dictionaryEntry, engines not contains Engine.MANUAL)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.MANUAL,
$a.active(),
$b.dictionaryEntry,
$b.engines not contains Engine.MANUAL
)
then
$dictionaryEntity.remove("X.11.0", "remove dictionary entity which intersects with a manual entity");
retract($dictionaryEntity);
$b.remove("X.11.0", "remove dictionary entity which intersects with a manual entity");
end
@ -1624,7 +1676,6 @@ rule "DICT.0.0: Remove Template Dictionary Entity when contained by Dossier Dict
$dictionaryRemoval: TextEntity($type: type(), entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY)
$entity: TextEntity(getTextRange().equals($dictionaryRemoval.getTextRange()), engines contains Engine.DICTIONARY, type() == $type, (entityType == EntityType.ENTITY || entityType == EntityType.HINT), !hasManualChanges())
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("DICT.0.0", "Remove Template Dictionary Entity when contained by Dossier Dictionary DICTIONARY_REMOVAL");
$entity.addEngine(Engine.DOSSIER_DICTIONARY);
end

View File

@ -18,8 +18,10 @@ import com.iqser.red.service.redaction.v1.server.model.document.TextRange;
import com.iqser.red.service.redaction.v1.server.model.document.entity.*;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType;
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.entity.Containment;
import com.iqser.red.service.redaction.v1.server.model.document.entity.Equality;
import com.iqser.red.service.redaction.v1.server.model.document.entity.Intersection;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.*;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Section;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Table;

View File

@ -14,4 +14,5 @@
<appender-ref ref="${logType}"/>
</root>
<logger name="org.drools.mvel" level="ERROR"/>
<logger name="org.springframework.web.socket.config" level="WARN"/>
</configuration>

View File

@ -32,6 +32,7 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.GZIPInputStream;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@ -61,23 +62,30 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemp
import com.iqser.red.service.redaction.v1.server.client.DictionaryClient;
import com.iqser.red.service.redaction.v1.server.client.LegalBasisClient;
import com.iqser.red.service.redaction.v1.server.client.RulesClient;
import com.iqser.red.service.redaction.v1.server.model.NerEntities;
import com.iqser.red.service.redaction.v1.server.model.dictionary.Dictionary;
import com.iqser.red.service.redaction.v1.server.model.dictionary.DictionaryFactory;
import com.iqser.red.service.redaction.v1.server.model.dictionary.DictionaryIncrement;
import com.iqser.red.service.redaction.v1.server.model.dictionary.DictionaryModel;
import com.iqser.red.service.redaction.v1.server.model.dictionary.DictionaryVersion;
import com.iqser.red.service.redaction.v1.server.queue.RedactionMessageReceiver;
import com.iqser.red.service.redaction.v1.server.service.AnalyzeService;
import com.iqser.red.service.redaction.v1.server.service.DictionaryService;
import com.iqser.red.service.redaction.v1.server.service.websocket.RedisSyncedWebSocketService;
import com.iqser.red.service.redaction.v1.server.storage.RedactionStorageService;
import com.iqser.red.service.redaction.v1.server.testcontainers.MongoDBTestContainer;
import com.iqser.red.service.redaction.v1.server.utils.LayoutParsingRequestProvider;
import com.iqser.red.storage.commons.service.StorageService;
import com.knecon.fforesight.keycloakcommons.security.TenantAuthenticationManagerResolver;
import com.knecon.fforesight.mongo.database.commons.liquibase.TenantMongoLiquibaseExecutor;
import com.knecon.fforesight.mongo.database.commons.service.MongoConnectionProvider;
import com.knecon.fforesight.service.layoutparser.internal.api.queue.LayoutParsingRequest;
import com.knecon.fforesight.service.layoutparser.internal.api.queue.LayoutParsingType;
import com.knecon.fforesight.service.layoutparser.processor.LayoutParsingPipeline;
import com.knecon.fforesight.tenantcommons.TenantContext;
import com.knecon.fforesight.tenantcommons.TenantProvider;
import com.knecon.fforesight.tenantcommons.model.MongoDBConnection;
import com.pdftron.pdf.PDFNet;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
@ -114,7 +122,7 @@ import lombok.extern.slf4j.Slf4j;
FileType.DOCUMENT_POSITION,
FileType.DOCUMENT_STRUCTURE,
FileType.DOCUMENT_TEXT);
Path dossierTemplateToUse = Path.of("/home/kschuettler/Downloads/New Folder/DOSSIER_TEMPLATE"); // Add your dossier-template here
Path dossierTemplateToUse = Path.of("/home/kschuettler/iqser/business-logic/redactmanager/prod-cp-eu-reg/EFSA_sanitisation_pre_GFL_v1"); // Add your dossier-template here
ObjectMapper mapper = ObjectMapperFactory.create();
final String TENANT_ID = "tenant";
TestDossierTemplate testDossierTemplate;
@ -151,13 +159,26 @@ import lombok.extern.slf4j.Slf4j;
private TenantProvider tenantProvider;
@Autowired
private DictionaryFactory dictionaryFactory;
@Autowired
private LayoutParsingPipeline layoutParsingPipeline;
@MockBean
private RedactionMessageReceiver redactionMessageReceiver;
@BeforeAll
public static void init() {
synchronized (PDFNet.class) {
PDFNet.initialize("demo:1650351709282:7bd235e003000000004ec28a6743e1163a085e2115de2536ab6e2cfe5a");
}
}
@Test
@SneakyThrows
public void runAnalysisEnd2End() {
String folder = "/home/kschuettler/Downloads/New Folder/436e4a2a-0ba3-4d3c-9944-c355f5c1cca2"; // Should contain all files from minio directly, still zipped. Can contain multiple files.
String folder = "/home/kschuettler/Dokumente/analysisend2end/file0"; // Should contain all files from minio directly, still zipped. Can contain multiple files.
Path absoluteFolderPath;
if (folder.startsWith("files")) { // if it starts with "files" it is most likely in the resources folder, else it should be an absolute path
@ -171,8 +192,18 @@ import lombok.extern.slf4j.Slf4j;
List<AnalyzeRequest> analyzeRequests = prepareStorageForFolder(absoluteFolderPath);
log.info("Found {} distinct fileIds with all required files", analyzeRequests.size());
for (int i = 0; i < analyzeRequests.size(); i++) {
long start = System.currentTimeMillis();
AnalyzeRequest analyzeRequest = analyzeRequests.get(i);
Path nerEntitiesFile = absoluteFolderPath.resolve(analyzeRequest.getFileId() + ".NER_ENTITIES.json");
if (!Files.exists(nerEntitiesFile)) {
storageService.storeJSONObject(TenantContext.getTenantId(),
RedactionStorageService.StorageIdUtils.getStorageId(analyzeRequest.getDossierId(),
analyzeRequest.getFileId(),
FileType.NER_ENTITIES),
new NerEntities());
}
long start = System.currentTimeMillis();
log.info("----------------------------------------------------------------------------------");
log.info("{}/{}: Starting analysis for file {}", i + 1, analyzeRequests.size(), analyzeRequest.getFileId());
analyzeService.analyze(analyzeRequest);
@ -192,7 +223,7 @@ import lombok.extern.slf4j.Slf4j;
manualRedactionEntry.setValue("7232");
manualRedactionEntry.setReason(
"(Regulations (EU) 2016/679 and (EU) 2018/1725 shall apply to the processing of personal data carried out pursuant to this Regulation. Any personal data made public pursuant to Article 38 of this Regulation and this Article shall only be used to ensure the transparency of the risk assessment under this Regulation and shall not be further processed in a manner that is incompatible with these purposes, in accordance with point (b) of Article 5(1) of Regulation (EU) 2016/679 and point (b) of Article 4(1) of Regulation (EU) 2018/1725, as the case may be)");
manualRedactionEntry.setLegalBasis("Article 39(e)(3) of Regulation (EC) No 178/2002");
manualRedactionEntry.setLegalBasis("personal_data_geolocation_article_39e3");
manualRedactionEntry.setProcessedDate(OffsetDateTime.now());
manualRedactionEntry.setRequestDate(OffsetDateTime.now());
manualRedactionEntry.setPositions(List.of(Rectangle.builder().topLeftX(332.134f).topLeftY(689.72f).width(26.688f).height(13.872f).page(1).build()));
@ -303,7 +334,7 @@ import lombok.extern.slf4j.Slf4j;
AnalyzeRequest request = new AnalyzeRequest();
request.setDossierId(UUID.randomUUID().toString());
request.setFileId(UUID.randomUUID().toString());
request.setFileId(fileName);
request.setDossierTemplateId(testDossierTemplate.id);
request.setAnalysisNumber(-1);
@ -320,18 +351,72 @@ import lombok.extern.slf4j.Slf4j;
Set<FileType> missingFileTypes = Sets.difference(REQUIRED_FILES, uploadedFileTypes);
if (!missingFileTypes.isEmpty()) {
log.error("Folder {} is missing files of type {}",
folder.toFile(),
missingFileTypes.stream()
.map(Enum::toString)
.collect(Collectors.joining(", ")));
return Optional.empty();
if (!missingFileTypes.isEmpty() && !missingFileTypes.contains(FileType.ORIGIN)) {
runLayoutParsingAndSaveFilesToFolder(folder, uploadedFileTypes, request);
}
// if (!missingFileTypes.isEmpty()) {
// log.error("Folder {} is missing files of type {}",
// folder.toFile(),
// missingFileTypes.stream()
// .map(Enum::toString)
// .collect(Collectors.joining(", ")));
// return Optional.empty();
// }
return Optional.of(request);
}
private void runLayoutParsingAndSaveFilesToFolder(Path folder, Set<FileType> uploadedFileTypes, AnalyzeRequest request) throws IOException {
uploadImageAndTableFilesIfMissing(uploadedFileTypes, request);
LayoutParsingRequest layoutParsingRequest = LayoutParsingRequestProvider.build(LayoutParsingType.DOCUMINE_OLD, request);
layoutParsingPipeline.parseLayoutAndSaveFilesToStorage(layoutParsingRequest);
try {
storeFileFromStorage(TENANT_ID, layoutParsingRequest.structureFileStorageId(), folder);
storeFileFromStorage(TENANT_ID, layoutParsingRequest.textBlockFileStorageId(), folder);
storeFileFromStorage(TENANT_ID, layoutParsingRequest.positionBlockFileStorageId(), folder);
storeFileFromStorage(TENANT_ID, layoutParsingRequest.pageFileStorageId(), folder);
} catch (IOException e) {
log.error("Failed to store files from storage to folder {}", folder, e);
}
}
private void uploadImageAndTableFilesIfMissing(Set<FileType> uploadedFileTypes, AnalyzeRequest request) throws IOException {
if (!uploadedFileTypes.contains(FileType.TABLES)) {
var cvServiceResponse = "files/cv_service_empty_response.json";
ClassPathResource cvServiceResponseFileResource = new ClassPathResource(cvServiceResponse);
storageService.storeObject(TenantContext.getTenantId(),
RedactionStorageService.StorageIdUtils.getStorageId(request.getDossierId(), request.getFileId(), FileType.TABLES),
cvServiceResponseFileResource.getInputStream());
}
if (!uploadedFileTypes.contains(FileType.IMAGE_INFO)) {
var imageServiceResponse = "files/empty_image_response.json";
ClassPathResource imageServiceResponseFileResource = new ClassPathResource(imageServiceResponse);
storageService.storeObject(TenantContext.getTenantId(),
RedactionStorageService.StorageIdUtils.getStorageId(request.getDossierId(), request.getFileId(), FileType.IMAGE_INFO),
imageServiceResponseFileResource.getInputStream());
}
}
private void storeFileFromStorage(String tenantId, String storageId, Path folder) throws IOException {
var inputStream = storageService.getObject(tenantId, storageId);
try (FileOutputStream fileOut = new FileOutputStream(folder.toString() + "/" + storageId.split("/")[1])) {
fileOut.write(inputStream.getContentAsByteArray());
} catch (IOException e) {
e.printStackTrace();
}
log.info("Stored file {} to {}", storageId, folder);
}
private static Stream<FileToUpload> findFilesToUpload(String fileName, Path folder, Set<FileType> endingsToUpload) throws IOException {
return Files.walk(folder)

View File

@ -1262,7 +1262,7 @@ public class RedactionIntegrationTest extends RulesIntegrationTest {
.value("0049 331 441 551 14")
.requestDate(OffsetDateTime.now())
.fileId(TEST_FILE_ID)
.legalBasis("Article 39(e)(2) of Regulation (EC) No 178/2002")
.legalBasis("vertebrate_study_personal_data_geolocation_article_39e2")
.user("user")
.build()))
.build());
@ -1315,7 +1315,7 @@ public class RedactionIntegrationTest extends RulesIntegrationTest {
.value("0049 331 441 551 14")
.requestDate(OffsetDateTime.now())
.fileId(TEST_FILE_ID)
.legalBasis("Article 39(e)(2) of Regulation (EC) No 178/2002")
.legalBasis("vertebrate_study_personal_data_geolocation_article_39e2")
.user("user")
.build()))
.recategorizations(Set.of(ManualRecategorization.builder()
@ -1654,35 +1654,46 @@ public class RedactionIntegrationTest extends RulesIntegrationTest {
.get();
request.setManualRedactions(ManualRedactions.builder()
.entriesToAdd(Set.of(ManualRedactionEntry.builder()
.annotationId("newId")
.fileId(TEST_FILE_ID)
.user("user")
.requestDate(OffsetDateTime.now())
.value("David Ksenia")
.type("CBI_author")
.positions(List.of(Rectangle.builder().topLeftX(56.8f).topLeftY(295.2f).width(65.59f).height(12.64f).page(1).build()))
.build()))
.resizeRedactions(Set.of(ManualResizeRedaction.builder()
.updateDictionary(false)
.annotationId(davidKsenia.getId())
.annotationId("newId")
.fileId(TEST_FILE_ID)
.user("user")
.requestDate(OffsetDateTime.now())
.value("David")
.positions(List.of(Rectangle.builder()
.topLeftX(56.8f)
.topLeftY(293.564f)
.width(29.2922f)
.height(15.408f)
.page(1)
.build()))
.positions(List.of(Rectangle.builder().topLeftX(56.8f).topLeftY(293.564f).width(29.2922f).height(15.408f).page(1).build()))
.addToAllDossiers(false)
.build()))
.build());
analyzeService.reanalyze(request);
entityLog = redactionStorageService.getEntityLog(TEST_DOSSIER_ID, TEST_FILE_ID);
var resizedEntity = entityLog.getEntityLogEntry()
.stream()
.filter(e -> e.getId().equals("newId"))
.findFirst()
.get();
var removedEntity = entityLog.getEntityLogEntry()
.stream()
.filter(e -> e.getId().equals(davidKsenia.getId()))
.findFirst()
.get();
assertEquals(resizedEntity.getState(), EntryState.APPLIED);
assertEquals(resizedEntity.getValue(), "David");
assertEquals(1, resizedEntity.getManualChanges().size());
assertEquals(resizedEntity.getManualChanges()
.get(0).getManualRedactionType(), ManualRedactionType.RESIZE);
assertEquals(EntryState.APPLIED, resizedEntity.getState());
assertEquals("David", resizedEntity.getValue());
assertEquals(2, resizedEntity.getManualChanges().size());
assertEquals(1, resizedEntity.getEngines().size());
assertEquals(EntryState.REMOVED, removedEntity.getState());
}
@ -1915,7 +1926,7 @@ public class RedactionIntegrationTest extends RulesIntegrationTest {
.reason("(Regulations (EU) 2016/679 and (EU) 2018/1725 shall apply to the processing of personal data carried out pursuant to this Regulation. Any personal data made public pursuant to Article 38 of this Regulation and this Article shall only be used to ensure the transparency of the risk assessment under this Regulation and shall not be further processed in a manner that is incompatible with these purposes, in accordance with point (b) of Article 5(1) of Regulation (EU) 2016/679 and point (b) of Article 4(1) of Regulation (EU) 2018/1725, as the case may be)")
.addToDossierDictionary(false)
.addToDictionary(false)
.legalBasis("Article 39(e)(3) of Regulation (EC) No 178/2002")
.legalBasis("personal_data_geolocation_article_39e3")
.rectangle(false)
.positions(List.of(Rectangle.builder()
.topLeftX(270.844f)
@ -2262,14 +2273,14 @@ public class RedactionIntegrationTest extends RulesIntegrationTest {
manualRedactionEntry.setValue(valueToAdd);
manualRedactionEntry.setReason("Author found, removed by manual override");
manualRedactionEntry.setSection("Header: This is my test");
manualRedactionEntry.setLegalBasis("Article 39(e)(3) of Regulation (EC) No 178/2002");
manualRedactionEntry.setLegalBasis("personal_data_geolocation_article_39e3");
manualRedactionEntry.setTextBefore("Lorem My Ipsum ");
manualRedactionEntry.setTextAfter("Crandu Seku Laku");
manualRedactionEntry.setPositions(localfullPositions);
ManualForceRedaction forceRequest = new ManualForceRedaction();
forceRequest.setAnnotationId(manualAddId);
forceRequest.setLegalBasis("Article 39(e)(3) of Regulation (EC) No 178/2002");
forceRequest.setLegalBasis("personal_data_geolocation_article_39e3");
forceRequest.setUser("test");
forceRequest.setRequestDate(OffsetDateTime.now());
@ -2353,8 +2364,10 @@ public class RedactionIntegrationTest extends RulesIntegrationTest {
assertEquals(entityLog.getEntityLogEntry().size(), 3);
}
@Test
public void testPurityRule() {
String EFSA_SANITISATION_RULES = loadFromClassPath("drools/efsa_sanitisation.drl");
when(rulesClient.getRules(TEST_DOSSIER_TEMPLATE_ID, RuleFileType.ENTITY)).thenReturn(JSONPrimitive.of(EFSA_SANITISATION_RULES));
@ -2363,7 +2376,10 @@ public class RedactionIntegrationTest extends RulesIntegrationTest {
analyzeService.analyze(request);
var entityLog = redactionStorageService.getEntityLog(TEST_DOSSIER_ID, TEST_FILE_ID);
var entriesCount = entityLog.getEntityLogEntry().stream().filter(e -> e.getValue().toLowerCase(Locale.ENGLISH).startsWith("purity")).collect(Collectors.toList()).size();
var entriesCount = entityLog.getEntityLogEntry()
.stream()
.filter(e -> e.getValue().toLowerCase(Locale.ENGLISH).startsWith("purity"))
.collect(Collectors.toList()).size();
assertEquals(7, entriesCount);
}

View File

@ -14,7 +14,6 @@ import org.junit.jupiter.api.Test;
import org.kie.api.runtime.KieSession;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import com.iqser.red.service.redaction.v1.server.model.document.DocumentTree;
import com.iqser.red.service.redaction.v1.server.model.document.TextRange;
@ -30,12 +29,10 @@ import com.iqser.red.service.redaction.v1.server.model.document.nodes.Table;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.TableCell;
import com.iqser.red.service.redaction.v1.server.model.document.textblock.TextBlock;
import com.iqser.red.service.redaction.v1.server.service.document.EntityCreationService;
import com.iqser.red.service.redaction.v1.server.service.document.EntityEnrichmentService;
import com.iqser.red.service.redaction.v1.server.service.drools.KieSessionUpdater;
public class DocumentIEntityInsertionIntegrationTest extends BuildDocumentIntegrationTest {
@Autowired
private EntityEnrichmentService entityEnrichmentService;
private EntityCreationService entityCreationService;
@Mock
@ -46,7 +43,7 @@ public class DocumentIEntityInsertionIntegrationTest extends BuildDocumentIntegr
public void createEntityCreationService() {
MockitoAnnotations.initMocks(this);
entityCreationService = new EntityCreationService(entityEnrichmentService, kieSession);
entityCreationService = new EntityCreationService(new KieSessionUpdater(kieSession));
}

View File

@ -39,7 +39,6 @@ import com.iqser.red.service.redaction.v1.server.model.document.textblock.TextBl
import com.iqser.red.service.redaction.v1.server.rules.RulesIntegrationTest;
import com.iqser.red.service.redaction.v1.server.service.DictionaryService;
import com.iqser.red.service.redaction.v1.server.service.document.EntityCreationService;
import com.iqser.red.service.redaction.v1.server.service.document.EntityEnrichmentService;
import com.iqser.red.service.redaction.v1.server.service.drools.EntityDroolsExecutionService;
import com.iqser.red.service.redaction.v1.server.utils.PdfVisualisationUtility;
import com.knecon.fforesight.tenantcommons.TenantContext;
@ -53,8 +52,6 @@ public class DocumentPerformanceIntegrationTest extends RulesIntegrationTest {
@Autowired
private DictionaryService dictionaryService;
@Autowired
private EntityEnrichmentService entityEnrichmentService;
private EntityCreationService entityCreationService;
@Autowired
@ -68,7 +65,7 @@ public class DocumentPerformanceIntegrationTest extends RulesIntegrationTest {
@BeforeEach
public void stubClients() {
entityCreationService = new EntityCreationService(entityEnrichmentService);
entityCreationService = new EntityCreationService();
TenantContext.setTenantId("redaction");
when(rulesClient.getVersion(TEST_DOSSIER_TEMPLATE_ID, RuleFileType.ENTITY)).thenReturn(System.currentTimeMillis());

View File

@ -5,28 +5,22 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import com.iqser.red.service.redaction.v1.server.model.dictionary.SearchImplementation;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Document;
import com.iqser.red.service.redaction.v1.server.service.document.EntityCreationService;
import com.iqser.red.service.redaction.v1.server.service.document.EntityEnrichmentService;
public class SearchImplementationTest extends BuildDocumentIntegrationTest {
@Autowired
private EntityEnrichmentService entityEnrichmentService;
@Test
public void testSearchImplementationWithPunctuation() {
Document document = buildGraph("files/Minimal Examples/TestPunctuation");
SearchImplementation searchImplementation = new SearchImplementation(List.of("Kuhn, J. O."), true);
EntityCreationService entityCreationService = new EntityCreationService(entityEnrichmentService);
EntityCreationService entityCreationService = new EntityCreationService();
List<TextEntity> entities = entityCreationService.bySearchImplementation(searchImplementation, "CBI_author", EntityType.ENTITY, document)
.toList();
assertEquals(2, entities.size());
@ -38,7 +32,7 @@ public class SearchImplementationTest extends BuildDocumentIntegrationTest {
Document document = buildGraph("files/syngenta/CustomerFiles/SYNGENTA_EFSA_sanitisation_GFL_v1_moreSections");
SearchImplementation searchImplementation = new SearchImplementation(List.of("mydossierredaction"), true);
EntityCreationService entityCreationService = new EntityCreationService(entityEnrichmentService);
EntityCreationService entityCreationService = new EntityCreationService();
List<TextEntity> entities = entityCreationService.bySearchImplementation(searchImplementation, "dossier_redaction", EntityType.ENTITY, document)
.toList();
assertEquals(2, entities.size());

View File

@ -12,7 +12,6 @@ import java.util.stream.Collectors;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileType;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType;
@ -21,7 +20,6 @@ import com.iqser.red.service.redaction.v1.server.model.document.nodes.Document;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.NodeType;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Table;
import com.iqser.red.service.redaction.v1.server.service.document.EntityCreationService;
import com.iqser.red.service.redaction.v1.server.service.document.EntityEnrichmentService;
import com.iqser.red.service.redaction.v1.server.storage.RedactionStorageService;
import com.iqser.red.service.redaction.v1.server.utils.EntityVisualizationUtility;
import com.knecon.fforesight.service.viewerdoc.service.PDFTronViewerDocumentService;
@ -32,10 +30,6 @@ import lombok.SneakyThrows;
public class TableTest extends BuildDocumentIntegrationTest {
private static final boolean DRAW_FILE = false;
@Autowired
private EntityEnrichmentService entityEnrichmentService;
private EntityCreationService entityCreationService;
private static final String TYPE_1 = "type1";
@ -52,7 +46,7 @@ public class TableTest extends BuildDocumentIntegrationTest {
@BeforeEach
public void createTable() {
entityCreationService = new EntityCreationService(entityEnrichmentService);
entityCreationService = new EntityCreationService();
String fileName = "files/Minimal Examples/BasicTable.pdf";

View File

@ -23,7 +23,6 @@ import com.iqser.red.service.redaction.v1.server.DeprecatedElementsFinder;
import com.iqser.red.service.redaction.v1.server.RedactionServiceSettings;
import com.iqser.red.service.redaction.v1.server.client.RulesClient;
import com.iqser.red.service.redaction.v1.server.model.drools.RuleFileBluePrint;
import com.iqser.red.service.redaction.v1.server.service.document.EntityEnrichmentService;
import com.iqser.red.service.redaction.v1.server.service.drools.DroolsValidationService;
import com.iqser.red.service.redaction.v1.server.service.drools.KieContainerCreationService;
import com.iqser.red.service.redaction.v1.server.service.drools.RuleFileParser;
@ -36,8 +35,6 @@ class DroolsValidationServiceTest {
@MockBean
RulesClient rulesClient;
@MockBean
EntityEnrichmentService entityEnrichmentService;
@MockBean
RedactionServiceSettings redactionServiceSettings;
@ -455,7 +452,7 @@ class DroolsValidationServiceTest {
$entity.redact(
"CBI.1.0",
"Author found",
"Article 39(e)(3) of Regulation (EC) No 178/2002"
"personal_data_geolocation_article_39e3"
);
end
""";

View File

@ -23,7 +23,6 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@ -54,7 +53,6 @@ import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityTyp
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Document;
import com.iqser.red.service.redaction.v1.server.redaction.utils.OsUtils;
import com.iqser.red.service.redaction.v1.server.service.document.EntityCreationService;
import com.iqser.red.service.redaction.v1.server.service.document.EntityEnrichmentService;
import com.knecon.fforesight.service.layoutparser.internal.api.queue.LayoutParsingType;
import com.knecon.fforesight.tenantcommons.TenantContext;
@ -67,8 +65,7 @@ public class ManualChangesEnd2EndTest extends AbstractRedactionIntegrationTest {
private static final String RULES = loadFromClassPath("drools/acceptance_rules.drl");
private static final String DM_RULES = loadFromClassPath("drools/documine_flora.drl");
@Autowired
private EntityEnrichmentService entityEnrichmentService;
private EntityCreationService entityCreationService;
@ -76,7 +73,7 @@ public class ManualChangesEnd2EndTest extends AbstractRedactionIntegrationTest {
@BeforeEach
public void createServices() {
entityCreationService = new EntityCreationService(entityEnrichmentService);
entityCreationService = new EntityCreationService();
}

View File

@ -20,12 +20,9 @@ import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityTyp
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Document;
import com.iqser.red.service.redaction.v1.server.service.document.EntityCreationService;
import com.iqser.red.service.redaction.v1.server.service.document.EntityEnrichmentService;
public class ManualChangesUnitTest extends BuildDocumentIntegrationTest {
@Autowired
private EntityEnrichmentService entityEnrichmentService;
private EntityCreationService entityCreationService;
@ -33,7 +30,7 @@ public class ManualChangesUnitTest extends BuildDocumentIntegrationTest {
@BeforeEach
public void createServices() {
entityCreationService = new EntityCreationService(entityEnrichmentService);
entityCreationService = new EntityCreationService();
}

View File

@ -35,15 +35,12 @@ import com.iqser.red.service.redaction.v1.server.model.document.nodes.Document;
import com.iqser.red.service.redaction.v1.server.service.DictionaryService;
import com.iqser.red.service.redaction.v1.server.service.EntityLogCreatorService;
import com.iqser.red.service.redaction.v1.server.service.document.EntityCreationService;
import com.iqser.red.service.redaction.v1.server.service.document.EntityEnrichmentService;
import com.iqser.red.service.redaction.v1.server.service.document.EntityFromPrecursorCreationService;
import lombok.SneakyThrows;
public class PrecursorEntityTest extends BuildDocumentIntegrationTest {
@Autowired
private EntityEnrichmentService entityEnrichmentService;
@Autowired
private EntityFromPrecursorCreationService entityFromPrecursorCreationService;
@ -104,7 +101,7 @@ public class PrecursorEntityTest extends BuildDocumentIntegrationTest {
public void createFoundManualRedaction2() {
Document document = buildGraph("files/Minimal Examples/TestPunctuation");
EntityCreationService entityCreationService = new EntityCreationService(entityEnrichmentService);
EntityCreationService entityCreationService = new EntityCreationService();
List<TextEntity> tempEntities = entityCreationService.byString("Kuhn, J. O.", "CBI_author", EntityType.ENTITY, document)
.toList();
@ -159,9 +156,9 @@ public class PrecursorEntityTest extends BuildDocumentIntegrationTest {
private DocumentAndEntity createFoundManualRedaction() {
Document document = buildGraph("files/syngenta/CustomerFiles/VV-919901.pdf");
EntityCreationService entityCreationService = new EntityCreationService(entityEnrichmentService);
EntityCreationService entityCreationService = new EntityCreationService();
List<TextEntity> tempEntities = entityCreationService.byString("To: Syngenta Ltd.", "temp", EntityType.ENTITY, document)
List<TextEntity> tempEntities = entityCreationService.byString("To: Syngenta Ltd.", "temp", EntityType.TEMPORARY, document)
.toList();
assertFalse(tempEntities.isEmpty());
var tempEntity = tempEntities.get(0);

View File

@ -19,7 +19,6 @@ import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import com.iqser.red.commons.jackson.ObjectMapperFactory;
@ -32,7 +31,6 @@ import com.iqser.red.service.redaction.v1.server.model.document.entity.PositionO
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Document;
import com.iqser.red.service.redaction.v1.server.service.document.EntityCreationService;
import com.iqser.red.service.redaction.v1.server.service.document.EntityEnrichmentService;
import com.iqser.red.service.redaction.v1.server.service.document.NerEntitiesAdapter;
import com.iqser.red.service.redaction.v1.server.utils.PdfVisualisationUtility;
@ -42,8 +40,6 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
class NerEntitiesAdapterTest extends BuildDocumentIntegrationTest {
@Autowired
private EntityEnrichmentService entityEnrichmentService;
private EntityCreationService entityCreationService;
@ -58,7 +54,7 @@ class NerEntitiesAdapterTest extends BuildDocumentIntegrationTest {
@BeforeEach
public void createEntityCreationService() {
entityCreationService = new EntityCreationService(entityEnrichmentService);
entityCreationService = new EntityCreationService();
}

View File

@ -25,7 +25,7 @@ import com.iqser.red.service.redaction.v1.server.model.dictionary.Dictionary;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Document;
import com.iqser.red.service.redaction.v1.server.service.ManualChangesApplicationService;
import com.iqser.red.service.redaction.v1.server.service.document.EntityCreationService;
import com.iqser.red.service.redaction.v1.server.service.document.EntityEnrichmentService;
import com.iqser.red.service.redaction.v1.server.service.drools.KieSessionUpdater;
@ExtendWith(MockitoExtension.class)
@Import(RulesIntegrationTest.TestConfiguration.class)
@ -33,8 +33,6 @@ public class RulesIntegrationTest extends BuildDocumentIntegrationTest {
protected static final String RULES = "drools/rules.drl";
@Autowired
protected EntityEnrichmentService entityEnrichmentService;
@Autowired
protected ManualChangesApplicationService manualChangesApplicationService;
protected EntityCreationService entityCreationService;
@ -82,7 +80,7 @@ public class RulesIntegrationTest extends BuildDocumentIntegrationTest {
Dictionary dict = Mockito.mock(Dictionary.class);
kieSession = kieContainer.newKieSession();
entityCreationService = new EntityCreationService(entityEnrichmentService, kieSession);
entityCreationService = new EntityCreationService(new KieSessionUpdater(kieSession));
kieSession.setGlobal("manualChangesApplicationService", manualChangesApplicationService);
kieSession.setGlobal("entityCreationService", entityCreationService);
kieSession.setGlobal("dictionary", dict);

View File

@ -11,7 +11,6 @@ Sude Halide Nurullah
Xinyi Y. Tao
Dorn
Prasher
David
annotation
J.B. RASCLE
(果梗を除去したもの)

View File

@ -0,0 +1,100 @@
the
be
to
of
and
a
in
that
have
I
it
for
not
on
with
he
as
you
do
at
this
but
his
by
from
they
we
say
her
she
or
an
will
my
one
all
would
there
their
what
so
up
out
if
about
who
get
which
go
me
when
make
can
like
time
no
just
him
know
take
people
into
year
your
good
some
could
them
see
other
than
then
now
look
only
come
its
over
think
also
back
after
use
two
how
our
work
first
well
way
even
new
want
because
any
these
give
day
most
us

View File

@ -18,8 +18,7 @@ import com.iqser.red.service.redaction.v1.server.model.document.TextRange;
import com.iqser.red.service.redaction.v1.server.model.document.entity.*;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType;
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.*;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Section;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.SuperSection;
@ -105,7 +104,7 @@ rule "CBI.0.1: Add CBI_author with \"et al.\" RegEx (non vertebrate study)"
then
entityCreationService.byRegex("\\b([A-ZÄÖÜ][^\\s\\.,]+( [A-ZÄÖÜ]{1,2}\\.?)?( ?[A-ZÄÖÜ]\\.?)?) et al\\.?", "CBI_author", EntityType.ENTITY, 1, $section)
.forEach(entity -> {
entity.redact("CBI.0.1", "Author found by \"et al\" regex", "Article 39(e)(3) of Regulation (EC) No 178/2002");
entity.redact("CBI.0.1", "Author found by \"et al\" regex", "personal_data_geolocation_article_39e3");
dictionary.recommendEverywhere(entity);
});
end
@ -118,7 +117,7 @@ rule "CBI.0.2: Add CBI_author with \"et al.\" RegEx (vertebrate study)"
then
entityCreationService.byRegex("\\b([A-ZÄÖÜ][^\\s\\.,]+( [A-ZÄÖÜ]{1,2}\\.?)?( ?[A-ZÄÖÜ]\\.?)?) et al\\.?", "CBI_author", EntityType.ENTITY, 1, $section)
.forEach(entity -> {
entity.redact("CBI.0.2", "Author found by \"et al\" regex", "Article 39(e)(2) of Regulation (EC) No 178/2002");
entity.redact("CBI.0.2", "Author found by \"et al\" regex", "vertebrate_study_personal_data_geolocation_article_39e2");
dictionary.recommendEverywhere(entity);
});
end
@ -128,7 +127,7 @@ rule "CBI.0.3: Redact CBI Authors (non vertebrate Study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$entity: TextEntity(type() == "CBI_author", dictionaryEntry)
then
$entity.redact("CBI.0.3", "Author found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$entity.redact("CBI.0.3", "Author found", "personal_data_geolocation_article_39e3");
end
rule "CBI.0.4: Redact CBI Authors (vertebrate Study)"
@ -136,7 +135,7 @@ rule "CBI.0.4: Redact CBI Authors (vertebrate Study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$entity: TextEntity(type() == "CBI_author", dictionaryEntry)
then
$entity.redact("CBI.0.4", "Author found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$entity.redact("CBI.0.4", "Author found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
@ -154,7 +153,7 @@ rule "CBI.1.1: Redact CBI Address (vertebrate Study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$entity: TextEntity(type() == "CBI_address", dictionaryEntry)
then
$entity.redact("CBI.1.1", "Address found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$entity.redact("CBI.1.1", "Address found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
@ -179,7 +178,7 @@ rule "CBI.9.0: Redact all cells with Header Author(s) as CBI_author (non vertebr
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.0", "Author(s) found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.0", "Author(s) found", "personal_data_geolocation_article_39e3"));
end
rule "CBI.9.1: Redact all cells with Header Author as CBI_author (non vertebrate study)"
@ -192,7 +191,7 @@ rule "CBI.9.1: Redact all cells with Header Author as CBI_author (non vertebrate
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.1", "Author found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.1", "Author found", "personal_data_geolocation_article_39e3"));
end
rule "CBI.9.2: Redact all cells with Header Author(s) as CBI_author (non vertebrate study)"
@ -220,7 +219,7 @@ rule "CBI.10.0: Redact all cells with Header Author(s) as CBI_author (vertebrate
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.10.0", "Author(s) found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.10.0", "Author(s) found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "CBI.10.1: Redact all cells with Header Author as CBI_author (vertebrate study)"
@ -233,7 +232,7 @@ rule "CBI.10.1: Redact all cells with Header Author as CBI_author (vertebrate st
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.10.1", "Author found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.10.1", "Author found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "CBI.10.2: Redact all cells with Header Author(s) as CBI_author (vertebrate study)"
@ -380,7 +379,7 @@ rule "CBI.20.2: Redact between \"PERFORMING LABORATORY\" and \"LABORATORY PROJEC
then
entityCreationService.betweenStrings("PERFORMING LABORATORY:", "LABORATORY PROJECT ID:", "CBI_address", EntityType.ENTITY, $section)
.forEach(laboratoryEntity -> {
laboratoryEntity.redact("CBI.20.2", "PERFORMING LABORATORY was found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
laboratoryEntity.redact("CBI.20.2", "PERFORMING LABORATORY was found", "vertebrate_study_personal_data_geolocation_article_39e2");
dictionary.recommendEverywhere(laboratoryEntity);
});
end
@ -405,7 +404,7 @@ rule "CBI.23.0: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (no
$document: Document(containsStringIgnoreCase("AUTHOR(S)"), containsAnyStringIgnoreCase("COMPLETION DATE", "STUDY COMPLETION DATE"))
then
entityCreationService.shortestBetweenAnyStringIgnoreCase(List.of("AUTHOR(S)", "AUTHOR(S):"), List.of("COMPLETION DATE", "COMPLETION DATE:", "STUDY COMPLETION DATE", "STUDY COMPLETION DATE:"), "CBI_author", EntityType.ENTITY, $document, 200)
.forEach(authorEntity -> authorEntity.redact("CBI.23.0", "AUTHOR(S) was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("CBI.23.0", "AUTHOR(S) was found", "personal_data_geolocation_article_39e3"));
end
rule "CBI.23.1: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (vertebrate study)"
@ -414,7 +413,7 @@ rule "CBI.23.1: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (ve
$document: Document(containsStringIgnoreCase("AUTHOR(S)"), containsAnyStringIgnoreCase("COMPLETION DATE", "STUDY COMPLETION DATE"))
then
entityCreationService.shortestBetweenAnyStringIgnoreCase(List.of("AUTHOR(S)", "AUTHOR(S):"), List.of("COMPLETION DATE", "COMPLETION DATE:", "STUDY COMPLETION DATE", "STUDY COMPLETION DATE:"), "CBI_author", EntityType.ENTITY, $document, 200)
.forEach(authorEntity -> authorEntity.redact("CBI.23.1", "AUTHOR(S) was found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("CBI.23.1", "AUTHOR(S) was found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -433,7 +432,7 @@ rule "PII.0.1: Redact all PII (non vertebrate study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$pii: TextEntity(type() == "PII", dictionaryEntry)
then
$pii.redact("PII.0.1", "Personal Information found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$pii.redact("PII.0.1", "Personal Information found", "personal_data_geolocation_article_39e3");
end
rule "PII.0.2: Redact all PII (vertebrate study)"
@ -441,7 +440,7 @@ rule "PII.0.2: Redact all PII (vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$pii: TextEntity(type() == "PII", dictionaryEntry)
then
$pii.redact("PII.0.2", "Personal Information found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$pii.redact("PII.0.2", "Personal Information found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
rule "PII.0.3: Redact all PII"
@ -467,7 +466,7 @@ rule "PII.1.1: Redact Emails by RegEx (Non vertebrate study)"
$section: Section(containsString("@"))
then
entityCreationService.byRegex("\\b([A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z\\-]{1,23}[A-Za-z])\\b", "PII", EntityType.ENTITY, 1, $section)
.forEach(emailEntity -> emailEntity.redact("PII.1.1", "Found by Email Regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(emailEntity -> emailEntity.redact("PII.1.1", "Found by Email Regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.1.2: Redact Emails by RegEx (vertebrate study)"
@ -476,7 +475,7 @@ rule "PII.1.2: Redact Emails by RegEx (vertebrate study)"
$section: Section(containsString("@"))
then
entityCreationService.byRegex("\\b([A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z\\-]{1,23}[A-Za-z])\\b", "PII", EntityType.ENTITY, 1, $section)
.forEach(emailEntity -> emailEntity.redact("PII.1.2", "Found by Email Regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(emailEntity -> emailEntity.redact("PII.1.2", "Found by Email Regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "PII.1.5: Redact Emails by RegEx"
@ -528,7 +527,7 @@ rule "PII.2.1: Redact Phone and Fax by RegEx (non vertebrate study)"
containsString("Fer"))
then
entityCreationService.byRegexIgnoreCase("\\b(contact|telephone|phone|ph\\.|fax|tel|ter[^\\w]|mobile|fel[^\\w]|fer[^\\w])[a-zA-Z\\s]{0,10}[:.\\s]{0,3}([\\+\\d\\(][\\s\\d\\(\\)\\-\\/\\.]{4,100}\\d)\\b", "PII", EntityType.ENTITY, 2, $section)
.forEach(contactEntity -> contactEntity.redact("PII.2.1", "Found by Phone and Fax Regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.2.1", "Found by Phone and Fax Regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.2.2: Redact Phone and Fax by RegEx (vertebrate study)"
@ -545,7 +544,7 @@ rule "PII.2.2: Redact Phone and Fax by RegEx (vertebrate study)"
containsString("Fer"))
then
entityCreationService.byRegexIgnoreCase("\\b(contact|telephone|phone|ph\\.|fax|tel|ter[^\\w]|mobile|fel[^\\w]|fer[^\\w])[a-zA-Z\\s]{0,10}[:.\\s]{0,3}([\\+\\d\\(][\\s\\d\\(\\)\\-\\/\\.]{4,100}\\d)\\b", "PII", EntityType.ENTITY, 2, $section)
.forEach(contactEntity -> contactEntity.redact("PII.2.2", "Found by Phone and Fax Regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.2.2", "Found by Phone and Fax Regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -564,7 +563,7 @@ rule "PII.3.1: Redact telephone numbers by RegEx (Non vertebrate study)"
$section: Section(!hasTables(), matchesRegex("[+]\\d{1,}"))
then
entityCreationService.byRegex("((([+]\\d{1,3} (\\d{7,12})\\b)|([+]\\d{1,3}(\\d{3,12})\\b|[+]\\d{1,3}([ -]\\(?\\d{1,6}\\)?){2,4})|[+]\\d{1,3} ?((\\d{2,6}\\)?)([ -]\\d{2,6}){1,4}))(-\\d{1,3})?\\b)", "PII", EntityType.ENTITY, 1, $section)
.forEach(entity -> entity.redact("PII.3.1", "Telephone number found by regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.3.1", "Telephone number found by regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.3.2: Redact telephone numbers by RegEx (vertebrate study)"
@ -573,7 +572,7 @@ rule "PII.3.2: Redact telephone numbers by RegEx (vertebrate study)"
$section: Section(!hasTables(), matchesRegex("[+]\\d{1,}"))
then
entityCreationService.byRegex("((([+]\\d{1,3} (\\d{7,12})\\b)|([+]\\d{1,3}(\\d{3,12})\\b|[+]\\d{1,3}([ -]\\(?\\d{1,6}\\)?){2,4})|[+]\\d{1,3} ?((\\d{2,6}\\)?)([ -]\\d{2,6}){1,4}))(-\\d{1,3})?\\b)", "PII", EntityType.ENTITY, 1, $section)
.forEach(entity -> entity.redact("PII.3.2", "Telephone number found by regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.3.2", "Telephone number found by regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "PII.3.4: Redact telephone numbers by RegEx (Non vertebrate study)"
@ -582,7 +581,7 @@ rule "PII.3.4: Redact telephone numbers by RegEx (Non vertebrate study)"
$rowCell: TableCell(matchesRegex("[+]\\d{1,}"))
then
entityCreationService.byRegex("((([+]\\d{1,3} (\\d{7,12})\\b)|([+]\\d{1,3}(\\d{3,12})\\b|[+]\\d{1,3}([ -]\\(?\\d{1,6}\\)?){2,4})|[+]\\d{1,3} ?((\\d{2,6}\\)?)([ -]\\d{2,6}){1,4}))(-\\d{1,3})?\\b)", "PII", EntityType.ENTITY, 1, $rowCell)
.forEach(entity -> entity.redact("PII.3.4", "Telephone number found by regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.3.4", "Telephone number found by regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.3.5: Redact telephone numbers by RegEx (vertebrate study)"
@ -591,7 +590,7 @@ rule "PII.3.5: Redact telephone numbers by RegEx (vertebrate study)"
$rowCell: TableCell(matchesRegex("[+]\\d{1,}"))
then
entityCreationService.byRegex("((([+]\\d{1,3} (\\d{7,12})\\b)|([+]\\d{1,3}(\\d{3,12})\\b|[+]\\d{1,3}([ -]\\(?\\d{1,6}\\)?){2,4})|[+]\\d{1,3} ?((\\d{2,6}\\)?)([ -]\\d{2,6}){1,4}))(-\\d{1,3})?\\b)", "PII", EntityType.ENTITY, 1, $rowCell)
.forEach(entity -> entity.redact("PII.3.5", "Telephone number found by regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.3.5", "Telephone number found by regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -672,7 +671,7 @@ rule "PII.5.1: Redact line after contact information keywords reduced (non verte
$section: Section(containsString($contactKeyword))
then
entityCreationService.lineAfterString($contactKeyword, "PII", EntityType.ENTITY, $section)
.forEach(contactEntity -> contactEntity.redact("PII.5.1", "Found after \"" + $contactKeyword + "\" contact keyword", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.5.1", "Found after \"" + $contactKeyword + "\" contact keyword", "personal_data_geolocation_article_39e3"));
end
rule "PII.5.2: Redact line after contact information keywords reduced (Vertebrate study)"
@ -685,7 +684,7 @@ rule "PII.5.2: Redact line after contact information keywords reduced (Vertebrat
$section: Section(containsString($contactKeyword))
then
entityCreationService.lineAfterString($contactKeyword, "PII", EntityType.ENTITY, $section)
.forEach(contactEntity -> contactEntity.redact("PII.5.2", "Found after \"" + $contactKeyword + "\" contact keyword", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.5.2", "Found after \"" + $contactKeyword + "\" contact keyword", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -710,7 +709,7 @@ rule "PII.6.1: Redact line between contact keywords (non vertebrate study)"
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
)
.forEach(contactEntity -> contactEntity.redact("PII.6.1", "Found between contact keywords", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.6.1", "Found between contact keywords", "personal_data_geolocation_article_39e3"));
end
rule "PII.6.2: Redact line between contact keywords (vertebrate study)"
@ -722,7 +721,7 @@ rule "PII.6.2: Redact line between contact keywords (vertebrate study)"
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
)
.forEach(contactEntity -> contactEntity.redact("PII.6.2", "Found between contact keywords", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.6.2", "Found between contact keywords", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "PII.6.3: Redact line between contact keywords (non vertebrate study)"
@ -766,7 +765,7 @@ rule "PII.7.1: Redact contact information if applicant is found (non vertebrate
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.7.1", "Applicant information was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.7.1", "Applicant information was found", "personal_data_geolocation_article_39e3"));
end
rule "PII.7.2: Redact contact information if applicant is found (vertebrate study)"
@ -784,7 +783,7 @@ rule "PII.7.2: Redact contact information if applicant is found (vertebrate stud
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.7.2", "Applicant information was found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.7.2", "Applicant information was found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -821,7 +820,7 @@ rule "PII.8.1: Redact contact information if producer is found (non vertebrate s
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.8.1", "Producer was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.8.1", "Producer was found", "personal_data_geolocation_article_39e3"));
end
rule "PII.8.2: Redact contact information if producer is found (vertebrate study)"
@ -839,7 +838,7 @@ rule "PII.8.2: Redact contact information if producer is found (vertebrate study
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.8.2", "Producer was found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.8.2", "Producer was found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -868,7 +867,7 @@ rule "PII.10.0: Redact study director abbreviation (non vertebrate study)"
$section: Section(containsString("KATH") || containsString("BECH") || containsString("KML"))
then
entityCreationService.byRegexIgnoreCase("((KATH)|(BECH)|(KML)) ?(\\d{4})","PII", EntityType.ENTITY, 1, $section)
.forEach(entity -> entity.redact("PII.10.0", "Personal information found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.10.0", "Personal information found", "personal_data_geolocation_article_39e3"));
end
@ -878,7 +877,7 @@ rule "PII.11.0: Redact On behalf of Sequani Ltd.:"
$section: SuperSection(!hasTables(), containsString("On behalf of Sequani Ltd.: Name Title"))
then
entityCreationService.betweenStrings("On behalf of Sequani Ltd.: Name Title", "On behalf of", "PII", EntityType.ENTITY, $section)
.forEach(authorEntity -> authorEntity.redact("PII.11.0", "On behalf of Sequani Ltd.: Name Title was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("PII.11.0", "On behalf of Sequani Ltd.: Name Title was found", "personal_data_geolocation_article_39e3"));
end
@ -889,7 +888,7 @@ rule "PII.12.0: Expand PII entities with salutation prefix"
$entityToExpand: TextEntity(type() == "PII", anyMatch(textBefore, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*"))
then
entityCreationService.byPrefixExpansionRegex($entityToExpand, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*")
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.0", "Expanded PII with salutation prefix", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.0", "Expanded PII with salutation prefix", "personal_data_geolocation_article_39e3"));
end
rule "PII.12.1: Expand PII entities with salutation prefix"
@ -898,7 +897,7 @@ rule "PII.12.1: Expand PII entities with salutation prefix"
$entityToExpand: TextEntity(type() == "PII", anyMatch(textBefore, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*"))
then
entityCreationService.byPrefixExpansionRegex($entityToExpand, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*")
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.1", "Expanded PII with salutation prefix", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.1", "Expanded PII with salutation prefix", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -927,7 +926,7 @@ rule "ETC.2.1: Redact signatures (non vertebrate study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$signature: Image(imageType == ImageType.SIGNATURE)
then
$signature.redact("ETC.2.1", "Signature Found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$signature.redact("ETC.2.1", "Signature Found", "personal_data_geolocation_article_39e3");
end
rule "ETC.2.2: Redact signatures (vertebrate study)"
@ -935,7 +934,7 @@ rule "ETC.2.2: Redact signatures (vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$signature: Image(imageType == ImageType.SIGNATURE)
then
$signature.redact("ETC.2.2", "Signature Found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$signature.redact("ETC.2.2", "Signature Found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
rule "ETC.2.3: Redact signatures"
@ -967,7 +966,7 @@ rule "ETC.3.2: Redact logos (vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$logo: Image(imageType == ImageType.LOGO)
then
$logo.redact("ETC.3.2", "Logo Found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$logo.redact("ETC.3.2", "Logo Found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
rule "ETC.3.3: Redact logos"
@ -985,7 +984,6 @@ rule "ETC.5.0: Skip dossier_redaction entries if confidentiality is 'confidentia
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.skip("ETC.5.0", "Ignore dossier_redaction when confidential");
$dossierRedaction.getIntersectingNodes().forEach(node -> update(node));
end
rule "ETC.5.1: Remove dossier_redaction entries if confidentiality is not 'confidential'"
@ -995,7 +993,6 @@ rule "ETC.5.1: Remove dossier_redaction entries if confidentiality is not 'confi
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.remove("ETC.5.1", "Remove dossier_redaction when not confidential");
retract($dossierRedaction);
end
@ -1114,8 +1111,6 @@ rule "MAN.0.0: Apply manual resize redaction"
then
manualChangesApplicationService.resize($entityToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($entityToBeResized);
$entityToBeResized.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.0.1: Apply manual resize redaction"
@ -1127,8 +1122,6 @@ rule "MAN.0.1: Apply manual resize redaction"
then
manualChangesApplicationService.resizeImage($imageToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($imageToBeResized);
update($imageToBeResized.getParent());
end
@ -1139,10 +1132,8 @@ rule "MAN.1.0: Apply id removals that are valid and not in forced redactions to
$idRemoval: IdRemoval($id: annotationId, !removeFromDictionary, !removeFromAllDossiers)
$entityToBeRemoved: TextEntity(matchesAnnotationId($id))
then
$entityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($entityToBeRemoved);
$entityToBeRemoved.addManualChange($idRemoval);
retract($idRemoval);
$entityToBeRemoved.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to Image"
@ -1152,9 +1143,7 @@ rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to
$imageEntityToBeRemoved: Image($id == id)
then
$imageEntityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($imageEntityToBeRemoved);
retract($idRemoval);
update($imageEntityToBeRemoved.getParent());
end
@ -1165,9 +1154,7 @@ rule "MAN.2.0: Apply force redaction"
$force: ManualForceRedaction($id: annotationId)
$entityToForce: TextEntity(matchesAnnotationId($id))
then
$entityToForce.getManualOverwrite().addChange($force);
update($entityToForce);
$entityToForce.getIntersectingNodes().forEach(node -> update(node));
$entityToForce.addManualChange($force);
retract($force);
end
@ -1178,8 +1165,6 @@ rule "MAN.2.1: Apply force redaction to images"
$imageToForce: Image(id == $id)
then
$imageToForce.getManualOverwrite().addChange($force);
update($imageToForce);
update($imageToForce.getParent());
retract($force);
end
@ -1192,9 +1177,7 @@ rule "MAN.3.0: Apply entity recategorization"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() != $type)
then
$entityToBeRecategorized.getIntersectingNodes().forEach(node -> update(node));
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
update($entityToBeRecategorized);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -1205,7 +1188,7 @@ rule "MAN.3.1: Apply entity recategorization of same type"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() == $type)
then
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -1217,8 +1200,6 @@ rule "MAN.3.2: Apply image recategorization"
$imageToBeRecategorized: Image($id == id)
then
manualChangesApplicationService.recategorize($imageToBeRecategorized, $recategorization);
update($imageToBeRecategorized);
update($imageToBeRecategorized.getParent());
retract($recategorization);
end
@ -1239,7 +1220,6 @@ rule "MAN.4.0: Apply legal basis change"
$imageToBeRecategorized: Image($id == id)
then
$imageToBeRecategorized.getManualOverwrite().addChange($legalBasisChange);
update($imageToBeRecategorized)
retract($legalBasisChange)
end
@ -1249,8 +1229,7 @@ rule "MAN.4.1: Apply legal basis change"
$legalBasisChange: ManualLegalBasisChange($id: annotationId)
$entityToBeChanged: TextEntity(matchesAnnotationId($id))
then
$entityToBeChanged.getManualOverwrite().addChange($legalBasisChange);
update($entityToBeChanged)
$entityToBeChanged.addManualChange($legalBasisChange);
retract($legalBasisChange)
end
@ -1261,71 +1240,114 @@ rule "MAN.4.1: Apply legal basis change"
rule "X.0.0: Remove Entity contained by Entity of same type"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), !hasManualChanges())
not TextEntity(getTextRange().equals($larger.getTextRange()), type() == $type, entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY, !hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
!$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
not TextEntity(
getTextRange().equals($container.getTextRange()),
type() == $container.type(),
entityType == EntityType.DICTIONARY_REMOVAL,
engines contains Engine.DOSSIER_DICTIONARY,
!hasManualChanges()
)
then
$contained.remove("X.0.0", "remove Entity contained by Entity of same type");
retract($contained);
end
end
rule "X.0.1: Remove Entity contained by Entity of same type with manual changes"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
then
$contained.getIntersectingNodes().forEach(node -> update(node));
$contained.remove("X.0.1", "remove Entity contained by Entity of same type with manual changes");
retract($contained);
end
end
// Rule unit: X.2
rule "X.2.0: Remove Entity of type ENTITY when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.ENTITY), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.ENTITY,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
end
rule "X.2.1: Remove Entity of type HINT when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.HINT), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.HINT,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("X.2.1", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.1", "remove Entity of type HINT when contained by FALSE_POSITIVE");
end
// Rule unit: X.3
rule "X.3.0: Remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION"
rule "X.3.0: Remove RECOMMENDATION Contained by FALSE_RECOMMENDATION"
salience 64
when
$falseRecommendation: TextEntity($type: type(), entityType == EntityType.FALSE_RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($falseRecommendation), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
end
// Rule unit: X.4
rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY with same type"
salience 256
when
$entity: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(getTextRange().equals($entity.getTextRange()), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$entity.addEngines($recommendation.getEngines());
$recommendation.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
retract($recommendation);
$a.addEngines($b.getEngines());
$b.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
end
@ -1333,68 +1355,100 @@ rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY
rule "X.5.0: Remove Entity of type RECOMMENDATION when intersected by ENTITY"
salience 256
when
$entity: TextEntity((entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(intersects($entity), entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$intersection: Intersection(
$a: a,
$b: b,
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$recommendation.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
retract($recommendation);
$b.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
end
rule "X.5.1: Remove Entity of type RECOMMENDATION when contained by RECOMMENDATION"
salience 256
when
$entity: TextEntity($type: type(), entityType == EntityType.RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($entity), type() != $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$container.type() != $contained.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
end
// Rule unit: X.6
rule "X.6.0: Remove Entity of lower rank, when contained by entity of type ENTITY or HINT"
rule "X.6.0: Remove Lower Rank Entity Contained by ENTITY or HINT"
salience 32
when
$higherRank: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$lowerRank: TextEntity(containedBy($higherRank), type() != $type, dictionary.getDictionaryRank(type) < dictionary.getDictionaryRank($type), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
($container.entityType == EntityType.ENTITY || $container.entityType == EntityType.HINT),
$container.active(),
$contained.type() != $container.type(),
eval(dictionary.getDictionaryRank($contained.type()) < dictionary.getDictionaryRank($container.type())),
!$contained.hasManualChanges()
)
then
$lowerRank.getIntersectingNodes().forEach(node -> update(node));
$lowerRank.remove("X.6.0", "remove Entity of lower rank, when contained by entity of type ENTITY or HINT");
retract($lowerRank);
$contained.remove("X.6.0", "remove Entity of lower rank when contained by entity of type ENTITY or HINT");
end
rule "X.6.1: remove Entity, when contained in another entity of type ENTITY or HINT with larger text range"
rule "X.6.1: Remove Entity, when contained in another entity of type ENTITY or HINT with larger text range"
salience 32
when
$outer: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$inner: TextEntity(containedBy($outer), type() != $type, $outer.getTextRange().length > getTextRange().length(), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
($container.entityType == EntityType.ENTITY || $container.entityType == EntityType.HINT),
$container.active(),
$contained.type() != $container.type(),
eval($container.getTextRange().length() > $contained.getTextRange().length()),
!$contained.hasManualChanges()
)
then
$inner.getIntersectingNodes().forEach(node -> update(node));
$inner.remove("X.6.1", "remove Entity, when contained in another entity of type ENTITY or HINT with larger text range");
retract($inner);
end
$contained.remove("X.6.1", "remove Entity when contained in another entity of type ENTITY or HINT with larger text range");
end
// Rule unit: X.8
rule "X.8.0: Remove Entity when text range and type equals to imported Entity"
salience 257
when
$entity: TextEntity($type: type(), engines contains Engine.IMPORTED, active())
$other: TextEntity(getTextRange().equals($entity.getTextRange()), this != $entity, type() == $type, engines not contains Engine.IMPORTED)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$entity.addEngines($other.getEngines());
retract($other);
$b.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$a.addEngines($b.getEngines());
end
rule "X.8.1: Remove Entity when intersected by imported Entity"
salience 256
when
$entity: TextEntity(engines contains Engine.IMPORTED, active())
$other: TextEntity(intersects($entity), this != $entity, engines not contains Engine.IMPORTED)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.1", "remove Entity when intersected by imported Entity");
retract($other);
$b.remove("X.8.1", "remove Entity when intersected by imported Entity");
end
@ -1420,25 +1474,36 @@ rule "X.10.0: remove false positives of ai"
// Rule unit: X.11
rule "X.11.1: Remove non manual entity which intersects with a manual entity"
rule "X.11.1: Remove non-manual entity which intersects with a manual entity"
salience 64
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active())
$nonManualEntity: TextEntity(intersects($manualEntity), engines not contains Engine.MANUAL)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.MANUAL,
$a.active(),
$b.engines not contains Engine.MANUAL
)
then
$nonManualEntity.remove("X.11.1", "remove entity which intersects with a manual entity");
retract($nonManualEntity);
$b.remove("X.11.1", "remove entity which intersects with a manual entity");
end
rule "X.11.2: Remove non manual entity which are equal to manual entity"
rule "X.11.2: Remove non-manual entity which is equal to manual entity"
salience 70
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active(), $type: type())
$nonManualEntity: TextEntity(getTextRange().equals($manualEntity.getTextRange()), type() == $type, entityType == EntityType.ENTITY, !hasManualChanges(), engines not contains Engine.MANUAL)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.MANUAL,
$a.active(),
$b.entityType == EntityType.ENTITY,
!$b.hasManualChanges(),
$b.engines not contains Engine.MANUAL
)
then
$manualEntity.addEngines($nonManualEntity.getEngines());
$nonManualEntity.remove("X.11.2", "remove non manual entity which are equal to manual entity");
retract($nonManualEntity);
$a.addEngines($b.getEngines());
$b.remove("X.11.2", "remove non-manual entity which is equal to manual entity");
end
@ -1451,7 +1516,6 @@ rule "DICT.0.0: Remove Template Dictionary Entity when contained by Dossier Dict
$dictionaryRemoval: TextEntity($type: type(), entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY)
$entity: TextEntity(getTextRange().equals($dictionaryRemoval.getTextRange()), engines contains Engine.DICTIONARY, type() == $type, (entityType == EntityType.ENTITY || entityType == EntityType.HINT), !hasManualChanges())
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("DICT.0.0", "Remove Template Dictionary Entity when contained by Dossier Dictionary DICTIONARY_REMOVAL");
$entity.addEngine(Engine.DOSSIER_DICTIONARY);
end

View File

@ -18,8 +18,7 @@ import com.iqser.red.service.redaction.v1.server.model.document.TextRange;
import com.iqser.red.service.redaction.v1.server.model.document.entity.*;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType;
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.*;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Section;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.SuperSection;
@ -118,7 +117,7 @@ rule "CBI.0.1: Add CBI_author with \"et al.\" RegEx (non vertebrate study)"
then
entityCreationService.byRegex("\\b([A-ZÄÖÜ][^\\s\\.,]+( [A-ZÄÖÜ]{1,2}\\.?)?( ?[A-ZÄÖÜ]\\.?)?) et al\\.?", "CBI_author", EntityType.ENTITY, 1, $section)
.forEach(entity -> {
entity.redact("CBI.0.1", "Author found by \"et al\" regex", "Article 39(e)(3) of Regulation (EC) No 178/2002");
entity.redact("CBI.0.1", "Author found by \"et al\" regex", "personal_data_geolocation_article_39e3");
dictionary.recommendEverywhere(entity);
});
end
@ -131,7 +130,7 @@ rule "CBI.0.2: Add CBI_author with \"et al.\" RegEx (vertebrate study)"
then
entityCreationService.byRegex("\\b([A-ZÄÖÜ][^\\s\\.,]+( [A-ZÄÖÜ]{1,2}\\.?)?( ?[A-ZÄÖÜ]\\.?)?) et al\\.?", "CBI_author", EntityType.ENTITY, 1, $section)
.forEach(entity -> {
entity.redact("CBI.0.2", "Author found by \"et al\" regex", "Article 39(e)(2) of Regulation (EC) No 178/2002");
entity.redact("CBI.0.2", "Author found by \"et al\" regex", "vertebrate_study_personal_data_geolocation_article_39e2");
dictionary.recommendEverywhere(entity);
});
end
@ -141,7 +140,7 @@ rule "CBI.0.3: Redact CBI Authors (non vertebrate Study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$entity: TextEntity(type() == "CBI_author", dictionaryEntry)
then
$entity.redact("CBI.0.3", "Author found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$entity.redact("CBI.0.3", "Author found", "personal_data_geolocation_article_39e3");
end
rule "CBI.0.4: Redact CBI Authors (vertebrate Study)"
@ -149,7 +148,7 @@ rule "CBI.0.4: Redact CBI Authors (vertebrate Study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$entity: TextEntity(type() == "CBI_author", dictionaryEntry)
then
$entity.redact("CBI.0.4", "Author found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$entity.redact("CBI.0.4", "Author found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
@ -167,7 +166,7 @@ rule "CBI.1.1: Redact CBI Address (vertebrate Study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$entity: TextEntity(type() == "CBI_address", dictionaryEntry)
then
$entity.redact("CBI.1.1", "Address found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$entity.redact("CBI.1.1", "Address found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
@ -232,7 +231,7 @@ rule "CBI.9.0: Redact all cells with Header Author(s) as CBI_author (non vertebr
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.0", "Author(s) found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.0", "Author(s) found", "personal_data_geolocation_article_39e3"));
end
rule "CBI.9.1: Redact all cells with Header Author as CBI_author (non vertebrate study)"
@ -245,7 +244,7 @@ rule "CBI.9.1: Redact all cells with Header Author as CBI_author (non vertebrate
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.1", "Author found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.1", "Author found", "personal_data_geolocation_article_39e3"));
end
rule "CBI.9.2: Redact all cells with Header Author(s) as CBI_author (non vertebrate study)"
@ -286,7 +285,7 @@ rule "CBI.10.0: Redact all cells with Header Author(s) as CBI_author (vertebrate
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.10.0", "Author(s) found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.10.0", "Author(s) found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "CBI.10.1: Redact all cells with Header Author as CBI_author (vertebrate study)"
@ -299,7 +298,7 @@ rule "CBI.10.1: Redact all cells with Header Author as CBI_author (vertebrate st
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.10.1", "Author found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.10.1", "Author found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "CBI.10.2: Redact all cells with Header Author(s) as CBI_author (vertebrate study)"
@ -368,7 +367,7 @@ rule "CBI.12.1: Redact and recommend TableCell with header 'Author' or 'Author(s
then
entityCreationService.bySemanticNode($authorCell, "CBI_author", EntityType.ENTITY)
.ifPresent(authorEntity -> {
authorEntity.redact("CBI.12.1", "Redacted because it's row belongs to a vertebrate study", "Article 39(e)(3) of Regulation (EC) No 178/2002");
authorEntity.redact("CBI.12.1", "Redacted because it's row belongs to a vertebrate study", "personal_data_geolocation_article_39e3");
dictionary.addMultipleAuthorsAsRecommendation(authorEntity);
});
end
@ -386,7 +385,7 @@ rule "CBI.12.2: Redact and recommend TableCell with header 'Author' or 'Author(s
entityCreationService.bySemanticNode($authorCell, "CBI_author", EntityType.ENTITY)
.ifPresent(authorEntity -> {
authorEntity.redact("CBI.12.2", "Redacted because it's row belongs to a vertebrate study", "Article 39(e)(2) of Regulation (EC) No 178/2002");
authorEntity.redact("CBI.12.2", "Redacted because it's row belongs to a vertebrate study", "vertebrate_study_personal_data_geolocation_article_39e2");
dictionary.addMultipleAuthorsAsRecommendation(authorEntity);
});
@ -537,7 +536,6 @@ rule "CBI.13.0: Ignore CBI Address recommendations"
$entity: TextEntity(type() == "CBI_address", entityType == EntityType.RECOMMENDATION)
then
$entity.ignore("CBI.13.0", "Ignore CBI Address Recommendations");
retract($entity)
end
rule "CBI.13.1: Redacted because Section contains a vertebrate"
@ -765,7 +763,6 @@ rule "CBI.18.0: Expand CBI_author entities with firstname initials"
.ifPresent(expandedEntity -> {
expandedEntity.addMatchedRules($entityToExpand.getMatchedRuleList());
$entityToExpand.remove("CBI.18.0", "Expand CBI_author entities with firstname initials");
retract($entityToExpand);
});
end
@ -779,7 +776,6 @@ rule "CBI.19.0: Expand CBI_author entities with salutation prefix"
.ifPresent(expandedEntity -> {
expandedEntity.addMatchedRules($entityToExpand.getMatchedRuleList());
$entityToExpand.remove("CBI.19.0", "Expand CBI_author entities with salutation prefix");
retract($entityToExpand);
});
end
@ -818,7 +814,7 @@ rule "CBI.20.2: Redact between \"PERFORMING LABORATORY\" and \"LABORATORY PROJEC
then
entityCreationService.betweenStrings("PERFORMING LABORATORY:", "LABORATORY PROJECT ID:", "CBI_address", EntityType.ENTITY, $section)
.forEach(laboratoryEntity -> {
laboratoryEntity.redact("CBI.20.2", "PERFORMING LABORATORY was found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
laboratoryEntity.redact("CBI.20.2", "PERFORMING LABORATORY was found", "vertebrate_study_personal_data_geolocation_article_39e2");
dictionary.recommendEverywhere(laboratoryEntity);
});
end
@ -879,7 +875,7 @@ rule "CBI.21.2: Redact short Authors section (non vertebrate study)"
then
entityCreationService.byRegexIgnoreCase("(?<=author\\(?s\\)?\\s\\n?)([\\p{Lu}\\p{L} ]{5,15}(,|\\n)?){1,3}", "CBI_author", EntityType.ENTITY, $section)
.forEach(entity -> {
entity.redact("CBI.21.2", "AUTHOR(S) was found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
entity.redact("CBI.21.2", "AUTHOR(S) was found", "personal_data_geolocation_article_39e3");
});
end
@ -891,7 +887,7 @@ rule "CBI.21.3: Redact short Authors section (vertebrate study)"
then
entityCreationService.byRegexIgnoreCase("(?<=author\\(?s\\)?\\s\\n?)([\\p{Lu}\\p{L} ]{5,15}(,|\\n)?){1,3}", "CBI_author", EntityType.ENTITY, $section)
.forEach(entity -> {
entity.redact("CBI.21.3", "AUTHOR(S) was found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
entity.redact("CBI.21.3", "AUTHOR(S) was found", "vertebrate_study_personal_data_geolocation_article_39e2");
});
end
@ -915,7 +911,7 @@ rule "CBI.23.0: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (no
$document: Document(containsStringIgnoreCase("AUTHOR(S)"), containsAnyStringIgnoreCase("COMPLETION DATE", "STUDY COMPLETION DATE"))
then
entityCreationService.shortestBetweenAnyStringIgnoreCase(List.of("AUTHOR(S)", "AUTHOR(S):"), List.of("COMPLETION DATE", "COMPLETION DATE:", "STUDY COMPLETION DATE", "STUDY COMPLETION DATE:"), "CBI_author", EntityType.ENTITY, $document, 200)
.forEach(authorEntity -> authorEntity.redact("CBI.23.0", "AUTHOR(S) was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("CBI.23.0", "AUTHOR(S) was found", "personal_data_geolocation_article_39e3"));
end
rule "CBI.23.1: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (vertebrate study)"
@ -924,7 +920,7 @@ rule "CBI.23.1: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (ve
$document: Document(containsStringIgnoreCase("AUTHOR(S)"), containsAnyStringIgnoreCase("COMPLETION DATE", "STUDY COMPLETION DATE"))
then
entityCreationService.shortestBetweenAnyStringIgnoreCase(List.of("AUTHOR(S)", "AUTHOR(S):"), List.of("COMPLETION DATE", "COMPLETION DATE:", "STUDY COMPLETION DATE", "STUDY COMPLETION DATE:"), "CBI_author", EntityType.ENTITY, $document, 200)
.forEach(authorEntity -> authorEntity.redact("CBI.23.1", "AUTHOR(S) was found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("CBI.23.1", "AUTHOR(S) was found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -943,7 +939,7 @@ rule "PII.0.1: Redact all PII (non vertebrate study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$pii: TextEntity(type() == "PII", dictionaryEntry)
then
$pii.redact("PII.0.1", "Personal Information found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$pii.redact("PII.0.1", "Personal Information found", "personal_data_geolocation_article_39e3");
end
rule "PII.0.2: Redact all PII (vertebrate study)"
@ -951,7 +947,7 @@ rule "PII.0.2: Redact all PII (vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$pii: TextEntity(type() == "PII", dictionaryEntry)
then
$pii.redact("PII.0.2", "Personal Information found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$pii.redact("PII.0.2", "Personal Information found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
rule "PII.0.3: Redact all PII"
@ -977,7 +973,7 @@ rule "PII.1.1: Redact Emails by RegEx (Non vertebrate study)"
$section: Section(containsString("@"))
then
entityCreationService.byRegex("\\b([A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z\\-]{1,23}[A-Za-z])\\b", "PII", EntityType.ENTITY, 1, $section)
.forEach(emailEntity -> emailEntity.redact("PII.1.1", "Found by Email Regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(emailEntity -> emailEntity.redact("PII.1.1", "Found by Email Regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.1.2: Redact Emails by RegEx (vertebrate study)"
@ -986,7 +982,7 @@ rule "PII.1.2: Redact Emails by RegEx (vertebrate study)"
$section: Section(containsString("@"))
then
entityCreationService.byRegex("\\b([A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z\\-]{1,23}[A-Za-z])\\b", "PII", EntityType.ENTITY, 1, $section)
.forEach(emailEntity -> emailEntity.redact("PII.1.2", "Found by Email Regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(emailEntity -> emailEntity.redact("PII.1.2", "Found by Email Regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "PII.1.3: Redact typoed Emails with indicator"
@ -994,7 +990,7 @@ rule "PII.1.3: Redact typoed Emails with indicator"
$section: Section(containsString("@") || containsStringIgnoreCase("mail"))
then
entityCreationService.byRegexIgnoreCase("mail[:\\.\\s]{1,2}([\\w\\/\\-\\{\\(\\. ]{3,20}(@|a|f)\\s?[\\w\\/\\-\\{\\(\\. ]{3,20}(\\. \\w{2,4}\\b|\\.\\B|\\.\\w{1,4}\\b))", "PII", EntityType.ENTITY, 1, $section)
.forEach(emailEntity -> emailEntity.redact("PII.1.3", "Personal information found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(emailEntity -> emailEntity.redact("PII.1.3", "Personal information found", "personal_data_geolocation_article_39e3"));
end
rule "PII.1.4: Redact typoed Emails with indicator"
@ -1054,7 +1050,7 @@ rule "PII.2.1: Redact Phone and Fax by RegEx (non vertebrate study)"
containsString("Fer"))
then
entityCreationService.byRegexIgnoreCase("\\b(contact|telephone|phone|ph\\.|fax|tel|ter[^\\w]|mobile|fel[^\\w]|fer[^\\w])[a-zA-Z\\s]{0,10}[:.\\s]{0,3}([\\+\\d\\(][\\s\\d\\(\\)\\-\\/\\.]{4,100}\\d)\\b", "PII", EntityType.ENTITY, 2, $section)
.forEach(contactEntity -> contactEntity.redact("PII.2.1", "Found by Phone and Fax Regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.2.1", "Found by Phone and Fax Regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.2.2: Redact Phone and Fax by RegEx (vertebrate study)"
@ -1071,7 +1067,7 @@ rule "PII.2.2: Redact Phone and Fax by RegEx (vertebrate study)"
containsString("Fer"))
then
entityCreationService.byRegexIgnoreCase("\\b(contact|telephone|phone|ph\\.|fax|tel|ter[^\\w]|mobile|fel[^\\w]|fer[^\\w])[a-zA-Z\\s]{0,10}[:.\\s]{0,3}([\\+\\d\\(][\\s\\d\\(\\)\\-\\/\\.]{4,100}\\d)\\b", "PII", EntityType.ENTITY, 2, $section)
.forEach(contactEntity -> contactEntity.redact("PII.2.2", "Found by Phone and Fax Regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.2.2", "Found by Phone and Fax Regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "PII.2.3: Redact phone numbers without indicators"
@ -1079,7 +1075,7 @@ rule "PII.2.3: Redact phone numbers without indicators"
$section: Section(containsString("+"))
then
entityCreationService.byRegex("(\\+[\\dO]{1,2} )(\\([\\dO]{1,3}\\))?[\\d\\-O ]{8,15}", "PII", EntityType.ENTITY, $section)
.forEach(entity -> entity.redact("PII.2.3", "Personal information found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.2.3", "Personal information found", "personal_data_geolocation_article_39e3"));
end
@ -1098,7 +1094,7 @@ rule "PII.3.1: Redact telephone numbers by RegEx (Non vertebrate study)"
$section: Section(!hasTables(), matchesRegex("[+]\\d{1,}"))
then
entityCreationService.byRegex("((([+]\\d{1,3} (\\d{7,12})\\b)|([+]\\d{1,3}(\\d{3,12})\\b|[+]\\d{1,3}([ -]\\(?\\d{1,6}\\)?){2,4})|[+]\\d{1,3} ?((\\d{2,6}\\)?)([ -]\\d{2,6}){1,4}))(-\\d{1,3})?\\b)", "PII", EntityType.ENTITY, 1, $section)
.forEach(entity -> entity.redact("PII.3.1", "Telephone number found by regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.3.1", "Telephone number found by regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.3.2: Redact telephone numbers by RegEx (vertebrate study)"
@ -1107,7 +1103,7 @@ rule "PII.3.2: Redact telephone numbers by RegEx (vertebrate study)"
$section: Section(!hasTables(), matchesRegex("[+]\\d{1,}"))
then
entityCreationService.byRegex("((([+]\\d{1,3} (\\d{7,12})\\b)|([+]\\d{1,3}(\\d{3,12})\\b|[+]\\d{1,3}([ -]\\(?\\d{1,6}\\)?){2,4})|[+]\\d{1,3} ?((\\d{2,6}\\)?)([ -]\\d{2,6}){1,4}))(-\\d{1,3})?\\b)", "PII", EntityType.ENTITY, 1, $section)
.forEach(entity -> entity.redact("PII.3.2", "Telephone number found by regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.3.2", "Telephone number found by regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "PII.3.3: Redact telephone numbers by RegEx"
@ -1124,7 +1120,7 @@ rule "PII.3.4: Redact telephone numbers by RegEx (Non vertebrate study)"
$rowCell: TableCell(matchesRegex("[+]\\d{1,}"))
then
entityCreationService.byRegex("((([+]\\d{1,3} (\\d{7,12})\\b)|([+]\\d{1,3}(\\d{3,12})\\b|[+]\\d{1,3}([ -]\\(?\\d{1,6}\\)?){2,4})|[+]\\d{1,3} ?((\\d{2,6}\\)?)([ -]\\d{2,6}){1,4}))(-\\d{1,3})?\\b)", "PII", EntityType.ENTITY, 1, $rowCell)
.forEach(entity -> entity.redact("PII.3.4", "Telephone number found by regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.3.4", "Telephone number found by regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.3.5: Redact telephone numbers by RegEx (vertebrate study)"
@ -1133,7 +1129,7 @@ rule "PII.3.5: Redact telephone numbers by RegEx (vertebrate study)"
$rowCell: TableCell(matchesRegex("[+]\\d{1,}"))
then
entityCreationService.byRegex("((([+]\\d{1,3} (\\d{7,12})\\b)|([+]\\d{1,3}(\\d{3,12})\\b|[+]\\d{1,3}([ -]\\(?\\d{1,6}\\)?){2,4})|[+]\\d{1,3} ?((\\d{2,6}\\)?)([ -]\\d{2,6}){1,4}))(-\\d{1,3})?\\b)", "PII", EntityType.ENTITY, 1, $rowCell)
.forEach(entity -> entity.redact("PII.3.5", "Telephone number found by regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.3.5", "Telephone number found by regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -1214,7 +1210,7 @@ rule "PII.5.1: Redact line after contact information keywords reduced (non verte
$section: Section(containsString($contactKeyword))
then
entityCreationService.lineAfterString($contactKeyword, "PII", EntityType.ENTITY, $section)
.forEach(contactEntity -> contactEntity.redact("PII.5.1", "Found after \"" + $contactKeyword + "\" contact keyword", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.5.1", "Found after \"" + $contactKeyword + "\" contact keyword", "personal_data_geolocation_article_39e3"));
end
rule "PII.5.2: Redact line after contact information keywords reduced (Vertebrate study)"
@ -1227,7 +1223,7 @@ rule "PII.5.2: Redact line after contact information keywords reduced (Vertebrat
$section: Section(containsString($contactKeyword))
then
entityCreationService.lineAfterString($contactKeyword, "PII", EntityType.ENTITY, $section)
.forEach(contactEntity -> contactEntity.redact("PII.5.2", "Found after \"" + $contactKeyword + "\" contact keyword", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.5.2", "Found after \"" + $contactKeyword + "\" contact keyword", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -1252,7 +1248,7 @@ rule "PII.6.1: Redact line between contact keywords (non vertebrate study)"
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
)
.forEach(contactEntity -> contactEntity.redact("PII.6.1", "Found between contact keywords", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.6.1", "Found between contact keywords", "personal_data_geolocation_article_39e3"));
end
rule "PII.6.2: Redact line between contact keywords (vertebrate study)"
@ -1264,7 +1260,7 @@ rule "PII.6.2: Redact line between contact keywords (vertebrate study)"
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
)
.forEach(contactEntity -> contactEntity.redact("PII.6.2", "Found between contact keywords", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.6.2", "Found between contact keywords", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "PII.6.3: Redact line between contact keywords (non vertebrate study)"
@ -1308,7 +1304,7 @@ rule "PII.7.1: Redact contact information if applicant is found (non vertebrate
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.7.1", "Applicant information was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.7.1", "Applicant information was found", "personal_data_geolocation_article_39e3"));
end
rule "PII.7.2: Redact contact information if applicant is found (vertebrate study)"
@ -1326,7 +1322,7 @@ rule "PII.7.2: Redact contact information if applicant is found (vertebrate stud
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.7.2", "Applicant information was found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.7.2", "Applicant information was found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -1363,7 +1359,7 @@ rule "PII.8.1: Redact contact information if producer is found (non vertebrate s
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.8.1", "Producer was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.8.1", "Producer was found", "personal_data_geolocation_article_39e3"));
end
rule "PII.8.2: Redact contact information if producer is found (vertebrate study)"
@ -1381,7 +1377,7 @@ rule "PII.8.2: Redact contact information if producer is found (vertebrate study
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.8.2", "Producer was found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.8.2", "Producer was found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -1400,7 +1396,7 @@ rule "PII.9.1: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (non
$document: Document(containsStringIgnoreCase("AUTHOR(S)"), containsAnyStringIgnoreCase("COMPLETION DATE", "STUDY COMPLETION DATE"))
then
entityCreationService.shortestBetweenAnyStringIgnoreCase(List.of("AUTHOR(S)", "AUTHOR(S):"), List.of("COMPLETION DATE", "COMPLETION DATE:", "STUDY COMPLETION DATE", "STUDY COMPLETION DATE:"), "PII", EntityType.ENTITY, $document)
.forEach(authorEntity -> authorEntity.redact("PII.9.1", "AUTHOR(S) was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("PII.9.1", "AUTHOR(S) was found", "personal_data_geolocation_article_39e3"));
end
rule "PII.9.2: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (vertebrate study)"
@ -1409,7 +1405,7 @@ rule "PII.9.2: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (ver
$document: Document(containsStringIgnoreCase("AUTHOR(S)"), containsAnyStringIgnoreCase("COMPLETION DATE", "STUDY COMPLETION DATE"))
then
entityCreationService.shortestBetweenAnyStringIgnoreCase(List.of("AUTHOR(S)", "AUTHOR(S):"), List.of("COMPLETION DATE", "COMPLETION DATE:", "STUDY COMPLETION DATE", "STUDY COMPLETION DATE:"), "PII", EntityType.ENTITY, $document)
.forEach(authorEntity -> authorEntity.redact("PII.9.2", "AUTHOR(S) was found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("PII.9.2", "AUTHOR(S) was found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "PII.9.3: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\""
@ -1428,7 +1424,7 @@ rule "PII.10.0: Redact study director abbreviation (non vertebrate study)"
$section: Section(containsString("KATH") || containsString("BECH") || containsString("KML"))
then
entityCreationService.byRegexIgnoreCase("((KATH)|(BECH)|(KML)) ?(\\d{4})","PII", EntityType.ENTITY, 1, $section)
.forEach(entity -> entity.redact("PII.10.0", "Personal information found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.10.0", "Personal information found", "personal_data_geolocation_article_39e3"));
end
rule "PII.10.1: Redact study director abbreviation (vertebrate study)"
@ -1437,7 +1433,7 @@ rule "PII.10.1: Redact study director abbreviation (vertebrate study)"
$section: Section(containsString("KATH") || containsString("BECH") || containsString("KML"))
then
entityCreationService.byRegexIgnoreCase("((KATH)|(BECH)|(KML)) ?(\\d{4})","PII", EntityType.ENTITY, 1, $section)
.forEach(entity -> entity.redact("PII.10.1", "Personal information found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.10.1", "Personal information found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -1447,7 +1443,7 @@ rule "PII.11.0: Redact On behalf of Sequani Ltd.:"
$section: SuperSection(!hasTables(), containsString("On behalf of Sequani Ltd.: Name Title"))
then
entityCreationService.betweenStrings("On behalf of Sequani Ltd.: Name Title", "On behalf of", "PII", EntityType.ENTITY, $section)
.forEach(authorEntity -> authorEntity.redact("PII.11.0", "On behalf of Sequani Ltd.: Name Title was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("PII.11.0", "On behalf of Sequani Ltd.: Name Title was found", "personal_data_geolocation_article_39e3"));
end
@ -1458,7 +1454,7 @@ rule "PII.12.0: Expand PII entities with salutation prefix"
$entityToExpand: TextEntity(type() == "PII", anyMatch(textBefore, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*"))
then
entityCreationService.byPrefixExpansionRegex($entityToExpand, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*")
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.0", "Expanded PII with salutation prefix", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.0", "Expanded PII with salutation prefix", "personal_data_geolocation_article_39e3"));
end
rule "PII.12.1: Expand PII entities with salutation prefix"
@ -1467,7 +1463,7 @@ rule "PII.12.1: Expand PII entities with salutation prefix"
$entityToExpand: TextEntity(type() == "PII", anyMatch(textBefore, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*"))
then
entityCreationService.byPrefixExpansionRegex($entityToExpand, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*")
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.1", "Expanded PII with salutation prefix", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.1", "Expanded PII with salutation prefix", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -1525,7 +1521,7 @@ rule "ETC.2.1: Redact signatures (non vertebrate study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$signature: Image(imageType == ImageType.SIGNATURE)
then
$signature.redact("ETC.2.1", "Signature Found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$signature.redact("ETC.2.1", "Signature Found", "personal_data_geolocation_article_39e3");
end
rule "ETC.2.2: Redact signatures (vertebrate study)"
@ -1533,7 +1529,7 @@ rule "ETC.2.2: Redact signatures (vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$signature: Image(imageType == ImageType.SIGNATURE)
then
$signature.redact("ETC.2.2", "Signature Found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$signature.redact("ETC.2.2", "Signature Found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
rule "ETC.2.3: Redact signatures"
@ -1565,7 +1561,7 @@ rule "ETC.3.2: Redact logos (vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$logo: Image(imageType == ImageType.LOGO)
then
$logo.redact("ETC.3.2", "Logo Found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$logo.redact("ETC.3.2", "Logo Found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
rule "ETC.3.3: Redact logos"
@ -1588,21 +1584,21 @@ rule "ETC.4.0: Redact dossier dictionary entries"
when
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.redact("ETC.4.0", "Specification of impurity found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$dossierRedaction.redact("ETC.4.0", "Specification of impurity found", "personal_data_geolocation_article_39e3");
end
rule "ETC.4.1: Redact dossier dictionary entries"
when
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.redact("ETC.4.1", "Dossier Redaction found", "Article 39(1)(2) of Regulation (EC) No 178/2002");
$dossierRedaction.redact("ETC.4.1", "Dossier Redaction found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
rule "ETC.4.2: Redact dossier dictionary entries"
when
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.redact("ETC.4.2", "Dossier redaction found", "Article 63(2)(a) of Regulation (EC) No 1107/2009 (making reference to Article 39 of Regulation EC No 178/2002)");
$dossierRedaction.redact("ETC.4.2", "Dossier redaction found", "links_producer_applicant");
end
@ -1613,7 +1609,6 @@ rule "ETC.5.0: Skip dossier_redaction entries if confidentiality is 'confidentia
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.skip("ETC.5.0", "Ignore dossier_redaction when confidential");
$dossierRedaction.getIntersectingNodes().forEach(node -> update(node));
end
rule "ETC.5.1: Remove dossier_redaction entries if confidentiality is not 'confidential'"
@ -1623,7 +1618,6 @@ rule "ETC.5.1: Remove dossier_redaction entries if confidentiality is not 'confi
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.remove("ETC.5.1", "Remove dossier_redaction when not confidential");
retract($dossierRedaction);
end
@ -1658,7 +1652,7 @@ rule "ETC.8.0: Redact formulas (vertebrate study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$logo: Image(imageType == ImageType.FORMULA)
then
$logo.redact("ETC.8.0", "Logo Found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$logo.redact("ETC.8.0", "Logo Found", "personal_data_geolocation_article_39e3");
end
rule "ETC.8.1: Redact formulas (non vertebrate study)"
@ -1666,7 +1660,7 @@ rule "ETC.8.1: Redact formulas (non vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$logo: Image(imageType == ImageType.FORMULA)
then
$logo.redact("ETC.8.1", "Logo Found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$logo.redact("ETC.8.1", "Logo Found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
@ -1705,7 +1699,7 @@ rule "ETC.11.0: Recommend first line in table cell with name and address of owne
$tableCell: TableCell(col == $header.col, row == 2) from $table.streamTableCells().toList()
then
entityCreationService.bySemanticNode($tableCell, "PII", EntityType.RECOMMENDATION)
.ifPresent(redactionEntity -> redactionEntity.redact("ETC.11.0", "Trial Site owner and address found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.ifPresent(redactionEntity -> redactionEntity.redact("ETC.11.0", "Trial Site owner and address found", "personal_data_geolocation_article_39e3"));
end
@ -1715,7 +1709,7 @@ rule "ETC.12.0: Redact dossier_redaction (Non vertebrate study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.redact("ETC.12.0", "Dossier dictionary entry found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$dossierRedaction.redact("ETC.12.0", "Dossier dictionary entry found", "personal_data_geolocation_article_39e3");
end
rule "ETC.12.1: Redact dossier_redaction (Vertebrate study)"
@ -1723,7 +1717,7 @@ rule "ETC.12.1: Redact dossier_redaction (Vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.redact("ETC.12.1", "Dossier dictionary entry found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$dossierRedaction.redact("ETC.12.1", "Dossier dictionary entry found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
rule "ETC.12.2: Skip dossier_redaction (Non vertebrate study)"
@ -1881,8 +1875,6 @@ rule "MAN.0.0: Apply manual resize redaction"
then
manualChangesApplicationService.resize($entityToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($entityToBeResized);
$entityToBeResized.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.0.1: Apply manual resize redaction"
@ -1894,8 +1886,6 @@ rule "MAN.0.1: Apply manual resize redaction"
then
manualChangesApplicationService.resizeImage($imageToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($imageToBeResized);
update($imageToBeResized.getParent());
end
@ -1906,10 +1896,8 @@ rule "MAN.1.0: Apply id removals that are valid and not in forced redactions to
$idRemoval: IdRemoval($id: annotationId, !removeFromDictionary, !removeFromAllDossiers)
$entityToBeRemoved: TextEntity(matchesAnnotationId($id))
then
$entityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($entityToBeRemoved);
$entityToBeRemoved.addManualChange($idRemoval);
retract($idRemoval);
$entityToBeRemoved.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to Image"
@ -1919,9 +1907,7 @@ rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to
$imageEntityToBeRemoved: Image($id == id)
then
$imageEntityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($imageEntityToBeRemoved);
retract($idRemoval);
update($imageEntityToBeRemoved.getParent());
end
@ -1932,9 +1918,7 @@ rule "MAN.2.0: Apply force redaction"
$force: ManualForceRedaction($id: annotationId)
$entityToForce: TextEntity(matchesAnnotationId($id))
then
$entityToForce.getManualOverwrite().addChange($force);
update($entityToForce);
$entityToForce.getIntersectingNodes().forEach(node -> update(node));
$entityToForce.addManualChange($force);
retract($force);
end
@ -1945,8 +1929,6 @@ rule "MAN.2.1: Apply force redaction to images"
$imageToForce: Image(id == $id)
then
$imageToForce.getManualOverwrite().addChange($force);
update($imageToForce);
update($imageToForce.getParent());
retract($force);
end
@ -1959,9 +1941,7 @@ rule "MAN.3.0: Apply entity recategorization"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() != $type)
then
$entityToBeRecategorized.getIntersectingNodes().forEach(node -> update(node));
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
update($entityToBeRecategorized);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -1972,7 +1952,7 @@ rule "MAN.3.1: Apply entity recategorization of same type"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() == $type)
then
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -1984,8 +1964,6 @@ rule "MAN.3.2: Apply image recategorization"
$imageToBeRecategorized: Image($id == id)
then
manualChangesApplicationService.recategorize($imageToBeRecategorized, $recategorization);
update($imageToBeRecategorized);
update($imageToBeRecategorized.getParent());
retract($recategorization);
end
@ -2006,7 +1984,6 @@ rule "MAN.4.0: Apply legal basis change"
$imageToBeRecategorized: Image($id == id)
then
$imageToBeRecategorized.getManualOverwrite().addChange($legalBasisChange);
update($imageToBeRecategorized)
retract($legalBasisChange)
end
@ -2016,8 +1993,7 @@ rule "MAN.4.1: Apply legal basis change"
$legalBasisChange: ManualLegalBasisChange($id: annotationId)
$entityToBeChanged: TextEntity(matchesAnnotationId($id))
then
$entityToBeChanged.getManualOverwrite().addChange($legalBasisChange);
update($entityToBeChanged)
$entityToBeChanged.addManualChange($legalBasisChange);
retract($legalBasisChange)
end
@ -2028,71 +2004,114 @@ rule "MAN.4.1: Apply legal basis change"
rule "X.0.0: Remove Entity contained by Entity of same type"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), !hasManualChanges())
not TextEntity(getTextRange().equals($larger.getTextRange()), type() == $type, entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY, !hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
!$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
not TextEntity(
getTextRange().equals($container.getTextRange()),
type() == $container.type(),
entityType == EntityType.DICTIONARY_REMOVAL,
engines contains Engine.DOSSIER_DICTIONARY,
!hasManualChanges()
)
then
$contained.remove("X.0.0", "remove Entity contained by Entity of same type");
retract($contained);
end
end
rule "X.0.1: Remove Entity contained by Entity of same type with manual changes"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
then
$contained.getIntersectingNodes().forEach(node -> update(node));
$contained.remove("X.0.1", "remove Entity contained by Entity of same type with manual changes");
retract($contained);
end
end
// Rule unit: X.2
rule "X.2.0: Remove Entity of type ENTITY when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.ENTITY), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.ENTITY,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
end
rule "X.2.1: Remove Entity of type HINT when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.HINT), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.HINT,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("X.2.1", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.1", "remove Entity of type HINT when contained by FALSE_POSITIVE");
end
// Rule unit: X.3
rule "X.3.0: Remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION"
rule "X.3.0: Remove RECOMMENDATION Contained by FALSE_RECOMMENDATION"
salience 64
when
$falseRecommendation: TextEntity($type: type(), entityType == EntityType.FALSE_RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($falseRecommendation), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
end
// Rule unit: X.4
rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY with same type"
salience 256
when
$entity: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(getTextRange().equals($entity.getTextRange()), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$entity.addEngines($recommendation.getEngines());
$recommendation.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
retract($recommendation);
$a.addEngines($b.getEngines());
$b.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
end
@ -2100,68 +2119,100 @@ rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY
rule "X.5.0: Remove Entity of type RECOMMENDATION when intersected by ENTITY"
salience 256
when
$entity: TextEntity((entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(intersects($entity), entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$intersection: Intersection(
$a: a,
$b: b,
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$recommendation.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
retract($recommendation);
$b.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
end
rule "X.5.1: Remove Entity of type RECOMMENDATION when contained by RECOMMENDATION"
salience 256
when
$entity: TextEntity($type: type(), entityType == EntityType.RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($entity), type() != $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$container.type() != $contained.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
end
// Rule unit: X.6
rule "X.6.0: Remove Entity of lower rank, when contained by entity of type ENTITY or HINT"
rule "X.6.0: Remove Lower Rank Entity Contained by ENTITY or HINT"
salience 32
when
$higherRank: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$lowerRank: TextEntity(containedBy($higherRank), type() != $type, dictionary.getDictionaryRank(type) < dictionary.getDictionaryRank($type), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
($container.entityType == EntityType.ENTITY || $container.entityType == EntityType.HINT),
$container.active(),
$contained.type() != $container.type(),
eval(dictionary.getDictionaryRank($contained.type()) < dictionary.getDictionaryRank($container.type())),
!$contained.hasManualChanges()
)
then
$lowerRank.getIntersectingNodes().forEach(node -> update(node));
$lowerRank.remove("X.6.0", "remove Entity of lower rank, when contained by entity of type ENTITY or HINT");
retract($lowerRank);
$contained.remove("X.6.0", "remove Entity of lower rank when contained by entity of type ENTITY or HINT");
end
rule "X.6.1: remove Entity, when contained in another entity of type ENTITY or HINT with larger text range"
rule "X.6.1: Remove Entity, when contained in another entity of type ENTITY or HINT with larger text range"
salience 32
when
$outer: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$inner: TextEntity(containedBy($outer), type() != $type, $outer.getTextRange().length > getTextRange().length(), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
($container.entityType == EntityType.ENTITY || $container.entityType == EntityType.HINT),
$container.active(),
$contained.type() != $container.type(),
eval($container.getTextRange().length() > $contained.getTextRange().length()),
!$contained.hasManualChanges()
)
then
$inner.getIntersectingNodes().forEach(node -> update(node));
$inner.remove("X.6.1", "remove Entity, when contained in another entity of type ENTITY or HINT with larger text range");
retract($inner);
end
$contained.remove("X.6.1", "remove Entity when contained in another entity of type ENTITY or HINT with larger text range");
end
// Rule unit: X.8
rule "X.8.0: Remove Entity when text range and type equals to imported Entity"
salience 257
when
$entity: TextEntity($type: type(), engines contains Engine.IMPORTED, active())
$other: TextEntity(getTextRange().equals($entity.getTextRange()), this != $entity, type() == $type, engines not contains Engine.IMPORTED)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$entity.addEngines($other.getEngines());
retract($other);
$b.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$a.addEngines($b.getEngines());
end
rule "X.8.1: Remove Entity when intersected by imported Entity"
salience 256
when
$entity: TextEntity(engines contains Engine.IMPORTED, active())
$other: TextEntity(intersects($entity), this != $entity, engines not contains Engine.IMPORTED)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.1", "remove Entity when intersected by imported Entity");
retract($other);
$b.remove("X.8.1", "remove Entity when intersected by imported Entity");
end
@ -2190,32 +2241,48 @@ rule "X.10.0: remove false positives of ai"
rule "X.11.0: Remove dictionary entity which intersects with a manual entity"
salience 64
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active())
$dictionaryEntity: TextEntity(intersects($manualEntity), dictionaryEntry, engines not contains Engine.MANUAL)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.MANUAL,
$a.active(),
$b.dictionaryEntry,
$b.engines not contains Engine.MANUAL
)
then
$dictionaryEntity.remove("X.11.0", "remove dictionary entity which intersects with a manual entity");
retract($dictionaryEntity);
$b.remove("X.11.0", "remove dictionary entity which intersects with a manual entity");
end
rule "X.11.1: Remove non manual entity which intersects with a manual entity"
rule "X.11.1: Remove non-manual entity which intersects with a manual entity"
salience 64
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active())
$nonManualEntity: TextEntity(intersects($manualEntity), engines not contains Engine.MANUAL)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.MANUAL,
$a.active(),
$b.engines not contains Engine.MANUAL
)
then
$nonManualEntity.remove("X.11.1", "remove entity which intersects with a manual entity");
retract($nonManualEntity);
$b.remove("X.11.1", "remove entity which intersects with a manual entity");
end
rule "X.11.2: Remove non manual entity which are equal to manual entity"
rule "X.11.2: Remove non-manual entity which is equal to manual entity"
salience 70
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active(), $type: type())
$nonManualEntity: TextEntity(getTextRange().equals($manualEntity.getTextRange()), type() == $type, entityType == EntityType.ENTITY, !hasManualChanges(), engines not contains Engine.MANUAL)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.MANUAL,
$a.active(),
$b.entityType == EntityType.ENTITY,
!$b.hasManualChanges(),
$b.engines not contains Engine.MANUAL
)
then
$manualEntity.addEngines($nonManualEntity.getEngines());
$nonManualEntity.remove("X.11.2", "remove non manual entity which are equal to manual entity");
retract($nonManualEntity);
$a.addEngines($b.getEngines());
$b.remove("X.11.2", "remove non-manual entity which is equal to manual entity");
end
@ -2228,7 +2295,6 @@ rule "DICT.0.0: Remove Template Dictionary Entity when contained by Dossier Dict
$dictionaryRemoval: TextEntity($type: type(), entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY)
$entity: TextEntity(getTextRange().equals($dictionaryRemoval.getTextRange()), engines contains Engine.DICTIONARY, type() == $type, (entityType == EntityType.ENTITY || entityType == EntityType.HINT), !hasManualChanges())
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("DICT.0.0", "Remove Template Dictionary Entity when contained by Dossier Dictionary DICTIONARY_REMOVAL");
$entity.addEngine(Engine.DOSSIER_DICTIONARY);
end

View File

@ -18,8 +18,7 @@ import com.iqser.red.service.redaction.v1.server.model.document.TextRange;
import com.iqser.red.service.redaction.v1.server.model.document.entity.*;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType;
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.*;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Section;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Table;
@ -1248,8 +1247,6 @@ rule "MAN.0.0: Apply manual resize redaction"
then
manualChangesApplicationService.resize($entityToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($entityToBeResized);
$entityToBeResized.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.0.1: Apply manual resize redaction"
@ -1261,8 +1258,6 @@ rule "MAN.0.1: Apply manual resize redaction"
then
manualChangesApplicationService.resizeImage($imageToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($imageToBeResized);
update($imageToBeResized.getParent());
end
@ -1273,10 +1268,8 @@ rule "MAN.1.0: Apply id removals that are valid and not in forced redactions to
$idRemoval: IdRemoval($id: annotationId, !removeFromDictionary, !removeFromAllDossiers)
$entityToBeRemoved: TextEntity(matchesAnnotationId($id))
then
$entityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($entityToBeRemoved);
$entityToBeRemoved.addManualChange($idRemoval);
retract($idRemoval);
$entityToBeRemoved.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to Image"
@ -1286,9 +1279,7 @@ rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to
$imageEntityToBeRemoved: Image($id == id)
then
$imageEntityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($imageEntityToBeRemoved);
retract($idRemoval);
update($imageEntityToBeRemoved.getParent());
end
@ -1299,9 +1290,7 @@ rule "MAN.2.0: Apply force redaction"
$force: ManualForceRedaction($id: annotationId)
$entityToForce: TextEntity(matchesAnnotationId($id))
then
$entityToForce.getManualOverwrite().addChange($force);
update($entityToForce);
$entityToForce.getIntersectingNodes().forEach(node -> update(node));
$entityToForce.addManualChange($force);
retract($force);
end
@ -1312,8 +1301,6 @@ rule "MAN.2.1: Apply force redaction to images"
$imageToForce: Image(id == $id)
then
$imageToForce.getManualOverwrite().addChange($force);
update($imageToForce);
update($imageToForce.getParent());
retract($force);
end
@ -1326,9 +1313,7 @@ rule "MAN.3.0: Apply entity recategorization"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() != $type)
then
$entityToBeRecategorized.getIntersectingNodes().forEach(node -> update(node));
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
update($entityToBeRecategorized);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -1339,7 +1324,7 @@ rule "MAN.3.1: Apply entity recategorization of same type"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() == $type)
then
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -1351,8 +1336,6 @@ rule "MAN.3.2: Apply image recategorization"
$imageToBeRecategorized: Image($id == id)
then
manualChangesApplicationService.recategorize($imageToBeRecategorized, $recategorization);
update($imageToBeRecategorized);
update($imageToBeRecategorized.getParent());
retract($recategorization);
end
@ -1373,7 +1356,6 @@ rule "MAN.4.0: Apply legal basis change"
$imageToBeRecategorized: Image($id == id)
then
$imageToBeRecategorized.getManualOverwrite().addChange($legalBasisChange);
update($imageToBeRecategorized)
retract($legalBasisChange)
end
@ -1383,8 +1365,7 @@ rule "MAN.4.1: Apply legal basis change"
$legalBasisChange: ManualLegalBasisChange($id: annotationId)
$entityToBeChanged: TextEntity(matchesAnnotationId($id))
then
$entityToBeChanged.getManualOverwrite().addChange($legalBasisChange);
update($entityToBeChanged)
$entityToBeChanged.addManualChange($legalBasisChange);
retract($legalBasisChange)
end
@ -1395,71 +1376,114 @@ rule "MAN.4.1: Apply legal basis change"
rule "X.0.0: Remove Entity contained by Entity of same type"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), !hasManualChanges())
not TextEntity(getTextRange().equals($larger.getTextRange()), type() == $type, entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY, !hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
!$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
not TextEntity(
getTextRange().equals($container.getTextRange()),
type() == $container.type(),
entityType == EntityType.DICTIONARY_REMOVAL,
engines contains Engine.DOSSIER_DICTIONARY,
!hasManualChanges()
)
then
$contained.remove("X.0.0", "remove Entity contained by Entity of same type");
retract($contained);
end
end
rule "X.0.1: Remove Entity contained by Entity of same type with manual changes"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
then
$contained.getIntersectingNodes().forEach(node -> update(node));
$contained.remove("X.0.1", "remove Entity contained by Entity of same type with manual changes");
retract($contained);
end
end
// Rule unit: X.2
rule "X.2.0: Remove Entity of type ENTITY when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.ENTITY), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.ENTITY,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
end
rule "X.2.1: Remove Entity of type HINT when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.HINT), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.HINT,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("X.2.1", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.1", "remove Entity of type HINT when contained by FALSE_POSITIVE");
end
// Rule unit: X.3
rule "X.3.0: Remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION"
rule "X.3.0: Remove RECOMMENDATION Contained by FALSE_RECOMMENDATION"
salience 64
when
$falseRecommendation: TextEntity($type: type(), entityType == EntityType.FALSE_RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($falseRecommendation), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
end
// Rule unit: X.4
rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY with same type"
salience 256
when
$entity: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(getTextRange().equals($entity.getTextRange()), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$entity.addEngines($recommendation.getEngines());
$recommendation.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
retract($recommendation);
$a.addEngines($b.getEngines());
$b.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
end
@ -1467,22 +1491,33 @@ rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY
rule "X.5.0: Remove Entity of type RECOMMENDATION when intersected by ENTITY"
salience 256
when
$entity: TextEntity((entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(intersects($entity), entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$intersection: Intersection(
$a: a,
$b: b,
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$recommendation.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
retract($recommendation);
$b.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
end
rule "X.5.1: Remove Entity of type RECOMMENDATION when contained by RECOMMENDATION"
salience 256
when
$entity: TextEntity($type: type(), entityType == EntityType.RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($entity), type() != $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$container.type() != $contained.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
end
// Rule unit: X.7
@ -1500,22 +1535,33 @@ rule "X.7.0: Remove all images"
rule "X.8.0: Remove Entity when text range and type equals to imported Entity"
salience 257
when
$entity: TextEntity($type: type(), engines contains Engine.IMPORTED, active())
$other: TextEntity(getTextRange().equals($entity.getTextRange()), this != $entity, type() == $type, engines not contains Engine.IMPORTED)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$entity.addEngines($other.getEngines());
retract($other);
$b.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$a.addEngines($b.getEngines());
end
rule "X.8.1: Remove Entity when intersected by imported Entity"
salience 256
when
$entity: TextEntity(engines contains Engine.IMPORTED, active())
$other: TextEntity(intersects($entity), this != $entity, engines not contains Engine.IMPORTED)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.1", "remove Entity when intersected by imported Entity");
retract($other);
$b.remove("X.8.1", "remove Entity when intersected by imported Entity");
end
@ -1544,11 +1590,16 @@ rule "X.10.0: remove false positives of ai"
rule "X.11.0: Remove dictionary entity which intersects with a manual entity"
salience 64
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active())
$dictionaryEntity: TextEntity(intersects($manualEntity), dictionaryEntry, engines not contains Engine.MANUAL)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.MANUAL,
$a.active(),
$b.dictionaryEntry,
$b.engines not contains Engine.MANUAL
)
then
$dictionaryEntity.remove("X.11.0", "remove dictionary entity which intersects with a manual entity");
retract($dictionaryEntity);
$b.remove("X.11.0", "remove dictionary entity which intersects with a manual entity");
end
@ -1561,7 +1612,6 @@ rule "DICT.0.0: Remove Template Dictionary Entity when contained by Dossier Dict
$dictionaryRemoval: TextEntity($type: type(), entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY)
$entity: TextEntity(getTextRange().equals($dictionaryRemoval.getTextRange()), engines contains Engine.DICTIONARY, type() == $type, (entityType == EntityType.ENTITY || entityType == EntityType.HINT), !hasManualChanges())
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("DICT.0.0", "Remove Template Dictionary Entity when contained by Dossier Dictionary DICTIONARY_REMOVAL");
$entity.addEngine(Engine.DOSSIER_DICTIONARY);
end

View File

@ -18,8 +18,7 @@ import com.iqser.red.service.redaction.v1.server.model.document.TextRange;
import com.iqser.red.service.redaction.v1.server.model.document.entity.*;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType;
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.*;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Section;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.SuperSection;
@ -105,7 +104,7 @@ rule "CBI.0.1: Add CBI_author with \"et al.\" RegEx (non vertebrate study)"
then
entityCreationService.byRegex("\\b([A-ZÄÖÜ][^\\s\\.,]+( [A-ZÄÖÜ]{1,2}\\.?)?( ?[A-ZÄÖÜ]\\.?)?) et al\\.?", "CBI_author", EntityType.ENTITY, 1, $section)
.forEach(entity -> {
entity.redact("CBI.0.1", "Author found by \"et al\" regex", "Article 39(e)(3) of Regulation (EC) No 178/2002");
entity.redact("CBI.0.1", "Author found by \"et al\" regex", "personal_data_geolocation_article_39e3");
dictionary.recommendEverywhere(entity);
});
end
@ -118,7 +117,7 @@ rule "CBI.0.2: Add CBI_author with \"et al.\" RegEx (vertebrate study)"
then
entityCreationService.byRegex("\\b([A-ZÄÖÜ][^\\s\\.,]+( [A-ZÄÖÜ]{1,2}\\.?)?( ?[A-ZÄÖÜ]\\.?)?) et al\\.?", "CBI_author", EntityType.ENTITY, 1, $section)
.forEach(entity -> {
entity.redact("CBI.0.2", "Author found by \"et al\" regex", "Article 39(e)(2) of Regulation (EC) No 178/2002");
entity.redact("CBI.0.2", "Author found by \"et al\" regex", "vertebrate_study_personal_data_geolocation_article_39e2");
dictionary.recommendEverywhere(entity);
});
end
@ -128,7 +127,7 @@ rule "CBI.0.3: Redact CBI Authors (non vertebrate Study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$entity: TextEntity(type() == "CBI_author", dictionaryEntry)
then
$entity.redact("CBI.0.3", "Author found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$entity.redact("CBI.0.3", "Author found", "personal_data_geolocation_article_39e3");
end
rule "CBI.0.4: Redact CBI Authors (vertebrate Study)"
@ -136,7 +135,7 @@ rule "CBI.0.4: Redact CBI Authors (vertebrate Study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$entity: TextEntity(type() == "CBI_author", dictionaryEntry)
then
$entity.redact("CBI.0.4", "Author found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$entity.redact("CBI.0.4", "Author found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
@ -154,7 +153,7 @@ rule "CBI.1.1: Redact CBI Address (vertebrate Study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$entity: TextEntity(type() == "CBI_address", dictionaryEntry)
then
$entity.redact("CBI.1.1", "Address found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$entity.redact("CBI.1.1", "Address found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
@ -179,7 +178,7 @@ rule "CBI.9.0: Redact all cells with Header Author(s) as CBI_author (non vertebr
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.0", "Author(s) found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.0", "Author(s) found", "personal_data_geolocation_article_39e3"));
end
rule "CBI.9.1: Redact all cells with Header Author as CBI_author (non vertebrate study)"
@ -192,7 +191,7 @@ rule "CBI.9.1: Redact all cells with Header Author as CBI_author (non vertebrate
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.1", "Author found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.1", "Author found", "personal_data_geolocation_article_39e3"));
end
@ -207,7 +206,7 @@ rule "CBI.10.0: Redact all cells with Header Author(s) as CBI_author (vertebrate
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.10.0", "Author(s) found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.10.0", "Author(s) found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "CBI.10.1: Redact all cells with Header Author as CBI_author (vertebrate study)"
@ -220,7 +219,7 @@ rule "CBI.10.1: Redact all cells with Header Author as CBI_author (vertebrate st
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.10.1", "Author found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.10.1", "Author found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -303,7 +302,7 @@ rule "CBI.20.2: Redact between \"PERFORMING LABORATORY\" and \"LABORATORY PROJEC
then
entityCreationService.betweenStrings("PERFORMING LABORATORY:", "LABORATORY PROJECT ID:", "CBI_address", EntityType.ENTITY, $section)
.forEach(laboratoryEntity -> {
laboratoryEntity.redact("CBI.20.2", "PERFORMING LABORATORY was found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
laboratoryEntity.redact("CBI.20.2", "PERFORMING LABORATORY was found", "vertebrate_study_personal_data_geolocation_article_39e2");
dictionary.recommendEverywhere(laboratoryEntity);
});
end
@ -316,7 +315,7 @@ rule "CBI.23.0: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (no
$document: Document(containsStringIgnoreCase("AUTHOR(S)"), containsAnyStringIgnoreCase("COMPLETION DATE", "STUDY COMPLETION DATE"))
then
entityCreationService.shortestBetweenAnyStringIgnoreCase(List.of("AUTHOR(S)", "AUTHOR(S):"), List.of("COMPLETION DATE", "COMPLETION DATE:", "STUDY COMPLETION DATE", "STUDY COMPLETION DATE:"), "CBI_author", EntityType.ENTITY, $document, 200)
.forEach(authorEntity -> authorEntity.redact("CBI.23.0", "AUTHOR(S) was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("CBI.23.0", "AUTHOR(S) was found", "personal_data_geolocation_article_39e3"));
end
rule "CBI.23.1: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (vertebrate study)"
@ -325,7 +324,7 @@ rule "CBI.23.1: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (ve
$document: Document(containsStringIgnoreCase("AUTHOR(S)"), containsAnyStringIgnoreCase("COMPLETION DATE", "STUDY COMPLETION DATE"))
then
entityCreationService.shortestBetweenAnyStringIgnoreCase(List.of("AUTHOR(S)", "AUTHOR(S):"), List.of("COMPLETION DATE", "COMPLETION DATE:", "STUDY COMPLETION DATE", "STUDY COMPLETION DATE:"), "CBI_author", EntityType.ENTITY, $document, 200)
.forEach(authorEntity -> authorEntity.redact("CBI.23.1", "AUTHOR(S) was found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("CBI.23.1", "AUTHOR(S) was found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -337,7 +336,7 @@ rule "PII.0.1: Redact all PII (non vertebrate study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$pii: TextEntity(type() == "PII", dictionaryEntry)
then
$pii.redact("PII.0.1", "Personal Information found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$pii.redact("PII.0.1", "Personal Information found", "personal_data_geolocation_article_39e3");
end
rule "PII.0.2: Redact all PII (vertebrate study)"
@ -345,7 +344,7 @@ rule "PII.0.2: Redact all PII (vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$pii: TextEntity(type() == "PII", dictionaryEntry)
then
$pii.redact("PII.0.2", "Personal Information found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$pii.redact("PII.0.2", "Personal Information found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
@ -356,7 +355,7 @@ rule "PII.1.1: Redact Emails by RegEx (Non vertebrate study)"
$section: Section(containsString("@"))
then
entityCreationService.byRegex("\\b([A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z\\-]{1,23}[A-Za-z])\\b", "PII", EntityType.ENTITY, 1, $section)
.forEach(emailEntity -> emailEntity.redact("PII.1.1", "Found by Email Regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(emailEntity -> emailEntity.redact("PII.1.1", "Found by Email Regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.1.2: Redact Emails by RegEx (vertebrate study)"
@ -365,7 +364,7 @@ rule "PII.1.2: Redact Emails by RegEx (vertebrate study)"
$section: Section(containsString("@"))
then
entityCreationService.byRegex("\\b([A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z\\-]{1,23}[A-Za-z])\\b", "PII", EntityType.ENTITY, 1, $section)
.forEach(emailEntity -> emailEntity.redact("PII.1.2", "Found by Email Regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(emailEntity -> emailEntity.redact("PII.1.2", "Found by Email Regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "PII.1.3: Redact typoed Emails with indicator"
@ -373,7 +372,7 @@ rule "PII.1.3: Redact typoed Emails with indicator"
$section: Section(containsString("@") || containsStringIgnoreCase("mail"))
then
entityCreationService.byRegexIgnoreCase("mail[:\\.\\s]{1,2}([\\w\\/\\-\\{\\(\\. ]{3,20}(@|a|f)\\s?[\\w\\/\\-\\{\\(\\. ]{3,20}(\\. \\w{2,4}\\b|\\.\\B|\\.\\w{1,4}\\b))", "PII", EntityType.ENTITY, 1, $section)
.forEach(emailEntity -> emailEntity.redact("PII.1.3", "Personal information found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(emailEntity -> emailEntity.redact("PII.1.3", "Personal information found", "personal_data_geolocation_article_39e3"));
end
@ -392,7 +391,7 @@ rule "PII.2.1: Redact Phone and Fax by RegEx (non vertebrate study)"
containsString("Fer"))
then
entityCreationService.byRegexIgnoreCase("\\b(contact|telephone|phone|ph\\.|fax|tel|ter[^\\w]|mobile|fel[^\\w]|fer[^\\w])[a-zA-Z\\s]{0,10}[:.\\s]{0,3}([\\+\\d\\(][\\s\\d\\(\\)\\-\\/\\.]{4,100}\\d)\\b", "PII", EntityType.ENTITY, 2, $section)
.forEach(contactEntity -> contactEntity.redact("PII.2.1", "Found by Phone and Fax Regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.2.1", "Found by Phone and Fax Regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.2.2: Redact Phone and Fax by RegEx (vertebrate study)"
@ -409,7 +408,7 @@ rule "PII.2.2: Redact Phone and Fax by RegEx (vertebrate study)"
containsString("Fer"))
then
entityCreationService.byRegexIgnoreCase("\\b(contact|telephone|phone|ph\\.|fax|tel|ter[^\\w]|mobile|fel[^\\w]|fer[^\\w])[a-zA-Z\\s]{0,10}[:.\\s]{0,3}([\\+\\d\\(][\\s\\d\\(\\)\\-\\/\\.]{4,100}\\d)\\b", "PII", EntityType.ENTITY, 2, $section)
.forEach(contactEntity -> contactEntity.redact("PII.2.2", "Found by Phone and Fax Regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.2.2", "Found by Phone and Fax Regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "PII.2.3: Redact phone numbers without indicators"
@ -417,7 +416,7 @@ rule "PII.2.3: Redact phone numbers without indicators"
$section: Section(containsString("+"))
then
entityCreationService.byRegex("(\\+[\\dO]{1,2} )(\\([\\dO]{1,3}\\))?[\\d\\-O ]{8,15}", "PII", EntityType.ENTITY, $section)
.forEach(entity -> entity.redact("PII.2.3", "Personal information found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.2.3", "Personal information found", "personal_data_geolocation_article_39e3"));
end
@ -428,7 +427,7 @@ rule "PII.3.1: Redact telephone numbers by RegEx (Non vertebrate study)"
$section: Section(!hasTables(), matchesRegex("[+]\\d{1,}"))
then
entityCreationService.byRegex("((([+]\\d{1,3} (\\d{7,12})\\b)|([+]\\d{1,3}(\\d{3,12})\\b|[+]\\d{1,3}([ -]\\(?\\d{1,6}\\)?){2,4})|[+]\\d{1,3} ?((\\d{2,6}\\)?)([ -]\\d{2,6}){1,4}))(-\\d{1,3})?\\b)", "PII", EntityType.ENTITY, 1, $section)
.forEach(entity -> entity.redact("PII.3.1", "Telephone number found by regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.3.1", "Telephone number found by regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.3.2: Redact telephone numbers by RegEx (vertebrate study)"
@ -437,7 +436,7 @@ rule "PII.3.2: Redact telephone numbers by RegEx (vertebrate study)"
$section: Section(!hasTables(), matchesRegex("[+]\\d{1,}"))
then
entityCreationService.byRegex("((([+]\\d{1,3} (\\d{7,12})\\b)|([+]\\d{1,3}(\\d{3,12})\\b|[+]\\d{1,3}([ -]\\(?\\d{1,6}\\)?){2,4})|[+]\\d{1,3} ?((\\d{2,6}\\)?)([ -]\\d{2,6}){1,4}))(-\\d{1,3})?\\b)", "PII", EntityType.ENTITY, 1, $section)
.forEach(entity -> entity.redact("PII.3.2", "Telephone number found by regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.3.2", "Telephone number found by regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "PII.3.4: Redact telephone numbers by RegEx (Non vertebrate study)"
@ -446,7 +445,7 @@ rule "PII.3.4: Redact telephone numbers by RegEx (Non vertebrate study)"
$rowCell: TableCell(matchesRegex("[+]\\d{1,}"))
then
entityCreationService.byRegex("((([+]\\d{1,3} (\\d{7,12})\\b)|([+]\\d{1,3}(\\d{3,12})\\b|[+]\\d{1,3}([ -]\\(?\\d{1,6}\\)?){2,4})|[+]\\d{1,3} ?((\\d{2,6}\\)?)([ -]\\d{2,6}){1,4}))(-\\d{1,3})?\\b)", "PII", EntityType.ENTITY, 1, $rowCell)
.forEach(entity -> entity.redact("PII.3.4", "Telephone number found by regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.3.4", "Telephone number found by regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.3.5: Redact telephone numbers by RegEx (vertebrate study)"
@ -455,7 +454,7 @@ rule "PII.3.5: Redact telephone numbers by RegEx (vertebrate study)"
$rowCell: TableCell(matchesRegex("[+]\\d{1,}"))
then
entityCreationService.byRegex("((([+]\\d{1,3} (\\d{7,12})\\b)|([+]\\d{1,3}(\\d{3,12})\\b|[+]\\d{1,3}([ -]\\(?\\d{1,6}\\)?){2,4})|[+]\\d{1,3} ?((\\d{2,6}\\)?)([ -]\\d{2,6}){1,4}))(-\\d{1,3})?\\b)", "PII", EntityType.ENTITY, 1, $rowCell)
.forEach(entity -> entity.redact("PII.3.5", "Telephone number found by regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.3.5", "Telephone number found by regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -470,7 +469,7 @@ rule "PII.5.1: Redact line after contact information keywords reduced (non verte
$section: Section(containsString($contactKeyword))
then
entityCreationService.lineAfterString($contactKeyword, "PII", EntityType.ENTITY, $section)
.forEach(contactEntity -> contactEntity.redact("PII.5.1", "Found after \"" + $contactKeyword + "\" contact keyword", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.5.1", "Found after \"" + $contactKeyword + "\" contact keyword", "personal_data_geolocation_article_39e3"));
end
rule "PII.5.2: Redact line after contact information keywords reduced (Vertebrate study)"
@ -483,7 +482,7 @@ rule "PII.5.2: Redact line after contact information keywords reduced (Vertebrat
$section: Section(containsString($contactKeyword))
then
entityCreationService.lineAfterString($contactKeyword, "PII", EntityType.ENTITY, $section)
.forEach(contactEntity -> contactEntity.redact("PII.5.2", "Found after \"" + $contactKeyword + "\" contact keyword", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.5.2", "Found after \"" + $contactKeyword + "\" contact keyword", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -497,7 +496,7 @@ rule "PII.6.1: Redact line between contact keywords (non vertebrate study)"
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
)
.forEach(contactEntity -> contactEntity.redact("PII.6.1", "Found between contact keywords", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.6.1", "Found between contact keywords", "personal_data_geolocation_article_39e3"));
end
rule "PII.6.2: Redact line between contact keywords (vertebrate study)"
@ -509,7 +508,7 @@ rule "PII.6.2: Redact line between contact keywords (vertebrate study)"
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
)
.forEach(contactEntity -> contactEntity.redact("PII.6.2", "Found between contact keywords", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.6.2", "Found between contact keywords", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -529,7 +528,7 @@ rule "PII.7.1: Redact contact information if applicant is found (non vertebrate
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.7.1", "Applicant information was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.7.1", "Applicant information was found", "personal_data_geolocation_article_39e3"));
end
rule "PII.7.2: Redact contact information if applicant is found (vertebrate study)"
@ -547,7 +546,7 @@ rule "PII.7.2: Redact contact information if applicant is found (vertebrate stud
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.7.2", "Applicant information was found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.7.2", "Applicant information was found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -567,7 +566,7 @@ rule "PII.8.1: Redact contact information if producer is found (non vertebrate s
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.8.1", "Producer was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.8.1", "Producer was found", "personal_data_geolocation_article_39e3"));
end
rule "PII.8.2: Redact contact information if producer is found (vertebrate study)"
@ -585,7 +584,7 @@ rule "PII.8.2: Redact contact information if producer is found (vertebrate study
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.8.2", "Producer was found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.8.2", "Producer was found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -596,7 +595,7 @@ rule "PII.10.0: Redact study director abbreviation (non vertebrate study)"
$section: Section(containsString("KATH") || containsString("BECH") || containsString("KML"))
then
entityCreationService.byRegexIgnoreCase("((KATH)|(BECH)|(KML)) ?(\\d{4})","PII", EntityType.ENTITY, 1, $section)
.forEach(entity -> entity.redact("PII.10.0", "Personal information found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.10.0", "Personal information found", "personal_data_geolocation_article_39e3"));
end
rule "PII.10.1: Redact study director abbreviation (vertebrate study)"
@ -605,7 +604,7 @@ rule "PII.10.1: Redact study director abbreviation (vertebrate study)"
$section: Section(containsString("KATH") || containsString("BECH") || containsString("KML"))
then
entityCreationService.byRegexIgnoreCase("((KATH)|(BECH)|(KML)) ?(\\d{4})","PII", EntityType.ENTITY, 1, $section)
.forEach(entity -> entity.redact("PII.10.1", "Personal information found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.10.1", "Personal information found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -615,7 +614,7 @@ rule "PII.11.0: Redact On behalf of Sequani Ltd.:"
$section: SuperSection(!hasTables(), containsString("On behalf of Sequani Ltd.: Name Title"))
then
entityCreationService.betweenStrings("On behalf of Sequani Ltd.: Name Title", "On behalf of", "PII", EntityType.ENTITY, $section)
.forEach(authorEntity -> authorEntity.redact("PII.11.0", "On behalf of Sequani Ltd.: Name Title was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("PII.11.0", "On behalf of Sequani Ltd.: Name Title was found", "personal_data_geolocation_article_39e3"));
end
@ -626,7 +625,7 @@ rule "PII.12.0: Expand PII entities with salutation prefix"
$entityToExpand: TextEntity(type() == "PII", anyMatch(textBefore, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*"))
then
entityCreationService.byPrefixExpansionRegex($entityToExpand, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*")
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.0", "Expanded PII with salutation prefix", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.0", "Expanded PII with salutation prefix", "personal_data_geolocation_article_39e3"));
end
rule "PII.12.1: Expand PII entities with salutation prefix"
@ -635,7 +634,7 @@ rule "PII.12.1: Expand PII entities with salutation prefix"
$entityToExpand: TextEntity(type() == "PII", anyMatch(textBefore, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*"))
then
entityCreationService.byPrefixExpansionRegex($entityToExpand, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*")
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.1", "Expanded PII with salutation prefix", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.1", "Expanded PII with salutation prefix", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -657,7 +656,7 @@ rule "ETC.2.1: Redact signatures (non vertebrate study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$signature: Image(imageType == ImageType.SIGNATURE)
then
$signature.redact("ETC.2.1", "Signature Found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$signature.redact("ETC.2.1", "Signature Found", "personal_data_geolocation_article_39e3");
end
rule "ETC.2.2: Redact signatures (vertebrate study)"
@ -665,7 +664,7 @@ rule "ETC.2.2: Redact signatures (vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$signature: Image(imageType == ImageType.SIGNATURE)
then
$signature.redact("ETC.2.2", "Signature Found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$signature.redact("ETC.2.2", "Signature Found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
@ -683,7 +682,7 @@ rule "ETC.3.2: Redact logos (vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$logo: Image(imageType == ImageType.LOGO)
then
$logo.redact("ETC.3.2", "Logo Found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$logo.redact("ETC.3.2", "Logo Found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
@ -694,7 +693,6 @@ rule "ETC.5.0: Skip dossier_redaction entries if confidentiality is 'confidentia
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.skip("ETC.5.0", "Ignore dossier_redaction when confidential");
$dossierRedaction.getIntersectingNodes().forEach(node -> update(node));
end
rule "ETC.5.1: Remove dossier_redaction entries if confidentiality is not 'confidential'"
@ -704,7 +702,6 @@ rule "ETC.5.1: Remove dossier_redaction entries if confidentiality is not 'confi
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.remove("ETC.5.1", "Remove dossier_redaction when not confidential");
retract($dossierRedaction);
end
@ -841,8 +838,6 @@ rule "MAN.0.0: Apply manual resize redaction"
then
manualChangesApplicationService.resize($entityToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($entityToBeResized);
$entityToBeResized.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.0.1: Apply manual resize redaction"
@ -854,8 +849,6 @@ rule "MAN.0.1: Apply manual resize redaction"
then
manualChangesApplicationService.resizeImage($imageToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($imageToBeResized);
update($imageToBeResized.getParent());
end
@ -866,10 +859,8 @@ rule "MAN.1.0: Apply id removals that are valid and not in forced redactions to
$idRemoval: IdRemoval($id: annotationId, !removeFromDictionary, !removeFromAllDossiers)
$entityToBeRemoved: TextEntity(matchesAnnotationId($id))
then
$entityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($entityToBeRemoved);
$entityToBeRemoved.addManualChange($idRemoval);
retract($idRemoval);
$entityToBeRemoved.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to Image"
@ -879,9 +870,7 @@ rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to
$imageEntityToBeRemoved: Image($id == id)
then
$imageEntityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($imageEntityToBeRemoved);
retract($idRemoval);
update($imageEntityToBeRemoved.getParent());
end
@ -892,9 +881,7 @@ rule "MAN.2.0: Apply force redaction"
$force: ManualForceRedaction($id: annotationId)
$entityToForce: TextEntity(matchesAnnotationId($id))
then
$entityToForce.getManualOverwrite().addChange($force);
update($entityToForce);
$entityToForce.getIntersectingNodes().forEach(node -> update(node));
$entityToForce.addManualChange($force);
retract($force);
end
@ -905,8 +892,6 @@ rule "MAN.2.1: Apply force redaction to images"
$imageToForce: Image(id == $id)
then
$imageToForce.getManualOverwrite().addChange($force);
update($imageToForce);
update($imageToForce.getParent());
retract($force);
end
@ -919,9 +904,7 @@ rule "MAN.3.0: Apply entity recategorization"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() != $type)
then
$entityToBeRecategorized.getIntersectingNodes().forEach(node -> update(node));
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
update($entityToBeRecategorized);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -932,7 +915,7 @@ rule "MAN.3.1: Apply entity recategorization of same type"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() == $type)
then
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -944,8 +927,6 @@ rule "MAN.3.2: Apply image recategorization"
$imageToBeRecategorized: Image($id == id)
then
manualChangesApplicationService.recategorize($imageToBeRecategorized, $recategorization);
update($imageToBeRecategorized);
update($imageToBeRecategorized.getParent());
retract($recategorization);
end
@ -966,7 +947,6 @@ rule "MAN.4.0: Apply legal basis change"
$imageToBeRecategorized: Image($id == id)
then
$imageToBeRecategorized.getManualOverwrite().addChange($legalBasisChange);
update($imageToBeRecategorized)
retract($legalBasisChange)
end
@ -976,8 +956,7 @@ rule "MAN.4.1: Apply legal basis change"
$legalBasisChange: ManualLegalBasisChange($id: annotationId)
$entityToBeChanged: TextEntity(matchesAnnotationId($id))
then
$entityToBeChanged.getManualOverwrite().addChange($legalBasisChange);
update($entityToBeChanged)
$entityToBeChanged.addManualChange($legalBasisChange);
retract($legalBasisChange)
end
@ -988,71 +967,114 @@ rule "MAN.4.1: Apply legal basis change"
rule "X.0.0: Remove Entity contained by Entity of same type"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), !hasManualChanges())
not TextEntity(getTextRange().equals($larger.getTextRange()), type() == $type, entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY, !hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
!$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
not TextEntity(
getTextRange().equals($container.getTextRange()),
type() == $container.type(),
entityType == EntityType.DICTIONARY_REMOVAL,
engines contains Engine.DOSSIER_DICTIONARY,
!hasManualChanges()
)
then
$contained.remove("X.0.0", "remove Entity contained by Entity of same type");
retract($contained);
end
end
rule "X.0.1: Remove Entity contained by Entity of same type with manual changes"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
then
$contained.getIntersectingNodes().forEach(node -> update(node));
$contained.remove("X.0.1", "remove Entity contained by Entity of same type with manual changes");
retract($contained);
end
end
// Rule unit: X.2
rule "X.2.0: Remove Entity of type ENTITY when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.ENTITY), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.ENTITY,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
end
rule "X.2.1: Remove Entity of type HINT when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.HINT), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.HINT,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("X.2.1", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.1", "remove Entity of type HINT when contained by FALSE_POSITIVE");
end
// Rule unit: X.3
rule "X.3.0: Remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION"
rule "X.3.0: Remove RECOMMENDATION Contained by FALSE_RECOMMENDATION"
salience 64
when
$falseRecommendation: TextEntity($type: type(), entityType == EntityType.FALSE_RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($falseRecommendation), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
end
// Rule unit: X.4
rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY with same type"
salience 256
when
$entity: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(getTextRange().equals($entity.getTextRange()), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$entity.addEngines($recommendation.getEngines());
$recommendation.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
retract($recommendation);
$a.addEngines($b.getEngines());
$b.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
end
@ -1060,68 +1082,100 @@ rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY
rule "X.5.0: Remove Entity of type RECOMMENDATION when intersected by ENTITY"
salience 256
when
$entity: TextEntity((entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(intersects($entity), entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$intersection: Intersection(
$a: a,
$b: b,
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$recommendation.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
retract($recommendation);
$b.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
end
rule "X.5.1: Remove Entity of type RECOMMENDATION when contained by RECOMMENDATION"
salience 256
when
$entity: TextEntity($type: type(), entityType == EntityType.RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($entity), type() != $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$container.type() != $contained.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
end
// Rule unit: X.6
rule "X.6.0: Remove Entity of lower rank, when contained by entity of type ENTITY or HINT"
rule "X.6.0: Remove Lower Rank Entity Contained by ENTITY or HINT"
salience 32
when
$higherRank: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$lowerRank: TextEntity(containedBy($higherRank), type() != $type, dictionary.getDictionaryRank(type) < dictionary.getDictionaryRank($type), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
($container.entityType == EntityType.ENTITY || $container.entityType == EntityType.HINT),
$container.active(),
$contained.type() != $container.type(),
eval(dictionary.getDictionaryRank($contained.type()) < dictionary.getDictionaryRank($container.type())),
!$contained.hasManualChanges()
)
then
$lowerRank.getIntersectingNodes().forEach(node -> update(node));
$lowerRank.remove("X.6.0", "remove Entity of lower rank, when contained by entity of type ENTITY or HINT");
retract($lowerRank);
$contained.remove("X.6.0", "remove Entity of lower rank when contained by entity of type ENTITY or HINT");
end
rule "X.6.1: remove Entity, when contained in another entity of type ENTITY or HINT with larger text range"
rule "X.6.1: Remove Entity, when contained in another entity of type ENTITY or HINT with larger text range"
salience 32
when
$outer: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$inner: TextEntity(containedBy($outer), type() != $type, $outer.getTextRange().length > getTextRange().length(), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
($container.entityType == EntityType.ENTITY || $container.entityType == EntityType.HINT),
$container.active(),
$contained.type() != $container.type(),
eval($container.getTextRange().length() > $contained.getTextRange().length()),
!$contained.hasManualChanges()
)
then
$inner.getIntersectingNodes().forEach(node -> update(node));
$inner.remove("X.6.1", "remove Entity, when contained in another entity of type ENTITY or HINT with larger text range");
retract($inner);
end
$contained.remove("X.6.1", "remove Entity when contained in another entity of type ENTITY or HINT with larger text range");
end
// Rule unit: X.8
rule "X.8.0: Remove Entity when text range and type equals to imported Entity"
salience 257
when
$entity: TextEntity($type: type(), engines contains Engine.IMPORTED, active())
$other: TextEntity(getTextRange().equals($entity.getTextRange()), this != $entity, type() == $type, engines not contains Engine.IMPORTED)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$entity.addEngines($other.getEngines());
retract($other);
$b.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$a.addEngines($b.getEngines());
end
rule "X.8.1: Remove Entity when intersected by imported Entity"
salience 256
when
$entity: TextEntity(engines contains Engine.IMPORTED, active())
$other: TextEntity(intersects($entity), this != $entity, engines not contains Engine.IMPORTED)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.1", "remove Entity when intersected by imported Entity");
retract($other);
$b.remove("X.8.1", "remove Entity when intersected by imported Entity");
end
@ -1147,25 +1201,36 @@ rule "X.10.0: remove false positives of ai"
// Rule unit: X.11
rule "X.11.1: Remove non manual entity which intersects with a manual entity"
rule "X.11.1: Remove non-manual entity which intersects with a manual entity"
salience 64
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active())
$nonManualEntity: TextEntity(intersects($manualEntity), engines not contains Engine.MANUAL)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.MANUAL,
$a.active(),
$b.engines not contains Engine.MANUAL
)
then
$nonManualEntity.remove("X.11.1", "remove entity which intersects with a manual entity");
retract($nonManualEntity);
$b.remove("X.11.1", "remove entity which intersects with a manual entity");
end
rule "X.11.2: Remove non manual entity which are equal to manual entity"
rule "X.11.2: Remove non-manual entity which is equal to manual entity"
salience 70
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active(), $type: type())
$nonManualEntity: TextEntity(getTextRange().equals($manualEntity.getTextRange()), type() == $type, entityType == EntityType.ENTITY, !hasManualChanges(), engines not contains Engine.MANUAL)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.MANUAL,
$a.active(),
$b.entityType == EntityType.ENTITY,
!$b.hasManualChanges(),
$b.engines not contains Engine.MANUAL
)
then
$manualEntity.addEngines($nonManualEntity.getEngines());
$nonManualEntity.remove("X.11.2", "remove non manual entity which are equal to manual entity");
retract($nonManualEntity);
$a.addEngines($b.getEngines());
$b.remove("X.11.2", "remove non-manual entity which is equal to manual entity");
end
@ -1178,7 +1243,6 @@ rule "DICT.0.0: Remove Template Dictionary Entity when contained by Dossier Dict
$dictionaryRemoval: TextEntity($type: type(), entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY)
$entity: TextEntity(getTextRange().equals($dictionaryRemoval.getTextRange()), engines contains Engine.DICTIONARY, type() == $type, (entityType == EntityType.ENTITY || entityType == EntityType.HINT), !hasManualChanges())
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("DICT.0.0", "Remove Template Dictionary Entity when contained by Dossier Dictionary DICTIONARY_REMOVAL");
$entity.addEngine(Engine.DOSSIER_DICTIONARY);
end

View File

@ -18,8 +18,7 @@ import com.iqser.red.service.redaction.v1.server.model.document.TextRange;
import com.iqser.red.service.redaction.v1.server.model.document.entity.*;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType;
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.*;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Section;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Table;
@ -160,8 +159,6 @@ rule "MAN.0.0: Apply manual resize redaction"
then
manualChangesApplicationService.resize($entityToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($entityToBeResized);
$entityToBeResized.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.0.1: Apply manual resize redaction"
@ -173,8 +170,6 @@ rule "MAN.0.1: Apply manual resize redaction"
then
manualChangesApplicationService.resizeImage($imageToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($imageToBeResized);
update($imageToBeResized.getParent());
end
@ -185,10 +180,8 @@ rule "MAN.1.0: Apply id removals that are valid and not in forced redactions to
$idRemoval: IdRemoval($id: annotationId, !removeFromDictionary, !removeFromAllDossiers)
$entityToBeRemoved: TextEntity(matchesAnnotationId($id))
then
$entityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($entityToBeRemoved);
$entityToBeRemoved.addManualChange($idRemoval);
retract($idRemoval);
$entityToBeRemoved.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to Image"
@ -198,9 +191,7 @@ rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to
$imageEntityToBeRemoved: Image($id == id)
then
$imageEntityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($imageEntityToBeRemoved);
retract($idRemoval);
update($imageEntityToBeRemoved.getParent());
end
@ -211,9 +202,7 @@ rule "MAN.2.0: Apply force redaction"
$force: ManualForceRedaction($id: annotationId)
$entityToForce: TextEntity(matchesAnnotationId($id))
then
$entityToForce.getManualOverwrite().addChange($force);
update($entityToForce);
$entityToForce.getIntersectingNodes().forEach(node -> update(node));
$entityToForce.addManualChange($force);
retract($force);
end
@ -224,8 +213,6 @@ rule "MAN.2.1: Apply force redaction to images"
$imageToForce: Image(id == $id)
then
$imageToForce.getManualOverwrite().addChange($force);
update($imageToForce);
update($imageToForce.getParent());
retract($force);
end
@ -238,9 +225,7 @@ rule "MAN.3.0: Apply entity recategorization"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() != $type)
then
$entityToBeRecategorized.getIntersectingNodes().forEach(node -> update(node));
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
update($entityToBeRecategorized);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -251,7 +236,7 @@ rule "MAN.3.1: Apply entity recategorization of same type"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() == $type)
then
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -263,8 +248,6 @@ rule "MAN.3.2: Apply image recategorization"
$imageToBeRecategorized: Image($id == id)
then
manualChangesApplicationService.recategorize($imageToBeRecategorized, $recategorization);
update($imageToBeRecategorized);
update($imageToBeRecategorized.getParent());
retract($recategorization);
end
@ -285,7 +268,6 @@ rule "MAN.4.0: Apply legal basis change"
$imageToBeRecategorized: Image($id == id)
then
$imageToBeRecategorized.getManualOverwrite().addChange($legalBasisChange);
update($imageToBeRecategorized)
retract($legalBasisChange)
end
@ -295,8 +277,7 @@ rule "MAN.4.1: Apply legal basis change"
$legalBasisChange: ManualLegalBasisChange($id: annotationId)
$entityToBeChanged: TextEntity(matchesAnnotationId($id))
then
$entityToBeChanged.getManualOverwrite().addChange($legalBasisChange);
update($entityToBeChanged)
$entityToBeChanged.addManualChange($legalBasisChange);
retract($legalBasisChange)
end
@ -307,71 +288,114 @@ rule "MAN.4.1: Apply legal basis change"
rule "X.0.0: Remove Entity contained by Entity of same type"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), !hasManualChanges())
not TextEntity(getTextRange().equals($larger.getTextRange()), type() == $type, entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY, !hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
!$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
not TextEntity(
getTextRange().equals($container.getTextRange()),
type() == $container.type(),
entityType == EntityType.DICTIONARY_REMOVAL,
engines contains Engine.DOSSIER_DICTIONARY,
!hasManualChanges()
)
then
$contained.remove("X.0.0", "remove Entity contained by Entity of same type");
retract($contained);
end
end
rule "X.0.1: Remove Entity contained by Entity of same type with manual changes"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
then
$contained.getIntersectingNodes().forEach(node -> update(node));
$contained.remove("X.0.1", "remove Entity contained by Entity of same type with manual changes");
retract($contained);
end
end
// Rule unit: X.2
rule "X.2.0: Remove Entity of type ENTITY when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.ENTITY), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.ENTITY,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
end
rule "X.2.1: Remove Entity of type HINT when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.HINT), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.HINT,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("X.2.1", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.1", "remove Entity of type HINT when contained by FALSE_POSITIVE");
end
// Rule unit: X.3
rule "X.3.0: Remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION"
rule "X.3.0: Remove RECOMMENDATION Contained by FALSE_RECOMMENDATION"
salience 64
when
$falseRecommendation: TextEntity($type: type(), entityType == EntityType.FALSE_RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($falseRecommendation), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
end
// Rule unit: X.4
rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY with same type"
salience 256
when
$entity: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(getTextRange().equals($entity.getTextRange()), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$entity.addEngines($recommendation.getEngines());
$recommendation.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
retract($recommendation);
$a.addEngines($b.getEngines());
$b.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
end
@ -379,68 +403,100 @@ rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY
rule "X.5.0: Remove Entity of type RECOMMENDATION when intersected by ENTITY"
salience 256
when
$entity: TextEntity((entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(intersects($entity), entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$intersection: Intersection(
$a: a,
$b: b,
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$recommendation.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
retract($recommendation);
$b.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
end
rule "X.5.1: Remove Entity of type RECOMMENDATION when contained by RECOMMENDATION"
salience 256
when
$entity: TextEntity($type: type(), entityType == EntityType.RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($entity), type() != $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$container.type() != $contained.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
end
// Rule unit: X.6
rule "X.6.0: Remove Entity of lower rank, when contained by entity of type ENTITY or HINT"
rule "X.6.0: Remove Lower Rank Entity Contained by ENTITY or HINT"
salience 32
when
$higherRank: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$lowerRank: TextEntity(containedBy($higherRank), type() != $type, dictionary.getDictionaryRank(type) < dictionary.getDictionaryRank($type), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
($container.entityType == EntityType.ENTITY || $container.entityType == EntityType.HINT),
$container.active(),
$contained.type() != $container.type(),
eval(dictionary.getDictionaryRank($contained.type()) < dictionary.getDictionaryRank($container.type())),
!$contained.hasManualChanges()
)
then
$lowerRank.getIntersectingNodes().forEach(node -> update(node));
$lowerRank.remove("X.6.0", "remove Entity of lower rank, when contained by entity of type ENTITY or HINT");
retract($lowerRank);
$contained.remove("X.6.0", "remove Entity of lower rank when contained by entity of type ENTITY or HINT");
end
rule "X.6.1: remove Entity, when contained in another entity of type ENTITY or HINT with larger text range"
rule "X.6.1: Remove Entity, when contained in another entity of type ENTITY or HINT with larger text range"
salience 32
when
$outer: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$inner: TextEntity(containedBy($outer), type() != $type, $outer.getTextRange().length > getTextRange().length(), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
($container.entityType == EntityType.ENTITY || $container.entityType == EntityType.HINT),
$container.active(),
$contained.type() != $container.type(),
eval($container.getTextRange().length() > $contained.getTextRange().length()),
!$contained.hasManualChanges()
)
then
$inner.getIntersectingNodes().forEach(node -> update(node));
$inner.remove("X.6.1", "remove Entity, when contained in another entity of type ENTITY or HINT with larger text range");
retract($inner);
end
$contained.remove("X.6.1", "remove Entity when contained in another entity of type ENTITY or HINT with larger text range");
end
// Rule unit: X.8
rule "X.8.0: Remove Entity when text range and type equals to imported Entity"
salience 257
when
$entity: TextEntity($type: type(), engines contains Engine.IMPORTED, active())
$other: TextEntity(getTextRange().equals($entity.getTextRange()), this != $entity, type() == $type, engines not contains Engine.IMPORTED)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$entity.addEngines($other.getEngines());
retract($other);
$b.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$a.addEngines($b.getEngines());
end
rule "X.8.1: Remove Entity when intersected by imported Entity"
salience 256
when
$entity: TextEntity(engines contains Engine.IMPORTED, active())
$other: TextEntity(intersects($entity), this != $entity, engines not contains Engine.IMPORTED)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.1", "remove Entity when intersected by imported Entity");
retract($other);
$b.remove("X.8.1", "remove Entity when intersected by imported Entity");
end
@ -466,25 +522,36 @@ rule "X.10.0: remove false positives of ai"
// Rule unit: X.11
rule "X.11.1: Remove non manual entity which intersects with a manual entity"
rule "X.11.1: Remove non-manual entity which intersects with a manual entity"
salience 64
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active())
$nonManualEntity: TextEntity(intersects($manualEntity), engines not contains Engine.MANUAL)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.MANUAL,
$a.active(),
$b.engines not contains Engine.MANUAL
)
then
$nonManualEntity.remove("X.11.1", "remove entity which intersects with a manual entity");
retract($nonManualEntity);
$b.remove("X.11.1", "remove entity which intersects with a manual entity");
end
rule "X.11.2: Remove non manual entity which are equal to manual entity"
rule "X.11.2: Remove non-manual entity which is equal to manual entity"
salience 70
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active(), $type: type())
$nonManualEntity: TextEntity(getTextRange().equals($manualEntity.getTextRange()), type() == $type, entityType == EntityType.ENTITY, !hasManualChanges(), engines not contains Engine.MANUAL)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.MANUAL,
$a.active(),
$b.entityType == EntityType.ENTITY,
!$b.hasManualChanges(),
$b.engines not contains Engine.MANUAL
)
then
$manualEntity.addEngines($nonManualEntity.getEngines());
$nonManualEntity.remove("X.11.2", "remove non manual entity which are equal to manual entity");
retract($nonManualEntity);
$a.addEngines($b.getEngines());
$b.remove("X.11.2", "remove non-manual entity which is equal to manual entity");
end
@ -497,7 +564,6 @@ rule "DICT.0.0: Remove Template Dictionary Entity when contained by Dossier Dict
$dictionaryRemoval: TextEntity($type: type(), entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY)
$entity: TextEntity(getTextRange().equals($dictionaryRemoval.getTextRange()), engines contains Engine.DICTIONARY, type() == $type, (entityType == EntityType.ENTITY || entityType == EntityType.HINT), !hasManualChanges())
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("DICT.0.0", "Remove Template Dictionary Entity when contained by Dossier Dictionary DICTIONARY_REMOVAL");
$entity.addEngine(Engine.DOSSIER_DICTIONARY);
end

View File

@ -18,8 +18,10 @@ import com.iqser.red.service.redaction.v1.server.model.document.TextRange;
import com.iqser.red.service.redaction.v1.server.model.document.entity.*;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType;
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.entity.Containment;
import com.iqser.red.service.redaction.v1.server.model.document.entity.Equality;
import com.iqser.red.service.redaction.v1.server.model.document.entity.Intersection;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.*;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Section;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.SuperSection;
@ -107,7 +109,7 @@ rule "CBI.0.1: Add CBI_author with \"et al.\" RegEx (non vertebrate study)"
then
entityCreationService.byRegex("\\b([A-ZÄÖÜ][^\\s\\.,]+( [A-ZÄÖÜ]{1,2}\\.?)?( ?[A-ZÄÖÜ]\\.?)?) et al\\.?", "CBI_author", EntityType.ENTITY, 1, $section)
.forEach(entity -> {
entity.redact("CBI.0.1", "Author found by \"et al\" regex", "Article 39(e)(3) of Regulation (EC) No 178/2002");
entity.redact("CBI.0.1", "Author found by \"et al\" regex", "personal_data_geolocation_article_39e3");
dictionary.recommendEverywhere(entity);
});
end
@ -120,7 +122,7 @@ rule "CBI.0.2: Add CBI_author with \"et al.\" RegEx (vertebrate study)"
then
entityCreationService.byRegex("\\b([A-ZÄÖÜ][^\\s\\.,]+( [A-ZÄÖÜ]{1,2}\\.?)?( ?[A-ZÄÖÜ]\\.?)?) et al\\.?", "CBI_author", EntityType.ENTITY, 1, $section)
.forEach(entity -> {
entity.redact("CBI.0.2", "Author found by \"et al\" regex", "Article 39(e)(2) of Regulation (EC) No 178/2002");
entity.redact("CBI.0.2", "Author found by \"et al\" regex", "vertebrate_study_personal_data_geolocation_article_39e2");
dictionary.recommendEverywhere(entity);
});
end
@ -137,7 +139,7 @@ rule "CBI.9.0: Redact all cells with Header Author(s) as CBI_author (non vertebr
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.0", "Author(s) found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.0", "Author(s) found", "personal_data_geolocation_article_39e3"));
end
rule "CBI.9.1: Redact all cells with Header Author as CBI_author (non vertebrate study)"
@ -150,7 +152,7 @@ rule "CBI.9.1: Redact all cells with Header Author as CBI_author (non vertebrate
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.1", "Author found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.1", "Author found", "personal_data_geolocation_article_39e3"));
end
rule "CBI.9.2: Redact all cells with Header Author(s) as CBI_author (non vertebrate study)"
@ -206,7 +208,7 @@ rule "CBI.12.1: Redact and recommend TableCell with header 'Author' or 'Author(s
then
entityCreationService.bySemanticNode($authorCell, "CBI_author", EntityType.ENTITY)
.ifPresent(authorEntity -> {
authorEntity.redact("CBI.12.1", "Redacted because it's row belongs to a vertebrate study", "Article 39(e)(3) of Regulation (EC) No 178/2002");
authorEntity.redact("CBI.12.1", "Redacted because it's row belongs to a vertebrate study", "personal_data_geolocation_article_39e3");
dictionary.addMultipleAuthorsAsRecommendation(authorEntity);
});
end
@ -224,7 +226,7 @@ rule "CBI.12.2: Redact and recommend TableCell with header 'Author' or 'Author(s
entityCreationService.bySemanticNode($authorCell, "CBI_author", EntityType.ENTITY)
.ifPresent(authorEntity -> {
authorEntity.redact("CBI.12.2", "Redacted because it's row belongs to a vertebrate study", "Article 39(e)(2) of Regulation (EC) No 178/2002");
authorEntity.redact("CBI.12.2", "Redacted because it's row belongs to a vertebrate study", "vertebrate_study_personal_data_geolocation_article_39e2");
dictionary.addMultipleAuthorsAsRecommendation(authorEntity);
});
@ -447,7 +449,6 @@ rule "CBI.18.0: Expand CBI_author entities with firstname initials"
.ifPresent(expandedEntity -> {
expandedEntity.addMatchedRules($entityToExpand.getMatchedRuleList());
$entityToExpand.remove("CBI.18.0", "Expand CBI_author entities with firstname initials");
retract($entityToExpand);
});
end
@ -461,7 +462,6 @@ rule "CBI.19.0: Expand CBI_author entities with salutation prefix"
.ifPresent(expandedEntity -> {
expandedEntity.addMatchedRules($entityToExpand.getMatchedRuleList());
$entityToExpand.remove("CBI.19.0", "Expand CBI_author entities with salutation prefix");
retract($entityToExpand);
});
end
@ -500,7 +500,7 @@ rule "CBI.20.2: Redact between \"PERFORMING LABORATORY\" and \"LABORATORY PROJEC
then
entityCreationService.betweenStrings("PERFORMING LABORATORY:", "LABORATORY PROJECT ID:", "CBI_address", EntityType.ENTITY, $section)
.forEach(laboratoryEntity -> {
laboratoryEntity.redact("CBI.20.2", "PERFORMING LABORATORY was found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
laboratoryEntity.redact("CBI.20.2", "PERFORMING LABORATORY was found", "vertebrate_study_personal_data_geolocation_article_39e2");
dictionary.recommendEverywhere(laboratoryEntity);
});
end
@ -525,7 +525,7 @@ rule "CBI.23.0: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (no
$document: Document(containsStringIgnoreCase("AUTHOR(S)"), containsAnyStringIgnoreCase("COMPLETION DATE", "STUDY COMPLETION DATE"))
then
entityCreationService.shortestBetweenAnyStringIgnoreCase(List.of("AUTHOR(S)", "AUTHOR(S):"), List.of("COMPLETION DATE", "COMPLETION DATE:", "STUDY COMPLETION DATE", "STUDY COMPLETION DATE:"), "CBI_author", EntityType.ENTITY, $document, 200)
.forEach(authorEntity -> authorEntity.redact("CBI.23.0", "AUTHOR(S) was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("CBI.23.0", "AUTHOR(S) was found", "personal_data_geolocation_article_39e3"));
end
rule "CBI.23.1: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (vertebrate study)"
@ -534,7 +534,7 @@ rule "CBI.23.1: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (ve
$document: Document(containsStringIgnoreCase("AUTHOR(S)"), containsAnyStringIgnoreCase("COMPLETION DATE", "STUDY COMPLETION DATE"))
then
entityCreationService.shortestBetweenAnyStringIgnoreCase(List.of("AUTHOR(S)", "AUTHOR(S):"), List.of("COMPLETION DATE", "COMPLETION DATE:", "STUDY COMPLETION DATE", "STUDY COMPLETION DATE:"), "CBI_author", EntityType.ENTITY, $document, 200)
.forEach(authorEntity -> authorEntity.redact("CBI.23.1", "AUTHOR(S) was found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("CBI.23.1", "AUTHOR(S) was found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -553,7 +553,7 @@ rule "PII.0.1: Redact all PII (non vertebrate study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$pii: TextEntity(type() == "PII", dictionaryEntry)
then
$pii.redact("PII.0.1", "Personal Information found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$pii.redact("PII.0.1", "Personal Information found", "personal_data_geolocation_article_39e3");
end
rule "PII.0.2: Redact all PII (vertebrate study)"
@ -561,7 +561,7 @@ rule "PII.0.2: Redact all PII (vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$pii: TextEntity(type() == "PII", dictionaryEntry)
then
$pii.redact("PII.0.2", "Personal Information found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$pii.redact("PII.0.2", "Personal Information found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
rule "PII.0.3: Redact all PII"
@ -587,7 +587,7 @@ rule "PII.1.1: Redact Emails by RegEx (Non vertebrate study)"
$section: Section(containsString("@"))
then
entityCreationService.byRegex("\\b([A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z\\-]{1,23}[A-Za-z])\\b", "PII", EntityType.ENTITY, 1, $section)
.forEach(emailEntity -> emailEntity.redact("PII.1.1", "Found by Email Regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(emailEntity -> emailEntity.redact("PII.1.1", "Found by Email Regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.1.2: Redact Emails by RegEx (vertebrate study)"
@ -596,7 +596,7 @@ rule "PII.1.2: Redact Emails by RegEx (vertebrate study)"
$section: Section(containsString("@"))
then
entityCreationService.byRegex("\\b([A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z\\-]{1,23}[A-Za-z])\\b", "PII", EntityType.ENTITY, 1, $section)
.forEach(emailEntity -> emailEntity.redact("PII.1.2", "Found by Email Regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(emailEntity -> emailEntity.redact("PII.1.2", "Found by Email Regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "PII.1.5: Redact Emails by RegEx"
@ -691,7 +691,7 @@ rule "PII.6.1: Redact line between contact keywords (non vertebrate study)"
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
)
.forEach(contactEntity -> contactEntity.redact("PII.6.1", "Found between contact keywords", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.6.1", "Found between contact keywords", "personal_data_geolocation_article_39e3"));
end
rule "PII.6.2: Redact line between contact keywords (vertebrate study)"
@ -703,7 +703,7 @@ rule "PII.6.2: Redact line between contact keywords (vertebrate study)"
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
)
.forEach(contactEntity -> contactEntity.redact("PII.6.2", "Found between contact keywords", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.6.2", "Found between contact keywords", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "PII.6.3: Redact line between contact keywords (non vertebrate study)"
@ -747,7 +747,7 @@ rule "PII.7.1: Redact contact information if applicant is found (non vertebrate
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.7.1", "Applicant information was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.7.1", "Applicant information was found", "personal_data_geolocation_article_39e3"));
end
rule "PII.7.2: Redact contact information if applicant is found (vertebrate study)"
@ -765,7 +765,7 @@ rule "PII.7.2: Redact contact information if applicant is found (vertebrate stud
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.7.2", "Applicant information was found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.7.2", "Applicant information was found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -802,7 +802,7 @@ rule "PII.8.1: Redact contact information if producer is found (non vertebrate s
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.8.1", "Producer was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.8.1", "Producer was found", "personal_data_geolocation_article_39e3"));
end
rule "PII.8.2: Redact contact information if producer is found (vertebrate study)"
@ -820,7 +820,7 @@ rule "PII.8.2: Redact contact information if producer is found (vertebrate study
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.8.2", "Producer was found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.8.2", "Producer was found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -848,7 +848,7 @@ rule "PII.11.0: Redact On behalf of Sequani Ltd.:"
$section: SuperSection(!hasTables(), containsString("On behalf of Sequani Ltd.: Name Title"))
then
entityCreationService.betweenStrings("On behalf of Sequani Ltd.: Name Title", "On behalf of", "PII", EntityType.ENTITY, $section)
.forEach(authorEntity -> authorEntity.redact("PII.11.0", "On behalf of Sequani Ltd.: Name Title was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("PII.11.0", "On behalf of Sequani Ltd.: Name Title was found", "personal_data_geolocation_article_39e3"));
end
@ -859,7 +859,7 @@ rule "PII.12.0: Expand PII entities with salutation prefix"
$entityToExpand: TextEntity(type() == "PII", anyMatch(textBefore, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*"))
then
entityCreationService.byPrefixExpansionRegex($entityToExpand, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*")
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.0", "Expanded PII with salutation prefix", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.0", "Expanded PII with salutation prefix", "personal_data_geolocation_article_39e3"));
end
rule "PII.12.1: Expand PII entities with salutation prefix"
@ -868,7 +868,7 @@ rule "PII.12.1: Expand PII entities with salutation prefix"
$entityToExpand: TextEntity(type() == "PII", anyMatch(textBefore, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*"))
then
entityCreationService.byPrefixExpansionRegex($entityToExpand, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*")
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.1", "Expanded PII with salutation prefix", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.1", "Expanded PII with salutation prefix", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -897,7 +897,7 @@ rule "ETC.2.1: Redact signatures (non vertebrate study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$signature: Image(imageType == ImageType.SIGNATURE)
then
$signature.redact("ETC.2.1", "Signature Found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$signature.redact("ETC.2.1", "Signature Found", "personal_data_geolocation_article_39e3");
end
rule "ETC.2.2: Redact signatures (vertebrate study)"
@ -905,7 +905,7 @@ rule "ETC.2.2: Redact signatures (vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$signature: Image(imageType == ImageType.SIGNATURE)
then
$signature.redact("ETC.2.2", "Signature Found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$signature.redact("ETC.2.2", "Signature Found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
rule "ETC.2.3: Redact signatures"
@ -937,7 +937,7 @@ rule "ETC.3.2: Redact logos (vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$logo: Image(imageType == ImageType.LOGO)
then
$logo.redact("ETC.3.2", "Logo Found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$logo.redact("ETC.3.2", "Logo Found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
rule "ETC.3.3: Redact logos"
@ -953,7 +953,7 @@ rule "ETC.4.0: Redact dossier dictionary entries"
when
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.redact("ETC.4.0", "Specification of impurity found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$dossierRedaction.redact("ETC.4.0", "Specification of impurity found", "personal_data_geolocation_article_39e3");
end
@ -964,7 +964,6 @@ rule "ETC.5.0: Skip dossier_redaction entries if confidentiality is 'confidentia
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.skip("ETC.5.0", "Ignore dossier_redaction when confidential");
$dossierRedaction.getIntersectingNodes().forEach(node -> update(node));
end
rule "ETC.5.1: Remove dossier_redaction entries if confidentiality is not 'confidential'"
@ -974,7 +973,6 @@ rule "ETC.5.1: Remove dossier_redaction entries if confidentiality is not 'confi
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.remove("ETC.5.1", "Remove dossier_redaction when not confidential");
retract($dossierRedaction);
end
@ -1009,7 +1007,7 @@ rule "ETC.8.0: Redact formulas (vertebrate study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$logo: Image(imageType == ImageType.FORMULA)
then
$logo.redact("ETC.8.0", "Logo Found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$logo.redact("ETC.8.0", "Logo Found", "personal_data_geolocation_article_39e3");
end
rule "ETC.8.1: Redact formulas (non vertebrate study)"
@ -1017,7 +1015,7 @@ rule "ETC.8.1: Redact formulas (non vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$logo: Image(imageType == ImageType.FORMULA)
then
$logo.redact("ETC.8.1", "Logo Found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$logo.redact("ETC.8.1", "Logo Found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
@ -1136,8 +1134,6 @@ rule "MAN.0.0: Apply manual resize redaction"
then
manualChangesApplicationService.resize($entityToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($entityToBeResized);
$entityToBeResized.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.0.1: Apply manual resize redaction"
@ -1149,8 +1145,6 @@ rule "MAN.0.1: Apply manual resize redaction"
then
manualChangesApplicationService.resizeImage($imageToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($imageToBeResized);
update($imageToBeResized.getParent());
end
@ -1161,10 +1155,8 @@ rule "MAN.1.0: Apply id removals that are valid and not in forced redactions to
$idRemoval: IdRemoval($id: annotationId, !removeFromDictionary, !removeFromAllDossiers)
$entityToBeRemoved: TextEntity(matchesAnnotationId($id))
then
$entityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($entityToBeRemoved);
$entityToBeRemoved.addManualChange($idRemoval);
retract($idRemoval);
$entityToBeRemoved.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to Image"
@ -1174,9 +1166,7 @@ rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to
$imageEntityToBeRemoved: Image($id == id)
then
$imageEntityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($imageEntityToBeRemoved);
retract($idRemoval);
update($imageEntityToBeRemoved.getParent());
end
@ -1187,9 +1177,7 @@ rule "MAN.2.0: Apply force redaction"
$force: ManualForceRedaction($id: annotationId)
$entityToForce: TextEntity(matchesAnnotationId($id))
then
$entityToForce.getManualOverwrite().addChange($force);
update($entityToForce);
$entityToForce.getIntersectingNodes().forEach(node -> update(node));
$entityToForce.addManualChange($force);
retract($force);
end
@ -1200,8 +1188,6 @@ rule "MAN.2.1: Apply force redaction to images"
$imageToForce: Image(id == $id)
then
$imageToForce.getManualOverwrite().addChange($force);
update($imageToForce);
update($imageToForce.getParent());
retract($force);
end
@ -1214,9 +1200,7 @@ rule "MAN.3.0: Apply entity recategorization"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() != $type)
then
$entityToBeRecategorized.getIntersectingNodes().forEach(node -> update(node));
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
update($entityToBeRecategorized);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -1227,7 +1211,7 @@ rule "MAN.3.1: Apply entity recategorization of same type"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() == $type)
then
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -1239,8 +1223,6 @@ rule "MAN.3.2: Apply image recategorization"
$imageToBeRecategorized: Image($id == id)
then
manualChangesApplicationService.recategorize($imageToBeRecategorized, $recategorization);
update($imageToBeRecategorized);
update($imageToBeRecategorized.getParent());
retract($recategorization);
end
@ -1261,7 +1243,6 @@ rule "MAN.4.0: Apply legal basis change"
$imageToBeRecategorized: Image($id == id)
then
$imageToBeRecategorized.getManualOverwrite().addChange($legalBasisChange);
update($imageToBeRecategorized)
retract($legalBasisChange)
end
@ -1271,8 +1252,7 @@ rule "MAN.4.1: Apply legal basis change"
$legalBasisChange: ManualLegalBasisChange($id: annotationId)
$entityToBeChanged: TextEntity(matchesAnnotationId($id))
then
$entityToBeChanged.getManualOverwrite().addChange($legalBasisChange);
update($entityToBeChanged)
$entityToBeChanged.addManualChange($legalBasisChange);
retract($legalBasisChange)
end
@ -1283,71 +1263,115 @@ rule "MAN.4.1: Apply legal basis change"
rule "X.0.0: Remove Entity contained by Entity of same type"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), !hasManualChanges())
not TextEntity(getTextRange().equals($larger.getTextRange()), type() == $type, entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY, !hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
!$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
not TextEntity(
getTextRange().equals($container.getTextRange()),
type() == $container.type(),
entityType == EntityType.DICTIONARY_REMOVAL,
engines contains Engine.DOSSIER_DICTIONARY,
!hasManualChanges()
)
then
$contained.remove("X.0.0", "remove Entity contained by Entity of same type");
retract($contained);
end
end
rule "X.0.1: Remove Entity contained by Entity of same type with manual changes"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
then
$contained.getIntersectingNodes().forEach(node -> update(node));
$contained.remove("X.0.1", "remove Entity contained by Entity of same type with manual changes");
retract($contained);
end
end
// Rule unit: X.2
rule "X.2.0: Remove Entity of type ENTITY when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.ENTITY), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.ENTITY,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
end
rule "X.2.1: Remove Entity of type HINT when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.HINT), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.HINT,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("X.2.1", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.1", "remove Entity of type HINT when contained by FALSE_POSITIVE");
end
// Rule unit: X.3
rule "X.3.0: Remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION"
rule "X.3.0: Remove RECOMMENDATION Contained by FALSE_RECOMMENDATION"
salience 64
when
$falseRecommendation: TextEntity($type: type(), entityType == EntityType.FALSE_RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($falseRecommendation), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
end
// Rule unit: X.4
rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY with same type"
salience 256
when
$entity: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(getTextRange().equals($entity.getTextRange()), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$entity.addEngines($recommendation.getEngines());
$recommendation.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
retract($recommendation);
$a.addEngines($b.getEngines());
$b.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
end
@ -1355,68 +1379,100 @@ rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY
rule "X.5.0: Remove Entity of type RECOMMENDATION when intersected by ENTITY"
salience 256
when
$entity: TextEntity((entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(intersects($entity), entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$intersection: Intersection(
$a: a,
$b: b,
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$recommendation.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
retract($recommendation);
$b.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
end
rule "X.5.1: Remove Entity of type RECOMMENDATION when contained by RECOMMENDATION"
salience 256
when
$entity: TextEntity($type: type(), entityType == EntityType.RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($entity), type() != $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$container.type() != $contained.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
end
// Rule unit: X.6
rule "X.6.0: Remove Entity of lower rank, when contained by entity of type ENTITY or HINT"
rule "X.6.0: Remove Lower Rank Entity Contained by ENTITY or HINT"
salience 32
when
$higherRank: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$lowerRank: TextEntity(containedBy($higherRank), type() != $type, dictionary.getDictionaryRank(type) < dictionary.getDictionaryRank($type), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
($container.entityType == EntityType.ENTITY || $container.entityType == EntityType.HINT),
$container.active(),
$contained.type() != $container.type(),
eval(dictionary.getDictionaryRank($contained.type()) < dictionary.getDictionaryRank($container.type())),
!$contained.hasManualChanges()
)
then
$lowerRank.getIntersectingNodes().forEach(node -> update(node));
$lowerRank.remove("X.6.0", "remove Entity of lower rank, when contained by entity of type ENTITY or HINT");
retract($lowerRank);
$contained.remove("X.6.0", "remove Entity of lower rank when contained by entity of type ENTITY or HINT");
end
rule "X.6.1: remove Entity, when contained in another entity of type ENTITY or HINT with larger text range"
rule "X.6.1: Remove Entity, when contained in another entity of type ENTITY or HINT with larger text range"
salience 32
when
$outer: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$inner: TextEntity(containedBy($outer), type() != $type, $outer.getTextRange().length > getTextRange().length(), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
($container.entityType == EntityType.ENTITY || $container.entityType == EntityType.HINT),
$container.active(),
$contained.type() != $container.type(),
eval($container.getTextRange().length() > $contained.getTextRange().length()),
!$contained.hasManualChanges()
)
then
$inner.getIntersectingNodes().forEach(node -> update(node));
$inner.remove("X.6.1", "remove Entity, when contained in another entity of type ENTITY or HINT with larger text range");
retract($inner);
end
$contained.remove("X.6.1", "remove Entity when contained in another entity of type ENTITY or HINT with larger text range");
end
// Rule unit: X.8
rule "X.8.0: Remove Entity when text range and type equals to imported Entity"
salience 257
when
$entity: TextEntity($type: type(), engines contains Engine.IMPORTED, active())
$other: TextEntity(getTextRange().equals($entity.getTextRange()), this != $entity, type() == $type, engines not contains Engine.IMPORTED)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$entity.addEngines($other.getEngines());
retract($other);
$b.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$a.addEngines($b.getEngines());
end
rule "X.8.1: Remove Entity when intersected by imported Entity"
salience 256
when
$entity: TextEntity(engines contains Engine.IMPORTED, active())
$other: TextEntity(intersects($entity), this != $entity, engines not contains Engine.IMPORTED)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.1", "remove Entity when intersected by imported Entity");
retract($other);
$b.remove("X.8.1", "remove Entity when intersected by imported Entity");
end
@ -1442,25 +1498,36 @@ rule "X.10.0: remove false positives of ai"
// Rule unit: X.11
rule "X.11.1: Remove non manual entity which intersects with a manual entity"
rule "X.11.1: Remove non-manual entity which intersects with a manual entity"
salience 64
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active())
$nonManualEntity: TextEntity(intersects($manualEntity), engines not contains Engine.MANUAL)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.MANUAL,
$a.active(),
$b.engines not contains Engine.MANUAL
)
then
$nonManualEntity.remove("X.11.1", "remove entity which intersects with a manual entity");
retract($nonManualEntity);
$b.remove("X.11.1", "remove entity which intersects with a manual entity");
end
rule "X.11.2: Remove non manual entity which are equal to manual entity"
rule "X.11.2: Remove non-manual entity which is equal to manual entity"
salience 70
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active(), $type: type())
$nonManualEntity: TextEntity(getTextRange().equals($manualEntity.getTextRange()), type() == $type, entityType == EntityType.ENTITY, !hasManualChanges(), engines not contains Engine.MANUAL)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.MANUAL,
$a.active(),
$b.entityType == EntityType.ENTITY,
!$b.hasManualChanges(),
$b.engines not contains Engine.MANUAL
)
then
$manualEntity.addEngines($nonManualEntity.getEngines());
$nonManualEntity.remove("X.11.2", "remove non manual entity which are equal to manual entity");
retract($nonManualEntity);
$a.addEngines($b.getEngines());
$b.remove("X.11.2", "remove non-manual entity which is equal to manual entity");
end
@ -1473,7 +1540,6 @@ rule "DICT.0.0: Remove Template Dictionary Entity when contained by Dossier Dict
$dictionaryRemoval: TextEntity($type: type(), entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY)
$entity: TextEntity(getTextRange().equals($dictionaryRemoval.getTextRange()), engines contains Engine.DICTIONARY, type() == $type, (entityType == EntityType.ENTITY || entityType == EntityType.HINT), !hasManualChanges())
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("DICT.0.0", "Remove Template Dictionary Entity when contained by Dossier Dictionary DICTIONARY_REMOVAL");
$entity.addEngine(Engine.DOSSIER_DICTIONARY);
end

View File

@ -18,8 +18,7 @@ import com.iqser.red.service.redaction.v1.server.model.document.TextRange;
import com.iqser.red.service.redaction.v1.server.model.document.entity.*;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType;
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.*;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Section;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Table;
@ -79,7 +78,7 @@ rule "CBI.0.1: Add CBI_author with \"et al.\" RegEx (non vertebrate study)"
then
entityCreationService.byRegex("\\b([A-ZÄÖÜ][^\\s\\.,]+( [A-ZÄÖÜ]{1,2}\\.?)?( ?[A-ZÄÖÜ]\\.?)?) et al\\.?", "CBI_author", EntityType.ENTITY, 1, $section)
.forEach(entity -> {
entity.redact("CBI.0.1", "Author found by \"et al\" regex", "Article 39(e)(3) of Regulation (EC) No 178/2002");
entity.redact("CBI.0.1", "Author found by \"et al\" regex", "personal_data_geolocation_article_39e3");
dictionary.recommendEverywhere(entity);
});
end
@ -92,7 +91,7 @@ rule "CBI.0.2: Add CBI_author with \"et al.\" RegEx (vertebrate study)"
then
entityCreationService.byRegex("\\b([A-ZÄÖÜ][^\\s\\.,]+( [A-ZÄÖÜ]{1,2}\\.?)?( ?[A-ZÄÖÜ]\\.?)?) et al\\.?", "CBI_author", EntityType.ENTITY, 1, $section)
.forEach(entity -> {
entity.redact("CBI.0.2", "Author found by \"et al\" regex", "Article 39(e)(2) of Regulation (EC) No 178/2002");
entity.redact("CBI.0.2", "Author found by \"et al\" regex", "vertebrate_study_personal_data_geolocation_article_39e2");
dictionary.recommendEverywhere(entity);
});
end
@ -102,7 +101,7 @@ rule "CBI.0.3: Redact CBI Authors (non vertebrate Study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$entity: TextEntity(type() == "CBI_author", dictionaryEntry)
then
$entity.redact("CBI.0.3", "Author found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$entity.redact("CBI.0.3", "Author found", "personal_data_geolocation_article_39e3");
end
rule "CBI.0.4: Redact CBI Authors (vertebrate Study)"
@ -110,7 +109,7 @@ rule "CBI.0.4: Redact CBI Authors (vertebrate Study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$entity: TextEntity(type() == "CBI_author", dictionaryEntry)
then
$entity.redact("CBI.0.4", "Author found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$entity.redact("CBI.0.4", "Author found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
@ -122,7 +121,7 @@ rule "PII.0.1: Redact all PII (non vertebrate study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$pii: TextEntity(type() == "PII", dictionaryEntry)
then
$pii.redact("PII.0.1", "Personal Information found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$pii.redact("PII.0.1", "Personal Information found", "personal_data_geolocation_article_39e3");
end
@ -231,8 +230,6 @@ rule "MAN.0.0: Apply manual resize redaction"
then
manualChangesApplicationService.resize($entityToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($entityToBeResized);
$entityToBeResized.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.0.1: Apply manual resize redaction"
@ -244,8 +241,6 @@ rule "MAN.0.1: Apply manual resize redaction"
then
manualChangesApplicationService.resizeImage($imageToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($imageToBeResized);
update($imageToBeResized.getParent());
end
@ -256,10 +251,8 @@ rule "MAN.1.0: Apply id removals that are valid and not in forced redactions to
$idRemoval: IdRemoval($id: annotationId, !removeFromDictionary, !removeFromAllDossiers)
$entityToBeRemoved: TextEntity(matchesAnnotationId($id))
then
$entityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($entityToBeRemoved);
$entityToBeRemoved.addManualChange($idRemoval);
retract($idRemoval);
$entityToBeRemoved.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to Image"
@ -269,9 +262,7 @@ rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to
$imageEntityToBeRemoved: Image($id == id)
then
$imageEntityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($imageEntityToBeRemoved);
retract($idRemoval);
update($imageEntityToBeRemoved.getParent());
end
@ -282,9 +273,7 @@ rule "MAN.2.0: Apply force redaction"
$force: ManualForceRedaction($id: annotationId)
$entityToForce: TextEntity(matchesAnnotationId($id))
then
$entityToForce.getManualOverwrite().addChange($force);
update($entityToForce);
$entityToForce.getIntersectingNodes().forEach(node -> update(node));
$entityToForce.addManualChange($force);
retract($force);
end
@ -295,8 +284,6 @@ rule "MAN.2.1: Apply force redaction to images"
$imageToForce: Image(id == $id)
then
$imageToForce.getManualOverwrite().addChange($force);
update($imageToForce);
update($imageToForce.getParent());
retract($force);
end
@ -309,9 +296,7 @@ rule "MAN.3.0: Apply entity recategorization"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() != $type)
then
$entityToBeRecategorized.getIntersectingNodes().forEach(node -> update(node));
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
update($entityToBeRecategorized);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -322,7 +307,7 @@ rule "MAN.3.1: Apply entity recategorization of same type"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() == $type)
then
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -343,7 +328,6 @@ rule "MAN.4.0: Apply legal basis change"
$imageToBeRecategorized: Image($id == id)
then
$imageToBeRecategorized.getManualOverwrite().addChange($legalBasisChange);
update($imageToBeRecategorized)
retract($legalBasisChange)
end
@ -353,8 +337,7 @@ rule "MAN.4.1: Apply legal basis change"
$legalBasisChange: ManualLegalBasisChange($id: annotationId)
$entityToBeChanged: TextEntity(matchesAnnotationId($id))
then
$entityToBeChanged.getManualOverwrite().addChange($legalBasisChange);
update($entityToBeChanged)
$entityToBeChanged.addManualChange($legalBasisChange);
retract($legalBasisChange)
end
@ -365,71 +348,114 @@ rule "MAN.4.1: Apply legal basis change"
rule "X.0.0: Remove Entity contained by Entity of same type"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), !hasManualChanges())
not TextEntity(getTextRange().equals($larger.getTextRange()), type() == $type, entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY, !hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
!$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
not TextEntity(
getTextRange().equals($container.getTextRange()),
type() == $container.type(),
entityType == EntityType.DICTIONARY_REMOVAL,
engines contains Engine.DOSSIER_DICTIONARY,
!hasManualChanges()
)
then
$contained.remove("X.0.0", "remove Entity contained by Entity of same type");
retract($contained);
end
end
rule "X.0.1: Remove Entity contained by Entity of same type with manual changes"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
then
$contained.getIntersectingNodes().forEach(node -> update(node));
$contained.remove("X.0.1", "remove Entity contained by Entity of same type with manual changes");
retract($contained);
end
end
// Rule unit: X.2
rule "X.2.0: Remove Entity of type ENTITY when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.ENTITY), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.ENTITY,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
end
rule "X.2.1: Remove Entity of type HINT when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.HINT), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.HINT,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("X.2.1", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.1", "remove Entity of type HINT when contained by FALSE_POSITIVE");
end
// Rule unit: X.3
rule "X.3.0: Remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION"
rule "X.3.0: Remove RECOMMENDATION Contained by FALSE_RECOMMENDATION"
salience 64
when
$falseRecommendation: TextEntity($type: type(), entityType == EntityType.FALSE_RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($falseRecommendation), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
end
// Rule unit: X.4
rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY with same type"
salience 256
when
$entity: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(getTextRange().equals($entity.getTextRange()), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$entity.addEngines($recommendation.getEngines());
$recommendation.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
retract($recommendation);
$a.addEngines($b.getEngines());
$b.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
end
@ -437,68 +463,100 @@ rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY
rule "X.5.0: Remove Entity of type RECOMMENDATION when intersected by ENTITY"
salience 256
when
$entity: TextEntity((entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(intersects($entity), entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$intersection: Intersection(
$a: a,
$b: b,
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$recommendation.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
retract($recommendation);
$b.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
end
rule "X.5.1: Remove Entity of type RECOMMENDATION when contained by RECOMMENDATION"
salience 256
when
$entity: TextEntity($type: type(), entityType == EntityType.RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($entity), type() != $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$container.type() != $contained.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
end
// Rule unit: X.6
rule "X.6.0: Remove Entity of lower rank, when contained by entity of type ENTITY or HINT"
rule "X.6.0: Remove Lower Rank Entity Contained by ENTITY or HINT"
salience 32
when
$higherRank: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$lowerRank: TextEntity(containedBy($higherRank), type() != $type, dictionary.getDictionaryRank(type) < dictionary.getDictionaryRank($type), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
($container.entityType == EntityType.ENTITY || $container.entityType == EntityType.HINT),
$container.active(),
$contained.type() != $container.type(),
eval(dictionary.getDictionaryRank($contained.type()) < dictionary.getDictionaryRank($container.type())),
!$contained.hasManualChanges()
)
then
$lowerRank.getIntersectingNodes().forEach(node -> update(node));
$lowerRank.remove("X.6.0", "remove Entity of lower rank, when contained by entity of type ENTITY or HINT");
retract($lowerRank);
$contained.remove("X.6.0", "remove Entity of lower rank when contained by entity of type ENTITY or HINT");
end
rule "X.6.1: remove Entity, when contained in another entity of type ENTITY or HINT with larger text range"
rule "X.6.1: Remove Entity, when contained in another entity of type ENTITY or HINT with larger text range"
salience 32
when
$outer: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$inner: TextEntity(containedBy($outer), type() != $type, $outer.getTextRange().length > getTextRange().length(), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
($container.entityType == EntityType.ENTITY || $container.entityType == EntityType.HINT),
$container.active(),
$contained.type() != $container.type(),
eval($container.getTextRange().length() > $contained.getTextRange().length()),
!$contained.hasManualChanges()
)
then
$inner.getIntersectingNodes().forEach(node -> update(node));
$inner.remove("X.6.1", "remove Entity, when contained in another entity of type ENTITY or HINT with larger text range");
retract($inner);
end
$contained.remove("X.6.1", "remove Entity when contained in another entity of type ENTITY or HINT with larger text range");
end
// Rule unit: X.8
rule "X.8.0: Remove Entity when text range and type equals to imported Entity"
salience 257
when
$entity: TextEntity($type: type(), engines contains Engine.IMPORTED, active())
$other: TextEntity(getTextRange().equals($entity.getTextRange()), this != $entity, type() == $type, engines not contains Engine.IMPORTED)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$entity.addEngines($other.getEngines());
retract($other);
$b.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$a.addEngines($b.getEngines());
end
rule "X.8.1: Remove Entity when intersected by imported Entity"
salience 256
when
$entity: TextEntity(engines contains Engine.IMPORTED, active())
$other: TextEntity(intersects($entity), this != $entity, engines not contains Engine.IMPORTED)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.1", "remove Entity when intersected by imported Entity");
retract($other);
$b.remove("X.8.1", "remove Entity when intersected by imported Entity");
end
@ -524,25 +582,36 @@ rule "X.10.0: remove false positives of ai"
// Rule unit: X.11
rule "X.11.1: Remove non manual entity which intersects with a manual entity"
rule "X.11.1: Remove non-manual entity which intersects with a manual entity"
salience 64
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active())
$nonManualEntity: TextEntity(intersects($manualEntity), engines not contains Engine.MANUAL)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.MANUAL,
$a.active(),
$b.engines not contains Engine.MANUAL
)
then
$nonManualEntity.remove("X.11.1", "remove entity which intersects with a manual entity");
retract($nonManualEntity);
$b.remove("X.11.1", "remove entity which intersects with a manual entity");
end
rule "X.11.2: Remove non manual entity which are equal to manual entity"
rule "X.11.2: Remove non-manual entity which is equal to manual entity"
salience 70
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active(), $type: type())
$nonManualEntity: TextEntity(getTextRange().equals($manualEntity.getTextRange()), type() == $type, entityType == EntityType.ENTITY, !hasManualChanges(), engines not contains Engine.MANUAL)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.MANUAL,
$a.active(),
$b.entityType == EntityType.ENTITY,
!$b.hasManualChanges(),
$b.engines not contains Engine.MANUAL
)
then
$manualEntity.addEngines($nonManualEntity.getEngines());
$nonManualEntity.remove("X.11.2", "remove non manual entity which are equal to manual entity");
retract($nonManualEntity);
$a.addEngines($b.getEngines());
$b.remove("X.11.2", "remove non-manual entity which is equal to manual entity");
end
@ -555,7 +624,6 @@ rule "DICT.0.0: Remove Template Dictionary Entity when contained by Dossier Dict
$dictionaryRemoval: TextEntity($type: type(), entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY)
$entity: TextEntity(getTextRange().equals($dictionaryRemoval.getTextRange()), engines contains Engine.DICTIONARY, type() == $type, (entityType == EntityType.ENTITY || entityType == EntityType.HINT), !hasManualChanges())
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("DICT.0.0", "Remove Template Dictionary Entity when contained by Dossier Dictionary DICTIONARY_REMOVAL");
$entity.addEngine(Engine.DOSSIER_DICTIONARY);
end

View File

@ -18,8 +18,7 @@ import com.iqser.red.service.redaction.v1.server.model.document.TextRange;
import com.iqser.red.service.redaction.v1.server.model.document.entity.*;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType;
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.*;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Section;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Table;
@ -310,8 +309,6 @@ rule "MAN.0.0: Apply manual resize redaction"
then
manualChangesApplicationService.resize($entityToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($entityToBeResized);
$entityToBeResized.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.0.1: Apply manual resize redaction"
@ -323,8 +320,6 @@ rule "MAN.0.1: Apply manual resize redaction"
then
manualChangesApplicationService.resizeImage($imageToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($imageToBeResized);
update($imageToBeResized.getParent());
end
@ -335,10 +330,8 @@ rule "MAN.1.0: Apply id removals that are valid and not in forced redactions to
$idRemoval: IdRemoval($id: annotationId, !removeFromDictionary, !removeFromAllDossiers)
$entityToBeRemoved: TextEntity(matchesAnnotationId($id))
then
$entityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($entityToBeRemoved);
$entityToBeRemoved.addManualChange($idRemoval);
retract($idRemoval);
$entityToBeRemoved.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to Image"
@ -348,9 +341,7 @@ rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to
$imageEntityToBeRemoved: Image($id == id)
then
$imageEntityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($imageEntityToBeRemoved);
retract($idRemoval);
update($imageEntityToBeRemoved.getParent());
end
@ -361,9 +352,7 @@ rule "MAN.2.0: Apply force redaction"
$force: ManualForceRedaction($id: annotationId)
$entityToForce: TextEntity(matchesAnnotationId($id))
then
$entityToForce.getManualOverwrite().addChange($force);
update($entityToForce);
$entityToForce.getIntersectingNodes().forEach(node -> update(node));
$entityToForce.addManualChange($force);
retract($force);
end
@ -374,8 +363,6 @@ rule "MAN.2.1: Apply force redaction to images"
$imageToForce: Image(id == $id)
then
$imageToForce.getManualOverwrite().addChange($force);
update($imageToForce);
update($imageToForce.getParent());
retract($force);
end
@ -388,9 +375,7 @@ rule "MAN.3.0: Apply entity recategorization"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() != $type)
then
$entityToBeRecategorized.getIntersectingNodes().forEach(node -> update(node));
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
update($entityToBeRecategorized);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -401,7 +386,7 @@ rule "MAN.3.1: Apply entity recategorization of same type"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() == $type)
then
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -413,8 +398,6 @@ rule "MAN.3.2: Apply image recategorization"
$imageToBeRecategorized: Image($id == id)
then
manualChangesApplicationService.recategorize($imageToBeRecategorized, $recategorization);
update($imageToBeRecategorized);
update($imageToBeRecategorized.getParent());
retract($recategorization);
end
@ -435,7 +418,6 @@ rule "MAN.4.0: Apply legal basis change"
$imageToBeRecategorized: Image($id == id)
then
$imageToBeRecategorized.getManualOverwrite().addChange($legalBasisChange);
update($imageToBeRecategorized)
retract($legalBasisChange)
end
@ -445,8 +427,7 @@ rule "MAN.4.1: Apply legal basis change"
$legalBasisChange: ManualLegalBasisChange($id: annotationId)
$entityToBeChanged: TextEntity(matchesAnnotationId($id))
then
$entityToBeChanged.getManualOverwrite().addChange($legalBasisChange);
update($entityToBeChanged)
$entityToBeChanged.addManualChange($legalBasisChange);
retract($legalBasisChange)
end
@ -457,71 +438,114 @@ rule "MAN.4.1: Apply legal basis change"
rule "X.0.0: Remove Entity contained by Entity of same type"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), !hasManualChanges())
not TextEntity(getTextRange().equals($larger.getTextRange()), type() == $type, entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY, !hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
!$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
not TextEntity(
getTextRange().equals($container.getTextRange()),
type() == $container.type(),
entityType == EntityType.DICTIONARY_REMOVAL,
engines contains Engine.DOSSIER_DICTIONARY,
!hasManualChanges()
)
then
$contained.remove("X.0.0", "remove Entity contained by Entity of same type");
retract($contained);
end
end
rule "X.0.1: Remove Entity contained by Entity of same type with manual changes"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
then
$contained.getIntersectingNodes().forEach(node -> update(node));
$contained.remove("X.0.1", "remove Entity contained by Entity of same type with manual changes");
retract($contained);
end
end
// Rule unit: X.2
rule "X.2.0: Remove Entity of type ENTITY when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.ENTITY), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.ENTITY,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
end
rule "X.2.1: Remove Entity of type HINT when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.HINT), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.HINT,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("X.2.1", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.1", "remove Entity of type HINT when contained by FALSE_POSITIVE");
end
// Rule unit: X.3
rule "X.3.0: Remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION"
rule "X.3.0: Remove RECOMMENDATION Contained by FALSE_RECOMMENDATION"
salience 64
when
$falseRecommendation: TextEntity($type: type(), entityType == EntityType.FALSE_RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($falseRecommendation), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
end
// Rule unit: X.4
rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY with same type"
salience 256
when
$entity: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(getTextRange().equals($entity.getTextRange()), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$entity.addEngines($recommendation.getEngines());
$recommendation.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
retract($recommendation);
$a.addEngines($b.getEngines());
$b.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
end
@ -529,46 +553,67 @@ rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY
rule "X.5.0: Remove Entity of type RECOMMENDATION when intersected by ENTITY"
salience 256
when
$entity: TextEntity((entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(intersects($entity), entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$intersection: Intersection(
$a: a,
$b: b,
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$recommendation.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
retract($recommendation);
$b.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
end
rule "X.5.1: Remove Entity of type RECOMMENDATION when contained by RECOMMENDATION"
salience 256
when
$entity: TextEntity($type: type(), entityType == EntityType.RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($entity), type() != $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$container.type() != $contained.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
end
// Rule unit: X.6
rule "X.6.0: Remove Entity of lower rank, when contained by entity of type ENTITY or HINT"
rule "X.6.0: Remove Lower Rank Entity Contained by ENTITY or HINT"
salience 32
when
$higherRank: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$lowerRank: TextEntity(containedBy($higherRank), type() != $type, dictionary.getDictionaryRank(type) < dictionary.getDictionaryRank($type), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
($container.entityType == EntityType.ENTITY || $container.entityType == EntityType.HINT),
$container.active(),
$contained.type() != $container.type(),
eval(dictionary.getDictionaryRank($contained.type()) < dictionary.getDictionaryRank($container.type())),
!$contained.hasManualChanges()
)
then
$lowerRank.getIntersectingNodes().forEach(node -> update(node));
$lowerRank.remove("X.6.0", "remove Entity of lower rank, when contained by entity of type ENTITY or HINT");
retract($lowerRank);
$contained.remove("X.6.0", "remove Entity of lower rank when contained by entity of type ENTITY or HINT");
end
rule "X.6.1: remove Entity, when contained in another entity of type ENTITY or HINT with larger text range"
rule "X.6.1: Remove Entity, when contained in another entity of type ENTITY or HINT with larger text range"
salience 32
when
$outer: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$inner: TextEntity(containedBy($outer), type() != $type, $outer.getTextRange().length > getTextRange().length(), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
($container.entityType == EntityType.ENTITY || $container.entityType == EntityType.HINT),
$container.active(),
$contained.type() != $container.type(),
eval($container.getTextRange().length() > $contained.getTextRange().length()),
!$contained.hasManualChanges()
)
then
$inner.getIntersectingNodes().forEach(node -> update(node));
$inner.remove("X.6.1", "remove Entity, when contained in another entity of type ENTITY or HINT with larger text range");
retract($inner);
end
$contained.remove("X.6.1", "remove Entity when contained in another entity of type ENTITY or HINT with larger text range");
end
// Rule unit: X.7
@ -586,22 +631,33 @@ rule "X.7.0: Remove all images"
rule "X.8.0: Remove Entity when text range and type equals to imported Entity"
salience 257
when
$entity: TextEntity($type: type(), engines contains Engine.IMPORTED, active())
$other: TextEntity(getTextRange().equals($entity.getTextRange()), this != $entity, type() == $type, engines not contains Engine.IMPORTED)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$entity.addEngines($other.getEngines());
retract($other);
$b.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$a.addEngines($b.getEngines());
end
rule "X.8.1: Remove Entity when intersected by imported Entity"
salience 256
when
$entity: TextEntity(engines contains Engine.IMPORTED, active())
$other: TextEntity(intersects($entity), this != $entity, engines not contains Engine.IMPORTED)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.1", "remove Entity when intersected by imported Entity");
retract($other);
$b.remove("X.8.1", "remove Entity when intersected by imported Entity");
end
@ -627,25 +683,36 @@ rule "X.10.0: remove false positives of ai"
// Rule unit: X.11
rule "X.11.1: Remove non manual entity which intersects with a manual entity"
rule "X.11.1: Remove non-manual entity which intersects with a manual entity"
salience 64
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active())
$nonManualEntity: TextEntity(intersects($manualEntity), engines not contains Engine.MANUAL)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.MANUAL,
$a.active(),
$b.engines not contains Engine.MANUAL
)
then
$nonManualEntity.remove("X.11.1", "remove entity which intersects with a manual entity");
retract($nonManualEntity);
$b.remove("X.11.1", "remove entity which intersects with a manual entity");
end
rule "X.11.2: Remove non manual entity which are equal to manual entity"
rule "X.11.2: Remove non-manual entity which is equal to manual entity"
salience 70
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active(), $type: type())
$nonManualEntity: TextEntity(getTextRange().equals($manualEntity.getTextRange()), type() == $type, entityType == EntityType.ENTITY, !hasManualChanges(), engines not contains Engine.MANUAL)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.MANUAL,
$a.active(),
$b.entityType == EntityType.ENTITY,
!$b.hasManualChanges(),
$b.engines not contains Engine.MANUAL
)
then
$manualEntity.addEngines($nonManualEntity.getEngines());
$nonManualEntity.remove("X.11.2", "remove non manual entity which are equal to manual entity");
retract($nonManualEntity);
$a.addEngines($b.getEngines());
$b.remove("X.11.2", "remove non-manual entity which is equal to manual entity");
end
@ -658,7 +725,6 @@ rule "DICT.0.0: Remove Template Dictionary Entity when contained by Dossier Dict
$dictionaryRemoval: TextEntity($type: type(), entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY)
$entity: TextEntity(getTextRange().equals($dictionaryRemoval.getTextRange()), engines contains Engine.DICTIONARY, type() == $type, (entityType == EntityType.ENTITY || entityType == EntityType.HINT), !hasManualChanges())
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("DICT.0.0", "Remove Template Dictionary Entity when contained by Dossier Dictionary DICTIONARY_REMOVAL");
$entity.addEngine(Engine.DOSSIER_DICTIONARY);
end

View File

@ -18,8 +18,7 @@ import com.iqser.red.service.redaction.v1.server.model.document.TextRange;
import com.iqser.red.service.redaction.v1.server.model.document.entity.*;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType;
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.*;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Section;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Table;
@ -210,8 +209,6 @@ rule "MAN.0.0: Apply manual resize redaction"
then
manualChangesApplicationService.resize($entityToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($entityToBeResized);
$entityToBeResized.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.0.1: Apply manual resize redaction"
@ -223,8 +220,6 @@ rule "MAN.0.1: Apply manual resize redaction"
then
manualChangesApplicationService.resizeImage($imageToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($imageToBeResized);
update($imageToBeResized.getParent());
end
@ -235,10 +230,8 @@ rule "MAN.1.0: Apply id removals that are valid and not in forced redactions to
$idRemoval: IdRemoval($id: annotationId, !removeFromDictionary, !removeFromAllDossiers)
$entityToBeRemoved: TextEntity(matchesAnnotationId($id))
then
$entityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($entityToBeRemoved);
$entityToBeRemoved.addManualChange($idRemoval);
retract($idRemoval);
$entityToBeRemoved.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to Image"
@ -248,9 +241,7 @@ rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to
$imageEntityToBeRemoved: Image($id == id)
then
$imageEntityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($imageEntityToBeRemoved);
retract($idRemoval);
update($imageEntityToBeRemoved.getParent());
end
@ -261,9 +252,7 @@ rule "MAN.2.0: Apply force redaction"
$force: ManualForceRedaction($id: annotationId)
$entityToForce: TextEntity(matchesAnnotationId($id))
then
$entityToForce.getManualOverwrite().addChange($force);
update($entityToForce);
$entityToForce.getIntersectingNodes().forEach(node -> update(node));
$entityToForce.addManualChange($force);
retract($force);
end
@ -274,8 +263,6 @@ rule "MAN.2.1: Apply force redaction to images"
$imageToForce: Image(id == $id)
then
$imageToForce.getManualOverwrite().addChange($force);
update($imageToForce);
update($imageToForce.getParent());
retract($force);
end
@ -288,9 +275,7 @@ rule "MAN.3.0: Apply entity recategorization"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() != $type)
then
$entityToBeRecategorized.getIntersectingNodes().forEach(node -> update(node));
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
update($entityToBeRecategorized);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -301,7 +286,7 @@ rule "MAN.3.1: Apply entity recategorization of same type"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() == $type)
then
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -313,8 +298,6 @@ rule "MAN.3.2: Apply image recategorization"
$imageToBeRecategorized: Image($id == id)
then
manualChangesApplicationService.recategorize($imageToBeRecategorized, $recategorization);
update($imageToBeRecategorized);
update($imageToBeRecategorized.getParent());
retract($recategorization);
end
@ -335,7 +318,6 @@ rule "MAN.4.0: Apply legal basis change"
$imageToBeRecategorized: Image($id == id)
then
$imageToBeRecategorized.getManualOverwrite().addChange($legalBasisChange);
update($imageToBeRecategorized)
retract($legalBasisChange)
end
@ -345,8 +327,7 @@ rule "MAN.4.1: Apply legal basis change"
$legalBasisChange: ManualLegalBasisChange($id: annotationId)
$entityToBeChanged: TextEntity(matchesAnnotationId($id))
then
$entityToBeChanged.getManualOverwrite().addChange($legalBasisChange);
update($entityToBeChanged)
$entityToBeChanged.addManualChange($legalBasisChange);
retract($legalBasisChange)
end
@ -357,92 +338,146 @@ rule "MAN.4.1: Apply legal basis change"
rule "X.0.0: Remove Entity contained by Entity of same type"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), !hasManualChanges())
not TextEntity(getTextRange().equals($larger.getTextRange()), type() == $type, entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY, !hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
!$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
not TextEntity(
getTextRange().equals($container.getTextRange()),
type() == $container.type(),
entityType == EntityType.DICTIONARY_REMOVAL,
engines contains Engine.DOSSIER_DICTIONARY,
!hasManualChanges()
)
then
$contained.remove("X.0.0", "remove Entity contained by Entity of same type");
retract($contained);
end
end
rule "X.0.1: Remove Entity contained by Entity of same type with manual changes"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
then
$contained.getIntersectingNodes().forEach(node -> update(node));
$contained.remove("X.0.1", "remove Entity contained by Entity of same type with manual changes");
retract($contained);
end
end
// Rule unit: X.2
rule "X.2.0: Remove Entity of type ENTITY when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.ENTITY), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.ENTITY,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
end
rule "X.2.0: Remove Entity of type ENTITY when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.ENTITY), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.ENTITY,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
end
rule "X.2.1: Remove Entity of type HINT when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.HINT), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.HINT,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("X.2.1", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.1", "remove Entity of type HINT when contained by FALSE_POSITIVE");
end
rule "X.2.1: Remove Entity of type HINT when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.HINT), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.HINT,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("X.2.1", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.1", "remove Entity of type HINT when contained by FALSE_POSITIVE");
end
// Rule unit: X.3
rule "X.3.0: Remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION"
rule "X.3.0: Remove RECOMMENDATION Contained by FALSE_RECOMMENDATION"
salience 64
when
$falseRecommendation: TextEntity($type: type(), entityType == EntityType.FALSE_RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($falseRecommendation), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
end
// Rule unit: X.4
rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY with same type"
salience 256
when
$entity: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(getTextRange().equals($entity.getTextRange()), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$entity.addEngines($recommendation.getEngines());
$recommendation.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
retract($recommendation);
$a.addEngines($b.getEngines());
$b.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
end
@ -450,46 +485,67 @@ rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY
rule "X.5.0: Remove Entity of type RECOMMENDATION when intersected by ENTITY"
salience 256
when
$entity: TextEntity((entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(intersects($entity), entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$intersection: Intersection(
$a: a,
$b: b,
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$recommendation.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
retract($recommendation);
$b.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
end
rule "X.5.1: Remove Entity of type RECOMMENDATION when contained by RECOMMENDATION"
salience 256
when
$entity: TextEntity($type: type(), entityType == EntityType.RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($entity), type() != $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$container.type() != $contained.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
end
// Rule unit: X.6
rule "X.6.0: Remove Entity of lower rank, when contained by entity of type ENTITY or HINT"
rule "X.6.0: Remove Lower Rank Entity Contained by ENTITY or HINT"
salience 32
when
$higherRank: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$lowerRank: TextEntity(containedBy($higherRank), type() != $type, dictionary.getDictionaryRank(type) < dictionary.getDictionaryRank($type), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
($container.entityType == EntityType.ENTITY || $container.entityType == EntityType.HINT),
$container.active(),
$contained.type() != $container.type(),
eval(dictionary.getDictionaryRank($contained.type()) < dictionary.getDictionaryRank($container.type())),
!$contained.hasManualChanges()
)
then
$lowerRank.getIntersectingNodes().forEach(node -> update(node));
$lowerRank.remove("X.6.0", "remove Entity of lower rank, when contained by entity of type ENTITY or HINT");
retract($lowerRank);
$contained.remove("X.6.0", "remove Entity of lower rank when contained by entity of type ENTITY or HINT");
end
rule "X.6.1: remove Entity, when contained in another entity of type ENTITY or HINT with larger text range"
rule "X.6.1: Remove Entity, when contained in another entity of type ENTITY or HINT with larger text range"
salience 32
when
$outer: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$inner: TextEntity(containedBy($outer), type() != $type, $outer.getTextRange().length > getTextRange().length(), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
($container.entityType == EntityType.ENTITY || $container.entityType == EntityType.HINT),
$container.active(),
$contained.type() != $container.type(),
eval($container.getTextRange().length() > $contained.getTextRange().length()),
!$contained.hasManualChanges()
)
then
$inner.getIntersectingNodes().forEach(node -> update(node));
$inner.remove("X.6.1", "remove Entity, when contained in another entity of type ENTITY or HINT with larger text range");
retract($inner);
end
$contained.remove("X.6.1", "remove Entity when contained in another entity of type ENTITY or HINT with larger text range");
end
// Rule unit: X.7
@ -507,22 +563,33 @@ rule "X.7.0: Remove all images"
rule "X.8.0: Remove Entity when text range and type equals to imported Entity"
salience 257
when
$entity: TextEntity($type: type(), engines contains Engine.IMPORTED, active())
$other: TextEntity(getTextRange().equals($entity.getTextRange()), this != $entity, type() == $type, engines not contains Engine.IMPORTED)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$entity.addEngines($other.getEngines());
retract($other);
$b.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$a.addEngines($b.getEngines());
end
rule "X.8.1: Remove Entity when intersected by imported Entity"
salience 256
when
$entity: TextEntity(engines contains Engine.IMPORTED, active())
$other: TextEntity(intersects($entity), this != $entity, engines not contains Engine.IMPORTED)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.1", "remove Entity when intersected by imported Entity");
retract($other);
$b.remove("X.8.1", "remove Entity when intersected by imported Entity");
end
@ -548,25 +615,36 @@ rule "X.10.0: remove false positives of ai"
// Rule unit: X.11
rule "X.11.1: Remove non manual entity which intersects with a manual entity"
rule "X.11.1: Remove non-manual entity which intersects with a manual entity"
salience 64
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active())
$nonManualEntity: TextEntity(intersects($manualEntity), engines not contains Engine.MANUAL)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.MANUAL,
$a.active(),
$b.engines not contains Engine.MANUAL
)
then
$nonManualEntity.remove("X.11.1", "remove entity which intersects with a manual entity");
retract($nonManualEntity);
$b.remove("X.11.1", "remove entity which intersects with a manual entity");
end
rule "X.11.2: Remove non manual entity which are equal to manual entity"
rule "X.11.2: Remove non-manual entity which is equal to manual entity"
salience 70
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active(), $type: type())
$nonManualEntity: TextEntity(getTextRange().equals($manualEntity.getTextRange()), type() == $type, entityType == EntityType.ENTITY, !hasManualChanges(), engines not contains Engine.MANUAL)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.MANUAL,
$a.active(),
$b.entityType == EntityType.ENTITY,
!$b.hasManualChanges(),
$b.engines not contains Engine.MANUAL
)
then
$manualEntity.addEngines($nonManualEntity.getEngines());
$nonManualEntity.remove("X.11.2", "remove non manual entity which are equal to manual entity");
retract($nonManualEntity);
$a.addEngines($b.getEngines());
$b.remove("X.11.2", "remove non-manual entity which is equal to manual entity");
end
@ -579,7 +657,6 @@ rule "DICT.0.0: Remove Template Dictionary Entity when contained by Dossier Dict
$dictionaryRemoval: TextEntity($type: type(), entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY)
$entity: TextEntity(getTextRange().equals($dictionaryRemoval.getTextRange()), engines contains Engine.DICTIONARY, type() == $type, (entityType == EntityType.ENTITY || entityType == EntityType.HINT), !hasManualChanges())
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("DICT.0.0", "Remove Template Dictionary Entity when contained by Dossier Dictionary DICTIONARY_REMOVAL");
$entity.addEngine(Engine.DOSSIER_DICTIONARY);
end

View File

@ -65,7 +65,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -121,7 +121,7 @@
"reason": "PII (Personal Identification Information) found",
"matchedRule": 12,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -325,7 +325,7 @@
"reason": "PII (Personal Identification Information) found",
"matchedRule": 12,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -381,7 +381,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -437,7 +437,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -549,7 +549,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -605,7 +605,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -661,7 +661,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -997,7 +997,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -1053,7 +1053,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "Footer",
@ -1165,7 +1165,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -1221,7 +1221,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -1277,7 +1277,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -1333,7 +1333,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -1445,7 +1445,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -1557,7 +1557,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -1613,7 +1613,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -1669,7 +1669,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -1893,7 +1893,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "Footer",
@ -2117,7 +2117,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -2285,7 +2285,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "Footer",
@ -2677,7 +2677,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -2789,7 +2789,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -2845,7 +2845,7 @@
"reason": "PII (Personal Identification Information) found",
"matchedRule": 12,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -2957,7 +2957,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "Footer",
@ -3125,7 +3125,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -3237,7 +3237,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -3349,7 +3349,7 @@
"reason": "PII (Personal Identification Information) found",
"matchedRule": 12,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -3405,7 +3405,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -3461,7 +3461,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -3629,7 +3629,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -3685,7 +3685,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "Footer",
@ -3797,7 +3797,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -3909,7 +3909,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -4021,7 +4021,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "Footer",
@ -4077,7 +4077,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -4189,7 +4189,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -4357,7 +4357,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -4413,7 +4413,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "Footer",
@ -4469,7 +4469,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -4525,7 +4525,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -4581,7 +4581,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -4637,7 +4637,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -4749,7 +4749,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "Footer",
@ -4917,7 +4917,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -5141,7 +5141,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -5253,7 +5253,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -5309,7 +5309,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -5365,7 +5365,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -5421,7 +5421,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -5477,7 +5477,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -5533,7 +5533,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -5589,7 +5589,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -5645,7 +5645,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -5757,7 +5757,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -5813,7 +5813,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -5878,7 +5878,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -5934,7 +5934,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -5990,7 +5990,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -6046,7 +6046,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -6102,7 +6102,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -6158,7 +6158,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -6214,7 +6214,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -6279,7 +6279,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -6335,7 +6335,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -6391,7 +6391,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -6456,7 +6456,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -6512,7 +6512,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -6624,7 +6624,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -6680,7 +6680,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -6801,7 +6801,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -6857,7 +6857,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -6913,7 +6913,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -6969,7 +6969,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -7025,7 +7025,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -7081,7 +7081,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -7137,7 +7137,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -7193,7 +7193,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -7249,7 +7249,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -7305,7 +7305,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -7361,7 +7361,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -7473,7 +7473,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -7529,7 +7529,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -7585,7 +7585,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -7641,7 +7641,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -7697,7 +7697,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "Footer",
@ -7753,7 +7753,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -7809,7 +7809,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -7865,7 +7865,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -7977,7 +7977,7 @@
"reason": "Published Information found",
"matchedRule": 11,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": false,
"section": "",
@ -8145,7 +8145,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "Footer",
@ -8313,7 +8313,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -8481,7 +8481,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -8705,7 +8705,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -8761,7 +8761,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -8826,7 +8826,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -8882,7 +8882,7 @@
"reason": "Author found",
"matchedRule": 1,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -8938,7 +8938,7 @@
"reason": "Address found",
"matchedRule": 2,
"rectangle": false,
"legalBasis": "Article 39(e)(3) of Regulation (EC) No 178/2002",
"legalBasis": "personal_data_geolocation_article_39e3",
"imported": false,
"redacted": true,
"section": "",
@ -9046,49 +9046,58 @@
],
"legalBasis": [
{
"name": "1.1 personal data (incl. geolocation); Article 39(e)(1)",
"description": "any other personal data except for\n a. the name and address of the applicant;\n b. the names of authors of published or publicly available studies supporting such requests; and the names of all participants and observers in meetings of the Scientific Committee and the Scientific Panels, their working groups and any other ad hoc group meeting on the subject matter.",
"reason": "Article 39(e)(3) of Regulation (EC) No 178/2002"
"name": "1.1 personal data (incl. geolocation); Article 39(e)(3)",
"description": "(Regulations (EU) 2016/679 and (EU) 2018/1725 shall apply to the processing of personal data carried out pursuant to this Regulation. Any personal data made public pursuant to Article 38 of this Regulation and this Article shall only be used to ensure the transparency of the risk assessment under this Regulation and shall not be further processed in a manner that is incompatible with these purposes, in accordance with point (b) of Article 5(1) of Regulation (EU) 2016/679 and point (b) of Article 4(1) of Regulation (EU) 2018/1725, as the case may be)",
"reason": "personal_data_geolocation_article_39e3",
"technicalName": "personal_data_geolocation_article_39e3"
},
{
"name": "1.2 vertebrate study related personal data (incl. geolocation); Article 39(e)(2)",
"description": "personal data (names and addresses) of individuals involved in testing on vertebrate studies or in obtaining toxicological information",
"reason": "Article 39(e)(2) of Regulation (EC) No 178/2002"
"reason": "Article 39(e)(2) of Regulation (EC) No 178/2002",
"technicalName": "vertebrate_study_personal_data_geolocation_article_39e2"
},
{
"name": "2. manufacturing or production process",
"description": "the manufacturing or production process, including the method and innovative aspects thereof, as well as other technical and industrial specifications inherent to that process or method, except for information which is relevant to the assessment of safety",
"reason": "manufacturing_production_process"
"reason": "Article 63(2)(a) of Regulation (EC) No 1107/2009 (making reference to Article 39 of Regulation EC No 178/2002)",
"technicalName": "manufacturing_production_process"
},
{
"name": "3. links between a producer and applicant",
"description": "commercial links between a producer or importer and the applicant or the authorisation holder, where applicable;",
"reason": "Article 63(2)(a) of Regulation (EC) No 1107/2009 (making reference to Article 39 of Regulation EC No 178/2002)"
"description": "commercial links between a producer or importer and the applicant or the authorisation holder, where applicable",
"reason": "links_producer_applicant",
"technicalName": "links_producer_applicant"
},
{
"name": "4. commercial information",
"description": "commercial information revealing sourcing, market shares or business strategy of the applicant",
"reason": "Article 63(2)(a) of Regulation (EC) No 1107/2009 (making reference to Article 39 of Regulation EC No 178/2002)"
"reason": "Article 63(2)(a) of Regulation (EC) No 1107/2009 (making reference to Article 39 of Regulation EC No 178/2002)",
"technicalName": "commercial_information"
},
{
"name": "5. quantitative composition",
"description": "quantitative composition of the subject matter of the request, except for information which is relevant to the assessment of safety",
"reason": "Article 63(2)(a) of Regulation (EC) No 1107/2009 (making reference to Article 39 of Regulation EC No 178/2002)"
"reason": "Article 63(2)(a) of Regulation (EC) No 1107/2009 (making reference to Article 39 of Regulation EC No 178/2002)",
"technicalName": "quantitative_composition"
},
{
"name": "6. specification of impurity",
"description": "the specification of impurity of the active substance and the related methods of analysis for impurities in the active substance as manufactured, except for the impurities that are considered to be toxicologically, ecotoxicologically or environmentally relevant and the related methods of analysis for such impurities",
"reason": "specification_impurity"
"reason": "Article 63(2)(b) of Regulation (EC) No 1107/2009",
"technicalName": "specification_impurity"
},
{
"name": "7. results of production batches",
"description": "results of production batches of the active substance including impurities",
"reason": "results_production_batches"
"reason": "Article 63(2)(c) of Regulation (EC) No 1107/2009",
"technicalName": "results_production_batches"
},
{
"name": "8. composition of a plant protection product",
"description": "information on the complete composition of a plant protection product",
"reason": "composition_plant_protection_product"
"reason": "Article 63(2)(d) of Regulation (EC) No 1107/2009",
"technicalName": "composition_plant_protection_product"
}
],
"dictionaryVersion": 492,

View File

@ -16,5 +16,7 @@
<logger name="org.apache.fontbox.ttf" level="ERROR"/>
<logger name="org.drools.mvel" level="ERROR"/>
<logger name="org.springframework.web.socket.config" level="WARN"/>
<logger name="org.mongodb.driver.client" level="ERROR"/>
</configuration>

View File

@ -18,8 +18,7 @@ import com.iqser.red.service.redaction.v1.server.model.document.TextRange;
import com.iqser.red.service.redaction.v1.server.model.document.entity.*;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType;
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.*;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Section;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.SuperSection;
@ -94,7 +93,7 @@ rule "CBI.0.1: Add CBI_author with \"et al.\" RegEx (non vertebrate study)"
then
entityCreationService.byRegex("\\b([A-ZÄÖÜ][^\\s\\.,]+( [A-ZÄÖÜ]{1,2}\\.?)?( ?[A-ZÄÖÜ]\\.?)?) et al\\.?", "CBI_author", EntityType.ENTITY, 1, $section)
.forEach(entity -> {
entity.redact("CBI.0.1", "Author found by \"et al\" regex", "Article 39(e)(3) of Regulation (EC) No 178/2002");
entity.redact("CBI.0.1", "Author found by \"et al\" regex", "personal_data_geolocation_article_39e3");
dictionary.recommendEverywhere(entity);
});
end
@ -107,7 +106,7 @@ rule "CBI.0.2: Add CBI_author with \"et al.\" RegEx (vertebrate study)"
then
entityCreationService.byRegex("\\b([A-ZÄÖÜ][^\\s\\.,]+( [A-ZÄÖÜ]{1,2}\\.?)?( ?[A-ZÄÖÜ]\\.?)?) et al\\.?", "CBI_author", EntityType.ENTITY, 1, $section)
.forEach(entity -> {
entity.redact("CBI.0.2", "Author found by \"et al\" regex", "Article 39(e)(2) of Regulation (EC) No 178/2002");
entity.redact("CBI.0.2", "Author found by \"et al\" regex", "vertebrate_study_personal_data_geolocation_article_39e2");
dictionary.recommendEverywhere(entity);
});
end
@ -117,7 +116,7 @@ rule "CBI.0.3: Redact CBI Authors (non vertebrate Study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$entity: TextEntity(type() == "CBI_author", dictionaryEntry)
then
$entity.apply("CBI.0.0", "Author found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$entity.apply("CBI.0.0", "Author found", "personal_data_geolocation_article_39e3");
end
rule "CBI.0.4: Redact CBI Authors (vertebrate Study)"
@ -125,7 +124,7 @@ rule "CBI.0.4: Redact CBI Authors (vertebrate Study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$entity: TextEntity(type() == "CBI_author", dictionaryEntry)
then
$entity.redact("CBI.0.4", "Author found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$entity.redact("CBI.0.4", "Author found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
@ -143,7 +142,7 @@ rule "CBI.1.1: Redact CBI Address (Vertebrate Study)"
FileAttribute(label == "Vertebrate Study", value.toLowerCase() == "yes")
$entity: TextEntity(type() == "CBI_address", dictionaryEntry)
then
$entity.redact("CBI.1.1", "Address found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$entity.redact("CBI.1.1", "Address found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
@ -168,7 +167,7 @@ rule "CBI.9.0: Redact all cells with Header Author(s) as CBI_author (non vertebr
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.0", "Author(s) found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.0", "Author(s) found", "personal_data_geolocation_article_39e3"));
end
rule "CBI.9.1: Redact all cells with Header Author as CBI_author (non vertebrate study)"
@ -181,7 +180,7 @@ rule "CBI.9.1: Redact all cells with Header Author as CBI_author (non vertebrate
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.1", "Author found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.1", "Author found", "personal_data_geolocation_article_39e3"));
end
@ -196,7 +195,7 @@ rule "CBI.10.0: Redact all cells with Header Author(s) as CBI_author (vertebrate
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.10.0", "Author(s) found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.10.0", "Author(s) found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "CBI.10.1: Redact all cells with Header Author as CBI_author (vertebrate study)"
@ -209,7 +208,7 @@ rule "CBI.10.1: Redact all cells with Header Author as CBI_author (vertebrate st
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.10.1", "Author found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.10.1", "Author found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -292,7 +291,7 @@ rule "CBI.20.2: Redact between \"PERFORMING LABORATORY\" and \"LABORATORY PROJEC
then
entityCreationService.betweenStrings("PERFORMING LABORATORY:", "LABORATORY PROJECT ID:", "CBI_address", EntityType.ENTITY, $section)
.forEach(laboratoryEntity -> {
laboratoryEntity.redact("CBI.20.2", "PERFORMING LABORATORY was found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
laboratoryEntity.redact("CBI.20.2", "PERFORMING LABORATORY was found", "vertebrate_study_personal_data_geolocation_article_39e2");
dictionary.recommendEverywhere(laboratoryEntity);
});
end
@ -305,7 +304,7 @@ rule "CBI.23.0: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (no
$document: Document(containsStringIgnoreCase("AUTHOR(S)"), containsAnyStringIgnoreCase("COMPLETION DATE", "STUDY COMPLETION DATE"))
then
entityCreationService.shortestBetweenAnyStringIgnoreCase(List.of("AUTHOR(S)", "AUTHOR(S):"), List.of("COMPLETION DATE", "COMPLETION DATE:", "STUDY COMPLETION DATE", "STUDY COMPLETION DATE:"), "CBI_author", EntityType.ENTITY, $document, 200)
.forEach(authorEntity -> authorEntity.redact("CBI.23.0", "AUTHOR(S) was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("CBI.23.0", "AUTHOR(S) was found", "personal_data_geolocation_article_39e3"));
end
rule "CBI.23.1: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (vertebrate study)"
@ -314,7 +313,7 @@ rule "CBI.23.1: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (ve
$document: Document(containsStringIgnoreCase("AUTHOR(S)"), containsAnyStringIgnoreCase("COMPLETION DATE", "STUDY COMPLETION DATE"))
then
entityCreationService.shortestBetweenAnyStringIgnoreCase(List.of("AUTHOR(S)", "AUTHOR(S):"), List.of("COMPLETION DATE", "COMPLETION DATE:", "STUDY COMPLETION DATE", "STUDY COMPLETION DATE:"), "CBI_author", EntityType.ENTITY, $document, 200)
.forEach(authorEntity -> authorEntity.redact("CBI.23.1", "AUTHOR(S) was found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("CBI.23.1", "AUTHOR(S) was found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -326,7 +325,7 @@ rule "PII.0.1: Redact all PII (non vertebrate study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$pii: TextEntity(type() == "PII", dictionaryEntry)
then
$pii.redact("PII.0.1", "Personal Information found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$pii.redact("PII.0.1", "Personal Information found", "personal_data_geolocation_article_39e3");
end
rule "PII.0.2: Redact all PII (vertebrate study)"
@ -334,7 +333,7 @@ rule "PII.0.2: Redact all PII (vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$pii: TextEntity(type() == "PII", dictionaryEntry)
then
$pii.redact("PII.0.2", "Personal Information found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$pii.redact("PII.0.2", "Personal Information found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
@ -345,7 +344,7 @@ rule "PII.1.1: Redact Emails by RegEx (Non vertebrate study)"
$section: Section(containsString("@"))
then
entityCreationService.byRegex("\\b([A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z\\-]{1,23}[A-Za-z])\\b", "PII", EntityType.ENTITY, 1, $section)
.forEach(emailEntity -> emailEntity.redact("PII.1.1", "Found by Email Regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(emailEntity -> emailEntity.redact("PII.1.1", "Found by Email Regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.1.2: Redact Emails by RegEx (vertebrate study)"
@ -354,7 +353,7 @@ rule "PII.1.2: Redact Emails by RegEx (vertebrate study)"
$section: Section(containsString("@"))
then
entityCreationService.byRegex("\\b([A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z\\-]{1,23}[A-Za-z])\\b", "PII", EntityType.ENTITY, 1, $section)
.forEach(emailEntity -> emailEntity.redact("PII.1.2", "Found by Email Regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(emailEntity -> emailEntity.redact("PII.1.2", "Found by Email Regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "PII.1.3: Redact typoed Emails with indicator"
@ -362,7 +361,7 @@ rule "PII.1.3: Redact typoed Emails with indicator"
$section: Section(containsString("@") || containsStringIgnoreCase("mail"))
then
entityCreationService.byRegexIgnoreCase("mail[:\\.\\s]{1,2}([\\w\\/\\-\\{\\(\\. ]{3,20}(@|a|f)\\s?[\\w\\/\\-\\{\\(\\. ]{3,20}(\\. \\w{2,4}\\b|\\.\\B|\\.\\w{1,4}\\b))", "PII", EntityType.ENTITY, 1, $section)
.forEach(emailEntity -> emailEntity.redact("PII.1.3", "Personal information found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(emailEntity -> emailEntity.redact("PII.1.3", "Personal information found", "personal_data_geolocation_article_39e3"));
end
@ -381,7 +380,7 @@ rule "PII.2.1: Redact Phone and Fax by RegEx (non vertebrate study)"
containsString("Fer"))
then
entityCreationService.byRegexIgnoreCase("\\b(contact|telephone|phone|ph\\.|fax|tel|ter[^\\w]|mobile|fel[^\\w]|fer[^\\w])[a-zA-Z\\s]{0,10}[:.\\s]{0,3}([\\+\\d\\(][\\s\\d\\(\\)\\-\\/\\.]{4,100}\\d)\\b", "PII", EntityType.ENTITY, 2, $section)
.forEach(contactEntity -> contactEntity.redact("PII.2.1", "Found by Phone and Fax Regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.2.1", "Found by Phone and Fax Regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.2.2: Redact Phone and Fax by RegEx (vertebrate study)"
@ -398,7 +397,7 @@ rule "PII.2.2: Redact Phone and Fax by RegEx (vertebrate study)"
containsString("Fer"))
then
entityCreationService.byRegexIgnoreCase("\\b(contact|telephone|phone|ph\\.|fax|tel|ter[^\\w]|mobile|fel[^\\w]|fer[^\\w])[a-zA-Z\\s]{0,10}[:.\\s]{0,3}([\\+\\d\\(][\\s\\d\\(\\)\\-\\/\\.]{4,100}\\d)\\b", "PII", EntityType.ENTITY, 2, $section)
.forEach(contactEntity -> contactEntity.redact("PII.2.2", "Found by Phone and Fax Regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.2.2", "Found by Phone and Fax Regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -409,7 +408,7 @@ rule "PII.3.1: Redact telephone numbers by RegEx (Non vertebrate study)"
$section: Section(!hasTables(), matchesRegex("[+]\\d{1,}"))
then
entityCreationService.byRegex("((([+]\\d{1,3} (\\d{7,12})\\b)|([+]\\d{1,3}(\\d{3,12})\\b|[+]\\d{1,3}([ -]\\(?\\d{1,6}\\)?){2,4})|[+]\\d{1,3} ?((\\d{2,6}\\)?)([ -]\\d{2,6}){1,4}))(-\\d{1,3})?\\b)", "PII", EntityType.ENTITY, 1, $section)
.forEach(entity -> entity.redact("PII.3.1", "Telephone number found by regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.3.1", "Telephone number found by regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.3.2: Redact telephone numbers by RegEx (vertebrate study)"
@ -418,7 +417,7 @@ rule "PII.3.2: Redact telephone numbers by RegEx (vertebrate study)"
$section: Section(!hasTables(), matchesRegex("[+]\\d{1,}"))
then
entityCreationService.byRegex("((([+]\\d{1,3} (\\d{7,12})\\b)|([+]\\d{1,3}(\\d{3,12})\\b|[+]\\d{1,3}([ -]\\(?\\d{1,6}\\)?){2,4})|[+]\\d{1,3} ?((\\d{2,6}\\)?)([ -]\\d{2,6}){1,4}))(-\\d{1,3})?\\b)", "PII", EntityType.ENTITY, 1, $section)
.forEach(entity -> entity.redact("PII.3.2", "Telephone number found by regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.3.2", "Telephone number found by regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "PII.3.4: Redact telephone numbers by RegEx (Non vertebrate study)"
@ -427,7 +426,7 @@ rule "PII.3.4: Redact telephone numbers by RegEx (Non vertebrate study)"
$rowCell: TableCell(matchesRegex("[+]\\d{1,}"))
then
entityCreationService.byRegex("((([+]\\d{1,3} (\\d{7,12})\\b)|([+]\\d{1,3}(\\d{3,12})\\b|[+]\\d{1,3}([ -]\\(?\\d{1,6}\\)?){2,4})|[+]\\d{1,3} ?((\\d{2,6}\\)?)([ -]\\d{2,6}){1,4}))(-\\d{1,3})?\\b)", "PII", EntityType.ENTITY, 1, $rowCell)
.forEach(entity -> entity.redact("PII.3.4", "Telephone number found by regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.3.4", "Telephone number found by regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.3.5: Redact telephone numbers by RegEx (vertebrate study)"
@ -436,7 +435,7 @@ rule "PII.3.5: Redact telephone numbers by RegEx (vertebrate study)"
$rowCell: TableCell(matchesRegex("[+]\\d{1,}"))
then
entityCreationService.byRegex("((([+]\\d{1,3} (\\d{7,12})\\b)|([+]\\d{1,3}(\\d{3,12})\\b|[+]\\d{1,3}([ -]\\(?\\d{1,6}\\)?){2,4})|[+]\\d{1,3} ?((\\d{2,6}\\)?)([ -]\\d{2,6}){1,4}))(-\\d{1,3})?\\b)", "PII", EntityType.ENTITY, 1, $rowCell)
.forEach(entity -> entity.redact("PII.3.5", "Telephone number found by regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.3.5", "Telephone number found by regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -451,7 +450,7 @@ rule "PII.5.1: Redact line after contact information keywords reduced (non verte
$section: Section(containsString($contactKeyword))
then
entityCreationService.lineAfterString($contactKeyword, "PII", EntityType.ENTITY, $section)
.forEach(contactEntity -> contactEntity.redact("PII.5.1", "Found after \"" + $contactKeyword + "\" contact keyword", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.5.1", "Found after \"" + $contactKeyword + "\" contact keyword", "personal_data_geolocation_article_39e3"));
end
rule "PII.5.2: Redact line after contact information keywords reduced (Vertebrate study)"
@ -464,7 +463,7 @@ rule "PII.5.2: Redact line after contact information keywords reduced (Vertebrat
$section: Section(containsString($contactKeyword))
then
entityCreationService.lineAfterString($contactKeyword, "PII", EntityType.ENTITY, $section)
.forEach(contactEntity -> contactEntity.redact("PII.5.2", "Found after \"" + $contactKeyword + "\" contact keyword", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.5.2", "Found after \"" + $contactKeyword + "\" contact keyword", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -478,7 +477,7 @@ rule "PII.6.1: Redact line between contact keywords (non vertebrate study)"
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
)
.forEach(contactEntity -> contactEntity.redact("PII.6.1", "Found between contact keywords", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.6.1", "Found between contact keywords", "personal_data_geolocation_article_39e3"));
end
rule "PII.6.2: Redact line between contact keywords (vertebrate study)"
@ -490,7 +489,7 @@ rule "PII.6.2: Redact line between contact keywords (vertebrate study)"
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
)
.forEach(contactEntity -> contactEntity.redact("PII.6.2", "Found between contact keywords", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.6.2", "Found between contact keywords", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -510,7 +509,7 @@ rule "PII.7.1: Redact contact information if applicant is found (non vertebrate
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.7.1", "Applicant information was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.7.1", "Applicant information was found", "personal_data_geolocation_article_39e3"));
end
rule "PII.7.2: Redact contact information if applicant is found (vertebrate study)"
@ -528,7 +527,7 @@ rule "PII.7.2: Redact contact information if applicant is found (vertebrate stud
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.7.2", "Applicant information was found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.7.2", "Applicant information was found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -548,7 +547,7 @@ rule "PII.8.1: Redact contact information if producer is found (non vertebrate s
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.8.1", "Producer was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.8.1", "Producer was found", "personal_data_geolocation_article_39e3"));
end
rule "PII.8.2: Redact contact information if producer is found (vertebrate study)"
@ -566,7 +565,7 @@ rule "PII.8.2: Redact contact information if producer is found (vertebrate study
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.8.2", "Producer was found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.8.2", "Producer was found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -577,7 +576,7 @@ rule "PII.10.0: Redact study director abbreviation (non vertebrate study)"
$section: Section(containsString("KATH") || containsString("BECH") || containsString("KML"))
then
entityCreationService.byRegexIgnoreCase("((KATH)|(BECH)|(KML)) ?(\\d{4})","PII", EntityType.ENTITY, 1, $section)
.forEach(entity -> entity.redact("PII.10.0", "Personal information found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.10.0", "Personal information found", "personal_data_geolocation_article_39e3"));
end
rule "PII.10.1: Redact study director abbreviation (vertebrate study)"
@ -586,7 +585,7 @@ rule "PII.10.1: Redact study director abbreviation (vertebrate study)"
$section: Section(containsString("KATH") || containsString("BECH") || containsString("KML"))
then
entityCreationService.byRegexIgnoreCase("((KATH)|(BECH)|(KML)) ?(\\d{4})","PII", EntityType.ENTITY, 1, $section)
.forEach(entity -> entity.redact("PII.10.1", "Personal information found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.10.1", "Personal information found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -596,7 +595,7 @@ rule "PII.11.0: Redact On behalf of Sequani Ltd.:"
$section: SuperSection(!hasTables(), containsString("On behalf of Sequani Ltd.: Name Title"))
then
entityCreationService.betweenStrings("On behalf of Sequani Ltd.: Name Title", "On behalf of", "PII", EntityType.ENTITY, $section)
.forEach(authorEntity -> authorEntity.redact("PII.11.0", "On behalf of Sequani Ltd.: Name Title was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("PII.11.0", "On behalf of Sequani Ltd.: Name Title was found", "personal_data_geolocation_article_39e3"));
end
@ -607,7 +606,7 @@ rule "PII.12.0: Expand PII entities with salutation prefix"
$entityToExpand: TextEntity(type() == "PII", anyMatch(textBefore, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*"))
then
entityCreationService.byPrefixExpansionRegex($entityToExpand, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*")
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.0", "Expanded PII with salutation prefix", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.0", "Expanded PII with salutation prefix", "personal_data_geolocation_article_39e3"));
end
rule "PII.12.1: Expand PII entities with salutation prefix"
@ -616,7 +615,7 @@ rule "PII.12.1: Expand PII entities with salutation prefix"
$entityToExpand: TextEntity(type() == "PII", anyMatch(textBefore, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*"))
then
entityCreationService.byPrefixExpansionRegex($entityToExpand, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*")
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.1", "Expanded PII with salutation prefix", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.1", "Expanded PII with salutation prefix", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -638,7 +637,7 @@ rule "ETC.2.1: Redact signatures (non vertebrate study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$signature: Image(imageType == ImageType.SIGNATURE)
then
$signature.redact("ETC.2.1", "Signature Found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$signature.redact("ETC.2.1", "Signature Found", "personal_data_geolocation_article_39e3");
end
rule "ETC.2.2: Redact signatures (vertebrate study)"
@ -646,7 +645,7 @@ rule "ETC.2.2: Redact signatures (vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$signature: Image(imageType == ImageType.SIGNATURE)
then
$signature.redact("ETC.2.2", "Signature Found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$signature.redact("ETC.2.2", "Signature Found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
@ -664,7 +663,7 @@ rule "ETC.3.2: Redact logos (vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$logo: Image(imageType == ImageType.LOGO)
then
$logo.redact("ETC.3.2", "Logo Found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$logo.redact("ETC.3.2", "Logo Found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
@ -723,8 +722,6 @@ rule "MAN.0.0: Apply manual resize redaction"
then
manualChangesApplicationService.resize($entityToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($entityToBeResized);
$entityToBeResized.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.0.1: Apply manual resize redaction"
@ -736,8 +733,6 @@ rule "MAN.0.1: Apply manual resize redaction"
then
manualChangesApplicationService.resizeImage($imageToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($imageToBeResized);
update($imageToBeResized.getParent());
end
@ -748,10 +743,8 @@ rule "MAN.1.0: Apply id removals that are valid and not in forced redactions to
$idRemoval: IdRemoval($id: annotationId, !removeFromDictionary, !removeFromAllDossiers)
$entityToBeRemoved: TextEntity(matchesAnnotationId($id))
then
$entityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($entityToBeRemoved);
$entityToBeRemoved.addManualChange($idRemoval);
retract($idRemoval);
$entityToBeRemoved.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to Image"
@ -761,9 +754,7 @@ rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to
$imageEntityToBeRemoved: Image($id == id)
then
$imageEntityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($imageEntityToBeRemoved);
retract($idRemoval);
update($imageEntityToBeRemoved.getParent());
end
@ -774,9 +765,7 @@ rule "MAN.2.0: Apply force redaction"
$force: ManualForceRedaction($id: annotationId)
$entityToForce: TextEntity(matchesAnnotationId($id))
then
$entityToForce.getManualOverwrite().addChange($force);
update($entityToForce);
$entityToForce.getIntersectingNodes().forEach(node -> update(node));
$entityToForce.addManualChange($force);
retract($force);
end
@ -787,8 +776,6 @@ rule "MAN.2.1: Apply force redaction to images"
$imageToForce: Image(id == $id)
then
$imageToForce.getManualOverwrite().addChange($force);
update($imageToForce);
update($imageToForce.getParent());
retract($force);
end
@ -801,9 +788,7 @@ rule "MAN.3.0: Apply entity recategorization"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() != $type)
then
$entityToBeRecategorized.getIntersectingNodes().forEach(node -> update(node));
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
update($entityToBeRecategorized);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -814,7 +799,7 @@ rule "MAN.3.1: Apply entity recategorization of same type"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() == $type)
then
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -826,8 +811,6 @@ rule "MAN.3.2: Apply image recategorization"
$imageToBeRecategorized: Image($id == id)
then
manualChangesApplicationService.recategorize($imageToBeRecategorized, $recategorization);
update($imageToBeRecategorized);
update($imageToBeRecategorized.getParent());
retract($recategorization);
end
@ -848,7 +831,6 @@ rule "MAN.4.0: Apply legal basis change"
$imageToBeRecategorized: Image($id == id)
then
$imageToBeRecategorized.getManualOverwrite().addChange($legalBasisChange);
update($imageToBeRecategorized)
retract($legalBasisChange)
end
@ -858,8 +840,7 @@ rule "MAN.4.1: Apply legal basis change"
$legalBasisChange: ManualLegalBasisChange($id: annotationId)
$entityToBeChanged: TextEntity(matchesAnnotationId($id))
then
$entityToBeChanged.getManualOverwrite().addChange($legalBasisChange);
update($entityToBeChanged)
$entityToBeChanged.addManualChange($legalBasisChange);
retract($legalBasisChange)
end
@ -870,71 +851,114 @@ rule "MAN.4.1: Apply legal basis change"
rule "X.0.0: Remove Entity contained by Entity of same type"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), !hasManualChanges())
not TextEntity(getTextRange().equals($larger.getTextRange()), type() == $type, entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY, !hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
!$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
not TextEntity(
getTextRange().equals($container.getTextRange()),
type() == $container.type(),
entityType == EntityType.DICTIONARY_REMOVAL,
engines contains Engine.DOSSIER_DICTIONARY,
!hasManualChanges()
)
then
$contained.remove("X.0.0", "remove Entity contained by Entity of same type");
retract($contained);
end
end
rule "X.0.1: Remove Entity contained by Entity of same type with manual changes"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
then
$contained.getIntersectingNodes().forEach(node -> update(node));
$contained.remove("X.0.1", "remove Entity contained by Entity of same type with manual changes");
retract($contained);
end
end
// Rule unit: X.2
rule "X.2.0: Remove Entity of type ENTITY when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.ENTITY), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.ENTITY,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
end
rule "X.2.1: Remove Entity of type HINT when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.HINT), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.HINT,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("X.2.1", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.1", "remove Entity of type HINT when contained by FALSE_POSITIVE");
end
// Rule unit: X.3
rule "X.3.0: Remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION"
rule "X.3.0: Remove RECOMMENDATION Contained by FALSE_RECOMMENDATION"
salience 64
when
$falseRecommendation: TextEntity($type: type(), entityType == EntityType.FALSE_RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($falseRecommendation), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
end
// Rule unit: X.4
rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY with same type"
salience 256
when
$entity: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(getTextRange().equals($entity.getTextRange()), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$entity.addEngines($recommendation.getEngines());
$recommendation.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
retract($recommendation);
$a.addEngines($b.getEngines());
$b.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
end
@ -942,68 +966,100 @@ rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY
rule "X.5.0: Remove Entity of type RECOMMENDATION when intersected by ENTITY"
salience 256
when
$entity: TextEntity((entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(intersects($entity), entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$intersection: Intersection(
$a: a,
$b: b,
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$recommendation.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
retract($recommendation);
$b.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
end
rule "X.5.1: Remove Entity of type RECOMMENDATION when contained by RECOMMENDATION"
salience 256
when
$entity: TextEntity($type: type(), entityType == EntityType.RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($entity), type() != $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$container.type() != $contained.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
end
// Rule unit: X.6
rule "X.6.0: Remove Entity of lower rank, when contained by entity of type ENTITY or HINT"
rule "X.6.0: Remove Lower Rank Entity Contained by ENTITY or HINT"
salience 32
when
$higherRank: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$lowerRank: TextEntity(containedBy($higherRank), type() != $type, dictionary.getDictionaryRank(type) < dictionary.getDictionaryRank($type), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
($container.entityType == EntityType.ENTITY || $container.entityType == EntityType.HINT),
$container.active(),
$contained.type() != $container.type(),
eval(dictionary.getDictionaryRank($contained.type()) < dictionary.getDictionaryRank($container.type())),
!$contained.hasManualChanges()
)
then
$lowerRank.getIntersectingNodes().forEach(node -> update(node));
$lowerRank.remove("X.6.0", "remove Entity of lower rank, when contained by entity of type ENTITY or HINT");
retract($lowerRank);
$contained.remove("X.6.0", "remove Entity of lower rank when contained by entity of type ENTITY or HINT");
end
rule "X.6.1: remove Entity, when contained in another entity of type ENTITY or HINT with larger text range"
rule "X.6.1: Remove Entity, when contained in another entity of type ENTITY or HINT with larger text range"
salience 32
when
$outer: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$inner: TextEntity(containedBy($outer), type() != $type, $outer.getTextRange().length > getTextRange().length(), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
($container.entityType == EntityType.ENTITY || $container.entityType == EntityType.HINT),
$container.active(),
$contained.type() != $container.type(),
eval($container.getTextRange().length() > $contained.getTextRange().length()),
!$contained.hasManualChanges()
)
then
$inner.getIntersectingNodes().forEach(node -> update(node));
$inner.remove("X.6.1", "remove Entity, when contained in another entity of type ENTITY or HINT with larger text range");
retract($inner);
end
$contained.remove("X.6.1", "remove Entity when contained in another entity of type ENTITY or HINT with larger text range");
end
// Rule unit: X.8
rule "X.8.0: Remove Entity when text range and type equals to imported Entity"
salience 257
when
$entity: TextEntity($type: type(), engines contains Engine.IMPORTED, active())
$other: TextEntity(getTextRange().equals($entity.getTextRange()), this != $entity, type() == $type, engines not contains Engine.IMPORTED)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$entity.addEngines($other.getEngines());
retract($other);
$b.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$a.addEngines($b.getEngines());
end
rule "X.8.1: Remove Entity when intersected by imported Entity"
salience 256
when
$entity: TextEntity(engines contains Engine.IMPORTED, active())
$other: TextEntity(intersects($entity), this != $entity, engines not contains Engine.IMPORTED)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.1", "remove Entity when intersected by imported Entity");
retract($other);
$b.remove("X.8.1", "remove Entity when intersected by imported Entity");
end
@ -1029,25 +1085,36 @@ rule "X.10.0: remove false positives of ai"
// Rule unit: X.11
rule "X.11.1: Remove non manual entity which intersects with a manual entity"
rule "X.11.1: Remove non-manual entity which intersects with a manual entity"
salience 64
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active())
$nonManualEntity: TextEntity(intersects($manualEntity), engines not contains Engine.MANUAL)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.MANUAL,
$a.active(),
$b.engines not contains Engine.MANUAL
)
then
$nonManualEntity.remove("X.11.1", "remove entity which intersects with a manual entity");
retract($nonManualEntity);
$b.remove("X.11.1", "remove entity which intersects with a manual entity");
end
rule "X.11.2: Remove non manual entity which are equal to manual entity"
rule "X.11.2: Remove non-manual entity which is equal to manual entity"
salience 70
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active(), $type: type())
$nonManualEntity: TextEntity(getTextRange().equals($manualEntity.getTextRange()), type() == $type, entityType == EntityType.ENTITY, !hasManualChanges(), engines not contains Engine.MANUAL)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.MANUAL,
$a.active(),
$b.entityType == EntityType.ENTITY,
!$b.hasManualChanges(),
$b.engines not contains Engine.MANUAL
)
then
$manualEntity.addEngines($nonManualEntity.getEngines());
$nonManualEntity.remove("X.11.2", "remove non manual entity which are equal to manual entity");
retract($nonManualEntity);
$a.addEngines($b.getEngines());
$b.remove("X.11.2", "remove non-manual entity which is equal to manual entity");
end
@ -1060,7 +1127,6 @@ rule "DICT.0.0: Remove Template Dictionary Entity when contained by Dossier Dict
$dictionaryRemoval: TextEntity($type: type(), entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY)
$entity: TextEntity(getTextRange().equals($dictionaryRemoval.getTextRange()), engines contains Engine.DICTIONARY, type() == $type, (entityType == EntityType.ENTITY || entityType == EntityType.HINT), !hasManualChanges())
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("DICT.0.0", "Remove Template Dictionary Entity when contained by Dossier Dictionary DICTIONARY_REMOVAL");
$entity.addEngine(Engine.DOSSIER_DICTIONARY);
end

View File

@ -18,8 +18,7 @@ import com.iqser.red.service.redaction.v1.server.model.document.TextRange;
import com.iqser.red.service.redaction.v1.server.model.document.entity.*;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType;
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.*;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Section;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.SuperSection;
@ -118,7 +117,7 @@ rule "CBI.0.1: Add CBI_author with \"et al.\" RegEx (non vertebrate study)"
then
entityCreationService.byRegex("\\b([A-ZÄÖÜ][^\\s\\.,]+( [A-ZÄÖÜ]{1,2}\\.?)?( ?[A-ZÄÖÜ]\\.?)?) et al\\.?", "CBI_author", EntityType.ENTITY, 1, $section)
.forEach(entity -> {
entity.redact("CBI.0.1", "Author found by \"et al\" regex", "Article 39(e)(3) of Regulation (EC) No 178/2002");
entity.redact("CBI.0.1", "Author found by \"et al\" regex", "personal_data_geolocation_article_39e3");
dictionary.recommendEverywhere(entity);
});
end
@ -131,7 +130,7 @@ rule "CBI.0.2: Add CBI_author with \"et al.\" RegEx (vertebrate study)"
then
entityCreationService.byRegex("\\b([A-ZÄÖÜ][^\\s\\.,]+( [A-ZÄÖÜ]{1,2}\\.?)?( ?[A-ZÄÖÜ]\\.?)?) et al\\.?", "CBI_author", EntityType.ENTITY, 1, $section)
.forEach(entity -> {
entity.redact("CBI.0.2", "Author found by \"et al\" regex", "Article 39(e)(2) of Regulation (EC) No 178/2002");
entity.redact("CBI.0.2", "Author found by \"et al\" regex", "vertebrate_study_personal_data_geolocation_article_39e2");
dictionary.recommendEverywhere(entity);
});
end
@ -141,7 +140,7 @@ rule "CBI.0.3: Redact CBI Authors (non vertebrate Study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$entity: TextEntity(type() == "CBI_author", dictionaryEntry)
then
$entity.redact("CBI.0.3", "Author found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$entity.redact("CBI.0.3", "Author found", "personal_data_geolocation_article_39e3");
end
rule "CBI.0.4: Redact CBI Authors (vertebrate Study)"
@ -149,7 +148,7 @@ rule "CBI.0.4: Redact CBI Authors (vertebrate Study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$entity: TextEntity(type() == "CBI_author", dictionaryEntry)
then
$entity.redact("CBI.0.4", "Author found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$entity.redact("CBI.0.4", "Author found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
@ -167,7 +166,7 @@ rule "CBI.1.1: Redact CBI Address (vertebrate Study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$entity: TextEntity(type() == "CBI_address", dictionaryEntry)
then
$entity.redact("CBI.1.1", "Address found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$entity.redact("CBI.1.1", "Address found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
@ -232,7 +231,7 @@ rule "CBI.9.0: Redact all cells with Header Author(s) as CBI_author (non vertebr
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.0", "Author(s) found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.0", "Author(s) found", "personal_data_geolocation_article_39e3"));
end
rule "CBI.9.1: Redact all cells with Header Author as CBI_author (non vertebrate study)"
@ -245,7 +244,7 @@ rule "CBI.9.1: Redact all cells with Header Author as CBI_author (non vertebrate
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.1", "Author found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.9.1", "Author found", "personal_data_geolocation_article_39e3"));
end
rule "CBI.9.2: Redact all cells with Header Author(s) as CBI_author (non vertebrate study)"
@ -285,7 +284,7 @@ rule "CBI.10.0: Redact all cells with Header Author(s) as CBI_author (vertebrate
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.10.0", "Author(s) found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.10.0", "Author(s) found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "CBI.10.1: Redact all cells with Header Author as CBI_author (vertebrate study)"
@ -298,7 +297,7 @@ rule "CBI.10.1: Redact all cells with Header Author as CBI_author (vertebrate st
.map(tableCell -> entityCreationService.bySemanticNode(tableCell, "CBI_author", EntityType.ENTITY))
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(redactionEntity -> redactionEntity.redact("CBI.10.1", "Author found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(redactionEntity -> redactionEntity.redact("CBI.10.1", "Author found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "CBI.10.2: Redact all cells with Header Author(s) as CBI_author (vertebrate study)"
@ -367,7 +366,7 @@ rule "CBI.12.1: Redact and recommend TableCell with header 'Author' or 'Author(s
then
entityCreationService.bySemanticNode($authorCell, "CBI_author", EntityType.ENTITY)
.ifPresent(authorEntity -> {
authorEntity.redact("CBI.12.1", "Redacted because it's row belongs to a vertebrate study", "Article 39(e)(3) of Regulation (EC) No 178/2002");
authorEntity.redact("CBI.12.1", "Redacted because it's row belongs to a vertebrate study", "personal_data_geolocation_article_39e3");
dictionary.addMultipleAuthorsAsRecommendation(authorEntity);
});
end
@ -385,7 +384,7 @@ rule "CBI.12.2: Redact and recommend TableCell with header 'Author' or 'Author(s
entityCreationService.bySemanticNode($authorCell, "CBI_author", EntityType.ENTITY)
.ifPresent(authorEntity -> {
authorEntity.redact("CBI.12.2", "Redacted because it's row belongs to a vertebrate study", "Article 39(e)(2) of Regulation (EC) No 178/2002");
authorEntity.redact("CBI.12.2", "Redacted because it's row belongs to a vertebrate study", "vertebrate_study_personal_data_geolocation_article_39e2");
dictionary.addMultipleAuthorsAsRecommendation(authorEntity);
});
@ -541,7 +540,6 @@ rule "CBI.13.0: Ignore CBI Address recommendations"
$entity: TextEntity(type() == "CBI_address", entityType == EntityType.RECOMMENDATION)
then
$entity.ignore("CBI.13.0", "Ignore CBI Address Recommendations");
retract($entity)
end
// from CBI.3.0
@ -775,7 +773,6 @@ rule "CBI.18.0: Expand CBI_author entities with firstname initials"
.ifPresent(expandedEntity -> {
expandedEntity.addMatchedRules($entityToExpand.getMatchedRuleList());
$entityToExpand.remove("CBI.18.0", "Expand CBI_author entities with firstname initials");
retract($entityToExpand);
});
end
@ -789,7 +786,6 @@ rule "CBI.19.0: Expand CBI_author entities with salutation prefix"
.ifPresent(expandedEntity -> {
expandedEntity.addMatchedRules($entityToExpand.getMatchedRuleList());
$entityToExpand.remove("CBI.19.0", "Expand CBI_author entities with salutation prefix");
retract($entityToExpand);
});
end
@ -828,7 +824,7 @@ rule "CBI.20.2: Redact between \"PERFORMING LABORATORY\" and \"LABORATORY PROJEC
then
entityCreationService.betweenStrings("PERFORMING LABORATORY:", "LABORATORY PROJECT ID:", "CBI_address", EntityType.ENTITY, $section)
.forEach(laboratoryEntity -> {
laboratoryEntity.redact("CBI.20.2", "PERFORMING LABORATORY was found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
laboratoryEntity.redact("CBI.20.2", "PERFORMING LABORATORY was found", "vertebrate_study_personal_data_geolocation_article_39e2");
dictionary.recommendEverywhere(laboratoryEntity);
});
end
@ -891,7 +887,7 @@ rule "CBI.21.2: Redact short Authors section (non vertebrate study)"
then
entityCreationService.byRegexIgnoreCase("(?<=author\\(?s\\)?\\s\\n?)([\\p{Lu}\\p{L} ]{5,15}(,|\\n)?){1,3}", "CBI_author", EntityType.ENTITY, $section)
.forEach(entity -> {
entity.redact("CBI.21.2", "AUTHOR(S) was found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
entity.redact("CBI.21.2", "AUTHOR(S) was found", "personal_data_geolocation_article_39e3");
});
end
@ -903,7 +899,7 @@ rule "CBI.21.3: Redact short Authors section (vertebrate study)"
then
entityCreationService.byRegexIgnoreCase("(?<=author\\(?s\\)?\\s\\n?)([\\p{Lu}\\p{L} ]{5,15}(,|\\n)?){1,3}", "CBI_author", EntityType.ENTITY, $section)
.forEach(entity -> {
entity.redact("CBI.21.3", "AUTHOR(S) was found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
entity.redact("CBI.21.3", "AUTHOR(S) was found", "vertebrate_study_personal_data_geolocation_article_39e2");
});
end
@ -927,7 +923,7 @@ rule "CBI.23.0: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (no
$document: Document(containsStringIgnoreCase("AUTHOR(S)"), containsAnyStringIgnoreCase("COMPLETION DATE", "STUDY COMPLETION DATE"))
then
entityCreationService.shortestBetweenAnyStringIgnoreCase(List.of("AUTHOR(S)", "AUTHOR(S):"), List.of("COMPLETION DATE", "COMPLETION DATE:", "STUDY COMPLETION DATE", "STUDY COMPLETION DATE:"), "CBI_author", EntityType.ENTITY, $document, 200)
.forEach(authorEntity -> authorEntity.redact("CBI.23.0", "AUTHOR(S) was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("CBI.23.0", "AUTHOR(S) was found", "personal_data_geolocation_article_39e3"));
end
rule "CBI.23.1: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (vertebrate study)"
@ -936,7 +932,7 @@ rule "CBI.23.1: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (ve
$document: Document(containsStringIgnoreCase("AUTHOR(S)"), containsAnyStringIgnoreCase("COMPLETION DATE", "STUDY COMPLETION DATE"))
then
entityCreationService.shortestBetweenAnyStringIgnoreCase(List.of("AUTHOR(S)", "AUTHOR(S):"), List.of("COMPLETION DATE", "COMPLETION DATE:", "STUDY COMPLETION DATE", "STUDY COMPLETION DATE:"), "CBI_author", EntityType.ENTITY, $document, 200)
.forEach(authorEntity -> authorEntity.redact("CBI.23.1", "AUTHOR(S) was found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("CBI.23.1", "AUTHOR(S) was found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -955,7 +951,7 @@ rule "PII.0.1: Redact all PII (non vertebrate study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$pii: TextEntity(type() == "PII", dictionaryEntry)
then
$pii.redact("PII.0.1", "Personal Information found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$pii.redact("PII.0.1", "Personal Information found", "personal_data_geolocation_article_39e3");
end
rule "PII.0.2: Redact all PII (vertebrate study)"
@ -963,7 +959,7 @@ rule "PII.0.2: Redact all PII (vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$pii: TextEntity(type() == "PII", dictionaryEntry)
then
$pii.redact("PII.0.2", "Personal Information found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$pii.redact("PII.0.2", "Personal Information found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
rule "PII.0.3: Redact all PII"
@ -989,7 +985,7 @@ rule "PII.1.1: Redact Emails by RegEx (Non vertebrate study)"
$section: Section(containsString("@"))
then
entityCreationService.byRegex("\\b([A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z\\-]{1,23}[A-Za-z])\\b", "PII", EntityType.ENTITY, 1, $section)
.forEach(emailEntity -> emailEntity.redact("PII.1.1", "Found by Email Regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(emailEntity -> emailEntity.redact("PII.1.1", "Found by Email Regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.1.2: Redact Emails by RegEx (vertebrate study)"
@ -998,7 +994,7 @@ rule "PII.1.2: Redact Emails by RegEx (vertebrate study)"
$section: Section(containsString("@"))
then
entityCreationService.byRegex("\\b([A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z\\-]{1,23}[A-Za-z])\\b", "PII", EntityType.ENTITY, 1, $section)
.forEach(emailEntity -> emailEntity.redact("PII.1.2", "Found by Email Regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(emailEntity -> emailEntity.redact("PII.1.2", "Found by Email Regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "PII.1.3: Redact typoed Emails with indicator"
@ -1006,7 +1002,7 @@ rule "PII.1.3: Redact typoed Emails with indicator"
$section: Section(containsString("@") || containsStringIgnoreCase("mail"))
then
entityCreationService.byRegexIgnoreCase("mail[:\\.\\s]{1,2}([\\w\\/\\-\\{\\(\\. ]{3,20}(@|a|f)\\s?[\\w\\/\\-\\{\\(\\. ]{3,20}(\\. \\w{2,4}\\b|\\.\\B|\\.\\w{1,4}\\b))", "PII", EntityType.ENTITY, 1, $section)
.forEach(emailEntity -> emailEntity.redact("PII.1.3", "Personal information found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(emailEntity -> emailEntity.redact("PII.1.3", "Personal information found", "personal_data_geolocation_article_39e3"));
end
rule "PII.1.4: Redact typoed Emails with indicator"
@ -1066,7 +1062,7 @@ rule "PII.2.1: Redact Phone and Fax by RegEx (non vertebrate study)"
containsString("Fer"))
then
entityCreationService.byRegexIgnoreCase("\\b(contact|telephone|phone|ph\\.|fax|tel|ter[^\\w]|mobile|fel[^\\w]|fer[^\\w])[a-zA-Z\\s]{0,10}[:.\\s]{0,3}([\\+\\d\\(][\\s\\d\\(\\)\\-\\/\\.]{4,100}\\d)\\b", "PII", EntityType.ENTITY, 2, $section)
.forEach(contactEntity -> contactEntity.redact("PII.2.1", "Found by Phone and Fax Regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.2.1", "Found by Phone and Fax Regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.2.2: Redact Phone and Fax by RegEx (vertebrate study)"
@ -1083,7 +1079,7 @@ rule "PII.2.2: Redact Phone and Fax by RegEx (vertebrate study)"
containsString("Fer"))
then
entityCreationService.byRegexIgnoreCase("\\b(contact|telephone|phone|ph\\.|fax|tel|ter[^\\w]|mobile|fel[^\\w]|fer[^\\w])[a-zA-Z\\s]{0,10}[:.\\s]{0,3}([\\+\\d\\(][\\s\\d\\(\\)\\-\\/\\.]{4,100}\\d)\\b", "PII", EntityType.ENTITY, 2, $section)
.forEach(contactEntity -> contactEntity.redact("PII.2.2", "Found by Phone and Fax Regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.2.2", "Found by Phone and Fax Regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "PII.2.3: Redact phone numbers without indicators"
@ -1091,7 +1087,7 @@ rule "PII.2.3: Redact phone numbers without indicators"
$section: Section(containsString("+"))
then
entityCreationService.byRegex("(\\+[\\dO]{1,2} )(\\([\\dO]{1,3}\\))?[\\d\\-O ]{8,15}", "PII", EntityType.ENTITY, $section)
.forEach(entity -> entity.redact("PII.2.3", "Personal information found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.2.3", "Personal information found", "personal_data_geolocation_article_39e3"));
end
@ -1110,7 +1106,7 @@ rule "PII.3.1: Redact telephone numbers by RegEx (Non vertebrate study)"
$section: Section(!hasTables(), matchesRegex("[+]\\d{1,}"))
then
entityCreationService.byRegex("((([+]\\d{1,3} (\\d{7,12})\\b)|([+]\\d{1,3}(\\d{3,12})\\b|[+]\\d{1,3}([ -]\\(?\\d{1,6}\\)?){2,4})|[+]\\d{1,3} ?((\\d{2,6}\\)?)([ -]\\d{2,6}){1,4}))(-\\d{1,3})?\\b)", "PII", EntityType.ENTITY, 1, $section)
.forEach(entity -> entity.redact("PII.3.1", "Telephone number found by regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.3.1", "Telephone number found by regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.3.2: Redact telephone numbers by RegEx (vertebrate study)"
@ -1119,7 +1115,7 @@ rule "PII.3.2: Redact telephone numbers by RegEx (vertebrate study)"
$section: Section(!hasTables(), matchesRegex("[+]\\d{1,}"))
then
entityCreationService.byRegex("((([+]\\d{1,3} (\\d{7,12})\\b)|([+]\\d{1,3}(\\d{3,12})\\b|[+]\\d{1,3}([ -]\\(?\\d{1,6}\\)?){2,4})|[+]\\d{1,3} ?((\\d{2,6}\\)?)([ -]\\d{2,6}){1,4}))(-\\d{1,3})?\\b)", "PII", EntityType.ENTITY, 1, $section)
.forEach(entity -> entity.redact("PII.3.2", "Telephone number found by regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.3.2", "Telephone number found by regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "PII.3.3: Redact telephone numbers by RegEx"
@ -1136,7 +1132,7 @@ rule "PII.3.4: Redact telephone numbers by RegEx (Non vertebrate study)"
$rowCell: TableCell(matchesRegex("[+]\\d{1,}"))
then
entityCreationService.byRegex("((([+]\\d{1,3} (\\d{7,12})\\b)|([+]\\d{1,3}(\\d{3,12})\\b|[+]\\d{1,3}([ -]\\(?\\d{1,6}\\)?){2,4})|[+]\\d{1,3} ?((\\d{2,6}\\)?)([ -]\\d{2,6}){1,4}))(-\\d{1,3})?\\b)", "PII", EntityType.ENTITY, 1, $rowCell)
.forEach(entity -> entity.redact("PII.3.4", "Telephone number found by regex", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.3.4", "Telephone number found by regex", "personal_data_geolocation_article_39e3"));
end
rule "PII.3.5: Redact telephone numbers by RegEx (vertebrate study)"
@ -1145,7 +1141,7 @@ rule "PII.3.5: Redact telephone numbers by RegEx (vertebrate study)"
$rowCell: TableCell(matchesRegex("[+]\\d{1,}"))
then
entityCreationService.byRegex("((([+]\\d{1,3} (\\d{7,12})\\b)|([+]\\d{1,3}(\\d{3,12})\\b|[+]\\d{1,3}([ -]\\(?\\d{1,6}\\)?){2,4})|[+]\\d{1,3} ?((\\d{2,6}\\)?)([ -]\\d{2,6}){1,4}))(-\\d{1,3})?\\b)", "PII", EntityType.ENTITY, 1, $rowCell)
.forEach(entity -> entity.redact("PII.3.5", "Telephone number found by regex", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.3.5", "Telephone number found by regex", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -1226,7 +1222,7 @@ rule "PII.5.1: Redact line after contact information keywords reduced (non verte
$section: Section(containsString($contactKeyword))
then
entityCreationService.lineAfterString($contactKeyword, "PII", EntityType.ENTITY, $section)
.forEach(contactEntity -> contactEntity.redact("PII.5.1", "Found after \"" + $contactKeyword + "\" contact keyword", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.5.1", "Found after \"" + $contactKeyword + "\" contact keyword", "personal_data_geolocation_article_39e3"));
end
rule "PII.5.2: Redact line after contact information keywords reduced (Vertebrate study)"
@ -1239,7 +1235,7 @@ rule "PII.5.2: Redact line after contact information keywords reduced (Vertebrat
$section: Section(containsString($contactKeyword))
then
entityCreationService.lineAfterString($contactKeyword, "PII", EntityType.ENTITY, $section)
.forEach(contactEntity -> contactEntity.redact("PII.5.2", "Found after \"" + $contactKeyword + "\" contact keyword", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.5.2", "Found after \"" + $contactKeyword + "\" contact keyword", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -1264,7 +1260,7 @@ rule "PII.6.1: Redact line between contact keywords (non vertebrate study)"
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
)
.forEach(contactEntity -> contactEntity.redact("PII.6.1", "Found between contact keywords", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.6.1", "Found between contact keywords", "personal_data_geolocation_article_39e3"));
end
rule "PII.6.2: Redact line between contact keywords (vertebrate study)"
@ -1276,7 +1272,7 @@ rule "PII.6.2: Redact line between contact keywords (vertebrate study)"
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
)
.forEach(contactEntity -> contactEntity.redact("PII.6.2", "Found between contact keywords", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(contactEntity -> contactEntity.redact("PII.6.2", "Found between contact keywords", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
rule "PII.6.3: Redact line between contact keywords (non vertebrate study)"
@ -1320,7 +1316,7 @@ rule "PII.7.1: Redact contact information if applicant is found (non vertebrate
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.7.1", "Applicant information was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.7.1", "Applicant information was found", "personal_data_geolocation_article_39e3"));
end
rule "PII.7.2: Redact contact information if applicant is found (vertebrate study)"
@ -1338,7 +1334,7 @@ rule "PII.7.2: Redact contact information if applicant is found (vertebrate stud
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.7.2", "Applicant information was found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.7.2", "Applicant information was found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -1375,7 +1371,7 @@ rule "PII.8.1: Redact contact information if producer is found (non vertebrate s
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.8.1", "Producer was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.8.1", "Producer was found", "personal_data_geolocation_article_39e3"));
end
rule "PII.8.2: Redact contact information if producer is found (vertebrate study)"
@ -1393,7 +1389,7 @@ rule "PII.8.2: Redact contact information if producer is found (vertebrate study
entityCreationService.betweenStrings("No:", "Fax", "PII", EntityType.ENTITY, $section),
entityCreationService.betweenStrings("Contact:", "Tel", "PII", EntityType.ENTITY, $section)
))
.forEach(entity -> entity.redact("PII.8.2", "Producer was found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.8.2", "Producer was found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -1413,7 +1409,7 @@ rule "PII.9.1: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (non
$document: Document(containsStringIgnoreCase("AUTHOR(S)"), containsAnyStringIgnoreCase("COMPLETION DATE", "STUDY COMPLETION DATE"))
then
entityCreationService.shortestBetweenAnyStringIgnoreCase(List.of("AUTHOR(S)", "AUTHOR(S):"), List.of("COMPLETION DATE", "COMPLETION DATE:", "STUDY COMPLETION DATE", "STUDY COMPLETION DATE:"), "PII", EntityType.ENTITY, $document)
.forEach(authorEntity -> authorEntity.redact("PII.9.1", "AUTHOR(S) was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("PII.9.1", "AUTHOR(S) was found", "personal_data_geolocation_article_39e3"));
end
rule "PII.9.2: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (vertebrate study)"
@ -1422,7 +1418,7 @@ rule "PII.9.2: Redact between \"AUTHOR(S)\" and \"(STUDY) COMPLETION DATE\" (ver
$document: Document(containsStringIgnoreCase("AUTHOR(S)"), containsAnyStringIgnoreCase("COMPLETION DATE", "STUDY COMPLETION DATE"))
then
entityCreationService.shortestBetweenAnyStringIgnoreCase(List.of("AUTHOR(S)", "AUTHOR(S):"), List.of("COMPLETION DATE", "COMPLETION DATE:", "STUDY COMPLETION DATE", "STUDY COMPLETION DATE:"), "PII", EntityType.ENTITY, $document)
.forEach(authorEntity -> authorEntity.redact("PII.9.2", "AUTHOR(S) was found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("PII.9.2", "AUTHOR(S) was found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -1442,7 +1438,7 @@ rule "PII.10.0: Redact study director abbreviation (non vertebrate study)"
$section: Section(containsString("KATH") || containsString("BECH") || containsString("KML"))
then
entityCreationService.byRegexIgnoreCase("((KATH)|(BECH)|(KML)) ?(\\d{4})","PII", EntityType.ENTITY, 1, $section)
.forEach(entity -> entity.redact("PII.10.0", "Personal information found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.10.0", "Personal information found", "personal_data_geolocation_article_39e3"));
end
@ -1452,7 +1448,7 @@ rule "PII.10.1: Redact study director abbreviation (vertebrate study)"
$section: Section(containsString("KATH") || containsString("BECH") || containsString("KML"))
then
entityCreationService.byRegexIgnoreCase("((KATH)|(BECH)|(KML)) ?(\\d{4})","PII", EntityType.ENTITY, 1, $section)
.forEach(entity -> entity.redact("PII.10.1", "Personal information found", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.forEach(entity -> entity.redact("PII.10.1", "Personal information found", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -1462,7 +1458,7 @@ rule "PII.11.0: Redact On behalf of Sequani Ltd.:"
$section: SuperSection(!hasTables(), containsString("On behalf of Sequani Ltd.: Name Title"))
then
entityCreationService.betweenStrings("On behalf of Sequani Ltd.: Name Title", "On behalf of", "PII", EntityType.ENTITY, $section)
.forEach(authorEntity -> authorEntity.redact("PII.11.0", "On behalf of Sequani Ltd.: Name Title was found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.forEach(authorEntity -> authorEntity.redact("PII.11.0", "On behalf of Sequani Ltd.: Name Title was found", "personal_data_geolocation_article_39e3"));
end
@ -1473,7 +1469,7 @@ rule "PII.12.0: Expand PII entities with salutation prefix"
$entityToExpand: TextEntity(type() == "PII", anyMatch(textBefore, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*"))
then
entityCreationService.byPrefixExpansionRegex($entityToExpand, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*")
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.0", "Expanded PII with salutation prefix", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.0", "Expanded PII with salutation prefix", "personal_data_geolocation_article_39e3"));
end
@ -1484,7 +1480,7 @@ rule "PII.12.1: Expand PII entities with salutation prefix"
$entityToExpand: TextEntity(type() == "PII", anyMatch(textBefore, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*"))
then
entityCreationService.byPrefixExpansionRegex($entityToExpand, "\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\s?\\.?\\s*")
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.1", "Expanded PII with salutation prefix", "Article 39(e)(2) of Regulation (EC) No 178/2002"));
.ifPresent(expandedEntity -> expandedEntity.apply("PII.12.1", "Expanded PII with salutation prefix", "vertebrate_study_personal_data_geolocation_article_39e2"));
end
@ -1542,7 +1538,7 @@ rule "ETC.2.1: Redact signatures (non vertebrate study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$signature: Image(imageType == ImageType.SIGNATURE)
then
$signature.redact("ETC.2.1", "Signature Found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$signature.redact("ETC.2.1", "Signature Found", "personal_data_geolocation_article_39e3");
end
rule "ETC.2.2: Redact signatures (vertebrate study)"
@ -1550,7 +1546,7 @@ rule "ETC.2.2: Redact signatures (vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$signature: Image(imageType == ImageType.SIGNATURE)
then
$signature.redact("ETC.2.2", "Signature Found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$signature.redact("ETC.2.2", "Signature Found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
rule "ETC.2.3: Redact signatures"
@ -1582,7 +1578,7 @@ rule "ETC.3.2: Redact logos (vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$logo: Image(imageType == ImageType.LOGO)
then
$logo.redact("ETC.3.2", "Logo Found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$logo.redact("ETC.3.2", "Logo Found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
rule "ETC.3.3: Redact logos"
@ -1606,21 +1602,21 @@ rule "ETC.4.0: Redact dossier dictionary entries"
when
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.redact("ETC.4.0", "Specification of impurity found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$dossierRedaction.redact("ETC.4.0", "Specification of impurity found", "personal_data_geolocation_article_39e3");
end
rule "ETC.4.1: Redact dossier dictionary entries"
when
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.redact("ETC.4.1", "Dossier Redaction found", "Article 39(1)(2) of Regulation (EC) No 178/2002");
$dossierRedaction.redact("ETC.4.1", "Dossier Redaction found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
rule "ETC.4.2: Redact dossier dictionary entries"
when
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.redact("ETC.4.2", "Dossier redaction found", "Article 63(2)(a) of Regulation (EC) No 1107/2009 (making reference to Article 39 of Regulation EC No 178/2002)");
$dossierRedaction.redact("ETC.4.2", "Dossier redaction found", "links_producer_applicant");
end
@ -1631,7 +1627,6 @@ rule "ETC.5.0: Skip dossier_redaction entries if confidentiality is 'confidentia
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.skip("ETC.5.0", "Ignore dossier_redaction when confidential");
$dossierRedaction.getIntersectingNodes().forEach(node -> update(node));
end
rule "ETC.5.1: Remove dossier_redaction entries if confidentiality is not 'confidential'"
@ -1641,7 +1636,6 @@ rule "ETC.5.1: Remove dossier_redaction entries if confidentiality is not 'confi
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.remove("ETC.5.1", "Remove dossier_redaction when not confidential");
retract($dossierRedaction);
end
@ -1676,7 +1670,7 @@ rule "ETC.8.0: Redact formulas (vertebrate study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$logo: Image(imageType == ImageType.FORMULA)
then
$logo.redact("ETC.8.0", "Logo Found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$logo.redact("ETC.8.0", "Logo Found", "personal_data_geolocation_article_39e3");
end
rule "ETC.8.1: Redact formulas (non vertebrate study)"
@ -1684,7 +1678,7 @@ rule "ETC.8.1: Redact formulas (non vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$logo: Image(imageType == ImageType.FORMULA)
then
$logo.redact("ETC.8.1", "Logo Found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$logo.redact("ETC.8.1", "Logo Found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
@ -1723,7 +1717,7 @@ rule "ETC.11.0: Recommend first line in table cell with name and address of owne
$tableCell: TableCell(col == $header.col, row == 2) from $table.streamTableCells().toList()
then
entityCreationService.bySemanticNode($tableCell, "PII", EntityType.RECOMMENDATION)
.ifPresent(redactionEntity -> redactionEntity.redact("ETC.11.0", "Trial Site owner and address found", "Article 39(e)(3) of Regulation (EC) No 178/2002"));
.ifPresent(redactionEntity -> redactionEntity.redact("ETC.11.0", "Trial Site owner and address found", "personal_data_geolocation_article_39e3"));
end
@ -1733,7 +1727,7 @@ rule "ETC.12.0: Redact dossier_redaction (Non vertebrate study)"
not FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.redact("ETC.12.0", "Dossier dictionary entry found", "Article 39(e)(3) of Regulation (EC) No 178/2002");
$dossierRedaction.redact("ETC.12.0", "Dossier dictionary entry found", "personal_data_geolocation_article_39e3");
end
rule "ETC.12.1: Redact dossier_redaction (Vertebrate study)"
@ -1741,7 +1735,7 @@ rule "ETC.12.1: Redact dossier_redaction (Vertebrate study)"
FileAttribute(label == "Vertebrate Study", value soundslike "Yes" || value.toLowerCase() == "y")
$dossierRedaction: TextEntity(type() == "dossier_redaction")
then
$dossierRedaction.redact("ETC.12.1", "Dossier dictionary entry found", "Article 39(e)(2) of Regulation (EC) No 178/2002");
$dossierRedaction.redact("ETC.12.1", "Dossier dictionary entry found", "vertebrate_study_personal_data_geolocation_article_39e2");
end
rule "ETC.12.2: Skip dossier_redaction (Non vertebrate study)"
@ -1899,8 +1893,6 @@ rule "MAN.0.0: Apply manual resize redaction"
then
manualChangesApplicationService.resize($entityToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($entityToBeResized);
$entityToBeResized.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.0.1: Apply manual resize redaction"
@ -1912,8 +1904,6 @@ rule "MAN.0.1: Apply manual resize redaction"
then
manualChangesApplicationService.resizeImage($imageToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($imageToBeResized);
update($imageToBeResized.getParent());
end
@ -1924,10 +1914,8 @@ rule "MAN.1.0: Apply id removals that are valid and not in forced redactions to
$idRemoval: IdRemoval($id: annotationId, !removeFromDictionary, !removeFromAllDossiers)
$entityToBeRemoved: TextEntity(matchesAnnotationId($id))
then
$entityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($entityToBeRemoved);
$entityToBeRemoved.addManualChange($idRemoval);
retract($idRemoval);
$entityToBeRemoved.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to Image"
@ -1937,9 +1925,7 @@ rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to
$imageEntityToBeRemoved: Image($id == id)
then
$imageEntityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($imageEntityToBeRemoved);
retract($idRemoval);
update($imageEntityToBeRemoved.getParent());
end
@ -1950,9 +1936,7 @@ rule "MAN.2.0: Apply force redaction"
$force: ManualForceRedaction($id: annotationId)
$entityToForce: TextEntity(matchesAnnotationId($id))
then
$entityToForce.getManualOverwrite().addChange($force);
update($entityToForce);
$entityToForce.getIntersectingNodes().forEach(node -> update(node));
$entityToForce.addManualChange($force);
retract($force);
end
@ -1963,8 +1947,6 @@ rule "MAN.2.1: Apply force redaction to images"
$imageToForce: Image(id == $id)
then
$imageToForce.getManualOverwrite().addChange($force);
update($imageToForce);
update($imageToForce.getParent());
retract($force);
end
@ -1977,9 +1959,7 @@ rule "MAN.3.0: Apply entity recategorization"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() != $type)
then
$entityToBeRecategorized.getIntersectingNodes().forEach(node -> update(node));
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
update($entityToBeRecategorized);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -1990,7 +1970,7 @@ rule "MAN.3.1: Apply entity recategorization of same type"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() == $type)
then
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -2002,8 +1982,6 @@ rule "MAN.3.2: Apply image recategorization"
$imageToBeRecategorized: Image($id == id)
then
manualChangesApplicationService.recategorize($imageToBeRecategorized, $recategorization);
update($imageToBeRecategorized);
update($imageToBeRecategorized.getParent());
retract($recategorization);
end
@ -2025,7 +2003,6 @@ rule "MAN.4.0: Apply legal basis change"
$imageToBeRecategorized: Image($id == id)
then
$imageToBeRecategorized.getManualOverwrite().addChange($legalBasisChange);
update($imageToBeRecategorized)
retract($legalBasisChange)
end
@ -2035,8 +2012,7 @@ rule "MAN.4.1: Apply legal basis change"
$legalBasisChange: ManualLegalBasisChange($id: annotationId)
$entityToBeChanged: TextEntity(matchesAnnotationId($id))
then
$entityToBeChanged.getManualOverwrite().addChange($legalBasisChange);
update($entityToBeChanged)
$entityToBeChanged.addManualChange($legalBasisChange);
retract($legalBasisChange)
end
@ -2047,81 +2023,134 @@ rule "MAN.4.1: Apply legal basis change"
rule "X.0.0: Remove Entity contained by Entity of same type"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), !hasManualChanges())
not TextEntity(getTextRange().equals($larger.getTextRange()), type() == $type, entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY, !hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
!$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
not TextEntity(
getTextRange().equals($container.getTextRange()),
type() == $container.type(),
entityType == EntityType.DICTIONARY_REMOVAL,
engines contains Engine.DOSSIER_DICTIONARY,
!hasManualChanges()
)
then
$contained.remove("X.0.0", "remove Entity contained by Entity of same type");
retract($contained);
end
end
rule "X.0.1: Remove Entity contained by Entity of same type with manual changes"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
then
$contained.getIntersectingNodes().forEach(node -> update(node));
$contained.remove("X.0.1", "remove Entity contained by Entity of same type with manual changes");
retract($contained);
end
end
rule "X.0.4: Remove Entity contained by Entity of same type"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), !hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges(), !removed())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
!$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
then
$contained.remove("X.0.4", "remove Entity contained by Entity of same type");
update($contained);
end
// Rule unit: X.2
rule "X.2.0: Remove Entity of type ENTITY when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.ENTITY), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.ENTITY,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
end
rule "X.2.1: Remove Entity of type HINT when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.HINT), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.HINT,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("X.2.1", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.1", "remove Entity of type HINT when contained by FALSE_POSITIVE");
end
// Rule unit: X.3
rule "X.3.0: Remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION"
rule "X.3.0: Remove RECOMMENDATION Contained by FALSE_RECOMMENDATION"
salience 64
when
$falseRecommendation: TextEntity($type: type(), entityType == EntityType.FALSE_RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($falseRecommendation), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
end
// Rule unit: X.4
rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY with same type"
salience 256
when
$entity: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(getTextRange().equals($entity.getTextRange()), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$entity.addEngines($recommendation.getEngines());
$recommendation.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
retract($recommendation);
$a.addEngines($b.getEngines());
$b.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
end
@ -2129,68 +2158,100 @@ rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY
rule "X.5.0: Remove Entity of type RECOMMENDATION when intersected by ENTITY"
salience 256
when
$entity: TextEntity((entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(intersects($entity), entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$intersection: Intersection(
$a: a,
$b: b,
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$recommendation.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
retract($recommendation);
$b.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
end
rule "X.5.1: Remove Entity of type RECOMMENDATION when contained by RECOMMENDATION"
salience 256
when
$entity: TextEntity($type: type(), entityType == EntityType.RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($entity), type() != $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$container.type() != $contained.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
end
// Rule unit: X.6
rule "X.6.0: Remove Entity of lower rank, when contained by entity of type ENTITY or HINT"
rule "X.6.0: Remove Lower Rank Entity Contained by ENTITY or HINT"
salience 32
when
$higherRank: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$lowerRank: TextEntity(containedBy($higherRank), type() != $type, dictionary.getDictionaryRank(type) < dictionary.getDictionaryRank($type), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
($container.entityType == EntityType.ENTITY || $container.entityType == EntityType.HINT),
$container.active(),
$contained.type() != $container.type(),
eval(dictionary.getDictionaryRank($contained.type()) < dictionary.getDictionaryRank($container.type())),
!$contained.hasManualChanges()
)
then
$lowerRank.getIntersectingNodes().forEach(node -> update(node));
$lowerRank.remove("X.6.0", "remove Entity of lower rank, when contained by entity of type ENTITY or HINT");
retract($lowerRank);
$contained.remove("X.6.0", "remove Entity of lower rank when contained by entity of type ENTITY or HINT");
end
rule "X.6.1: remove Entity, when contained in another entity of type ENTITY or HINT with larger text range"
rule "X.6.1: Remove Entity, when contained in another entity of type ENTITY or HINT with larger text range"
salience 32
when
$outer: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$inner: TextEntity(containedBy($outer), type() != $type, $outer.getTextRange().length > getTextRange().length(), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
($container.entityType == EntityType.ENTITY || $container.entityType == EntityType.HINT),
$container.active(),
$contained.type() != $container.type(),
eval($container.getTextRange().length() > $contained.getTextRange().length()),
!$contained.hasManualChanges()
)
then
$inner.getIntersectingNodes().forEach(node -> update(node));
$inner.remove("X.6.1", "remove Entity, when contained in another entity of type ENTITY or HINT with larger text range");
retract($inner);
end
$contained.remove("X.6.1", "remove Entity when contained in another entity of type ENTITY or HINT with larger text range");
end
// Rule unit: X.8
rule "X.8.0: Remove Entity when text range and type equals to imported Entity"
salience 257
when
$entity: TextEntity($type: type(), engines contains Engine.IMPORTED, active())
$other: TextEntity(getTextRange().equals($entity.getTextRange()), this != $entity, type() == $type, engines not contains Engine.IMPORTED)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$entity.addEngines($other.getEngines());
retract($other);
$b.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$a.addEngines($b.getEngines());
end
rule "X.8.1: Remove Entity when intersected by imported Entity"
salience 256
when
$entity: TextEntity(engines contains Engine.IMPORTED, active())
$other: TextEntity(intersects($entity), this != $entity, engines not contains Engine.IMPORTED)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.1", "remove Entity when intersected by imported Entity");
retract($other);
$b.remove("X.8.1", "remove Entity when intersected by imported Entity");
end
@ -2219,34 +2280,50 @@ rule "X.10.0: remove false positives of ai"
rule "X.11.0: Remove dictionary entity which intersects with a manual entity"
salience 64
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active())
$dictionaryEntity: TextEntity(intersects($manualEntity), dictionaryEntry, engines not contains Engine.MANUAL)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.MANUAL,
$a.active(),
$b.dictionaryEntry,
$b.engines not contains Engine.MANUAL
)
then
$dictionaryEntity.remove("X.11.0", "remove dictionary entity which intersects with a manual entity");
retract($dictionaryEntity);
$b.remove("X.11.0", "remove dictionary entity which intersects with a manual entity");
end
rule "X.11.1: Remove non manual entity which intersects with a manual entity"
rule "X.11.1: Remove non-manual entity which intersects with a manual entity"
salience 64
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active())
$nonManualEntity: TextEntity(intersects($manualEntity), engines not contains Engine.MANUAL)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.MANUAL,
$a.active(),
$b.engines not contains Engine.MANUAL
)
then
$nonManualEntity.remove("X.11.1", "remove entity which intersects with a manual entity");
retract($nonManualEntity);
$b.remove("X.11.1", "remove entity which intersects with a manual entity");
end
rule "X.11.2: Remove non manual entity which are equal to manual entity"
rule "X.11.2: Remove non-manual entity which is equal to manual entity"
salience 70
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active(), $type: type())
$nonManualEntity: TextEntity(getTextRange().equals($manualEntity.getTextRange()), type() == $type, entityType == EntityType.ENTITY, !hasManualChanges(), engines not contains Engine.MANUAL)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.MANUAL,
$a.active(),
$b.entityType == EntityType.ENTITY,
!$b.hasManualChanges(),
$b.engines not contains Engine.MANUAL
)
then
$manualEntity.addEngines($nonManualEntity.getEngines());
$nonManualEntity.remove("X.11.2", "remove non manual entity which are equal to manual entity");
retract($nonManualEntity);
$a.addEngines($b.getEngines());
$b.remove("X.11.2", "remove non-manual entity which is equal to manual entity");
end
@ -2259,7 +2336,6 @@ rule "DICT.0.0: Remove Template Dictionary Entity when contained by Dossier Dict
$dictionaryRemoval: TextEntity($type: type(), entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY)
$entity: TextEntity(getTextRange().equals($dictionaryRemoval.getTextRange()), engines contains Engine.DICTIONARY, type() == $type, (entityType == EntityType.ENTITY || entityType == EntityType.HINT), !hasManualChanges())
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("DICT.0.0", "Remove Template Dictionary Entity when contained by Dossier Dictionary DICTIONARY_REMOVAL");
$entity.addEngine(Engine.DOSSIER_DICTIONARY);
end

View File

@ -18,8 +18,7 @@ import com.iqser.red.service.redaction.v1.server.model.document.TextRange;
import com.iqser.red.service.redaction.v1.server.model.document.entity.*;
import com.iqser.red.service.redaction.v1.server.model.document.entity.EntityType;
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule;
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity
import com.iqser.red.service.redaction.v1.server.model.document.entity.MatchedRule
import com.iqser.red.service.redaction.v1.server.model.document.entity.TextEntity;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.*;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Section;
import com.iqser.red.service.redaction.v1.server.model.document.nodes.Table;
@ -1315,8 +1314,6 @@ rule "MAN.0.0: Apply manual resize redaction"
then
manualChangesApplicationService.resize($entityToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($entityToBeResized);
$entityToBeResized.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.0.1: Apply manual resize redaction"
@ -1328,8 +1325,6 @@ rule "MAN.0.1: Apply manual resize redaction"
then
manualChangesApplicationService.resizeImage($imageToBeResized, $resizeRedaction);
retract($resizeRedaction);
update($imageToBeResized);
update($imageToBeResized.getParent());
end
@ -1340,10 +1335,8 @@ rule "MAN.1.0: Apply id removals that are valid and not in forced redactions to
$idRemoval: IdRemoval($id: annotationId, !removeFromDictionary, !removeFromAllDossiers)
$entityToBeRemoved: TextEntity(matchesAnnotationId($id))
then
$entityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($entityToBeRemoved);
$entityToBeRemoved.addManualChange($idRemoval);
retract($idRemoval);
$entityToBeRemoved.getIntersectingNodes().forEach(node -> update(node));
end
rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to Image"
@ -1353,9 +1346,7 @@ rule "MAN.1.1: Apply id removals that are valid and not in forced redactions to
$imageEntityToBeRemoved: Image($id == id)
then
$imageEntityToBeRemoved.getManualOverwrite().addChange($idRemoval);
update($imageEntityToBeRemoved);
retract($idRemoval);
update($imageEntityToBeRemoved.getParent());
end
@ -1366,9 +1357,7 @@ rule "MAN.2.0: Apply force redaction"
$force: ManualForceRedaction($id: annotationId)
$entityToForce: TextEntity(matchesAnnotationId($id))
then
$entityToForce.getManualOverwrite().addChange($force);
update($entityToForce);
$entityToForce.getIntersectingNodes().forEach(node -> update(node));
$entityToForce.addManualChange($force);
retract($force);
end
@ -1379,8 +1368,6 @@ rule "MAN.2.1: Apply force redaction to images"
$imageToForce: Image(id == $id)
then
$imageToForce.getManualOverwrite().addChange($force);
update($imageToForce);
update($imageToForce.getParent());
retract($force);
end
@ -1393,9 +1380,7 @@ rule "MAN.3.0: Apply entity recategorization"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() != $type)
then
$entityToBeRecategorized.getIntersectingNodes().forEach(node -> update(node));
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
update($entityToBeRecategorized);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -1406,7 +1391,7 @@ rule "MAN.3.1: Apply entity recategorization of same type"
not ManualRecategorization($id == annotationId, requestDate.isBefore($requestDate))
$entityToBeRecategorized: TextEntity(matchesAnnotationId($id), type() == $type)
then
$entityToBeRecategorized.getManualOverwrite().addChange($recategorization);
$entityToBeRecategorized.addManualChange($recategorization);
retract($recategorization);
end
@ -1418,8 +1403,6 @@ rule "MAN.3.2: Apply image recategorization"
$imageToBeRecategorized: Image($id == id)
then
manualChangesApplicationService.recategorize($imageToBeRecategorized, $recategorization);
update($imageToBeRecategorized);
update($imageToBeRecategorized.getParent());
retract($recategorization);
end
@ -1439,7 +1422,6 @@ rule "MAN.4.0: Apply legal basis change"
$imageToBeRecategorized: Image($id == id)
then
$imageToBeRecategorized.getManualOverwrite().addChange($legalBasisChange);
update($imageToBeRecategorized)
retract($legalBasisChange)
end
@ -1449,8 +1431,7 @@ rule "MAN.4.1: Apply legal basis change"
$legalBasisChange: ManualLegalBasisChange($id: annotationId)
$entityToBeChanged: TextEntity(matchesAnnotationId($id))
then
$entityToBeChanged.getManualOverwrite().addChange($legalBasisChange);
update($entityToBeChanged)
$entityToBeChanged.addManualChange($legalBasisChange);
retract($legalBasisChange)
end
@ -1461,72 +1442,115 @@ rule "MAN.4.1: Apply legal basis change"
rule "X.0.0: Remove Entity contained by Entity of same type"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), !hasManualChanges())
not TextEntity(getTextRange().equals($larger.getTextRange()), type() == $type, entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY, !hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
!$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
not TextEntity(
getTextRange().equals($container.getTextRange()),
type() == $container.type(),
entityType == EntityType.DICTIONARY_REMOVAL,
engines contains Engine.DOSSIER_DICTIONARY,
!hasManualChanges()
)
then
$contained.remove("X.0.0", "remove Entity contained by Entity of same type");
retract($contained);
end
end
rule "X.0.1: Remove Entity contained by Entity of same type with manual changes"
salience 65
when
$larger: TextEntity($type: type(), $entityType: entityType, !removed(), hasManualChanges())
$contained: TextEntity(containedBy($larger), type() == $type, entityType == $entityType, this != $larger, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.type() == $contained.type(),
$container.entityType == $contained.entityType,
$container != $contained,
!$container.removed(),
$container.hasManualChanges(),
!$contained.hasManualChanges(),
!$contained.removed()
)
then
$contained.getIntersectingNodes().forEach(node -> update(node));
$contained.remove("X.0.1", "remove Entity contained by Entity of same type with manual changes");
retract($contained);
end
end
// Rule unit: X.2
rule "X.2.0: Remove Entity of type ENTITY when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.ENTITY), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.ENTITY,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.0", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
end
rule "X.2.1: Remove Entity of type HINT when contained by FALSE_POSITIVE"
salience 64
when
$falsePositive: TextEntity($type: type(), entityType == EntityType.FALSE_POSITIVE, active())
$entity: TextEntity(containedBy($falsePositive), type() == $type, (entityType == EntityType.HINT), !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_POSITIVE,
$container.active(),
$contained.entityType == EntityType.HINT,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("X.2.1", "remove Entity of type ENTITY when contained by FALSE_POSITIVE");
retract($entity)
end
$contained.remove("X.2.1", "remove Entity of type HINT when contained by FALSE_POSITIVE");
end
// Rule unit: X.3
rule "X.3.0: Remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION"
rule "X.3.0: Remove RECOMMENDATION Contained by FALSE_RECOMMENDATION"
salience 64
when
$falseRecommendation: TextEntity($type: type(), entityType == EntityType.FALSE_RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($falseRecommendation), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.FALSE_RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$contained.type() == $container.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.3.0", "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION");
end
// Rule unit: X.4
rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY with same type"
salience 256
when
$entity: TextEntity($type: type(), (entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(getTextRange().equals($entity.getTextRange()), type() == $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$entity.addEngines($recommendation.getEngines());
$recommendation.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
retract($recommendation);
$a.addEngines($b.getEngines());
$b.remove("X.4.0", "remove Entity of type RECOMMENDATION when text range equals ENTITY with same type");
end
@ -1534,11 +1558,16 @@ rule "X.4.0: Remove Entity of type RECOMMENDATION when text range equals ENTITY
rule "X.5.0: Remove Entity of type RECOMMENDATION when intersected by ENTITY"
salience 256
when
$entity: TextEntity((entityType == EntityType.ENTITY || entityType == EntityType.HINT), active())
$recommendation: TextEntity(intersects($entity), entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$intersection: Intersection(
$a: a,
$b: b,
($a.entityType == EntityType.ENTITY || $a.entityType == EntityType.HINT),
$a.active(),
$b.entityType == EntityType.RECOMMENDATION,
!$b.hasManualChanges()
)
then
$recommendation.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
retract($recommendation);
$b.remove("X.5.0", "remove Entity of type RECOMMENDATION when intersected by ENTITY");
end
@ -1546,12 +1575,18 @@ rule "X.5.0: Remove Entity of type RECOMMENDATION when intersected by ENTITY"
rule "X.5.1: Remove Entity of type RECOMMENDATION when contained by RECOMMENDATION"
salience 256
when
$entity: TextEntity($type: type(), entityType == EntityType.RECOMMENDATION, active())
$recommendation: TextEntity(containedBy($entity), type() != $type, entityType == EntityType.RECOMMENDATION, !hasManualChanges())
$containment: Containment(
$container: container,
$contained: contained,
$container.entityType == EntityType.RECOMMENDATION,
$container.active(),
$contained.entityType == EntityType.RECOMMENDATION,
$container.type() != $contained.type(),
!$contained.hasManualChanges()
)
then
$recommendation.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
retract($recommendation);
end
$contained.remove("X.5.1", "remove Entity of type RECOMMENDATION when contained by RECOMMENDATION");
end
// Rule unit: X.7
@ -1569,22 +1604,33 @@ rule "X.7.0: Remove all images"
rule "X.8.0: Remove Entity when text range and type equals to imported Entity"
salience 257
when
$entity: TextEntity($type: type(), engines contains Engine.IMPORTED, active())
$other: TextEntity(getTextRange().equals($entity.getTextRange()), this != $entity, type() == $type, engines not contains Engine.IMPORTED)
$equality: Equality(
$a: a,
$b: b,
$a.type() == $b.type(),
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$entity.addEngines($other.getEngines());
retract($other);
$b.remove("X.8.0", "remove Entity when text range and type equals to imported Entity");
$a.addEngines($b.getEngines());
end
rule "X.8.1: Remove Entity when intersected by imported Entity"
salience 256
when
$entity: TextEntity(engines contains Engine.IMPORTED, active())
$other: TextEntity(intersects($entity), this != $entity, engines not contains Engine.IMPORTED)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.IMPORTED,
$a.active(),
$b.engines not contains Engine.IMPORTED,
$a != $b
)
then
$other.remove("X.8.1", "remove Entity when intersected by imported Entity");
retract($other);
$b.remove("X.8.1", "remove Entity when intersected by imported Entity");
end
// Rule unit: X.9
@ -1611,11 +1657,16 @@ rule "X.10.0: remove false positives of ai"
rule "X.11.0: Remove dictionary entity which intersects with a manual entity"
salience 64
when
$manualEntity: TextEntity(engines contains Engine.MANUAL, active())
$dictionaryEntity: TextEntity(intersects($manualEntity), dictionaryEntry, engines not contains Engine.MANUAL)
$intersection: Intersection(
$a: a,
$b: b,
$a.engines contains Engine.MANUAL,
$a.active(),
$b.dictionaryEntry,
$b.engines not contains Engine.MANUAL
)
then
$dictionaryEntity.remove("X.11.0", "remove dictionary entity which intersects with a manual entity");
retract($dictionaryEntity);
$b.remove("X.11.0", "remove dictionary entity which intersects with a manual entity");
end
@ -1628,7 +1679,6 @@ rule "DICT.0.0: Remove Template Dictionary Entity when contained by Dossier Dict
$dictionaryRemoval: TextEntity($type: type(), entityType == EntityType.DICTIONARY_REMOVAL, engines contains Engine.DOSSIER_DICTIONARY)
$entity: TextEntity(getTextRange().equals($dictionaryRemoval.getTextRange()), engines contains Engine.DICTIONARY, type() == $type, (entityType == EntityType.ENTITY || entityType == EntityType.HINT), !hasManualChanges())
then
$entity.getIntersectingNodes().forEach(node -> update(node));
$entity.remove("DICT.0.0", "Remove Template Dictionary Entity when contained by Dossier Dictionary DICTIONARY_REMOVAL");
$entity.addEngine(Engine.DOSSIER_DICTIONARY);
end

View File

@ -1,240 +0,0 @@
id,old rule names,old rule code,translates to
0,"""0: Add CBI_author from ai 5""","""\n when\n Section(aiMatchesType(\""CARDINAL\""))\n then\n section.addAiEntities(\""CARDINAL\"", \""cardinal\"");\n end""",[AI.2.0]
1,"""0: Add CBI_author from ai 3""","""\n when\n Section(aiMatchesType(\""POSTAL\""))\n then\n section.addAiEntities(\""POSTAL\"", \""postal\"");\n end""",[AI.2.0]
2,"""0: Add CBI_author from ai 6""","""\n when\n Section(aiMatchesType(\""CITY\""))\n then\n section.addAiEntities(\""CITY\"", \""city\"");\n end""",[AI.2.0]
3,"""0: Add CBI_author from ai 7""","""\n when\n Section(aiMatchesType(\""STATE\""))\n then\n section.addAiEntities(\""STATE\"", \""state\"");\n end""",[AI.2.0]
4,"""0: Add CBI_author from ai 2""","""\n when\n Section(aiMatchesType(\""STREET\""))\n then\n section.addAiEntities(\""STREET\"", \""street\"");\n end""",[AI.2.0]
5,"""0: Recommend CTL/BL laboratory that start with BL or CTL""","""\n when\n Section(searchText.contains(\""CT\"") || searchText.contains(\""BL\""))\n then\n /* Regular expression: ((\\b((([Cc]T(([1ILli\\/])| L|~P))|(BL))[\\. ]?([\\dA-Ziltphz~\\/.:!]| ?[\\(',][Ppi](\\(e)?|([\\(-?']\\/))+( ?[\\(\\/\\dA-Znasieg]+)?)\\b( ?\\/? ?\\d+)?)|(\\bCT[L1i]\\b)) */\n section.addRecommendationByRegEx(\""((\\\\b((([Cc]T(([1ILli\\\\/])| L|~P))|(BL))[\\\\. ]?([\\\\dA-Ziltphz~\\\\/.:!]| ?[\\\\(',][Ppi](\\\\(e)?|([\\\\(-?']\\\\/))+( ?[\\\\(\\\\/\\\\dA-Znasieg]+)?)\\\\b( ?\\\\/? ?\\\\d+)?)|(\\\\bCT[L1i]\\\\b))\"", true, 0, \""CBI_address\"");\n end""",[SYN.1.0]
6,"""0: Add CBI_author from ai 4""","""\n when\n Section(aiMatchesType(\""COUNTRY\""))\n then\n section.addAiEntities(\""COUNTRY\"", \""country\"");\n end""",[AI.2.0]
7,"""0: Combine address parts from ai to CBI_address (org is mandatory)""","""\n when\n Section(aiMatchesType(\""ORG\""))\n then\n section.combineAiTypes(\""ORG\"", \""STREET,POSTAL,COUNTRY,CARDINAL,CITY,STATE\"", 20, \""CBI_address\"", 3, false);\n end""",[AI.1.0]
8,"""0: Combine address parts from ai to CBI_address (city is mandatory)""","""\n when\n Section(aiMatchesType(\""CITY\""))\n then\n section.combineAiTypes(\""CITY\"", \""ORG,STREET,POSTAL,COUNTRY,CARDINAL,STATE\"", 20, \""CBI_address\"", 3, false);\n end""",[AI.1.0]
9,"""0: Combine address parts from ai to CBI_address (street is mandatory)""","""\n when\n Section(aiMatchesType(\""STREET\""))\n then\n section.combineAiTypes(\""STREET\"", \""ORG,POSTAL,COUNTRY,CARDINAL,CITY,STATE\"", 20, \""CBI_address\"", 3, false);\n end""",[AI.1.0]
10,"""0: Add CBI_author from ai, 1: Add CBI_author from ai""","""\n when\n Section(aiMatchesType(\""CBI_author\""))\n then\n section.addAiEntities(\""CBI_author\"", \""CBI_author\"");\n end""",[AI.0.0]
11,"""0: Add CBI_author from ai 8""","""\n when\n Section(aiMatchesType(\""ORG\""))\n then\n section.addAiEntities(\""ORG\"", \""org\"");\n end""",[AI.2.0]
12,"""1: Redacted because Section contains Vertebrate""","""\n when\n Section(matchesType(\""vertebrate\""))\n then\n section.redact(\""CBI_author\"", 1, \""Vertebrate found\"", \""names_addresses_persons\"");\n section.redact(\""CBI_address\"", 1, \""Vertebrate found\"", \""names_addresses_persons\"");\n end""",[CBI.3.0]
13,"""5: Do not redact genitive CBI_author, 7: Do not redact genitive CBI_author, 1: Do not redact genitive CBI_author""","""\n when\n Section(matchesType(\""CBI_author\""))\n then\n section.expandToFalsePositiveByRegEx(\""CBI_author\"", \""[''ʼˈ´`ʻ']s\"", false, 0);\n end""",[CBI.2.0]
14,"""1: Redact CBI Authors (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesType(\""CBI_author\""))\n then\n section.redact(\""CBI_author\"", 1, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[CBI.0.0]
15,"""2: Combine ai types CBI_author from ai""","""\n when\n Section(aiMatchesType(\""ORG\""))\n then\n section.combineAiTypes(\""ORG\"", \""STREET,POSTAL,COUNTRY,CARDINAL,CITY,STATE\"", 20, \""CBI_address\"", 2, false);\n end""",[AI.1.0]
16,"""2: Not Redacted because Section contains no Vertebrate""","""\n when\n Section(!matchesType(\""vertebrate\""))\n then\n section.redactNot(\""CBI_author\"", 2, \""No Vertebrate found\"");\n section.redactNot(\""CBI_address\"", 2, \""No Vertebrate found\"");\n end""",[CBI.3.0]
17,"""2: Redact CBI Authors (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesType(\""CBI_author\""))\n then\n section.redact(\""CBI_author\"", 2, \""Author found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[CBI.0.0]
18,"""2: Redacted because Section contains Vertebrate""","""\n when\n Section(matchesType(\""vertebrate\""))\n then\n section.redact(\""CBI_author\"", 2, \""Vertebrate found\"", \""names_addresses_persons\"");\n section.redact(\""CBI_address\"", 2, \""Vertebrate found\"", \""names_addresses_persons\"");\n end""",[CBI.3.0]
19,"""3: Redact CBI Authors (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesType(\""CBI_author\""))\n then\n section.redact(\""CBI_author\"", 3, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[CBI.0.0]
20,"""3: Not Redacted because Section contains no Vertebrate""","""\n when\n Section(!matchesType(\""vertebrate\""))\n then\n section.redactNot(\""CBI_author\"", 3, \""No Vertebrate found\"");\n section.redactNot(\""CBI_address\"", 3, \""No Vertebrate found\"");\n end""",[CBI.3.2]
21,"""3: Do not redact Names and Addresses if no redaction Indicator is contained""","""\n when\n Section(matchesType(\""vertebrate\""), matchesType(\""no_redaction_indicator\""))\n then\n section.redactNot(\""CBI_author\"", 3, \""Vertebrate and No Redaction Indicator found\"");\n section.redactNot(\""CBI_address\"", 3, \""Vertebrate and No Redaction Indicator found\"");\n end""",[CBI.4.0]
22,"""3: Redact not CBI Address (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesType(\""CBI_address\""))\n then\n section.redactNot(\""CBI_address\"", 3, \""Address found for non vertebrate study\"");\n end""",[CBI.1.0]
23,"""3: Redact not CBI Address (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesType(\""CBI_address\""))\n then\n section.redactNot(\""CBI_address\"", 3, \""Address found for non vertebrate study\"");\n section.ignoreRecommendations(\""CBI_address\"");\n end""",[CBI.1.0]
24,"""4: Redact Names and Addresses if no_redaction_indicator and redaction_indicator is contained""","""\n when\n Section(matchesType(\""vertebrate\""), matchesType(\""no_redaction_indicator\""), matchesType(\""redaction_indicator\""))\n then\n section.redact(\""CBI_author\"", 4, \""Vertebrate and Redaction Indicator found\"", \""names_addresses_persons\"");\n section.redact(\""CBI_address\"", 4, \""Vertebrate and Redaction Indicator found\"", \""names_addresses_persons\"");\n end""",[CBI.5.0]
25,"""4: Redact CBI Address (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesType(\""CBI_address\""))\n then\n section.redact(\""CBI_address\"", 4, \""Address found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[CBI.1.1]
26,"""4: Redact CBI Authors (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesType(\""CBI_author\""))\n then\n section.redact(\""CBI_author\"", 4, \""Author found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[CBI.0.0]
27,"""4: Do not redact Names and Addresses if no redaction Indicator is contained""","""\n when\n Section(matchesType(\""vertebrate\""), matchesType(\""no_redaction_indicator\""))\n then\n section.redactNot(\""CBI_author\"", 4, \""Vertebrate and No Redaction Indicator found\"");\n section.redactNot(\""CBI_address\"", 4, \""Vertebrate and No Redaction Indicator found\"");\n end""",[CBI.4.0]
28,"""5: Do not redact Names and Addresses if no redaction Indicator is contained""","""\n when\n Section(matchesType(\""vertebrate\""), matchesType(\""published_information\""))\n then\n section.redactNotAndReference(\""CBI_author\"",\""published_information\"", 5, \""Published Information found\"");\n section.redactNotAndReference(\""CBI_address\"",\""published_information\"", 5, \""Published Information found\"");\n end""",[CBI.4.0]
29,"""5: Redact Names and Addresses if no_redaction_indicator and redaction_indicator is contained""","""\n when\n Section(matchesType(\""vertebrate\""), matchesType(\""no_redaction_indicator\""), matchesType(\""redaction_indicator\""))\n then\n section.redact(\""CBI_author\"", 5, \""Vertebrate and Redaction Indicator found\"", \""names_addresses_persons\"");\n section.redact(\""CBI_address\"", 5, \""Vertebrate and Redaction Indicator found\"", \""names_addresses_persons\"");\n end""",[CBI.5.0]
30,"""5: Redact not CBI Address (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesType(\""CBI_address\""))\n then\n section.redactNot(\""CBI_address\"", 5, \""Address found for non vertebrate study\"");\n section.ignoreRecommendations(\""CBI_address\"");\n end""",[CBI.1.0]
31,"""6: Do not redact Names and Addresses if no redaction Indicator is contained""","""\n when\n Section(matchesType(\""vertebrate\""), matchesType(\""published_information\""))\n then\n section.redactNotAndReference(\""CBI_author\"",\""published_information\"", 6, \""Published Information found\"");\n section.redactNotAndReference(\""CBI_address\"",\""published_information\"", 6, \""Published Information found\"");\n end""",[CBI.4.0]
32,"""6: Redact CBI Address (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesType(\""CBI_address\""))\n then\n section.redact(\""CBI_address\"", 6, \""Address found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[CBI.1.1]
33,"""6: Redact Author(s) cells in Tables with Author(s) header (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && hasTableHeader(\""Author(s)\"") && !hasTableHeader(\""Vertebrate study Y/N\""))\n then\n section.redactCell(\""Author(s)\"", 6, \""CBI_author\"", false, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""","[CBI.9.0, CBI.11.0]"
34,"""6: Not redacted because Vertebrate Study = N""","""\n when\n Section(rowEquals(\""Vertebrate study Y/N\"", \""N\"") || rowEquals(\""Vertebrate study Y/N\"", \""No\""))\n then\n section.redactNotCell(\""Author(s)\"", 6, \""CBI_author\"", true, \""Not redacted because row is not a vertebrate study\"");\n section.redactNot(\""CBI_author\"", 6, \""Not redacted because row is not a vertebrate study\"");\n section.redactNot(\""CBI_address\"", 6, \""Not redacted because row is not a vertebrate study\"");\n section.highlightCell(\""Vertebrate study Y/N\"", 6, \""hint_only\"");\n end""",[CBI.12.0]
35,"""7: Redact Author(s) cells in Tables with Author(s) header (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && hasTableHeader(\""Author(s)\"") && !hasTableHeader(\""Vertebrate study Y/N\""))\n then\n section.redactCell(\""Author(s)\"", 7, \""CBI_author\"", false, \""Author found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[CBI.10.0, CBI.11.0]"
36,"""7: Not redacted because Vertebrate Study = N""","""\n when\n Section(rowEquals(\""Vertebrate study Y/N\"", \""N\"") || rowEquals(\""Vertebrate study Y/N\"", \""No\""))\n then\n section.redactNotCell(\""Author(s)\"", 7, \""CBI_author\"", true, \""Not redacted because row is not a vertebrate study\"");\n section.redactNot(\""CBI_author\"", 7, \""Not redacted because row is not a vertebrate study\"");\n section.redactNot(\""CBI_address\"", 7, \""Not redacted because row is not a vertebrate study\"");\n section.highlightCell(\""Vertebrate study Y/N\"", 7, \""hint_only\"");\n end""",[CBI.12.0]
37,"""7: Redact if must redact entry is found""","""\n when\n Section(matchesType(\""must_redact\""))\n then\n section.redact(\""CBI_author\"", 7, \""must_redact entry was found.\"", \""names_addresses_persons\"");\n section.redact(\""CBI_address\"", 7, \""must_redact entry was found.\"", \""names_addresses_persons\"");\n end""",[CBI.8.0]
38,"""8: Redact Authors and Addresses in Reference Table if it is a Vertebrate study""","""\n when\n Section(rowEquals(\""Vertebrate study Y/N\"", \""Y\"") || rowEquals(\""Vertebrate study Y/N\"", \""Yes\""))\n then\n section.redactCell(\""Author(s)\"", 8, \""CBI_author\"", true, \""Redacted because row is a vertebrate study\"", \""names_addresses_persons\"");\n section.redact(\""CBI_address\"", 8, \""Redacted because row is a vertebrate study\"", \""names_addresses_persons\"");\n section.highlightCell(\""Vertebrate study Y/N\"", 8, \""must_redact\"");\n end""",[CBI.12.0]
39,"""8: Redact if must redact entry is found""","""\n when\n Section(matchesType(\""must_redact\""))\n then\n section.redact(\""CBI_author\"", 8, \""Specification of impurity of the active substance was found.\"", \""specification_impurity_active_substance\"");\n section.redact(\""CBI_address\"", 8, \""Specification of impurity of the active substance was found.\"", \""specification_impurity_active_substance\"");\n end""",[CBI.8.0]
40,"""8: Redact Author cells in Tables with Author header (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && hasTableHeader(\""Author\"") && !hasTableHeader(\""Vertebrate study Y/N\""))\n then\n section.redactCell(\""Author\"", 8, \""CBI_author\"", false, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""","[CBI.9.0, CBI.11.0]"
41,"""8: Redact Author(s) cells in Tables with Author(s) header (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && hasTableHeader(\""Author(s)\"") && !hasTableHeader(\""Vertebrate study Y/N\""))\n then\n section.redactCell(\""Author(s)\"", 8, \""CBI_author\"", false, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""","[CBI.9.0, CBI.11.0]"
42,"""9: Redact Author(s) cells in Tables with Author(s) header (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && hasTableHeader(\""Author(s)\"") && !hasTableHeader(\""Vertebrate study Y/N\""))\n then\n section.redactCell(\""Author(s)\"", 9, \""CBI_author\"", false, \""Author found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[CBI.10.0, CBI.11.0]"
43,"""9: Redact Author cells in Tables with Author header (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && hasTableHeader(\""Author\"") && !hasTableHeader(\""Vertebrate study Y/N\""))\n then\n section.redactCell(\""Author\"", 9, \""CBI_author\"", false, \""Author found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[CBI.10.0, CBI.11.0]"
44,"""9: Redact sponsor company""","""\n when\n Section(searchText.toLowerCase().contains(\""batches produced at\""))\n then\n section.redactIfPrecededBy(\""batches produced at\"", \""CBI_sponsor\"", 9, \""Redacted because it represents a sponsor company\"", \""names_addresses_persons\"");\n section.addHintAnnotation(\""batches produced at\"", \""must_redact\"");\n end""",[CBI.14.0]
45,"""9: Redact Authors and Addresses in Reference Table if it is a Vertebrate study""","""\n when\n Section(rowEquals(\""Vertebrate study Y/N\"", \""Y\"") || rowEquals(\""Vertebrate study Y/N\"", \""Yes\""))\n then\n section.redactCell(\""Author(s)\"", 9, \""CBI_author\"", true, \""Redacted because row is a vertebrate study\"", \""names_addresses_persons\"");\n section.redact(\""CBI_address\"", 9, \""Redacted because row is a vertebrate study\"", \""names_addresses_persons\"");\n section.highlightCell(\""Vertebrate study Y/N\"", 9, \""must_redact\"");\n end""",[CBI.12.0]
46,"""10: Redact and recommand Authors in Tables with Vertebrate study Y/N header (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (rowEquals(\""Vertebrate study Y/N\"", \""Y\"") || rowEquals(\""Vertebrate study Y/N\"", \""Yes\"") || rowEquals(\""Vertebrate study Y/N\"", \""N\"") || rowEquals(\""Vertebrate study Y/N\"", \""No\"")))\n then\n section.redactCell(\""Author(s)\"", 10, \""CBI_author\"", true, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""","[CBI.9.0, CBI.11.0]"
47,"""10: Redact determination of residues""","""\n when\n Section((\n searchText.toLowerCase.contains(\""determination of residues\"") ||\n searchText.toLowerCase.contains(\""determination of total residues\"")\n ) && (\n searchText.toLowerCase.contains(\""livestock\"") ||\n searchText.toLowerCase.contains(\""live stock\"") ||\n searchText.toLowerCase.contains(\""tissue\"") ||\n searchText.toLowerCase.contains(\""tissues\"") ||\n searchText.toLowerCase.contains(\""liver\"") ||\n searchText.toLowerCase.contains(\""muscle\"") ||\n searchText.toLowerCase.contains(\""bovine\"") ||\n searchText.toLowerCase.contains(\""ruminant\"") ||\n searchText.toLowerCase.contains(\""ruminants\"")\n ))\n then\n section.redact(\""CBI_author\"", 10, \""Determination of residues was found.\"", \""names_addresses_persons\"");\n section.redact(\""CBI_address\"", 10, \""Determination of residues was found.\"", \""names_addresses_persons\"");\n section.addHintAnnotation(\""determination of residues\"", \""must_redact\"");\n section.addHintAnnotation(\""determination of total residues\"", \""must_redact\"");\n section.addHintAnnotation(\""livestock\"", \""must_redact\"");\n section.addHintAnnotation(\""live stock\"", \""must_redact\"");\n section.addHintAnnotation(\""tissue\"", \""must_redact\"");\n section.addHintAnnotation(\""tissues\"", \""must_redact\"");\n section.addHintAnnotation(\""liver\"", \""must_redact\"");\n section.addHintAnnotation(\""muscle\"", \""must_redact\"");\n section.addHintAnnotation(\""bovine\"", \""must_redact\"");\n section.addHintAnnotation(\""ruminant\"", \""must_redact\"");\n section.addHintAnnotation(\""ruminants\"", \""must_redact\"");\n end""",[CBI.15.0]
48,"""10: Redact Author cells in Tables with Author header (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && hasTableHeader(\""Author\"") && !hasTableHeader(\""Vertebrate study Y/N\""))\n then\n section.redactCell(\""Author\"", 10, \""CBI_author\"", false, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""","[CBI.9.0, CBI.11.0]"
49,"""10: Redact sponsor company""","""\n when\n Section(searchText.toLowerCase().contains(\""batches produced at\""))\n then\n section.redactIfPrecededBy(\""batches produced at\"", \""CBI_sponsor\"", 10, \""Redacted because it represents a sponsor company\"", \""names_addresses_persons\"");\n section.addHintAnnotation(\""batches produced at\"", \""must_redact\"");\n end""",[CBI.14.0]
50,"""11: Redact and recommand Authors in Tables with Vertebrate study Y/N header (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (rowEquals(\""Vertebrate study Y/N\"", \""Y\"") || rowEquals(\""Vertebrate study Y/N\"", \""Yes\"") || rowEquals(\""Vertebrate study Y/N\"", \""N\"") || rowEquals(\""Vertebrate study Y/N\"", \""No\"")))\n then\n section.redactCell(\""Author(s)\"", 11, \""CBI_author\"", true, \""Author found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[CBI.10.0, CBI.11.0]"
51,"""11: Redact if CTL/* or BL/* was found""","""\n when\n Section(searchText.contains(\""CTL/\"") || searchText.contains(\""BL/\""))\n then\n section.redact(\""CBI_author\"", 11, \""Laboraty for vertebrate studies found\"", \""names_addresses_persons\"");\n section.redact(\""CBI_address\"", 11, \""Laboraty for vertebrate studies found\"", \""names_addresses_persons\"");\n section.addHintAnnotation(\""CTL\"", \""must_redact\"");\n section.addHintAnnotation(\""BL\"", \""must_redact\"");\n end""",[SYN.0.0]
52,"""11: Redact determination of residues""","""\n when\n Section((\n searchText.toLowerCase.contains(\""determination of residues\"") ||\n searchText.toLowerCase.contains(\""determination of total residues\"")\n ) && (\n searchText.toLowerCase.contains(\""livestock\"") ||\n searchText.toLowerCase.contains(\""live stock\"") ||\n searchText.toLowerCase.contains(\""tissue\"") ||\n searchText.toLowerCase.contains(\""tissues\"") ||\n searchText.toLowerCase.contains(\""liver\"") ||\n searchText.toLowerCase.contains(\""muscle\"") ||\n searchText.toLowerCase.contains(\""bovine\"") ||\n searchText.toLowerCase.contains(\""ruminant\"") ||\n searchText.toLowerCase.contains(\""ruminants\"")\n ))\n then\n section.redact(\""CBI_author\"", 11, \""Determination of residues was found.\"", \""names_addresses_persons\"");\n section.redact(\""CBI_address\"", 11, \""Determination of residues was found.\"", \""names_addresses_persons\"");\n section.addHintAnnotation(\""determination of residues\"", \""must_redact\"");\n section.addHintAnnotation(\""determination of total residues\"", \""must_redact\"");\n section.addHintAnnotation(\""livestock\"", \""must_redact\"");\n section.addHintAnnotation(\""live stock\"", \""must_redact\"");\n section.addHintAnnotation(\""tissue\"", \""must_redact\"");\n section.addHintAnnotation(\""tissues\"", \""must_redact\"");\n section.addHintAnnotation(\""liver\"", \""must_redact\"");\n section.addHintAnnotation(\""muscle\"", \""must_redact\"");\n section.addHintAnnotation(\""bovine\"", \""must_redact\"");\n section.addHintAnnotation(\""ruminant\"", \""must_redact\"");\n section.addHintAnnotation(\""ruminants\"", \""must_redact\"");\n end""",[CBI.15.0]
53,"""11: Redact Author cells in Tables with Author header (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && hasTableHeader(\""Author\"") && !hasTableHeader(\""Vertebrate study Y/N\""))\n then\n section.redactCell(\""Author\"", 11, \""CBI_author\"", false, \""Author found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[CBI.10.0, CBI.11.0]"
54,"""12: Redact and add recommendation for et al. author""","""\n when\n Section(searchText.contains(\""et al\""))\n then\n\t\tsection.redactAndRecommendByRegEx(\""\\\\b([A-ZÄÖÜ][^\\\\s\\\\.,]+( [A-ZÄÖÜ]{1,2}\\\\.?)?( ?[A-ZÄÖÜ]\\\\.?)?) et al\\\\.?\"", false, 1, \""CBI_author\"", 12, \""Author found\"", \""names_addresses_persons\"");\n end""",[CBI.16.0]
55,"""12: Redact and recommand Authors in Tables with Vertebrate study Y/N header (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (rowEquals(\""Vertebrate study Y/N\"", \""Y\"") || rowEquals(\""Vertebrate study Y/N\"", \""Yes\"") || rowEquals(\""Vertebrate study Y/N\"", \""N\"") || rowEquals(\""Vertebrate study Y/N\"", \""No\"")))\n then\n section.redactCell(\""Author(s)\"", 12, \""CBI_author\"", true, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""","[CBI.9.0, CBI.11.0]"
56,"""12: Recommend CTL/BL laboratory""","""\n when\n Section(searchText.contains(\""CT\"") || searchText.contains(\""BL\""))\n then\n section.addRecommendationByRegEx(\""((\\\\b((([Cc]T(([1ILli\\\\/])| L|~P))|(BL))[\\\\. ]?([\\\\dA-Ziltphz~\\\\/.:!]| ?[\\\\(',][Ppi](\\\\(e)?|([\\\\(-?']\\\\/))+( ?[\\\\(\\\\/\\\\dA-Znasieg]+)?)\\\\b( ?\\\\/? ?\\\\d+)?)|(\\\\bCT[L1i]\\\\b))\"", true, 0, \""CBI_address\"");\n end""",[SYN.1.0]
57,"""12: Redact if CTL/* or BL/* was found (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (searchText.contains(\""CTL/\"") || searchText.contains(\""BL/\"")))\n then\n section.addHintAnnotation(\""CTL\"", \""hint_only\"");\n section.addHintAnnotation(\""BL\"", \""hint_only\"");\n end""",[SYN.0.0]
58,"""13: Redact and recommand Authors in Tables with Vertebrate study Y/N header (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (rowEquals(\""Vertebrate study Y/N\"", \""Y\"") || rowEquals(\""Vertebrate study Y/N\"", \""Yes\"") || rowEquals(\""Vertebrate study Y/N\"", \""N\"") || rowEquals(\""Vertebrate study Y/N\"", \""No\"")))\n then\n section.redactCell(\""Author(s)\"", 13, \""CBI_author\"", true, \""Author found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[CBI.10.0, CBI.11.0]"
59,"""14: Add recommendation for Addresses in Test Organism sections, 13: Add recommendation for Addresses in Test Organism sections""","""\n when\n Section(searchText.contains(\""Species:\"") && searchText.contains(\""Source:\""))\n then\n\t\tsection.recommendLineAfter(\""Source:\"", \""CBI_address\"");\n end""",[CBI.17.0]
60,"""13: Redact and add recommendation for et al. author""","""\n when\n Section(searchText.contains(\""et al\""))\n then\n\t\tsection.redactAndRecommendByRegEx(\""\\\\b([A-ZÄÖÜ][^\\\\s\\\\.,]+( [A-ZÄÖÜ]{1,2}\\\\.?)?( ?[A-ZÄÖÜ]\\\\.?)?) et al\\\\.?\"", false, 1, \""CBI_author\"", 13, \""Author found\"", \""names_addresses_persons\"");\n end""",[CBI.16.0]
61,"""13: Redact if CTL/* or BL/* was found (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (searchText.contains(\""CTL/\"") || searchText.contains(\""BL/\"")))\n then\n section.addRedaction(\""CTL\"", \""must_redact\"", 13, \""Laboratory for vertebrate studies found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"" );\n section.addRedaction(\""BL\"", \""must_redact\"", 13, \""Laboratory for vertebrate studies found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"" );\n end""",[SYN.0.0]
62,"""15: Add recommendation for Addresses in Test Animals sections, 14: Add recommendation for Addresses in Test Animals sections""","""\n when\n Section(searchText.contains(\""Species\"") && searchText.contains(\""Source\""))\n then\n\t\tsection.recommendLineAfter(\""Source\"", \""CBI_address\"");\n end""",[CBI.17.0]
63,"""14: Redact addresses that start with BL or CTL""","""\n when\n Section(searchText.contains(\""BL\"") || searchText.contains(\""CT\""))\n then\n section.addRecommendationByRegEx(\""((\\\\b((([Cc]T(([1ILli\\\\/])| L|~P))|(BL))[\\\\. ]?([\\\\dA-Ziltphz~\\\\/.:!]| ?[\\\\(',][Ppi](\\\\(e)?|([\\\\(-?']\\\\/))+( ?[\\\\(\\\\/\\\\dA-Znasieg]+)?)\\\\b( ?\\\\/? ?\\\\d+)?)|(\\\\bCT[L1i]\\\\b))\"", true, 0, \""CBI_address\"");\n end""",[SYN.1.0]
64,"""14: Redacted PII Personal Identification Information""","""\n when\n Section(matchesType(\""PII\""))\n then\n section.redact(\""PII\"", 14, \""PII (Personal Identification Information) found\"", \""links_producer_applicant\"");\n end""","[PII.0.0, PII.0.1]"
65,"""14: Redact and add recommendation for et al. author (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""et al\""))\n then\n section.redactAndRecommendByRegEx(\""\\\\b([A-ZÄÖÜ][^\\\\s\\\\.,]+( [A-ZÄÖÜ]{1,2}\\\\.?)?( ?[A-ZÄÖÜ]\\\\.?)?) et al\\\\.?\"", false, 1, \""CBI_author\"", 14, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[CBI.16.0]
66,"""15: Redact Emails by RegEx""","""\n when\n Section(searchText.contains(\""@\""))\n then\n section.redactByRegEx(\""\\\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\\\.[A-Z]{2,4}\\\\b\"", true, 0, \""PII\"", 15, \""PII (Personal Identification Information) found\"", \""links_producer_applicant\"");\n end""","[PII.1.0, PII.1.1]"
67,"""15: Redact and add recommendation for et al. author (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""et al\""))\n then\n section.redactAndRecommendByRegEx(\""\\\\b([A-ZÄÖÜ][^\\\\s\\\\.,]+( [A-ZÄÖÜ]{1,2}\\\\.?)?( ?[A-ZÄÖÜ]\\\\.?)?) et al\\\\.?\"", false, 1, \""CBI_author\"", 15, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[CBI.16.0]
68,"""15: Redact and add recommendation for et al. author (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""et al\""))\n then\n section.redactAndRecommendByRegEx(\""\\\\b([A-ZÄÖÜ][^\\\\s\\\\.,]+( [A-ZÄÖÜ]{1,2}\\\\.?)?( ?[A-ZÄÖÜ]\\\\.?)?) et al\\\\.?\"", false, 1, \""CBI_author\"", 15, \""Author found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[CBI.16.0]
69,"""16: Redacted PII Personal Identification Information""","""\n when\n Section(matchesType(\""PII\""))\n then\n section.redact(\""PII\"", 16, \""PII (Personal Identification Information) found\"", \""links_producer_applicant\"");\n end""","[PII.0.0, PII.0.1]"
70,"""16: Redact and add recommendation for et al. author (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""et al\""))\n then\n section.redactAndRecommendByRegEx(\""\\\\b([A-ZÄÖÜ][^\\\\s\\\\.,]+( [A-ZÄÖÜ]{1,2}\\\\.?)?( ?[A-ZÄÖÜ]\\\\.?)?) et al\\\\.?\"", false, 1, \""CBI_author\"", 16, \""Author found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[CBI.16.0]
71,"""16: Redact contact information""","""\n when\n Section(text.contains(\""Contact point:\"")\n || text.contains(\""Phone:\"")\n || text.contains(\""Fax:\"")\n || text.contains(\""Tel.:\"")\n || text.contains(\""Tel:\"")\n || text.contains(\""E-mail:\"")\n || text.contains(\""Email:\"")\n || text.contains(\""e-mail:\"")\n || text.contains(\""E-mail address:\"")\n || text.contains(\""Alternative contact:\"")\n || text.contains(\""Telephone number:\"")\n || text.contains(\""Telephone No:\"")\n || text.contains(\""Fax number:\"")\n || text.contains(\""Telephone:\"")\n || text.contains(\""European contact:\""))\n then\n section.redactLineAfter(\""Contact point:\"", \""PII\"", 16, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Phone:\"", \""PII\"", 16, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Fax:\"", \""PII\"", 16, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Tel.:\"", \""PII\"", 16, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Tel:\"", \""PII\"", 16, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""E-mail:\"", \""PII\"", 16, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Email:\"", \""PII\"", 16, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""e-mail:\"", \""PII\"", 16, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""E-mail address:\"", \""PII\"", 16, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Contact:\"", \""PII\"", 16, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Alternative contact:\"", \""PII\"", 16, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Telephone number:\"", \""PII\"", 16, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Telephone No:\"", \""PII\"", 16, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Fax number:\"", \""PII\"", 16, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Telephone:\"", \""PII\"", 16, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactBetween(\""No:\"", \""Fax\"", \""PII\"", 16, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactBetween(\""Contact:\"", \""Tel.:\"", \""PII\"", 16, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""European contact:\"", \""PII\"", 16, true, \""Contact information was found\"", \""links_producer_applicant\"");\n end""","[PII.4.0, PII.4.1, PII.6.0, PII.6.1]"
72,"""16: Add recommendation for Addresses in Test Organism sections, 17: Add recommendation for Addresses in Test Organism sections""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""Species:\"") && searchText.contains(\""Source:\""))\n then\n section.recommendLineAfter(\""Source:\"", \""CBI_address\"");\n end""",[CBI.17.0]
73,"""17: Redact Emails by RegEx""","""\n when\n Section(searchText.contains(\""@\""))\n then\n section.redactByRegEx(\""\\\\b([A-Za-z0-9._%+\\\\-]+@[A-Za-z0-9.\\\\-]+\\\\.[A-Za-z\\\\-]{1,23}[A-Za-z])\\\\b\"", true, 1, \""PII\"", 17, \""PII (Personal Identification Information) found\"", \""links_producer_applicant\"");\n end""","[PII.1.0, PII.1.1]"
74,"""17: Add recommendation for Addresses in Test Animals sections, 18: Add recommendation for Addresses in Test Animals sections""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""Species\"") && searchText.contains(\""Source\""))\n then\n section.recommendLineAfter(\""Source\"", \""CBI_address\"");\n end""",[CBI.17.0]
75,"""17: Redact contact information if applicant is found""","""\n when\n Section(headlineContainsWord(\""applicant\"") || text.contains(\""Applicant\"") || headlineContainsWord(\""Primary contact\"") || headlineContainsWord(\""Alternative contact\"") || text.contains(\""Telephone number:\""))\n then\n section.redactLineAfter(\""Contact point:\"", \""PII\"", 17, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Phone:\"", \""PII\"", 17, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Fax:\"", \""PII\"", 17, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Tel.:\"", \""PII\"", 17, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Tel:\"", \""PII\"", 17, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""E-mail:\"", \""PII\"", 17, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Email:\"", \""PII\"", 17, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""e-mail:\"", \""PII\"", 17, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""E-mail address:\"", \""PII\"", 17, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Contact:\"", \""PII\"", 17, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Alternative contact:\"", \""PII\"", 17, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Telephone number:\"", \""PII\"", 17, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Telephone No:\"", \""PII\"", 17, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Fax number:\"", \""PII\"", 17, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Telephone:\"", \""PII\"", 17, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactBetween(\""No:\"", \""Fax\"", \""PII\"", 17, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactBetween(\""Contact:\"", \""Tel.:\"", \""PII\"", 17, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""European contact:\"", \""PII\"", 17, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n end""",[PII.7.0]
76,"""18: Do not redact Names and Addresses if Published Information found""","""\n when\n Section(matchesType(\""published_information\""))\n then\n section.redactNotAndReference(\""CBI_author\"",\""published_information\"", 18, \""Published Information found\"");\n section.redactNotAndReference(\""CBI_address\"",\""published_information\"", 18, \""Published Information found\"");\n end""",[CBI.7.0]
77,"""18: Redact contact information if Producer is found""","""\n when\n Section(text.toLowerCase().contains(\""producer of the plant protection\"") || text.toLowerCase().contains(\""producer of the active substance\"") || text.contains(\""Manufacturer of the active substance\"") || text.contains(\""Manufacturer:\"") || text.contains(\""Producer or producers of the active substance\""))\n then\n section.redactLineAfter(\""Contact:\"", \""PII\"", 18, true, \""Producer was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Telephone:\"", \""PII\"", 18, true, \""Producer was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Phone:\"", \""PII\"", 18, true, \""Producer was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Fax:\"", \""PII\"", 18, true, \""Producer was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""E-mail:\"", \""PII\"", 18, true, \""Producer was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Contact:\"", \""PII\"", 18, true, \""Producer was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Fax number:\"", \""PII\"", 18, true, \""Producer was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Telephone number:\"", \""PII\"", 18, true, \""Producer was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Tel:\"", \""PII\"", 18, true, \""Producer was found\"", \""links_producer_applicant\"");\n section.redactBetween(\""No:\"", \""Fax\"", \""PII\"", 18, true, \""Producer was found\"", \""links_producer_applicant\"");\n end""",[PII.8.0]
78,"""18: Redact contact information""","""\n when\n Section(text.contains(\""Contact point:\"")\n || text.contains(\""Phone:\"")\n || text.contains(\""Fax:\"")\n || text.contains(\""Tel.:\"")\n || text.contains(\""Tel:\"")\n || text.contains(\""E-mail:\"")\n || text.contains(\""Email:\"")\n || text.contains(\""e-mail:\"")\n || text.contains(\""E-mail address:\"")\n || text.contains(\""Alternative contact:\"")\n || text.contains(\""Telephone number:\"")\n || text.contains(\""Telephone No:\"")\n || text.contains(\""Fax number:\"")\n || text.contains(\""Telephone:\"")\n || text.contains(\""Phone No.\"")\n || text.contains(\""European contact:\""))\n then\n section.redactLineAfter(\""Contact point:\"", \""PII\"", 18, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Phone:\"", \""PII\"", 18, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Fax:\"", \""PII\"", 18, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Tel.:\"", \""PII\"", 18, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Tel:\"", \""PII\"", 18, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""E-mail:\"", \""PII\"", 18, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Email:\"", \""PII\"", 18, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""e-mail:\"", \""PII\"", 18, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""E-mail address:\"", \""PII\"", 18, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Contact:\"", \""PII\"", 18, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Alternative contact:\"", \""PII\"", 18, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Telephone number:\"", \""PII\"", 18, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Telephone No:\"", \""PII\"", 18, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Fax number:\"", \""PII\"", 18, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Telephone:\"", \""PII\"", 18, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Phone No.\"", \""PII\"", 18, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactBetween(\""No:\"", \""Fax\"", \""PII\"", 18, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactBetween(\""Contact:\"", \""Tel.:\"", \""PII\"", 18, true, \""Contact information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""European contact:\"", \""PII\"", 18, true, \""Contact information was found\"", \""links_producer_applicant\"");\n end""","[PII.4.0, PII.4.1, PII.6.0, PII.6.1]"
79,"""19: Redact contact information if applicant is found""","""\n when\n Section(headlineContainsWord(\""applicant\"") || text.contains(\""Applicant\"") || headlineContainsWord(\""Primary contact\"") || headlineContainsWord(\""Alternative contact\"") || text.contains(\""Telephone number:\""))\n then\n section.redactLineAfter(\""Contact point:\"", \""PII\"", 19, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Phone:\"", \""PII\"", 19, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Fax:\"", \""PII\"", 19, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Tel.:\"", \""PII\"", 19, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Tel:\"", \""PII\"", 19, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""E-mail:\"", \""PII\"", 19, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Email:\"", \""PII\"", 19, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""e-mail:\"", \""PII\"", 19, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""E-mail address:\"", \""PII\"", 19, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Contact:\"", \""PII\"", 19, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Alternative contact:\"", \""PII\"", 19, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Telephone number:\"", \""PII\"", 19, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Telephone No:\"", \""PII\"", 19, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Fax number:\"", \""PII\"", 19, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Telephone:\"", \""PII\"", 19, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Phone No.\"", \""PII\"", 19, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactBetween(\""No:\"", \""Fax\"", \""PII\"", 19, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactBetween(\""Contact:\"", \""Tel.:\"", \""PII\"", 19, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""European contact:\"", \""PII\"", 19, true, \""Applicant information was found\"", \""links_producer_applicant\"");\n end""",[PII.7.0]
80,"""19: Redact AUTHOR(S)""","""\n when\n Section(searchText.contains(\""AUTHOR(S):\""))\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""COMPLETION DATE:\"", \""PII\"", 19, true, \""AUTHOR(S) was found\"", \""links_producer_applicant\"");\n end""","[PII.9.0, PII.9.1]"
81,"""19: Redacted PII Personal Identification Information (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesType(\""PII\""))\n then\n section.redact(\""PII\"", 19, \""PII (Personal Identification Information) found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.0.0]
82,"""19: Redacted PII Personal Identification Information (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesType(\""PII\""))\n then\n section.redact(\""PII\"", 19, \""Personal information found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.0.0]
83,"""19: Do not redact Names and Addresses if Published Information found""","""\n when\n Section(matchesType(\""published_information\""))\n then\n section.redactNotAndReference(\""CBI_author\"",\""published_information\"", 19, \""Published Information found\"");\n section.redactNotAndReference(\""CBI_address\"",\""published_information\"", 19, \""Published Information found\"");\n end""",[CBI.7.0]
84,"""20: Redact contact information if Producer is found""","""\n when\n Section(text.toLowerCase().contains(\""producer of the plant protection\"") || text.toLowerCase().contains(\""producer of the active substance\"") || text.contains(\""Manufacturer of the active substance\"") || text.contains(\""Manufacturer:\"") || text.contains(\""Producer or producers of the active substance\""))\n then\n section.redactLineAfter(\""Contact:\"", \""PII\"", 20, true, \""Producer was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Telephone:\"", \""PII\"", 20, true, \""Producer was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Phone:\"", \""PII\"", 20, true, \""Producer was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Fax:\"", \""PII\"", 20, true, \""Producer was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""E-mail:\"", \""PII\"", 20, true, \""Producer was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Contact:\"", \""PII\"", 20, true, \""Producer was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Fax number:\"", \""PII\"", 20, true, \""Producer was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Telephone number:\"", \""PII\"", 20, true, \""Producer was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Tel:\"", \""PII\"", 20, true, \""Producer was found\"", \""links_producer_applicant\"");\n section.redactLineAfter(\""Phone No.\"", \""PII\"", 20, true, \""Producer was found\"", \""links_producer_applicant\"");\n section.redactBetween(\""No:\"", \""Fax\"", \""PII\"", 20, true, \""Producer was found\"", \""links_producer_applicant\"");\n end""",[PII.8.0]
85,"""20: Redact PERFORMING LABORATORY""","""\n when\n Section(searchText.contains(\""PERFORMING LABORATORY:\""))\n then\n section.redactBetween(\""PERFORMING LABORATORY:\"", \""LABORATORY PROJECT ID:\"", \""PII\"", 20, true, \""PERFORMING LABORATORY was found\"", \""links_producer_applicant\"");\n end""","[CBI.20.0, CBI.20.1]"
86,"""20: Redacted PII Personal Identification Information (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesType(\""PII\""))\n then\n section.redact(\""PII\"", 20, \""Personal information found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.0.1]
87,"""20: Redacted PII Personal Identification Information (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesType(\""PII\""))\n then\n section.redact(\""PII\"", 20, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.0.1]
88,"""21: Redact Emails by RegEx (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""@\""))\n then\n section.redactByRegEx(\""\\\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\\\.[A-Z]{2,4}\\\\b\"", true, 0, \""PII\"", 21, \""PII (Personal Identification Information) found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.1.0]
89,"""21: Redact Emails by RegEx (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""@\""))\n then\n section.redactByRegEx(\""\\\\b([A-Za-z0-9._%+\\\\-]+@[A-Za-z0-9.\\\\-]+\\\\.[A-Za-z\\\\-]{1,23}[A-Za-z])\\\\b\"", true, 1, \""PII\"", 21, \""Personal information found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.1.0]
90,"""21: Redact On behalf of Sequani Ltd.:""","""\n when\n Section(searchText.contains(\""On behalf of Sequani Ltd.: Name Title\""))\n then\n section.redactBetween(\""On behalf of Sequani Ltd.: Name Title\"", \""On behalf of\"", \""PII\"", 21, false , \""PII (Personal Identification Information) found\"", \""links_producer_applicant\"");\n end""",[PII.11.0]
91,"""21: Redact AUTHOR(S)""","""\n when\n Section(searchText.contains(\""AUTHOR(S):\""))\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""COMPLETION DATE:\"", \""PII\"", 21, true, \""AUTHOR(S) was found\"", \""links_producer_applicant\"");\n end""","[PII.9.0, PII.9.1]"
92,"""22: Redact Emails by RegEx (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""@\""))\n then\n section.redactByRegEx(\""\\\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\\\.[A-Z]{2,4}\\\\b\"", true, 0, \""PII\"", 22, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.1.1]
93,"""22: Redact Emails by RegEx (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""@\""))\n then\n section.redactByRegEx(\""\\\\b([A-Za-z0-9._%+\\\\-]+@[A-Za-z0-9.\\\\-]+\\\\.[A-Za-z\\\\-]{1,23}[A-Za-z])\\\\b\"", true, 1, \""PII\"", 22, \""Personal information found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.1.1]
94,"""22: Redact PERFORMING LABORATORY""","""\n when\n Section(searchText.contains(\""PERFORMING LABORATORY:\""))\n then\n section.redactBetween(\""PERFORMING LABORATORY:\"", \""LABORATORY PROJECT ID:\"", \""PII\"", 22, true, \""PERFORMING LABORATORY was found\"", \""links_producer_applicant\"");\n end""","[CBI.20.0, CBI.20.1]"
95,"""22: Redact On behalf of Syngenta Ltd.:""","""\n when\n Section(searchText.contains(\""On behalf of Syngenta Ltd.: Name Title\""))\n then\n section.redactBetween(\""On behalf of Syngenta Ltd.: Name Title\"", \""Study dates\"", \""PII\"", 22, false , \""PII (Personal Identification Information) found\"", \""links_producer_applicant\"");\n end""",[PII.11.0]
96,"""23: Redact contact information (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (text.contains(\""Contact point:\"")\n || text.contains(\""Phone:\"")\n || text.contains(\""Fax:\"")\n || text.contains(\""Tel.:\"")\n || text.contains(\""Tel:\"")\n || text.contains(\""E-mail:\"")\n || text.contains(\""Email:\"")\n || text.contains(\""e-mail:\"")\n || text.contains(\""E-mail address:\"")\n || text.contains(\""Alternative contact:\"")\n || text.contains(\""Telephone number:\"")\n || text.contains(\""Telephone No:\"")\n || text.contains(\""Fax number:\"")\n || text.contains(\""Telephone:\"")\n || text.contains(\""Phone No.\"")\n || text.contains(\""European contact:\"")))\n then\n section.redactLineAfter(\""Contact point:\"", \""PII\"", 23, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Phone:\"", \""PII\"", 23, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Fax:\"", \""PII\"", 23, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Tel.:\"", \""PII\"", 23, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Tel:\"", \""PII\"", 23, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""E-mail:\"", \""PII\"", 23, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Email:\"", \""PII\"", 23, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""e-mail:\"", \""PII\"", 23, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""E-mail address:\"", \""PII\"", 23, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Contact:\"", \""PII\"", 23, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Alternative contact:\"", \""PII\"", 23, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone number:\"", \""PII\"", 23, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone No:\"", \""PII\"", 23, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Fax number:\"", \""PII\"", 23, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone:\"", \""PII\"", 23, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Phone No.\"", \""PII\"", 23, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactBetween(\""No:\"", \""Fax\"", \""PII\"", 23, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactBetween(\""Contact:\"", \""Tel.:\"", \""PII\"", 23, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""European contact:\"", \""PII\"", 23, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""","[PII.5.0, PII.6.0]"
97,"""23: Redact contact information (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (text.contains(\""Contact point:\"")\n || text.contains(\""Contact:\"")\n || text.contains(\""Alternative contact:\"")\n || (text.contains(\""No:\"") && text.contains(\""Fax\""))\n || (text.contains(\""Contact:\"") && text.contains(\""Tel.:\""))\n || text.contains(\""European contact:\"")\n ))\n then\n section.redactLineAfter(\""Contact point:\"", \""PII\"", 23, true, \""Personal information found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Contact:\"", \""PII\"", 23, true, \""Personal information found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Alternative contact:\"", \""PII\"", 23, true, \""Personal information found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactBetween(\""No:\"", \""Fax\"", \""PII\"", 23, true, \""Personal information found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactBetween(\""Contact:\"", \""Tel.:\"", \""PII\"", 23, true, \""Personal information found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""European contact:\"", \""PII\"", 23, true, \""Personal information found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""","[PII.4.0, PII.6.0]"
98,"""24: Redact contact information (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (text.contains(\""Contact point:\"")\n || text.contains(\""Contact:\"")\n || text.contains(\""Alternative contact:\"")\n || (text.contains(\""No:\"") && text.contains(\""Fax\""))\n || (text.contains(\""Contact:\"") && text.contains(\""Tel.:\""))\n || text.contains(\""European contact:\"")\n ))\n then\n section.redactLineAfter(\""Contact point:\"", \""PII\"", 24, true, \""Personal information found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Contact:\"", \""PII\"", 24, true, \""Personal information found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Alternative contact:\"", \""PII\"", 24, true, \""Personal information found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactBetween(\""No:\"", \""Fax\"", \""PII\"", 24, true, \""Personal information found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactBetween(\""Contact:\"", \""Tel.:\"", \""PII\"", 24, true, \""Personal information found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""European contact:\"", \""PII\"", 24, true, \""Personal information found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[PII.5.1, PII.6.1]"
99,"""24: Redact contact information (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (text.contains(\""Contact point:\"")\n || text.contains(\""Phone:\"")\n || text.contains(\""Fax:\"")\n || text.contains(\""Tel.:\"")\n || text.contains(\""Tel:\"")\n || text.contains(\""E-mail:\"")\n || text.contains(\""Email:\"")\n || text.contains(\""e-mail:\"")\n || text.contains(\""E-mail address:\"")\n || text.contains(\""Alternative contact:\"")\n || text.contains(\""Telephone number:\"")\n || text.contains(\""Telephone No:\"")\n || text.contains(\""Fax number:\"")\n || text.contains(\""Telephone:\"")\n || text.contains(\""Phone No.\"")\n || text.contains(\""European contact:\"")))\n then\n section.redactLineAfter(\""Contact point:\"", \""PII\"", 24, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Phone:\"", \""PII\"", 24, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Fax:\"", \""PII\"", 24, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Tel.:\"", \""PII\"", 24, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Tel:\"", \""PII\"", 24, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""E-mail:\"", \""PII\"", 24, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Email:\"", \""PII\"", 24, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""e-mail:\"", \""PII\"", 24, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""E-mail address:\"", \""PII\"", 24, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Contact:\"", \""PII\"", 24, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Alternative contact:\"", \""PII\"", 24, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone number:\"", \""PII\"", 24, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone No:\"", \""PII\"", 24, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Fax number:\"", \""PII\"", 24, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone:\"", \""PII\"", 24, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Phone No.\"", \""PII\"", 24, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactBetween(\""No:\"", \""Fax\"", \""PII\"", 24, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactBetween(\""Contact:\"", \""Tel.:\"", \""PII\"", 24, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""European contact:\"", \""PII\"", 24, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[PII.4.1, PII.6.1]"
100,"""25: Redact Phone and Fax by RegEx""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (\n text.contains(\""Contact\"")\n || text.contains(\""Telephone\"")\n || text.contains(\""Phone\"")\n || text.contains(\""Ph.\"")\n || text.contains(\""Fax\"")\n || text.contains(\""Tel\"")\n || text.contains(\""Ter\"")\n || text.contains(\""Cell\"")\n || text.contains(\""Mobile\"")\n || text.contains(\""Fel\"")\n || text.contains(\""Fer\"")\n ))\n then\n section.redactByRegEx(\""\\\\b(contact|telephone|phone|fax|tel|ter|cell|mobile|fel|fer)[a-zA-Z\\\\s]{0,10}[:.\\\\s]{0,3}([\\\\+\\\\d\\\\(][\\\\s\\\\d\\\\(\\\\)\\\\-\\\\/\\\\.]{4,100}\\\\d)\\\\b\"", true, 2, \""PII\"", 25, \""Personal information found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.2.0]
101,"""25: Redact Phone and Fax by RegEx (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (\n text.contains(\""Contact\"")\n || text.contains(\""Telephone\"")\n || text.contains(\""Phone\"")\n || text.contains(\""Fax\"")\n || text.contains(\""Tel\"")\n || text.contains(\""Ter\"")\n || text.contains(\""Mobile\"")\n || text.contains(\""Fel\"")\n || text.contains(\""Fer\"")\n ))\n then\n section.redactByRegEx(\""\\\\b(contact|telephone|phone|fax|tel|ter|mobile|fel|fer)[a-zA-Z\\\\s]{0,10}[:.\\\\s]{0,3}([\\\\+\\\\d\\\\(][\\\\s\\\\d\\\\(\\\\)\\\\-\\\\/\\\\.]{4,100}\\\\d)\\\\b\"", true, 2, \""PII\"", 25, \""Personal information found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.2.0]
102,"""25: Redact contact information if applicant is found (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (headlineContainsWord(\""applicant\"") || text.contains(\""Applicant\"") || headlineContainsWord(\""Primary contact\"") || headlineContainsWord(\""Alternative contact\"") || text.contains(\""Telephone number:\"")))\n then\n section.redactLineAfter(\""Contact point:\"", \""PII\"", 25, true, \""Applicant information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Phone:\"", \""PII\"", 25, true, \""Applicant information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Fax:\"", \""PII\"", 25, true, \""Applicant information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Tel.:\"", \""PII\"", 25, true, \""Applicant information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Tel:\"", \""PII\"", 25, true, \""Applicant information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""E-mail:\"", \""PII\"", 25, true, \""Applicant information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Email:\"", \""PII\"", 25, true, \""Applicant information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""e-mail:\"", \""PII\"", 25, true, \""Applicant information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""E-mail address:\"", \""PII\"", 25, true, \""Applicant information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Contact:\"", \""PII\"", 25, true, \""Applicant information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Alternative contact:\"", \""PII\"", 25, true, \""Applicant information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone number:\"", \""PII\"", 25, true, \""Applicant information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone No:\"", \""PII\"", 25, true, \""Applicant information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Fax number:\"", \""PII\"", 25, true, \""Applicant information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone:\"", \""PII\"", 25, true, \""Applicant information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Phone No.\"", \""PII\"", 25, true, \""Applicant information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactBetween(\""No:\"", \""Fax\"", \""PII\"", 25, true, \""Applicant information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactBetween(\""Contact:\"", \""Tel.:\"", \""PII\"", 25, true, \""Applicant information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""European contact:\"", \""PII\"", 25, true, \""Applicant information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.7.0]
103,"""33: Purity Hint, 34: Purity Hint, 50: Purity Hint, 25: Purity Hint, 39: Purity Hint""","""\n when\n Section(searchText.toLowerCase().contains(\""purity\""))\n then\n\t section.addHintAnnotationByRegEx(\""(purity ?( of|\\\\(.{1,20}\\\\))?( ?:)?) .{0,5}[\\\\d\\\\.]+( .{0,4}\\\\.)? ?%\"", true, 1, \""hint_only\"");\n end""",[ETC.0.0]
104,"""25: Redact Purity""","""\n when\n Section(searchText.contains(\""purity\""))\n then\n\t section.redactByRegEx(\""purity ?:? (([\\\\d\\\\.]+)( .{0,4}\\\\.)? ?%)\"", true, 1, \""purity\"", 17, \""Purity found\"", \""method_manufacture\"");\n end""",[ETC.1.0]
105,"""26: Redact Phone and Fax by RegEx (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (\n text.contains(\""Contact\"")\n || text.contains(\""Telephone\"")\n || text.contains(\""Phone\"")\n || text.contains(\""Ph.\"")\n || text.contains(\""Fax\"")\n || text.contains(\""Tel\"")\n || text.contains(\""Ter\"")\n || text.contains(\""Cell\"")\n || text.contains(\""Mobile\"")\n || text.contains(\""Fel\"")\n || text.contains(\""Fer\"")\n ))\n then\n section.redactByRegEx(\""\\\\b(contact|telephone|phone|fax|tel|ter|cell|mobile|fel|fer)[a-zA-Z\\\\s]{0,10}[:.\\\\s]{0,3}([\\\\+\\\\d\\\\(][\\\\s\\\\d\\\\(\\\\)\\\\-\\\\/\\\\.]{4,100}\\\\d)\\\\b\"", true, 2, \""PII\"", 26, \""Personal information found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.2.1]
106,"""26: Redact contact information if applicant is found (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (headlineContainsWord(\""applicant\"") || text.contains(\""Applicant\"") || headlineContainsWord(\""Primary contact\"") || headlineContainsWord(\""Alternative contact\"") || text.contains(\""Telephone number:\"")))\n then\n section.redactLineAfter(\""Contact point:\"", \""PII\"", 26, true, \""Applicant information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Phone:\"", \""PII\"", 26, true, \""Applicant information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Fax:\"", \""PII\"", 26, true, \""Applicant information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Tel.:\"", \""PII\"", 26, true, \""Applicant information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Tel:\"", \""PII\"", 26, true, \""Applicant information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""E-mail:\"", \""PII\"", 26, true, \""Applicant information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Email:\"", \""PII\"", 26, true, \""Applicant information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""e-mail:\"", \""PII\"", 26, true, \""Applicant information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""E-mail address:\"", \""PII\"", 26, true, \""Applicant information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Contact:\"", \""PII\"", 26, true, \""Applicant information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Alternative contact:\"", \""PII\"", 26, true, \""Applicant information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone number:\"", \""PII\"", 26, true, \""Applicant information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone No:\"", \""PII\"", 26, true, \""Applicant information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Fax number:\"", \""PII\"", 26, true, \""Applicant information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone:\"", \""PII\"", 26, true, \""Applicant information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Phone No.\"", \""PII\"", 26, true, \""Applicant information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactBetween(\""No:\"", \""Fax\"", \""PII\"", 26, true, \""Applicant information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactBetween(\""Contact:\"", \""Tel.:\"", \""PII\"", 26, true, \""Applicant information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""European contact:\"", \""PII\"", 26, true, \""Applicant information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.7.0]
107,"""26: Redact signatures""","""\n when\n Section(matchesImageType(\""signature\""))\n then\n section.redactImage(\""signature\"", 26, \""Signature found\"", \""names_addresses_persons\"");\n end""",[ETC.2.0]
108,"""26: Redact Phone and Fax by RegEx (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (\n text.contains(\""Contact\"")\n || text.contains(\""Telephone\"")\n || text.contains(\""Phone\"")\n || text.contains(\""Fax\"")\n || text.contains(\""Tel\"")\n || text.contains(\""Ter\"")\n || text.contains(\""Mobile\"")\n || text.contains(\""Fel\"")\n || text.contains(\""Fer\"")\n ))\n then\n section.redactByRegEx(\""\\\\b(contact|telephone|phone|fax|tel|ter|mobile|fel|fer)[a-zA-Z\\\\s]{0,10}[:.\\\\s]{0,3}([\\\\+\\\\d\\\\(][\\\\s\\\\d\\\\(\\\\)\\\\-\\\\/\\\\.]{4,100}\\\\d)\\\\b\"", true, 2, \""PII\"", 26, \""Personal information found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.2.1]
109,"""27: Redact AUTHOR(S) (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"")\n && searchText.contains(\""AUTHOR(S):\"")\n && searchText.contains(\""COMPLETION DATE:\"")\n && !searchText.contains(\""STUDY COMPLETION DATE:\"")\n )\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""COMPLETION DATE:\"", \""PII\"", 27, true, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.0]
110,"""27: Redact Logos""","""\n when\n Section(matchesImageType(\""logo\""))\n then\n section.redactImage(\""logo\"", 27, \""Logo found\"", \""names_addresses_persons\"");\n end""",[ETC.3.0]
111,"""27: Redact contact information if Producer is found (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (text.toLowerCase().contains(\""producer of the plant protection\"") || text.toLowerCase().contains(\""producer of the active substance\"") || text.contains(\""Manufacturer of the active substance\"") || text.contains(\""Manufacturer:\"") || text.contains(\""Producer or producers of the active substance\"")))\n then\n section.redactLineAfter(\""Contact:\"", \""PII\"", 27, true, \""Producer was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone:\"", \""PII\"", 27, true, \""Producer was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Phone:\"", \""PII\"", 27, true, \""Producer was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Fax:\"", \""PII\"", 27, true, \""Producer was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""E-mail:\"", \""PII\"", 27, true, \""Producer was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Contact:\"", \""PII\"", 27, true, \""Producer was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Fax number:\"", \""PII\"", 27, true, \""Producer was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone number:\"", \""PII\"", 27, true, \""Producer was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Tel:\"", \""PII\"", 27, true, \""Producer was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Phone No.\"", \""PII\"", 27, true, \""Producer was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactBetween(\""No:\"", \""Fax\"", \""PII\"", 27, true, \""Producer was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.8.0]
112,"""28: Redact contact information if Producer is found (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (text.toLowerCase().contains(\""producer of the plant protection\"") || text.toLowerCase().contains(\""producer of the active substance\"") || text.contains(\""Manufacturer of the active substance\"") || text.contains(\""Manufacturer:\"") || text.contains(\""Producer or producers of the active substance\"")))\n then\n section.redactLineAfter(\""Contact:\"", \""PII\"", 28, true, \""Producer was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone:\"", \""PII\"", 28, true, \""Producer was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Phone:\"", \""PII\"", 28, true, \""Producer was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Fax:\"", \""PII\"", 28, true, \""Producer was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""E-mail:\"", \""PII\"", 28, true, \""Producer was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Contact:\"", \""PII\"", 28, true, \""Producer was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Fax number:\"", \""PII\"", 28, true, \""Producer was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone number:\"", \""PII\"", 28, true, \""Producer was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Tel:\"", \""PII\"", 28, true, \""Producer was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Phone No.\"", \""PII\"", 28, true, \""Producer was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactBetween(\""No:\"", \""Fax\"", \""PII\"", 28, true, \""Producer was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.8.0]
113,"""28: Redact AUTHOR(S) (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"")\n && searchText.contains(\""AUTHOR(S):\"")\n && searchText.contains(\""COMPLETION DATE:\"")\n && !searchText.contains(\""STUDY COMPLETION DATE:\"")\n )\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""COMPLETION DATE:\"", \""PII\"", 28, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.0]
114,"""28: Redact dossier dictionary match""","""\n when\n Section(matchesType(\""dossier_redaction\""))\n then\n section.redact(\""dossier_redaction\"", 28, \""Specification of impurity found\"", \""specification_impurity_active_substance\"");\n end""","[ETC.4.0, ETC.4.1, ETC.4.2]"
115,"""29: Redact AUTHOR(S) (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""AUTHOR(S):\"") && searchText.contains(\""COMPLETION DATE:\"") && !searchText.contains(\""STUDY COMPLETION DATE:\""))\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""COMPLETION DATE:\"", \""PII\"", 29, true, \""AUTHOR(S) was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.0]
116,"""34: Ignore dossier_redaction entries if confidentiality is not 'confidential', 51: Ignore dossier_redaction entries if confidential, 29: Ignore dossier_redaction unless confidential, 40: Ignore dossier_redaction entries if confidential""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Confidentiality\"",\""confidential\"") && matchesType(\""dossier_redaction\""));\n then\n section.ignore(\""dossier_redaction\"");\n end""",[ETC.5.0]
117,"""29: Redact AUTHOR(S) (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"")\n && searchText.contains(\""AUTHOR(S):\"")\n && searchText.contains(\""STUDY COMPLETION DATE:\"")\n )\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""STUDY COMPLETION DATE:\"", \""PII\"", 29, true, \""AUTHOR(S) was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.0]
118,"""30: Redact AUTHOR(S) (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"")\n && searchText.contains(\""AUTHOR(S):\"")\n && searchText.contains(\""STUDY COMPLETION DATE:\"")\n )\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""STUDY COMPLETION DATE:\"", \""PII\"", 30, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.1]
119,"""30: Redacted PII Personal Identification Information (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesType(\""PII\""))\n then\n section.redact(\""PII\"", 30, \""PII (Personal Identification Information) found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.0.0]
120,"""30: Redact AUTHOR(S) (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""AUTHOR(S):\"") && searchText.contains(\""COMPLETION DATE:\"") && !searchText.contains(\""STUDY COMPLETION DATE:\""))\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""COMPLETION DATE:\"", \""PII\"", 30, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.1]
121,"""31: Redacted PII Personal Identification Information (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesType(\""PII\""))\n then\n section.redact(\""PII\"", 31, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.0.1]
122,"""31: Redact AUTHOR(S) (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""AUTHOR(S):\"") && searchText.contains(\""STUDY COMPLETION DATE:\""))\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""STUDY COMPLETION DATE:\"", \""PII\"", 31, true, \""AUTHOR(S) was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.0]
123,"""31: Redact PERFORMING LABORATORY (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"")\n && searchText.contains(\""PERFORMING LABORATORY:\"")\n )\n then\n section.redactBetween(\""PERFORMING LABORATORY:\"", \""LABORATORY PROJECT ID:\"", \""CBI_address\"", 31, true, \""PERFORMING LABORATORY was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactNot(\""CBI_address\"", 31, \""Performing laboratory found for non vertebrate study\"");\n end""",[CBI.20.0]
124,"""32: Redact PERFORMING LABORATORY (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"")\n && searchText.contains(\""PERFORMING LABORATORY:\""))\n then\n section.redactBetween(\""PERFORMING LABORATORY:\"", \""LABORATORY PROJECT ID:\"", \""CBI_address\"", 32, true, \""PERFORMING LABORATORY was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[CBI.20.1]
125,"""32: Redact Emails by RegEx (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""@\""))\n then\n section.redactByRegEx(\""\\\\b([A-Za-z0-9._%+\\\\-]+@[A-Za-z0-9.\\\\-]+\\\\.[A-Za-z\\\\-]{1,23}[A-Za-z])\\\\b\"", true, 1, \""PII\"", 32, \""PII (Personal Identification Information) found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.1.0]
126,"""32: Redact AUTHOR(S) (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""AUTHOR(S):\"") && searchText.contains(\""STUDY COMPLETION DATE:\""))\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""STUDY COMPLETION DATE:\"", \""PII\"", 32, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.1]
127,"""33: Redact Emails by RegEx (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""@\""))\n then\n section.redactByRegEx(\""\\\\b([A-Za-z0-9._%+\\\\-]+@[A-Za-z0-9.\\\\-]+\\\\.[A-Za-z\\\\-]{1,23}[A-Za-z])\\\\b\"", true, 1, \""PII\"", 33, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.1.1]
128,"""33: Redact study director abbreviation""","""\n when\n Section((searchText.contains(\""KATH\"") || searchText.contains(\""BECH\"") || searchText.contains(\""KML\"")))\n then\n section.redactWordPartByRegEx(\""((KATH)|(BECH)|(KML)) ?(\\\\d{4})\"", true, 0, 1, \""PII\"", 34, \""Personal information found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.10.0]
129,"""33: Redact PERFORMING LABORATORY (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""PERFORMING LABORATORY:\""))\n then\n section.redactBetween(\""PERFORMING LABORATORY:\"", \""LABORATORY PROJECT ID:\"", \""CBI_address\"", 33, true, \""PERFORMING LABORATORY was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactNot(\""CBI_address\"", 33, \""Performing laboratory found for non vertebrate study\"");\n end""",[CBI.20.0]
130,"""34: Redact PERFORMING LABORATORY (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""PERFORMING LABORATORY:\""))\n then\n section.redactBetween(\""PERFORMING LABORATORY:\"", \""LABORATORY PROJECT ID:\"", \""CBI_address\"", 34, true, \""PERFORMING LABORATORY was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[CBI.20.1]
131,"""34: Redact telephone numbers by RegEx (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && containsRegEx(\""[+]\\\\d{1,}\"", true))\n then\n section.redactByRegEx(\""((([+]\\\\d{1,3} (\\\\d{7,12})\\\\b)|([+]\\\\d{1,3}(\\\\d{3,12})\\\\b|[+]\\\\d{1,3}([ -]\\\\(?\\\\d{1,6}\\\\)?){2,4})|[+]\\\\d{1,3} ?((\\\\d{2,6}\\\\)?)([ -]\\\\d{2,6}){1,4}))(-\\\\d{1,3})?\\\\b)\"", true, 1, \""PII\"", 34, \""PII (Personal Identification Information) found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.3.0]
132,"""35: Redact telephone numbers by RegEx (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && containsRegEx(\""[+]\\\\d{1,}\"", true))\n then\n section.redactByRegEx(\""((([+]\\\\d{1,3} (\\\\d{7,12})\\\\b)|([+]\\\\d{1,3}(\\\\d{3,12})\\\\b|[+]\\\\d{1,3}([ -]\\\\(?\\\\d{1,6}\\\\)?){2,4})|[+]\\\\d{1,3} ?((\\\\d{2,6}\\\\)?)([ -]\\\\d{2,6}){1,4}))(-\\\\d{1,3})?\\\\b)\"", true, 1, \""PII\"", 35, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.3.1]
133,"""35: Redact signatures (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesImageType(\""signature\""))\n then\n section.redactImage(\""signature\"", 35, \""Signature found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[ETC.2.0]
134,"""36: Redact signatures (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesImageType(\""signature\""))\n then\n section.redactImage(\""signature\"", 36, \""Signature found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[ETC.2.0]
135,"""37: Redact contact information (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (text.contains(\""Contact point:\"")\n || text.contains(\""Phone:\"")\n || text.contains(\""Fax:\"")\n || text.contains(\""Tel.:\"")\n || text.contains(\""Tel:\"")\n || text.contains(\""E-mail:\"")\n || text.contains(\""Email:\"")\n || text.contains(\""e-mail:\"")\n || text.contains(\""E-mail address:\"")\n || text.contains(\""Alternative contact:\"")\n || text.contains(\""Telephone number:\"")\n || text.contains(\""Telephone No:\"")\n || text.contains(\""Fax number:\"")\n || text.contains(\""Telephone:\"")\n || text.contains(\""Phone No.\"")\n || text.contains(\""European contact:\"")))\n then\n section.redactLineAfter(\""Contact point:\"", \""PII\"", 37, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Phone:\"", \""PII\"", 37, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Fax:\"", \""PII\"", 37, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Tel.:\"", \""PII\"", 37, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Tel:\"", \""PII\"", 37, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""E-mail:\"", \""PII\"", 37, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Email:\"", \""PII\"", 37, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""e-mail:\"", \""PII\"", 37, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""E-mail address:\"", \""PII\"", 37, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Contact:\"", \""PII\"", 37, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Alternative contact:\"", \""PII\"", 37, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone number:\"", \""PII\"", 37, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone No:\"", \""PII\"", 37, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Fax number:\"", \""PII\"", 37, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone:\"", \""PII\"", 37, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Phone No.\"", \""PII\"", 37, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactBetween(\""No:\"", \""Fax\"", \""PII\"", 37, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactBetween(\""Contact:\"", \""Tel.:\"", \""PII\"", 37, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""European contact:\"", \""PII\"", 37, true, \""Contact information was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""","[PII.4.0, PII.6.0]"
136,"""38: Redact contact information (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (text.contains(\""Contact point:\"")\n || text.contains(\""Phone:\"")\n || text.contains(\""Fax:\"")\n || text.contains(\""Tel.:\"")\n || text.contains(\""Tel:\"")\n || text.contains(\""E-mail:\"")\n || text.contains(\""Email:\"")\n || text.contains(\""e-mail:\"")\n || text.contains(\""E-mail address:\"")\n || text.contains(\""Alternative contact:\"")\n || text.contains(\""Telephone number:\"")\n || text.contains(\""Telephone No:\"")\n || text.contains(\""Fax number:\"")\n || text.contains(\""Telephone:\"")\n || text.contains(\""Phone No.\"")\n || text.contains(\""European contact:\"")))\n then\n section.redactLineAfter(\""Contact point:\"", \""PII\"", 38, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Phone:\"", \""PII\"", 38, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Fax:\"", \""PII\"", 38, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Tel.:\"", \""PII\"", 38, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Tel:\"", \""PII\"", 38, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""E-mail:\"", \""PII\"", 38, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Email:\"", \""PII\"", 38, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""e-mail:\"", \""PII\"", 38, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""E-mail address:\"", \""PII\"", 38, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Contact:\"", \""PII\"", 38, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Alternative contact:\"", \""PII\"", 38, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone number:\"", \""PII\"", 38, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone No:\"", \""PII\"", 38, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Fax number:\"", \""PII\"", 38, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone:\"", \""PII\"", 38, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Phone No.\"", \""PII\"", 38, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactBetween(\""No:\"", \""Fax\"", \""PII\"", 38, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactBetween(\""Contact:\"", \""Tel.:\"", \""PII\"", 38, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""European contact:\"", \""PII\"", 38, true, \""Contact information was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[PII.4.1, PII.6.1]"
137,"""39: Redact AUTHOR(S) (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""AUTHOR(S):\"") && searchText.contains(\""COMPLETION DATE:\"") && !searchText.contains(\""STUDY COMPLETION DATE:\""))\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""COMPLETION DATE:\"", \""PII\"", 39, true, \""AUTHOR(S) was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.0]
138,"""40: Redact AUTHOR(S) (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""AUTHOR(S):\"") && searchText.contains(\""COMPLETION DATE:\"") && !searchText.contains(\""STUDY COMPLETION DATE:\""))\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""COMPLETION DATE:\"", \""PII\"", 40, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.1]
139,"""41: Redact signatures (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesImageType(\""signature\""))\n then\n section.redactImage(\""signature\"", 41, \""Signature found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[ETC.2.0]
140,"""41: Redact AUTHOR(S) (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""AUTHOR(S):\"") && searchText.contains(\""STUDY COMPLETION DATE:\""))\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""STUDY COMPLETION DATE:\"", \""PII\"", 41, true, \""AUTHOR(S) was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.0]
141,"""42: Redact signatures (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesImageType(\""signature\""))\n then\n section.redactImage(\""signature\"", 42, \""Signature found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[ETC.2.0]
142,"""42: Redact AUTHOR(S) (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""AUTHOR(S):\"") && searchText.contains(\""STUDY COMPLETION DATE:\""))\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""STUDY COMPLETION DATE:\"", \""PII\"", 42, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.1]
143,"""43: Redact PERFORMING LABORATORY (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""PERFORMING LABORATORY:\""))\n then\n section.redactBetween(\""PERFORMING LABORATORY:\"", \""LABORATORY PROJECT ID:\"", \""CBI_address\"", 43, true, \""PERFORMING LABORATORY was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactNot(\""CBI_address\"", 43, \""Performing laboratory found for non vertebrate study\"");\n end""",[CBI.20.0]
144,"""43: Redact Logos (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesImageType(\""logo\""))\n then\n section.redactImage(\""logo\"", 43, \""Logo found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[ETC.3.0]
145,"""44: Redact PERFORMING LABORATORY (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""PERFORMING LABORATORY:\""))\n then\n section.redactBetween(\""PERFORMING LABORATORY:\"", \""LABORATORY PROJECT ID:\"", \""CBI_address\"", 44, true, \""PERFORMING LABORATORY was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[CBI.20.1]
146,"""52: Redact signatures (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesImageType(\""signature\""))\n then\n section.redactImage(\""signature\"", 52, \""Signature found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[ETC.2.0]
147,"""53: Redact signatures (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesImageType(\""signature\""))\n then\n section.redactImage(\""signature\"", 53, \""Signature found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[ETC.2.0]
148,"""54: Redact Logos (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesImageType(\""logo\""))\n then\n section.redactImage(\""logo\"", 54, \""Logo found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[ETC.3.0]
149,"""0: Expand CBI Authors with firstname initials""","""\n when\n Section(matchesType(\""CBI_author\""))\n then\n section.expandByRegEx(\""CBI_author\"", \""(,? [A-Z]\\\\.?( ?[A-Z]\\\\.?)?( ?[A-Z]\\\\.?)?\\\\b\\\\.?)\"", false, 1);\n end""",[CBI.18.0]
150,"""0: Expand CBI Authors with firstname initials""","""\n when\n Section(matchesType(\""CBI_author\""))\n then\n section.expandByRegEx(\""CBI_author\"", \""(,? [A-Z]\\\\.?( ?[A-Z]\\\\.?)?( ?[A-Z]\\\\.?)?\\\\b\\\\.?)\"", false, 1, \""[^\\\\s]+\"");\n end""",[CBI.18.0]
151,"""0: Expand CBI_author and PII matches with salutation prefix""","""\n when\n Section((matchesType(\""CBI_author\"") || matchesType(\""PII\"")) && (\n searchText.contains(\""Mr\"")\n || searchText.contains(\""Mrs\"")\n || searchText.contains(\""Ms\"")\n || searchText.contains(\""Miss\"")\n || searchText.contains(\""Sir\"")\n || searchText.contains(\""Madam\"")\n || searchText.contains(\""Madame\"")\n || searchText.contains(\""Mme\"")\n ))\n then\n section.expandByPrefixRegEx(\""CBI_author\"", \""\\\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\\\s?\\\\.?\\\\s*\"", false, 0);\n section.expandByPrefixRegEx(\""PII\"", \""\\\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\\\s?\\\\.?\\\\s*\"", false, 0);\n end""","[CBI.19.0, PII.12.0]"
152,"""102: Guidelines FileAttributes""","""\n when\n Section((text.contains(\""DATA REQUIREMENT(S):\"") || text.contains(\""TEST GUIDELINE(S):\"")) && (text.contains(\""OECD\"") || text.contains(\""EPA\"") || text.contains(\""OPPTS\"")))\n then\n section.addFileAttribute(\""OECD Number\"", \""OECD (No\\\\.? )?\\\\d{3}( \\\\(\\\\d{4}\\\\))?\"", false, 0);\n end""",[ETC.7.0]
153,"""28: Redact Logos""","""\n when\n Section(matchesImageType(\""logo\""))\n then\n section.redactImage(\""logo\"", 28, \""Logo found\"", \""names_addresses_persons\"");\n end""",[ETC.3.0]
154,"""8: Redact Author cells in Tables with Author header (Non vertebrate study)""","""\n when\n Section(hasTableHeader(\""h5.1\""))\n then\n section.redactCell(\""h5.1\"", 8, \""CBI_author\"", false, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""","[CBI.9.0, CBI.11.0]"
155,"""30: Ignore dossier_redactions if confidential""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Confidentiality\"",\""confidential\"") && matchesType(\""dossier_redactions\""));\n then\n section.ignore(\""dossier_redactions\"");\n end""",[ETC.5.0]
156,"""27: Redact formula""","""\n when\n Section(matchesImageType(\""formula\""))\n then\n section.redactImage(\""formula\"", 27, \""Formula found\"", \""names_addresses_persons\"");\n end""",[ETC.8.0]
157,"""5: Do not redact Names and Addresses if no redaction Indicator is contained""","""\n when\n Section(matchesType(\""vertebrate\""), matchesType(\""published_information\""))\n then\n section.redactNotAndReference(\""CBI_author\"",\""published_information\"", 5, \""Vertebrate and Published Information found\"");\n section.redactNotAndReference(\""CBI_address\"",\""published_information\"", 5, \""Vertebrate and Published Information found\"");\n end""",[CBI.4.0]
158,"""29: Redact Dossier Redactions""","""\n when\n Section(matchesType(\""dossier_redactions\""))\n then\n section.redact(\""dossier_redactions\"", 29, \""Dossier Redaction found\"", \""Article 39(1)(2) of Regulation (EC) No 178/2002\"");\n end""","[ETC.4.0, ETC.4.1, ETC.4.2]"
159,"""10: Redact determination of residues""","""\n when\n Section((\n searchText.toLowerCase.contains(\""determination of residues\"") ||\n searchText.toLowerCase.contains(\""determination of total residues\"")\n ) && (\n searchText.toLowerCase.contains(\""livestock\"") ||\n searchText.toLowerCase.contains(\""live stock\"") ||\n searchText.toLowerCase.contains(\""tissue\"") ||\n searchText.toLowerCase.contains(\""tissues\"") ||\n searchText.toLowerCase.contains(\""liver\"") ||\n searchText.toLowerCase.contains(\""muscle\"") ||\n searchText.toLowerCase.contains(\""bovine\"") ||\n searchText.toLowerCase.contains(\""ruminant\"") ||\n searchText.toLowerCase.contains(\""ruminants\"")\n ))\n then\n section.redact(\""CBI_author\"", 10, \""Determination of residues was found.\"", \""names_addresses_persons\"");\n section.redact(\""CBI_address\"", 10, \""Determination of residues was found.\"", \""names_addresses_persons\"");\n section.addHintAnnotation(\""determination of residues\"", \""must_redact\"");\n section.addHintAnnotation(\""livestock\"", \""must_redact\"");\n section.addHintAnnotation(\""live stock\"", \""must_redact\"");\n section.addHintAnnotation(\""tissue\"", \""must_redact\"");\n section.addHintAnnotation(\""tissues\"", \""must_redact\"");\n section.addHintAnnotation(\""liver\"", \""must_redact\"");\n section.addHintAnnotation(\""muscle\"", \""must_redact\"");\n section.addHintAnnotation(\""bovine\"", \""must_redact\"");\n section.addHintAnnotation(\""ruminant\"", \""must_redact\"");\n section.addHintAnnotation(\""ruminants\"", \""must_redact\"");\n end""",[CBI.15.0]
160,"""19: Redact AUTHOR(S)""","""\n when\n Section(searchText.contains(\""AUTHOR(S):\"") && fileAttributeByPlaceholderEquals(\""{fileattributes.vertebrateStudy}\"", \""true\""))\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""COMPLETION DATE:\"", \""PII\"", 19, true, \""AUTHOR(S) was found\"", \""links_producer_applicant\"");\n end""",[PII.9.1]
161,"""101: Redact CAS numbers""","""\n when\n Section(hasTableHeader(\""Sample #\""))\n then\n section.redactCell(\""Sample #\"", 8, \""PII\"", true, \""Redacted because row is a vertebrate study\"", \""names_addresses_persons\"");\n end""",[ETC.6.0]
162,"""21: Redact Emails by RegEx""","""\n when\n Section(searchText.contains(\""@\""))\n then\n section.redactByRegEx(\""\\\\b([A-Za-z0-9._%+\\\\-]+@[A-Za-z0-9.\\\\-]+\\\\.[A-Za-z\\\\-]{1,23}[A-Za-z])\\\\b\"", true, 1, \""PII\"", 21, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[PII.1.0, PII.1.1]"
163,"""32: Redact signatures""","""\n when\n Section(matchesImageType(\""signature\""))\n then\n section.redactImage(\""signature\"", 32, \""Signature found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[ETC.2.0, ETC.2.1]"
164,"""11: Do not redact Names and Addresses if Published Information found""","""\n when\n Section(matchesType(\""published_information\""))\n then\n section.redactNotAndReference(\""CBI_author\"",\""published_information\"", 11, \""Published Information found\"");\n section.redactNotAndReference(\""CBI_address\"",\""published_information\"", 11, \""Published Information found\"");\n end""","[CBI.7.0, CBI.7.1]"
165,"""9: Add recommendation for Addresses in Test Organism sections""","""\n when\n Section(searchText.contains(\""Species:\"") && searchText.contains(\""Source:\""))\n then\n section.recommendLineAfter(\""Source:\"", \""CBI_address\"");\n end""",[CBI.17.1]
166,"""5: Redact Author cells in Tables with Author header""","""\n when\n Section(hasTableHeader(\""Author\"") && !hasTableHeader(\""Vertebrate study Y/N\""))\n then\n section.redactCell(\""Author\"", 5, \""CBI_author\"", false, \""Author found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[CBI.9.1, CBI.10.1]"
167,"""21: Redact Phone and Fax by RegEx""","""\n when\n Section(\n text.contains(\""Telephone\"")\n || text.contains(\""Phone\"")\n || text.contains(\""Ph.\"")\n || text.contains(\""Fax\"")\n || text.contains(\""Tel\"")\n || text.contains(\""Ter\"")\n || text.contains(\""Cell\"")\n || text.contains(\""Mobile\"")\n || text.contains(\""Fel\"")\n || text.contains(\""Fer\"")\n )\n then\n section.redactByRegEx(\""\\\\b(telephone|phone|fax|tel|ter|cell|mobile|fel|fer)[:.\\\\s]{0,3}((\\\\(?\\\\+?[0-9])(\\\\(?[0-9\\\\/.\\\\-\\\\s]+\\\\)?)*([0-9]+\\\\)?))\\\\b\"", true, 2, \""PII\"", 23, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[PII.2.0, PII.2.1]"
168,"""2: Redact CBI Address""","""\n when\n Section(matchesType(\""CBI_address\""))\n then\n section.redact(\""CBI_address\"", 4, \""Address found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[CBI.1.1]
169,"""25: Redact AUTHOR(S)""","""\n when\n Section(searchText.contains(\""AUTHOR(S):\"")\n && searchText.contains(\""COMPLETION DATE:\"")\n && !searchText.contains(\""STUDY COMPLETION DATE:\""))\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""COMPLETION DATE:\"", \""PII\"", 25, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[PII.9.0, PII.9.1]"
170,"""6: Redact and recommand Authors in Tables with Vertebrate study Y/N header""","""\n when\n Section(rowEquals(\""Vertebrate study Y/N\"", \""Y\"") || rowEquals(\""Vertebrate study Y/N\"", \""Yes\"") || rowEquals(\""Vertebrate study Y/N\"", \""N\"") || rowEquals(\""Vertebrate study Y/N\"", \""No\""))\n then\n section.redactCell(\""Author(s)\"", 6, \""CBI_author\"", true, \""Author found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[CBI.9.0, CBI.9.1, CBI.10.0, CBI.10.1, CBI.11.0, CBI.12.0, CBI.12.1]"
171,"""22: Redact contact information""","""\n when\n Section(text.contains(\""Contact point:\"")\n || text.contains(\""Phone:\"")\n || text.contains(\""Fax:\"")\n || text.contains(\""Tel.:\"")\n || text.contains(\""Tel:\"")\n || text.contains(\""E-mail:\"")\n || text.contains(\""Email:\"")\n || text.contains(\""e-mail:\"")\n || text.contains(\""E-mail address:\"")\n || text.contains(\""Contact:\"")\n || text.contains(\""Alternative contact:\"")\n || text.contains(\""Telephone number:\"")\n || text.contains(\""Telephone No:\"")\n || text.contains(\""Fax number:\"")\n || text.contains(\""Telephone:\"")\n || text.contains(\""Phone No.\"")\n || (text.contains(\""No:\"") && text.contains(\""Fax\""))\n || (text.contains(\""Contact:\"") && text.contains(\""Tel.:\""))\n || text.contains(\""European contact:\"")\n )\n then\n section.redactLineAfter(\""Contact point:\"", \""PII\"", 22, true, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Phone:\"", \""PII\"", 22, true, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Fax:\"", \""PII\"", 22, true, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Tel.:\"", \""PII\"", 22, true, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Tel:\"", \""PII\"", 22, true, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""E-mail:\"", \""PII\"", 22, true, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Email:\"", \""PII\"", 22, true, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""e-mail:\"", \""PII\"", 22, true, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""E-mail address:\"", \""PII\"", 22, true, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Contact:\"", \""PII\"", 22, true, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Alternative contact:\"", \""PII\"", 22, true, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone number:\"", \""PII\"", 22, true, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone No:\"", \""PII\"", 22, true, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Fax number:\"", \""PII\"", 22, true, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Telephone:\"", \""PII\"", 22, true, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""Phone No.\"", \""PII\"", 22, true, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactBetween(\""No:\"", \""Fax\"", \""PII\"", 22, true, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactBetween(\""Contact:\"", \""Tel.:\"", \""PII\"", 22, true, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLineAfter(\""European contact:\"", \""PII\"", 22, true, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[PII.4.0, PII.4.1, PII.5.0, PII.5.1, PII.6.0, PII.6.1, PII.7.0, PII.7.1, PII.8.0, PII.8.1]"
172,"""20: Redacted PII Personal Identification Information""","""\n when\n Section(matchesType(\""PII\""))\n then\n section.redact(\""PII\"", 20, \""PII (Personal Identification Information) found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[PII.0.0, PII.0.1]"
173,"""1: Redact CBI Authors""","""\n when\n Section(matchesType(\""CBI_author\""))\n then\n section.redact(\""CBI_author\"", 1, \""Author found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[CBI.0.0, CBI.0.1]"
174,"""4: Redact Author(s) cells in Tables with Author(s) header""","""\n when\n Section(hasTableHeader(\""Author(s)\"") && !hasTableHeader(\""Vertebrate study Y/N\""))\n then\n section.redactCell(\""Author(s)\"", 4, \""CBI_author\"", false, \""Author found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[CBI.9.0, CBI.10.0]"
175,"""8: Redact and add recommendation for et al. author""","""\n when\n Section(searchText.contains(\""et al\""))\n then\n section.redactAndRecommendByRegEx(\""\\\\b([A-ZÄÖÜ][^\\\\s\\\\.,]+( [A-ZÄÖÜ]{1,2}\\\\.?)?( ?[A-ZÄÖÜ]\\\\.?)?) et al\\\\.?\"", false, 1, \""CBI_author\"", 15, \""Author found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[CBI.16.0, CBI.16.1]"
176,"""26: Redact AUTHOR(S)""","""\n when\n Section(searchText.contains(\""AUTHOR(S):\"") && searchText.contains(\""STUDY COMPLETION DATE:\""))\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""STUDY COMPLETION DATE:\"", \""PII\"", 26, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[PII.9.0, PII.9.1]"
177,"""27: Redact PERFORMING LABORATORY""","""\n when\n Section(searchText.contains(\""PERFORMING LABORATORY:\""))\n then\n section.redactBetween(\""PERFORMING LABORATORY:\"", \""LABORATORY PROJECT ID:\"", \""CBI_address\"", 27, true, \""PERFORMING LABORATORY was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[CBI.20.0, CBI.20.1]"
178,"""10: Add recommendation for Addresses in Test Animals sections""","""\n when\n Section(searchText.contains(\""Species\"") && searchText.contains(\""Source\""))\n then\n section.recommendLineAfter(\""Source\"", \""CBI_address\"");\n end""","[CBI.17.0, CBI.17.1]"
179,"""33: Redact Logos""","""\n when\n Section(matchesImageType(\""logo\""))\n then\n section.redactImage(\""logo\"", 33, \""Logo found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""","[ETC.3.0, ETC.3.1]"
180,"""26: Redact Phone and Fax by RegEx (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (\n text.contains(\""Contact\"")\n || text.contains(\""Telephone\"")\n || text.contains(\""Phone\"")\n || text.contains(\""Ph.\"")\n || text.contains(\""Fax\"")\n || text.contains(\""Tel\"")\n || text.contains(\""Ter\"")\n || text.contains(\""Mobile\"")\n || text.contains(\""Fel\"")\n || text.contains(\""Fer\"")\n ))\n then\n section.redactByRegEx(\""\\\\b(contact|telephone|phone|ph\\\\.|fax|tel|ter|mobile|fel|fer)[a-zA-Z\\\\s]{0,10}[:.\\\\s]{0,3}([\\\\+\\\\d\\\\(][\\\\s\\\\d\\\\(\\\\)\\\\-\\\\/\\\\.]{4,100}\\\\d)\\\\b\"", true, 2, \""PII\"", 26, \""Personal information found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.2.1]
181,"""25: Redact Phone and Fax by RegEx (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (\n text.contains(\""Contact\"")\n || text.contains(\""Telephone\"")\n || text.contains(\""Phone\"")\n || text.contains(\""Ph.\"")\n || text.contains(\""Fax\"")\n || text.contains(\""Tel\"")\n || text.contains(\""Ter\"")\n || text.contains(\""Mobile\"")\n || text.contains(\""Fel\"")\n || text.contains(\""Fer\"")\n ))\n then\n section.redactByRegEx(\""\\\\b(contact|telephone|phone|ph\\\\.|fax|tel|ter|mobile|fel|fer)[a-zA-Z\\\\s]{0,10}[:.\\\\s]{0,3}([\\\\+\\\\d\\\\(][\\\\s\\\\d\\\\(\\\\)\\\\-\\\\/\\\\.]{4,100}\\\\d)\\\\b\"", true, 2, \""PII\"", 25, \""Personal information found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.2.0]
182,"""10: Add recommendation for Addresses in Test Animals sections""","""\n when\n Section(searchText.contains(\""Species\"") && searchText.contains(\""Source\""))\n then\n\t\tsection.recommendLineAfter(\""Source\"", \""PII\"");\n end""","[CBI.17.0, CBI.17.1]"
183,"""0: Combine address parts from AI to addresses as PII (org is mandatory)""","""\n when\n Section(aiMatchesType(\""ORG\""))\n then\n section.combineAiTypes(\""ORG\"", \""STREET,POSTAL,COUNTRY,CARDINAL,CITY,STATE\"", 20, \""PII\"", 3, false);\n end""",[AI.1.0]
184,"""0: Combine address parts from AI to addresses as PII (street is mandatory)""","""\n when\n Section(aiMatchesType(\""STREET\""))\n then\n section.combineAiTypes(\""STREET\"", \""ORG,POSTAL,COUNTRY,CARDINAL,CITY,STATE\"", 20, \""PII\"", 3, false);\n end""",[AI.1.0]
185,"""18: Redact AUTHOR(S)""","""\n when\n Section(searchText.contains(\""AUTHOR(S):\"") && searchText.contains(\""STUDY COMPLETION DATE:\""))\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""STUDY COMPLETION DATE:\"", \""PII\"", 18, true, \""AUTHOR(S) was found\"", \""personal_data_geolocation\"");\n end""","[PII.9.0, PII.9.1]"
186,"""0: Combine address parts from AI to addresses as PII (city is mandatory)""","""\n when\n Section(aiMatchesType(\""CITY\""))\n then\n section.combineAiTypes(\""CITY\"", \""ORG,STREET,POSTAL,COUNTRY,CARDINAL,STATE\"", 20, \""PII\"", 3, false);\n end""",[AI.1.0]
187,"""24: Redact signatures""","""\n when\n Section(matchesImageType(\""signature\""))\n then\n section.redactImage(\""signature\"", 24, \""Signature found\"", \""personal_data_geolocation\"");\n end""","[ETC.2.0, ETC.2.1]"
188,"""13: Redact Emails by RegEx""","""\n when\n Section(searchText.contains(\""@\""))\n then\n section.redactByRegEx(\""\\\\b([A-Za-z0-9._%+\\\\-]+@[A-Za-z0-9.\\\\-]+\\\\.[A-Za-z\\\\-]{1,23}[A-Za-z])\\\\b\"", true, 1, \""PII\"", 13, \""PII (Personal Identification Information) found\"", \""personal_data_geolocation\"");\n end""","[PII.1.0, PII.1.1]"
189,"""4: Redact Author(s) cells in Tables with Author(s) header""","""\n when\n Section(hasTableHeader(\""Author(s)\"") && !hasTableHeader(\""Vertebrate study Y/N\""))\n then\n section.redactCell(\""Author(s)\"", 4, \""PII\"", false, \""Author found\"", \""personal_data_geolocation\"");\n end""","[CBI.9.0, CBI.10.0, CBI.11.0]"
190,"""25: Redact Logos""","""\n when\n Section(matchesImageType(\""logo\""))\n then\n section.redactImage(\""logo\"", 25, \""Logo found\"", \""personal_data_geolocation\"");\n end""","[ETC.3.0, ETC.3.1]"
191,"""11: Do not redact Names and Addresses if Published Information found""","""\n when\n Section(matchesType(\""published_information\""))\n then\n section.redactNot(\""PII\"", 11, \""Published Information found\"");\n section.redactNot(\""PII\"", 11, \""Published Information found\"");\n end""","[CBI.7.0, CBI.7.1, CBI.6.0, CBI.6.1]"
192,"""2: Do not redact genitive PIIs""","""\n when\n Section(matchesType(\""PII\""))\n then\n section.expandToFalsePositiveByRegEx(\""PII\"", \""[''ʼˈ´`ʻ']s\"", false, 0);\n end""",[CBI.2.0]
193,"""5: Redact Author cells in Tables with Author header""","""\n when\n Section(hasTableHeader(\""Author\"") && !hasTableHeader(\""Vertebrate study Y/N\""))\n then\n section.redactCell(\""Author\"", 5, \""PII\"", false, \""Author found\"", \""personal_data_geolocation\"");\n end""","[CBI.9.1, CBI.10.1, CBI.12.0]"
194,"""19: Redact PERFORMING LABORATORY""","""\n when\n Section(searchText.contains(\""PERFORMING LABORATORY:\""))\n then\n section.redactBetween(\""PERFORMING LABORATORY:\"", \""LABORATORY PROJECT ID:\"", \""PII\"", 19, true, \""PERFORMING LABORATORY was found\"", \""personal_data_geolocation\"");\n end""","[CBI.20.0, CBI.20.1]"
195,"""0: Recommend authors from AI as PII""","""\n when\n Section(aiMatchesType(\""CBI_author\""))\n then\n section.addAiEntities(\""CBI_author\"", \""PII\"");\n end""",[AI.3.0]
196,"""9: Add recommendation for Addresses in Test Organism sections""","""\n when\n Section(searchText.contains(\""Species:\"") && searchText.contains(\""Source:\""))\n then\n\t\tsection.recommendLineAfter(\""Source:\"", \""PII\"");\n end""",[CBI.17.1]
197,"""1: Redacted PII Personal Identification Information""","""\n when\n Section(matchesType(\""PII\""))\n then\n section.redact(\""PII\"", 1, \""Personal information found\"", \""personal_data_geolocation\"");\n end""","[PII.0.0, PII.0.1]"
198,"""8: Redact and add recommendation for et al. author""","""\n when\n Section(searchText.contains(\""et al\""))\n then\n\t\tsection.redactAndRecommendByRegEx(\""\\\\b([A-ZÄÖÜ][^\\\\s\\\\.,]+( [A-ZÄÖÜ]{1,2}\\\\.?)?( ?[A-ZÄÖÜ]\\\\.?)?) et al\\\\.?\"", false, 1, \""PII\"", 8, \""Author found\"", \""personal_data_geolocation\"");\n end""","[CBI.16.0, CBI.16.1]"
199,"""14: Redact contact information""","""\n when\n Section(text.contains(\""Contact point:\"")\n || text.contains(\""Phone:\"")\n || text.contains(\""Fax:\"")\n || text.contains(\""Tel.:\"")\n || text.contains(\""Tel:\"")\n || text.contains(\""E-mail:\"")\n || text.contains(\""Email:\"")\n || text.contains(\""e-mail:\"")\n || text.contains(\""E-mail address:\"")\n || text.contains(\""Contact:\"")\n || text.contains(\""Alternative contact:\"")\n || text.contains(\""Telephone number:\"")\n || text.contains(\""Telephone No:\"")\n || text.contains(\""Fax number:\"")\n || text.contains(\""Telephone:\"")\n || text.contains(\""Phone No.\"")\n || (text.contains(\""No:\"") && text.contains(\""Fax\""))\n || (text.contains(\""Contact:\"") && text.contains(\""Tel.:\""))\n || text.contains(\""European contact:\"")\n )\n then\n section.redactLineAfter(\""Contact point:\"", \""PII\"", 14, true, \""Personal information found\"", \""personal_data_geolocation\"");\n section.redactLineAfter(\""Phone:\"", \""PII\"", 14, true, \""Personal information found\"", \""personal_data_geolocation\"");\n section.redactLineAfter(\""Fax:\"", \""PII\"", 14, true, \""Personal information found\"", \""personal_data_geolocation\"");\n section.redactLineAfter(\""Tel.:\"", \""PII\"", 14, true, \""Personal information found\"", \""personal_data_geolocation\"");\n section.redactLineAfter(\""Tel:\"", \""PII\"", 14, true, \""Personal information found\"", \""personal_data_geolocation\"");\n section.redactLineAfter(\""E-mail:\"", \""PII\"", 14, true, \""Personal information found\"", \""personal_data_geolocation\"");\n section.redactLineAfter(\""Email:\"", \""PII\"", 14, true, \""Personal information found\"", \""personal_data_geolocation\"");\n section.redactLineAfter(\""e-mail:\"", \""PII\"", 14, true, \""Personal information found\"", \""personal_data_geolocation\"");\n section.redactLineAfter(\""E-mail address:\"", \""PII\"", 14, true, \""Personal information found\"", \""personal_data_geolocation\"");\n section.redactLineAfter(\""Contact:\"", \""PII\"", 14, true, \""Personal information found\"", \""personal_data_geolocation\"");\n section.redactLineAfter(\""Alternative contact:\"", \""PII\"", 14, true, \""Personal information found\"", \""personal_data_geolocation\"");\n section.redactLineAfter(\""Telephone number:\"", \""PII\"", 14, true, \""Personal information found\"", \""personal_data_geolocation\"");\n section.redactLineAfter(\""Telephone No:\"", \""PII\"", 14, true, \""Personal information found\"", \""personal_data_geolocation\"");\n section.redactLineAfter(\""Fax number:\"", \""PII\"", 14, true, \""Personal information found\"", \""personal_data_geolocation\"");\n section.redactLineAfter(\""Telephone:\"", \""PII\"", 14, true, \""Personal information found\"", \""personal_data_geolocation\"");\n section.redactLineAfter(\""Phone No.\"", \""PII\"", 14, true, \""Personal information found\"", \""personal_data_geolocation\"");\n section.redactBetween(\""No:\"", \""Fax\"", \""PII\"", 14, true, \""Personal information found\"", \""personal_data_geolocation\"");\n section.redactBetween(\""Contact:\"", \""Tel.:\"", \""PII\"", 14, true, \""Personal information found\"", \""personal_data_geolocation\"");\n section.redactLineAfter(\""European contact:\"", \""PII\"", 14, true, \""Personal information found\"", \""personal_data_geolocation\"");\n end""","[PII.4.0, PII.4.1, PII.6.0, PII.6.1]"
200,"""17: Redact AUTHOR(S)""","""\n when\n Section(searchText.contains(\""AUTHOR(S):\""))\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""COMPLETION DATE:\"", \""PII\"", 17, true, \""AUTHOR(S) was found\"", \""personal_data_geolocation\"");\n end""","[PII.9.0, PII.9.1]"
201,"""6: Redact and recommand Authors in Tables with Vertebrate study Y/N header""","""\n when\n Section(rowEquals(\""Vertebrate study Y/N\"", \""Y\"") || rowEquals(\""Vertebrate study Y/N\"", \""Yes\"") || rowEquals(\""Vertebrate study Y/N\"", \""N\"") || rowEquals(\""Vertebrate study Y/N\"", \""No\""))\n then\n section.redactCell(\""Author(s)\"", 6, \""PII\"", false, \""Author found\"", \""personal_data_geolocation\"");\n end""","[CBI.11.0, CBI.12.2, CBI.12.1]"
202,"""27: Redact Logos""","""\n °when\n Section(matchesImageType(\""logo\""))\n then\n //section.redactImage(\""logo\"", 27, \""Logo found\"", \""names_addresses_persons\"");\n section.redactNotImage(\""logo\"", 27, \""No Logos in preGFL documents\"");\n end""","[ETC.3.0, ETC.3.1]"
203,"""27: Redact Logos""","""\n when\n Section(matchesImageType(\""logo\""))\n then\n //section.redactImage(\""logo\"", 27, \""Logo found\"", \""names_addresses_persons\"");\n section.redactNotImage(\""logo\"", 27, \""No Logos in preGFL documents\"");\n end""","[ETC.3.0, ETC.3.1]"
204,"""10a: Redact Addresses in Reference Tables for vertebrate studies in non-vertebrate documents""","""\n when\n Section(hasTableHeader(\""Vertebrate study Y/N\"") && (rowEquals(\""Vertebrate study Y/N\"", \""Y\"") || rowEquals(\""Vertebrate study Y/N\"", \""Yes\"")))\n then\n section.redact(\""CBI_address\"", 10, \""Redacted because row is a vertebrate study\"", \""names_addresses_persons\"");\n end""",[CBI.22.0]
205,"""27a: Redact AUTHOR(S) (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"")\n && searchText.toUpperCase().contains(\""AUTHOR(S)\"")\n && !searchText.toUpperCase().contains(\""AUTHOR(S):\"")\n && searchText.toUpperCase().contains(\""COMPLETION DATE\"")\n && !searchText.toUpperCase().contains(\""STUDY COMPLETION DATE\"")\n )\n then\n section.redactLinesBetween(\""AUTHOR(S)\"", \""COMPLETION DATE\"", \""CBI_author\"", 27, true, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s)\"", \""Completion Date\"", \""CBI_author\"", 27, true, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""AUTHOR(S)\\n\"", \""COMPLETION DATE\"", \""CBI_author\"", 27, true, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s)\\n\"", \""Completion Date\"", \""CBI_author\"", 27, true, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.0]
206,"""29b: Redact short Authors section""","""\n when\n Section(\n !fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"")\n && searchText.toLowerCase().contains(\""author(s)\"")\n && searchText.length() < 50\n && sectionNumber <= 20\n && !aiMatchesType(\""CBI_Author\"")\n )\n then\n section.redactByRegEx(\""(?<=author\\\\(?s\\\\)?\\\\s\\\\n?)([\\\\p{Lu}\\\\p{L} ]{5,15}(,|\\\\n)?){1,3}\"",true,0,\""CBI_author\"",29,\""AUTHOR(S) was found\"",\""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[CBI.21.0]
207,"""28a: Redact AUTHOR(S) (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"")\n && searchText.toUpperCase().contains(\""AUTHOR(S)\"")\n && !searchText.toUpperCase().contains(\""AUTHOR(S):\"")\n && searchText.toUpperCase().contains(\""COMPLETION DATE\"")\n && !searchText.toUpperCase().contains(\""STUDY COMPLETION DATE\"")\n )\n then\n section.redactLinesBetween(\""AUTHOR(S)\"", \""COMPLETION DATE\"", \""CBI_author\"", 28, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s)\"", \""Completion Date\"", \""CBI_author\"", 28, true, \""Author(s) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""AUTHOR(S)\\n\"", \""COMPLETION DATE\"", \""CBI_author\"", 28, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s)\\n\"", \""Completion Date\"", \""CBI_author\"", 28, true, \""Author(s) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.1]
208,"""65: Redact Skipped Impurities""","""\n when\n Section((fileAttributeByLabelEqualsIgnoreCase(\""Redact Skipped Impurities\"",\""Yes\"") || fileAttributeByLabelEqualsIgnoreCase(\""Redact Skipped Impurities\"",\""Y\"")) && matchesType(\""skipped_impurities\""))\n then\n section.redact(\""skipped_impurities\"", 65, \""Occasional Impurity found\"", \""specification_impurity\"");\n end""",[ETC.9.0]
209,"""19c: Recommend first line in table cell with name and address of owner""","""\n when\n Section(searchText.toLowerCase().contains(\""trial site\"") && hasTableHeader(\""Name and Address of Owner / Tenant\""))\n then\n section.redactCell(\""Name and Address of Owner / Tenant\"",19,\""PII\"",true,\""Trial Site owner and address found\"",\""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[ETC.11.0]
210,"""67: Redact Product Composition Information""","""\n when\n Section(matchesType(\""product_composition\""))\n then\n section.redact(\""product_composition\"",67, \""Product Composition Information found\"",\""composition_plant_protection_product\"");\n end""",[ETC.10.0]
211,"""25: Redact Phone and Fax by RegEx (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (\n text.contains(\""Contact\"")\n || text.contains(\""Telephone\"")\n || text.contains(\""Téléphone\"")\n || text.contains(\""Phone\"")\n || text.contains(\""Fax\"")\n || text.contains(\""Tel\"")\n || text.contains(\""Ter\"")\n || text.contains(\""Mobile\"")\n || text.contains(\""Fel\"")\n || text.contains(\""Fer\"")\n ))\n then\n section.redactByRegEx(\""\\\\b(contact|t\\\\p{Ll}l\\\\p{Ll}phone|phone|fax|tel|ter|mobile|fel|fer)[a-zA-Z\\\\s\\\\.]{0,10}[:.\\\\s]{0,3}([\\\\+\\\\d\\\\(O][\\\\s\\\\d\\\\(\\\\)\\\\-\\\\/\\\\.O]{4,100}\\\\d)\\\\b\"", true, 2, \""PII\"", 25, \""Personal information found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.2.0]
212,"""19a: recommend title prefixed words as PII""","""\n when\n Section(\n searchText.contains(\""Dr \"")\n || searchText.contains(\""PD Dr \"")\n || searchText.contains(\""Prof. Dr \"")\n || searchText.contains(\""Dr. med. vet \"")\n || searchText.contains(\""Dr. rer. nat \"")\n || searchText.contains(\""PhD \"")\n || searchText.contains(\""BSc \"")\n || searchText.contains(\""(FH) \"")\n || searchText.contains(\""Mr \"")\n || searchText.contains(\""Mrs \"")\n || searchText.contains(\""Ms \"")\n || searchText.contains(\""Miss \"")\n || searchText.contains(\""Dr.\"")\n || searchText.contains(\""PD Dr.\"")\n || searchText.contains(\""Prof. Dr.\"")\n || searchText.contains(\""Dr. med. vet.\"")\n || searchText.contains(\""Dr. rer. nat.\"")\n || searchText.contains(\""PhD.\"")\n || searchText.contains(\""BSc.\"")\n || searchText.contains(\""(FH).\"")\n || searchText.contains(\""Mr.\"")\n || searchText.contains(\""Mrs.\"")\n || searchText.contains(\""Ms.\"")\n || searchText.contains(\""Miss.\"")\n )\n then\n section.addRecommendationByRegEx(\""((Dr|PD Dr|Prof. Dr|Dr. med. vet|Dr. rer. nat|PhD|BSc|\\\\(FH\\\\)|Mr|Mrs|Ms|Miss)[.\\\\s]{1,2})([\\\\p{Lu}][\\\\p{L}\\\\-.]{1,20}\\\\s[\\\\p{Lu}][\\\\p{L}\\\\-.]{1,20})\"", false, 3, \""PII\"");\n end""",[PII.14.0]
213,"""0: Combine address parts from ai to CBI_address (city is mandatory)""","""\n when\n Section(aiMatchesType(\""CITY\""))\n then\n section.combineAiTypes(\""CITY\"", \""ORG,DEPARTMENT,STREET,POSTAL,COUNTRY,CARDINAL,STATE\"", 20, \""CBI_address\"", 3, false);\n end""",[AI.1.0]
214,"""29: Redact AUTHOR(S) (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"")\n && searchText.toUpperCase().contains(\""AUTHOR(S):\"")\n && searchText.toUpperCase().contains(\""STUDY COMPLETION DATE:\"")\n )\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""STUDY COMPLETION DATE:\"", \""CBI_author\"", 29, true, \""AUTHOR(S) was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s):\"", \""Study Completion Date:\"", \""CBI_author\"", 29, true, \""AUTHOR(S) was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s):\"", \""Study completion Date:\"", \""CBI_author\"", 29, true, \""AUTHOR(S) was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""AUTHOR(S):\\n\"", \""STUDY COMPLETION DATE:\"", \""CBI_author\"", 29, true, \""AUTHOR(S) was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s):\\n\"", \""Study Completion Date:\"", \""CBI_author\"", 29, true, \""AUTHOR(S) was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s):\\n\"", \""Study completion Date:\"", \""CBI_author\"", 29, true, \""AUTHOR(S) was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.0]
215,"""22: Redact Emails by RegEx (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""@\""))\n then\n section.redactByRegEx(\""\\\\b([A-Za-z0-9._%+\\\\-]+@\\\\s?[A-Za-z0-9.\\\\-]+\\\\.[A-Za-z\\\\-]{1,23}[A-Za-z])\\\\b\"", true, 1, \""PII\"", 22, \""Personal information found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.1.1]
216,"""27: Redact AUTHOR(S) (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"")\n && searchText.toUpperCase().contains(\""AUTHOR(S):\"")\n && searchText.toUpperCase().contains(\""COMPLETION DATE:\"")\n && !searchText.toUpperCase().contains(\""STUDY COMPLETION DATE:\"")\n )\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""COMPLETION DATE:\"", \""CBI_author\"", 27, true, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s):\"", \""Completion Date:\"", \""CBI_author\"", 27, true, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""AUTHOR(S):\\n\"", \""COMPLETION DATE:\"", \""CBI_author\"", 27, true, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s):\\n\"", \""Completion Date:\"", \""CBI_author\"", 27, true, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.0]
217,"""21a: Redact typoed Emails with indicator""","""\n when\n Section(searchText.contains(\""@\"") || searchText.toLowerCase().contains(\""mail\""))\n then\n section.redactByRegEx(\""mail[:\\\\.\\\\s]{1,2}([\\\\w\\\\/\\\\-\\\\{\\\\(\\\\. ]{3,20 }(@|a|f)\\\\s?[\\\\w\\\\/\\\\-\\\\{\\\\(\\\\. ]{3,20}(\\\\. \\\\w{2,4}\\\\b|\\\\.\\\\B|\\\\.\\\\w{1,4}\\\\b))\"",true,1,\""PII\"",21,\""Personal information found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.1.2]
218,"""0: Combine address parts from ai to CBI_address (department is mandatory)""","""\n when\n Section(aiMatchesType(\""DEPARTMENT\""))\n then\n section.combineAiTypes(\""DEPARTMENT\"", \""ORG,STREET,POSTAL,COUNTRY,CARDINAL,CITY,STATE\"", 20, \""CBI_address\"", 3, false);\n end""",[AI.1.0]
219,"""0: Combine address parts from ai to CBI_address (street is mandatory)""","""\n when\n Section(aiMatchesType(\""STREET\""))\n then\n section.combineAiTypes(\""STREET\"", \""ORG,DEPARTMENT,POSTAL,COUNTRY,CARDINAL,CITY,STATE\"", 20, \""CBI_address\"", 3, false);\n end""",[AI.1.0]
220,"""19b: Add recommendation for PII after Contact Person""","""\n when\n Section(searchText.toLowerCase().contains(\""contact person:\""))\n then\n section.recommendLineAfter(\""Contact Person\"", \""PII\"");\n section.recommendLineAfter(\""Contact person\"", \""PII\"");\n section.recommendLineAfter(\""contact person\"", \""PII\"");\n section.recommendLineAfter(\""Contact Person:\"", \""PII\"");\n section.recommendLineAfter(\""Contact person:\"", \""PII\"");\n section.recommendLineAfter(\""contact person:\"", \""PII\"");\n end""",[PII.13.0]
221,"""0: Combine address parts from ai to CBI_address (org is mandatory)""","""\n when\n Section(aiMatchesType(\""ORG\""))\n then\n section.combineAiTypes(\""ORG\"", \""DEPARTMENT,STREET,POSTAL,COUNTRY,CARDINAL,CITY,STATE\"", 20, \""CBI_address\"", 3, false);\n end""",[AI.1.0]
222,"""25a: Redact phone numbers without indicators""","""\n when\n Section(text.contains(\""+\""))\n then\n section.redactByRegEx(\""(\\\\+[\\\\dO]{1,2} )(\\\\([\\\\dO]{1,3}\\\\))?[\\\\d\\\\-O ]{8,15}\"",false,0,\""PII\"",25,\""Personal information found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.2.2]
223,"""34: Dossier""","""\n when\n Section(matchesType(\""dossier_redaction\""))\n then\n section.redact(\""dossier_redaction\"", 34, \""Dossier redaction found\"", \""Article 63(2)(a) of Regulation (EC) No 1107/2009 (making reference to Article 39 of Regulation EC No 178/2002)\"");\n end""","[ETC.4.0, ETC.4.1, ETC.4.2]"
224,"""30: Redact AUTHOR(S) (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"")\n && searchText.toUpperCase().contains(\""AUTHOR(S):\"")\n && searchText.toUpperCase().contains(\""STUDY COMPLETION DATE:\"")\n )\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""STUDY COMPLETION DATE:\"", \""CBI_author\"", 30, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s):\"", \""Study Completion Date:\"", \""CBI_author\"", 30, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s):\"", \""Study completion Date:\"", \""CBI_author\"", 30, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""AUTHOR(S):\\n\"", \""STUDY COMPLETION DATE:\"", \""CBI_author\"", 30, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s):\\n\"", \""Study Completion Date:\"", \""CBI_author\"", 30, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s):\\n\"", \""Study completion Date:\"", \""CBI_author\"", 30, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.1]
225,"""30a: Redact AUTHOR(S) (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"")\n && searchText.toUpperCase().contains(\""AUTHOR(S)\"")\n && !searchText.toUpperCase().contains(\""AUTHOR(S):\"")\n && searchText.toUpperCase().contains(\""STUDY COMPLETION DATE\"")\n )\n then\n section.redactLinesBetween(\""AUTHOR(S)\"", \""STUDY COMPLETION DATE\"", \""CBI_author\"", 30, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s)\"", \""Study Completion Date\"", \""CBI_author\"", 30, true, \""Author(s) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s)\"", \""Study completion Date\"", \""CBI_author\"", 30, true, \""Author(s) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""AUTHOR(S)\\n\"", \""STUDY COMPLETION DATE\"", \""CBI_author\"", 30, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s)\\n\"", \""Study Completion Date\"", \""CBI_author\"", 30, true, \""Author(s) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s)\\n\"", \""Study completion Date\"", \""CBI_author\"", 30, true, \""Author(s) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.1]
226,"""29a: Redact AUTHOR(S) (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"")\n && searchText.toUpperCase().contains(\""AUTHOR(S)\"")\n && !searchText.toUpperCase().contains(\""AUTHOR(S):\"")\n && searchText.toUpperCase().contains(\""STUDY COMPLETION DATE\"")\n )\n then\n section.redactLinesBetween(\""AUTHOR(S)\"", \""STUDY COMPLETION DATE\"", \""CBI_author\"", 29, true, \""AUTHOR(S) was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s)\"", \""Study Completion Date\"", \""CBI_author\"", 29, true, \""Author(s) was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s)\"", \""Study completion Date\"", \""CBI_author\"", 29, true, \""Author(s) was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""AUTHOR(S)\\n\"", \""STUDY COMPLETION DATE\"", \""CBI_author\"", 29, true, \""AUTHOR(S) was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s)\\n\"", \""Study Completion Date\"", \""CBI_author\"", 29, true, \""Author(s) was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s)\\n\"", \""Study completion Date\"", \""CBI_author\"", 29, true, \""Author(s) was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.0]
227,"""28: Redact AUTHOR(S) (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"")\n && searchText.toUpperCase().contains(\""AUTHOR(S):\"")\n && searchText.toUpperCase().contains(\""COMPLETION DATE:\"")\n && !searchText.toUpperCase().contains(\""STUDY COMPLETION DATE:\"")\n )\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""COMPLETION DATE:\"", \""CBI_author\"", 28, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s):\"", \""Completion Date:\"", \""CBI_author\"", 28, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""AUTHOR(S):\\n\"", \""COMPLETION DATE:\"", \""CBI_author\"", 28, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n section.redactLinesBetween(\""Author(s):\\n\"", \""Completion Date:\"", \""CBI_author\"", 28, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.1]
228,"""30b: Redact short Authors section""","""\n when\n Section(\n fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"")\n && searchText.toLowerCase().contains(\""author(s)\"")\n && searchText.length() < 50\n && sectionNumber <= 20\n && !aiMatchesType(\""CBI_Author\"")\n )\n then\n section.redactByRegEx(\""(?<=author\\\\(?s\\\\)?\\\\s\\\\n?)([\\\\p{Lu}\\\\p{L} ]{5,15}(,|\\\\n)?){1,3}\"",true,0,\""CBI_author\"",30,\""AUTHOR(S) was found\"",\""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[CBI.21.1]
229,"""26: Redact Phone and Fax by RegEx (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && (\n text.contains(\""Contact\"")\n || text.contains(\""Telephone\"")\n || text.contains(\""Téléphone\"")\n || text.contains(\""Phone\"")\n || text.contains(\""Fax\"")\n || text.contains(\""Tel\"")\n || text.contains(\""Ter\"")\n || text.contains(\""Mobile\"")\n || text.contains(\""Fel\"")\n || text.contains(\""Fer\"")\n ))\n then\n section.redactByRegEx(\""\\\\b(contact|t\\\\p{Ll}l\\\\p{Ll}phone|phone|fax|tel|ter|mobile|fel|fer)[a-zA-Z\\\\s]{0,10}[:.\\\\s]{0,3}([\\\\+\\\\d\\\\(O][\\\\s\\\\d\\\\(\\\\)\\\\-\\\\/\\\\.O]{4,100}\\\\d)\\\\b\"", true, 2, \""PII\"", 26, \""Personal information found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.2.1]
230,"""60: Redact Must Impurities""","""\n when\n Section((fileAttributeByLabelEqualsIgnoreCase(\""Redact Impurities\"",\""Yes\"") || fileAttributeByLabelEqualsIgnoreCase(\""Redact Impurities\"",\""Y\"")) && matchesType(\""impurities\""))\n then\n section.redact(\""impurities\"", 60, \""Impurity found\"", \""specification_impurity\"");\n end""",[ETC.9.1]
231,"""21: Redact Emails by RegEx (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && searchText.contains(\""@\""))\n then\n section.redactByRegEx(\""\\\\b([A-Za-z0-9._%+\\\\-]+@\\\\s?[A-Za-z0-9.\\\\-]+\\\\.[A-Za-z\\\\-]{1,23}[A-Za-z])\\\\b\"", true, 1, \""PII\"", 21, \""Personal information found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.2.0]
232,"""21a: Redact typoed Emails with indicator""","""\n when\n Section(searchText.contains(\""@\"") || searchText.toLowerCase().contains(\""mail\""))\n then\n section.redactByRegEx(\""mail[:\\\\.\\\\s]{1,2}([\\\\w\\\\/\\\\-\\\\{\\\\(\\\\. ]{3,20}(@|a|f)\\\\s?[\\\\w\\\\/\\\\-\\\\{\\\\(\\\\. ]{3,20}(\\\\. \\\\w{2,4}\\\\b|\\\\.\\\\B|\\\\.\\\\w{1,4}\\\\b))\"",true,1,\""PII\"",21,\""Personal information found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.1.2]
233,"""29: Redact AUTHOR(S) (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"")\n && searchText.contains(\""AUTHOR(S):\"")\n && searchText.contains(\""STUDY COMPLETION DATE:\"")\n )\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""STUDY COMPLETION DATE:\"", \""CBI_author\"", 29, true, \""AUTHOR(S) was found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.0]
234,"""28: Redact AUTHOR(S) (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"")\n && searchText.contains(\""AUTHOR(S):\"")\n && searchText.contains(\""COMPLETION DATE:\"")\n && !searchText.contains(\""STUDY COMPLETION DATE:\"")\n )\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""COMPLETION DATE:\"", \""CBI_author\"", 28, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.1]
235,"""30: Redact AUTHOR(S) (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"")\n && searchText.contains(\""AUTHOR(S):\"")\n && searchText.contains(\""STUDY COMPLETION DATE:\"")\n )\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""STUDY COMPLETION DATE:\"", \""CBI_author\"", 30, true, \""AUTHOR(S) was found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.1]
236,"""27: Redact AUTHOR(S) (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"")\n && searchText.contains(\""AUTHOR(S):\"")\n && searchText.contains(\""COMPLETION DATE:\"")\n && !searchText.contains(\""STUDY COMPLETION DATE:\"")\n )\n then\n section.redactLinesBetween(\""AUTHOR(S):\"", \""COMPLETION DATE:\"", \""CBI_author\"", 27, true, \""Author found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[PII.9.0]
237,"""34a: Redact dossier_redaction (Non vertebrate study)""","""\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesType(\""dossier_redaction\""))\n then\n section.redact(\""dossier_redaction\"", 34, \""Dossier dictionary entry found\"", \""Article 39(e)(3) of Regulation (EC) No 178/2002\"");\n end""",[ETC.12.0]
238,"""34b: Redact dossier_redaction (Vertebrate study)""","""\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\""Vertebrate Study\"",\""Yes\"") && matchesType(\""dossier_redaction\""))\n then\n section.redact(\""dossier_redaction\"", 34, \""Dossier dictionary entry found\"", \""Article 39(e)(2) of Regulation (EC) No 178/2002\"");\n end""",[ETC.12.1]
1 id old rule names old rule code translates to
id old rule names old rule code translates to
0 "0: Add CBI_author from ai 5" "\n when\n Section(aiMatchesType(\"CARDINAL\"))\n then\n section.addAiEntities(\"CARDINAL\", \"cardinal\");\n end" [AI.2.0]
1 "0: Add CBI_author from ai 3" "\n when\n Section(aiMatchesType(\"POSTAL\"))\n then\n section.addAiEntities(\"POSTAL\", \"postal\");\n end" [AI.2.0]
2 "0: Add CBI_author from ai 6" "\n when\n Section(aiMatchesType(\"CITY\"))\n then\n section.addAiEntities(\"CITY\", \"city\");\n end" [AI.2.0]
3 "0: Add CBI_author from ai 7" "\n when\n Section(aiMatchesType(\"STATE\"))\n then\n section.addAiEntities(\"STATE\", \"state\");\n end" [AI.2.0]
4 "0: Add CBI_author from ai 2" "\n when\n Section(aiMatchesType(\"STREET\"))\n then\n section.addAiEntities(\"STREET\", \"street\");\n end" [AI.2.0]
5 "0: Recommend CTL/BL laboratory that start with BL or CTL" "\n when\n Section(searchText.contains(\"CT\") || searchText.contains(\"BL\"))\n then\n /* Regular expression: ((\\b((([Cc]T(([1ILli\\/])| L|~P))|(BL))[\\. ]?([\\dA-Ziltphz~\\/.:!]| ?[\\(',][Ppi](\\(e)?|([\\(-?']\\/))+( ?[\\(\\/\\dA-Znasieg]+)?)\\b( ?\\/? ?\\d+)?)|(\\bCT[L1i]\\b)) */\n section.addRecommendationByRegEx(\"((\\\\b((([Cc]T(([1ILli\\\\/])| L|~P))|(BL))[\\\\. ]?([\\\\dA-Ziltphz~\\\\/.:!]| ?[\\\\(',][Ppi](\\\\(e)?|([\\\\(-?']\\\\/))+( ?[\\\\(\\\\/\\\\dA-Znasieg]+)?)\\\\b( ?\\\\/? ?\\\\d+)?)|(\\\\bCT[L1i]\\\\b))\", true, 0, \"CBI_address\");\n end" [SYN.1.0]
6 "0: Add CBI_author from ai 4" "\n when\n Section(aiMatchesType(\"COUNTRY\"))\n then\n section.addAiEntities(\"COUNTRY\", \"country\");\n end" [AI.2.0]
7 "0: Combine address parts from ai to CBI_address (org is mandatory)" "\n when\n Section(aiMatchesType(\"ORG\"))\n then\n section.combineAiTypes(\"ORG\", \"STREET,POSTAL,COUNTRY,CARDINAL,CITY,STATE\", 20, \"CBI_address\", 3, false);\n end" [AI.1.0]
8 "0: Combine address parts from ai to CBI_address (city is mandatory)" "\n when\n Section(aiMatchesType(\"CITY\"))\n then\n section.combineAiTypes(\"CITY\", \"ORG,STREET,POSTAL,COUNTRY,CARDINAL,STATE\", 20, \"CBI_address\", 3, false);\n end" [AI.1.0]
9 "0: Combine address parts from ai to CBI_address (street is mandatory)" "\n when\n Section(aiMatchesType(\"STREET\"))\n then\n section.combineAiTypes(\"STREET\", \"ORG,POSTAL,COUNTRY,CARDINAL,CITY,STATE\", 20, \"CBI_address\", 3, false);\n end" [AI.1.0]
10 "0: Add CBI_author from ai, 1: Add CBI_author from ai" "\n when\n Section(aiMatchesType(\"CBI_author\"))\n then\n section.addAiEntities(\"CBI_author\", \"CBI_author\");\n end" [AI.0.0]
11 "0: Add CBI_author from ai 8" "\n when\n Section(aiMatchesType(\"ORG\"))\n then\n section.addAiEntities(\"ORG\", \"org\");\n end" [AI.2.0]
12 "1: Redacted because Section contains Vertebrate" "\n when\n Section(matchesType(\"vertebrate\"))\n then\n section.redact(\"CBI_author\", 1, \"Vertebrate found\", \"names_addresses_persons\");\n section.redact(\"CBI_address\", 1, \"Vertebrate found\", \"names_addresses_persons\");\n end" [CBI.3.0]
13 "5: Do not redact genitive CBI_author, 7: Do not redact genitive CBI_author, 1: Do not redact genitive CBI_author" "\n when\n Section(matchesType(\"CBI_author\"))\n then\n section.expandToFalsePositiveByRegEx(\"CBI_author\", \"['’’'ʼˈ´`‘′ʻ’']s\", false, 0);\n end" [CBI.2.0]
14 "1: Redact CBI Authors (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesType(\"CBI_author\"))\n then\n section.redact(\"CBI_author\", 1, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [CBI.0.0]
15 "2: Combine ai types CBI_author from ai" "\n when\n Section(aiMatchesType(\"ORG\"))\n then\n section.combineAiTypes(\"ORG\", \"STREET,POSTAL,COUNTRY,CARDINAL,CITY,STATE\", 20, \"CBI_address\", 2, false);\n end" [AI.1.0]
16 "2: Not Redacted because Section contains no Vertebrate" "\n when\n Section(!matchesType(\"vertebrate\"))\n then\n section.redactNot(\"CBI_author\", 2, \"No Vertebrate found\");\n section.redactNot(\"CBI_address\", 2, \"No Vertebrate found\");\n end" [CBI.3.0]
17 "2: Redact CBI Authors (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesType(\"CBI_author\"))\n then\n section.redact(\"CBI_author\", 2, \"Author found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.0.0]
18 "2: Redacted because Section contains Vertebrate" "\n when\n Section(matchesType(\"vertebrate\"))\n then\n section.redact(\"CBI_author\", 2, \"Vertebrate found\", \"names_addresses_persons\");\n section.redact(\"CBI_address\", 2, \"Vertebrate found\", \"names_addresses_persons\");\n end" [CBI.3.0]
19 "3: Redact CBI Authors (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesType(\"CBI_author\"))\n then\n section.redact(\"CBI_author\", 3, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [CBI.0.0]
20 "3: Not Redacted because Section contains no Vertebrate" "\n when\n Section(!matchesType(\"vertebrate\"))\n then\n section.redactNot(\"CBI_author\", 3, \"No Vertebrate found\");\n section.redactNot(\"CBI_address\", 3, \"No Vertebrate found\");\n end" [CBI.3.2]
21 "3: Do not redact Names and Addresses if no redaction Indicator is contained" "\n when\n Section(matchesType(\"vertebrate\"), matchesType(\"no_redaction_indicator\"))\n then\n section.redactNot(\"CBI_author\", 3, \"Vertebrate and No Redaction Indicator found\");\n section.redactNot(\"CBI_address\", 3, \"Vertebrate and No Redaction Indicator found\");\n end" [CBI.4.0]
22 "3: Redact not CBI Address (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesType(\"CBI_address\"))\n then\n section.redactNot(\"CBI_address\", 3, \"Address found for non vertebrate study\");\n end" [CBI.1.0]
23 "3: Redact not CBI Address (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesType(\"CBI_address\"))\n then\n section.redactNot(\"CBI_address\", 3, \"Address found for non vertebrate study\");\n section.ignoreRecommendations(\"CBI_address\");\n end" [CBI.1.0]
24 "4: Redact Names and Addresses if no_redaction_indicator and redaction_indicator is contained" "\n when\n Section(matchesType(\"vertebrate\"), matchesType(\"no_redaction_indicator\"), matchesType(\"redaction_indicator\"))\n then\n section.redact(\"CBI_author\", 4, \"Vertebrate and Redaction Indicator found\", \"names_addresses_persons\");\n section.redact(\"CBI_address\", 4, \"Vertebrate and Redaction Indicator found\", \"names_addresses_persons\");\n end" [CBI.5.0]
25 "4: Redact CBI Address (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesType(\"CBI_address\"))\n then\n section.redact(\"CBI_address\", 4, \"Address found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.1.1]
26 "4: Redact CBI Authors (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesType(\"CBI_author\"))\n then\n section.redact(\"CBI_author\", 4, \"Author found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.0.0]
27 "4: Do not redact Names and Addresses if no redaction Indicator is contained" "\n when\n Section(matchesType(\"vertebrate\"), matchesType(\"no_redaction_indicator\"))\n then\n section.redactNot(\"CBI_author\", 4, \"Vertebrate and No Redaction Indicator found\");\n section.redactNot(\"CBI_address\", 4, \"Vertebrate and No Redaction Indicator found\");\n end" [CBI.4.0]
28 "5: Do not redact Names and Addresses if no redaction Indicator is contained" "\n when\n Section(matchesType(\"vertebrate\"), matchesType(\"published_information\"))\n then\n section.redactNotAndReference(\"CBI_author\",\"published_information\", 5, \"Published Information found\");\n section.redactNotAndReference(\"CBI_address\",\"published_information\", 5, \"Published Information found\");\n end" [CBI.4.0]
29 "5: Redact Names and Addresses if no_redaction_indicator and redaction_indicator is contained" "\n when\n Section(matchesType(\"vertebrate\"), matchesType(\"no_redaction_indicator\"), matchesType(\"redaction_indicator\"))\n then\n section.redact(\"CBI_author\", 5, \"Vertebrate and Redaction Indicator found\", \"names_addresses_persons\");\n section.redact(\"CBI_address\", 5, \"Vertebrate and Redaction Indicator found\", \"names_addresses_persons\");\n end" [CBI.5.0]
30 "5: Redact not CBI Address (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesType(\"CBI_address\"))\n then\n section.redactNot(\"CBI_address\", 5, \"Address found for non vertebrate study\");\n section.ignoreRecommendations(\"CBI_address\");\n end" [CBI.1.0]
31 "6: Do not redact Names and Addresses if no redaction Indicator is contained" "\n when\n Section(matchesType(\"vertebrate\"), matchesType(\"published_information\"))\n then\n section.redactNotAndReference(\"CBI_author\",\"published_information\", 6, \"Published Information found\");\n section.redactNotAndReference(\"CBI_address\",\"published_information\", 6, \"Published Information found\");\n end" [CBI.4.0]
32 "6: Redact CBI Address (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesType(\"CBI_address\"))\n then\n section.redact(\"CBI_address\", 6, \"Address found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.1.1]
33 "6: Redact Author(s) cells in Tables with Author(s) header (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && hasTableHeader(\"Author(s)\") && !hasTableHeader(\"Vertebrate study Y/N\"))\n then\n section.redactCell(\"Author(s)\", 6, \"CBI_author\", false, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [CBI.9.0, CBI.11.0]
34 "6: Not redacted because Vertebrate Study = N" "\n when\n Section(rowEquals(\"Vertebrate study Y/N\", \"N\") || rowEquals(\"Vertebrate study Y/N\", \"No\"))\n then\n section.redactNotCell(\"Author(s)\", 6, \"CBI_author\", true, \"Not redacted because row is not a vertebrate study\");\n section.redactNot(\"CBI_author\", 6, \"Not redacted because row is not a vertebrate study\");\n section.redactNot(\"CBI_address\", 6, \"Not redacted because row is not a vertebrate study\");\n section.highlightCell(\"Vertebrate study Y/N\", 6, \"hint_only\");\n end" [CBI.12.0]
35 "7: Redact Author(s) cells in Tables with Author(s) header (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && hasTableHeader(\"Author(s)\") && !hasTableHeader(\"Vertebrate study Y/N\"))\n then\n section.redactCell(\"Author(s)\", 7, \"CBI_author\", false, \"Author found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.10.0, CBI.11.0]
36 "7: Not redacted because Vertebrate Study = N" "\n when\n Section(rowEquals(\"Vertebrate study Y/N\", \"N\") || rowEquals(\"Vertebrate study Y/N\", \"No\"))\n then\n section.redactNotCell(\"Author(s)\", 7, \"CBI_author\", true, \"Not redacted because row is not a vertebrate study\");\n section.redactNot(\"CBI_author\", 7, \"Not redacted because row is not a vertebrate study\");\n section.redactNot(\"CBI_address\", 7, \"Not redacted because row is not a vertebrate study\");\n section.highlightCell(\"Vertebrate study Y/N\", 7, \"hint_only\");\n end" [CBI.12.0]
37 "7: Redact if must redact entry is found" "\n when\n Section(matchesType(\"must_redact\"))\n then\n section.redact(\"CBI_author\", 7, \"must_redact entry was found.\", \"names_addresses_persons\");\n section.redact(\"CBI_address\", 7, \"must_redact entry was found.\", \"names_addresses_persons\");\n end" [CBI.8.0]
38 "8: Redact Authors and Addresses in Reference Table if it is a Vertebrate study" "\n when\n Section(rowEquals(\"Vertebrate study Y/N\", \"Y\") || rowEquals(\"Vertebrate study Y/N\", \"Yes\"))\n then\n section.redactCell(\"Author(s)\", 8, \"CBI_author\", true, \"Redacted because row is a vertebrate study\", \"names_addresses_persons\");\n section.redact(\"CBI_address\", 8, \"Redacted because row is a vertebrate study\", \"names_addresses_persons\");\n section.highlightCell(\"Vertebrate study Y/N\", 8, \"must_redact\");\n end" [CBI.12.0]
39 "8: Redact if must redact entry is found" "\n when\n Section(matchesType(\"must_redact\"))\n then\n section.redact(\"CBI_author\", 8, \"Specification of impurity of the active substance was found.\", \"specification_impurity_active_substance\");\n section.redact(\"CBI_address\", 8, \"Specification of impurity of the active substance was found.\", \"specification_impurity_active_substance\");\n end" [CBI.8.0]
40 "8: Redact Author cells in Tables with Author header (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && hasTableHeader(\"Author\") && !hasTableHeader(\"Vertebrate study Y/N\"))\n then\n section.redactCell(\"Author\", 8, \"CBI_author\", false, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [CBI.9.0, CBI.11.0]
41 "8: Redact Author(s) cells in Tables with Author(s) header (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && hasTableHeader(\"Author(s)\") && !hasTableHeader(\"Vertebrate study Y/N\"))\n then\n section.redactCell(\"Author(s)\", 8, \"CBI_author\", false, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [CBI.9.0, CBI.11.0]
42 "9: Redact Author(s) cells in Tables with Author(s) header (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && hasTableHeader(\"Author(s)\") && !hasTableHeader(\"Vertebrate study Y/N\"))\n then\n section.redactCell(\"Author(s)\", 9, \"CBI_author\", false, \"Author found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.10.0, CBI.11.0]
43 "9: Redact Author cells in Tables with Author header (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && hasTableHeader(\"Author\") && !hasTableHeader(\"Vertebrate study Y/N\"))\n then\n section.redactCell(\"Author\", 9, \"CBI_author\", false, \"Author found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.10.0, CBI.11.0]
44 "9: Redact sponsor company" "\n when\n Section(searchText.toLowerCase().contains(\"batches produced at\"))\n then\n section.redactIfPrecededBy(\"batches produced at\", \"CBI_sponsor\", 9, \"Redacted because it represents a sponsor company\", \"names_addresses_persons\");\n section.addHintAnnotation(\"batches produced at\", \"must_redact\");\n end" [CBI.14.0]
45 "9: Redact Authors and Addresses in Reference Table if it is a Vertebrate study" "\n when\n Section(rowEquals(\"Vertebrate study Y/N\", \"Y\") || rowEquals(\"Vertebrate study Y/N\", \"Yes\"))\n then\n section.redactCell(\"Author(s)\", 9, \"CBI_author\", true, \"Redacted because row is a vertebrate study\", \"names_addresses_persons\");\n section.redact(\"CBI_address\", 9, \"Redacted because row is a vertebrate study\", \"names_addresses_persons\");\n section.highlightCell(\"Vertebrate study Y/N\", 9, \"must_redact\");\n end" [CBI.12.0]
46 "10: Redact and recommand Authors in Tables with Vertebrate study Y/N header (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (rowEquals(\"Vertebrate study Y/N\", \"Y\") || rowEquals(\"Vertebrate study Y/N\", \"Yes\") || rowEquals(\"Vertebrate study Y/N\", \"N\") || rowEquals(\"Vertebrate study Y/N\", \"No\")))\n then\n section.redactCell(\"Author(s)\", 10, \"CBI_author\", true, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [CBI.9.0, CBI.11.0]
47 "10: Redact determination of residues" "\n when\n Section((\n searchText.toLowerCase.contains(\"determination of residues\") ||\n searchText.toLowerCase.contains(\"determination of total residues\")\n ) && (\n searchText.toLowerCase.contains(\"livestock\") ||\n searchText.toLowerCase.contains(\"live stock\") ||\n searchText.toLowerCase.contains(\"tissue\") ||\n searchText.toLowerCase.contains(\"tissues\") ||\n searchText.toLowerCase.contains(\"liver\") ||\n searchText.toLowerCase.contains(\"muscle\") ||\n searchText.toLowerCase.contains(\"bovine\") ||\n searchText.toLowerCase.contains(\"ruminant\") ||\n searchText.toLowerCase.contains(\"ruminants\")\n ))\n then\n section.redact(\"CBI_author\", 10, \"Determination of residues was found.\", \"names_addresses_persons\");\n section.redact(\"CBI_address\", 10, \"Determination of residues was found.\", \"names_addresses_persons\");\n section.addHintAnnotation(\"determination of residues\", \"must_redact\");\n section.addHintAnnotation(\"determination of total residues\", \"must_redact\");\n section.addHintAnnotation(\"livestock\", \"must_redact\");\n section.addHintAnnotation(\"live stock\", \"must_redact\");\n section.addHintAnnotation(\"tissue\", \"must_redact\");\n section.addHintAnnotation(\"tissues\", \"must_redact\");\n section.addHintAnnotation(\"liver\", \"must_redact\");\n section.addHintAnnotation(\"muscle\", \"must_redact\");\n section.addHintAnnotation(\"bovine\", \"must_redact\");\n section.addHintAnnotation(\"ruminant\", \"must_redact\");\n section.addHintAnnotation(\"ruminants\", \"must_redact\");\n end" [CBI.15.0]
48 "10: Redact Author cells in Tables with Author header (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && hasTableHeader(\"Author\") && !hasTableHeader(\"Vertebrate study Y/N\"))\n then\n section.redactCell(\"Author\", 10, \"CBI_author\", false, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [CBI.9.0, CBI.11.0]
49 "10: Redact sponsor company" "\n when\n Section(searchText.toLowerCase().contains(\"batches produced at\"))\n then\n section.redactIfPrecededBy(\"batches produced at\", \"CBI_sponsor\", 10, \"Redacted because it represents a sponsor company\", \"names_addresses_persons\");\n section.addHintAnnotation(\"batches produced at\", \"must_redact\");\n end" [CBI.14.0]
50 "11: Redact and recommand Authors in Tables with Vertebrate study Y/N header (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (rowEquals(\"Vertebrate study Y/N\", \"Y\") || rowEquals(\"Vertebrate study Y/N\", \"Yes\") || rowEquals(\"Vertebrate study Y/N\", \"N\") || rowEquals(\"Vertebrate study Y/N\", \"No\")))\n then\n section.redactCell(\"Author(s)\", 11, \"CBI_author\", true, \"Author found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.10.0, CBI.11.0]
51 "11: Redact if CTL/* or BL/* was found" "\n when\n Section(searchText.contains(\"CTL/\") || searchText.contains(\"BL/\"))\n then\n section.redact(\"CBI_author\", 11, \"Laboraty for vertebrate studies found\", \"names_addresses_persons\");\n section.redact(\"CBI_address\", 11, \"Laboraty for vertebrate studies found\", \"names_addresses_persons\");\n section.addHintAnnotation(\"CTL\", \"must_redact\");\n section.addHintAnnotation(\"BL\", \"must_redact\");\n end" [SYN.0.0]
52 "11: Redact determination of residues" "\n when\n Section((\n searchText.toLowerCase.contains(\"determination of residues\") ||\n searchText.toLowerCase.contains(\"determination of total residues\")\n ) && (\n searchText.toLowerCase.contains(\"livestock\") ||\n searchText.toLowerCase.contains(\"live stock\") ||\n searchText.toLowerCase.contains(\"tissue\") ||\n searchText.toLowerCase.contains(\"tissues\") ||\n searchText.toLowerCase.contains(\"liver\") ||\n searchText.toLowerCase.contains(\"muscle\") ||\n searchText.toLowerCase.contains(\"bovine\") ||\n searchText.toLowerCase.contains(\"ruminant\") ||\n searchText.toLowerCase.contains(\"ruminants\")\n ))\n then\n section.redact(\"CBI_author\", 11, \"Determination of residues was found.\", \"names_addresses_persons\");\n section.redact(\"CBI_address\", 11, \"Determination of residues was found.\", \"names_addresses_persons\");\n section.addHintAnnotation(\"determination of residues\", \"must_redact\");\n section.addHintAnnotation(\"determination of total residues\", \"must_redact\");\n section.addHintAnnotation(\"livestock\", \"must_redact\");\n section.addHintAnnotation(\"live stock\", \"must_redact\");\n section.addHintAnnotation(\"tissue\", \"must_redact\");\n section.addHintAnnotation(\"tissues\", \"must_redact\");\n section.addHintAnnotation(\"liver\", \"must_redact\");\n section.addHintAnnotation(\"muscle\", \"must_redact\");\n section.addHintAnnotation(\"bovine\", \"must_redact\");\n section.addHintAnnotation(\"ruminant\", \"must_redact\");\n section.addHintAnnotation(\"ruminants\", \"must_redact\");\n end" [CBI.15.0]
53 "11: Redact Author cells in Tables with Author header (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && hasTableHeader(\"Author\") && !hasTableHeader(\"Vertebrate study Y/N\"))\n then\n section.redactCell(\"Author\", 11, \"CBI_author\", false, \"Author found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.10.0, CBI.11.0]
54 "12: Redact and add recommendation for et al. author" "\n when\n Section(searchText.contains(\"et al\"))\n then\n\t\tsection.redactAndRecommendByRegEx(\"\\\\b([A-ZÄÖÜ][^\\\\s\\\\.,]+( [A-ZÄÖÜ]{1,2}\\\\.?)?( ?[A-ZÄÖÜ]\\\\.?)?) et al\\\\.?\", false, 1, \"CBI_author\", 12, \"Author found\", \"names_addresses_persons\");\n end" [CBI.16.0]
55 "12: Redact and recommand Authors in Tables with Vertebrate study Y/N header (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (rowEquals(\"Vertebrate study Y/N\", \"Y\") || rowEquals(\"Vertebrate study Y/N\", \"Yes\") || rowEquals(\"Vertebrate study Y/N\", \"N\") || rowEquals(\"Vertebrate study Y/N\", \"No\")))\n then\n section.redactCell(\"Author(s)\", 12, \"CBI_author\", true, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [CBI.9.0, CBI.11.0]
56 "12: Recommend CTL/BL laboratory" "\n when\n Section(searchText.contains(\"CT\") || searchText.contains(\"BL\"))\n then\n section.addRecommendationByRegEx(\"((\\\\b((([Cc]T(([1ILli\\\\/])| L|~P))|(BL))[\\\\. ]?([\\\\dA-Ziltphz~\\\\/.:!]| ?[\\\\(',][Ppi](\\\\(e)?|([\\\\(-?']\\\\/))+( ?[\\\\(\\\\/\\\\dA-Znasieg]+)?)\\\\b( ?\\\\/? ?\\\\d+)?)|(\\\\bCT[L1i]\\\\b))\", true, 0, \"CBI_address\");\n end" [SYN.1.0]
57 "12: Redact if CTL/* or BL/* was found (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (searchText.contains(\"CTL/\") || searchText.contains(\"BL/\")))\n then\n section.addHintAnnotation(\"CTL\", \"hint_only\");\n section.addHintAnnotation(\"BL\", \"hint_only\");\n end" [SYN.0.0]
58 "13: Redact and recommand Authors in Tables with Vertebrate study Y/N header (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (rowEquals(\"Vertebrate study Y/N\", \"Y\") || rowEquals(\"Vertebrate study Y/N\", \"Yes\") || rowEquals(\"Vertebrate study Y/N\", \"N\") || rowEquals(\"Vertebrate study Y/N\", \"No\")))\n then\n section.redactCell(\"Author(s)\", 13, \"CBI_author\", true, \"Author found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.10.0, CBI.11.0]
59 "14: Add recommendation for Addresses in Test Organism sections, 13: Add recommendation for Addresses in Test Organism sections" "\n when\n Section(searchText.contains(\"Species:\") && searchText.contains(\"Source:\"))\n then\n\t\tsection.recommendLineAfter(\"Source:\", \"CBI_address\");\n end" [CBI.17.0]
60 "13: Redact and add recommendation for et al. author" "\n when\n Section(searchText.contains(\"et al\"))\n then\n\t\tsection.redactAndRecommendByRegEx(\"\\\\b([A-ZÄÖÜ][^\\\\s\\\\.,]+( [A-ZÄÖÜ]{1,2}\\\\.?)?( ?[A-ZÄÖÜ]\\\\.?)?) et al\\\\.?\", false, 1, \"CBI_author\", 13, \"Author found\", \"names_addresses_persons\");\n end" [CBI.16.0]
61 "13: Redact if CTL/* or BL/* was found (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (searchText.contains(\"CTL/\") || searchText.contains(\"BL/\")))\n then\n section.addRedaction(\"CTL\", \"must_redact\", 13, \"Laboratory for vertebrate studies found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\" );\n section.addRedaction(\"BL\", \"must_redact\", 13, \"Laboratory for vertebrate studies found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\" );\n end" [SYN.0.0]
62 "15: Add recommendation for Addresses in Test Animals sections, 14: Add recommendation for Addresses in Test Animals sections" "\n when\n Section(searchText.contains(\"Species\") && searchText.contains(\"Source\"))\n then\n\t\tsection.recommendLineAfter(\"Source\", \"CBI_address\");\n end" [CBI.17.0]
63 "14: Redact addresses that start with BL or CTL" "\n when\n Section(searchText.contains(\"BL\") || searchText.contains(\"CT\"))\n then\n section.addRecommendationByRegEx(\"((\\\\b((([Cc]T(([1ILli\\\\/])| L|~P))|(BL))[\\\\. ]?([\\\\dA-Ziltphz~\\\\/.:!]| ?[\\\\(',][Ppi](\\\\(e)?|([\\\\(-?']\\\\/))+( ?[\\\\(\\\\/\\\\dA-Znasieg]+)?)\\\\b( ?\\\\/? ?\\\\d+)?)|(\\\\bCT[L1i]\\\\b))\", true, 0, \"CBI_address\");\n end" [SYN.1.0]
64 "14: Redacted PII Personal Identification Information" "\n when\n Section(matchesType(\"PII\"))\n then\n section.redact(\"PII\", 14, \"PII (Personal Identification Information) found\", \"links_producer_applicant\");\n end" [PII.0.0, PII.0.1]
65 "14: Redact and add recommendation for et al. author (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"et al\"))\n then\n section.redactAndRecommendByRegEx(\"\\\\b([A-ZÄÖÜ][^\\\\s\\\\.,]+( [A-ZÄÖÜ]{1,2}\\\\.?)?( ?[A-ZÄÖÜ]\\\\.?)?) et al\\\\.?\", false, 1, \"CBI_author\", 14, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [CBI.16.0]
66 "15: Redact Emails by RegEx" "\n when\n Section(searchText.contains(\"@\"))\n then\n section.redactByRegEx(\"\\\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\\\.[A-Z]{2,4}\\\\b\", true, 0, \"PII\", 15, \"PII (Personal Identification Information) found\", \"links_producer_applicant\");\n end" [PII.1.0, PII.1.1]
67 "15: Redact and add recommendation for et al. author (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"et al\"))\n then\n section.redactAndRecommendByRegEx(\"\\\\b([A-ZÄÖÜ][^\\\\s\\\\.,]+( [A-ZÄÖÜ]{1,2}\\\\.?)?( ?[A-ZÄÖÜ]\\\\.?)?) et al\\\\.?\", false, 1, \"CBI_author\", 15, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [CBI.16.0]
68 "15: Redact and add recommendation for et al. author (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"et al\"))\n then\n section.redactAndRecommendByRegEx(\"\\\\b([A-ZÄÖÜ][^\\\\s\\\\.,]+( [A-ZÄÖÜ]{1,2}\\\\.?)?( ?[A-ZÄÖÜ]\\\\.?)?) et al\\\\.?\", false, 1, \"CBI_author\", 15, \"Author found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.16.0]
69 "16: Redacted PII Personal Identification Information" "\n when\n Section(matchesType(\"PII\"))\n then\n section.redact(\"PII\", 16, \"PII (Personal Identification Information) found\", \"links_producer_applicant\");\n end" [PII.0.0, PII.0.1]
70 "16: Redact and add recommendation for et al. author (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"et al\"))\n then\n section.redactAndRecommendByRegEx(\"\\\\b([A-ZÄÖÜ][^\\\\s\\\\.,]+( [A-ZÄÖÜ]{1,2}\\\\.?)?( ?[A-ZÄÖÜ]\\\\.?)?) et al\\\\.?\", false, 1, \"CBI_author\", 16, \"Author found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.16.0]
71 "16: Redact contact information" "\n when\n Section(text.contains(\"Contact point:\")\n || text.contains(\"Phone:\")\n || text.contains(\"Fax:\")\n || text.contains(\"Tel.:\")\n || text.contains(\"Tel:\")\n || text.contains(\"E-mail:\")\n || text.contains(\"Email:\")\n || text.contains(\"e-mail:\")\n || text.contains(\"E-mail address:\")\n || text.contains(\"Alternative contact:\")\n || text.contains(\"Telephone number:\")\n || text.contains(\"Telephone No:\")\n || text.contains(\"Fax number:\")\n || text.contains(\"Telephone:\")\n || text.contains(\"European contact:\"))\n then\n section.redactLineAfter(\"Contact point:\", \"PII\", 16, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Phone:\", \"PII\", 16, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Fax:\", \"PII\", 16, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Tel.:\", \"PII\", 16, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Tel:\", \"PII\", 16, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"E-mail:\", \"PII\", 16, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Email:\", \"PII\", 16, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"e-mail:\", \"PII\", 16, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"E-mail address:\", \"PII\", 16, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Contact:\", \"PII\", 16, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Alternative contact:\", \"PII\", 16, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Telephone number:\", \"PII\", 16, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Telephone No:\", \"PII\", 16, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Fax number:\", \"PII\", 16, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Telephone:\", \"PII\", 16, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactBetween(\"No:\", \"Fax\", \"PII\", 16, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactBetween(\"Contact:\", \"Tel.:\", \"PII\", 16, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"European contact:\", \"PII\", 16, true, \"Contact information was found\", \"links_producer_applicant\");\n end" [PII.4.0, PII.4.1, PII.6.0, PII.6.1]
72 "16: Add recommendation for Addresses in Test Organism sections, 17: Add recommendation for Addresses in Test Organism sections" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"Species:\") && searchText.contains(\"Source:\"))\n then\n section.recommendLineAfter(\"Source:\", \"CBI_address\");\n end" [CBI.17.0]
73 "17: Redact Emails by RegEx" "\n when\n Section(searchText.contains(\"@\"))\n then\n section.redactByRegEx(\"\\\\b([A-Za-z0-9._%+\\\\-]+@[A-Za-z0-9.\\\\-]+\\\\.[A-Za-z\\\\-]{1,23}[A-Za-z])\\\\b\", true, 1, \"PII\", 17, \"PII (Personal Identification Information) found\", \"links_producer_applicant\");\n end" [PII.1.0, PII.1.1]
74 "17: Add recommendation for Addresses in Test Animals sections, 18: Add recommendation for Addresses in Test Animals sections" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"Species\") && searchText.contains(\"Source\"))\n then\n section.recommendLineAfter(\"Source\", \"CBI_address\");\n end" [CBI.17.0]
75 "17: Redact contact information if applicant is found" "\n when\n Section(headlineContainsWord(\"applicant\") || text.contains(\"Applicant\") || headlineContainsWord(\"Primary contact\") || headlineContainsWord(\"Alternative contact\") || text.contains(\"Telephone number:\"))\n then\n section.redactLineAfter(\"Contact point:\", \"PII\", 17, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Phone:\", \"PII\", 17, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Fax:\", \"PII\", 17, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Tel.:\", \"PII\", 17, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Tel:\", \"PII\", 17, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"E-mail:\", \"PII\", 17, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Email:\", \"PII\", 17, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"e-mail:\", \"PII\", 17, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"E-mail address:\", \"PII\", 17, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Contact:\", \"PII\", 17, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Alternative contact:\", \"PII\", 17, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Telephone number:\", \"PII\", 17, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Telephone No:\", \"PII\", 17, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Fax number:\", \"PII\", 17, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Telephone:\", \"PII\", 17, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactBetween(\"No:\", \"Fax\", \"PII\", 17, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactBetween(\"Contact:\", \"Tel.:\", \"PII\", 17, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"European contact:\", \"PII\", 17, true, \"Applicant information was found\", \"links_producer_applicant\");\n end" [PII.7.0]
76 "18: Do not redact Names and Addresses if Published Information found" "\n when\n Section(matchesType(\"published_information\"))\n then\n section.redactNotAndReference(\"CBI_author\",\"published_information\", 18, \"Published Information found\");\n section.redactNotAndReference(\"CBI_address\",\"published_information\", 18, \"Published Information found\");\n end" [CBI.7.0]
77 "18: Redact contact information if Producer is found" "\n when\n Section(text.toLowerCase().contains(\"producer of the plant protection\") || text.toLowerCase().contains(\"producer of the active substance\") || text.contains(\"Manufacturer of the active substance\") || text.contains(\"Manufacturer:\") || text.contains(\"Producer or producers of the active substance\"))\n then\n section.redactLineAfter(\"Contact:\", \"PII\", 18, true, \"Producer was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Telephone:\", \"PII\", 18, true, \"Producer was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Phone:\", \"PII\", 18, true, \"Producer was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Fax:\", \"PII\", 18, true, \"Producer was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"E-mail:\", \"PII\", 18, true, \"Producer was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Contact:\", \"PII\", 18, true, \"Producer was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Fax number:\", \"PII\", 18, true, \"Producer was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Telephone number:\", \"PII\", 18, true, \"Producer was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Tel:\", \"PII\", 18, true, \"Producer was found\", \"links_producer_applicant\");\n section.redactBetween(\"No:\", \"Fax\", \"PII\", 18, true, \"Producer was found\", \"links_producer_applicant\");\n end" [PII.8.0]
78 "18: Redact contact information" "\n when\n Section(text.contains(\"Contact point:\")\n || text.contains(\"Phone:\")\n || text.contains(\"Fax:\")\n || text.contains(\"Tel.:\")\n || text.contains(\"Tel:\")\n || text.contains(\"E-mail:\")\n || text.contains(\"Email:\")\n || text.contains(\"e-mail:\")\n || text.contains(\"E-mail address:\")\n || text.contains(\"Alternative contact:\")\n || text.contains(\"Telephone number:\")\n || text.contains(\"Telephone No:\")\n || text.contains(\"Fax number:\")\n || text.contains(\"Telephone:\")\n || text.contains(\"Phone No.\")\n || text.contains(\"European contact:\"))\n then\n section.redactLineAfter(\"Contact point:\", \"PII\", 18, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Phone:\", \"PII\", 18, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Fax:\", \"PII\", 18, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Tel.:\", \"PII\", 18, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Tel:\", \"PII\", 18, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"E-mail:\", \"PII\", 18, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Email:\", \"PII\", 18, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"e-mail:\", \"PII\", 18, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"E-mail address:\", \"PII\", 18, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Contact:\", \"PII\", 18, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Alternative contact:\", \"PII\", 18, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Telephone number:\", \"PII\", 18, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Telephone No:\", \"PII\", 18, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Fax number:\", \"PII\", 18, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Telephone:\", \"PII\", 18, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Phone No.\", \"PII\", 18, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactBetween(\"No:\", \"Fax\", \"PII\", 18, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactBetween(\"Contact:\", \"Tel.:\", \"PII\", 18, true, \"Contact information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"European contact:\", \"PII\", 18, true, \"Contact information was found\", \"links_producer_applicant\");\n end" [PII.4.0, PII.4.1, PII.6.0, PII.6.1]
79 "19: Redact contact information if applicant is found" "\n when\n Section(headlineContainsWord(\"applicant\") || text.contains(\"Applicant\") || headlineContainsWord(\"Primary contact\") || headlineContainsWord(\"Alternative contact\") || text.contains(\"Telephone number:\"))\n then\n section.redactLineAfter(\"Contact point:\", \"PII\", 19, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Phone:\", \"PII\", 19, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Fax:\", \"PII\", 19, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Tel.:\", \"PII\", 19, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Tel:\", \"PII\", 19, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"E-mail:\", \"PII\", 19, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Email:\", \"PII\", 19, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"e-mail:\", \"PII\", 19, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"E-mail address:\", \"PII\", 19, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Contact:\", \"PII\", 19, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Alternative contact:\", \"PII\", 19, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Telephone number:\", \"PII\", 19, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Telephone No:\", \"PII\", 19, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Fax number:\", \"PII\", 19, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Telephone:\", \"PII\", 19, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Phone No.\", \"PII\", 19, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactBetween(\"No:\", \"Fax\", \"PII\", 19, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactBetween(\"Contact:\", \"Tel.:\", \"PII\", 19, true, \"Applicant information was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"European contact:\", \"PII\", 19, true, \"Applicant information was found\", \"links_producer_applicant\");\n end" [PII.7.0]
80 "19: Redact AUTHOR(S)" "\n when\n Section(searchText.contains(\"AUTHOR(S):\"))\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"COMPLETION DATE:\", \"PII\", 19, true, \"AUTHOR(S) was found\", \"links_producer_applicant\");\n end" [PII.9.0, PII.9.1]
81 "19: Redacted PII Personal Identification Information (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesType(\"PII\"))\n then\n section.redact(\"PII\", 19, \"PII (Personal Identification Information) found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.0.0]
82 "19: Redacted PII Personal Identification Information (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesType(\"PII\"))\n then\n section.redact(\"PII\", 19, \"Personal information found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.0.0]
83 "19: Do not redact Names and Addresses if Published Information found" "\n when\n Section(matchesType(\"published_information\"))\n then\n section.redactNotAndReference(\"CBI_author\",\"published_information\", 19, \"Published Information found\");\n section.redactNotAndReference(\"CBI_address\",\"published_information\", 19, \"Published Information found\");\n end" [CBI.7.0]
84 "20: Redact contact information if Producer is found" "\n when\n Section(text.toLowerCase().contains(\"producer of the plant protection\") || text.toLowerCase().contains(\"producer of the active substance\") || text.contains(\"Manufacturer of the active substance\") || text.contains(\"Manufacturer:\") || text.contains(\"Producer or producers of the active substance\"))\n then\n section.redactLineAfter(\"Contact:\", \"PII\", 20, true, \"Producer was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Telephone:\", \"PII\", 20, true, \"Producer was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Phone:\", \"PII\", 20, true, \"Producer was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Fax:\", \"PII\", 20, true, \"Producer was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"E-mail:\", \"PII\", 20, true, \"Producer was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Contact:\", \"PII\", 20, true, \"Producer was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Fax number:\", \"PII\", 20, true, \"Producer was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Telephone number:\", \"PII\", 20, true, \"Producer was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Tel:\", \"PII\", 20, true, \"Producer was found\", \"links_producer_applicant\");\n section.redactLineAfter(\"Phone No.\", \"PII\", 20, true, \"Producer was found\", \"links_producer_applicant\");\n section.redactBetween(\"No:\", \"Fax\", \"PII\", 20, true, \"Producer was found\", \"links_producer_applicant\");\n end" [PII.8.0]
85 "20: Redact PERFORMING LABORATORY" "\n when\n Section(searchText.contains(\"PERFORMING LABORATORY:\"))\n then\n section.redactBetween(\"PERFORMING LABORATORY:\", \"LABORATORY PROJECT ID:\", \"PII\", 20, true, \"PERFORMING LABORATORY was found\", \"links_producer_applicant\");\n end" [CBI.20.0, CBI.20.1]
86 "20: Redacted PII Personal Identification Information (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesType(\"PII\"))\n then\n section.redact(\"PII\", 20, \"Personal information found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.0.1]
87 "20: Redacted PII Personal Identification Information (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesType(\"PII\"))\n then\n section.redact(\"PII\", 20, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.0.1]
88 "21: Redact Emails by RegEx (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"@\"))\n then\n section.redactByRegEx(\"\\\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\\\.[A-Z]{2,4}\\\\b\", true, 0, \"PII\", 21, \"PII (Personal Identification Information) found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.1.0]
89 "21: Redact Emails by RegEx (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"@\"))\n then\n section.redactByRegEx(\"\\\\b([A-Za-z0-9._%+\\\\-]+@[A-Za-z0-9.\\\\-]+\\\\.[A-Za-z\\\\-]{1,23}[A-Za-z])\\\\b\", true, 1, \"PII\", 21, \"Personal information found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.1.0]
90 "21: Redact On behalf of Sequani Ltd.:" "\n when\n Section(searchText.contains(\"On behalf of Sequani Ltd.: Name Title\"))\n then\n section.redactBetween(\"On behalf of Sequani Ltd.: Name Title\", \"On behalf of\", \"PII\", 21, false , \"PII (Personal Identification Information) found\", \"links_producer_applicant\");\n end" [PII.11.0]
91 "21: Redact AUTHOR(S)" "\n when\n Section(searchText.contains(\"AUTHOR(S):\"))\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"COMPLETION DATE:\", \"PII\", 21, true, \"AUTHOR(S) was found\", \"links_producer_applicant\");\n end" [PII.9.0, PII.9.1]
92 "22: Redact Emails by RegEx (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"@\"))\n then\n section.redactByRegEx(\"\\\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\\\.[A-Z]{2,4}\\\\b\", true, 0, \"PII\", 22, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.1.1]
93 "22: Redact Emails by RegEx (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"@\"))\n then\n section.redactByRegEx(\"\\\\b([A-Za-z0-9._%+\\\\-]+@[A-Za-z0-9.\\\\-]+\\\\.[A-Za-z\\\\-]{1,23}[A-Za-z])\\\\b\", true, 1, \"PII\", 22, \"Personal information found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.1.1]
94 "22: Redact PERFORMING LABORATORY" "\n when\n Section(searchText.contains(\"PERFORMING LABORATORY:\"))\n then\n section.redactBetween(\"PERFORMING LABORATORY:\", \"LABORATORY PROJECT ID:\", \"PII\", 22, true, \"PERFORMING LABORATORY was found\", \"links_producer_applicant\");\n end" [CBI.20.0, CBI.20.1]
95 "22: Redact On behalf of Syngenta Ltd.:" "\n when\n Section(searchText.contains(\"On behalf of Syngenta Ltd.: Name Title\"))\n then\n section.redactBetween(\"On behalf of Syngenta Ltd.: Name Title\", \"Study dates\", \"PII\", 22, false , \"PII (Personal Identification Information) found\", \"links_producer_applicant\");\n end" [PII.11.0]
96 "23: Redact contact information (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (text.contains(\"Contact point:\")\n || text.contains(\"Phone:\")\n || text.contains(\"Fax:\")\n || text.contains(\"Tel.:\")\n || text.contains(\"Tel:\")\n || text.contains(\"E-mail:\")\n || text.contains(\"Email:\")\n || text.contains(\"e-mail:\")\n || text.contains(\"E-mail address:\")\n || text.contains(\"Alternative contact:\")\n || text.contains(\"Telephone number:\")\n || text.contains(\"Telephone No:\")\n || text.contains(\"Fax number:\")\n || text.contains(\"Telephone:\")\n || text.contains(\"Phone No.\")\n || text.contains(\"European contact:\")))\n then\n section.redactLineAfter(\"Contact point:\", \"PII\", 23, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Phone:\", \"PII\", 23, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Fax:\", \"PII\", 23, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Tel.:\", \"PII\", 23, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Tel:\", \"PII\", 23, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"E-mail:\", \"PII\", 23, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Email:\", \"PII\", 23, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"e-mail:\", \"PII\", 23, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"E-mail address:\", \"PII\", 23, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Contact:\", \"PII\", 23, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Alternative contact:\", \"PII\", 23, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone number:\", \"PII\", 23, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone No:\", \"PII\", 23, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Fax number:\", \"PII\", 23, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone:\", \"PII\", 23, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Phone No.\", \"PII\", 23, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactBetween(\"No:\", \"Fax\", \"PII\", 23, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactBetween(\"Contact:\", \"Tel.:\", \"PII\", 23, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"European contact:\", \"PII\", 23, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.5.0, PII.6.0]
97 "23: Redact contact information (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (text.contains(\"Contact point:\")\n || text.contains(\"Contact:\")\n || text.contains(\"Alternative contact:\")\n || (text.contains(\"No:\") && text.contains(\"Fax\"))\n || (text.contains(\"Contact:\") && text.contains(\"Tel.:\"))\n || text.contains(\"European contact:\")\n ))\n then\n section.redactLineAfter(\"Contact point:\", \"PII\", 23, true, \"Personal information found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Contact:\", \"PII\", 23, true, \"Personal information found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Alternative contact:\", \"PII\", 23, true, \"Personal information found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactBetween(\"No:\", \"Fax\", \"PII\", 23, true, \"Personal information found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactBetween(\"Contact:\", \"Tel.:\", \"PII\", 23, true, \"Personal information found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"European contact:\", \"PII\", 23, true, \"Personal information found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.4.0, PII.6.0]
98 "24: Redact contact information (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (text.contains(\"Contact point:\")\n || text.contains(\"Contact:\")\n || text.contains(\"Alternative contact:\")\n || (text.contains(\"No:\") && text.contains(\"Fax\"))\n || (text.contains(\"Contact:\") && text.contains(\"Tel.:\"))\n || text.contains(\"European contact:\")\n ))\n then\n section.redactLineAfter(\"Contact point:\", \"PII\", 24, true, \"Personal information found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Contact:\", \"PII\", 24, true, \"Personal information found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Alternative contact:\", \"PII\", 24, true, \"Personal information found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactBetween(\"No:\", \"Fax\", \"PII\", 24, true, \"Personal information found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactBetween(\"Contact:\", \"Tel.:\", \"PII\", 24, true, \"Personal information found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"European contact:\", \"PII\", 24, true, \"Personal information found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.5.1, PII.6.1]
99 "24: Redact contact information (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (text.contains(\"Contact point:\")\n || text.contains(\"Phone:\")\n || text.contains(\"Fax:\")\n || text.contains(\"Tel.:\")\n || text.contains(\"Tel:\")\n || text.contains(\"E-mail:\")\n || text.contains(\"Email:\")\n || text.contains(\"e-mail:\")\n || text.contains(\"E-mail address:\")\n || text.contains(\"Alternative contact:\")\n || text.contains(\"Telephone number:\")\n || text.contains(\"Telephone No:\")\n || text.contains(\"Fax number:\")\n || text.contains(\"Telephone:\")\n || text.contains(\"Phone No.\")\n || text.contains(\"European contact:\")))\n then\n section.redactLineAfter(\"Contact point:\", \"PII\", 24, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Phone:\", \"PII\", 24, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Fax:\", \"PII\", 24, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Tel.:\", \"PII\", 24, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Tel:\", \"PII\", 24, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"E-mail:\", \"PII\", 24, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Email:\", \"PII\", 24, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"e-mail:\", \"PII\", 24, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"E-mail address:\", \"PII\", 24, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Contact:\", \"PII\", 24, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Alternative contact:\", \"PII\", 24, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone number:\", \"PII\", 24, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone No:\", \"PII\", 24, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Fax number:\", \"PII\", 24, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone:\", \"PII\", 24, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Phone No.\", \"PII\", 24, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactBetween(\"No:\", \"Fax\", \"PII\", 24, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactBetween(\"Contact:\", \"Tel.:\", \"PII\", 24, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"European contact:\", \"PII\", 24, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.4.1, PII.6.1]
100 "25: Redact Phone and Fax by RegEx" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (\n text.contains(\"Contact\")\n || text.contains(\"Telephone\")\n || text.contains(\"Phone\")\n || text.contains(\"Ph.\")\n || text.contains(\"Fax\")\n || text.contains(\"Tel\")\n || text.contains(\"Ter\")\n || text.contains(\"Cell\")\n || text.contains(\"Mobile\")\n || text.contains(\"Fel\")\n || text.contains(\"Fer\")\n ))\n then\n section.redactByRegEx(\"\\\\b(contact|telephone|phone|fax|tel|ter|cell|mobile|fel|fer)[a-zA-Z\\\\s]{0,10}[:.\\\\s]{0,3}([\\\\+\\\\d\\\\(][\\\\s\\\\d\\\\(\\\\)\\\\-\\\\/\\\\.]{4,100}\\\\d)\\\\b\", true, 2, \"PII\", 25, \"Personal information found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.2.0]
101 "25: Redact Phone and Fax by RegEx (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (\n text.contains(\"Contact\")\n || text.contains(\"Telephone\")\n || text.contains(\"Phone\")\n || text.contains(\"Fax\")\n || text.contains(\"Tel\")\n || text.contains(\"Ter\")\n || text.contains(\"Mobile\")\n || text.contains(\"Fel\")\n || text.contains(\"Fer\")\n ))\n then\n section.redactByRegEx(\"\\\\b(contact|telephone|phone|fax|tel|ter|mobile|fel|fer)[a-zA-Z\\\\s]{0,10}[:.\\\\s]{0,3}([\\\\+\\\\d\\\\(][\\\\s\\\\d\\\\(\\\\)\\\\-\\\\/\\\\.]{4,100}\\\\d)\\\\b\", true, 2, \"PII\", 25, \"Personal information found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.2.0]
102 "25: Redact contact information if applicant is found (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (headlineContainsWord(\"applicant\") || text.contains(\"Applicant\") || headlineContainsWord(\"Primary contact\") || headlineContainsWord(\"Alternative contact\") || text.contains(\"Telephone number:\")))\n then\n section.redactLineAfter(\"Contact point:\", \"PII\", 25, true, \"Applicant information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Phone:\", \"PII\", 25, true, \"Applicant information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Fax:\", \"PII\", 25, true, \"Applicant information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Tel.:\", \"PII\", 25, true, \"Applicant information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Tel:\", \"PII\", 25, true, \"Applicant information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"E-mail:\", \"PII\", 25, true, \"Applicant information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Email:\", \"PII\", 25, true, \"Applicant information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"e-mail:\", \"PII\", 25, true, \"Applicant information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"E-mail address:\", \"PII\", 25, true, \"Applicant information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Contact:\", \"PII\", 25, true, \"Applicant information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Alternative contact:\", \"PII\", 25, true, \"Applicant information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone number:\", \"PII\", 25, true, \"Applicant information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone No:\", \"PII\", 25, true, \"Applicant information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Fax number:\", \"PII\", 25, true, \"Applicant information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone:\", \"PII\", 25, true, \"Applicant information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Phone No.\", \"PII\", 25, true, \"Applicant information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactBetween(\"No:\", \"Fax\", \"PII\", 25, true, \"Applicant information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactBetween(\"Contact:\", \"Tel.:\", \"PII\", 25, true, \"Applicant information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"European contact:\", \"PII\", 25, true, \"Applicant information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.7.0]
103 "33: Purity Hint, 34: Purity Hint, 50: Purity Hint, 25: Purity Hint, 39: Purity Hint" "\n when\n Section(searchText.toLowerCase().contains(\"purity\"))\n then\n\t section.addHintAnnotationByRegEx(\"(purity ?( of|\\\\(.{1,20}\\\\))?( ?:)?) .{0,5}[\\\\d\\\\.]+( .{0,4}\\\\.)? ?%\", true, 1, \"hint_only\");\n end" [ETC.0.0]
104 "25: Redact Purity" "\n when\n Section(searchText.contains(\"purity\"))\n then\n\t section.redactByRegEx(\"purity ?:? (([\\\\d\\\\.]+)( .{0,4}\\\\.)? ?%)\", true, 1, \"purity\", 17, \"Purity found\", \"method_manufacture\");\n end" [ETC.1.0]
105 "26: Redact Phone and Fax by RegEx (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (\n text.contains(\"Contact\")\n || text.contains(\"Telephone\")\n || text.contains(\"Phone\")\n || text.contains(\"Ph.\")\n || text.contains(\"Fax\")\n || text.contains(\"Tel\")\n || text.contains(\"Ter\")\n || text.contains(\"Cell\")\n || text.contains(\"Mobile\")\n || text.contains(\"Fel\")\n || text.contains(\"Fer\")\n ))\n then\n section.redactByRegEx(\"\\\\b(contact|telephone|phone|fax|tel|ter|cell|mobile|fel|fer)[a-zA-Z\\\\s]{0,10}[:.\\\\s]{0,3}([\\\\+\\\\d\\\\(][\\\\s\\\\d\\\\(\\\\)\\\\-\\\\/\\\\.]{4,100}\\\\d)\\\\b\", true, 2, \"PII\", 26, \"Personal information found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.2.1]
106 "26: Redact contact information if applicant is found (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (headlineContainsWord(\"applicant\") || text.contains(\"Applicant\") || headlineContainsWord(\"Primary contact\") || headlineContainsWord(\"Alternative contact\") || text.contains(\"Telephone number:\")))\n then\n section.redactLineAfter(\"Contact point:\", \"PII\", 26, true, \"Applicant information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Phone:\", \"PII\", 26, true, \"Applicant information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Fax:\", \"PII\", 26, true, \"Applicant information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Tel.:\", \"PII\", 26, true, \"Applicant information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Tel:\", \"PII\", 26, true, \"Applicant information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"E-mail:\", \"PII\", 26, true, \"Applicant information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Email:\", \"PII\", 26, true, \"Applicant information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"e-mail:\", \"PII\", 26, true, \"Applicant information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"E-mail address:\", \"PII\", 26, true, \"Applicant information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Contact:\", \"PII\", 26, true, \"Applicant information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Alternative contact:\", \"PII\", 26, true, \"Applicant information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone number:\", \"PII\", 26, true, \"Applicant information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone No:\", \"PII\", 26, true, \"Applicant information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Fax number:\", \"PII\", 26, true, \"Applicant information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone:\", \"PII\", 26, true, \"Applicant information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Phone No.\", \"PII\", 26, true, \"Applicant information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactBetween(\"No:\", \"Fax\", \"PII\", 26, true, \"Applicant information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactBetween(\"Contact:\", \"Tel.:\", \"PII\", 26, true, \"Applicant information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"European contact:\", \"PII\", 26, true, \"Applicant information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.7.0]
107 "26: Redact signatures" "\n when\n Section(matchesImageType(\"signature\"))\n then\n section.redactImage(\"signature\", 26, \"Signature found\", \"names_addresses_persons\");\n end" [ETC.2.0]
108 "26: Redact Phone and Fax by RegEx (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (\n text.contains(\"Contact\")\n || text.contains(\"Telephone\")\n || text.contains(\"Phone\")\n || text.contains(\"Fax\")\n || text.contains(\"Tel\")\n || text.contains(\"Ter\")\n || text.contains(\"Mobile\")\n || text.contains(\"Fel\")\n || text.contains(\"Fer\")\n ))\n then\n section.redactByRegEx(\"\\\\b(contact|telephone|phone|fax|tel|ter|mobile|fel|fer)[a-zA-Z\\\\s]{0,10}[:.\\\\s]{0,3}([\\\\+\\\\d\\\\(][\\\\s\\\\d\\\\(\\\\)\\\\-\\\\/\\\\.]{4,100}\\\\d)\\\\b\", true, 2, \"PII\", 26, \"Personal information found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.2.1]
109 "27: Redact AUTHOR(S) (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\")\n && searchText.contains(\"AUTHOR(S):\")\n && searchText.contains(\"COMPLETION DATE:\")\n && !searchText.contains(\"STUDY COMPLETION DATE:\")\n )\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"COMPLETION DATE:\", \"PII\", 27, true, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.9.0]
110 "27: Redact Logos" "\n when\n Section(matchesImageType(\"logo\"))\n then\n section.redactImage(\"logo\", 27, \"Logo found\", \"names_addresses_persons\");\n end" [ETC.3.0]
111 "27: Redact contact information if Producer is found (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (text.toLowerCase().contains(\"producer of the plant protection\") || text.toLowerCase().contains(\"producer of the active substance\") || text.contains(\"Manufacturer of the active substance\") || text.contains(\"Manufacturer:\") || text.contains(\"Producer or producers of the active substance\")))\n then\n section.redactLineAfter(\"Contact:\", \"PII\", 27, true, \"Producer was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone:\", \"PII\", 27, true, \"Producer was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Phone:\", \"PII\", 27, true, \"Producer was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Fax:\", \"PII\", 27, true, \"Producer was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"E-mail:\", \"PII\", 27, true, \"Producer was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Contact:\", \"PII\", 27, true, \"Producer was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Fax number:\", \"PII\", 27, true, \"Producer was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone number:\", \"PII\", 27, true, \"Producer was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Tel:\", \"PII\", 27, true, \"Producer was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Phone No.\", \"PII\", 27, true, \"Producer was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactBetween(\"No:\", \"Fax\", \"PII\", 27, true, \"Producer was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.8.0]
112 "28: Redact contact information if Producer is found (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (text.toLowerCase().contains(\"producer of the plant protection\") || text.toLowerCase().contains(\"producer of the active substance\") || text.contains(\"Manufacturer of the active substance\") || text.contains(\"Manufacturer:\") || text.contains(\"Producer or producers of the active substance\")))\n then\n section.redactLineAfter(\"Contact:\", \"PII\", 28, true, \"Producer was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone:\", \"PII\", 28, true, \"Producer was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Phone:\", \"PII\", 28, true, \"Producer was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Fax:\", \"PII\", 28, true, \"Producer was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"E-mail:\", \"PII\", 28, true, \"Producer was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Contact:\", \"PII\", 28, true, \"Producer was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Fax number:\", \"PII\", 28, true, \"Producer was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone number:\", \"PII\", 28, true, \"Producer was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Tel:\", \"PII\", 28, true, \"Producer was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Phone No.\", \"PII\", 28, true, \"Producer was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactBetween(\"No:\", \"Fax\", \"PII\", 28, true, \"Producer was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.8.0]
113 "28: Redact AUTHOR(S) (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\")\n && searchText.contains(\"AUTHOR(S):\")\n && searchText.contains(\"COMPLETION DATE:\")\n && !searchText.contains(\"STUDY COMPLETION DATE:\")\n )\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"COMPLETION DATE:\", \"PII\", 28, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.9.0]
114 "28: Redact dossier dictionary match" "\n when\n Section(matchesType(\"dossier_redaction\"))\n then\n section.redact(\"dossier_redaction\", 28, \"Specification of impurity found\", \"specification_impurity_active_substance\");\n end" [ETC.4.0, ETC.4.1, ETC.4.2]
115 "29: Redact AUTHOR(S) (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"AUTHOR(S):\") && searchText.contains(\"COMPLETION DATE:\") && !searchText.contains(\"STUDY COMPLETION DATE:\"))\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"COMPLETION DATE:\", \"PII\", 29, true, \"AUTHOR(S) was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.9.0]
116 "34: Ignore dossier_redaction entries if confidentiality is not 'confidential', 51: Ignore dossier_redaction entries if confidential, 29: Ignore dossier_redaction unless confidential, 40: Ignore dossier_redaction entries if confidential" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Confidentiality\",\"confidential\") && matchesType(\"dossier_redaction\"));\n then\n section.ignore(\"dossier_redaction\");\n end" [ETC.5.0]
117 "29: Redact AUTHOR(S) (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\")\n && searchText.contains(\"AUTHOR(S):\")\n && searchText.contains(\"STUDY COMPLETION DATE:\")\n )\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"STUDY COMPLETION DATE:\", \"PII\", 29, true, \"AUTHOR(S) was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.9.0]
118 "30: Redact AUTHOR(S) (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\")\n && searchText.contains(\"AUTHOR(S):\")\n && searchText.contains(\"STUDY COMPLETION DATE:\")\n )\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"STUDY COMPLETION DATE:\", \"PII\", 30, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.9.1]
119 "30: Redacted PII Personal Identification Information (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesType(\"PII\"))\n then\n section.redact(\"PII\", 30, \"PII (Personal Identification Information) found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.0.0]
120 "30: Redact AUTHOR(S) (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"AUTHOR(S):\") && searchText.contains(\"COMPLETION DATE:\") && !searchText.contains(\"STUDY COMPLETION DATE:\"))\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"COMPLETION DATE:\", \"PII\", 30, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.9.1]
121 "31: Redacted PII Personal Identification Information (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesType(\"PII\"))\n then\n section.redact(\"PII\", 31, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.0.1]
122 "31: Redact AUTHOR(S) (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"AUTHOR(S):\") && searchText.contains(\"STUDY COMPLETION DATE:\"))\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"STUDY COMPLETION DATE:\", \"PII\", 31, true, \"AUTHOR(S) was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.9.0]
123 "31: Redact PERFORMING LABORATORY (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\")\n && searchText.contains(\"PERFORMING LABORATORY:\")\n )\n then\n section.redactBetween(\"PERFORMING LABORATORY:\", \"LABORATORY PROJECT ID:\", \"CBI_address\", 31, true, \"PERFORMING LABORATORY was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactNot(\"CBI_address\", 31, \"Performing laboratory found for non vertebrate study\");\n end" [CBI.20.0]
124 "32: Redact PERFORMING LABORATORY (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\")\n && searchText.contains(\"PERFORMING LABORATORY:\"))\n then\n section.redactBetween(\"PERFORMING LABORATORY:\", \"LABORATORY PROJECT ID:\", \"CBI_address\", 32, true, \"PERFORMING LABORATORY was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.20.1]
125 "32: Redact Emails by RegEx (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"@\"))\n then\n section.redactByRegEx(\"\\\\b([A-Za-z0-9._%+\\\\-]+@[A-Za-z0-9.\\\\-]+\\\\.[A-Za-z\\\\-]{1,23}[A-Za-z])\\\\b\", true, 1, \"PII\", 32, \"PII (Personal Identification Information) found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.1.0]
126 "32: Redact AUTHOR(S) (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"AUTHOR(S):\") && searchText.contains(\"STUDY COMPLETION DATE:\"))\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"STUDY COMPLETION DATE:\", \"PII\", 32, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.9.1]
127 "33: Redact Emails by RegEx (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"@\"))\n then\n section.redactByRegEx(\"\\\\b([A-Za-z0-9._%+\\\\-]+@[A-Za-z0-9.\\\\-]+\\\\.[A-Za-z\\\\-]{1,23}[A-Za-z])\\\\b\", true, 1, \"PII\", 33, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.1.1]
128 "33: Redact study director abbreviation" "\n when\n Section((searchText.contains(\"KATH\") || searchText.contains(\"BECH\") || searchText.contains(\"KML\")))\n then\n section.redactWordPartByRegEx(\"((KATH)|(BECH)|(KML)) ?(\\\\d{4})\", true, 0, 1, \"PII\", 34, \"Personal information found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.10.0]
129 "33: Redact PERFORMING LABORATORY (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"PERFORMING LABORATORY:\"))\n then\n section.redactBetween(\"PERFORMING LABORATORY:\", \"LABORATORY PROJECT ID:\", \"CBI_address\", 33, true, \"PERFORMING LABORATORY was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactNot(\"CBI_address\", 33, \"Performing laboratory found for non vertebrate study\");\n end" [CBI.20.0]
130 "34: Redact PERFORMING LABORATORY (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"PERFORMING LABORATORY:\"))\n then\n section.redactBetween(\"PERFORMING LABORATORY:\", \"LABORATORY PROJECT ID:\", \"CBI_address\", 34, true, \"PERFORMING LABORATORY was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.20.1]
131 "34: Redact telephone numbers by RegEx (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && containsRegEx(\"[+]\\\\d{1,}\", true))\n then\n section.redactByRegEx(\"((([+]\\\\d{1,3} (\\\\d{7,12})\\\\b)|([+]\\\\d{1,3}(\\\\d{3,12})\\\\b|[+]\\\\d{1,3}([ -]\\\\(?\\\\d{1,6}\\\\)?){2,4})|[+]\\\\d{1,3} ?((\\\\d{2,6}\\\\)?)([ -]\\\\d{2,6}){1,4}))(-\\\\d{1,3})?\\\\b)\", true, 1, \"PII\", 34, \"PII (Personal Identification Information) found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.3.0]
132 "35: Redact telephone numbers by RegEx (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && containsRegEx(\"[+]\\\\d{1,}\", true))\n then\n section.redactByRegEx(\"((([+]\\\\d{1,3} (\\\\d{7,12})\\\\b)|([+]\\\\d{1,3}(\\\\d{3,12})\\\\b|[+]\\\\d{1,3}([ -]\\\\(?\\\\d{1,6}\\\\)?){2,4})|[+]\\\\d{1,3} ?((\\\\d{2,6}\\\\)?)([ -]\\\\d{2,6}){1,4}))(-\\\\d{1,3})?\\\\b)\", true, 1, \"PII\", 35, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.3.1]
133 "35: Redact signatures (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesImageType(\"signature\"))\n then\n section.redactImage(\"signature\", 35, \"Signature found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [ETC.2.0]
134 "36: Redact signatures (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesImageType(\"signature\"))\n then\n section.redactImage(\"signature\", 36, \"Signature found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [ETC.2.0]
135 "37: Redact contact information (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (text.contains(\"Contact point:\")\n || text.contains(\"Phone:\")\n || text.contains(\"Fax:\")\n || text.contains(\"Tel.:\")\n || text.contains(\"Tel:\")\n || text.contains(\"E-mail:\")\n || text.contains(\"Email:\")\n || text.contains(\"e-mail:\")\n || text.contains(\"E-mail address:\")\n || text.contains(\"Alternative contact:\")\n || text.contains(\"Telephone number:\")\n || text.contains(\"Telephone No:\")\n || text.contains(\"Fax number:\")\n || text.contains(\"Telephone:\")\n || text.contains(\"Phone No.\")\n || text.contains(\"European contact:\")))\n then\n section.redactLineAfter(\"Contact point:\", \"PII\", 37, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Phone:\", \"PII\", 37, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Fax:\", \"PII\", 37, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Tel.:\", \"PII\", 37, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Tel:\", \"PII\", 37, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"E-mail:\", \"PII\", 37, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Email:\", \"PII\", 37, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"e-mail:\", \"PII\", 37, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"E-mail address:\", \"PII\", 37, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Contact:\", \"PII\", 37, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Alternative contact:\", \"PII\", 37, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone number:\", \"PII\", 37, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone No:\", \"PII\", 37, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Fax number:\", \"PII\", 37, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone:\", \"PII\", 37, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Phone No.\", \"PII\", 37, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactBetween(\"No:\", \"Fax\", \"PII\", 37, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactBetween(\"Contact:\", \"Tel.:\", \"PII\", 37, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"European contact:\", \"PII\", 37, true, \"Contact information was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.4.0, PII.6.0]
136 "38: Redact contact information (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (text.contains(\"Contact point:\")\n || text.contains(\"Phone:\")\n || text.contains(\"Fax:\")\n || text.contains(\"Tel.:\")\n || text.contains(\"Tel:\")\n || text.contains(\"E-mail:\")\n || text.contains(\"Email:\")\n || text.contains(\"e-mail:\")\n || text.contains(\"E-mail address:\")\n || text.contains(\"Alternative contact:\")\n || text.contains(\"Telephone number:\")\n || text.contains(\"Telephone No:\")\n || text.contains(\"Fax number:\")\n || text.contains(\"Telephone:\")\n || text.contains(\"Phone No.\")\n || text.contains(\"European contact:\")))\n then\n section.redactLineAfter(\"Contact point:\", \"PII\", 38, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Phone:\", \"PII\", 38, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Fax:\", \"PII\", 38, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Tel.:\", \"PII\", 38, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Tel:\", \"PII\", 38, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"E-mail:\", \"PII\", 38, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Email:\", \"PII\", 38, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"e-mail:\", \"PII\", 38, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"E-mail address:\", \"PII\", 38, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Contact:\", \"PII\", 38, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Alternative contact:\", \"PII\", 38, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone number:\", \"PII\", 38, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone No:\", \"PII\", 38, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Fax number:\", \"PII\", 38, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone:\", \"PII\", 38, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Phone No.\", \"PII\", 38, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactBetween(\"No:\", \"Fax\", \"PII\", 38, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactBetween(\"Contact:\", \"Tel.:\", \"PII\", 38, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"European contact:\", \"PII\", 38, true, \"Contact information was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.4.1, PII.6.1]
137 "39: Redact AUTHOR(S) (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"AUTHOR(S):\") && searchText.contains(\"COMPLETION DATE:\") && !searchText.contains(\"STUDY COMPLETION DATE:\"))\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"COMPLETION DATE:\", \"PII\", 39, true, \"AUTHOR(S) was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.9.0]
138 "40: Redact AUTHOR(S) (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"AUTHOR(S):\") && searchText.contains(\"COMPLETION DATE:\") && !searchText.contains(\"STUDY COMPLETION DATE:\"))\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"COMPLETION DATE:\", \"PII\", 40, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.9.1]
139 "41: Redact signatures (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesImageType(\"signature\"))\n then\n section.redactImage(\"signature\", 41, \"Signature found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [ETC.2.0]
140 "41: Redact AUTHOR(S) (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"AUTHOR(S):\") && searchText.contains(\"STUDY COMPLETION DATE:\"))\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"STUDY COMPLETION DATE:\", \"PII\", 41, true, \"AUTHOR(S) was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.9.0]
141 "42: Redact signatures (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesImageType(\"signature\"))\n then\n section.redactImage(\"signature\", 42, \"Signature found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [ETC.2.0]
142 "42: Redact AUTHOR(S) (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"AUTHOR(S):\") && searchText.contains(\"STUDY COMPLETION DATE:\"))\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"STUDY COMPLETION DATE:\", \"PII\", 42, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.9.1]
143 "43: Redact PERFORMING LABORATORY (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"PERFORMING LABORATORY:\"))\n then\n section.redactBetween(\"PERFORMING LABORATORY:\", \"LABORATORY PROJECT ID:\", \"CBI_address\", 43, true, \"PERFORMING LABORATORY was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactNot(\"CBI_address\", 43, \"Performing laboratory found for non vertebrate study\");\n end" [CBI.20.0]
144 "43: Redact Logos (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesImageType(\"logo\"))\n then\n section.redactImage(\"logo\", 43, \"Logo found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [ETC.3.0]
145 "44: Redact PERFORMING LABORATORY (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"PERFORMING LABORATORY:\"))\n then\n section.redactBetween(\"PERFORMING LABORATORY:\", \"LABORATORY PROJECT ID:\", \"CBI_address\", 44, true, \"PERFORMING LABORATORY was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.20.1]
146 "52: Redact signatures (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesImageType(\"signature\"))\n then\n section.redactImage(\"signature\", 52, \"Signature found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [ETC.2.0]
147 "53: Redact signatures (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesImageType(\"signature\"))\n then\n section.redactImage(\"signature\", 53, \"Signature found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [ETC.2.0]
148 "54: Redact Logos (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesImageType(\"logo\"))\n then\n section.redactImage(\"logo\", 54, \"Logo found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [ETC.3.0]
149 "0: Expand CBI Authors with firstname initials" "\n when\n Section(matchesType(\"CBI_author\"))\n then\n section.expandByRegEx(\"CBI_author\", \"(,? [A-Z]\\\\.?( ?[A-Z]\\\\.?)?( ?[A-Z]\\\\.?)?\\\\b\\\\.?)\", false, 1);\n end" [CBI.18.0]
150 "0: Expand CBI Authors with firstname initials" "\n when\n Section(matchesType(\"CBI_author\"))\n then\n section.expandByRegEx(\"CBI_author\", \"(,? [A-Z]\\\\.?( ?[A-Z]\\\\.?)?( ?[A-Z]\\\\.?)?\\\\b\\\\.?)\", false, 1, \"[^\\\\s]+\");\n end" [CBI.18.0]
151 "0: Expand CBI_author and PII matches with salutation prefix" "\n when\n Section((matchesType(\"CBI_author\") || matchesType(\"PII\")) && (\n searchText.contains(\"Mr\")\n || searchText.contains(\"Mrs\")\n || searchText.contains(\"Ms\")\n || searchText.contains(\"Miss\")\n || searchText.contains(\"Sir\")\n || searchText.contains(\"Madam\")\n || searchText.contains(\"Madame\")\n || searchText.contains(\"Mme\")\n ))\n then\n section.expandByPrefixRegEx(\"CBI_author\", \"\\\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\\\s?\\\\.?\\\\s*\", false, 0);\n section.expandByPrefixRegEx(\"PII\", \"\\\\b(Mrs?|Ms|Miss|Sir|Madame?|Mme)\\\\s?\\\\.?\\\\s*\", false, 0);\n end" [CBI.19.0, PII.12.0]
152 "102: Guidelines FileAttributes" "\n when\n Section((text.contains(\"DATA REQUIREMENT(S):\") || text.contains(\"TEST GUIDELINE(S):\")) && (text.contains(\"OECD\") || text.contains(\"EPA\") || text.contains(\"OPPTS\")))\n then\n section.addFileAttribute(\"OECD Number\", \"OECD (No\\\\.? )?\\\\d{3}( \\\\(\\\\d{4}\\\\))?\", false, 0);\n end" [ETC.7.0]
153 "28: Redact Logos" "\n when\n Section(matchesImageType(\"logo\"))\n then\n section.redactImage(\"logo\", 28, \"Logo found\", \"names_addresses_persons\");\n end" [ETC.3.0]
154 "8: Redact Author cells in Tables with Author header (Non vertebrate study)" "\n when\n Section(hasTableHeader(\"h5.1\"))\n then\n section.redactCell(\"h5.1\", 8, \"CBI_author\", false, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [CBI.9.0, CBI.11.0]
155 "30: Ignore dossier_redactions if confidential" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Confidentiality\",\"confidential\") && matchesType(\"dossier_redactions\"));\n then\n section.ignore(\"dossier_redactions\");\n end" [ETC.5.0]
156 "27: Redact formula" "\n when\n Section(matchesImageType(\"formula\"))\n then\n section.redactImage(\"formula\", 27, \"Formula found\", \"names_addresses_persons\");\n end" [ETC.8.0]
157 "5: Do not redact Names and Addresses if no redaction Indicator is contained" "\n when\n Section(matchesType(\"vertebrate\"), matchesType(\"published_information\"))\n then\n section.redactNotAndReference(\"CBI_author\",\"published_information\", 5, \"Vertebrate and Published Information found\");\n section.redactNotAndReference(\"CBI_address\",\"published_information\", 5, \"Vertebrate and Published Information found\");\n end" [CBI.4.0]
158 "29: Redact Dossier Redactions" "\n when\n Section(matchesType(\"dossier_redactions\"))\n then\n section.redact(\"dossier_redactions\", 29, \"Dossier Redaction found\", \"Article 39(1)(2) of Regulation (EC) No 178/2002\");\n end" [ETC.4.0, ETC.4.1, ETC.4.2]
159 "10: Redact determination of residues" "\n when\n Section((\n searchText.toLowerCase.contains(\"determination of residues\") ||\n searchText.toLowerCase.contains(\"determination of total residues\")\n ) && (\n searchText.toLowerCase.contains(\"livestock\") ||\n searchText.toLowerCase.contains(\"live stock\") ||\n searchText.toLowerCase.contains(\"tissue\") ||\n searchText.toLowerCase.contains(\"tissues\") ||\n searchText.toLowerCase.contains(\"liver\") ||\n searchText.toLowerCase.contains(\"muscle\") ||\n searchText.toLowerCase.contains(\"bovine\") ||\n searchText.toLowerCase.contains(\"ruminant\") ||\n searchText.toLowerCase.contains(\"ruminants\")\n ))\n then\n section.redact(\"CBI_author\", 10, \"Determination of residues was found.\", \"names_addresses_persons\");\n section.redact(\"CBI_address\", 10, \"Determination of residues was found.\", \"names_addresses_persons\");\n section.addHintAnnotation(\"determination of residues\", \"must_redact\");\n section.addHintAnnotation(\"livestock\", \"must_redact\");\n section.addHintAnnotation(\"live stock\", \"must_redact\");\n section.addHintAnnotation(\"tissue\", \"must_redact\");\n section.addHintAnnotation(\"tissues\", \"must_redact\");\n section.addHintAnnotation(\"liver\", \"must_redact\");\n section.addHintAnnotation(\"muscle\", \"must_redact\");\n section.addHintAnnotation(\"bovine\", \"must_redact\");\n section.addHintAnnotation(\"ruminant\", \"must_redact\");\n section.addHintAnnotation(\"ruminants\", \"must_redact\");\n end" [CBI.15.0]
160 "19: Redact AUTHOR(S)" "\n when\n Section(searchText.contains(\"AUTHOR(S):\") && fileAttributeByPlaceholderEquals(\"{fileattributes.vertebrateStudy}\", \"true\"))\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"COMPLETION DATE:\", \"PII\", 19, true, \"AUTHOR(S) was found\", \"links_producer_applicant\");\n end" [PII.9.1]
161 "101: Redact CAS numbers" "\n when\n Section(hasTableHeader(\"Sample #\"))\n then\n section.redactCell(\"Sample #\", 8, \"PII\", true, \"Redacted because row is a vertebrate study\", \"names_addresses_persons\");\n end" [ETC.6.0]
162 "21: Redact Emails by RegEx" "\n when\n Section(searchText.contains(\"@\"))\n then\n section.redactByRegEx(\"\\\\b([A-Za-z0-9._%+\\\\-]+@[A-Za-z0-9.\\\\-]+\\\\.[A-Za-z\\\\-]{1,23}[A-Za-z])\\\\b\", true, 1, \"PII\", 21, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.1.0, PII.1.1]
163 "32: Redact signatures" "\n when\n Section(matchesImageType(\"signature\"))\n then\n section.redactImage(\"signature\", 32, \"Signature found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [ETC.2.0, ETC.2.1]
164 "11: Do not redact Names and Addresses if Published Information found" "\n when\n Section(matchesType(\"published_information\"))\n then\n section.redactNotAndReference(\"CBI_author\",\"published_information\", 11, \"Published Information found\");\n section.redactNotAndReference(\"CBI_address\",\"published_information\", 11, \"Published Information found\");\n end" [CBI.7.0, CBI.7.1]
165 "9: Add recommendation for Addresses in Test Organism sections" "\n when\n Section(searchText.contains(\"Species:\") && searchText.contains(\"Source:\"))\n then\n section.recommendLineAfter(\"Source:\", \"CBI_address\");\n end" [CBI.17.1]
166 "5: Redact Author cells in Tables with Author header" "\n when\n Section(hasTableHeader(\"Author\") && !hasTableHeader(\"Vertebrate study Y/N\"))\n then\n section.redactCell(\"Author\", 5, \"CBI_author\", false, \"Author found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.9.1, CBI.10.1]
167 "21: Redact Phone and Fax by RegEx" "\n when\n Section(\n text.contains(\"Telephone\")\n || text.contains(\"Phone\")\n || text.contains(\"Ph.\")\n || text.contains(\"Fax\")\n || text.contains(\"Tel\")\n || text.contains(\"Ter\")\n || text.contains(\"Cell\")\n || text.contains(\"Mobile\")\n || text.contains(\"Fel\")\n || text.contains(\"Fer\")\n )\n then\n section.redactByRegEx(\"\\\\b(telephone|phone|fax|tel|ter|cell|mobile|fel|fer)[:.\\\\s]{0,3}((\\\\(?\\\\+?[0-9])(\\\\(?[0-9\\\\/.\\\\-\\\\s]+\\\\)?)*([0-9]+\\\\)?))\\\\b\", true, 2, \"PII\", 23, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.2.0, PII.2.1]
168 "2: Redact CBI Address" "\n when\n Section(matchesType(\"CBI_address\"))\n then\n section.redact(\"CBI_address\", 4, \"Address found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.1.1]
169 "25: Redact AUTHOR(S)" "\n when\n Section(searchText.contains(\"AUTHOR(S):\")\n && searchText.contains(\"COMPLETION DATE:\")\n && !searchText.contains(\"STUDY COMPLETION DATE:\"))\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"COMPLETION DATE:\", \"PII\", 25, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.9.0, PII.9.1]
170 "6: Redact and recommand Authors in Tables with Vertebrate study Y/N header" "\n when\n Section(rowEquals(\"Vertebrate study Y/N\", \"Y\") || rowEquals(\"Vertebrate study Y/N\", \"Yes\") || rowEquals(\"Vertebrate study Y/N\", \"N\") || rowEquals(\"Vertebrate study Y/N\", \"No\"))\n then\n section.redactCell(\"Author(s)\", 6, \"CBI_author\", true, \"Author found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.9.0, CBI.9.1, CBI.10.0, CBI.10.1, CBI.11.0, CBI.12.0, CBI.12.1]
171 "22: Redact contact information" "\n when\n Section(text.contains(\"Contact point:\")\n || text.contains(\"Phone:\")\n || text.contains(\"Fax:\")\n || text.contains(\"Tel.:\")\n || text.contains(\"Tel:\")\n || text.contains(\"E-mail:\")\n || text.contains(\"Email:\")\n || text.contains(\"e-mail:\")\n || text.contains(\"E-mail address:\")\n || text.contains(\"Contact:\")\n || text.contains(\"Alternative contact:\")\n || text.contains(\"Telephone number:\")\n || text.contains(\"Telephone No:\")\n || text.contains(\"Fax number:\")\n || text.contains(\"Telephone:\")\n || text.contains(\"Phone No.\")\n || (text.contains(\"No:\") && text.contains(\"Fax\"))\n || (text.contains(\"Contact:\") && text.contains(\"Tel.:\"))\n || text.contains(\"European contact:\")\n )\n then\n section.redactLineAfter(\"Contact point:\", \"PII\", 22, true, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Phone:\", \"PII\", 22, true, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Fax:\", \"PII\", 22, true, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Tel.:\", \"PII\", 22, true, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Tel:\", \"PII\", 22, true, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"E-mail:\", \"PII\", 22, true, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Email:\", \"PII\", 22, true, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"e-mail:\", \"PII\", 22, true, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"E-mail address:\", \"PII\", 22, true, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Contact:\", \"PII\", 22, true, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Alternative contact:\", \"PII\", 22, true, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone number:\", \"PII\", 22, true, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone No:\", \"PII\", 22, true, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Fax number:\", \"PII\", 22, true, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Telephone:\", \"PII\", 22, true, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"Phone No.\", \"PII\", 22, true, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactBetween(\"No:\", \"Fax\", \"PII\", 22, true, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactBetween(\"Contact:\", \"Tel.:\", \"PII\", 22, true, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLineAfter(\"European contact:\", \"PII\", 22, true, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.4.0, PII.4.1, PII.5.0, PII.5.1, PII.6.0, PII.6.1, PII.7.0, PII.7.1, PII.8.0, PII.8.1]
172 "20: Redacted PII Personal Identification Information" "\n when\n Section(matchesType(\"PII\"))\n then\n section.redact(\"PII\", 20, \"PII (Personal Identification Information) found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.0.0, PII.0.1]
173 "1: Redact CBI Authors" "\n when\n Section(matchesType(\"CBI_author\"))\n then\n section.redact(\"CBI_author\", 1, \"Author found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.0.0, CBI.0.1]
174 "4: Redact Author(s) cells in Tables with Author(s) header" "\n when\n Section(hasTableHeader(\"Author(s)\") && !hasTableHeader(\"Vertebrate study Y/N\"))\n then\n section.redactCell(\"Author(s)\", 4, \"CBI_author\", false, \"Author found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.9.0, CBI.10.0]
175 "8: Redact and add recommendation for et al. author" "\n when\n Section(searchText.contains(\"et al\"))\n then\n section.redactAndRecommendByRegEx(\"\\\\b([A-ZÄÖÜ][^\\\\s\\\\.,]+( [A-ZÄÖÜ]{1,2}\\\\.?)?( ?[A-ZÄÖÜ]\\\\.?)?) et al\\\\.?\", false, 1, \"CBI_author\", 15, \"Author found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.16.0, CBI.16.1]
176 "26: Redact AUTHOR(S)" "\n when\n Section(searchText.contains(\"AUTHOR(S):\") && searchText.contains(\"STUDY COMPLETION DATE:\"))\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"STUDY COMPLETION DATE:\", \"PII\", 26, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.9.0, PII.9.1]
177 "27: Redact PERFORMING LABORATORY" "\n when\n Section(searchText.contains(\"PERFORMING LABORATORY:\"))\n then\n section.redactBetween(\"PERFORMING LABORATORY:\", \"LABORATORY PROJECT ID:\", \"CBI_address\", 27, true, \"PERFORMING LABORATORY was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.20.0, CBI.20.1]
178 "10: Add recommendation for Addresses in Test Animals sections" "\n when\n Section(searchText.contains(\"Species\") && searchText.contains(\"Source\"))\n then\n section.recommendLineAfter(\"Source\", \"CBI_address\");\n end" [CBI.17.0, CBI.17.1]
179 "33: Redact Logos" "\n when\n Section(matchesImageType(\"logo\"))\n then\n section.redactImage(\"logo\", 33, \"Logo found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [ETC.3.0, ETC.3.1]
180 "26: Redact Phone and Fax by RegEx (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (\n text.contains(\"Contact\")\n || text.contains(\"Telephone\")\n || text.contains(\"Phone\")\n || text.contains(\"Ph.\")\n || text.contains(\"Fax\")\n || text.contains(\"Tel\")\n || text.contains(\"Ter\")\n || text.contains(\"Mobile\")\n || text.contains(\"Fel\")\n || text.contains(\"Fer\")\n ))\n then\n section.redactByRegEx(\"\\\\b(contact|telephone|phone|ph\\\\.|fax|tel|ter|mobile|fel|fer)[a-zA-Z\\\\s]{0,10}[:.\\\\s]{0,3}([\\\\+\\\\d\\\\(][\\\\s\\\\d\\\\(\\\\)\\\\-\\\\/\\\\.]{4,100}\\\\d)\\\\b\", true, 2, \"PII\", 26, \"Personal information found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.2.1]
181 "25: Redact Phone and Fax by RegEx (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (\n text.contains(\"Contact\")\n || text.contains(\"Telephone\")\n || text.contains(\"Phone\")\n || text.contains(\"Ph.\")\n || text.contains(\"Fax\")\n || text.contains(\"Tel\")\n || text.contains(\"Ter\")\n || text.contains(\"Mobile\")\n || text.contains(\"Fel\")\n || text.contains(\"Fer\")\n ))\n then\n section.redactByRegEx(\"\\\\b(contact|telephone|phone|ph\\\\.|fax|tel|ter|mobile|fel|fer)[a-zA-Z\\\\s]{0,10}[:.\\\\s]{0,3}([\\\\+\\\\d\\\\(][\\\\s\\\\d\\\\(\\\\)\\\\-\\\\/\\\\.]{4,100}\\\\d)\\\\b\", true, 2, \"PII\", 25, \"Personal information found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.2.0]
182 "10: Add recommendation for Addresses in Test Animals sections" "\n when\n Section(searchText.contains(\"Species\") && searchText.contains(\"Source\"))\n then\n\t\tsection.recommendLineAfter(\"Source\", \"PII\");\n end" [CBI.17.0, CBI.17.1]
183 "0: Combine address parts from AI to addresses as PII (org is mandatory)" "\n when\n Section(aiMatchesType(\"ORG\"))\n then\n section.combineAiTypes(\"ORG\", \"STREET,POSTAL,COUNTRY,CARDINAL,CITY,STATE\", 20, \"PII\", 3, false);\n end" [AI.1.0]
184 "0: Combine address parts from AI to addresses as PII (street is mandatory)" "\n when\n Section(aiMatchesType(\"STREET\"))\n then\n section.combineAiTypes(\"STREET\", \"ORG,POSTAL,COUNTRY,CARDINAL,CITY,STATE\", 20, \"PII\", 3, false);\n end" [AI.1.0]
185 "18: Redact AUTHOR(S)" "\n when\n Section(searchText.contains(\"AUTHOR(S):\") && searchText.contains(\"STUDY COMPLETION DATE:\"))\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"STUDY COMPLETION DATE:\", \"PII\", 18, true, \"AUTHOR(S) was found\", \"personal_data_geolocation\");\n end" [PII.9.0, PII.9.1]
186 "0: Combine address parts from AI to addresses as PII (city is mandatory)" "\n when\n Section(aiMatchesType(\"CITY\"))\n then\n section.combineAiTypes(\"CITY\", \"ORG,STREET,POSTAL,COUNTRY,CARDINAL,STATE\", 20, \"PII\", 3, false);\n end" [AI.1.0]
187 "24: Redact signatures" "\n when\n Section(matchesImageType(\"signature\"))\n then\n section.redactImage(\"signature\", 24, \"Signature found\", \"personal_data_geolocation\");\n end" [ETC.2.0, ETC.2.1]
188 "13: Redact Emails by RegEx" "\n when\n Section(searchText.contains(\"@\"))\n then\n section.redactByRegEx(\"\\\\b([A-Za-z0-9._%+\\\\-]+@[A-Za-z0-9.\\\\-]+\\\\.[A-Za-z\\\\-]{1,23}[A-Za-z])\\\\b\", true, 1, \"PII\", 13, \"PII (Personal Identification Information) found\", \"personal_data_geolocation\");\n end" [PII.1.0, PII.1.1]
189 "4: Redact Author(s) cells in Tables with Author(s) header" "\n when\n Section(hasTableHeader(\"Author(s)\") && !hasTableHeader(\"Vertebrate study Y/N\"))\n then\n section.redactCell(\"Author(s)\", 4, \"PII\", false, \"Author found\", \"personal_data_geolocation\");\n end" [CBI.9.0, CBI.10.0, CBI.11.0]
190 "25: Redact Logos" "\n when\n Section(matchesImageType(\"logo\"))\n then\n section.redactImage(\"logo\", 25, \"Logo found\", \"personal_data_geolocation\");\n end" [ETC.3.0, ETC.3.1]
191 "11: Do not redact Names and Addresses if Published Information found" "\n when\n Section(matchesType(\"published_information\"))\n then\n section.redactNot(\"PII\", 11, \"Published Information found\");\n section.redactNot(\"PII\", 11, \"Published Information found\");\n end" [CBI.7.0, CBI.7.1, CBI.6.0, CBI.6.1]
192 "2: Do not redact genitive PIIs" "\n when\n Section(matchesType(\"PII\"))\n then\n section.expandToFalsePositiveByRegEx(\"PII\", \"['’’'ʼˈ´`‘′ʻ’']s\", false, 0);\n end" [CBI.2.0]
193 "5: Redact Author cells in Tables with Author header" "\n when\n Section(hasTableHeader(\"Author\") && !hasTableHeader(\"Vertebrate study Y/N\"))\n then\n section.redactCell(\"Author\", 5, \"PII\", false, \"Author found\", \"personal_data_geolocation\");\n end" [CBI.9.1, CBI.10.1, CBI.12.0]
194 "19: Redact PERFORMING LABORATORY" "\n when\n Section(searchText.contains(\"PERFORMING LABORATORY:\"))\n then\n section.redactBetween(\"PERFORMING LABORATORY:\", \"LABORATORY PROJECT ID:\", \"PII\", 19, true, \"PERFORMING LABORATORY was found\", \"personal_data_geolocation\");\n end" [CBI.20.0, CBI.20.1]
195 "0: Recommend authors from AI as PII" "\n when\n Section(aiMatchesType(\"CBI_author\"))\n then\n section.addAiEntities(\"CBI_author\", \"PII\");\n end" [AI.3.0]
196 "9: Add recommendation for Addresses in Test Organism sections" "\n when\n Section(searchText.contains(\"Species:\") && searchText.contains(\"Source:\"))\n then\n\t\tsection.recommendLineAfter(\"Source:\", \"PII\");\n end" [CBI.17.1]
197 "1: Redacted PII Personal Identification Information" "\n when\n Section(matchesType(\"PII\"))\n then\n section.redact(\"PII\", 1, \"Personal information found\", \"personal_data_geolocation\");\n end" [PII.0.0, PII.0.1]
198 "8: Redact and add recommendation for et al. author" "\n when\n Section(searchText.contains(\"et al\"))\n then\n\t\tsection.redactAndRecommendByRegEx(\"\\\\b([A-ZÄÖÜ][^\\\\s\\\\.,]+( [A-ZÄÖÜ]{1,2}\\\\.?)?( ?[A-ZÄÖÜ]\\\\.?)?) et al\\\\.?\", false, 1, \"PII\", 8, \"Author found\", \"personal_data_geolocation\");\n end" [CBI.16.0, CBI.16.1]
199 "14: Redact contact information" "\n when\n Section(text.contains(\"Contact point:\")\n || text.contains(\"Phone:\")\n || text.contains(\"Fax:\")\n || text.contains(\"Tel.:\")\n || text.contains(\"Tel:\")\n || text.contains(\"E-mail:\")\n || text.contains(\"Email:\")\n || text.contains(\"e-mail:\")\n || text.contains(\"E-mail address:\")\n || text.contains(\"Contact:\")\n || text.contains(\"Alternative contact:\")\n || text.contains(\"Telephone number:\")\n || text.contains(\"Telephone No:\")\n || text.contains(\"Fax number:\")\n || text.contains(\"Telephone:\")\n || text.contains(\"Phone No.\")\n || (text.contains(\"No:\") && text.contains(\"Fax\"))\n || (text.contains(\"Contact:\") && text.contains(\"Tel.:\"))\n || text.contains(\"European contact:\")\n )\n then\n section.redactLineAfter(\"Contact point:\", \"PII\", 14, true, \"Personal information found\", \"personal_data_geolocation\");\n section.redactLineAfter(\"Phone:\", \"PII\", 14, true, \"Personal information found\", \"personal_data_geolocation\");\n section.redactLineAfter(\"Fax:\", \"PII\", 14, true, \"Personal information found\", \"personal_data_geolocation\");\n section.redactLineAfter(\"Tel.:\", \"PII\", 14, true, \"Personal information found\", \"personal_data_geolocation\");\n section.redactLineAfter(\"Tel:\", \"PII\", 14, true, \"Personal information found\", \"personal_data_geolocation\");\n section.redactLineAfter(\"E-mail:\", \"PII\", 14, true, \"Personal information found\", \"personal_data_geolocation\");\n section.redactLineAfter(\"Email:\", \"PII\", 14, true, \"Personal information found\", \"personal_data_geolocation\");\n section.redactLineAfter(\"e-mail:\", \"PII\", 14, true, \"Personal information found\", \"personal_data_geolocation\");\n section.redactLineAfter(\"E-mail address:\", \"PII\", 14, true, \"Personal information found\", \"personal_data_geolocation\");\n section.redactLineAfter(\"Contact:\", \"PII\", 14, true, \"Personal information found\", \"personal_data_geolocation\");\n section.redactLineAfter(\"Alternative contact:\", \"PII\", 14, true, \"Personal information found\", \"personal_data_geolocation\");\n section.redactLineAfter(\"Telephone number:\", \"PII\", 14, true, \"Personal information found\", \"personal_data_geolocation\");\n section.redactLineAfter(\"Telephone No:\", \"PII\", 14, true, \"Personal information found\", \"personal_data_geolocation\");\n section.redactLineAfter(\"Fax number:\", \"PII\", 14, true, \"Personal information found\", \"personal_data_geolocation\");\n section.redactLineAfter(\"Telephone:\", \"PII\", 14, true, \"Personal information found\", \"personal_data_geolocation\");\n section.redactLineAfter(\"Phone No.\", \"PII\", 14, true, \"Personal information found\", \"personal_data_geolocation\");\n section.redactBetween(\"No:\", \"Fax\", \"PII\", 14, true, \"Personal information found\", \"personal_data_geolocation\");\n section.redactBetween(\"Contact:\", \"Tel.:\", \"PII\", 14, true, \"Personal information found\", \"personal_data_geolocation\");\n section.redactLineAfter(\"European contact:\", \"PII\", 14, true, \"Personal information found\", \"personal_data_geolocation\");\n end" [PII.4.0, PII.4.1, PII.6.0, PII.6.1]
200 "17: Redact AUTHOR(S)" "\n when\n Section(searchText.contains(\"AUTHOR(S):\"))\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"COMPLETION DATE:\", \"PII\", 17, true, \"AUTHOR(S) was found\", \"personal_data_geolocation\");\n end" [PII.9.0, PII.9.1]
201 "6: Redact and recommand Authors in Tables with Vertebrate study Y/N header" "\n when\n Section(rowEquals(\"Vertebrate study Y/N\", \"Y\") || rowEquals(\"Vertebrate study Y/N\", \"Yes\") || rowEquals(\"Vertebrate study Y/N\", \"N\") || rowEquals(\"Vertebrate study Y/N\", \"No\"))\n then\n section.redactCell(\"Author(s)\", 6, \"PII\", false, \"Author found\", \"personal_data_geolocation\");\n end" [CBI.11.0, CBI.12.2, CBI.12.1]
202 "27: Redact Logos" "\n °when\n Section(matchesImageType(\"logo\"))\n then\n //section.redactImage(\"logo\", 27, \"Logo found\", \"names_addresses_persons\");\n section.redactNotImage(\"logo\", 27, \"No Logos in preGFL documents\");\n end" [ETC.3.0, ETC.3.1]
203 "27: Redact Logos" "\n when\n Section(matchesImageType(\"logo\"))\n then\n //section.redactImage(\"logo\", 27, \"Logo found\", \"names_addresses_persons\");\n section.redactNotImage(\"logo\", 27, \"No Logos in preGFL documents\");\n end" [ETC.3.0, ETC.3.1]
204 "10a: Redact Addresses in Reference Tables for vertebrate studies in non-vertebrate documents" "\n when\n Section(hasTableHeader(\"Vertebrate study Y/N\") && (rowEquals(\"Vertebrate study Y/N\", \"Y\") || rowEquals(\"Vertebrate study Y/N\", \"Yes\")))\n then\n section.redact(\"CBI_address\", 10, \"Redacted because row is a vertebrate study\", \"names_addresses_persons\");\n end" [CBI.22.0]
205 "27a: Redact AUTHOR(S) (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\")\n && searchText.toUpperCase().contains(\"AUTHOR(S)\")\n && !searchText.toUpperCase().contains(\"AUTHOR(S):\")\n && searchText.toUpperCase().contains(\"COMPLETION DATE\")\n && !searchText.toUpperCase().contains(\"STUDY COMPLETION DATE\")\n )\n then\n section.redactLinesBetween(\"AUTHOR(S)\", \"COMPLETION DATE\", \"CBI_author\", 27, true, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s)\", \"Completion Date\", \"CBI_author\", 27, true, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"AUTHOR(S)\\n\", \"COMPLETION DATE\", \"CBI_author\", 27, true, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s)\\n\", \"Completion Date\", \"CBI_author\", 27, true, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.9.0]
206 "29b: Redact short Authors section" "\n when\n Section(\n !fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\")\n && searchText.toLowerCase().contains(\"author(s)\")\n && searchText.length() < 50\n && sectionNumber <= 20\n && !aiMatchesType(\"CBI_Author\")\n )\n then\n section.redactByRegEx(\"(?<=author\\\\(?s\\\\)?\\\\s\\\\n?)([\\\\p{Lu}\\\\p{L} ]{5,15}(,|\\\\n)?){1,3}\",true,0,\"CBI_author\",29,\"AUTHOR(S) was found\",\"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [CBI.21.0]
207 "28a: Redact AUTHOR(S) (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\")\n && searchText.toUpperCase().contains(\"AUTHOR(S)\")\n && !searchText.toUpperCase().contains(\"AUTHOR(S):\")\n && searchText.toUpperCase().contains(\"COMPLETION DATE\")\n && !searchText.toUpperCase().contains(\"STUDY COMPLETION DATE\")\n )\n then\n section.redactLinesBetween(\"AUTHOR(S)\", \"COMPLETION DATE\", \"CBI_author\", 28, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s)\", \"Completion Date\", \"CBI_author\", 28, true, \"Author(s) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"AUTHOR(S)\\n\", \"COMPLETION DATE\", \"CBI_author\", 28, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s)\\n\", \"Completion Date\", \"CBI_author\", 28, true, \"Author(s) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.9.1]
208 "65: Redact Skipped Impurities" "\n when\n Section((fileAttributeByLabelEqualsIgnoreCase(\"Redact Skipped Impurities\",\"Yes\") || fileAttributeByLabelEqualsIgnoreCase(\"Redact Skipped Impurities\",\"Y\")) && matchesType(\"skipped_impurities\"))\n then\n section.redact(\"skipped_impurities\", 65, \"Occasional Impurity found\", \"specification_impurity\");\n end" [ETC.9.0]
209 "19c: Recommend first line in table cell with name and address of owner" "\n when\n Section(searchText.toLowerCase().contains(\"trial site\") && hasTableHeader(\"Name and Address of Owner / Tenant\"))\n then\n section.redactCell(\"Name and Address of Owner / Tenant\",19,\"PII\",true,\"Trial Site owner and address found\",\"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [ETC.11.0]
210 "67: Redact Product Composition Information" "\n when\n Section(matchesType(\"product_composition\"))\n then\n section.redact(\"product_composition\",67, \"Product Composition Information found\",\"composition_plant_protection_product\");\n end" [ETC.10.0]
211 "25: Redact Phone and Fax by RegEx (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (\n text.contains(\"Contact\")\n || text.contains(\"Telephone\")\n || text.contains(\"Téléphone\")\n || text.contains(\"Phone\")\n || text.contains(\"Fax\")\n || text.contains(\"Tel\")\n || text.contains(\"Ter\")\n || text.contains(\"Mobile\")\n || text.contains(\"Fel\")\n || text.contains(\"Fer\")\n ))\n then\n section.redactByRegEx(\"\\\\b(contact|t\\\\p{Ll}l\\\\p{Ll}phone|phone|fax|tel|ter|mobile|fel|fer)[a-zA-Z\\\\s\\\\.]{0,10}[:.\\\\s]{0,3}([\\\\+\\\\d\\\\(O][\\\\s\\\\d\\\\(\\\\)\\\\-\\\\/\\\\.O]{4,100}\\\\d)\\\\b\", true, 2, \"PII\", 25, \"Personal information found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.2.0]
212 "19a: recommend title prefixed words as PII" "\n when\n Section(\n searchText.contains(\"Dr \")\n || searchText.contains(\"PD Dr \")\n || searchText.contains(\"Prof. Dr \")\n || searchText.contains(\"Dr. med. vet \")\n || searchText.contains(\"Dr. rer. nat \")\n || searchText.contains(\"PhD \")\n || searchText.contains(\"BSc \")\n || searchText.contains(\"(FH) \")\n || searchText.contains(\"Mr \")\n || searchText.contains(\"Mrs \")\n || searchText.contains(\"Ms \")\n || searchText.contains(\"Miss \")\n || searchText.contains(\"Dr.\")\n || searchText.contains(\"PD Dr.\")\n || searchText.contains(\"Prof. Dr.\")\n || searchText.contains(\"Dr. med. vet.\")\n || searchText.contains(\"Dr. rer. nat.\")\n || searchText.contains(\"PhD.\")\n || searchText.contains(\"BSc.\")\n || searchText.contains(\"(FH).\")\n || searchText.contains(\"Mr.\")\n || searchText.contains(\"Mrs.\")\n || searchText.contains(\"Ms.\")\n || searchText.contains(\"Miss.\")\n )\n then\n section.addRecommendationByRegEx(\"((Dr|PD Dr|Prof. Dr|Dr. med. vet|Dr. rer. nat|PhD|BSc|\\\\(FH\\\\)|Mr|Mrs|Ms|Miss)[.\\\\s]{1,2})([\\\\p{Lu}][\\\\p{L}\\\\-.]{1,20}\\\\s[\\\\p{Lu}][\\\\p{L}\\\\-.]{1,20})\", false, 3, \"PII\");\n end" [PII.14.0]
213 "0: Combine address parts from ai to CBI_address (city is mandatory)" "\n when\n Section(aiMatchesType(\"CITY\"))\n then\n section.combineAiTypes(\"CITY\", \"ORG,DEPARTMENT,STREET,POSTAL,COUNTRY,CARDINAL,STATE\", 20, \"CBI_address\", 3, false);\n end" [AI.1.0]
214 "29: Redact AUTHOR(S) (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\")\n && searchText.toUpperCase().contains(\"AUTHOR(S):\")\n && searchText.toUpperCase().contains(\"STUDY COMPLETION DATE:\")\n )\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"STUDY COMPLETION DATE:\", \"CBI_author\", 29, true, \"AUTHOR(S) was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s):\", \"Study Completion Date:\", \"CBI_author\", 29, true, \"AUTHOR(S) was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s):\", \"Study completion Date:\", \"CBI_author\", 29, true, \"AUTHOR(S) was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"AUTHOR(S):\\n\", \"STUDY COMPLETION DATE:\", \"CBI_author\", 29, true, \"AUTHOR(S) was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s):\\n\", \"Study Completion Date:\", \"CBI_author\", 29, true, \"AUTHOR(S) was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s):\\n\", \"Study completion Date:\", \"CBI_author\", 29, true, \"AUTHOR(S) was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.9.0]
215 "22: Redact Emails by RegEx (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"@\"))\n then\n section.redactByRegEx(\"\\\\b([A-Za-z0-9._%+\\\\-]+@\\\\s?[A-Za-z0-9.\\\\-]+\\\\.[A-Za-z\\\\-]{1,23}[A-Za-z])\\\\b\", true, 1, \"PII\", 22, \"Personal information found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.1.1]
216 "27: Redact AUTHOR(S) (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\")\n && searchText.toUpperCase().contains(\"AUTHOR(S):\")\n && searchText.toUpperCase().contains(\"COMPLETION DATE:\")\n && !searchText.toUpperCase().contains(\"STUDY COMPLETION DATE:\")\n )\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"COMPLETION DATE:\", \"CBI_author\", 27, true, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s):\", \"Completion Date:\", \"CBI_author\", 27, true, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"AUTHOR(S):\\n\", \"COMPLETION DATE:\", \"CBI_author\", 27, true, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s):\\n\", \"Completion Date:\", \"CBI_author\", 27, true, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.9.0]
217 "21a: Redact typoed Emails with indicator" "\n when\n Section(searchText.contains(\"@\") || searchText.toLowerCase().contains(\"mail\"))\n then\n section.redactByRegEx(\"mail[:\\\\.\\\\s]{1,2}([\\\\w\\\\/\\\\-\\\\{\\\\(\\\\. ]{3,20 }(@|a|f)\\\\s?[\\\\w\\\\/\\\\-\\\\{\\\\(\\\\. ]{3,20}(\\\\. \\\\w{2,4}\\\\b|\\\\.\\\\B|\\\\.\\\\w{1,4}\\\\b))\",true,1,\"PII\",21,\"Personal information found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.1.2]
218 "0: Combine address parts from ai to CBI_address (department is mandatory)" "\n when\n Section(aiMatchesType(\"DEPARTMENT\"))\n then\n section.combineAiTypes(\"DEPARTMENT\", \"ORG,STREET,POSTAL,COUNTRY,CARDINAL,CITY,STATE\", 20, \"CBI_address\", 3, false);\n end" [AI.1.0]
219 "0: Combine address parts from ai to CBI_address (street is mandatory)" "\n when\n Section(aiMatchesType(\"STREET\"))\n then\n section.combineAiTypes(\"STREET\", \"ORG,DEPARTMENT,POSTAL,COUNTRY,CARDINAL,CITY,STATE\", 20, \"CBI_address\", 3, false);\n end" [AI.1.0]
220 "19b: Add recommendation for PII after Contact Person" "\n when\n Section(searchText.toLowerCase().contains(\"contact person:\"))\n then\n section.recommendLineAfter(\"Contact Person\", \"PII\");\n section.recommendLineAfter(\"Contact person\", \"PII\");\n section.recommendLineAfter(\"contact person\", \"PII\");\n section.recommendLineAfter(\"Contact Person:\", \"PII\");\n section.recommendLineAfter(\"Contact person:\", \"PII\");\n section.recommendLineAfter(\"contact person:\", \"PII\");\n end" [PII.13.0]
221 "0: Combine address parts from ai to CBI_address (org is mandatory)" "\n when\n Section(aiMatchesType(\"ORG\"))\n then\n section.combineAiTypes(\"ORG\", \"DEPARTMENT,STREET,POSTAL,COUNTRY,CARDINAL,CITY,STATE\", 20, \"CBI_address\", 3, false);\n end" [AI.1.0]
222 "25a: Redact phone numbers without indicators" "\n when\n Section(text.contains(\"+\"))\n then\n section.redactByRegEx(\"(\\\\+[\\\\dO]{1,2} )(\\\\([\\\\dO]{1,3}\\\\))?[\\\\d\\\\-O ]{8,15}\",false,0,\"PII\",25,\"Personal information found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.2.2]
223 "34: Dossier" "\n when\n Section(matchesType(\"dossier_redaction\"))\n then\n section.redact(\"dossier_redaction\", 34, \"Dossier redaction found\", \"Article 63(2)(a) of Regulation (EC) No 1107/2009 (making reference to Article 39 of Regulation EC No 178/2002)\");\n end" [ETC.4.0, ETC.4.1, ETC.4.2]
224 "30: Redact AUTHOR(S) (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\")\n && searchText.toUpperCase().contains(\"AUTHOR(S):\")\n && searchText.toUpperCase().contains(\"STUDY COMPLETION DATE:\")\n )\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"STUDY COMPLETION DATE:\", \"CBI_author\", 30, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s):\", \"Study Completion Date:\", \"CBI_author\", 30, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s):\", \"Study completion Date:\", \"CBI_author\", 30, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"AUTHOR(S):\\n\", \"STUDY COMPLETION DATE:\", \"CBI_author\", 30, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s):\\n\", \"Study Completion Date:\", \"CBI_author\", 30, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s):\\n\", \"Study completion Date:\", \"CBI_author\", 30, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.9.1]
225 "30a: Redact AUTHOR(S) (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\")\n && searchText.toUpperCase().contains(\"AUTHOR(S)\")\n && !searchText.toUpperCase().contains(\"AUTHOR(S):\")\n && searchText.toUpperCase().contains(\"STUDY COMPLETION DATE\")\n )\n then\n section.redactLinesBetween(\"AUTHOR(S)\", \"STUDY COMPLETION DATE\", \"CBI_author\", 30, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s)\", \"Study Completion Date\", \"CBI_author\", 30, true, \"Author(s) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s)\", \"Study completion Date\", \"CBI_author\", 30, true, \"Author(s) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"AUTHOR(S)\\n\", \"STUDY COMPLETION DATE\", \"CBI_author\", 30, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s)\\n\", \"Study Completion Date\", \"CBI_author\", 30, true, \"Author(s) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s)\\n\", \"Study completion Date\", \"CBI_author\", 30, true, \"Author(s) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.9.1]
226 "29a: Redact AUTHOR(S) (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\")\n && searchText.toUpperCase().contains(\"AUTHOR(S)\")\n && !searchText.toUpperCase().contains(\"AUTHOR(S):\")\n && searchText.toUpperCase().contains(\"STUDY COMPLETION DATE\")\n )\n then\n section.redactLinesBetween(\"AUTHOR(S)\", \"STUDY COMPLETION DATE\", \"CBI_author\", 29, true, \"AUTHOR(S) was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s)\", \"Study Completion Date\", \"CBI_author\", 29, true, \"Author(s) was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s)\", \"Study completion Date\", \"CBI_author\", 29, true, \"Author(s) was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"AUTHOR(S)\\n\", \"STUDY COMPLETION DATE\", \"CBI_author\", 29, true, \"AUTHOR(S) was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s)\\n\", \"Study Completion Date\", \"CBI_author\", 29, true, \"Author(s) was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s)\\n\", \"Study completion Date\", \"CBI_author\", 29, true, \"Author(s) was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.9.0]
227 "28: Redact AUTHOR(S) (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\")\n && searchText.toUpperCase().contains(\"AUTHOR(S):\")\n && searchText.toUpperCase().contains(\"COMPLETION DATE:\")\n && !searchText.toUpperCase().contains(\"STUDY COMPLETION DATE:\")\n )\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"COMPLETION DATE:\", \"CBI_author\", 28, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s):\", \"Completion Date:\", \"CBI_author\", 28, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"AUTHOR(S):\\n\", \"COMPLETION DATE:\", \"CBI_author\", 28, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n section.redactLinesBetween(\"Author(s):\\n\", \"Completion Date:\", \"CBI_author\", 28, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.9.1]
228 "30b: Redact short Authors section" "\n when\n Section(\n fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\")\n && searchText.toLowerCase().contains(\"author(s)\")\n && searchText.length() < 50\n && sectionNumber <= 20\n && !aiMatchesType(\"CBI_Author\")\n )\n then\n section.redactByRegEx(\"(?<=author\\\\(?s\\\\)?\\\\s\\\\n?)([\\\\p{Lu}\\\\p{L} ]{5,15}(,|\\\\n)?){1,3}\",true,0,\"CBI_author\",30,\"AUTHOR(S) was found\",\"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [CBI.21.1]
229 "26: Redact Phone and Fax by RegEx (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && (\n text.contains(\"Contact\")\n || text.contains(\"Telephone\")\n || text.contains(\"Téléphone\")\n || text.contains(\"Phone\")\n || text.contains(\"Fax\")\n || text.contains(\"Tel\")\n || text.contains(\"Ter\")\n || text.contains(\"Mobile\")\n || text.contains(\"Fel\")\n || text.contains(\"Fer\")\n ))\n then\n section.redactByRegEx(\"\\\\b(contact|t\\\\p{Ll}l\\\\p{Ll}phone|phone|fax|tel|ter|mobile|fel|fer)[a-zA-Z\\\\s]{0,10}[:.\\\\s]{0,3}([\\\\+\\\\d\\\\(O][\\\\s\\\\d\\\\(\\\\)\\\\-\\\\/\\\\.O]{4,100}\\\\d)\\\\b\", true, 2, \"PII\", 26, \"Personal information found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.2.1]
230 "60: Redact Must Impurities" "\n when\n Section((fileAttributeByLabelEqualsIgnoreCase(\"Redact Impurities\",\"Yes\") || fileAttributeByLabelEqualsIgnoreCase(\"Redact Impurities\",\"Y\")) && matchesType(\"impurities\"))\n then\n section.redact(\"impurities\", 60, \"Impurity found\", \"specification_impurity\");\n end" [ETC.9.1]
231 "21: Redact Emails by RegEx (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && searchText.contains(\"@\"))\n then\n section.redactByRegEx(\"\\\\b([A-Za-z0-9._%+\\\\-]+@\\\\s?[A-Za-z0-9.\\\\-]+\\\\.[A-Za-z\\\\-]{1,23}[A-Za-z])\\\\b\", true, 1, \"PII\", 21, \"Personal information found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.2.0]
232 "21a: Redact typoed Emails with indicator" "\n when\n Section(searchText.contains(\"@\") || searchText.toLowerCase().contains(\"mail\"))\n then\n section.redactByRegEx(\"mail[:\\\\.\\\\s]{1,2}([\\\\w\\\\/\\\\-\\\\{\\\\(\\\\. ]{3,20}(@|a|f)\\\\s?[\\\\w\\\\/\\\\-\\\\{\\\\(\\\\. ]{3,20}(\\\\. \\\\w{2,4}\\\\b|\\\\.\\\\B|\\\\.\\\\w{1,4}\\\\b))\",true,1,\"PII\",21,\"Personal information found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.1.2]
233 "29: Redact AUTHOR(S) (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\")\n && searchText.contains(\"AUTHOR(S):\")\n && searchText.contains(\"STUDY COMPLETION DATE:\")\n )\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"STUDY COMPLETION DATE:\", \"CBI_author\", 29, true, \"AUTHOR(S) was found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.9.0]
234 "28: Redact AUTHOR(S) (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\")\n && searchText.contains(\"AUTHOR(S):\")\n && searchText.contains(\"COMPLETION DATE:\")\n && !searchText.contains(\"STUDY COMPLETION DATE:\")\n )\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"COMPLETION DATE:\", \"CBI_author\", 28, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.9.1]
235 "30: Redact AUTHOR(S) (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\")\n && searchText.contains(\"AUTHOR(S):\")\n && searchText.contains(\"STUDY COMPLETION DATE:\")\n )\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"STUDY COMPLETION DATE:\", \"CBI_author\", 30, true, \"AUTHOR(S) was found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [PII.9.1]
236 "27: Redact AUTHOR(S) (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\")\n && searchText.contains(\"AUTHOR(S):\")\n && searchText.contains(\"COMPLETION DATE:\")\n && !searchText.contains(\"STUDY COMPLETION DATE:\")\n )\n then\n section.redactLinesBetween(\"AUTHOR(S):\", \"COMPLETION DATE:\", \"CBI_author\", 27, true, \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [PII.9.0]
237 "34a: Redact dossier_redaction (Non vertebrate study)" "\n when\n Section(!fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesType(\"dossier_redaction\"))\n then\n section.redact(\"dossier_redaction\", 34, \"Dossier dictionary entry found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n end" [ETC.12.0]
238 "34b: Redact dossier_redaction (Vertebrate study)" "\n when\n Section(fileAttributeByLabelEqualsIgnoreCase(\"Vertebrate Study\",\"Yes\") && matchesType(\"dossier_redaction\"))\n then\n section.redact(\"dossier_redaction\", 34, \"Dossier dictionary entry found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n end" [ETC.12.1]

View File

@ -25,9 +25,9 @@ public class RuleFileMigrationTest {
// Put your redaction service drools paths and dossier-templates paths both RM and DM here
static final List<String> ruleFileDirs = List.of(
"/home/kschuettler/iqser/redaction/redaction-service/redaction-service-v1/redaction-service-server-v1/src/test/resources/drools",
"/home/kschuettler/iqser/redaction/dossier-templates-v2",
"/home/kschuettler/iqser/fforesight/dossier-templates-v2");
//"/Users/maverickstuder/Documents/DocuMine/dossier-templates-v2/",
"/Users/maverickstuder/Documents/RedactManager/dossier-templates-v2/");
@Test

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
"package drools\n\nimport com.iqser.red.service.redaction.v1.server.redaction.model.Section\n\nglobal Section section\n\n\n// --- NO RULES HERE --- MANUAL REDACTION ONLY --- //\n"

View File

@ -1 +0,0 @@
"package drools\n\nimport com.iqser.red.service.redaction.v1.server.redaction.model.Section\n\nglobal Section section\n\n\n// --- NO RULES HERE --- MANUAL REDACTION ONLY --- //\n"

View File

@ -1 +0,0 @@
"package drools\n\nimport com.iqser.red.service.redaction.v1.server.redaction.model.Section\n\nglobal Section section\n\n\n// --------------------------------------- CBI rules -------------------------------------------------------------------\n\nrule \"1: Redacted because Section contains Vertebrate\"\n when\n Section(matchesType(\"vertebrate\"))\n then\n section.redact(\"CBI_author\", 1, \"Vertebrate found\", \"names_addresses_persons\");\n section.redact(\"CBI_address\", 1, \"Vertebrate found\", \"names_addresses_persons\");\n end"

View File

@ -1 +0,0 @@
"package drools\n\nimport com.iqser.red.service.redaction.v1.server.redaction.model.Section\n\nglobal Section section\n\n\n// --------------------------------------- CBI rules -------------------------------------------------------------------\n\nrule \"1: Redacted because Section contains Vertebrate\"\n when\n Section(matchesType(\"vertebrate\"))\n then\n section.redact(\"CBI_author\", 1, \"Vertebrate found\", \"names_addresses_persons\");\n section.redact(\"CBI_address\", 1, \"Vertebrate found\", \"names_addresses_persons\");\n end"

File diff suppressed because one or more lines are too long