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

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

commit 2f8c40f772b6384e8f3c0dfa5a16baa49f3489d8
Author: Siegfried Goeschl <[email protected]>
AuthorDate: Sun Oct 17 23:24:22 2021 +0200

    FREEMARKER-199 [freemarker-generator] Add "utah-parser-tool"
---
 .../src/app/config/freemarker-generator.properties |  1 +
 .../utahparser/juniper_bgp_summary_example.txt     | 12 ++++
 .../utahparser/juniper_bgp_summary_template.xml    | 69 ++++++++++++++++++
 .../templates/utahparser/csv/transform.ftl         | 31 ++++++++
 .../templates/utahparser/json/transform.ftl        | 19 +++++
 .../freemarker/generator/cli/ExamplesTest.java     | 11 +++
 freemarker-generator-tools/pom.xml                 |  6 ++
 .../generator/tools/commonscsv/CommonsCSVTool.java |  6 ++
 .../commonscsv/impl/CommonsCSVPrinterFacade.java   | 12 ++++
 .../generator/tools/utahparser/UtahParserTool.java | 56 +++++++++++++++
 .../tools/utahparser/impl/ParserWrapper.java       | 82 ++++++++++++++++++++++
 .../utahparser/juniper_bgp_summary_example.txt     | 12 ++++
 .../utahparser/juniper_bgp_summary_template.xml    | 69 ++++++++++++++++++
 .../tools/utahparser/UtahParserToolTest.java       | 68 ++++++++++++++++++
 14 files changed, 454 insertions(+)

diff --git 
a/freemarker-generator-cli/src/app/config/freemarker-generator.properties 
b/freemarker-generator-cli/src/app/config/freemarker-generator.properties
index 25b7029..d65937b 100644
--- a/freemarker-generator-cli/src/app/config/freemarker-generator.properties
+++ b/freemarker-generator-cli/src/app/config/freemarker-generator.properties
@@ -34,6 +34,7 @@ 
freemarker.tools.jsonpath=org.apache.freemarker.generator.tools.jsonpath.JsonPat
 freemarker.tools.jsoup=org.apache.freemarker.generator.tools.jsoup.JsoupTool
 
freemarker.tools.properties=org.apache.freemarker.generator.tools.properties.PropertiesTool
 freemarker.tools.system=org.apache.freemarker.generator.tools.system.SystemTool
+freemarker.tools.utahparser=org.apache.freemarker.generator.tools.utahparser.UtahParserTool
 freemarker.tools.uuid=org.apache.freemarker.generator.tools.uuid.UUIDTool
 freemarker.tools.xml=org.apache.freemarker.generator.tools.xml.XmlTool
 
freemarker.tools.yaml=org.apache.freemarker.generator.tools.snakeyaml.SnakeYamlTool
diff --git 
a/freemarker-generator-cli/src/app/examples/data/text/utahparser/juniper_bgp_summary_example.txt
 
b/freemarker-generator-cli/src/app/examples/data/text/utahparser/juniper_bgp_summary_example.txt
new file mode 100644
index 0000000..c4a209e
--- /dev/null
+++ 
b/freemarker-generator-cli/src/app/examples/data/text/utahparser/juniper_bgp_summary_example.txt
@@ -0,0 +1,12 @@
+Groups: 3 Peers: 3 Down peers: 0
+Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
+inet.0               947        310          0          0          0          0
+inet6.0              849        807          0          0          0          0
+Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn 
State|#Active/Received/Damped...
+10.247.68.182         65550     131725   28179233       0      11     6w3d17h 
Establ
+  inet.0: 4/5/1
+  inet6.0: 0/0/0
+10.254.166.246        65550     136159   29104942       0       0      6w5d6h 
Establ
+  inet.0: 0/0/0
+  inet6.0: 7/8/1
+192.0.2.100           65551    1269381    1363320       0       1      9w5d6h 
1/2/3 4/5/6
\ No newline at end of file
diff --git 
a/freemarker-generator-cli/src/app/examples/data/text/utahparser/juniper_bgp_summary_template.xml
 
