From 176b3c3d9952847359bbb705e85352dcf79349f2 Mon Sep 17 00:00:00 2001
From: Reiner Jung <reiner.jung@email.uni-kiel.de>
Date: Fri, 7 Jul 2023 14:48:49 +0200
Subject: [PATCH] Improved code for CSV serialization and deserialization.

---
 .../code/stages/data/DataflowEntry.java       | 31 ++++++++
 .../code/stages/data/FileOperationEntry.java  | 40 ++++++++++
 .../code/stages/data/GlobalDataEntry.java     | 42 ++++++++++
 .../code/stages/data/NotFoundEntry.java       | 42 ++++++++++
 .../data/CommonBlockArgumentDataflow.java     | 33 ++++++++
 .../tools/maa/stages/ComponentStatistics.java | 33 ++++++++
 .../maa/stages/ProvidedInterfaceEntry.java    | 33 ++++++++
 .../metrics/ModuleNodeCountCouplingEntry.java | 45 +++++++++++
 .../stages/metrics/NumberOfCallsEntry.java    | 78 +++++++++++++++++--
 .../metrics/OperationNodeCountEntry.java      | 70 ++++++++++++++++-
 .../stages/ModelEditDistanceEntry.java        | 27 +++++++
 .../tools/sar/StorageOperationDataflow.java   | 30 +++++++
 12 files changed, 495 insertions(+), 9 deletions(-)

diff --git a/analysis/src/main/java/org/oceandsl/analysis/code/stages/data/DataflowEntry.java b/analysis/src/main/java/org/oceandsl/analysis/code/stages/data/DataflowEntry.java
index fbbd14da..2de67394 100644
--- a/analysis/src/main/java/org/oceandsl/analysis/code/stages/data/DataflowEntry.java
+++ b/analysis/src/main/java/org/oceandsl/analysis/code/stages/data/DataflowEntry.java
@@ -114,4 +114,35 @@ public class DataflowEntry {
         this.direction = direction;
     }
 
+    @Override
+    public boolean equals(final Object object) {
+        if (object instanceof DataflowEntry) {
+            final DataflowEntry other = (DataflowEntry) object;
+            return this.checkString(this.sourcePath, other.getSourcePath())
+                    && this.checkString(this.sourceModule, other.getSourceModule())
+                    && this.checkString(this.sourceOperation, other.getSourceOperation())
+                    && this.checkString(this.targetPath, other.getTargetPath())
+                    && this.checkString(this.targetModule, other.getTargetModule())
+                    && this.checkString(this.targetOperation, other.getTargetOperation());
+        } else {
+            return false;
+        }
+    }
+
+    private boolean checkString(final String left, final String right) {
+        if (left == null && right == null) {
+            return true;
+        } else if (left != null && right != null) {
+            return left.equals(right);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return this.sourcePath.hashCode() ^ this.sourceModule.hashCode() ^ this.sourceOperation.hashCode()
+                ^ this.targetPath.hashCode() ^ this.targetModule.hashCode() ^ this.targetOperation.hashCode();
+    }
+
 }
