RED-6369: Rules Refactor
* added id to ImageNode * added Manual Redaction Handling to Rules * minor rename
This commit is contained in:
parent
3e7081a87a
commit
8bbaa4c140
@ -10,7 +10,7 @@ import lombok.NoArgsConstructor;
|
|||||||
@Builder
|
@Builder
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class EntityRecogintionEntity {
|
public class EntityRecognitionEntity {
|
||||||
|
|
||||||
private String value;
|
private String value;
|
||||||
private int startOffset;
|
private int startOffset;
|
||||||
@ -14,6 +14,6 @@ import lombok.NoArgsConstructor;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class NerEntities {
|
public class NerEntities {
|
||||||
|
|
||||||
private Map<Integer, List<EntityRecogintionEntity>> data = new HashMap<>();
|
private Map<Integer, List<EntityRecognitionEntity>> data = new HashMap<>();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -161,9 +161,9 @@ public class EntityNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean matchesResizedAnnotationId(String resizedAnnotationId) {
|
public boolean matchesAnnotationId(String manualRedactionId) {
|
||||||
|
|
||||||
return getRedactionPositionsPerPage().stream().anyMatch(entityPosition -> entityPosition.getId().equals(resizedAnnotationId));
|
return getRedactionPositionsPerPage().stream().anyMatch(entityPosition -> entityPosition.getId().equals(manualRedactionId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import static java.lang.String.format;
|
|||||||
import static java.util.stream.Collectors.groupingBy;
|
import static java.util.stream.Collectors.groupingBy;
|
||||||
import static java.util.stream.Collectors.toList;
|
import static java.util.stream.Collectors.toList;
|
||||||
|
|
||||||
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -37,6 +38,7 @@ import com.iqser.red.service.redaction.v1.server.document.graph.nodes.TableNode;
|
|||||||
import com.iqser.red.service.redaction.v1.server.document.graph.textblock.AtomicTextBlock;
|
import com.iqser.red.service.redaction.v1.server.document.graph.textblock.AtomicTextBlock;
|
||||||
import com.iqser.red.service.redaction.v1.server.parsing.model.TextPositionSequence;
|
import com.iqser.red.service.redaction.v1.server.parsing.model.TextPositionSequence;
|
||||||
import com.iqser.red.service.redaction.v1.server.redaction.model.PdfImage;
|
import com.iqser.red.service.redaction.v1.server.redaction.model.PdfImage;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.redaction.utils.IdBuilder;
|
||||||
import com.iqser.red.service.redaction.v1.server.tableextraction.model.AbstractTextContainer;
|
import com.iqser.red.service.redaction.v1.server.tableextraction.model.AbstractTextContainer;
|
||||||
import com.iqser.red.service.redaction.v1.server.tableextraction.model.Cell;
|
import com.iqser.red.service.redaction.v1.server.tableextraction.model.Cell;
|
||||||
import com.iqser.red.service.redaction.v1.server.tableextraction.model.Table;
|
import com.iqser.red.service.redaction.v1.server.tableextraction.model.Table;
|
||||||
@ -254,10 +256,12 @@ public class DocumentGraphFactory {
|
|||||||
|
|
||||||
private void addImage(SectionNode sectionNode, PdfImage image, Context context) {
|
private void addImage(SectionNode sectionNode, PdfImage image, Context context) {
|
||||||
|
|
||||||
|
Rectangle2D position = RectangleTransformations.toRectangle2D(image.getPosition());
|
||||||
PageNode page = getPage(image.getPage(), context);
|
PageNode page = getPage(image.getPage(), context);
|
||||||
ImageNode imageNode = ImageNode.builder()
|
ImageNode imageNode = ImageNode.builder()
|
||||||
|
.id(IdBuilder.buildId(Set.of(page), List.of(position)))
|
||||||
.imageType(image.getImageType())
|
.imageType(image.getImageType())
|
||||||
.position(RectangleTransformations.toRectangle2D(image.getPosition()))
|
.position(position)
|
||||||
.transparency(image.isHasTransparency())
|
.transparency(image.isHasTransparency())
|
||||||
.page(page)
|
.page(page)
|
||||||
.tableOfContents(context.tableOfContents())
|
.tableOfContents(context.tableOfContents())
|
||||||
|
|||||||
@ -112,6 +112,12 @@ public class RectangleTransformations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Rectangle2D toRectangle2D(com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Rectangle rect) {
|
||||||
|
|
||||||
|
return new Rectangle2D.Double(rect.getTopLeftX() - rect.getWidth(), rect.getTopLeftY() - rect.getHeight(), rect.getWidth(), rect.getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class Rectangle2DUnion implements Collector<Rectangle2D, Area, Rectangle2D> {
|
private static class Rectangle2DUnion implements Collector<Rectangle2D, Area, Rectangle2D> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -30,11 +30,12 @@ import lombok.experimental.FieldDefaults;
|
|||||||
public class ImageNode implements SemanticNode {
|
public class ImageNode implements SemanticNode {
|
||||||
|
|
||||||
List<Integer> tocId;
|
List<Integer> tocId;
|
||||||
|
String id;
|
||||||
|
|
||||||
ImageType imageType;
|
ImageType imageType;
|
||||||
boolean transparency;
|
boolean transparency;
|
||||||
Rectangle2D position;
|
Rectangle2D position;
|
||||||
|
|
||||||
boolean redaction;
|
boolean redaction;
|
||||||
boolean ignored;
|
boolean ignored;
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
|
|||||||
@ -19,6 +19,7 @@ public class PropertiesMapper {
|
|||||||
properties.put("imageType", image.getImageType().toString());
|
properties.put("imageType", image.getImageType().toString());
|
||||||
properties.put("transparency", String.valueOf(image.isTransparency()));
|
properties.put("transparency", String.valueOf(image.isTransparency()));
|
||||||
properties.put("position", RectangleTransformations.toString(image.getPosition()));
|
properties.put("position", RectangleTransformations.toString(image.getPosition()));
|
||||||
|
properties.put("id", image.getId());
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,6 +55,7 @@ public class PropertiesMapper {
|
|||||||
builder.imageType(parseImageType(properties.get("imageType")));
|
builder.imageType(parseImageType(properties.get("imageType")));
|
||||||
builder.transparency(Boolean.parseBoolean(properties.get("transparency")));
|
builder.transparency(Boolean.parseBoolean(properties.get("transparency")));
|
||||||
builder.position(parseRectangle2D(properties.get("position")));
|
builder.position(parseRectangle2D(properties.get("position")));
|
||||||
|
builder.id(properties.get("id"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -73,7 +75,7 @@ public class PropertiesMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static ImageType parseImageType(String imageType) {
|
public static ImageType parseImageType(String imageType) {
|
||||||
|
|
||||||
return switch (imageType) {
|
return switch (imageType) {
|
||||||
case "LOGO" -> ImageType.LOGO;
|
case "LOGO" -> ImageType.LOGO;
|
||||||
|
|||||||
@ -0,0 +1,45 @@
|
|||||||
|
package com.iqser.red.service.redaction.v1.server.document.services;
|
||||||
|
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualResizeRedaction;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.document.graph.entity.EntityNode;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.document.graph.entity.RedactionPosition;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.document.graph.factory.RectangleTransformations;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ManualRedactionApplicationService {
|
||||||
|
|
||||||
|
private final EntityCreationService entityCreationService;
|
||||||
|
|
||||||
|
|
||||||
|
public void resizeEntityAndReinsert(EntityNode entityToBeResized, ManualResizeRedaction manualResizeRedaction) {
|
||||||
|
|
||||||
|
RedactionPosition redactionPositionToBeResized = entityToBeResized.getRedactionPositionsPerPage()
|
||||||
|
.stream()
|
||||||
|
.filter(redactionPosition -> redactionPosition.getId().equals(manualResizeRedaction.getValue()))
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow(() -> new NoSuchElementException("No redaction position with matching annotation id found!"));
|
||||||
|
|
||||||
|
redactionPositionToBeResized.setRectanglePerLine(manualResizeRedaction.getPositions().stream().map(RectangleTransformations::toRectangle2D).toList());
|
||||||
|
|
||||||
|
int newStartOffset;
|
||||||
|
if (manualResizeRedaction.getValue().length() > entityToBeResized.getValue().length()) {
|
||||||
|
newStartOffset = entityToBeResized.getBoundary().start() - manualResizeRedaction.getValue().indexOf(entityToBeResized.getValue());
|
||||||
|
} else {
|
||||||
|
newStartOffset = entityToBeResized.getBoundary().start() + entityToBeResized.getValue().indexOf(manualResizeRedaction.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
entityToBeResized.setResized(true);
|
||||||
|
entityToBeResized.getBoundary().setStart(newStartOffset);
|
||||||
|
entityToBeResized.getBoundary().setEnd(newStartOffset + manualResizeRedaction.getValue().length());
|
||||||
|
entityToBeResized.removeFromGraph();
|
||||||
|
entityCreationService.addEntityToGraph(entityToBeResized, entityToBeResized.getDeepestFullyContainingNode().getTableOfContents());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ package drools
|
|||||||
import static java.lang.String.format;
|
import static java.lang.String.format;
|
||||||
import static com.iqser.red.service.redaction.v1.server.document.services.CharSequenceSearchUtils.anyMatch;
|
import static com.iqser.red.service.redaction.v1.server.document.services.CharSequenceSearchUtils.anyMatch;
|
||||||
import static com.iqser.red.service.redaction.v1.server.document.services.EntityEnrichmentService.setFields;
|
import static com.iqser.red.service.redaction.v1.server.document.services.EntityEnrichmentService.setFields;
|
||||||
|
import static com.iqser.red.service.redaction.v1.server.document.mapper.PropertiesMapper.parseImageType;
|
||||||
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -21,9 +22,15 @@ import com.iqser.red.service.redaction.v1.server.document.services.EntityCreatio
|
|||||||
import com.iqser.red.service.redaction.v1.server.redaction.model.dictionary.Dictionary;
|
import com.iqser.red.service.redaction.v1.server.redaction.model.dictionary.Dictionary;
|
||||||
import com.iqser.red.service.redaction.v1.server.redaction.model.dictionary.DictionaryModel;
|
import com.iqser.red.service.redaction.v1.server.redaction.model.dictionary.DictionaryModel;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualResizeRedaction;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualResizeRedaction;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.IdRemoval;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualForceRedaction;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualImageRecategorization;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.AnnotationStatus;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.document.services.ManualRedactionApplicationService;
|
||||||
|
|
||||||
global DocumentGraph document
|
global DocumentGraph document
|
||||||
global EntityCreationService entityCreationService
|
global EntityCreationService entityCreationService
|
||||||
|
global ManualRedactionApplicationService manualRedactionApplicationService
|
||||||
global Dictionary dictionary
|
global Dictionary dictionary
|
||||||
|
|
||||||
// --------------------------------------- queries -------------------------------------------------------------------
|
// --------------------------------------- queries -------------------------------------------------------------------
|
||||||
@ -32,11 +39,64 @@ query "getFileAttributes"
|
|||||||
$fileAttribute: FileAttribute()
|
$fileAttribute: FileAttribute()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
// --------------------------------------- manual redaction rules -------------------------------------------------------------------
|
||||||
|
|
||||||
|
rule "Apply manual resize redaction"
|
||||||
|
salience 200
|
||||||
|
when
|
||||||
|
$resizeRedactions: ManualResizeRedaction($id: annotationId)
|
||||||
|
$entityToBeResized: EntityNode(matchesAnnotationId($id))
|
||||||
|
then
|
||||||
|
manualRedactionApplicationService.resizeEntityAndReinsert($entityToBeResized, $resizeRedactions);
|
||||||
|
retract($resizeRedactions);
|
||||||
|
update($entityToBeResized);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "Apply id removals that are valid and not in forced redactions to Entity"
|
||||||
|
salience 200
|
||||||
|
when
|
||||||
|
IdRemoval(status == AnnotationStatus.APPROVED, !removeFromDictionary, requestDate != null, $id: annotationId)
|
||||||
|
not ManualForceRedaction($id == annotationId, status == AnnotationStatus.APPROVED, requestDate != null)
|
||||||
|
$entityToBeRemoved: EntityNode(matchesAnnotationId($id))
|
||||||
|
then
|
||||||
|
$entityToBeRemoved.removeFromGraph();
|
||||||
|
retract($entityToBeRemoved);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "Apply id removals that are valid and not in forced redactions to Image"
|
||||||
|
salience 200
|
||||||
|
when
|
||||||
|
IdRemoval(status == AnnotationStatus.APPROVED, !removeFromDictionary, requestDate != null, $id: annotationId)
|
||||||
|
not ManualForceRedaction($id == annotationId, status == AnnotationStatus.APPROVED, requestDate != null)
|
||||||
|
$entityToBeRemoved: ImageNode($id == id)
|
||||||
|
then
|
||||||
|
$entityToBeRemoved.setIgnored(true);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "Apply force redaction"
|
||||||
|
salience 200
|
||||||
|
when
|
||||||
|
ManualForceRedaction($id: annotationId, status == AnnotationStatus.APPROVED, requestDate != null, $legalBasis: legalBasis)
|
||||||
|
$entityToForce: EntityNode(matchesAnnotationId($id))
|
||||||
|
then
|
||||||
|
$entityToForce.setLegalBasis($legalBasis);
|
||||||
|
$entityToForce.setRedaction(true);
|
||||||
|
$entityToForce.setSkipRemoveEntitiesContainedInLarger(true);
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "Apply image recategorization"
|
||||||
|
salience 200
|
||||||
|
when
|
||||||
|
ManualImageRecategorization($id: annotationId, status == AnnotationStatus.APPROVED, $imageType: type)
|
||||||
|
$image: ImageNode($id == id)
|
||||||
|
then
|
||||||
|
$image.setImageType(parseImageType($imageType));
|
||||||
|
end
|
||||||
|
|
||||||
// --------------------------------------- merging rules -------------------------------------------------------------------
|
// --------------------------------------- merging rules -------------------------------------------------------------------
|
||||||
|
|
||||||
rule "merge intersecting Entities of same type"
|
rule "merge intersecting Entities of same type"
|
||||||
salience 100
|
salience 100
|
||||||
|
|
||||||
when
|
when
|
||||||
$first: EntityNode($type: type, $entityType: entityType, !resized, !skipRemoveEntitiesContainedInLarger)
|
$first: EntityNode($type: type, $entityType: entityType, !resized, !skipRemoveEntitiesContainedInLarger)
|
||||||
$second: EntityNode(intersects($first), type == $type, entityType == $entityType, this != $first, !resized, !skipRemoveEntitiesContainedInLarger)
|
$second: EntityNode(intersects($first), type == $type, entityType == $entityType, this != $first, !resized, !skipRemoveEntitiesContainedInLarger)
|
||||||
@ -51,7 +111,6 @@ rule "merge intersecting Entities of same type"
|
|||||||
|
|
||||||
rule "remove Entity of type ENTITY when contained by FALSE_POSITIVE"
|
rule "remove Entity of type ENTITY when contained by FALSE_POSITIVE"
|
||||||
salience 100
|
salience 100
|
||||||
|
|
||||||
when
|
when
|
||||||
$falsePositive: EntityNode($type: type, entityType == EntityType.FALSE_POSITIVE)
|
$falsePositive: EntityNode($type: type, entityType == EntityType.FALSE_POSITIVE)
|
||||||
$entity: EntityNode(containedBy($falsePositive), type == $type, entityType == EntityType.ENTITY, !resized, !skipRemoveEntitiesContainedInLarger)
|
$entity: EntityNode(containedBy($falsePositive), type == $type, entityType == EntityType.ENTITY, !resized, !skipRemoveEntitiesContainedInLarger)
|
||||||
@ -62,7 +121,6 @@ rule "remove Entity of type ENTITY when contained by FALSE_POSITIVE"
|
|||||||
|
|
||||||
rule "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION"
|
rule "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATION"
|
||||||
salience 100
|
salience 100
|
||||||
|
|
||||||
when
|
when
|
||||||
$falseRecommendation: EntityNode($type: type, entityType == EntityType.FALSE_RECOMMENDATION)
|
$falseRecommendation: EntityNode($type: type, entityType == EntityType.FALSE_RECOMMENDATION)
|
||||||
$recommendation: EntityNode(containedBy($falseRecommendation), type == $type, entityType == EntityType.RECOMMENDATION, !resized, !skipRemoveEntitiesContainedInLarger)
|
$recommendation: EntityNode(containedBy($falseRecommendation), type == $type, entityType == EntityType.RECOMMENDATION, !resized, !skipRemoveEntitiesContainedInLarger)
|
||||||
@ -73,7 +131,6 @@ rule "remove Entity of type RECOMMENDATION when contained by FALSE_RECOMMENDATIO
|
|||||||
|
|
||||||
rule "remove Entity of type RECOMMENDATION when contained by ENTITY"
|
rule "remove Entity of type RECOMMENDATION when contained by ENTITY"
|
||||||
salience 100
|
salience 100
|
||||||
|
|
||||||
when
|
when
|
||||||
$entity: EntityNode($type: type, entityType == EntityType.ENTITY)
|
$entity: EntityNode($type: type, entityType == EntityType.ENTITY)
|
||||||
$recommendation: EntityNode(containedBy($entity), type == $type, entityType == EntityType.RECOMMENDATION, !resized, !skipRemoveEntitiesContainedInLarger)
|
$recommendation: EntityNode(containedBy($entity), type == $type, entityType == EntityType.RECOMMENDATION, !resized, !skipRemoveEntitiesContainedInLarger)
|
||||||
@ -84,7 +141,6 @@ rule "remove Entity of type RECOMMENDATION when contained by ENTITY"
|
|||||||
|
|
||||||
rule "remove Entity of lower rank, when equal boundaries and entityType"
|
rule "remove Entity of lower rank, when equal boundaries and entityType"
|
||||||
salience 100
|
salience 100
|
||||||
|
|
||||||
when
|
when
|
||||||
$higherRank: EntityNode($type: type, $entityType: entityType, $boundary: boundary)
|
$higherRank: EntityNode($type: type, $entityType: entityType, $boundary: boundary)
|
||||||
$lowerRank: EntityNode($boundary == boundary, type != $type, entityType == $entityType, dictionary.getDictionaryRank(type) < dictionary.getDictionaryRank($type))
|
$lowerRank: EntityNode($boundary == boundary, type != $type, entityType == $entityType, dictionary.getDictionaryRank(type) < dictionary.getDictionaryRank($type))
|
||||||
@ -98,7 +154,6 @@ rule "remove Entity of lower rank, when equal boundaries and entityType"
|
|||||||
rule "run local dictionary search"
|
rule "run local dictionary search"
|
||||||
agenda-group "LOCAL_DICTIONARY_ADDS"
|
agenda-group "LOCAL_DICTIONARY_ADDS"
|
||||||
salience -999
|
salience -999
|
||||||
|
|
||||||
when
|
when
|
||||||
DictionaryModel(!localEntries.isEmpty(), $type: type, $searchImplementation: localSearch) from dictionary.getDictionaryModels()
|
DictionaryModel(!localEntries.isEmpty(), $type: type, $searchImplementation: localSearch) from dictionary.getDictionaryModels()
|
||||||
then
|
then
|
||||||
@ -107,12 +162,10 @@ rule "run local dictionary search"
|
|||||||
entityNodes.forEach(entityNode -> insert(entityNode));
|
entityNodes.forEach(entityNode -> insert(entityNode));
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------- CBI rules -------------------------------------------------------------------
|
// --------------------------------------- CBI rules -------------------------------------------------------------------
|
||||||
|
|
||||||
rule "1: Redact CBI Authors (Non vertebrate study)"
|
rule "1: Redact CBI Authors (Non vertebrate study)"
|
||||||
no-loop true
|
no-loop true
|
||||||
|
|
||||||
when
|
when
|
||||||
not FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
not FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
||||||
$entity: EntityNode(type == "CBI_author", entityType == EntityType.ENTITY)
|
$entity: EntityNode(type == "CBI_author", entityType == EntityType.ENTITY)
|
||||||
@ -124,7 +177,6 @@ rule "1: Redact CBI Authors (Non vertebrate study)"
|
|||||||
|
|
||||||
rule "2: Redact CBI Authors (Vertebrate study)"
|
rule "2: Redact CBI Authors (Vertebrate study)"
|
||||||
no-loop true
|
no-loop true
|
||||||
|
|
||||||
when
|
when
|
||||||
FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
||||||
$entity: EntityNode(type == "CBI_author", entityType == EntityType.ENTITY)
|
$entity: EntityNode(type == "CBI_author", entityType == EntityType.ENTITY)
|
||||||
@ -136,7 +188,6 @@ rule "2: Redact CBI Authors (Vertebrate study)"
|
|||||||
|
|
||||||
rule "3: Don't redact CBI Address (Non vertebrate study)"
|
rule "3: Don't redact CBI Address (Non vertebrate study)"
|
||||||
no-loop true
|
no-loop true
|
||||||
|
|
||||||
when
|
when
|
||||||
not FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
not FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
||||||
$entity: EntityNode(type == "CBI_address", entityType == EntityType.ENTITY)
|
$entity: EntityNode(type == "CBI_address", entityType == EntityType.ENTITY)
|
||||||
@ -147,7 +198,6 @@ rule "3: Don't redact CBI Address (Non vertebrate study)"
|
|||||||
|
|
||||||
rule "4: Redact CBI Address (Vertebrate study)"
|
rule "4: Redact CBI Address (Vertebrate study)"
|
||||||
no-loop true
|
no-loop true
|
||||||
|
|
||||||
when
|
when
|
||||||
FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
||||||
$entity: EntityNode(type == "CBI_address", entityType == EntityType.ENTITY)
|
$entity: EntityNode(type == "CBI_address", entityType == EntityType.ENTITY)
|
||||||
@ -158,7 +208,6 @@ rule "4: Redact CBI Address (Vertebrate study)"
|
|||||||
end
|
end
|
||||||
|
|
||||||
rule "5: Add FALSE_POSITIVE Entity for genitive CBI_author"
|
rule "5: Add FALSE_POSITIVE Entity for genitive CBI_author"
|
||||||
|
|
||||||
when
|
when
|
||||||
$entity: EntityNode(type == "CBI_author", anyMatch(textAfter, "['’’'ʼˈ´`‘′ʻ’']s"), redaction)
|
$entity: EntityNode(type == "CBI_author", anyMatch(textAfter, "['’’'ʼˈ´`‘′ʻ’']s"), redaction)
|
||||||
then
|
then
|
||||||
@ -167,10 +216,8 @@ rule "5: Add FALSE_POSITIVE Entity for genitive CBI_author"
|
|||||||
insert(falsePositive);
|
insert(falsePositive);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
rule "6: Create Entity from Author(s) cells in Tables with Author(s) header and add Authorname as Recommendation"
|
rule "6: Create Entity from Author(s) cells in Tables with Author(s) header and add Authorname as Recommendation"
|
||||||
agenda-group "LOCAL_DICTIONARY_ADDS"
|
agenda-group "LOCAL_DICTIONARY_ADDS"
|
||||||
|
|
||||||
when
|
when
|
||||||
authorCell: TableCellNode(!header, (hasHeader("Author(s)") || hasHeader("Author")), hasText())
|
authorCell: TableCellNode(!header, (hasHeader("Author(s)") || hasHeader("Author")), hasText())
|
||||||
then
|
then
|
||||||
@ -182,7 +229,6 @@ rule "6: Create Entity from Author(s) cells in Tables with Author(s) header and
|
|||||||
|
|
||||||
rule "7: Add CBI_author with \"et al.\" Regex"
|
rule "7: Add CBI_author with \"et al.\" Regex"
|
||||||
agenda-group "LOCAL_DICTIONARY_ADDS"
|
agenda-group "LOCAL_DICTIONARY_ADDS"
|
||||||
|
|
||||||
when
|
when
|
||||||
$section: SectionNode(containsString("et al."))
|
$section: SectionNode(containsString("et al."))
|
||||||
then
|
then
|
||||||
@ -193,7 +239,6 @@ rule "7: Add CBI_author with \"et al.\" Regex"
|
|||||||
end
|
end
|
||||||
|
|
||||||
rule "8: Add recommendation for Addresses in Test Organism sections"
|
rule "8: Add recommendation for Addresses in Test Organism sections"
|
||||||
|
|
||||||
when
|
when
|
||||||
//FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
//FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
||||||
$section: SectionNode(containsString("Species") && containsString("Source") && !containsString("Species:") && !containsString("Source:"))
|
$section: SectionNode(containsString("Species") && containsString("Source") && !containsString("Species:") && !containsString("Source:"))
|
||||||
@ -203,7 +248,6 @@ rule "8: Add recommendation for Addresses in Test Organism sections"
|
|||||||
entities.forEach(entity -> insert(entity));
|
entities.forEach(entity -> insert(entity));
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
rule "9: Add recommendation for Addresses in Test Animals sections"
|
rule "9: Add recommendation for Addresses in Test Animals sections"
|
||||||
|
|
||||||
when
|
when
|
||||||
@ -216,7 +260,6 @@ rule "9: Add recommendation for Addresses in Test Animals sections"
|
|||||||
end
|
end
|
||||||
|
|
||||||
rule "12: Recommend CTL/BL laboratory that start with BL or CTL"
|
rule "12: Recommend CTL/BL laboratory that start with BL or CTL"
|
||||||
|
|
||||||
when
|
when
|
||||||
$section : SectionNode(containsString("BL") || containsString("CT"))
|
$section : SectionNode(containsString("BL") || containsString("CT"))
|
||||||
then
|
then
|
||||||
@ -226,13 +269,11 @@ rule "12: Recommend CTL/BL laboratory that start with BL or CTL"
|
|||||||
entities.forEach(entity -> dictionary.addLocalDictionaryEntry("PII", entity.getValue(), false));
|
entities.forEach(entity -> dictionary.addLocalDictionaryEntry("PII", entity.getValue(), false));
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------- PII rules -------------------------------------------------------------------
|
// --------------------------------------- PII rules -------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
rule "10: Redacted PII Personal Identification Information (Non vertebrate study)"
|
rule "10: Redacted PII Personal Identification Information (Non vertebrate study)"
|
||||||
no-loop true
|
no-loop true
|
||||||
|
|
||||||
when
|
when
|
||||||
not FileAttribute(label == "Vertebrate Study" , value.toLowerCase() != "yes")
|
not FileAttribute(label == "Vertebrate Study" , value.toLowerCase() != "yes")
|
||||||
$entity: EntityNode(type == "PII", entityType == EntityType.ENTITY)
|
$entity: EntityNode(type == "PII", entityType == EntityType.ENTITY)
|
||||||
@ -242,11 +283,8 @@ rule "10: Redacted PII Personal Identification Information (Non vertebrate study
|
|||||||
update($entity)
|
update($entity)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
rule "11: Redacted PII Personal Identification Information (Vertebrate study)"
|
rule "11: Redacted PII Personal Identification Information (Vertebrate study)"
|
||||||
no-loop true
|
no-loop true
|
||||||
|
|
||||||
when
|
when
|
||||||
FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
||||||
$entity: EntityNode(type == "PII", entityType == EntityType.ENTITY)
|
$entity: EntityNode(type == "PII", entityType == EntityType.ENTITY)
|
||||||
@ -257,7 +295,6 @@ rule "11: Redacted PII Personal Identification Information (Vertebrate study)"
|
|||||||
end
|
end
|
||||||
|
|
||||||
rule "12: Redact Emails by RegEx (Non vertebrate study)"
|
rule "12: Redact Emails by RegEx (Non vertebrate study)"
|
||||||
|
|
||||||
when
|
when
|
||||||
not FileAttribute(label == "Vertebrate Study" , value.toLowerCase() != "yes")
|
not FileAttribute(label == "Vertebrate Study" , value.toLowerCase() != "yes")
|
||||||
$section: SectionNode(containsString("@"))
|
$section: SectionNode(containsString("@"))
|
||||||
@ -268,7 +305,6 @@ rule "12: Redact Emails by RegEx (Non vertebrate study)"
|
|||||||
end
|
end
|
||||||
|
|
||||||
rule "13: Redact Emails by RegEx (Vertebrate study)"
|
rule "13: Redact Emails by RegEx (Vertebrate study)"
|
||||||
|
|
||||||
when
|
when
|
||||||
FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
||||||
$section: SectionNode(containsString("@"))
|
$section: SectionNode(containsString("@"))
|
||||||
@ -278,10 +314,8 @@ rule "13: Redact Emails by RegEx (Vertebrate study)"
|
|||||||
entities.forEach(entity -> insert(entity));
|
entities.forEach(entity -> insert(entity));
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
rule "14: Redact line after contact information (Non vertebrate study)"
|
rule "14: Redact line after contact information (Non vertebrate study)"
|
||||||
agenda-group "LOCAL_DICTIONARY_ADDS"
|
agenda-group "LOCAL_DICTIONARY_ADDS"
|
||||||
|
|
||||||
when
|
when
|
||||||
not FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
not FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
||||||
$string: String() from List.of("Contact point:",
|
$string: String() from List.of("Contact point:",
|
||||||
@ -313,10 +347,8 @@ rule "14: Redact line after contact information (Non vertebrate study)"
|
|||||||
entities.forEach(entity -> dictionary.addLocalDictionaryEntry("PII", entity.getValue(), false));
|
entities.forEach(entity -> dictionary.addLocalDictionaryEntry("PII", entity.getValue(), false));
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
rule "15: Redact line after contact information (Vertebrate study)"
|
rule "15: Redact line after contact information (Vertebrate study)"
|
||||||
agenda-group "LOCAL_DICTIONARY_ADDS"
|
agenda-group "LOCAL_DICTIONARY_ADDS"
|
||||||
|
|
||||||
when
|
when
|
||||||
FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
||||||
$string: String() from List.of("Contact point:",
|
$string: String() from List.of("Contact point:",
|
||||||
@ -346,10 +378,8 @@ rule "15: Redact line after contact information (Vertebrate study)"
|
|||||||
entities.forEach(entity -> dictionary.addLocalDictionaryEntry("PII", entity.getValue(), false));
|
entities.forEach(entity -> dictionary.addLocalDictionaryEntry("PII", entity.getValue(), false));
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
rule "16: redact line between contact keywords"
|
rule "16: redact line between contact keywords"
|
||||||
agenda-group "LOCAL_DICTIONARY_ADDS"
|
agenda-group "LOCAL_DICTIONARY_ADDS"
|
||||||
|
|
||||||
when
|
when
|
||||||
not FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
not FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
||||||
$section: SectionNode((containsString("No:") && containsString("Fax")) || (containsString("Contact:") && containsString("Tel")))
|
$section: SectionNode((containsString("No:") && containsString("Fax")) || (containsString("Contact:") && containsString("Tel")))
|
||||||
@ -364,7 +394,6 @@ rule "16: redact line between contact keywords"
|
|||||||
|
|
||||||
rule "17: redact line between contact keywords"
|
rule "17: redact line between contact keywords"
|
||||||
agenda-group "LOCAL_DICTIONARY_ADDS"
|
agenda-group "LOCAL_DICTIONARY_ADDS"
|
||||||
|
|
||||||
when
|
when
|
||||||
FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
FileAttribute(label == "Vertebrate Study" , value.toLowerCase() == "yes")
|
||||||
$section: SectionNode((containsString("No:") && containsString("Fax")) || (containsString("Contact:") && containsString("Tel")))
|
$section: SectionNode((containsString("No:") && containsString("Fax")) || (containsString("Contact:") && containsString("Tel")))
|
||||||
@ -378,7 +407,6 @@ rule "17: redact line between contact keywords"
|
|||||||
end
|
end
|
||||||
|
|
||||||
rule "18: Redact Phone and Fax by RegEx"
|
rule "18: Redact Phone and Fax by RegEx"
|
||||||
|
|
||||||
when
|
when
|
||||||
$section: SectionNode(containsString("Contact") ||
|
$section: SectionNode(containsString("Contact") ||
|
||||||
containsString("Telephone") ||
|
containsString("Telephone") ||
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user