b/freemarker-generator-cli/src/app/examples/data/text/utahparser/juniper_bgp_summary_template.xml
new file mode 100644
index 0000000..bb1093a
--- /dev/null
+++ 
b/freemarker-generator-cli/src/app/examples/data/text/utahparser/juniper_bgp_summary_template.xml
@@ -0,0 +1,69 @@
+<config>
+    <searches>
+
+        <!-- in this case, we have a CSV (space delimited file) so we define 
the line once, and then reuse it over
+        and again for each value -->
+        <search 
id="QUERY-LINE"><![CDATA[\s*{ipAddress}\s+{numbers}\s+{numbers}\s+{numbers}\s+{numbers}\s+{numbers}\s+{numbersThenText}]]></search>
+
+
+        <search id="inetInline"><![CDATA[{inet} {inet}]]></search>
+        <search id="inet4"><![CDATA[inet.0:\s*{inet}]]></search>
+        <search id="inet6"><![CDATA[inet6.0:\s*{inet}]]></search>
+        <search id="inet"><![CDATA[{numbers}/{numbers}/{numbers}]]></search>
+
+        <!-- Some rules for finding text, to make the values a little easier 
below -->
+        <search id="numbers"><![CDATA[(\d+)]]></search>
+        <search id="numbersThenText"><![CDATA[(\d+\S+)]]></search>
+        <search id="string"><![CDATA[(\S+?)]]></search>
+        <search id="ipAddress"><![CDATA[(\d+(\.\d+){3})]]></search>
+        <search id="EOL"><![CDATA[[\n\r]]]></search>
+    </searches>
+
+    <!-- the record starts with a line with an ip address and ends with either 
an inet6 line, or where the ids are at
+    the end of the line-->
+    <delim retain="true">{ipAddress}.*(\/\d+)\s*{EOL}</delim>
+    <delim>\s*({inet6})</delim>
+
+    <!--
+    This is the last line of the header
+     -->
+    <header-delim><![CDATA[Peer\s+AS\s+InPkt]]></header-delim>
+
+    <!--
+    Files look like this:
+
+    10.247.68.182         65550     131725   28179233       0      11     
6w3d17h Establ
+      inet.0: 4/5/1
+      inet6.0: 0/0/0
+
+      or
+
+    192.0.2.100           65551    1269381    1363320       0       1      
9w5d6h 2/3/0 0/0/0
+  -->
+    <values>
+        <!-- here we reuse the line pattern, only we pull out different group 
values -->
+        <value id="remoteIp" group="1"><![CDATA[{QUERY-LINE}]]></value>
+        <value id="uptime" group="8"><![CDATA[{QUERY-LINE}]]></value>
+
+        <!-- here we check for values in the inet* lines and use these -->
+        <value id="activeV4" group="1"><![CDATA[{inet4}]]></value>
+        <value id="receivedV4" group="2"><![CDATA[{inet4}]]></value>
+        <value id="accepted_V4" group="3"><![CDATA[{inet4}]]></value>
+
+        <value id="activeV6" group="1"><![CDATA[{inet6}]]></value>
+        <value id="receivedV6" group="2"><![CDATA[{inet6}]]></value>
+        <value id="accepted_V6" group="3"><![CDATA[{inet6}]]></value>
+
+        <!--
+        here we check for values at the end of the query line, and use these
+         NOTE: since we only set non-null values, these will not overwrite any 
values set above
+        -->
+        <value id="activeV4" 
group="9"><![CDATA[{QUERY-LINE}\s*{inetInline}]]></value>
+        <value id="receivedV4" 
group="10"><![CDATA[{QUERY-LINE}\s*{inetInline}]]></value>
+        <value id="accepted_V4" 
group="11"><![CDATA[{QUERY-LINE}\s*{inetInline}]]></value>
+        <value id="activeV6" 
group="12"><![CDATA[{QUERY-LINE}\s*{inetInline}]]></value>
+        <value id="receivedV6" 
group="13"><![CDATA[{QUERY-LINE}\s*{inetInline}]]></value>
+        <value id="accepted_V6" 
group="14"><![CDATA[{QUERY-LINE}\s*{inetInline}]]></value>
+
+    </values>
+</config>
\ No newline at end of file
diff --git 
a/freemarker-generator-cli/src/app/examples/templates/utahparser/csv/transform.ftl
 
