diff --git a/tools/fxca/src/main/java/org/oceandsl/tools/fxca/FxcaMain.java b/tools/fxca/src/main/java/org/oceandsl/tools/fxca/FxcaMain.java
index b3847434c4016842d4405c5a53ba2dbfda18413d..f7acc24af19ce634b22ca61d180c90a043df14f5 100644
--- a/tools/fxca/src/main/java/org/oceandsl/tools/fxca/FxcaMain.java
+++ b/tools/fxca/src/main/java/org/oceandsl/tools/fxca/FxcaMain.java
@@ -47,9 +47,6 @@ import org.oceandsl.tools.fxca.tools.IOUtils;
 public final class FxcaMain extends AbstractService<TeetimeConfiguration, Settings> {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(FxcaMain.class);
-    private static final String OPERATION_DEFINITIONS = "operation-definitions.csv";
-    private static final String CALL_TABLE = "calltable.csv";
-    private static final String NOT_FOUND = "notfound.csv";
 
     /**
      * As suggested by PMD, make this a utility class that cannot be instantiated.
@@ -68,91 +65,6 @@ public final class FxcaMain extends AbstractService<TeetimeConfiguration, Settin
         }
     }
 
-//    private static void processModules(final FortranProject projectModel, final Path inputPath,
-//            final Path outputDirectoryPath) {
-//        final List<FortranModule> namelessModules = new ArrayList<>();
-//
-//        FxcaMain.LOGGER.info("Added modules from {}.", inputPath);
-//
-//        try (final OutputStream outputStream = Files
-//                .newOutputStream(outputDirectoryPath.resolve(FxcaMain.OPERATION_DEFINITIONS))) {
-//            final PrintStream operationListOutput = new PrintStream(outputStream);
-//
-//            operationListOutput.println("file,operation");
-//
-//            for (final FortranModule fortranModule : projectModel.getModules().values()) {
-//                if (!fortranModule.isNamedModule()) {
-//                    namelessModules.add(fortranModule);
-//                }
-//
-//                FxcaMain.LOGGER.debug("operation declarations:");
-//
-//                try {
-//                    for (final String operationName : fortranModule.computeOperationDeclarations()) {
-//                        operationListOutput
-//                                .println(fortranModule.getXmlFilePath().toAbsolutePath().getFileName().toString() + ","
-//                                        + operationName);
-//                    }
-//                } catch (ParserConfigurationException | SAXException e) {
-//                    FxcaMain.LOGGER.error("Cannot process module {}: {}", fortranModule.getModuleName(),
-//                            e.getLocalizedMessage());
-//                }
-//
-//                FxcaMain.LOGGER.debug("subroutine calls of {}: ", fortranModule.getXmlFilePath());
-//                try {
-//                    fortranModule.subroutineCalls()
-//                            .forEach(pair -> FxcaMain.LOGGER.info("call: {} --> {}", pair.first, pair.second));
-//                } catch (ParserConfigurationException | SAXException e) {
-//                    FxcaMain.LOGGER.error("Cannot process subroutine calls for module {}: {}",
-//                            fortranModule.getModuleName(), e.getLocalizedMessage());
-//                }
-//
-//                FxcaMain.LOGGER.debug("function calls of {}:", fortranModule.getXmlFilePath());
-//                try {
-//                    fortranModule.functionCalls()
-//                            .forEach(pair -> FxcaMain.LOGGER.info("call: {} --> {}", pair.first, pair.second));
-//                } catch (ParserConfigurationException | SAXException e) {
-//                    FxcaMain.LOGGER.error("Cannot process function calls for module {}: {}",
-//                            fortranModule.getModuleName(), e.getLocalizedMessage());
-//                }
-//
-//                FxcaMain.LOGGER.debug("node types:");
-//                try {
-//                    IOUtils.printWithCommas(
-//                            fortranModule.computeAllNodeAttributes(node -> StatementNode.nodeType(node.getNodeType())));
-//                } catch (ParserConfigurationException | SAXException e) {
-//                    FxcaMain.LOGGER.error("Cannot output node attribute for module {}: {}",
-//                            fortranModule.getModuleName(), e.getLocalizedMessage());
-//                }
-//
-//                FxcaMain.LOGGER.debug("node names:");
-//                try {
-//                    IOUtils.printWithCommas(fortranModule.computeAllNodeAttributes(node -> node.getNodeName()));
-//                } catch (ParserConfigurationException | SAXException e) {
-//                    FxcaMain.LOGGER.error("Cannot output node names for module {}: {}", fortranModule.getModuleName(),
-//                            e.getLocalizedMessage());
-//                }
-//            }
-//
-//            final PrintStream tableOutput = new PrintStream(
-//                    Files.newOutputStream(outputDirectoryPath.resolve(FxcaMain.CALL_TABLE)));
-//            final PrintStream errorOutput = new PrintStream(
-//                    Files.newOutputStream(outputDirectoryPath.resolve(FxcaMain.NOT_FOUND)));
-//
-////            try {
-////                projectModel.exportCallTable(tableOutput, errorOutput, namelessModules);
-////            } catch (ParserConfigurationException | SAXException e) {
-////                FxcaMain.LOGGER.error("Call table export failed: {}", e.getLocalizedMessage());
-////            }
-//
-//            operationListOutput.close();
-//            tableOutput.close();
-//            errorOutput.close();
-//        } catch (final IOException e) {
-//            FxcaMain.LOGGER.error("Cannot write {} file: {}", FxcaMain.OPERATION_DEFINITIONS, e.getLocalizedMessage());
-//        }
-//    }
-
     @Override
     protected TeetimeConfiguration createTeetimeConfiguration() throws ConfigurationException {
         return new TeetimeConfiguration(this.settings);
diff --git a/tools/fxca/src/main/java/org/oceandsl/tools/fxca/TeetimeConfiguration.java b/tools/fxca/src/main/java/org/oceandsl/tools/fxca/TeetimeConfiguration.java
index 71883b873684c14b66adff1f7ca2806a16d2227d..14759052c73aa3873b380eb9a51038e5fc7477fc 100644
--- a/tools/fxca/src/main/java/org/oceandsl/tools/fxca/TeetimeConfiguration.java
+++ b/tools/fxca/src/main/java/org/oceandsl/tools/fxca/TeetimeConfiguration.java
@@ -16,11 +16,15 @@
 package org.oceandsl.tools.fxca;
 
 import teetime.framework.Configuration;
+import teetime.stage.basic.distributor.Distributor;
+import teetime.stage.basic.distributor.strategy.CopyByReferenceStrategy;
 
 import org.oceandsl.analysis.generic.stages.DirectoryProducer;
 import org.oceandsl.analysis.generic.stages.DirectoryScannerStage;
 import org.oceandsl.analysis.generic.stages.TableCSVSink;
-import org.oceandsl.tools.fxca.stages.ComputeOutputState;
+import org.oceandsl.tools.fxca.model.FortranProject;
+import org.oceandsl.tools.fxca.stages.CreateCallTableStage;
+import org.oceandsl.tools.fxca.stages.CreateOperationTableStage;
 import org.oceandsl.tools.fxca.stages.ProcessModuleStructureStage;
 import org.oceandsl.tools.fxca.stages.ProcessOperationCallStage;
 import org.oceandsl.tools.fxca.stages.ReadDomStage;
@@ -44,20 +48,32 @@ public class TeetimeConfiguration extends Configuration {
         final ReadDomStage readDomStage = new ReadDomStage();
         final ProcessModuleStructureStage processModuleStructureStage = new ProcessModuleStructureStage();
         final ProcessOperationCallStage processOperationCallStage = new ProcessOperationCallStage();
-        final ComputeOutputState computeOutputStage = new ComputeOutputState();
+
+        final Distributor<FortranProject> projectDistributor = new Distributor<>(new CopyByReferenceStrategy());
+
+        final CreateCallTableStage callTableStage = new CreateCallTableStage();
+        final CreateOperationTableStage operationTableStage = new CreateOperationTableStage();
 
         /** output stages */
-        final TableCSVSink operationDefinitionsSink = new TableCSVSink(
+        final TableCSVSink operationTableSink = new TableCSVSink(
                 o -> settings.getOutputDirectoryPath().resolve(TeetimeConfiguration.OPERATION_DEFINITIONS), true);
         final TableCSVSink callTableSink = new TableCSVSink(
                 o -> settings.getOutputDirectoryPath().resolve(TeetimeConfiguration.CALL_TABLE), true);
-        final TableCSVSink notoundSink = new TableCSVSink(
+        final TableCSVSink notFoundSink = new TableCSVSink(
                 o -> settings.getOutputDirectoryPath().resolve(TeetimeConfiguration.NOT_FOUND), true);
 
         this.connectPorts(producer.getOutputPort(), directoryScannerStage.getInputPort());
         this.connectPorts(directoryScannerStage.getOutputPort(), readDomStage.getInputPort());
         this.connectPorts(readDomStage.getOutputPort(), processModuleStructureStage.getInputPort());
         this.connectPorts(processModuleStructureStage.getOutputPort(), processOperationCallStage.getInputPort());
-        this.connectPorts(processOperationCallStage.getOutputPort(), computeOutputStage.getInputPort());
+
+        this.connectPorts(processOperationCallStage.getOutputPort(), projectDistributor.getInputPort());
+        this.connectPorts(processOperationCallStage.getNotFoundOutputPort(), notFoundSink.getInputPort());
+
+        this.connectPorts(projectDistributor.getNewOutputPort(), callTableStage.getInputPort());
+        this.connectPorts(callTableStage.getOutputPort(), callTableSink.getInputPort());
+
+        this.connectPorts(projectDistributor.getNewOutputPort(), operationTableStage.getInputPort());
+        this.connectPorts(operationTableStage.getOutputPort(), operationTableSink.getInputPort());
     }
 }
diff --git a/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/CallTableStage.java b/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/CallTableStage.java
deleted file mode 100644
index dc73a23a3034ebd3d14971eb7a850256805217dd..0000000000000000000000000000000000000000
--- a/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/CallTableStage.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package org.oceandsl.tools.fxca.stages;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.List;
-
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.xml.sax.SAXException;
-
-import teetime.stage.basic.AbstractTransformation;
-
-import org.oceandsl.analysis.code.stages.data.Table;
-import org.oceandsl.tools.fxca.model.FortranModule;
-import org.oceandsl.tools.fxca.model.FortranProject;
-import org.oceandsl.tools.fxca.tools.ListTools;
-import org.oceandsl.tools.fxca.tools.Pair;
-
-/**
- *
- * @author Henning Schnoor -- initial contribution
- * @author Reiner Jung
- *
- */
-public class CallTableStage extends AbstractTransformation<FortranProject, Table> {
-
-    @Override
-    protected void execute(final FortranProject element) throws Exception {
-        // TODO Auto-generated method stub
-
-    }
-
-    /**
-     * Exports the call cable into CSV files.
-     *
-     * @param PrintStream
-     *            for table
-     * @param PrintStream
-     *            for list of not-found entries
-     * @param globalModules
-     *            list of modules that are available to all modules / files without explicit
-     *            reference
-     * @throws ParserConfigurationException
-     * @throws SAXException
-     * @throws IOException
-     */
-    private void exportCallTable(final PrintStream tableOut, final PrintStream notFoundOut,
-            final List<FortranModule> globalModules) throws ParserConfigurationException, SAXException, IOException {
-        tableOut.println("callerfilename,callermodule,callerfunction,calleefilename,calleemodule,calleefunction");
-        this.logger.debug("Calls to operations that could not be found:");
-        for (final FortranModule module : globalModules) {
-            for (final Pair<String, String> call : module.operationCalls()) {
-                final String callerFunctionName = call.first;
-                final String callerFileName = module.getXmlFilePath().toAbsolutePath().getFileName().toString();
-                final String calleeFunctionName = call.second;
-                final FortranModule calleeXML = this.resolveCallee(module, calleeFunctionName, globalModules);
-                final String calleeFileName = calleeXML == null ? "<unknown>"
-                        : calleeXML.getXmlFilePath().toAbsolutePath().getFileName().toString();
-                final String calleeModuleName = calleeXML == null ? "<unknown>" : calleeXML.getModuleName();
-                tableOut.println(callerFileName + ", " + module.getModuleName() + ", " + callerFunctionName + ", "
-                        + calleeFileName + ", " + calleeModuleName + ", " + calleeFunctionName);
-                if (calleeXML == null) {
-                    notFoundOut.println(callerFileName + ":" + callerFunctionName + " --> " + calleeFunctionName);
-                }
-            }
-        }
-    }
-
-    private FortranModule resolveCallee(final FortranModule xml, final String calleeFunctionName,
-            final List<FortranModule> globalModules) {
-        this.logger.debug("resolve Callee: {} from {}", calleeFunctionName, xml.getXmlFilePath());
-        /*
-         * if ("MDS_WRITE_FIELD".equals(calleeFunctionName)) { System.exit(0); }
-         */
-        return ListTools.getUniqueElementIfNonEmpty(
-                this.resolveCalleeModuleCandidates(xml, calleeFunctionName, globalModules), null);
-    }
-
-    private List<FortranModule> resolveCalleeModuleCandidates(final FortranModule callerModule,
-            final String calleeOperationName, final List<FortranModule> globalModules) {
-
-        final List<FortranModule> result = ListTools.ofM();
-        final List<FortranModule> usedModules = ListTools.ofM(callerModule); // local definitions
-                                                                             // are always the first
-                                                                             // ones.
-
-        for (final String usedModuleName : callerModule.getUsedModules()) {
-            // final FortranModule moduleXML = moduleNames.get(usedModuleName);
-//            if (moduleXML == null) {
-//                this.logger.warn("MODULE NOT FOUND: [{}]", usedModuleName);
-//            } else {
-//                usedModules.add(moduleXML);
-//            }
-        }
-
-        if (globalModules != null) {
-            usedModules.addAll(globalModules);
-        }
-
-        for (final FortranModule usedModule : usedModules) {
-            if (usedModule.getSpecifiedOperations().contains(calleeOperationName)) {
-                result.add(usedModule);
-            }
-        }
-        return result;
-    }
-
-}
diff --git a/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/ComputeOutputState.java b/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/ComputeOutputState.java
deleted file mode 100644
index 2ef5c99a68d38d65b881ce38f8680fa6f6aa4344..0000000000000000000000000000000000000000
--- a/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/ComputeOutputState.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package org.oceandsl.tools.fxca.stages;
-
-import teetime.framework.AbstractConsumerStage;
-import teetime.framework.OutputPort;
-
-import org.oceandsl.analysis.code.stages.data.StringValueHandler;
-import org.oceandsl.analysis.code.stages.data.Table;
-import org.oceandsl.analysis.code.stages.data.ValueConversionErrorException;
-import org.oceandsl.tools.fxca.model.FortranModule;
-import org.oceandsl.tools.fxca.model.FortranProject;
-import org.oceandsl.tools.fxca.tools.Pair;
-
-public class ComputeOutputState extends AbstractConsumerStage<FortranProject> {
-
-    private static final String SOURCE_PATH = "callerfilename";
-    private static final String SOURCE_MODULE = "callermodule";
-    private static final String SOURCE_OPERATION = "callerfunction";
-    private static final String TARGET_PATH = "calleefilename";
-    private static final String TARGET_MODULE = "calleemodule";
-    private static final String TARGET_OPERATION = "calleefunction";
-
-    private final OutputPort<Table> callsOutputPort = this.createOutputPort(Table.class);
-    private final OutputPort<Table> callTableOutputPort = this.createOutputPort(Table.class);
-    private final OutputPort<Table> notFoundOutputPort = this.createOutputPort(Table.class);
-
-    @Override
-    protected void execute(final FortranProject project) throws Exception {
-        final Table callsTable = new Table("calls", new StringValueHandler(SOURCE_PATH),
-                new StringValueHandler(SOURCE_MODULE), new StringValueHandler(SOURCE_OPERATION),
-                new StringValueHandler(TARGET_PATH), new StringValueHandler(TARGET_MODULE),
-                new StringValueHandler(TARGET_OPERATION));
-        project.getModules().values().forEach(module -> {
-            module.getCalls().forEach(call -> {
-                final Pair<FortranModule, String> caller = call.getFirst();
-                final Pair<FortranModule, String> callee = call.getSecond();
-
-                if (caller != null) {
-                    final FortranModule callerModule = caller.getFirst();
-
-                    final String callerPath;
-                    final String callerModuleName;
-                    final String callerOperation = caller.getSecond();
-
-                    if (callerModule.isNamedModule()) {
-                        callerPath = callerModule.getDocument().getBaseURI();
-                        callerModuleName = callerModule.getModuleName();
-                    } else {
-                        callerPath = callerModule.getModuleName();
-                        callerModuleName = "<no-module>";
-                    }
-
-                    if (callee != null) {
-                        final FortranModule calleeModule = callee.getFirst();
-
-                        final String calleePath;
-                        final String calleeModuleName;
-                        final String calleeOperation = callee.getSecond();
-
-                        if (calleeModule.isNamedModule()) {
-                            calleePath = calleeModule.getDocument().getBaseURI();
-                            calleeModuleName = calleeModule.getModuleName();
-                        } else {
-                            calleePath = calleeModule.getModuleName();
-                            calleeModuleName = "<no-module>";
-                        }
-                        try {
-                            callsTable.addRow(callerPath, callerModuleName, callerOperation, calleePath,
-                                    calleeModuleName, calleeOperation);
-                        } catch (final ValueConversionErrorException e) {
-                            // TODO Auto-generated catch block
-                            e.printStackTrace();
-                        }
-                    } else {
-                        this.logger.debug("Caller {} {} {} has no callee ", callerPath, callerModuleName,
-                                callerOperation);
-                    }
-                } else {
-                    if (callee != null) {
-                        final FortranModule calleeModule = callee.getFirst();
-
-                        final String calleePath;
-                        final String calleeModuleName;
-                        final String calleeOperation = callee.getSecond();
-
-                        if (calleeModule.isNamedModule()) {
-                            calleePath = calleeModule.getDocument().getBaseURI();
-                            calleeModuleName = calleeModule.getModuleName();
-                        } else {
-                            calleePath = calleeModule.getModuleName();
-                            calleeModuleName = "<no-module>";
-                        }
-
-                        this.logger.debug("No caller for callee {} {} {}", calleePath, calleeModuleName,
-                                calleeOperation);
-                    } else {
-                        this.logger.debug("Empty call");
-                    }
-                }
-            });
-        });
-
-        this.callsOutputPort.send(callsTable);
-    }
-
-}
diff --git a/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/CreateCallTableStage.java b/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/CreateCallTableStage.java
new file mode 100644
index 0000000000000000000000000000000000000000..7b9ea393de1e0f15cca4f71ce2eec1038ca8702a
--- /dev/null
+++ b/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/CreateCallTableStage.java
@@ -0,0 +1,90 @@
+package org.oceandsl.tools.fxca.stages;
+
+import teetime.stage.basic.AbstractTransformation;
+
+import org.oceandsl.analysis.code.stages.data.StringValueHandler;
+import org.oceandsl.analysis.code.stages.data.Table;
+import org.oceandsl.analysis.code.stages.data.ValueConversionErrorException;
+import org.oceandsl.tools.fxca.model.FortranModule;
+import org.oceandsl.tools.fxca.model.FortranProject;
+import org.oceandsl.tools.fxca.tools.Pair;
+
+public class CreateCallTableStage extends AbstractTransformation<FortranProject, Table> {
+
+    private static final String SOURCE_PATH = "callerfilename";
+    private static final String SOURCE_MODULE = "callermodule";
+    private static final String SOURCE_OPERATION = "callerfunction";
+    private static final String TARGET_PATH = "calleefilename";
+    private static final String TARGET_MODULE = "calleemodule";
+    private static final String TARGET_OPERATION = "calleefunction";
+
+    private record Operation(String path, String moduleName, String operation) {
+        Operation(final String path, final String moduleName, final String operation) {
+            this.path = path;
+            this.moduleName = moduleName;
+            this.operation = operation;
+        }
+    }
+
+    @Override
+    protected void execute(final FortranProject project) throws Exception {
+        final Table callsTable = new Table("calls", new StringValueHandler(CreateCallTableStage.SOURCE_PATH),
+                new StringValueHandler(CreateCallTableStage.SOURCE_MODULE),
+                new StringValueHandler(CreateCallTableStage.SOURCE_OPERATION),
+                new StringValueHandler(CreateCallTableStage.TARGET_PATH),
+                new StringValueHandler(CreateCallTableStage.TARGET_MODULE),
+                new StringValueHandler(CreateCallTableStage.TARGET_OPERATION));
+
+        final Table notFound = new Table("not-found", new StringValueHandler(CreateCallTableStage.SOURCE_PATH),
+                new StringValueHandler(CreateCallTableStage.SOURCE_MODULE),
+                new StringValueHandler(CreateCallTableStage.SOURCE_OPERATION),
+                new StringValueHandler(CreateCallTableStage.TARGET_OPERATION));
+
+        project.getModules().values().forEach(module -> {
+            module.getCalls().forEach(call -> {
+                final Pair<FortranModule, String> callerPair = call.getFirst();
+                final Pair<FortranModule, String> calleePair = call.getSecond();
+
+                if (callerPair != null) {
+                    final Operation caller = this.composeOperation(callerPair);
+                    if (calleePair != null) {
+                        final Operation callee = this.composeOperation(calleePair);
+                        try {
+                            callsTable.addRow(caller.path, caller.moduleName, caller.operation, callee.path,
+                                    callee.moduleName, callee.operation);
+                        } catch (final ValueConversionErrorException e) {
+                            this.logger.error("Error writing calls to table: {}", e.getLocalizedMessage());
+                        }
+                    } else {
+                        this.logger.warn("Caller {} {} {} has no callee ", caller.path, caller.moduleName,
+                                caller.operation);
+                    }
+                } else {
+                    if (calleePair != null) {
+                        final Operation callee = this.composeOperation(calleePair);
+                        this.logger.warn("No caller for callee {} {} {}", callee.path, callee.moduleName,
+                                callee.operation);
+                    } else {
+                        this.logger.error("Empty call");
+                    }
+                }
+            });
+        });
+
+        this.outputPort.send(callsTable);
+    }
+
+    private Operation composeOperation(final Pair<FortranModule, String> operationDescription) {
+        final FortranModule module = operationDescription.getFirst();
+
+        final String callerOperation = operationDescription.getSecond();
+
+        if (module.isNamedModule()) {
+            return new Operation(module.getDocument().getBaseURI(), module.getModuleName(), callerOperation);
+        } else {
+            return new Operation(module.getDocument().getBaseURI(), "<no-module>", callerOperation);
+        }
+
+    }
+
+}
diff --git a/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/CreateOperationTableStage.java b/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/CreateOperationTableStage.java
new file mode 100644
index 0000000000000000000000000000000000000000..b48123c3de4b6edebc3be2042018c79b702c2618
--- /dev/null
+++ b/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/CreateOperationTableStage.java
@@ -0,0 +1,51 @@
+/***************************************************************************
+ * 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.fxca.stages;
+
+import teetime.stage.basic.AbstractTransformation;
+
+import org.oceandsl.analysis.code.stages.data.StringValueHandler;
+import org.oceandsl.analysis.code.stages.data.Table;
+import org.oceandsl.analysis.code.stages.data.ValueConversionErrorException;
+import org.oceandsl.tools.fxca.model.FortranProject;
+
+/**
+ * Create a table containing operations.
+ *
+ * @author Henning Schnoor -- initial contribution
+ * @author Reiner Jung
+ */
+public class CreateOperationTableStage extends AbstractTransformation<FortranProject, Table> {
+
+    @Override
+    protected void execute(final FortranProject project) throws Exception {
+        final Table callsTable = new Table("operation", new StringValueHandler("file"),
+                new StringValueHandler("operation"));
+        project.getModules().values().forEach(module -> {
+            final String path = module.getDocument().getBaseURI();
+            module.getSpecifiedOperations().forEach(operation -> {
+                try {
+                    callsTable.addRow(path, operation);
+                } catch (final ValueConversionErrorException e) {
+                    this.logger.error("Error writing values to operation table: {}", e.getLocalizedMessage());
+                }
+            });
+        });
+
+        this.outputPort.send(callsTable);
+    }
+
+}
diff --git a/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/ProcessModuleStructureStage.java b/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/ProcessModuleStructureStage.java
index c22728a234a6b5274a99aa7258decd0aafe81d8d..a1a35591663fc538e1bb397d9a94f8596a4bfa57 100644
--- a/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/ProcessModuleStructureStage.java
+++ b/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/ProcessModuleStructureStage.java
@@ -16,6 +16,7 @@
 package org.oceandsl.tools.fxca.stages;
 
 import java.io.IOException;
+import java.util.Locale;
 import java.util.Set;
 
 import javax.xml.parsers.ParserConfigurationException;
@@ -29,8 +30,8 @@ import teetime.stage.basic.AbstractTransformation;
 
 import org.oceandsl.tools.fxca.model.FortranModule;
 import org.oceandsl.tools.fxca.model.FortranProject;
-import org.oceandsl.tools.fxca.model.StatementNode;
 import org.oceandsl.tools.fxca.tools.ListTools;
+import org.oceandsl.tools.fxca.tools.NodeProcessingUtils;
 
 /**
  *
@@ -50,7 +51,7 @@ public class ProcessModuleStructureStage extends AbstractTransformation<Document
     protected void execute(final Document document) throws Exception {
         final Element documentElement = document.getDocumentElement();
         final Node moduleStatement = ListTools.getUniqueElementIfNonEmpty(
-                StatementNode.allDescendents(documentElement, StatementNode.isModuleStatement, true), null);
+                NodeProcessingUtils.allDescendents(documentElement, NodeProcessingUtils.isModuleStatement, true), null);
 
         final boolean namedModule = moduleStatement != null;
         final String moduleName = namedModule ? moduleStatement.getChildNodes().item(1).getTextContent()
@@ -71,7 +72,7 @@ public class ProcessModuleStructureStage extends AbstractTransformation<Document
     }
 
     private void computeUsedModels(final FortranModule module, final Element rootNode) {
-        final Set<Node> useStatements = StatementNode.allDescendents(rootNode, StatementNode.isUseStatement, false);
+        final Set<Node> useStatements = NodeProcessingUtils.allDescendents(rootNode, NodeProcessingUtils.isUseStatement, false);
         for (final Node useStatement : useStatements) {
             final String usedModuleName = useStatement.getChildNodes().item(1).getTextContent();
             this.logger.debug("found use statement: {}, module name: {}", useStatement.getTextContent(),
@@ -82,10 +83,10 @@ public class ProcessModuleStructureStage extends AbstractTransformation<Document
 
     public void computeOperationDeclarations(final FortranModule module, final Element documentElement)
             throws ParserConfigurationException, SAXException, IOException {
-        StatementNode
-                .getDescendentAttributes(documentElement, StatementNode.isOperationStatement,
-                        operationNode -> StatementNode.getNameOfOperation(operationNode))
-                .forEach(operation -> module.getSpecifiedOperations().add(operation));
+        NodeProcessingUtils
+                .getDescendentAttributes(documentElement, NodeProcessingUtils.isOperationStatement,
+                        operationNode -> NodeProcessingUtils.getNameOfOperation(operationNode))
+                .forEach(operation -> module.getSpecifiedOperations().add(operation.toLowerCase(Locale.getDefault())));
     }
 
 }
diff --git a/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/ProcessOperationCallStage.java b/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/ProcessOperationCallStage.java
index 1b6e92250782d1c82f4eadbbfc597f9d18f35c43..0216d7f5f5a83533309d7514ef68ddceeb02fe83 100644
--- a/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/ProcessOperationCallStage.java
+++ b/tools/fxca/src/main/java/org/oceandsl/tools/fxca/stages/ProcessOperationCallStage.java
@@ -25,11 +25,15 @@ import javax.xml.parsers.ParserConfigurationException;
 import org.w3c.dom.Element;
 import org.xml.sax.SAXException;
 
+import teetime.framework.OutputPort;
 import teetime.stage.basic.AbstractFilter;
 
+import org.oceandsl.analysis.code.stages.data.StringValueHandler;
+import org.oceandsl.analysis.code.stages.data.Table;
+import org.oceandsl.analysis.code.stages.data.ValueConversionErrorException;
 import org.oceandsl.tools.fxca.model.FortranModule;
 import org.oceandsl.tools.fxca.model.FortranProject;
-import org.oceandsl.tools.fxca.model.StatementNode;
+import org.oceandsl.tools.fxca.tools.NodeProcessingUtils;
 import org.oceandsl.tools.fxca.tools.Pair;
 
 /**
@@ -39,32 +43,72 @@ import org.oceandsl.tools.fxca.tools.Pair;
  */
 public class ProcessOperationCallStage extends AbstractFilter<FortranProject> {
 
+    private final OutputPort<Table> notFoundOutputPort = this.createOutputPort(Table.class);
+
     @Override
     protected void execute(final FortranProject project) throws Exception {
+        final Table notFoundTable = new Table("not-found", new StringValueHandler("caller-path"),
+                new StringValueHandler("caller-module"), new StringValueHandler("caller-operation"),
+                new StringValueHandler("callee-operation"));
+
         project.getModules().values().forEach(module -> {
             final Element element = module.getDocument().getDocumentElement();
-            try {
-                final List<Pair<String, String>> calls = StatementNode.subroutineCalls(element);
-                calls.forEach(call -> {
-                    final Pair<FortranModule, String> caller = this.findOperation(project.getModules().values(),
-                            call.getFirst());
-                    final Pair<FortranModule, String> callee = this.findOperation(project.getModules().values(),
-                            call.getSecond());
-                    if (caller == null) {
-                        this.logger.debug("Caller not found for {}", call.getFirst());
-                    }
-                    if (callee == null) {
-                        this.logger.debug("Callee not found for {}", call.getSecond());
-                    }
-                    module.getCalls().add(new Pair<>(caller, callee));
-                });
-            } catch (ParserConfigurationException | SAXException | IOException e) {
-                // TODO Auto-generated catch block
-                e.printStackTrace();
-            }
+            this.processSubroutines(project, module, element, notFoundTable);
+            this.processFunctions(project, module, element, notFoundTable);
         });
 
         this.outputPort.send(project);
+        this.notFoundOutputPort.send(notFoundTable);
+    }
+
+    private void processSubroutines(final FortranProject project, final FortranModule module, final Element element,
+            final Table notFoundTable) {
+        try {
+            final List<Pair<String, String>> calls = NodeProcessingUtils.subroutineCalls(element);
+            this.processCalls(project, module, calls, notFoundTable);
+        } catch (ParserConfigurationException | SAXException | IOException e) {
+            this.logger.error("Processing subroutine calls in file {} failed: {}", element.getBaseURI(),
+                    e.getLocalizedMessage());
+        }
+    }
+
+    private void processFunctions(final FortranProject project, final FortranModule module, final Element element,
+            final Table notFoundTable) {
+        try {
+            final List<Pair<String, String>> calls = NodeProcessingUtils.functionCalls(element);
+            this.processCalls(project, module, calls, notFoundTable);
+        } catch (ParserConfigurationException | SAXException | IOException e) {
+            this.logger.error("Processing subroutine calls in file {} failed: {}", element.getBaseURI(),
+                    e.getLocalizedMessage());
+        }
+
+    }
+
+    private void processCalls(final FortranProject project, final FortranModule module,
+            final List<Pair<String, String>> calls, final Table notFoundTable) {
+        calls.forEach(call -> {
+            final Pair<FortranModule, String> caller = this.findOperation(project.getModules().values(),
+                    call.getFirst());
+            final Pair<FortranModule, String> callee = this.findOperation(project.getModules().values(),
+                    call.getSecond());
+            if (caller == null) {
+                this.logger.info("Caller not found for {}", call.getFirst());
+            }
+            if (callee == null) {
+                try {
+                    notFoundTable.addRow(caller.first.getDocument().getBaseURI(), caller.first.getModuleName(),
+                            caller.second, call.second);
+                } catch (final ValueConversionErrorException e) {
+                    this.logger.error("Cannot add row to callee not found table: {}", e.getLocalizedMessage());
+                }
+                this.logger.info("Callee not found for {}", call.getSecond());
+            }
+            module.getCalls().add(new Pair<>(caller, callee));
+        });
+    }
+
+    public OutputPort<Table> getNotFoundOutputPort() {
+        return this.notFoundOutputPort;
     }
 
     private Pair<FortranModule, String> findOperation(final Collection<FortranModule> modules, final String signature) {
diff --git a/tools/fxca/src/main/java/org/oceandsl/tools/fxca/model/LocalExpressionAccess.java b/tools/fxca/src/main/java/org/oceandsl/tools/fxca/tools/LocalExpressionAccess.java
similarity index 76%
rename from tools/fxca/src/main/java/org/oceandsl/tools/fxca/model/LocalExpressionAccess.java
rename to tools/fxca/src/main/java/org/oceandsl/tools/fxca/tools/LocalExpressionAccess.java
index 76f603c8a2a3ae99817a1519b46c8d4d65c41b8d..ca9a1982319d5069ee8a42d98b400c8f51746ef6 100644
--- a/tools/fxca/src/main/java/org/oceandsl/tools/fxca/model/LocalExpressionAccess.java
+++ b/tools/fxca/src/main/java/org/oceandsl/tools/fxca/tools/LocalExpressionAccess.java
@@ -1,4 +1,4 @@
-package org.oceandsl.tools.fxca.model;
+package org.oceandsl.tools.fxca.tools;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -30,17 +30,17 @@ public class LocalExpressionAccess {
         COMMON_BLOCK, LOCAL_VARIABLE, OPERATION_PARAMETER, OPERATION_CALL
     }
 
-    static LocalAccessParameters namesInCommonBlocks = new LocalAccessParameters(StatementNode.isCommonStatement,
-            StatementNode.isCommonBlockObjectStatement, StatementNode.isSmallN,
-            smallNNode -> StatementNode.getSuccessorNode(smallNNode, "0").getTextContent());
+    static LocalAccessParameters namesInCommonBlocks = new LocalAccessParameters(NodeProcessingUtils.isCommonStatement,
+            NodeProcessingUtils.isCommonBlockObjectStatement, NodeProcessingUtils.isSmallN,
+            smallNNode -> NodeProcessingUtils.getSuccessorNode(smallNNode, "0").getTextContent());
 
     static LocalAccessParameters namesInOperationParameterList = new LocalAccessParameters(
-            StatementNode.isOperationStatement, StatementNode.isArgN, StatementNode.isSmallN,
-            smallNNode -> StatementNode.getSuccessorNode(smallNNode, "0").getTextContent());
+            NodeProcessingUtils.isOperationStatement, NodeProcessingUtils.isArgN, NodeProcessingUtils.isSmallN,
+            smallNNode -> NodeProcessingUtils.getSuccessorNode(smallNNode, "0").getTextContent());
 
-    static LocalAccessParameters namesInLocalVariableList = new LocalAccessParameters(StatementNode.isTDeclStmt,
-            StatementNode.isEnDcl, StatementNode.isSmallN,
-            smallNNode -> StatementNode.getSuccessorNode(smallNNode, "0").getTextContent());
+    static LocalAccessParameters namesInLocalVariableList = new LocalAccessParameters(NodeProcessingUtils.isTDeclStmt,
+            NodeProcessingUtils.isEnDcl, NodeProcessingUtils.isSmallN,
+            smallNNode -> NodeProcessingUtils.getSuccessorNode(smallNNode, "0").getTextContent());
 
     static Set<String> localNamesDefinedInApplyingBlocks(final Node node, final LocalAccessParameters parameters,
             final boolean verbose) {
@@ -50,9 +50,9 @@ public class LocalExpressionAccess {
         Node current = node;
 
         while (current != null) {
-            final List<Node> applyingBlocksOnThisLevel = StatementNode.findAll(current,
+            final List<Node> applyingBlocksOnThisLevel = NodeProcessingUtils.findAll(current,
                     nnode -> nnode.getPreviousSibling(), parameters.blockNodeTypeCheckPredicate, true,
-                    StatementNode.paranthesisTypes, -1);
+                    NodeProcessingUtils.paranthesisTypes, -1);
             applyingBlocks.addAll(applyingBlocksOnThisLevel);
             current = current.getParentNode();
         }
@@ -78,8 +78,8 @@ public class LocalExpressionAccess {
         }
 
         final HashSet<String> result = new HashSet<>();
-        for (final Node element : StatementNode.allDescendents(blockNode, parameters.outerDelimiterPredicate, true)) {
-            for (final Node smallN : StatementNode.allDescendents(element, parameters.innerDelimiterPredicate, true)) {
+        for (final Node element : NodeProcessingUtils.allDescendents(blockNode, parameters.outerDelimiterPredicate, true)) {
+            for (final Node smallN : NodeProcessingUtils.allDescendents(element, parameters.innerDelimiterPredicate, true)) {
                 result.add(parameters.extractName.apply(smallN));
             }
         }
@@ -89,11 +89,11 @@ public class LocalExpressionAccess {
 
     public static boolean isNamedExpressionLocalReference(final Node node, final LocalAccessParameters parameters) {
 
-        if (!StatementNode.namedExpressionAccess.test(node)) {
+        if (!NodeProcessingUtils.namedExpressionAccess.test(node)) {
             return false;
         }
 
-        final String nameOfCalledFunction = StatementNode.nameOfCalledFunction(node);
+        final String nameOfCalledFunction = NodeProcessingUtils.nameOfCalledFunction(node);
 
         return LocalExpressionAccess.localNamesDefinedInApplyingBlocks(node, parameters, false)
                 .contains(nameOfCalledFunction);
@@ -117,7 +117,7 @@ public class LocalExpressionAccess {
     }
 
     public static boolean isLocalAccess(final Node referenceNode) {
-        return StatementNode.isCallStatement.or(StatementNode.namedExpressionAccess).test(referenceNode)
+        return NodeProcessingUtils.isCallStatement.or(NodeProcessingUtils.namedExpressionAccess).test(referenceNode)
                 && typeOfReferenceAccess(referenceNode) != accessType.OPERATION_CALL;
     }
 
@@ -156,7 +156,7 @@ public class LocalExpressionAccess {
             throw new IllegalStateException();
         }
 
-        return StatementNode.nameOfCalledFunction(referenceNode) + suffix;
+        return NodeProcessingUtils.nameOfCalledFunction(referenceNode) + suffix;
     }
 
 }
diff --git a/tools/fxca/src/main/java/org/oceandsl/tools/fxca/model/StatementNode.java b/tools/fxca/src/main/java/org/oceandsl/tools/fxca/tools/NodeProcessingUtils.java
similarity index 58%
rename from tools/fxca/src/main/java/org/oceandsl/tools/fxca/model/StatementNode.java
rename to tools/fxca/src/main/java/org/oceandsl/tools/fxca/tools/NodeProcessingUtils.java
index 59ebb747c24b82e649aba46a09525894f4ac6f63..03bd1e5682a1e66b884474032cf7faef12a7fb41 100644
--- a/tools/fxca/src/main/java/org/oceandsl/tools/fxca/model/StatementNode.java
+++ b/tools/fxca/src/main/java/org/oceandsl/tools/fxca/tools/NodeProcessingUtils.java
@@ -13,13 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  ***************************************************************************/
-package org.oceandsl.tools.fxca.model;
+package org.oceandsl.tools.fxca.tools;
 
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Set;
 import java.util.function.Function;
 import java.util.function.Predicate;
@@ -32,9 +33,6 @@ import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 import org.xml.sax.SAXException;
 
-import org.oceandsl.tools.fxca.tools.ListTools;
-import org.oceandsl.tools.fxca.tools.Pair;
-
 // No own attributes, only accessor functions for nodes. Implemented as class in order to allow
 // chaining.
 
@@ -43,60 +41,79 @@ import org.oceandsl.tools.fxca.tools.Pair;
  * @author Henning Schnoor
  * @since 1.3.0
  */
-public class StatementNode {
-
-    public static Predicate<Node> isSubroutineStatement = StatementNode.hasName("subroutine-stmt");
-    public static Predicate<Node> isEndSubroutineStatement = StatementNode.hasName("end-subroutine-stmt");
-    public static Predicate<Node> isFunctionStatement = StatementNode.hasName("function-stmt");
-    public static Predicate<Node> isOperationStatement = StatementNode.isSubroutineStatement
-            .or(StatementNode.isFunctionStatement);
-    public static Predicate<Node> isEndFunctionStatement = StatementNode.hasName("end-function-stmt");
-    public static Predicate<Node> isModuleStatement = StatementNode.hasName("module-stmt");
-    public static Predicate<Node> isUseStatement = StatementNode.hasName("use-stmt");
-    public static Predicate<Node> isCallStatement = StatementNode.hasName("call-stmt");
-    public static Predicate<Node> isSubroutineName = StatementNode.hasName("subroutine-N");
-    public static Predicate<Node> isFunctionName = StatementNode.hasName("function-N");
-    public static Predicate<Node> isNamedExpression = StatementNode.hasName("named-E");
-    public static Predicate<Node> isBigN = StatementNode.hasName("N");
-    public static Predicate<Node> isArgN = StatementNode.hasName("arg-N");
-    public static Predicate<Node> isTDeclStmt = StatementNode.hasName("T-decl-stmt");
-    public static Predicate<Node> isEnDcl = StatementNode.hasName("EN-decl");
-    public static Predicate<Node> isSmallN = StatementNode.hasName("n");
-    public static Predicate<Node> isElementLT = StatementNode.hasName("element-LT");
-    public static Predicate<Node> isRLT = StatementNode.hasName("R-LT");
-    public static Predicate<Node> isElement = StatementNode.hasName("element");
-    public static Predicate<Node> isParensR = StatementNode.hasName("parens-R");
-    public static Predicate<Node> isRegularLeftParanthesis = StatementNode.isParensR
+public class NodeProcessingUtils {
+
+    public static Predicate<Node> isProgramStatement = NodeProcessingUtils.hasName("program-stmt");
+    public static Predicate<Node> isSubroutineStatement = NodeProcessingUtils.hasName("subroutine-stmt");
+    public static Predicate<Node> isFunctionStatement = NodeProcessingUtils.hasName("function-stmt");
+    public static Predicate<Node> isEntryStatement = NodeProcessingUtils.hasName("entry-stmt");
+    public static Predicate<Node> isOperationStatement = NodeProcessingUtils.isSubroutineStatement
+            .or(NodeProcessingUtils.isFunctionStatement).or(NodeProcessingUtils.isEntryStatement)
+            .or(NodeProcessingUtils.isProgramStatement);
+
+    public static Predicate<Node> isEndSubroutineStatement = NodeProcessingUtils.hasName("end-subroutine-stmt");
+    public static Predicate<Node> isEndFunctionStatement = NodeProcessingUtils.hasName("end-function-stmt");
+
+    public static Predicate<Node> isModuleStatement = NodeProcessingUtils.hasName("module-stmt");
+    public static Predicate<Node> isUseStatement = NodeProcessingUtils.hasName("use-stmt");
+
+    public static Predicate<Node> isCallStatement = NodeProcessingUtils.hasName("call-stmt");
+
+    public static Predicate<Node> isProgramName = NodeProcessingUtils.hasName("program-N");
+    public static Predicate<Node> isSubroutineName = NodeProcessingUtils.hasName("subroutine-N");
+    public static Predicate<Node> isFunctionName = NodeProcessingUtils.hasName("function-N");
+    public static Predicate<Node> isEntryName = NodeProcessingUtils.hasName("entry-N");
+
+    public static Predicate<Node> isNamedExpression = NodeProcessingUtils.hasName("named-E");
+    public static Predicate<Node> isBigN = NodeProcessingUtils.hasName("N");
+    public static Predicate<Node> isArgN = NodeProcessingUtils.hasName("arg-N");
+    public static Predicate<Node> isTDeclStmt = NodeProcessingUtils.hasName("T-decl-stmt");
+    public static Predicate<Node> isEnDcl = NodeProcessingUtils.hasName("EN-decl");
+    public static Predicate<Node> isSmallN = NodeProcessingUtils.hasName("n");
+    public static Predicate<Node> isElementLT = NodeProcessingUtils.hasName("element-LT");
+    public static Predicate<Node> isRLT = NodeProcessingUtils.hasName("R-LT");
+    public static Predicate<Node> isElement = NodeProcessingUtils.hasName("element");
+    public static Predicate<Node> isParensR = NodeProcessingUtils.hasName("parens-R");
+    public static Predicate<Node> isRegularLeftParanthesis = NodeProcessingUtils.isParensR
             .and(node -> node.getTextContent().startsWith("("));
-    public static Predicate<Node> isCommonStatement = StatementNode.hasName("common-stmt");
-    public static Predicate<Node> isCommonBlockObjectStatement = StatementNode.hasName("common-block-obj-N");
+    public static Predicate<Node> isCommonStatement = NodeProcessingUtils.hasName("common-stmt");
+    public static Predicate<Node> isCommonBlockObjectStatement = NodeProcessingUtils.hasName("common-block-obj-N");
     public static Predicate<Node> isLocalAccess = node -> LocalExpressionAccess.isLocalAccess(node);
 
-    public static Predicate<Node> namedExpressionAccess = StatementNode.isNamedExpression
-            .and(StatementNode.childSatisfies("0", StatementNode.isBigN))
-            .and(StatementNode.childSatisfies("0,0", StatementNode.isSmallN))
-            .and(StatementNode.childSatisfies("1", StatementNode.isRLT))
-            .and(StatementNode.childSatisfies("1,0", StatementNode.isRegularLeftParanthesis));
+    public static Predicate<Node> namedExpressionAccess = NodeProcessingUtils.isNamedExpression
+            .and(NodeProcessingUtils.childSatisfies("0", NodeProcessingUtils.isBigN))
+            .and(NodeProcessingUtils.childSatisfies("0,0", NodeProcessingUtils.isSmallN))
+            .and(NodeProcessingUtils.childSatisfies("1", NodeProcessingUtils.isRLT))
+            .and(NodeProcessingUtils.childSatisfies("1,0", NodeProcessingUtils.isRegularLeftParanthesis));
 
     public static Pair<Predicate<Node>, Predicate<Node>> endFunctionToBeginFunction = new Pair<>(
-            StatementNode.isEndFunctionStatement, StatementNode.isFunctionStatement);
+            NodeProcessingUtils.isEndFunctionStatement, NodeProcessingUtils.isFunctionStatement);
 
     public static Pair<Predicate<Node>, Predicate<Node>> endSubroutineToBeginSubroutine = new Pair<>(
-            StatementNode.isEndSubroutineStatement, StatementNode.isSubroutineStatement);
+            NodeProcessingUtils.isEndSubroutineStatement, NodeProcessingUtils.isSubroutineStatement);
 
     public static List<Pair<Predicate<Node>, Predicate<Node>>> paranthesisTypes = List
-            .of(StatementNode.endFunctionToBeginFunction, StatementNode.endSubroutineToBeginSubroutine);
+            .of(NodeProcessingUtils.endFunctionToBeginFunction, NodeProcessingUtils.endSubroutineToBeginSubroutine);
+
+    private static String ROOT_PROGRAM = "main";
+
+    /** methods. */
 
     public static String nameOfCalledFunction(final Node functionCallNode) {
-        return StatementNode.getSuccessorNode(functionCallNode, "0,0").getTextContent();
+        return NodeProcessingUtils.getSuccessorNode(functionCallNode, "0,0").getTextContent()
+                .toLowerCase(Locale.getDefault());
     }
 
     public static String nameOfCalledOperation(final Node operationCallNode) {
-        return StatementNode.getSuccessorNode(operationCallNode, "1").getTextContent();
+        return NodeProcessingUtils.getSuccessorNode(operationCallNode, "1").getTextContent()
+                .toLowerCase(Locale.getDefault());
     }
 
     public static Predicate<Node> hasName(final String name) {
-        return node -> name.equals(node.getNodeName());
+        return node -> {
+            System.err.println("---> " + node);
+            return name.equals(node.getNodeName());
+        };
     }
 
     public static Predicate<Node> hasTextContent(final String content) {
@@ -104,7 +121,7 @@ public class StatementNode {
     }
 
     public static Predicate<Node> childSatisfies(final String path, final Predicate<Node> predicate) {
-        return node -> predicate.test(StatementNode.getSuccessorNode(node, path));
+        return node -> predicate.test(NodeProcessingUtils.getSuccessorNode(node, path));
     }
 
     public static String nodeType(final short nodeType) {
@@ -133,7 +150,7 @@ public class StatementNode {
             spaces = spaces + " ";
         }
         int numberOfPrintedNodes = 1;
-        System.out.println(spaces + "[node type] " + StatementNode.nodeType(node.getNodeType()));
+        System.out.println(spaces + "[node type] " + NodeProcessingUtils.nodeType(node.getNodeType()));
         System.out.println(spaces + "[node name] " + node.getNodeName());
         System.out.println(spaces + "[node value] " + node.getNodeValue());
         System.out.println(spaces + "[node text content] " + node.getTextContent());
@@ -141,37 +158,11 @@ public class StatementNode {
 
         for (int i = 0; i < node.getChildNodes().getLength(); i++) {
             final Node child = node.getChildNodes().item(i);
-            numberOfPrintedNodes += StatementNode.printNode(child, depth + 1);
+            numberOfPrintedNodes += NodeProcessingUtils.printNode(child, depth + 1);
         }
         return numberOfPrintedNodes;
     }
 
-    // Node Search
-
-    // private static boolean testNodeAndFirstChildPredicateChain(Node t, List<Predicate<Node>>
-    // predicates) {
-    // if (predicates.isEmpty()) {
-    // return true;
-    // }
-    // if (!predicates.get(0).test(t)) {
-    // return false;
-    // }
-    // if (predicates.size() == 1) {
-    // return true;
-    // }
-    // if (t.getChildNodes().getLength() == 0) {
-    // return false;
-    // }
-    // return testNodeAndFirstChildPredicateChain(t.getFirstChild(), predicates.subList(1,
-    // predicates.size()));
-    // }
-
-    /*
-     * static private Predicate<Node> nodeAndfirstChildPredicateChain(List<Predicate<Node>>
-     * predicates) { return node -> testNodeAndFirstChildPredicateChain(node, predicates); }
-     */
-
-    // TODO this is not doing the right thing
     public static Node getSuccessorNode(final Node node, final String path) {
         final String firstNumber = StringUtils.substringBefore(path, ",");
         final String nextPath = StringUtils.substringAfter(path, ",");
@@ -183,24 +174,14 @@ public class StatementNode {
         if (nextPath.isEmpty()) {
             return node.getChildNodes().item(childIndex);
         } else {
-            return StatementNode.getSuccessorNode(node.getChildNodes().item(childIndex), nextPath);
+            return NodeProcessingUtils.getSuccessorNode(node.getChildNodes().item(childIndex), nextPath);
         }
     }
 
-    /*
-     * private static ASTNode getFirstChildChain(Node node, int depth) {
-     *
-     * Node result = node;
-     *
-     * for (int i = 0; i < depth; i++) { result = result.getFirstChild(); }
-     *
-     * return new ASTNode(result); }
-     */
-
     // NOTE: Only terminates if nextNode eventually returns null or a matching element.
     private static Node findFirst(final Node parent, final Function<Node, Node> nextNode,
             final Predicate<Node> condition, final boolean includeSelf) {
-        return findFirst(parent, nextNode, condition, includeSelf, null);
+        return NodeProcessingUtils.findFirst(parent, nextNode, condition, includeSelf, null);
     }
 
     // paranthesistypes: contains pairs of "opening paranthesis" and "closed paranthesis"
@@ -219,7 +200,8 @@ public class StatementNode {
             final Predicate<Node> condition, final boolean includeSelf,
             final List<Pair<Predicate<Node>, Predicate<Node>>> paranthesesTypes) {
 
-        final List<Node> result = findAll(parent, nextNode, condition, includeSelf, paranthesesTypes, 1);
+        final List<Node> result = NodeProcessingUtils.findAll(parent, nextNode, condition, includeSelf,
+                paranthesesTypes, 1);
 
         return result.isEmpty() ? null : result.get(0);
     }
@@ -238,9 +220,9 @@ public class StatementNode {
         boolean inParanthesisInterval = false;
         // End if we do not have anywhere to search, or we have reached the limit (where "-1" counts
         // as "no limit").
-        while (current != null && (result.size() < maxElementsToFind || maxElementsToFind == -1)) {
+        while ((current != null) && ((result.size() < maxElementsToFind) || (maxElementsToFind == -1))) {
 
-            if (!inParanthesisInterval && condition.test(current) && (current != parent || includeSelf)) {
+            if (!inParanthesisInterval && condition.test(current) && ((current != parent) || includeSelf)) {
                 result.add(current);
             }
 
@@ -272,71 +254,76 @@ public class StatementNode {
 
     private static boolean hasConnectedWith(final Node parent, final Function<Node, Node> nextNode,
             final Predicate<Node> condition, final boolean includeSelf) {
-        return findFirst(parent, nextNode, condition, includeSelf) != null;
+        return NodeProcessingUtils.findFirst(parent, nextNode, condition, includeSelf) != null;
     }
 
     private static boolean hasLeftSibling(final Node parent, final Predicate<Node> condition,
             final boolean includeSelf) {
-        return hasConnectedWith(parent, node -> node.getPreviousSibling(), condition, includeSelf);
+        return NodeProcessingUtils.hasConnectedWith(parent, node -> node.getPreviousSibling(), condition, includeSelf);
     }
 
     private static Node firstLeftSibling(final Node parent, final Predicate<Node> condition, final boolean includeSelf,
             final List<Pair<Predicate<Node>, Predicate<Node>>> paranthesisTypes) {
-        return findFirst(parent, node -> node.getPreviousSibling(), condition, includeSelf, paranthesisTypes);
+        return NodeProcessingUtils.findFirst(parent, node -> node.getPreviousSibling(), condition, includeSelf,
+                paranthesisTypes);
     }
 
     private static Node firstAncestor(final Node parent, final Predicate<Node> condition, final boolean includeSelf) {
-        return findFirst(parent, node -> node.getParentNode(), condition, includeSelf);
+        return NodeProcessingUtils.findFirst(parent, node -> node.getParentNode(), condition, includeSelf);
     }
 
     public static Set<Node> allDescendents(final Node node, final Predicate<Node> condition,
             final boolean includeSelf) {
-        return addAllDescendentsTo(node, condition, includeSelf, new HashSet<>());
+        return NodeProcessingUtils.addAllDescendentsTo(node, condition, includeSelf, new HashSet<>());
     }
 
     private static <T extends Collection<Node>> T addAllDescendentsTo(final Node node, final Predicate<Node> condition,
             final boolean includeSelf, final T addToThese) {
-
+        System.err.println(">>> " + node);
         if (condition.test(node) && includeSelf) {
             addToThese.add(node);
         }
 
         for (int i = 0; i < node.getChildNodes().getLength(); i++) {
             final Node child = node.getChildNodes().item(i);
-            addAllDescendentsTo(child, condition, true, addToThese);
+            NodeProcessingUtils.addAllDescendentsTo(child, condition, true, addToThese);
         }
 
         return addToThese;
     }
 
     public static String getNameOfOperation(final Node operationStatement) {
-
-        if (StatementNode.isSubroutineStatement.test(operationStatement)) {
-            return StatementNode.getNameOfOperation(operationStatement, StatementNode.isSubroutineName);
-        } else if (StatementNode.isFunctionStatement.test(operationStatement)) {
-            return StatementNode.getNameOfOperation(operationStatement, StatementNode.isFunctionName);
+        if (NodeProcessingUtils.isSubroutineStatement.test(operationStatement)) {
+            return NodeProcessingUtils.getNameOfOperation(operationStatement, NodeProcessingUtils.isSubroutineName);
+        } else if (NodeProcessingUtils.isFunctionStatement.test(operationStatement)) {
+            return NodeProcessingUtils.getNameOfOperation(operationStatement, NodeProcessingUtils.isFunctionName);
+        } else if (NodeProcessingUtils.isEntryStatement.test(operationStatement)) {
+            return NodeProcessingUtils.getNameOfOperation(operationStatement, NodeProcessingUtils.isEntryName);
+        } else if (NodeProcessingUtils.isProgramStatement.test(operationStatement)) {
+            return NodeProcessingUtils.ROOT_PROGRAM;
         }
 
         throw new IllegalArgumentException("Node is neither a function nor a subroutine statement.");
     }
 
     public static String getNameOfOperation(final Node operationStatement, final Predicate<Node> namePredicate) {
-        final Set<Node> nameNodes = allDescendents(operationStatement, namePredicate, true);
-        return ListTools.getUniqueElement(nameNodes).getTextContent();
+        final Set<Node> nameNodes = NodeProcessingUtils.allDescendents(operationStatement, namePredicate, true);
+        return ListTools.getUniqueElement(nameNodes).getTextContent().toLowerCase(Locale.getDefault());
     }
 
     public static <T> Set<T> getDescendentAttributes(final Node node, final Predicate<Node> predicate,
             final Function<Node, T> extractAttribute) throws ParserConfigurationException, SAXException, IOException {
-        return allDescendents(node, predicate, true).stream().map(extractAttribute).collect(Collectors.toSet());
+        return NodeProcessingUtils.allDescendents(node, predicate, true).stream().map(extractAttribute)
+                .collect(Collectors.toSet());
     }
 
     public static List<Pair<String, String>> operationCalls(final Node node, final Predicate<Node> callPredicate,
             final Function<Node, String> calledOperation) {
         final Set<Pair<String, String>> result = new HashSet<>(); // Check for double entries
-        final Set<Node> callStatements = allDescendents(node, callPredicate, true);
+        final Set<Node> callStatements = NodeProcessingUtils.allDescendents(node, callPredicate, true);
         for (final Node callStatement : callStatements) {
             final String callee = calledOperation.apply(callStatement);
-            final String caller = getNameOfContainingOperation(callStatement);
+            final String caller = NodeProcessingUtils.getNameOfContainingOperation(callStatement);
             result.add(new Pair<>(caller, callee));
         }
 
@@ -345,41 +332,44 @@ public class StatementNode {
 
     public static List<Pair<String, String>> subroutineCalls(final Node node)
             throws ParserConfigurationException, SAXException, IOException {
-        return operationCalls(node, StatementNode.isCallStatement.and(StatementNode.isLocalAccess.negate()),
-                subroutineCall -> StatementNode.nameOfCalledOperation(subroutineCall));
+        return NodeProcessingUtils.operationCalls(node,
+                NodeProcessingUtils.isCallStatement.and(NodeProcessingUtils.isLocalAccess.negate()),
+                subroutineCall -> NodeProcessingUtils.nameOfCalledOperation(subroutineCall));
     }
 
     public static List<Pair<String, String>> functionCalls(final Node node)
             throws ParserConfigurationException, SAXException, IOException {
-        return operationCalls(node, StatementNode.namedExpressionAccess.and(StatementNode.isLocalAccess.negate()),
-                functionCall -> StatementNode.nameOfCalledFunction(functionCall));
+        return NodeProcessingUtils.operationCalls(node,
+                NodeProcessingUtils.namedExpressionAccess.and(NodeProcessingUtils.isLocalAccess.negate()),
+                functionCall -> NodeProcessingUtils.nameOfCalledFunction(functionCall));
     }
 
     /** ---------------------------------- */
 
     public static Node findContainingStatement(final Node parent, final Predicate<Node> condition) {
-        return findContainingStatement(parent, condition, null);
+        return NodeProcessingUtils.findContainingStatement(parent, condition, null);
     }
 
     public static Node findContainingStatement(final Node parent, final Predicate<Node> condition,
             final List<Pair<Predicate<Node>, Predicate<Node>>> paranthesisTypes) {
 
-        final Predicate<Node> hasSuchANodeAsLeftSibling = node -> hasLeftSibling(node, condition, false);
-        final Node siblingOfSuchNode = firstAncestor(parent, hasSuchANodeAsLeftSibling, !condition.test(parent));
+        final Predicate<Node> hasSuchANodeAsLeftSibling = node -> NodeProcessingUtils.hasLeftSibling(node, condition,
+                false);
+        final Node siblingOfSuchNode = NodeProcessingUtils.firstAncestor(parent, hasSuchANodeAsLeftSibling,
+                !condition.test(parent));
 
         if (siblingOfSuchNode == null) {
             return null;
         }
 
-        return firstLeftSibling(siblingOfSuchNode, condition, true, paranthesisTypes);
+        return NodeProcessingUtils.firstLeftSibling(siblingOfSuchNode, condition, true, paranthesisTypes);
     }
 
     private static String getNameOfContainingOperation(final Node node) {
-
-        final Node containingOperationStatement = findContainingStatement(node, StatementNode.isOperationStatement,
-                StatementNode.paranthesisTypes);
-        return containingOperationStatement == null ? "<root>"
-                : StatementNode.getNameOfOperation(containingOperationStatement);
+        final Node containingOperationStatement = NodeProcessingUtils.findContainingStatement(node,
+                NodeProcessingUtils.isOperationStatement, NodeProcessingUtils.paranthesisTypes);
+        return containingOperationStatement == null ? NodeProcessingUtils.ROOT_PROGRAM
+                : NodeProcessingUtils.getNameOfOperation(containingOperationStatement);
     }
 
     // We make some assumptions about the structure of the Fortran files (and the generated XML
@@ -395,29 +385,29 @@ public class StatementNode {
 
         final short type = node.getNodeType();
 
-        if (type == Node.TEXT_NODE && node.getChildNodes().getLength() > 0) {
+        if ((type == Node.TEXT_NODE) && (node.getChildNodes().getLength() > 0)) {
             throw new IllegalArgumentException("text node with children");
         }
 
-        if ("call-stmt".equals(node.getNodeName()) && node.getChildNodes().getLength() < 2) {
-            StatementNode.printNode(node, 0);
+        if ("call-stmt".equals(node.getNodeName()) && (node.getChildNodes().getLength() < 2)) {
+            NodeProcessingUtils.printNode(node, 0);
             throw new IllegalArgumentException("call statement with < 2 children");
         }
 
-        if (StatementNode.isNamedExpression.test(node)) {
+        if (NodeProcessingUtils.isNamedExpression.test(node)) {
             // NodeList children = node.getChildNodes();
             final Node firstChild = node.getFirstChild();
             final Node firstGrandChild = firstChild.getFirstChild();
-            if (!StatementNode.isBigN.test(firstChild)) {
+            if (!NodeProcessingUtils.isBigN.test(firstChild)) {
                 throw new IllegalArgumentException("named expression with unexpected type of first child.");
             }
 
-            if (!StatementNode.isSmallN.test(firstGrandChild)) {
+            if (!NodeProcessingUtils.isSmallN.test(firstGrandChild)) {
                 throw new IllegalArgumentException("named expression with unexpected type of first grandchild.");
             }
 
             if (firstGrandChild.getChildNodes().getLength() > 1) {
-                StatementNode.printNode(firstGrandChild, 0);
+                NodeProcessingUtils.printNode(firstGrandChild, 0);
                 throw new IllegalArgumentException(
                         "named expression with unexpected chlildren length list of first grandchild.");
             }
@@ -427,7 +417,7 @@ public class StatementNode {
     }
 
     public int getNumberOfDescendants(final Node parent, final boolean countSelf) {
-        return allDescendents(parent, node -> true, countSelf).size();
+        return NodeProcessingUtils.allDescendents(parent, node -> true, countSelf).size();
     }
 
 }