You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by sg...@apache.org on 2020/02/05 10:07:56 UTC

[freemarker-generator] branch FREEMARKER-129 updated: FREEMARKER-129 Move the tools into "freemarker-generator-tools"

This is an automated email from the ASF dual-hosted git repository.

sgoeschl pushed a commit to branch FREEMARKER-129
in repository https://gitbox.apache.org/repos/asf/freemarker-generator.git


The following commit(s) were added to refs/heads/FREEMARKER-129 by this push:
     new 6a73084  FREEMARKER-129 Move the tools into "freemarker-generator-tools"
6a73084 is described below

commit 6a7308401560f53f7352f31580f6e27806c56711
Author: Siegfried Goeschl <si...@gmail.com>
AuthorDate: Wed Feb 5 11:07:42 2020 +0100

    FREEMARKER-129 Move the tools into "freemarker-generator-tools"
---
 freemarker-generator-cli/pom.xml                   |   5 +-
 .../src/main/config/freemarker-cli.properties      |  24 +-
 .../cli/tools/commonscsv/CommonsCSVTool.java       | 271 ---------------------
 .../cli/tools/commonsexec/CommonsExecTool.java     |  54 ----
 .../generator/cli/tools/excel/ExcelTool.java       | 179 --------------
 .../cli/tools/freemarker/FreeMarkerTool.java       |  53 ----
 .../generator/cli/tools/grok/GrokTool.java         |  36 ---
 .../generator/cli/tools/grok/GrokWrapper.java      |  42 ----
 .../generator/cli/tools/jsonpath/JsonPathTool.java |  45 ----
 .../generator/cli/tools/jsoup/JsoupTool.java       |  38 ---
 .../cli/tools/properties/PropertiesTool.java       |  47 ----
 .../cli/tools/snakeyaml/SnakeYamlTool.java         |  39 ---
 .../generator/cli/tools/system/SystemTool.java     |  96 --------
 .../generator/cli/tools/uuid/UUIDTool.java         |  32 ---
 .../generator/cli/tools/xml/XmlTool.java           |  43 ----
 .../src/main/resources/freemarker-cli.properties   |  24 +-
 .../cli/tools/commonscsv/CommonsCSVToolTest.java   | 153 ------------
 .../cli/tools/commonsexec/CommonsExecToolTest.java |  52 ----
 .../generator/cli/tools/excel/ExcelToolTest.java   | 115 ---------
 .../cli/tools/freemarker/FreeMarkerToolTest.java   |  48 ----
 .../generator/cli/tools/grok/GrokToolTest.java     |  45 ----
 .../cli/tools/jsonpath/JsonPathToolTest.java       |  74 ------
 .../generator/cli/tools/jsoup/JsoupToolTest.java   |  59 -----
 .../cli/tools/properties/PropertiesToolTest.java   |  48 ----
 .../cli/tools/snakeyaml/SnakeYamlToolTest.java     |  61 -----
 .../generator/cli/tools/system/SystemToolTest.java |  44 ----
 .../generator/cli/tools/uuid/UUIDToolTest.java     |  39 ---
 .../generator/cli/tools/xml/XmlToolTest.java       |  62 -----
 pom.xml                                            |   1 +
 29 files changed, 27 insertions(+), 1802 deletions(-)

diff --git a/freemarker-generator-cli/pom.xml b/freemarker-generator-cli/pom.xml
index ea17736..68b27d1 100644
--- a/freemarker-generator-cli/pom.xml
+++ b/freemarker-generator-cli/pom.xml
@@ -180,7 +180,7 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.freemarker.generator</groupId>
-            <artifactId>freemarker-generator-base</artifactId>
+            <artifactId>freemarker-generator-tools</artifactId>
             <version>${project.version}</version>
         </dependency>
         <dependency>
@@ -230,7 +230,6 @@
             <artifactId>commons-exec</artifactId>
             <version>1.3</version>
         </dependency>
-
         <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-csv</artifactId>
@@ -239,7 +238,7 @@
         <dependency>
             <groupId>org.freemarker</groupId>
             <artifactId>freemarker</artifactId>
-            <version>2.3.29</version>
+            <version>${freemarker.version}</version>
         </dependency>
         <!-- Apache POI -->
         <dependency>
diff --git a/freemarker-generator-cli/src/main/config/freemarker-cli.properties b/freemarker-generator-cli/src/main/config/freemarker-cli.properties
index 8222e7a..129015f 100644
--- a/freemarker-generator-cli/src/main/config/freemarker-cli.properties
+++ b/freemarker-generator-cli/src/main/config/freemarker-cli.properties
@@ -23,15 +23,15 @@ freemarker.locale=en_US
 #############################################################################
 # Configure FreeMarker Tools (name -> implementation class)
 #############################################################################