b/freemarker-generator-cli/src/app/examples/templates/utahparser/csv/transform.ftl
new file mode 100644
index 0000000..5063619
--- /dev/null
+++ 
b/freemarker-generator-cli/src/app/examples/templates/utahparser/csv/transform.ftl
@@ -0,0 +1,31 @@
+<#--
+  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.
+-->
+<#-- Setup Utah-Parser -->
+<#assign conf =  tools.utahparser.getConfig(dataSources[0])>
+<#assign parser = tools.utahparser.getParser(conf, dataSources[1])>
+<#assign records = parser.toList()>
+<#assign firstRecord = records[0]!{}>
+<#-- Setup CSVPrinter  -->
+<#assign csvHeaders = tools.csv.extractHeaders(firstRecord)>
+<#assign cvsFormat = 
tools.csv.formats.EXCEL.withHeader(csvHeaders).withDelimiter(';')>
+<#assign csvPrinter = tools.csv.printer(cvsFormat)>
+<#-- Print records as CSV  -->
+<#compress>
+    <#list records as record>
+        ${csvPrinter.printRecord(record, csvHeaders)}
+    </#list>
+</#compress>
\ No newline at end of file
diff --git 
a/freemarker-generator-cli/src/app/examples/templates/utahparser/json/transform.ftl
 
b/freemarker-generator-cli/src/app/examples/templates/utahparser/json/transform.ftl
new file mode 100644
index 0000000..4c2a53e
--- /dev/null
+++ 
b/freemarker-generator-cli/src/app/examples/templates/utahparser/json/transform.ftl
@@ -0,0 +1,19 @@
+<#--
+  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.
+-->
+<#assign conf =  tools.utahparser.getConfig(dataSources[0])>
+<#assign parser = tools.utahparser.getParser(conf, dataSources[1])>
+${tools.gson.toJson(parser.toList())}
\ No newline at end of file
diff --git 
a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/ExamplesTest.java
 
b/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/ExamplesTest.java
index 0aa2399..687925f 100644
--- 
a/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/ExamplesTest.java
+++ 
b/freemarker-generator-cli/src/test/java/org/apache/freemarker/generator/cli/ExamplesTest.java
@@ -126,6 +126,17 @@ public class ExamplesTest extends AbstractMainTest {
     }
 
     @Test
