Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/keenwrite.git

Add interpolation to definition processor

AuthorDaveJarvis <email>
Date2020-06-07 20:55:51 GMT-0700
Commitb89be257366c585cd71e85f598d8c2e95137d1a4
Parentfbb8e60
Delta200 lines added, 202 lines removed, 2-line decrease
src/test/java/com/scrivenvar/definition/TreeItemInterpolatorTest.java
full.getChildren().add( expr );
- final var map = TreeItemInterpolator.toMap( root );
+ final var map = TreeItemAdapter.toMap( root );
var actualAuthor = map.get( "$root.name.full$" );
var expectedAuthor = AUTHOR_ALL;
assertEquals( expectedAuthor, actualAuthor );
- TreeItemInterpolator.interpolate( map );
+ MapInterpolator.interpolate( map );
actualAuthor = map.get( "$root.name.full$" );
src/main/java/com/scrivenvar/processors/ProcessorFactory.java
}
+ protected Processor<String> createDefinitionProcessor(
+ final Processor<String> p ) {
+ return new DefinitionProcessor( p, getResolvedMap() );
+ }
+
protected Processor<String> createMarkdownProcessor(
final FileEditorTab tab ) {
final var caret = tab.caretPositionProperty();
final var tpc = getCommonProcessor();
final var cip = createMarkdownInsertionProcessor( tpc, caret );
- return new DefinitionProcessor( cip, getResolvedMap() );
+ return createDefinitionProcessor( cip );
}
protected Processor<String> createXMLProcessor( final FileEditorTab tab ) {
final var caret = tab.caretPositionProperty();
final var tpc = getCommonProcessor();
final var xmlp = new XMLProcessor( tpc, tab.getPath() );
- final var dp = new DefinitionProcessor( xmlp, getResolvedMap() );
+ final var dp = createDefinitionProcessor( xmlp );
return createXMLInsertionProcessor( dp, caret );
src/main/java/com/scrivenvar/processors/RVariableProcessor.java
* Converts the keys of the resolved map from default form to R form, then
* performs a substitution on the text. The default R variable syntax is
- * <code>v$tree$leaf</code>.
+ * {@code v$tree$leaf}.
*
* @author White Magic Software, Ltd.
src/main/java/com/scrivenvar/definition/TreeAdapter.java
+/*
+ * Copyright 2016 White Magic Software, Ltd.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
package com.scrivenvar.definition;
import javafx.scene.control.TreeItem;
import java.io.IOException;
import java.nio.file.Path;
+/**
+ * Responsible for converting an object hierarchy into a {@link TreeItem}
+ * hierarchy.
+ *
+ * @author White Magic Software, Ltd.
+ */
public interface TreeAdapter {
/**
src/main/java/com/scrivenvar/definition/TreeItemAdapter.java
+/*
+ * Copyright 2020 White Magic Software, Ltd.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.scrivenvar.definition;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.scrivenvar.decorators.YamlVariableDecorator;
+import com.scrivenvar.preview.HTMLPreviewPane;
+import javafx.scene.control.TreeItem;
+import javafx.scene.control.TreeView;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Stack;
+
+import static com.scrivenvar.Constants.DEFAULT_MAP_SIZE;
+
+/**
+ * Given a {@link TreeItem}, this will generate a flat map with all the
+ * values in the tree recursively interpolated. The application integrates
+ * definition files as follows:
+ * <ol>
+ * <li>Load YAML file into {@link JsonNode} hierarchy.</li>
+ * <li>Convert JsonNode to a {@link TreeItem} hierarchy.</li>
+ * <li>Interpolate {@link TreeItem} hierarchy as a flat map.</li>
+ * <li>Substitute flat map variables into document as required.</li>
+ * </ol>
+ *
+ * <p>
+ * This class is responsible for producing the interpolated flat map. This
+ * allows dynamic edits of the {@link TreeView} to be displayed in the
+ * {@link HTMLPreviewPane} without having to reload the definition file.
+ * Reloading the definition file would work, but has a number of drawbacks.
+ * </p>
+ *
+ * @author White Magic Software, Ltd.
+ */
+public class TreeItemAdapter {
+ /**
+ * Separates YAML variable nodes (e.g., the dots in {@code $root.node.var$]).
+ */
+ public static final String SEPARATOR = ".";
+
+ /**
+ * Default buffer length for keys ({@link StringBuilder} has 16 character
+ * buffer) that should be large enough for most keys to avoid reallocating
+ * memory to increase the {@link StringBuilder}'s buffer.
+ */
+ public static final int DEFAULT_KEY_LENGTH = 64;
+
+ /**
+ * In-order traversal of a {@link TreeItem} hierarchy, exposing each item
+ * as a consecutive list.
+ */
+ private static final class TreeIterator
+ implements Iterator<TreeItem<String>> {
+ private final Stack<TreeItem<String>> mStack = new Stack<>();
+
+ public TreeIterator( final TreeItem<String> root ) {
+ if( root != null ) {
+ mStack.push( root );
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ return !mStack.isEmpty();
+ }
+
+ @Override
+ public TreeItem<String> next() {
+ final TreeItem<String> next = mStack.pop();
+ next.getChildren().forEach( mStack::push );
+
+ return next;
+ }
+ }
+
+ private TreeItemAdapter() {
+ }
+
+ /**
+ * Iterate over a given root node (at any level of the tree) and process each
+ * leaf node into a flat map. Values must be interpolated separately.
+ */
+ public static Map<String, String> toMap( final TreeItem<String> root ) {
+ final Map<String, String> map = new HashMap<>( DEFAULT_MAP_SIZE );
+ final TreeIterator iterator = new TreeIterator( root );
+
+ iterator.forEachRemaining( item -> {
+ if( item.isLeaf() ) {
+ map.put( toPath( item.getParent() ), item.getValue() );
+ }
+ } );
+
+ return map;
+ }
+
+
+ /**
+ * For a given node, this will ascend the tree to generate a key name
+ * that is associated with the leaf node's value.
+ *
+ * @param node Ascendants represent the key to this node's value.
+ * @param <T> Data type that the {@link TreeItem} contains.
+ * @return The string representation of the node's unique key.
+ */
+ public static <T> String toPath( TreeItem<T> node ) {
+ assert node != null;
+
+ final StringBuilder key = new StringBuilder( DEFAULT_KEY_LENGTH );
+ final Stack<TreeItem<T>> stack = new Stack<>();
+
+ while( node != null && !(node instanceof RootTreeItem) ) {
+ stack.push( node );
+ node = node.getParent();
+ }
+
+ // Gets set at end of first iteration (to avoid an if condition).
+ String separator = "";
+
+ while( !stack.empty() ) {
+ final T subkey = stack.pop().getValue();
+ key.append( separator );
+ key.append( subkey );
+ separator = SEPARATOR;
+ }
+
+ return YamlVariableDecorator.entoken( key.toString() );
+ }
+}
src/main/java/com/scrivenvar/definition/TreeItemInterpolator.java
-/*
- * Copyright 2020 White Magic Software, Ltd.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * o Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * o Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.scrivenvar.definition;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.scrivenvar.decorators.YamlVariableDecorator;
-import com.scrivenvar.preview.HTMLPreviewPane;
-import javafx.scene.control.TreeItem;
-import javafx.scene.control.TreeView;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Stack;
-import java.util.regex.Matcher;
-
-import static com.scrivenvar.Constants.DEFAULT_MAP_SIZE;
-import static com.scrivenvar.decorators.YamlVariableDecorator.REGEX_PATTERN;
-
-/**
- * Given a {@link TreeItem}, this will generate a flat map with all the
- * values in the tree recursively interpolated. The application integrates
- * definition files as follows:
- * <ol>
- * <li>Load YAML file into {@link JsonNode} hierarchy.</li>
- * <li>Convert JsonNode to a {@link TreeItem} hierarchy.</li>
- * <li>Interpolate {@link TreeItem} hierarchy as a flat map.</li>
- * <li>Substitute flat map variables into document as required.</li>
- * </ol>
- *
- * <p>
- * This class is responsible for producing the interpolated flat map. This
- * allows dynamic edits of the {@link TreeView} to be displayed in the
- * {@link HTMLPreviewPane} without having to reload the definition file.
- * Reloading the definition file would work, but has a number of drawbacks.
- * </p>
- *
- * @author White Magic Software, Ltd.
- */
-public class TreeItemInterpolator {
- /**
- * Separates YAML variable nodes (e.g., the dots in {@code $root.node.var$]).
- */
- public static final String SEPARATOR = ".";
-
- private final static int GROUP_DELIMITED = 1;
-
- /**
- * Default buffer length for keys ({@link StringBuilder} has 16 character
- * buffer) that should be large enough for most keys to avoid reallocating
- * memory to increase the {@link StringBuilder}'s buffer.
- */
- public static final int DEFAULT_KEY_LENGTH = 64;
-
- /**
- * In-order traversal of a {@link TreeItem} hierarchy, exposing each item
- * as a consecutive list.
- */
- private static final class TreeIterator
- implements Iterator<TreeItem<String>> {
- private final Stack<TreeItem<String>> mStack = new Stack<>();
-
- public TreeIterator( final TreeItem<String> root ) {
- if( root != null ) {
- mStack.push( root );
- }
- }
-
- @Override
- public boolean hasNext() {
- return !mStack.isEmpty();
- }
-
- @Override
- public TreeItem<String> next() {
- final TreeItem<String> next = mStack.pop();
- next.getChildren().forEach( mStack::push );
-
- return next;
- }
- }
-
- private TreeItemInterpolator() {
- }
-
- /**
- * Iterate over a given root node (at any level of the tree) and process each
- * leaf node into a flat map. Values must be interpolated separately.
- */
- public static Map<String, String> toMap( final TreeItem<String> root ) {
- final Map<String, String> map = new HashMap<>( DEFAULT_MAP_SIZE );
- final TreeIterator iterator = new TreeIterator( root );
-
- iterator.forEachRemaining( item -> {
- if( item.isLeaf() ) {
- map.put( toPath( item.getParent() ), item.getValue() );
- }
- } );
-
- return map;
- }
-
- /**
- * Performs string interpolation on the values in the given map. This will
- * change any value in the map that contains a variable that matches
- * {@link YamlVariableDecorator#REGEX_PATTERN}.
- *
- * @param map Contains values that represent references to keys.
- */
- public static void interpolate( final Map<String, String> map ) {
- map.replaceAll( ( k, v ) -> resolve( map, v ) );
- }
-
- /**
- * Given a value with zero or more key references, this will resolve all
- * the values, recursively. If a key cannot be dereferenced, the value will
- * contain the key name.
- *
- * @param map Map to search for keys when resolving key references.
- * @param value Value containing zero or more key references
- * @return The given value with all embedded key references interpolated.
- */
- private static String resolve(
- final Map<String, String> map, String value ) {
- final Matcher matcher = REGEX_PATTERN.matcher( value );
-
- while( matcher.find() ) {
- final String keyName = matcher.group( GROUP_DELIMITED );
-
- final String keyValue = resolve(
- map, map.getOrDefault( keyName, keyName )
- );
-
- value = value.replace( keyName, keyValue );
- }
-
- return value;
- }
-
- /**
- * For a given node, this will ascend the tree to generate a key name
- * that is associated with the leaf node's value.
- *
- * @param node Ascendants represent the key to this node's value.
- * @param <T> Data type that the {@link TreeItem} contains.
- * @return The string representation of the node's unique key.
- */
- public static <T> String toPath( TreeItem<T> node ) {
- assert node != null;
-
- final StringBuilder key = new StringBuilder( DEFAULT_KEY_LENGTH );
- final Stack<TreeItem<T>> stack = new Stack<>();
-
- while( node != null && !(node instanceof RootTreeItem) ) {
- stack.push( node );
- node = node.getParent();
- }
-
- // Gets set at end of first iteration (to avoid an if condition).
- String separator = "";
-
- while( !stack.empty() ) {
- final T subkey = stack.pop().getValue();
- key.append( separator );
- key.append( subkey );
- separator = SEPARATOR;
- }
-
- return YamlVariableDecorator.entoken( key.toString() );
- }
-}
src/main/java/com/scrivenvar/definition/VariableTreeItem.java
*/
public String toPath() {
- return TreeItemInterpolator.toPath( getParent() );
+ return TreeItemAdapter.toPath( getParent() );
}
}