-freemarker.tools.CSVTool=org.apache.freemarker.generator.cli.tools.commonscsv.CommonsCSVTool
-freemarker.tools.ExecTool=org.apache.freemarker.generator.cli.tools.commonsexec.CommonsExecTool
-freemarker.tools.ExcelTool=org.apache.freemarker.generator.cli.tools.excel.ExcelTool
-freemarker.tools.FreeMarkerTool=org.apache.freemarker.generator.cli.tools.freemarker.FreeMarkerTool
-freemarker.tools.GrokTool=org.apache.freemarker.generator.cli.tools.grok.GrokTool
-freemarker.tools.JsonPathTool=org.apache.freemarker.generator.cli.tools.jsonpath.JsonPathTool
-freemarker.tools.JsoupTool=org.apache.freemarker.generator.cli.tools.jsoup.JsoupTool
-freemarker.tools.PropertiesTool=org.apache.freemarker.generator.cli.tools.properties.PropertiesTool
-freemarker.tools.YamlTool=org.apache.freemarker.generator.cli.tools.snakeyaml.SnakeYamlTool
-freemarker.tools.SystemTool=org.apache.freemarker.generator.cli.tools.system.SystemTool
-freemarker.tools.UUIDTool=org.apache.freemarker.generator.cli.tools.uuid.UUIDTool
-freemarker.tools.XmlTool=org.apache.freemarker.generator.cli.tools.xml.XmlTool
+freemarker.tools.CSVTool=org.apache.freemarker.generator.tools.commonscsv.CommonsCSVTool
+freemarker.tools.ExecTool=org.apache.freemarker.generator.tools.commonsexec.CommonsExecTool
+freemarker.tools.ExcelTool=org.apache.freemarker.generator.tools.excel.ExcelTool
+freemarker.tools.FreeMarkerTool=org.apache.freemarker.generator.tools.freemarker.FreeMarkerTool
+freemarker.tools.GrokTool=org.apache.freemarker.generator.tools.grok.GrokTool
+freemarker.tools.JsonPathTool=org.apache.freemarker.generator.tools.jsonpath.JsonPathTool
+freemarker.tools.JsoupTool=org.apache.freemarker.generator.tools.jsoup.JsoupTool
+freemarker.tools.PropertiesTool=org.apache.freemarker.generator.tools.properties.PropertiesTool
+freemarker.tools.YamlTool=org.apache.freemarker.generator.tools.snakeyaml.SnakeYamlTool
+freemarker.tools.SystemTool=org.apache.freemarker.generator.tools.system.SystemTool
+freemarker.tools.UUIDTool=org.apache.freemarker.generator.tools.uuid.UUIDTool
+freemarker.tools.XmlTool=org.apache.freemarker.generator.tools.xml.XmlTool
diff --git a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/commonscsv/CommonsCSVTool.java b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/commonscsv/CommonsCSVTool.java
deleted file mode 100644
index 0470579..0000000
--- a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/commonscsv/CommonsCSVTool.java
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.commonscsv;
-
-import org.apache.commons.csv.CSVFormat;
-import org.apache.commons.csv.CSVParser;
-import org.apache.commons.csv.CSVPrinter;
-import org.apache.commons.csv.CSVRecord;
-import org.apache.commons.io.input.BOMInputStream;
-import org.apache.freemarker.generator.base.document.Document;
-import org.apache.freemarker.generator.base.util.StringUtils;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Writer;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static java.util.Objects.requireNonNull;
-import static java.util.stream.Collectors.toList;
-import static org.apache.commons.io.IOUtils.toInputStream;
-
-public class CommonsCSVTool {
-
-    public CSVParser parse(Document document, CSVFormat format) {
-        if (document == null) {
-            throw new IllegalArgumentException("No document was provided");
-        }
-
-        try {
-            // As stated in the documentation : "If you do not read all records from the given {@code reader},
-            // you should call {@link #close()} on the parser, unless you close the {@code reader}."
-            // The underlying input stream is closed by the document by its "CloseableReaper".
-            final InputStream is = new BOMInputStream(document.getInputStream(), false);
-            return parse(is, document.getCharset(), format);
-        } catch (IOException e) {
-            throw new RuntimeException("Failed to parse CSV: " + document, e);
-        }
-    }
-
-    public CSVParser parse(String csv, CSVFormat format) {
-        if (StringUtils.isEmpty(csv)) {
-            throw new IllegalArgumentException("No CSV was provided");
-        }
-
-        try {
-            // We don't need to close the underyling ByteArrayInputStream
-            return parse(toInputStream(csv, UTF_8), UTF_8, format);
-        } catch (IOException e) {
-            throw new RuntimeException("Failed to parse CSV", e);
-        }
-    }
-
-    public Map<String, CSVFormat> getFormats() {
-        return createCSVFormats();
-    }
-
-    /**
-     * Get a CSVPrinter using the FreeMarker's writer instance.
-     *
-     * @param csvFormat CSV format to use for writing records
-     * @param writer    Writer to receive the CSV output
-     * @return CSVPrinter instance
-     * @throws IOException thrown if the parameters of the format are inconsistent or if either out or format are null.
-     */
-    public CSVPrinter printer(CSVFormat csvFormat, Writer writer) throws IOException {
-        // We do not close the CSVPrinter but the underlying writer at the of processing
-        return new CSVPrinter(writer, csvFormat);
-    }
-
-    /**
-     * Extract the list of unique values (keys) of the column "name".
-     *
-     * @param records records to process
-     * @param name    column name to process
-     * @return unique keys
-     */
-    public List<String> toKeys(Collection<CSVRecord> records, String name) {
-        return toKeys(records, new ValueResolver(name));
-    }
-
-    /**
-     * Extract the list of unique values (keys) of the column with the given index..
-     *
-     * @param records records to process
-     * @param index   column index to map
-     * @return unique keys
-     */
-    public List<String> toKeys(Collection<CSVRecord> records, Integer index) {
-        return toKeys(records, new ValueResolver(index));
-    }
-
-    /**
-     * Map the given value of the CVS record into (key to record). If duplicates
-     * are encountered return the first occurence of the CVS record. The map
-     * retains the insertion order of they keys.
-     *
-     * @param records records to process
-     * @param name    column name to map
-     * @return map of records
-     */
-    public Map<String, CSVRecord> toMap(Collection<CSVRecord> records, String name) {
-        return toMap(records, new ValueResolver(name));
-    }
-
-    /**
-     * Map the given value of the CVS record into (key to record). If duplicates
-     * are encountered return the first occurence of the CVS record. The map
-     * retains the insertion order of they keys.
-     *
-     * @param records records to process
-     * @param index   column index to map
-     * @return map of records
-     */
-    public Map<String, CSVRecord> toMap(Collection<CSVRecord> records, Integer index) {
-        return toMap(records, new ValueResolver(index));
-    }
-
-    /**
-     * Map the given value of the CVS record into a list of records.
-     *
-     * @param records records to process
-     * @param name    column name to map
-     * @return map of records
-     */
-    public Map<String, List<CSVRecord>> toMultiMap(Collection<CSVRecord> records, String name) {
-        return toMultiMap(records, new ValueResolver(name));
-    }
-
-    /**
-     * Map the given value of the CVS record into a list of records.
-     *
-     * @param records records to process
-     * @param index   column index to map
-     * @return map of records
-     */
-    public Map<String, List<CSVRecord>> toMultiMap(Collection<CSVRecord> records, Integer index) {
-        return toMultiMap(records, new ValueResolver(index));
-    }
-
-    /**
-     * Maps the sybmolic name of a delimiter to a single character since it
-     * is not possible to define commony used delimiters on the command line.
-     *
-     * @param name symbolic name of delimiter
-     * @return CSV delimiter
-     */
-    public char toDelimiter(String name) {
-        if (name == null || name.isEmpty()) {
-            throw new IllegalArgumentException("Now CSV delimiter provided");
-        }
-
-        switch (name.toUpperCase().trim()) {
-            case "COMMA":
-                return ',';
-            case "HASH":
-                return '#';
-            case "PIPE":
-                return '|';
-            case "RS":
-                return 30;
-            case "SEMICOLON":
-                return ';';
-            case "SPACE":
-                return ' ';
-            case "TAB":
-                return '\t';
-            default:
-                if (name.length() == 1) {
-                    return name.charAt(0);
-                } else {
-                    throw new IllegalArgumentException("Unsupported CSV delimiter: " + name);
-                }
-        }
-    }
-
-    private static CSVParser parse(InputStream is, Charset charset, CSVFormat format) throws IOException {
-        if (is == null) {
-            throw new IllegalArgumentException("No input stream was provided");
-        }
-
-        // As stated in the documentation : "If you do not read all records from the given {@code reader},
-        // you should call {@link #close()} on the parser, unless you close the {@code reader}."
-        return CSVParser.parse(is, charset, format);
-    }
-
-    private static List<String> toKeys(Collection<CSVRecord> csvRecords, Function<CSVRecord, String> value) {
-        return csvRecords.stream()
-                .map(value)
-                .distinct()
-                .collect(toList());
-    }
-
-    private static Map<String, CSVRecord> toMap(Collection<CSVRecord> records, Function<CSVRecord, String> value) {
-        return records.stream()
-                .collect(Collectors.toMap(
-                        value,
-                        record -> record,
-                        (firstKey, currentKey) -> firstKey,
-                        LinkedHashMap::new
-                ));
-    }
-
-    private static Map<String, List<CSVRecord>> toMultiMap(Collection<CSVRecord> records, Function<CSVRecord, String> value) {
-        final Map<String, List<CSVRecord>> result = new LinkedHashMap<>();
-        final List<String> keys = toKeys(records, value);
-        keys.forEach(key -> result.put(key, new ArrayList<>()));
-        records.forEach(record -> result.get(value.apply(record)).add(record));
-        return result;
-    }
-
-    private static Map<String, CSVFormat> createCSVFormats() {
-        final Map<String, CSVFormat> result = new HashMap<>();
-        result.put("DEFAULT", CSVFormat.DEFAULT);
-        result.put("EXCEL", CSVFormat.EXCEL);
-        result.put("INFORMIX_UNLOAD", CSVFormat.INFORMIX_UNLOAD);
-        result.put("INFORMIX_UNLOAD_CSV", CSVFormat.INFORMIX_UNLOAD_CSV);
-        result.put("MONGODB_CSV", CSVFormat.MONGODB_CSV);
-        result.put("MONGODB_TSV", CSVFormat.MONGODB_TSV);
-        result.put("MYSQL", CSVFormat.MYSQL);
-        result.put("RFC4180", CSVFormat.RFC4180);
-        result.put("ORACLE", CSVFormat.ORACLE);
-        result.put("POSTGRESQL_CSV", CSVFormat.POSTGRESQL_CSV);
-        result.put("POSTGRESQL_TEXT", CSVFormat.POSTGRESQL_TEXT);
-        result.put("TDF", CSVFormat.TDF);
-        return result;
-    }
-
-    private static final class ValueResolver implements Function<CSVRecord, String> {
-
-        private final Integer index;
-        private final String name;
-
-        ValueResolver(Integer index) {
-            this.index = requireNonNull(index);
-            this.name = null;
-        }
-
-        ValueResolver(String name) {
-            this.index = null;
-            this.name = requireNonNull(name);
-        }
-
-        @Override
-        public String apply(CSVRecord record) {
-            return index != null ? record.get(index) : record.get(name);
-        }
-    }
-}
diff --git a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/commonsexec/CommonsExecTool.java b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/commonsexec/CommonsExecTool.java
deleted file mode 100644
index bef411c..0000000
--- a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/commonsexec/CommonsExecTool.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.commonsexec;
-
-import org.apache.commons.exec.CommandLine;
-import org.apache.commons.exec.DefaultExecutor;
-import org.apache.commons.exec.Executor;
-import org.apache.commons.exec.PumpStreamHandler;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.List;
-
-public class CommonsExecTool {
-
-    public String execute(String line) {
-        return execute(CommandLine.parse(line));
-    }
-
-    public String execute(String executable, List<String> args) {
-        return execute(commandLine(executable, args));
-    }
-
-    private String execute(CommandLine commandLine) {
-        try (ByteArrayOutputStream boas = new ByteArrayOutputStream()) {
-            final Executor executor = new DefaultExecutor();
-            executor.setStreamHandler(new PumpStreamHandler(boas));
-            executor.execute(commandLine);
-            return boas.toString();
-        } catch (IOException e) {
-            throw new RuntimeException("Executing command failed: " + commandLine, e);
-        }
-    }
-
-    private static CommandLine commandLine(String executable, List<String> args) {
-        final CommandLine cmdLine = new CommandLine(executable);
-        cmdLine.addArguments(args.toArray(new String[0]));
-        return cmdLine;
-    }
-}
diff --git a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/excel/ExcelTool.java b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/excel/ExcelTool.java
deleted file mode 100644
index 7e14232..0000000
--- a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/excel/ExcelTool.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.excel;
-
-import org.apache.freemarker.generator.base.document.Document;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellType;
-import org.apache.poi.ss.usermodel.DataFormatter;
-import org.apache.poi.ss.usermodel.DateUtil;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.text.SimpleDateFormat;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-
-import static org.apache.poi.ss.usermodel.Row.MissingCellPolicy.CREATE_NULL_AS_BLANK;
-
-/**
- * Parse Excel documents (XLS &amp; XLSX) using Apache POI.
- */
-public class ExcelTool {
-
-    private static final boolean EMULATE_CSV = true;
-    private static final SimpleDateFormat TIME_DATE_FORMAT = new SimpleDateFormat("HH:mm:ss");
-    private static final SimpleDateFormat YEAR_TIME_FORMAT = new SimpleDateFormat("yyyy");
-
-    public Workbook parse(Document document) {
-        try (InputStream is = document.getUnsafeInputStream()) {
-            final Workbook workbook = WorkbookFactory.create(is);
-            // make sure that the workbook is closed together with the document
-            return document.addClosable(workbook);
-        } catch (IOException e) {
-            throw new RuntimeException("Failed to parse Ecxel document: " + document, e);
-        }
-    }
-
-    /**
-     * Get all sheets of a workbook.
-     *
-     * @param workbook The workbook
-     * @return Sheets of the workbook
-     */
-    public List<Sheet> getSheets(Workbook workbook) {
-        final List<Sheet> result = new ArrayList<>();
-        for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
-            result.add(workbook.getSheetAt(i));
-        }
-        return result;
-    }
-
-    /**
-     * Transform the Excel sheet into a table. Please not that locales are mostly
-     * ignored by Apache POI (see https://poi.apache.org/apidocs/dev/org/apache/poi/ss/usermodel/DataFormatter.html)
-     *
-     * @param sheet Excel sheet
-     * @return Table containing formatted cell values as strings
-     */
-    public List<List<String>> toTable(Sheet sheet) {
-        final DataFormatter dataFormatter = dataFormatter();
-        final Iterator<Row> iterator = sheet.iterator();
-        final List<List<String>> result = new ArrayList<>();
-
-        while (iterator.hasNext()) {
-            final Row row = iterator.next();
-            result.add(toColumns(row, dataFormatter));
-        }
-
-        return result;
-    }
-
-    /**
-     * EXPERIMENTAL FEATURE
-     * <p>
-     * Transform the sheet to table contaning raw Java objects, e.g. Date, Double, ...
-     *
-     * @param sheet Excel sheet
-     * @return Table containing cells as raw Java objects
-     */
-    public List<List<Object>> toRawTable(Sheet sheet) {
-        final DataFormatter dataFormatter = dataFormatter();
-        final Iterator<Row> iterator = sheet.iterator();
-        final List<List<Object>> result = new ArrayList<>();
-
-        while (iterator.hasNext()) {
-            final Row row = iterator.next();
-            result.add(toRawColumns(row, dataFormatter));
-        }
-
-        return result;
-    }
-
-    private static List<String> toColumns(Row row, DataFormatter dataFormatter) {
-        final List<String> columnValues = new ArrayList<>();
-        for (int columnIndex = 0; columnIndex < row.getLastCellNum(); columnIndex++) {
-            final Cell cell = row.getCell(columnIndex, CREATE_NULL_AS_BLANK);
-            final String formatedCellValue = dataFormatter.formatCellValue(cell).trim();
-            columnValues.add(formatedCellValue);
-        }
-        return columnValues;
-    }
-
-    private static List<Object> toRawColumns(Row row, DataFormatter dataFormatter) {
-        final List<Object> columnValues = new ArrayList<>();
-        for (int columnIndex = 0; columnIndex < row.getLastCellNum(); columnIndex++) {
-            final Cell cell = row.getCell(columnIndex, CREATE_NULL_AS_BLANK);
-            final Object cellValue = toCellValue(cell, dataFormatter);
-            columnValues.add(cellValue);
-        }
-        return columnValues;
-    }
-
-    private static Object toCellValue(Cell cell, DataFormatter formatter) {
-        final CellType cellType = cell.getCellType();
-        switch (cellType) {
-            case BOOLEAN:
-                return cell.getBooleanCellValue();
-            case NUMERIC:
-                return DateUtil.isCellDateFormatted(cell) ? toDateCellValue(cell) : cell.getNumericCellValue();
-            default:
-                return formatter.formatCellValue(cell);
-        }
-    }
-
-    /**
-     * Try desperately to make sense out of Excel and its handling of dates.
-     * See https://stackoverflow.com/questions/15710888/reading-time-values-from-spreadsheet-using-poi-api.
-     *
-     * @param cell Cell containing some sort of date or time
-     * @return The corresponding Java istance
-     */
-    private static synchronized Object toDateCellValue(Cell cell) {
-        final Date date = cell.getDateCellValue();
-
-        // "Time-only" values have date set to 31-Dec-1899 so if year is "1899"
-        // you can assume it is a "time-only" value
-        final String year = YEAR_TIME_FORMAT.format(date);
-
-        if (year.equals("1899")) {
-            // handle "Time-only" value
-            return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()).toLocalTime();
-        } else {
-            // here you may have a date-only or date-time value
-            final String timeStamp = TIME_DATE_FORMAT.format(date);
-            if (timeStamp.equals("00:00:00")) {
-                // if time is 00:00:00 you can assume it is a date only value (but it could be midnight)
-                return new java.sql.Date(date.getTime()).toLocalDate();
-            } else {
-                return date;
-            }
-        }
-    }
-
-    private static DataFormatter dataFormatter() {
-        return new DataFormatter(EMULATE_CSV);
-    }
-}
diff --git a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/freemarker/FreeMarkerTool.java b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/freemarker/FreeMarkerTool.java
deleted file mode 100644
index 8ab67d6..0000000
--- a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/freemarker/FreeMarkerTool.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.freemarker;
-
-import freemarker.ext.beans.BeansWrapper;
-import freemarker.ext.beans.BeansWrapperBuilder;
-import freemarker.template.Configuration;
-import freemarker.template.TemplateHashModel;
-import freemarker.template.utility.ObjectConstructor;
-
-public class FreeMarkerTool {
-
-    private volatile BeansWrapper beansWrapper;
-    private volatile ObjectConstructor objectConstructor;
-
-    public synchronized ObjectConstructor getObjectConstructor() {
-        if (objectConstructor == null) {
-            objectConstructor = new ObjectConstructor();
-        }
-        return objectConstructor;
-    }
-
-    public synchronized BeansWrapper getBeansWrapper() {
-        if (beansWrapper == null) {
-            beansWrapper = new BeansWrapperBuilder(Configuration.VERSION_2_3_29).build();
-        }
-        return beansWrapper;
-    }
-
-    public TemplateHashModel getEnums() {
-        return getBeansWrapper().getEnumModels();
-    }
-
-    public TemplateHashModel getStatics() {
-        return getBeansWrapper().getStaticModels();
-    }
-}
-
-
diff --git a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/grok/GrokTool.java b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/grok/GrokTool.java
deleted file mode 100644
index 0023e6c..0000000
--- a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/grok/GrokTool.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.grok;
-
-import io.krakens.grok.api.Grok;
-import io.krakens.grok.api.GrokCompiler;
-
-public class GrokTool {
-
-    private static final String DEFAULT_PATTERN = "/patterns/patterns";
-
-    public GrokWrapper compile(String pattern) {
-        return compile(DEFAULT_PATTERN, pattern);
-    }
-
-    public GrokWrapper compile(String path, String pattern) {
-        final GrokCompiler grokCompiler = GrokCompiler.newInstance();
-        grokCompiler.registerPatternFromClasspath(path);
-        final Grok grok = grokCompiler.compile(pattern);
-        return new GrokWrapper(grok);
-    }
-}
diff --git a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/grok/GrokWrapper.java b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/grok/GrokWrapper.java
deleted file mode 100644
index f1205a1..0000000
--- a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/grok/GrokWrapper.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.grok;
-
-import io.krakens.grok.api.Grok;
-import org.apache.freemarker.generator.base.util.StringUtils;
-
-import java.util.Collections;
-import java.util.Map;
-
-import static java.util.Objects.requireNonNull;
-
-public class GrokWrapper {
-
-    private final Grok grok;
-
-    public GrokWrapper(Grok grok) {
-        this.grok = requireNonNull(grok);
-    }
-
-    public Map<String, Object> match(String line) {
-        if (StringUtils.isEmpty(line)) {
-            return Collections.emptyMap();
-        }
-
-        return grok.match(line).capture();
-    }
-}
diff --git a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/jsonpath/JsonPathTool.java b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/jsonpath/JsonPathTool.java
deleted file mode 100644
index 543b57f..0000000
--- a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/jsonpath/JsonPathTool.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.jsonpath;
-
-import com.jayway.jsonpath.Configuration;
-import com.jayway.jsonpath.DocumentContext;
-import com.jayway.jsonpath.JsonPath;
-import com.jayway.jsonpath.Option;
-import org.apache.freemarker.generator.base.document.Document;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-public class JsonPathTool {
-
-    public DocumentContext parse(Document document) throws IOException {
-        try (InputStream is = document.getUnsafeInputStream()) {
-            return JsonPath.using(configuration()).parse(is);
-        }
-    }
-
-    public DocumentContext parse(String json) {
-        return JsonPath.using(configuration()).parse(json);
-    }
-
-    private Configuration configuration() {
-        return Configuration.builder()
-                .options(Option.SUPPRESS_EXCEPTIONS)
-                .build();
-    }
-}
diff --git a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/jsoup/JsoupTool.java b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/jsoup/JsoupTool.java
deleted file mode 100644
index b6eb9fb..0000000
--- a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/jsoup/JsoupTool.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.jsoup;
-
-import org.apache.freemarker.generator.base.document.Document;
-import org.jsoup.Jsoup;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-public class JsoupTool {
-
-    public org.jsoup.nodes.Document parse(Document document) {
-        try (InputStream is = document.getUnsafeInputStream()) {
-            return Jsoup.parse(is, document.getCharset().name(), "");
-        } catch (IOException e) {
-            throw new RuntimeException("Failed to parse HTML document: " + document, e);
-        }
-    }
-
-    public org.jsoup.nodes.Document parse(String html) {
-        return Jsoup.parse(html);
-    }
-}
diff --git a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/properties/PropertiesTool.java b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/properties/PropertiesTool.java
deleted file mode 100644
index 80f6d37..0000000
--- a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/properties/PropertiesTool.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.properties;
-
-import org.apache.freemarker.generator.base.document.Document;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StringReader;
-import java.util.Properties;
-
-public class PropertiesTool {
-
-    public Properties parse(Document document) {
-        try (InputStream is = document.getUnsafeInputStream()) {
-            final Properties properties = new Properties();
-            properties.load(is);
-            return properties;
-        } catch (IOException e) {
-            throw new RuntimeException("Failed to parse properties: " + document, e);
-        }
-    }
-
-    public Properties parse(String value) {
-        try (StringReader reader = new StringReader(value)) {
-            final Properties properties = new Properties();
-            properties.load(reader);
-            return properties;
-        } catch (IOException e) {
-            throw new RuntimeException("Failed to parse properties: " + value, e);
-        }
-    }
-}
diff --git a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/snakeyaml/SnakeYamlTool.java b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/snakeyaml/SnakeYamlTool.java
deleted file mode 100644
index 6494b7c..0000000
--- a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/snakeyaml/SnakeYamlTool.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.snakeyaml;
-
-import org.apache.freemarker.generator.base.document.Document;
-import org.yaml.snakeyaml.Yaml;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Map;
-
-public class SnakeYamlTool {
-
-    public Map<String, Object> parse(Document document) {
-        try (InputStream is = document.getUnsafeInputStream()) {
-            return new Yaml().load(is);
-        } catch (IOException e) {
-            throw new RuntimeException("Failed to load YAML document: " + document, e);
-        }
-    }
-
-    public Map<String, Object> parse(String value) {
-        return new Yaml().load(value);
-    }
-}
diff --git a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/system/SystemTool.java b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/system/SystemTool.java
deleted file mode 100644
index 626ca2c..0000000
--- a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/system/SystemTool.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.system;
-
-import java.io.File;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import static java.util.Collections.emptyList;
-import static java.util.Objects.requireNonNull;
-
-/**
- * Provides system related functionality, e.g. accessing environment variable,
- * system properties, hostname, ...
- */
-@SuppressWarnings("unchecked")
-public class SystemTool {
-
-    private final List<String> commandLineArgs;
-    private final List<File> templateDirectories;
-
-    public SystemTool() {
-        this.commandLineArgs = emptyList();
-        this.templateDirectories = emptyList();
-    }
-
-    public SystemTool(Map<String, Object> settings) {
-        requireNonNull(settings);
-        this.commandLineArgs = (List<String>) settings.getOrDefault("freemarker.cli.args", emptyList());
-        this.templateDirectories = (List<File>) settings.getOrDefault("freemarker.template.directories", emptyList());
-    }
-
-    public List<String> getCommandLineArgs() {
-        return commandLineArgs;
-    }
-
-    public List<File> getTemplateDirectories() {
-        return templateDirectories;
-    }
-
-    public Properties getProperties() {
-        return (Properties) AccessController.doPrivileged((PrivilegedAction) System::getProperties);
-    }
-
-    public String getProperty(String key) {
-        return (String) AccessController.doPrivileged((PrivilegedAction) () -> System.getProperty(key));
-    }
-
-    public String getProperty(String key, String def) {
-        return (String) AccessController.doPrivileged((PrivilegedAction) () -> System.getProperty(key, def));
-    }
-
-    public Map<String, String> getEnvs() {
-        return (Map<String, String>) AccessController.doPrivileged((PrivilegedAction) System::getenv);
-    }
-
-    public String getEnv(String name) {
-        return (String) AccessController.doPrivileged((PrivilegedAction) () -> System.getenv(name));
-    }
-
-    public String getEnv(String name, String def) {
-        final String env = this.getEnv(name);
-        return env != null ? env : def;
-    }
-
-    public String getHostName() {
-        try {
-            return InetAddress.getLocalHost().getHostName();
-        } catch (UnknownHostException ignored) {
-            return "localhost";
-        }
-    }
-
-    public long currentTimeMillis() {
-        return System.currentTimeMillis();
-    }
-}
diff --git a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/uuid/UUIDTool.java b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/uuid/UUIDTool.java
deleted file mode 100644
index cb7203d..0000000
--- a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/uuid/UUIDTool.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.uuid;
-
-import java.util.UUID;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-public class UUIDTool {
-
-    public UUID randomUUID() {
-        return UUID.randomUUID();
-    }
-
-    public UUID namedUUID(String name) {
-        return UUID.nameUUIDFromBytes(name.getBytes(UTF_8));
-    }
-}
diff --git a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/xml/XmlTool.java b/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/xml/XmlTool.java
deleted file mode 100644
index 9980391..0000000
--- a/freemarker-generator-cli/src/main/java/org/apache/freemarker/generator/cli/tools/xml/XmlTool.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.xml;
-
-import freemarker.ext.dom.NodeModel;
-import org.apache.freemarker.generator.base.document.Document;
-import org.xml.sax.InputSource;
-
-import java.io.InputStream;
-import java.io.StringReader;
-
-public class XmlTool {
-
-    public NodeModel parse(Document document) {
-        try (InputStream is = document.getUnsafeInputStream()) {
-            return NodeModel.parse(new InputSource(is));
-        } catch (Exception e) {
-            throw new RuntimeException("Failed to parse XML document: " + document, e);
-        }
-    }
-
-    public NodeModel parse(String value) {
-        try (StringReader reader = new StringReader(value)) {
-            return NodeModel.parse(new InputSource(reader));
-        } catch (Exception e) {
-            throw new RuntimeException("Failed to parse XML document: " + value, e);
-        }
-    }
-}
diff --git a/freemarker-generator-cli/src/main/resources/freemarker-cli.properties b/freemarker-generator-cli/src/main/resources/freemarker-cli.properties
index 8222e7a..129015f 100644
--- a/freemarker-generator-cli/src/main/resources/freemarker-cli.properties
+++ b/freemarker-generator-cli/src/main/resources/freemarker-cli.properties
@@ -23,15 +23,15 @@ freemarker.locale=en_US
 #############################################################################
 # Configure FreeMarker Tools (name -> implementation class)
 #############################################################################