+    public void shouldRunUtahParserExamples() throws IOException {
+        assertValid(execute("-t 
src/app/examples/templates/utahparser/csv/transform.ftl " +
+                
"src/app/examples/data/text/utahparser/juniper_bgp_summary_template.xml " +
+                
"src/app/examples/data/text/utahparser/juniper_bgp_summary_example.txt"));
+
+        assertValid(execute("-t 
src/app/examples/templates/utahparser/json/transform.ftl " +
+                
"src/app/examples/data/text/utahparser/juniper_bgp_summary_template.xml " +
+                
"src/app/examples/data/text/utahparser/juniper_bgp_summary_example.txt"));
+    }
+
+    @Test
     public void shouldRunInteractiveTemplateExamples() throws IOException {
         assertValid(execute("-i 
${tools.jsonpath.parse(dataSources[0]).read(\"$.info.title\")} 
src/app/examples/data/json/swagger-spec.json"));
         assertValid(execute("-i 
${tools.xml.parse(dataSources[0])[\"recipients/person[1]/name\"]} 
src/app/examples/data/xml/recipients.xml"));
diff --git a/freemarker-generator-tools/pom.xml 
b/freemarker-generator-tools/pom.xml
index 590246f..04ca3f1 100644
--- a/freemarker-generator-tools/pom.xml
+++ b/freemarker-generator-tools/pom.xml
@@ -129,6 +129,12 @@
             <artifactId>snakeyaml</artifactId>
             <version>1.28</version>
         </dependency>
+        <!-- UtahPrserTool -->
+        <dependency>
+            <groupId>com.sonalake</groupId>
+            <artifactId>utah-parser</artifactId>
+            <version>1.0.2</version>
+        </dependency>
         <!-- Testing -->
         <dependency>
             <groupId>junit</groupId>
diff --git 
a/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/commonscsv/CommonsCSVTool.java
 
b/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/commonscsv/CommonsCSVTool.java
index 12c757d..519c171 100644
--- 
a/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/commonscsv/CommonsCSVTool.java
+++ 
b/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/commonscsv/CommonsCSVTool.java
@@ -33,6 +33,7 @@ import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
@@ -98,6 +99,11 @@ public class CommonsCSVTool {
         return new CommonsCSVPrinterFacade(csvFormat);
     }
 
+    public String[] extractHeaders(Map<String, Object> map) {
+        final Set<String> keySet = map.keySet();
+        return keySet.toArray(new String[0]);
+    }
+
     /**
      * Extract the list of unique values (keys) of the column "name".
      *
diff --git 
a/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/commonscsv/impl/CommonsCSVPrinterFacade.java
 
b/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/commonscsv/impl/CommonsCSVPrinterFacade.java
index 9909d17..958dbdb 100644
--- 
a/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/commonscsv/impl/CommonsCSVPrinterFacade.java
+++ 
b/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/commonscsv/impl/CommonsCSVPrinterFacade.java
@@ -25,6 +25,9 @@ import java.io.IOException;
 import java.io.StringWriter;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 
 /**
  * Wrap <code>CSVPrinter</code> so each print method returns
@@ -91,6 +94,15 @@ public class CommonsCSVPrinterFacade implements Flushable, 
Closeable {
         return getOutput();
     }
 
+    public String printRecord(Map<String, Object> map, String[] headers) 
throws IOException {
+        final List<String> values = new ArrayList<>(headers.length);
+        for (String header : headers) {
+            final Object value = map.get(header);
+            values.add(value != null ? value.toString() : "");
+        }
+        return printRecord(values);
+    }
+
     private String getOutput() {
         writer.flush();
         final String output = writer.getBuffer().toString();
diff --git 
a/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/utahparser/UtahParserTool.java
 
b/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/utahparser/UtahParserTool.java
new file mode 100644
index 0000000..87ceb0d
--- /dev/null
+++ 
b/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/utahparser/UtahParserTool.java
@@ -0,0 +1,56 @@
+/*
+ * 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.tools.utahparser;
+
+import com.sonalake.utah.Parser;
+import com.sonalake.utah.config.Config;
+import com.sonalake.utah.config.ConfigLoader;
+import org.apache.freemarker.generator.base.datasource.DataSource;
+import org.apache.freemarker.generator.base.datasource.DataSourceLoaderFactory;
+import org.apache.freemarker.generator.tools.utahparser.impl.ParserWrapper;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class UtahParserTool {
+
+    public Config getConfig(String source) {
+        return this.getConfig(DataSourceLoaderFactory.create().load(source));
+    }
+
+    public Config getConfig(DataSource dataSource) {
+        try (InputStream is = dataSource.getUnsafeInputStream()) {
+            return loadConfig(is);
+        } catch (IOException var16) {
+            throw new RuntimeException("Failed to load parser configuration: " 
+ dataSource, var16);
+        }
+    }
+
+    public ParserWrapper getParser(Config config, DataSource dataSource) {
+        final InputStreamReader is = new 
InputStreamReader(dataSource.getInputStream());
+        return new ParserWrapper(Parser.parse(config, is));
+    }
+
+    public String toString() {
+        return "Parse semi-structured text using regular expressions (see 
https://github.com/sonalake/utah-parser)";
+    }
+
+    private static Config loadConfig(InputStream is) throws IOException {
+        return new ConfigLoader().loadConfig(new InputStreamReader(is));
+    }
+}
\ No newline at end of file
diff --git 
a/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/utahparser/impl/ParserWrapper.java
 
b/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/utahparser/impl/ParserWrapper.java
new file mode 100644
index 0000000..585f8f8
--- /dev/null
+++ 
b/freemarker-generator-tools/src/main/java/org/apache/freemarker/generator/tools/utahparser/impl/ParserWrapper.java
@@ -0,0 +1,82 @@
+/*
+ * 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.tools.utahparser.impl;
+
+import com.sonalake.utah.Parser;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Wraps the <code>com.sonalake.utah.Parser</code> to provide convenience
+ * methods such support of iterators.
+ */
+public class ParserWrapper implements Iterable<Map<String, String>> {
+
+    /** The wrapped parser instance */
+    private final Parser parser;
+
+    public ParserWrapper(Parser parser) {
+        this.parser = requireNonNull(parser);
+    }
+
+    @Override
+    public Iterator<Map<String, String>> iterator() {
+        return new RecordsIterator(parser);
+    }
+
+    public List<Map<String, String>> toList() {
+        final List<Map<String, String>> result = new ArrayList<>();
+        for (Map<String, String> record : this) {
+            result.add(record);
+        }
+        return result;
+    }
+
+    private static final class RecordsIterator implements Iterator<Map<String, 
String>> {
+
+        private final Parser parser;
+        private Map<String, String> nextRecord;
+
+        // constructor
+        RecordsIterator(Parser parser) {
+            this.parser = requireNonNull(parser);
+            this.nextRecord = parser.next();
+        }
+
+        @Override
+        public boolean hasNext() {
+            return nextRecord != null;
+        }
+
+        @Override
+        public Map<String, String> next() {
+            if (nextRecord == null) {
+                throw new NoSuchElementException();
+            }
+
+            final Map<String, String> currentRecord = nextRecord;
+            nextRecord = parser.next();
+            return currentRecord;
+        }
+    }
+}
\ No newline at end of file
diff --git 
a/freemarker-generator-tools/src/test/data/utahparser/juniper_bgp_summary_example.txt
 
b/freemarker-generator-tools/src/test/data/utahparser/juniper_bgp_summary_example.txt
new file mode 100644
index 0000000..c4a209e
--- /dev/null
+++ 
b/freemarker-generator-tools/src/test/data/utahparser/juniper_bgp_summary_example.txt
@@ -0,0 +1,12 @@
+Groups: 3 Peers: 3 Down peers: 0
+Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
+inet.0               947        310          0          0          0          0
+inet6.0              849        807          0          0          0          0
+Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn 
State|#Active/Received/Damped...
+10.247.68.182         65550     131725   28179233       0      11     6w3d17h 
Establ
+  inet.0: 4/5/1
+  inet6.0: 0/0/0
+10.254.166.246        65550     136159   29104942       0       0      6w5d6h 
Establ
+  inet.0: 0/0/0
+  inet6.0: 7/8/1
+192.0.2.100           65551    1269381    1363320       0       1      9w5d6h 
1/2/3 4/5/6
\ No newline at end of file
diff --git 
a/freemarker-generator-tools/src/test/data/utahparser/juniper_bgp_summary_template.xml
 
b/freemarker-generator-tools/src/test/data/utahparser/juniper_bgp_summary_template.xml
new file mode 100644
index 0000000..bb1093a
--- /dev/null
+++ 
b/freemarker-generator-tools/src/test/data/utahparser/juniper_bgp_summary_template.xml
@@ -0,0 +1,69 @@
+<config>
+    <searches>
+
+        <!-- in this case, we have a CSV (space delimited file) so we define 
the line once, and then reuse it over
+        and again for each value -->
+        <search 
id="QUERY-LINE"><![CDATA[\s*{ipAddress}\s+{numbers}\s+{numbers}\s+{numbers}\s+{numbers}\s+{numbers}\s+{numbersThenText}]]></search>
+
+
+        <search id="inetInline"><![CDATA[{inet} {inet}]]></search>
+        <search id="inet4"><![CDATA[inet.0:\s*{inet}]]></search>
+        <search id="inet6"><![CDATA[inet6.0:\s*{inet}]]></search>
+        <search id="inet"><![CDATA[{numbers}/{numbers}/{numbers}]]></search>
+
+        <!-- Some rules for finding text, to make the values a little easier 
below -->
+        <search id="numbers"><![CDATA[(\d+)]]></search>
+        <search id="numbersThenText"><![CDATA[(\d+\S+)]]></search>
+        <search id="string"><![CDATA[(\S+?)]]></search>
+        <search id="ipAddress"><![CDATA[(\d+(\.\d+){3})]]></search>
+        <search id="EOL"><![CDATA[[\n\r]]]></search>
+    </searches>
+
+    <!-- the record starts with a line with an ip address and ends with either 
an inet6 line, or where the ids are at
+    the end of the line-->
+    <delim retain="true">{ipAddress}.*(\/\d+)\s*{EOL}</delim>
+    <delim>\s*({inet6})</delim>
+
+    <!--
+    This is the last line of the header
+     -->
+    <header-delim><![CDATA[Peer\s+AS\s+InPkt]]></header-delim>
+
+    <!--
+    Files look like this:
+
+    10.247.68.182         65550     131725   28179233       0      11     
6w3d17h Establ
+      inet.0: 4/5/1
+      inet6.0: 0/0/0
+
+      or
+
+    192.0.2.100           65551    1269381    1363320       0       1      
9w5d6h 2/3/0 0/0/0
+  -->
+    <values>
+        <!-- here we reuse the line pattern, only we pull out different group 
values -->
+        <value id="remoteIp" group="1"><![CDATA[{QUERY-LINE}]]></value>
+        <value id="uptime" group="8"><![CDATA[{QUERY-LINE}]]></value>
+
+        <!-- here we check for values in the inet* lines and use these -->
+        <value id="activeV4" group="1"><![CDATA[{inet4}]]></value>
+        <value id="receivedV4" group="2"><![CDATA[{inet4}]]></value>
+        <value id="accepted_V4" group="3"><![CDATA[{inet4}]]></value>
+
+        <value id="activeV6" group="1"><![CDATA[{inet6}]]></value>
+        <value id="receivedV6" group="2"><![CDATA[{inet6}]]></value>
+        <value id="accepted_V6" group="3"><![CDATA[{inet6}]]></value>
+
+        <!--
+        here we check for values at the end of the query line, and use these
+         NOTE: since we only set non-null values, these will not overwrite any 
values set above
+        -->
+        <value id="activeV4" 
group="9"><![CDATA[{QUERY-LINE}\s*{inetInline}]]></value>
+        <value id="receivedV4" 
group="10"><![CDATA[{QUERY-LINE}\s*{inetInline}]]></value>
+        <value id="accepted_V4" 
group="11"><![CDATA[{QUERY-LINE}\s*{inetInline}]]></value>
+        <value id="activeV6" 
group="12"><![CDATA[{QUERY-LINE}\s*{inetInline}]]></value>
+        <value id="receivedV6" 
group="13"><![CDATA[{QUERY-LINE}\s*{inetInline}]]></value>
+        <value id="accepted_V6" 
group="14"><![CDATA[{QUERY-LINE}\s*{inetInline}]]></value>
+
+    </values>
+</config>
\ No newline at end of file
diff --git 
a/freemarker-generator-tools/src/test/java/org/apache/freemarker/generator/tools/utahparser/UtahParserToolTest.java
 
b/freemarker-generator-tools/src/test/java/org/apache/freemarker/generator/tools/utahparser/UtahParserToolTest.java
new file mode 100644
index 0000000..4e742bb
--- /dev/null
+++ 
b/freemarker-generator-tools/src/test/java/org/apache/freemarker/generator/tools/utahparser/UtahParserToolTest.java
@@ -0,0 +1,68 @@
+package org.apache.freemarker.generator.tools.utahparser;
+
+import com.sonalake.utah.config.Config;
+import org.apache.freemarker.generator.base.datasource.DataSource;
+import org.apache.freemarker.generator.base.datasource.DataSourceFactory;
+import org.apache.freemarker.generator.tools.utahparser.impl.ParserWrapper;
+import org.junit.Test;
+
+import java.io.File;
+
+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;
+
+public class UtahParserToolTest {
+
+    private final static String EXAMPLE_FILE_NAME = 
"src/test/data/utahparser/juniper_bgp_summary_example.txt";
+    private final static String TEMPLATE_FILE_NAME = 
"src/test/data/utahparser/juniper_bgp_summary_template.xml";
+
+    @Test
+
+    public void shallLoadConfFromFile() {
+        final Config config = utahParserTool().getConfig(TEMPLATE_FILE_NAME);
+
+        assertNotNull(config);
+        assertTrue(config.isDelimiterValid());
+    }
+
+    @Test
+    public void shallLoadConfFromDataSource() {
+        final DataSource dataSource = dataSource(TEMPLATE_FILE_NAME);
+        final Config config = utahParserTool().getConfig(dataSource);
+
+        assertNotNull(config);
+        assertTrue(config.isDelimiterValid());
+    }
+
+    @Test
+    public void shallGetParserInstance() {
+        final DataSource dataSource = dataSource(EXAMPLE_FILE_NAME);
+        final UtahParserTool utahParserTool = utahParserTool();
+        final Config config = utahParserTool.getConfig(TEMPLATE_FILE_NAME);
+        final ParserWrapper parser = utahParserTool.getParser(config, 
dataSource);
+
+        assertNotNull(parser);
+        assertNotNull(parser.iterator());
+    }
+
+    @Test
+    public void shallParseAllData() {
+        final DataSource dataSource = dataSource(EXAMPLE_FILE_NAME);
+        final UtahParserTool utahParserTool = utahParserTool();
+        final Config config = utahParserTool.getConfig(TEMPLATE_FILE_NAME);
+        final ParserWrapper parser = utahParserTool.getParser(config, 
dataSource);
+
+        assertEquals(3, parser.toList().size());
+    }
+
+    private static UtahParserTool utahParserTool() {
+        return new UtahParserTool();
+    }
+
+    private static DataSource dataSource(String fileName) {
+        return DataSourceFactory.fromFile(new File(fileName), UTF_8);
+    }
+
+}

Reply via email to