diff --git a/analysis/src/main/java/org/oceandsl/analysis/code/stages/data/FileOperationEntry.java b/analysis/src/main/java/org/oceandsl/analysis/code/stages/data/FileOperationEntry.java
index 792c904a..c250c3b4 100644
--- a/analysis/src/main/java/org/oceandsl/analysis/code/stages/data/FileOperationEntry.java
+++ b/analysis/src/main/java/org/oceandsl/analysis/code/stages/data/FileOperationEntry.java
@@ -1,3 +1,18 @@
+/***************************************************************************
+ * Copyright (C) 2023 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
 package org.oceandsl.analysis.code.stages.data;
 
 import org.csveed.annotations.CsvCell;
@@ -34,4 +49,29 @@ public class FileOperationEntry {
         this.name = name;
     }
 
+    @Override
+    public boolean equals(final Object object) {
+        if (object instanceof FileOperationEntry) {
+            final FileOperationEntry other = (FileOperationEntry) object;
+            return this.checkString(this.name, other.getName()) && this.checkString(this.path, other.getPath());
+        } else {
+            return false;
+        }
+    }
+
+    private boolean checkString(final String left, final String right) {
+        if (left == null && right == null) {
+            return true;
+        } else if (left != null && right != null) {
+            return left.equals(right);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return this.name.hashCode() ^ this.path.hashCode();
+    }
+
 }
diff --git a/analysis/src/main/java/org/oceandsl/analysis/code/stages/data/GlobalDataEntry.java b/analysis/src/main/java/org/oceandsl/analysis/code/stages/data/GlobalDataEntry.java
index 70b85b77..532416ad 100644
--- a/analysis/src/main/java/org/oceandsl/analysis/code/stages/data/GlobalDataEntry.java
+++ b/analysis/src/main/java/org/oceandsl/analysis/code/stages/data/GlobalDataEntry.java
@@ -1,3 +1,18 @@
+/***************************************************************************
+ * Copyright (C) 2023 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
 package org.oceandsl.analysis.code.stages.data;
 
 import org.csveed.annotations.CsvCell;
@@ -59,4 +74,31 @@ public class GlobalDataEntry {
         this.variables = variables;
     }
 
+    @Override
+    public boolean equals(final Object object) {
+        if (object instanceof GlobalDataEntry) {
+            final GlobalDataEntry other = (GlobalDataEntry) object;
+            return this.checkString(this.files, other.getFiles()) && this.checkString(this.modules, other.getModules())
+                    && this.checkString(this.name, other.getName())
+                    && this.checkString(this.variables, other.getVariables());
+        } else {
+            return false;
+        }
+    }
+
+    private boolean checkString(final String left, final String right) {
+        if (left == null && right == null) {
+            return true;
+        } else if (left != null && right != null) {
+            return left.equals(right);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return this.name.hashCode() ^ this.files.hashCode() ^ this.modules.hashCode() ^ this.variables.hashCode();
+    }
+
 }
diff --git a/analysis/src/main/java/org/oceandsl/analysis/code/stages/data/NotFoundEntry.java b/analysis/src/main/java/org/oceandsl/analysis/code/stages/data/NotFoundEntry.java
index 2f63c075..79c6df96 100644
--- a/analysis/src/main/java/org/oceandsl/analysis/code/stages/data/NotFoundEntry.java
+++ b/analysis/src/main/java/org/oceandsl/analysis/code/stages/data/NotFoundEntry.java
@@ -1,3 +1,18 @@
+/***************************************************************************
+ * Copyright (C) 2023 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
 package org.oceandsl.analysis.code.stages.data;
 
 import org.csveed.annotations.CsvCell;
@@ -56,4 +71,31 @@ public class NotFoundEntry {
         this.call = call;
     }
 
+    @Override
+    public boolean equals(final Object object) {
+        if (object instanceof NotFoundEntry) {
+            final NotFoundEntry other = (NotFoundEntry) object;
+            return this.checkString(this.call, other.getCall()) && this.checkString(this.fileName, other.getFileName())
+                    && this.checkString(this.moduleName, other.getModuleName())
+                    && this.checkString(this.operation, other.getOperation());
+        } else {
+            return false;
+        }
+    }
+
+    private boolean checkString(final String left, final String right) {
+        if (left == null && right == null) {
+            return true;
+        } else if (left != null && right != null) {
+            return left.equals(right);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return this.call.hashCode() ^ this.fileName.hashCode() ^ this.moduleName.hashCode() ^ this.operation.hashCode();
+    }
+
 }
diff --git a/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/dataflow/data/CommonBlockArgumentDataflow.java b/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/dataflow/data/CommonBlockArgumentDataflow.java
index 1d5a6ad6..82f90075 100644
--- a/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/dataflow/data/CommonBlockArgumentDataflow.java
+++ b/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/dataflow/data/CommonBlockArgumentDataflow.java
@@ -41,6 +41,10 @@ public class CommonBlockArgumentDataflow implements IDataflowEntry {
     @CsvCell(columnIndex = 5, columnName = "direction")
     private EDirection direction;
 
+    public CommonBlockArgumentDataflow() {
+        // dummy constructor for csveed
+    }
+
     public CommonBlockArgumentDataflow(final String commonBlockName, final String fileName, final String moduleName,
             final String operationName, final EDirection direction) {
         this.commonBlockName = commonBlockName;
@@ -90,4 +94,33 @@ public class CommonBlockArgumentDataflow implements IDataflowEntry {
         this.direction = direction;
     }
 
+    @Override
+    public boolean equals(final Object object) {
+        if (object instanceof CommonBlockArgumentDataflow) {
+            final CommonBlockArgumentDataflow other = (CommonBlockArgumentDataflow) object;
+            return this.checkString(this.commonBlockName, other.getCommonBlockName())
+                    && this.checkString(this.fileName, other.getFileName())
+                    && this.checkString(this.moduleName, other.getModuleName())
+                    && this.checkString(this.operationName, other.getOperationName())
+                    && this.direction.equals(other.getDirection());
+        } else {
+            return false;
+        }
+    }
+
+    private boolean checkString(final String left, final String right) {
+        if (left == null && right == null) {
+            return true;
+        } else if (left != null && right != null) {
+            return left.equals(right);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return this.commonBlockName.hashCode() ^ this.direction.hashCode() ^ this.fileName.hashCode()
+                ^ this.moduleName.hashCode() ^ this.operationName.hashCode();
+    }
 }
diff --git a/tools/maa/src/main/java/org/oceandsl/tools/maa/stages/ComponentStatistics.java b/tools/maa/src/main/java/org/oceandsl/tools/maa/stages/ComponentStatistics.java
index 14a976dd..1fdbeb1d 100644
--- a/tools/maa/src/main/java/org/oceandsl/tools/maa/stages/ComponentStatistics.java
+++ b/tools/maa/src/main/java/org/oceandsl/tools/maa/stages/ComponentStatistics.java
@@ -34,6 +34,10 @@ public class ComponentStatistics {
     @CsvCell(columnIndex = 4, columnName = "requires-operations")
     private long requiredOperations;
 
+    public ComponentStatistics() {
+        // dummy for csveed
+    }
+
     public ComponentStatistics(final String componentName, final int operations, final long providedOperations,
             final long requiredOperations) {
         this.componentName = componentName;
@@ -74,4 +78,33 @@ public class ComponentStatistics {
         this.requiredOperations = requiredOperations;
     }
 
+    @Override
+    public boolean equals(final Object object) {
+        if (object instanceof ComponentStatistics) {
+            final ComponentStatistics other = (ComponentStatistics) object;
+            return this.checkString(this.componentName, other.getComponentName())
+                    && this.operations == other.getOperations()
+                    && this.providedOperations == other.getProvidedOperations()
+                    && this.requiredOperations == other.getRequiredOperations();
+        } else {
+            return false;
+        }
+    }
+
+    private boolean checkString(final String left, final String right) {
+        if (left == null && right == null) {
+            return true;
+        } else if (left != null && right != null) {
+            return left.equals(right);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return this.componentName.hashCode() ^ Long.hashCode(this.operations) ^ Long.hashCode(this.providedOperations)
+                ^ Long.hashCode(this.requiredOperations);
+    }
+
 }
diff --git a/tools/maa/src/main/java/org/oceandsl/tools/maa/stages/ProvidedInterfaceEntry.java b/tools/maa/src/main/java/org/oceandsl/tools/maa/stages/ProvidedInterfaceEntry.java
index 112f0522..d90921d1 100644
--- a/tools/maa/src/main/java/org/oceandsl/tools/maa/stages/ProvidedInterfaceEntry.java
+++ b/tools/maa/src/main/java/org/oceandsl/tools/maa/stages/ProvidedInterfaceEntry.java
@@ -28,6 +28,10 @@ public class ProvidedInterfaceEntry {
     @CsvCell(columnIndex = 4, columnName = "caller-component-types")
     private String callerComponentTypes;
 
+    public ProvidedInterfaceEntry() {
+        // dummy for csveed
+    }
+
     public ProvidedInterfaceEntry(final String componentType, final String providedInterface, final String operation,
             final String callerComponentTypes) {
         this.componentType = componentType;
@@ -67,4 +71,33 @@ public class ProvidedInterfaceEntry {
     public void setCallerComponentTypes(final String callerComponentTypes) {
         this.callerComponentTypes = callerComponentTypes;
     }
+
+    @Override
+    public boolean equals(final Object object) {
+        if (object instanceof ProvidedInterfaceEntry) {
+            final ProvidedInterfaceEntry other = (ProvidedInterfaceEntry) object;
+            return this.checkString(this.callerComponentTypes, other.getCallerComponentTypes())
+                    && this.checkString(this.componentType, other.getComponentType())
+                    && this.checkString(this.operation, other.getOperation())
+                    && this.checkString(this.providedInterface, other.getProvidedInterface());
+        } else {
+            return false;
+        }
+    }
+
+    private boolean checkString(final String left, final String right) {
+        if (left == null && right == null) {
+            return true;
+        } else if (left != null && right != null) {
+            return left.equals(right);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return this.callerComponentTypes.hashCode() ^ this.componentType.hashCode() ^ this.operation.hashCode()
+                ^ this.providedInterface.hashCode();
+    }
 }
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/metrics/ModuleNodeCountCouplingEntry.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/metrics/ModuleNodeCountCouplingEntry.java
index 3bd54dfd..8ec761f8 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/metrics/ModuleNodeCountCouplingEntry.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/metrics/ModuleNodeCountCouplingEntry.java
@@ -1,3 +1,18 @@
+/***************************************************************************
+ * Copyright (C) 2023 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
 package org.oceandsl.tools.mvis.stages.metrics;
 
 import org.csveed.annotations.CsvCell;
@@ -11,6 +26,10 @@ public class ModuleNodeCountCouplingEntry {
     @CsvCell(columnIndex = 3, columnName = "out-edges")
     private int outEdges;
 
+    public ModuleNodeCountCouplingEntry() {
+        // dummy for csveed
+    }
+
     public ModuleNodeCountCouplingEntry(final String module, final int inEdges, final int outEdges) {
         this.module = module;
         this.inEdges = inEdges;
@@ -41,4 +60,30 @@ public class ModuleNodeCountCouplingEntry {
         this.outEdges = outEdges;
     }
 
+    @Override
+    public boolean equals(final Object object) {
+        if (object instanceof ModuleNodeCountCouplingEntry) {
+            final ModuleNodeCountCouplingEntry other = (ModuleNodeCountCouplingEntry) object;
+            return this.checkString(this.module, other.getModule()) && this.inEdges == other.getInEdges()
+                    && this.outEdges == other.getOutEdges();
+        } else {
+            return false;
+        }
+    }
+
+    private boolean checkString(final String left, final String right) {
+        if (left == null && right == null) {
+            return true;
+        } else if (left != null && right != null) {
+            return left.equals(right);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return this.module.hashCode() ^ Long.hashCode(this.inEdges) ^ Long.hashCode(this.outEdges);
+    }
+
 }
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/metrics/NumberOfCallsEntry.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/metrics/NumberOfCallsEntry.java
index 6d882e5f..2fde26f5 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/metrics/NumberOfCallsEntry.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/metrics/NumberOfCallsEntry.java
@@ -1,3 +1,18 @@
+/***************************************************************************
+ * Copyright (C) 2023 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
 package org.oceandsl.tools.mvis.stages.metrics;
 
 import org.csveed.annotations.CsvCell;
@@ -5,15 +20,19 @@ import org.csveed.annotations.CsvCell;
 public class NumberOfCallsEntry {
 
     @CsvCell(columnIndex = 1, columnName = "source-path")
-    private final String sourceFile;
+    private String sourceFile;
     @CsvCell(columnIndex = 2, columnName = "source-operation")
-    private final String sourceFunction;
+    private String sourceFunction;
     @CsvCell(columnIndex = 3, columnName = "target-path")
-    private final String targetFile;
+    private String targetFile;
     @CsvCell(columnIndex = 4, columnName = "target-operation")
-    private final String targetFunction;
+    private String targetFunction;
     @CsvCell(columnIndex = 5, columnName = "calls")
-    private final long calls;
+    private long calls;
+
+    public NumberOfCallsEntry() {
+        // dummy constructor for csveed
+    }
 
     public NumberOfCallsEntry(final String sourceFile, final String sourceFunction, final String targetFile,
             final String targetFunction, final long calls) {
@@ -28,20 +47,69 @@ public class NumberOfCallsEntry {
         return this.sourceFile;
     }
 
+    public void setSourceFile(final String sourceFile) {
+        this.sourceFile = sourceFile;
+    }
+
     public String getSourceFunction() {
         return this.sourceFunction;
     }
 
+    public void setSourceFunction(final String sourceFunction) {
+        this.sourceFunction = sourceFunction;
+    }
+
     public String getTargetFile() {
         return this.targetFile;
     }
 
+    public void setTargetFile(final String targetFile) {
+        this.targetFile = targetFile;
+    }
+
     public String getTargetFunction() {
         return this.targetFunction;
     }
 
+    public void setTargetFunction(final String targetFunction) {
+        this.targetFunction = targetFunction;
+    }
+
     public long getCalls() {
         return this.calls;
     }
 
+    public void setCalls(final long calls) {
+        this.calls = calls;
+    }
+
+    @Override
+    public boolean equals(final Object object) {
+        if (object instanceof NumberOfCallsEntry) {
+            final NumberOfCallsEntry other = (NumberOfCallsEntry) object;
+            return this.checkString(this.sourceFile, other.getSourceFile())
+                    && this.checkString(this.sourceFunction, other.getSourceFunction())
+                    && this.checkString(this.targetFile, other.getTargetFile())
+                    && this.checkString(this.targetFunction, other.getTargetFunction())
+                    && this.calls == other.getCalls();
+        } else {
+            return false;
+        }
+    }
+
+    private boolean checkString(final String left, final String right) {
+        if (left == null && right == null) {
+            return true;
+        } else if (left != null && right != null) {
+            return left.equals(right);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return this.sourceFile.hashCode() ^ this.sourceFunction.hashCode() ^ this.targetFile.hashCode()
+                ^ this.targetFunction.hashCode() ^ Long.hashCode(this.calls);
+    }
 }
diff --git a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/metrics/OperationNodeCountEntry.java b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/metrics/OperationNodeCountEntry.java
index c815eb10..6e604ed2 100644
--- a/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/metrics/OperationNodeCountEntry.java
+++ b/tools/mvis/src/main/java/org/oceandsl/tools/mvis/stages/metrics/OperationNodeCountEntry.java
@@ -1,3 +1,18 @@
+/***************************************************************************
+ * Copyright (C) 2023 OceanDSL (https://oceandsl.uni-kiel.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
 package org.oceandsl.tools.mvis.stages.metrics;
 
 import org.csveed.annotations.CsvCell;
@@ -5,13 +20,17 @@ import org.csveed.annotations.CsvCell;
 public class OperationNodeCountEntry {
 
     @CsvCell(columnIndex = 1, columnName = "module")
-    private final String module;
+    private String module;
     @CsvCell(columnIndex = 2, columnName = "operation")
-    private final String operation;
+    private String operation;
     @CsvCell(columnIndex = 3, columnName = "in-edges")
-    private final int inEdges;
+    private int inEdges;
     @CsvCell(columnIndex = 4, columnName = "out-edges")
-    private final int outEdges;
+    private int outEdges;
+
+    public OperationNodeCountEntry() {
+        // dummy constructor for csveed
+    }
 
     public OperationNodeCountEntry(final String module, final String operation, final int inEdges, final int outEdges) {
         this.module = module;
@@ -24,16 +43,59 @@ public class OperationNodeCountEntry {
         return this.module;
     }
 
+    public void setModule(final String module) {
+        this.module = module;
+    }
+
     public String getOperation() {
         return this.operation;
     }
 
+    public void setOperation(final String operation) {
+        this.operation = operation;
+    }
+
     public int getInEdges() {
         return this.inEdges;
     }
 
+    public void setInEdges(final int inEdges) {
+        this.inEdges = inEdges;
+    }
+
     public int getOutEdges() {
         return this.outEdges;
     }
 
+    public void setOutEdges(final int outEdges) {
+        this.outEdges = outEdges;
+    }
+
+    @Override
+    public boolean equals(final Object object) {
+        if (object instanceof OperationNodeCountEntry) {
+            final OperationNodeCountEntry other = (OperationNodeCountEntry) object;
+            return this.checkString(this.module, other.getModule())
+                    && this.checkString(this.operation, other.getOperation()) && this.inEdges == other.getInEdges()
+                    && this.outEdges == other.getOutEdges();
+        } else {
+            return false;
+        }
+    }
+
+    private boolean checkString(final String left, final String right) {
+        if (left == null && right == null) {
+            return true;
+        } else if (left != null && right != null) {
+            return left.equals(right);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return this.module.hashCode() ^ this.operation.hashCode() ^ Integer.hashCode(this.inEdges)
+                ^ Integer.hashCode(this.outEdges);
+    }
 }
diff --git a/tools/restructuring/src/main/java/org/oceandsl/tools/restructuring/stages/ModelEditDistanceEntry.java b/tools/restructuring/src/main/java/org/oceandsl/tools/restructuring/stages/ModelEditDistanceEntry.java
index bdbdb69c..5eefca08 100644
--- a/tools/restructuring/src/main/java/org/oceandsl/tools/restructuring/stages/ModelEditDistanceEntry.java
+++ b/tools/restructuring/src/main/java/org/oceandsl/tools/restructuring/stages/ModelEditDistanceEntry.java
@@ -41,4 +41,31 @@ public class ModelEditDistanceEntry {
         this.numberOfSteps = numberOfSteps;
     }
 
+    @Override
+    public boolean equals(final Object object) {
+        if (object instanceof ModelEditDistanceEntry) {
+            final ModelEditDistanceEntry other = (ModelEditDistanceEntry) object;
+            return this.checkString(this.goalModelName, other.getGoalModelName())
+                    && this.checkString(this.originalModelName, other.getOriginalModelName())
+                    && this.numberOfSteps == other.getNumberOfSteps();
+        } else {
+            return false;
+        }
+    }
+
+    private boolean checkString(final String left, final String right) {
+        if (left == null && right == null) {
+            return true;
+        } else if (left != null && right != null) {
+            return left.equals(right);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return this.goalModelName.hashCode() ^ this.originalModelName.hashCode() ^ Integer.hashCode(this.numberOfSteps);
+    }
+
 }
diff --git a/tools/sar/src/main/java/org/oceandsl/tools/sar/StorageOperationDataflow.java b/tools/sar/src/main/java/org/oceandsl/tools/sar/StorageOperationDataflow.java
index f54466f0..47b5fd6e 100644
--- a/tools/sar/src/main/java/org/oceandsl/tools/sar/StorageOperationDataflow.java
+++ b/tools/sar/src/main/java/org/oceandsl/tools/sar/StorageOperationDataflow.java
@@ -95,4 +95,34 @@ public class StorageOperationDataflow {
         this.direction = direction;
     }
 
+    @Override
+    public boolean equals(final Object object) {
+        if (object instanceof StorageOperationDataflow) {
+            final StorageOperationDataflow other = (StorageOperationDataflow) object;
+            return this.checkString(this.commonBlockName, other.getCommonBlockName())
+                    && this.checkString(this.fileName, other.getFileName())
+                    && this.checkString(this.moduleName, other.getModuleName())
+                    && this.checkString(this.operationName, other.getOperationName())
+                    && this.direction.equals(other.getDirection());
+        } else {
+            return false;
+        }
+    }
+
+    private boolean checkString(final String left, final String right) {
+        if (left == null && right == null) {
+            return true;
+        } else if (left != null && right != null) {
+            return left.equals(right);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return this.commonBlockName.hashCode() ^ this.fileName.hashCode() ^ this.moduleName.hashCode()
+                ^ this.operationName.hashCode() ^ this.direction.hashCode();
+    }
+
 }
-- 
GitLab