-freemarker.tools.CSVTool=org.apache.freemarker.generator.cli.tools.commonscsv.CommonsCSVTool
-freemarker.tools.ExecTool=org.apache.freemarker.generator.cli.tools.commonsexec.CommonsExecTool
-freemarker.tools.ExcelTool=org.apache.freemarker.generator.cli.tools.excel.ExcelTool
-freemarker.tools.FreeMarkerTool=org.apache.freemarker.generator.cli.tools.freemarker.FreeMarkerTool
-freemarker.tools.GrokTool=org.apache.freemarker.generator.cli.tools.grok.GrokTool
-freemarker.tools.JsonPathTool=org.apache.freemarker.generator.cli.tools.jsonpath.JsonPathTool
-freemarker.tools.JsoupTool=org.apache.freemarker.generator.cli.tools.jsoup.JsoupTool
-freemarker.tools.PropertiesTool=org.apache.freemarker.generator.cli.tools.properties.PropertiesTool
-freemarker.tools.YamlTool=org.apache.freemarker.generator.cli.tools.snakeyaml.SnakeYamlTool
-freemarker.tools.SystemTool=org.apache.freemarker.generator.cli.tools.system.SystemTool
-freemarker.tools.UUIDTool=org.apache.freemarker.generator.cli.tools.uuid.UUIDTool
-freemarker.tools.XmlTool=org.apache.freemarker.generator.cli.tools.xml.XmlTool
+freemarker.tools.CSVTool=org.apache.freemarker.generator.tools.commonscsv.CommonsCSVTool
+freemarker.tools.ExecTool=org.apache.freemarker.generator.tools.commonsexec.CommonsExecTool
+freemarker.tools.ExcelTool=org.apache.freemarker.generator.tools.excel.ExcelTool
+freemarker.tools.FreeMarkerTool=org.apache.freemarker.generator.tools.freemarker.FreeMarkerTool
+freemarker.tools.GrokTool=org.apache.freemarker.generator.tools.grok.GrokTool
+freemarker.tools.JsonPathTool=org.apache.freemarker.generator.tools.jsonpath.JsonPathTool
+freemarker.tools.JsoupTool=org.apache.freemarker.generator.tools.jsoup.JsoupTool
+freemarker.tools.PropertiesTool=org.apache.freemarker.generator.tools.properties.PropertiesTool
+freemarker.tools.YamlTool=org.apache.freemarker.generator.tools.snakeyaml.SnakeYamlTool
+freemarker.tools.SystemTool=org.apache.freemarker.generator.tools.system.SystemTool
+freemarker.tools.UUIDTool=org.apache.freemarker.generator.tools.uuid.UUIDTool
+freemarker.tools.XmlTool=org.apache.freemarker.generator.tools.xml.XmlTool
diff --git a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/commonscsv/CommonsCSVToolTest.java b/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/commonscsv/CommonsCSVToolTest.java
deleted file mode 100644
index 804766d..0000000
--- a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/commonscsv/CommonsCSVToolTest.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.commonscsv;
-
-import org.apache.commons.csv.CSVFormat;
-import org.apache.commons.csv.CSVParser;
-import org.apache.commons.csv.CSVPrinter;
-import org.apache.commons.csv.CSVRecord;
-import org.apache.freemarker.generator.base.document.Document;
-import org.apache.freemarker.generator.base.document.DocumentFactory;
-import org.junit.Test;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.List;
-import java.util.Map;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static junit.framework.TestCase.assertEquals;
-import static junit.framework.TestCase.assertNotNull;
-import static junit.framework.TestCase.assertTrue;
-import static org.apache.commons.csv.CSVFormat.DEFAULT;
-import static org.apache.commons.csv.CSVFormat.EXCEL;
-
-public class CommonsCSVToolTest {
-
-    private static final String ANY_KEY = "C71";
-    private static final String CONTRACT_ID = "contract_id";
-    private static final int CONTRACT_ID_IDX = 0;
-    private static final File BOM_CSV = new File("./site/sample/csv/excel-export-utf8.csv");
-    private static final File TEST_CSV = new File("./site/sample/csv/contract.csv");
-
-    @Test
-    public void shallParseCvsFile() throws IOException {
-        try (CSVParser parser = commonsCsvTool().parse(document(), DEFAULT.withHeader())) {
-            assertNotNull(parser);
-            assertEquals(32, parser.getHeaderMap().size());
-            assertEquals(22, parser.getRecords().size());
-        }
-    }
-
-    @Test
-    public void shallParseCvsString() throws IOException {
-        try (CSVParser parser = commonsCsvTool().parse(document().getText(), DEFAULT.withHeader())) {
-            assertNotNull(parser);
-            assertEquals(32, parser.getHeaderMap().size());
-            assertEquals(22, parser.getRecords().size());
-        }
-    }
-
-    @Test
-    public void shallGetKeysFromCsvRecords() throws IOException {
-        final CommonsCSVTool commonsCsvTool = commonsCsvTool();
-        final List<String> keys;
-
-        try (CSVParser parser = commonsCsvTool.parse(document(), DEFAULT.withHeader())) {
-            keys = commonsCsvTool.toKeys(parser.getRecords(), CONTRACT_ID);
-        }
-
-        assertEquals(7, keys.size());
-        assertEquals(7, keys.size());
-        assertEquals("C71", keys.get(0));
-        assertEquals("C72", keys.get(1));
-        assertEquals("C73", keys.get(2));
-        assertEquals("C74", keys.get(3));
-        assertEquals("C75", keys.get(4));
-        assertEquals("C76", keys.get(5));
-        assertEquals("C78", keys.get(6));
-    }
-
-    @Test
-    public void shallCreateMapFromCsvRecords() throws IOException {
-        final CommonsCSVTool commonsCsvTool = commonsCsvTool();
-        final Map<String, CSVRecord> map;
-
-        try (CSVParser parser = commonsCsvTool.parse(document(), DEFAULT.withHeader())) {
-            map = commonsCsvTool.toMap(parser.getRecords(), CONTRACT_ID);
-        }
-
-        assertEquals(7, map.size());
-        assertEquals(ANY_KEY, map.get(ANY_KEY).get(CONTRACT_ID_IDX));
-    }
-
-    @Test
-    public void shallCreateMultiMapFromCsvRecords() throws IOException {
-        final CommonsCSVTool commonsCsvTool = commonsCsvTool();
-        final Map<String, List<CSVRecord>> map;
-
-        try (CSVParser parser = commonsCsvTool.parse(document(), DEFAULT.withHeader())) {
-            map = commonsCsvTool.toMultiMap(parser.getRecords(), CONTRACT_ID);
-        }
-
-        assertEquals(7, map.size());
-        assertEquals(ANY_KEY, map.get(ANY_KEY).get(0).get(CONTRACT_ID_IDX));
-    }
-
-    @Test
-    public void shallPrintCsvRecords() throws IOException {
-        final CommonsCSVTool commonsCsvTool = commonsCsvTool();
-        final CSVFormat cvsFormat = DEFAULT.withHeader();
-        final Writer writer = new StringWriter();
-
-        try (CSVParser parser = commonsCsvTool.parse(document(), cvsFormat)) {
-            try (CSVPrinter printer = commonsCsvTool.printer(cvsFormat, writer)) {
-                printer.printRecord(parser.getHeaderMap());
-            }
-        }
-
-        assertTrue(writer.toString().contains(CONTRACT_ID));
-    }
-
-    @Test
-    public void shallStripBomFromCsvFile() throws IOException {
-        try (CSVParser parser = commonsCsvTool().parse(document(BOM_CSV), EXCEL.withHeader().withDelimiter(';'))) {
-            assertEquals("Text", parser.getHeaderNames().get(0));
-        }
-    }
-
-    @Test
-    public void shallConvertToCsvDelimiter() {
-        assertEquals(' ', commonsCsvTool().toDelimiter("space"));
-        assertEquals(' ', commonsCsvTool().toDelimiter("SPACE"));
-        assertEquals('^', commonsCsvTool().toDelimiter("^"));
-    }
-
-    private Document document() {
-        return document(TEST_CSV);
-    }
-
-    private Document document(File file) {
-        return DocumentFactory.create(file, UTF_8);
-    }
-
-    private CommonsCSVTool commonsCsvTool() {
-        return new CommonsCSVTool();
-    }
-}
diff --git a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/commonsexec/CommonsExecToolTest.java b/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/commonsexec/CommonsExecToolTest.java
deleted file mode 100644
index 6ee2cf3..0000000
--- a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/commonsexec/CommonsExecToolTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.commonsexec;
-
-import org.junit.Test;
-
-import java.util.Collections;
-
-import static junit.framework.TestCase.assertFalse;
-
-public class CommonsExecToolTest {
-
-    // The "date" command should work on all platforms
-    private static final String ANY_EXECUTABLE = "date";
-
-    @Test
-    public void shallExecuteCommand() {
-        final String result = commonsExecTool().execute(ANY_EXECUTABLE, Collections.emptyList());
-
-        assertFalse(result.isEmpty());
-    }
-
-    @Test
-    public void shallExecuteCommandLine() {
-        final String result = commonsExecTool().execute(ANY_EXECUTABLE);
-
-        assertFalse(result.isEmpty());
-    }
-
-    @Test(expected = RuntimeException.class)
-    public void shallThrowExecptionForUnknownCommand() {
-        commonsExecTool().execute("does-not-exist");
-    }
-
-    private CommonsExecTool commonsExecTool() {
-        return new CommonsExecTool();
-    }
-}
diff --git a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/excel/ExcelToolTest.java b/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/excel/ExcelToolTest.java
deleted file mode 100644
index b39bd40..0000000
--- a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/excel/ExcelToolTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.excel;
-
-import org.apache.freemarker.generator.base.document.Document;
-import org.apache.freemarker.generator.base.document.DocumentFactory;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.junit.Test;
-
-import java.io.File;
-import java.util.List;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static junit.framework.TestCase.assertEquals;
-
-public class ExcelToolTest {
-
-    private final File TEST_XLS = new File("./site/sample/excel/test.xls");
-    private final File TEST_XLSX = new File("./site/sample/excel/test.xlsx");
-    private final File MULTIPLE_SHEETS_XSLX_FILE = new File("./site/sample/excel/test-multiple-sheets.xlsx");
-
-    @Test
-    public void shallParseXlsFile() {
-        final Workbook workbook = workbook(TEST_XLS);
-
-        final List<Sheet> sheets = excelTool().getSheets(workbook);
-        final List<List<String>> records = excelTool().toTable(sheets.get(0));
-
-        assertEquals(1, sheets.size());
-        assertEquals(3, records.size());
-    }
-
-    @Test
-    public void shallParseXlsxFile() {
-        final Workbook workbook = workbook(TEST_XLSX);
-
-        final List<Sheet> sheets = excelTool().getSheets(workbook);
-        final List<List<String>> records = excelTool().toTable(sheets.get(0));
-
-        assertEquals(1, sheets.size());
-        assertEquals(3, records.size());
-    }
-
-    @Test
-    public void shallParseMultiSheetExcel() {
-        final Workbook workbook = workbook(MULTIPLE_SHEETS_XSLX_FILE);
-
-        final List<Sheet> sheets = excelTool().getSheets(workbook);
-
-        assertEquals(2, sheets.size());
-        assertEquals(3, excelTool().toTable(sheets.get(0)).size());
-        assertEquals(2, excelTool().toTable(sheets.get(1)).size());
-    }
-
-    @Test
-    public void shouldConvertSheetToTable() {
-        final Workbook workbook = workbook(TEST_XLSX);
-        final List<Sheet> sheets = excelTool().getSheets(workbook);
-        final List<List<String>> records = excelTool().toTable(sheets.get(0));
-
-        final List<String> record = records.get(1);
-
-        assertEquals("Row 1", record.get(0));
-        assertEquals("01/31/17", record.get(1));
-        assertEquals("100.00", record.get(2));
-        assertEquals("€100.00", record.get(3));
-        assertEquals("11:00", record.get(4));
-        assertEquals("10.00%", record.get(5));
-        assertEquals("C2*F2", record.get(6));
-    }
-
-    @Test
-    public void shouldConvertSheetToRawTable() {
-        final Workbook workbook = workbook(TEST_XLSX);
-        final List<Sheet> sheets = excelTool().getSheets(workbook);
-        final List<List<Object>> records = excelTool().toRawTable(sheets.get(0));
-
-        final List<Object> record = records.get(1);
-
-        assertEquals("Row 1", record.get(0));
-        assertEquals("2017-01-31", record.get(1).toString());
-        assertEquals(100.00, record.get(2));
-        assertEquals(100.00, record.get(2));
-        assertEquals("11:00", record.get(4).toString());
-        assertEquals(0.1, record.get(5));
-        assertEquals("C2*F2", record.get(6));
-    }
-
-    private Workbook workbook(File file) {
-        return excelTool().parse(document(file));
-    }
-
-    private ExcelTool excelTool() {
-        return new ExcelTool();
-    }
-
-    private Document document(File file) {
-        return DocumentFactory.create(file, UTF_8);
-    }
-}
diff --git a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/freemarker/FreeMarkerToolTest.java b/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/freemarker/FreeMarkerToolTest.java
deleted file mode 100644
index 29253bf..0000000
--- a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/freemarker/FreeMarkerToolTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.freemarker;
-
-import org.junit.Test;
-
-import static junit.framework.TestCase.assertNotNull;
-
-public class FreeMarkerToolTest {
-
-    @Test
-    public void shallGetBeansWrapper() {
-        assertNotNull(freeMarkerTool().getBeansWrapper());
-    }
-
-    @Test
-    public void shallGetObjectConstructor() {
-        assertNotNull(freeMarkerTool().getObjectConstructor());
-    }
-
-    @Test
-    public void shallGetEnums() {
-        assertNotNull(freeMarkerTool().getEnums());
-    }
-
-    @Test
-    public void shallGetStatics() {
-        assertNotNull(freeMarkerTool().getStatics());
-    }
-
-    private FreeMarkerTool freeMarkerTool() {
-        return new FreeMarkerTool();
-    }
-}
diff --git a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/grok/GrokToolTest.java b/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/grok/GrokToolTest.java
deleted file mode 100644
index 97d0b16..0000000
--- a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/grok/GrokToolTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.grok;
-
-import org.junit.Test;
-
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-
-public class GrokToolTest {
-
-    private static final String LOG = "112.169.19.192 - - [06/Mar/2013:01:36:30 +0900] \"GET / HTTP/1.1\" 200 44346 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.152 Safari/537.22\"";
-
-    @Test
-    public void shallParseCombinedAccessLog() {
-        final GrokWrapper grok = grokTool().compile("%{COMBINEDAPACHELOG}");
-
-        final Map<String, Object> map = grok.match(LOG);
-
-        assertEquals("GET", map.get("verb"));
-        assertEquals("06/Mar/2013:01:36:30 +0900", map.get("timestamp"));
-        assertEquals("44346", map.get("bytes"));
-        assertEquals("/", map.get("request"));
-        assertEquals("1.1", map.get("httpversion"));
-    }
-
-    private GrokTool grokTool() {
-        return new GrokTool();
-    }
-}
diff --git a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/jsonpath/JsonPathToolTest.java b/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/jsonpath/JsonPathToolTest.java
deleted file mode 100644
index c03f70e..0000000
--- a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/jsonpath/JsonPathToolTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.jsonpath;
-
-import com.jayway.jsonpath.DocumentContext;
-import org.junit.Test;
-
-import static junit.framework.TestCase.assertEquals;
-import static junit.framework.TestCase.assertNull;
-
-public class JsonPathToolTest {
-
-    private static final String JSON_OBJECT_STRING = "{\n" +
-            "\"id\": 110,\n" +
-            "\"language\": \"Python\",\n" +
-            "\"price\": 1900,\n" +
-            "}";
-
-    private static final String JSON_ARRAY_STRING = "{\n" +
-            "   \"eBooks\":[\n" +
-            "      {\n" +
-            "         \"language\":\"Pascal\",\n" +
-            "         \"edition\":\"third\"\n" +
-            "      },\n" +
-            "      {\n" +
-            "         \"language\":\"Python\",\n" +
-            "         \"edition\":\"four\"\n" +
-            "      },\n" +
-            "      {\n" +
-            "         \"language\":\"SQL\",\n" +
-            "         \"edition\":\"second\"\n" +
-            "      }\n" +
-            "   ]\n" +
-            "}";
-
-    @Test
-    public void shallParseJsonObject() {
-        assertEquals(parse(JSON_OBJECT_STRING).read("$.language"), "Python");
-        assertEquals(parse(JSON_OBJECT_STRING).read("$['language']"), "Python");
-    }
-
-    @Test
-    public void shallParseJsonArray() {
-        assertEquals(parse(JSON_ARRAY_STRING).read("$.eBooks[0].language"), "Pascal");
-        assertEquals(parse(JSON_ARRAY_STRING).read("$['eBooks'][0]['language']"), "Pascal");
-    }
-
-    @Test
-    public void shallSuppressExceptionForUnknonwPath() {
-        assertNull(parse(JSON_OBJECT_STRING).read("$.unknown"));
-    }
-
-    private DocumentContext parse(String json) {
-        return jsonPathTool().parse(json);
-    }
-
-    private JsonPathTool jsonPathTool() {
-        return new JsonPathTool();
-    }
-}
diff --git a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/jsoup/JsoupToolTest.java b/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/jsoup/JsoupToolTest.java
deleted file mode 100644
index deabb8c..0000000
--- a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/jsoup/JsoupToolTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.jsoup;
-
-import org.jsoup.nodes.Document;
-import org.junit.Test;
-
-import static junit.framework.TestCase.assertEquals;
-import static junit.framework.TestCase.assertNull;
-
-public class JsoupToolTest {
-
-    private static final String ANY_HTML_CONTENT = "<!DOCTYPE html>\n" +
-            "<html lang=\"en\">\n" +
-            "  <head>\n" +
-            "    <meta charset=\"utf-8\">\n" +
-            "    <title>title</title>\n" +
-            "    <link rel=\"stylesheet\" href=\"style.css\">\n" +
-            "    <script src=\"script.js\"></script>\n" +
-            "  </head>\n" +
-            "  <body>\n" +
-            "    <h1>Hello World</h1>\n" +
-            "  </body>\n" +
-            "</html>";
-
-    @Test
-    public void shallParseStringHtmlContent() {
-        assertEquals("Hello World", parse(ANY_HTML_CONTENT).select("h1").first().text());
-    }
-
-    @Test
-    public void shallReturnNullForUndefinedCSSPath() {
-        assertNull(parse(ANY_HTML_CONTENT).select("h2").first());
-    }
-
-    private Document parse(String html) {
-        return jsoupTool().parse(html);
-    }
-
-    private JsoupTool jsoupTool() {
-        return new JsoupTool();
-    }
-
-
-}
diff --git a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/properties/PropertiesToolTest.java b/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/properties/PropertiesToolTest.java
deleted file mode 100644
index 5b649d7..0000000
--- a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/properties/PropertiesToolTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.properties;
-
-import org.apache.freemarker.generator.base.document.Document;
-import org.apache.freemarker.generator.base.document.DocumentFactory;
-import org.junit.Test;
-
-import static junit.framework.TestCase.assertEquals;
-
-public class PropertiesToolTest {
-
-    private static final String ANY_PROPERTIES_STRING = "foo=bar";
-
-    @Test
-    public void shallParsePropertiesDocument() {
-        try (Document document = document(ANY_PROPERTIES_STRING)) {
-            assertEquals("bar", propertiesTool().parse(document).getProperty("foo"));
-        }
-    }
-
-    @Test
-    public void shallParsePropertiesString() {
-        assertEquals("bar", propertiesTool().parse(ANY_PROPERTIES_STRING).getProperty("foo"));
-    }
-
-    private PropertiesTool propertiesTool() {
-        return new PropertiesTool();
-    }
-
-    private Document document(String value) {
-        return DocumentFactory.create("test.properties", value);
-    }
-}
diff --git a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/snakeyaml/SnakeYamlToolTest.java b/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/snakeyaml/SnakeYamlToolTest.java
deleted file mode 100644
index 4f22e7f..0000000
--- a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/snakeyaml/SnakeYamlToolTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.snakeyaml;
-
-import org.apache.freemarker.generator.base.document.Document;
-import org.apache.freemarker.generator.base.document.DocumentFactory;
-import org.junit.Test;
-
-import java.util.List;
-import java.util.Map;
-
-import static junit.framework.TestCase.assertEquals;
-
-public class SnakeYamlToolTest {
-
-    private static final String ANY_YAML_STRING = "docker:\n" +
-            "    - image: ubuntu:14.04\n" +
-            "    - image: mongo:2.6.8\n" +
-            "      command: [mongod, --smallfiles]\n" +
-            "    - image: postgres:9.4.1";
-
-    @Test
-    public void shallParseYamlDocument() {
-        try (Document document = document(ANY_YAML_STRING)) {
-            final Map<String, Object> map = snakeYamlTool().parse(document);
-
-            assertEquals(1, map.size());
-            assertEquals(3, ((List<?>) map.get("docker")).size());
-        }
-    }
-
-    @Test
-    public void shallParseYamlString() {
-        final Map<String, Object> map = snakeYamlTool().parse(ANY_YAML_STRING);
-
-        assertEquals(1, map.size());
-        assertEquals(3, ((List<?>) map.get("docker")).size());
-    }
-
-    private SnakeYamlTool snakeYamlTool() {
-        return new SnakeYamlTool();
-    }
-
-    private Document document(String value) {
-        return DocumentFactory.create("test.yml", value);
-    }
-}
diff --git a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/system/SystemToolTest.java b/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/system/SystemToolTest.java
deleted file mode 100644
index 4519438..0000000
--- a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/system/SystemToolTest.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.system;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertFalse;
-
-public class SystemToolTest {
-
-    @Test
-    public void shallGetProperties() {
-        assertFalse(systemTool().getProperties().isEmpty());
-    }
-
-    @Test
-    public void shallGetEnvs() {
-        assertFalse(systemTool().getEnvs().isEmpty());
-    }
-
-    @Test
-    public void shallGetHostName() {
-        assertFalse(systemTool().getHostName().isEmpty());
-    }
-
-    private SystemTool systemTool() {
-        return new SystemTool();
-    }
-
-}
diff --git a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/uuid/UUIDToolTest.java b/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/uuid/UUIDToolTest.java
deleted file mode 100644
index a5a21a9..0000000
--- a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/uuid/UUIDToolTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.uuid;
-
-import org.junit.Test;
-
-import static junit.framework.TestCase.assertEquals;
-import static junit.framework.TestCase.assertNotNull;
-
-public class UUIDToolTest {
-
-    @Test
-    public void shallCreateRandomUUID() {
-        assertNotNull(uuidTool().randomUUID());
-    }
-
-    @Test
-    public void shallCreateNamedUUID() {
-        assertEquals("b068931c-c450-342b-a3f5-b3d276ea4297", uuidTool().namedUUID("name").toString());
-    }
-
-    private UUIDTool uuidTool() {
-        return new UUIDTool();
-    }
-}
diff --git a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/xml/XmlToolTest.java b/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/xml/XmlToolTest.java
deleted file mode 100644
index 75343f8..0000000
--- a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/tools/xml/XmlToolTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.freemarker.generator.cli.tools.xml;
-
-import freemarker.ext.dom.NodeModel;
-import org.apache.freemarker.generator.base.document.Document;
-import org.apache.freemarker.generator.base.document.DocumentFactory;
-import org.junit.Test;
-
-import static junit.framework.TestCase.assertEquals;
-import static junit.framework.TestCase.assertNotNull;
-
-public class XmlToolTest {
-
-    private static final String ANY_XML_STRING = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
-            "<note>\n" +
-            "  <to>Tove</to>\n" +
-            "  <from>Jani</from>\n" +
-            "  <heading>Reminder</heading>\n" +
-            "  <body>Don't forget me this weekend!</body>\n" +
-            "</note>";
-
-    @Test
-    public void shallParseXmlDocument() throws Exception {
-        try (Document document = document(ANY_XML_STRING)) {
-            final NodeModel model = xmlTool().parse(document);
-
-            assertNotNull(model);
-            assertEquals(1, model.getChildNodes().size());
-        }
-    }
-
-    @Test
-    public void shallParseXmlString() throws Exception {
-        final NodeModel model = xmlTool().parse(ANY_XML_STRING);
-
-        assertNotNull(model);
-        assertEquals(1, model.getChildNodes().size());
-    }
-
-    private XmlTool xmlTool() {
-        return new XmlTool();
-    }
-
-    private Document document(String value) {
-        return DocumentFactory.create("test.xml", value);
-    }
-}
diff --git a/pom.xml b/pom.xml
index beef682..d8a3946 100644
--- a/pom.xml
+++ b/pom.xml
@@ -51,6 +51,7 @@
 
     <modules>
         <module>freemarker-generator-base</module>
+        <module>freemarker-generator-tools</module>
         <module>freemarker-generator-cli</module>
         <module>freemarker-generator-maven-plugin</module>
     </modules>