From f72921813517d00981c7de55648311c27bb8c45a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B8rn-Andre=20Skaar?=
 <31540110+bjornandre@users.noreply.github.com>
Date: Tue, 6 Feb 2024 15:00:44 +0100
Subject: [PATCH] Refactor Mapper and MapFunc (#17)

* Rewrite Mapper interface som that the Mapper can populate values in PseudoFuncOutput. Simplified MapFunc to delegate most of the work to the Mapper.
* Add getAlgorithm method to all PseudoFunc implementations.
---
 pom.xml                                       | 21 ++++--------
 .../ssb/dapla/dlp/pseudo/func/PseudoFunc.java |  3 ++
 .../dlp/pseudo/func/PseudoFuncOutput.java     | 15 +++++++--
 .../dapla/dlp/pseudo/func/fpe/FpeFunc.java    |  7 ++++
 .../dapla/dlp/pseudo/func/map/MapFunc.java    | 32 +++++--------------
 .../ssb/dapla/dlp/pseudo/func/map/Mapper.java |  9 ++++--
 .../dlp/pseudo/func/redact/RedactFunc.java    |  8 +++++
 .../pseudo/func/tink/daead/TinkDaeadFunc.java |  7 ++++
 .../dlp/pseudo/func/tink/fpe/TinkFpeFunc.java |  6 ++++
 9 files changed, 63 insertions(+), 45 deletions(-)

diff --git a/pom.xml b/pom.xml
index ad41c53..8d7d001 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
 
   <groupId>no.ssb.dapla.dlp.pseudo.func</groupId>
   <artifactId>dapla-dlp-pseudo-func</artifactId>
-  <version>1.2.9-SNAPSHOT</version>
+  <version>1.3.0-SNAPSHOT</version>
   <name>dapla-dlp-pseudo-func</name>
 
   <properties>
@@ -186,29 +186,20 @@
 
   <repositories>
     <repository>
-      <id>artifact-registry</id>
-      <url>${artifact-registry.url}</url>
-      <releases>
-        <enabled>true</enabled>
-      </releases>
-      <snapshots>
-        <enabled>false</enabled>
-      </snapshots>
+      <id>central</id>
+      <url>https://repo.maven.apache.org/maven2</url>
     </repository>
     <repository>
-      <id>artifact-registry-snapshot</id>
+      <id>artifact-registry</id>
       <url>${artifact-registry.url}</url>
       <releases>
-        <enabled>false</enabled>
+        <enabled>true</enabled>
+        <updatePolicy>always</updatePolicy>
       </releases>
       <snapshots>
         <enabled>true</enabled>
       </snapshots>
     </repository>
-    <repository>
-      <id>central</id>
-      <url>https://repo.maven.apache.org/maven2</url>
-    </repository>
   </repositories>
 
   <profiles>
diff --git a/src/main/java/no/ssb/dapla/dlp/pseudo/func/PseudoFunc.java b/src/main/java/no/ssb/dapla/dlp/pseudo/func/PseudoFunc.java
index ccc865c..c13a0bf 100644
--- a/src/main/java/no/ssb/dapla/dlp/pseudo/func/PseudoFunc.java
+++ b/src/main/java/no/ssb/dapla/dlp/pseudo/func/PseudoFunc.java
@@ -5,6 +5,9 @@ public interface PseudoFunc {
     /** Name of the function declaration (including any parameters), e.g. foo(param1,param2) */
     String getFuncDecl();
 
+    /** Name of the encryption algorithm, e.g. TINK_FPE, TINK-DAEAD */
+    String getAlgorithm();
+
     /**
      * Preprocessing of input. This will be called before apply
      */
diff --git a/src/main/java/no/ssb/dapla/dlp/pseudo/func/PseudoFuncOutput.java b/src/main/java/no/ssb/dapla/dlp/pseudo/func/PseudoFuncOutput.java
index 4b229e9..0ae3596 100644
--- a/src/main/java/no/ssb/dapla/dlp/pseudo/func/PseudoFuncOutput.java
+++ b/src/main/java/no/ssb/dapla/dlp/pseudo/func/PseudoFuncOutput.java
@@ -6,14 +6,18 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 @Value
 @NoArgsConstructor
 public class PseudoFuncOutput {
-    private List<Object> values = new ArrayList<>();
-    private List<String> warnings = new ArrayList<>();
+    List<Object> values = new ArrayList<>();
+    List<String> warnings = new ArrayList<>();
+    Map<String, String> metadata = new HashMap<>();
+
 
     public PseudoFuncOutput(Object v) {
         if (v instanceof Collection) {
@@ -39,6 +43,10 @@ public void addWarning(String warning) {
         warnings.add(warning);
     }
 
+    public void addMetadata(String key, String value) {
+        metadata.put(key, value);
+    }
+
     public List<String> getStringValues() {
         return values.stream()
           .map(String::valueOf)
@@ -46,7 +54,7 @@ public List<String> getStringValues() {
     }
 
     public Object getFirstValue() {
-        return getValues().get(0);
+        return getValues().getFirst();
     }
 
     @Override
@@ -57,4 +65,5 @@ public String toString() {
     public boolean hasWarnings() {
         return ! warnings.isEmpty();
     }
+
 }
diff --git a/src/main/java/no/ssb/dapla/dlp/pseudo/func/fpe/FpeFunc.java b/src/main/java/no/ssb/dapla/dlp/pseudo/func/fpe/FpeFunc.java
index 1014d91..d0f298c 100644
--- a/src/main/java/no/ssb/dapla/dlp/pseudo/func/fpe/FpeFunc.java
+++ b/src/main/java/no/ssb/dapla/dlp/pseudo/func/fpe/FpeFunc.java
@@ -14,10 +14,17 @@ public class FpeFunc extends AbstractPseudoFunc {
     private final FormatPreservingEncryption fpe;
     private final FpeConfigService fpeConfigService = new FpeConfigService();
 
+    private static final String ALGORITHM = "FPE";
+
     // We should consider implementing a more sophisticated tweak, see:
     // https://crypto.stackexchange.com/questions/10903/what-are-the-uses-of-tweaks-in-block-ciphers
     private static final byte[] STATIC_TWEAK = new byte[0];
 
+    @Override
+    public String getAlgorithm() {
+        return ALGORITHM;
+    }
+
     public FpeFunc(PseudoFuncConfig genericConfig) {
         super(genericConfig.getFuncDecl());
         config = fpeConfigService.resolve(genericConfig);
diff --git a/src/main/java/no/ssb/dapla/dlp/pseudo/func/map/MapFunc.java b/src/main/java/no/ssb/dapla/dlp/pseudo/func/map/MapFunc.java
index c0ea4d1..888d5c7 100644
--- a/src/main/java/no/ssb/dapla/dlp/pseudo/func/map/MapFunc.java
+++ b/src/main/java/no/ssb/dapla/dlp/pseudo/func/map/MapFunc.java
@@ -10,13 +10,15 @@
 
 @Slf4j
 public class MapFunc extends AbstractPseudoFunc {
-    private final MapFuncConfig config;
-    private final MapFuncConfigService mapFuncConfigService = new MapFuncConfigService();
     private final Mapper mapper;
 
+    @Override
+    public String getAlgorithm() {
+        return null;
+    }
+
     public MapFunc(PseudoFuncConfig genericConfig) {
         super(genericConfig.getFuncDecl());
-        this.config = mapFuncConfigService.resolve(genericConfig);
         this.mapper = loadMapper();
         this.mapper.setConfig(genericConfig.asMap());
     }
@@ -31,35 +33,17 @@ public static Mapper loadMapper() {
 
     @Override
     public void init(PseudoFuncInput input) {
-        for (Object inputValue : input.getValues()) {
-            mapper.init(String.valueOf(inputValue));
-        }
+        mapper.init(input);
     }
 
     @Override
     public PseudoFuncOutput apply(PseudoFuncInput input) {
-        PseudoFuncOutput output = new PseudoFuncOutput();
-
-        for (Object inputValue : input.getValues()) {
-            String plain = String.valueOf(inputValue);
-            final Object pseudonymized = mapper.map(plain);
-            output.add(pseudonymized);
-        }
-
-        return output;
+        return mapper.map(input);
     }
 
     @Override
     public PseudoFuncOutput restore(PseudoFuncInput input) {
-        PseudoFuncOutput output = new PseudoFuncOutput();
-
-        for (Object inputValue : input.getValues()) {
-            String mapped = String.valueOf(inputValue);
-            final Object clear = mapper.restore(mapped);
-            output.add(clear);
-        }
-
-        return output;
+        return mapper.restore(input);
     }
 
 }
diff --git a/src/main/java/no/ssb/dapla/dlp/pseudo/func/map/Mapper.java b/src/main/java/no/ssb/dapla/dlp/pseudo/func/map/Mapper.java
index 360fc30..f3169ea 100644
--- a/src/main/java/no/ssb/dapla/dlp/pseudo/func/map/Mapper.java
+++ b/src/main/java/no/ssb/dapla/dlp/pseudo/func/map/Mapper.java
@@ -1,13 +1,16 @@
 package no.ssb.dapla.dlp.pseudo.func.map;
 
+import no.ssb.dapla.dlp.pseudo.func.PseudoFuncInput;
+import no.ssb.dapla.dlp.pseudo.func.PseudoFuncOutput;
+
 import java.util.Map;
 
 public interface Mapper {
 
-    void init(Object data);
+    void init(PseudoFuncInput data);
     void setConfig(Map<String, Object> config);
-    Object map(Object data);
+    PseudoFuncOutput map(PseudoFuncInput data);
 
-    Object restore(Object mapped);
+    PseudoFuncOutput restore(PseudoFuncInput mapped);
 
 }
diff --git a/src/main/java/no/ssb/dapla/dlp/pseudo/func/redact/RedactFunc.java b/src/main/java/no/ssb/dapla/dlp/pseudo/func/redact/RedactFunc.java
index 02450f6..e361fe7 100644
--- a/src/main/java/no/ssb/dapla/dlp/pseudo/func/redact/RedactFunc.java
+++ b/src/main/java/no/ssb/dapla/dlp/pseudo/func/redact/RedactFunc.java
@@ -16,6 +16,14 @@ public class RedactFunc extends AbstractPseudoFunc {
     private final RedactFuncConfigService configService = new RedactFuncConfigService();
     private final RedactFuncConfig config;
 
+    // A.k.a Free Text Redaction
+    private static final String ALGORITHM = "REDACT";
+
+    @Override
+    public String getAlgorithm() {
+        return ALGORITHM;
+    }
+
     public RedactFunc(@NonNull PseudoFuncConfig genericConfig) {
         super(genericConfig.getFuncDecl());
         this.config = configService.resolve(genericConfig);
diff --git a/src/main/java/no/ssb/dapla/dlp/pseudo/func/tink/daead/TinkDaeadFunc.java b/src/main/java/no/ssb/dapla/dlp/pseudo/func/tink/daead/TinkDaeadFunc.java
index 4158a22..7b23c98 100644
--- a/src/main/java/no/ssb/dapla/dlp/pseudo/func/tink/daead/TinkDaeadFunc.java
+++ b/src/main/java/no/ssb/dapla/dlp/pseudo/func/tink/daead/TinkDaeadFunc.java
@@ -17,6 +17,13 @@ public class TinkDaeadFunc extends AbstractPseudoFunc {
     private final TinkDaeadFuncConfigService configService = new TinkDaeadFuncConfigService();
     private final TinkDaeadFuncConfig config;
 
+    private static final String ALGORITHM = "TINK-DAEAD";
+
+    @Override
+    public String getAlgorithm() {
+        return ALGORITHM;
+    }
+
     public TinkDaeadFunc(@NonNull PseudoFuncConfig genericConfig) {
         super(genericConfig.getFuncDecl());
         this.config = configService.resolve(genericConfig);
diff --git a/src/main/java/no/ssb/dapla/dlp/pseudo/func/tink/fpe/TinkFpeFunc.java b/src/main/java/no/ssb/dapla/dlp/pseudo/func/tink/fpe/TinkFpeFunc.java
index ae9b983..b3ef858 100644
--- a/src/main/java/no/ssb/dapla/dlp/pseudo/func/tink/fpe/TinkFpeFunc.java
+++ b/src/main/java/no/ssb/dapla/dlp/pseudo/func/tink/fpe/TinkFpeFunc.java
@@ -15,6 +15,12 @@ public class TinkFpeFunc extends AbstractPseudoFunc {
     private final TinkFpeFuncConfigService configService = new TinkFpeFuncConfigService();
     private final TinkFpeFuncConfig config;
 
+    private static final String ALGORITHM = "TINK-FPE";
+    @Override
+    public String getAlgorithm() {
+        return ALGORITHM;
+    }
+
     public TinkFpeFunc(@NonNull PseudoFuncConfig genericConfig) {
         super(genericConfig.getFuncDecl());
         this.config = configService.resolve(genericConfig);