| Author | djarvis <email> |
|---|---|
| Date | 2016-12-22 00:00:52 GMT-0800 |
| Commit | 66ca8027744fa69a94e3729814be102f28483286 |
| Parent | 3c379b0 |
| Delta | 0 lines added, 426 lines removed, 426-line decrease |
| -/* | ||
| - * 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.test; | ||
| - | ||
| -import com.scrivenvar.definition.DefinitionPane; | ||
| -import static javafx.application.Application.launch; | ||
| -import javafx.scene.control.TreeItem; | ||
| -import javafx.scene.control.TreeView; | ||
| -import javafx.stage.Stage; | ||
| - | ||
| -/** | ||
| - * TestDefinitionPane application for debugging. | ||
| - */ | ||
| -public final class TestDefinitionPane extends TestHarness { | ||
| - /** | ||
| - * Application entry point. | ||
| - * | ||
| - * @param stage The primary application stage. | ||
| - * | ||
| - * @throws Exception Could not read configuration file. | ||
| - */ | ||
| - @Override | ||
| - public void start( final Stage stage ) throws Exception { | ||
| - super.start( stage ); | ||
| - | ||
| - TreeView<String> root = createTreeView(); | ||
| - DefinitionPane pane = createDefinitionPane( root ); | ||
| - | ||
| - test( pane, "language.ai.", "article" ); | ||
| - test( pane, "language.ai", "ai" ); | ||
| - test( pane, "l", "location" ); | ||
| - test( pane, "la", "language" ); | ||
| - test( pane, "c.p.n", "name" ); | ||
| - test( pane, "c.p.n.", "First" ); | ||
| - test( pane, "...", "c" ); | ||
| - test( pane, "foo", "c" ); | ||
| - test( pane, "foo.bar", "c" ); | ||
| - test( pane, "", "c" ); | ||
| - test( pane, "c", "protagonist" ); | ||
| - test( pane, "c.", "protagonist" ); | ||
| - test( pane, "c.p", "protagonist" ); | ||
| - test( pane, "c.protagonist", "protagonist" ); | ||
| - | ||
| - throw new RuntimeException( "Complete" ); | ||
| - } | ||
| - | ||
| - private void test( DefinitionPane pane, String path, String value ) { | ||
| - System.out.println( "---------------------------" ); | ||
| - System.out.println( "Find Path: '" + path + "'" ); | ||
| - final TreeItem<String> node = pane.findNode( path ); | ||
| - System.out.println( "Path Node: " + node ); | ||
| - System.out.println( "Node Val : " + node.getValue() ); | ||
| - } | ||
| - | ||
| - public static void main( String[] args ) { | ||
| - launch( args ); | ||
| - } | ||
| -} | ||
| -/* | ||
| - * 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.test; | ||
| - | ||
| -import static com.scrivenvar.Messages.get; | ||
| -import com.scrivenvar.definition.DefinitionPane; | ||
| -import com.scrivenvar.definition.yaml.YamlParser; | ||
| -import com.scrivenvar.definition.yaml.YamlTreeAdapter; | ||
| -import java.io.IOException; | ||
| -import java.io.InputStream; | ||
| -import javafx.application.Application; | ||
| -import javafx.scene.Scene; | ||
| -import javafx.scene.control.TreeView; | ||
| -import javafx.scene.layout.BorderPane; | ||
| -import javafx.stage.Stage; | ||
| -import org.fxmisc.flowless.VirtualizedScrollPane; | ||
| -import org.fxmisc.richtext.StyleClassedTextArea; | ||
| - | ||
| -/** | ||
| - * TestDefinitionPane application for debugging and head-banging. | ||
| - */ | ||
| -public abstract class TestHarness extends Application { | ||
| - | ||
| - private static Application app; | ||
| - private Scene scene; | ||
| - | ||
| - /** | ||
| - * Application entry point. | ||
| - * | ||
| - * @param stage The primary application stage. | ||
| - * | ||
| - * @throws Exception Could not read configuration file. | ||
| - */ | ||
| - @Override | ||
| - public void start( final Stage stage ) throws Exception { | ||
| - initApplication(); | ||
| - initScene(); | ||
| - initStage( stage ); | ||
| - } | ||
| - | ||
| - protected TreeView<String> createTreeView() throws IOException { | ||
| - return new YamlTreeAdapter( new YamlParser() ).adapt( | ||
| - asStream( "/com/scrivenvar/variables.yaml" ), | ||
| - get( "Pane.defintion.node.root.title" ) | ||
| - ); | ||
| - } | ||
| - | ||
| - protected DefinitionPane createDefinitionPane( TreeView<String> root ) { | ||
| - return new DefinitionPane( root ); | ||
| - } | ||
| - | ||
| - private void initApplication() { | ||
| - app = this; | ||
| - } | ||
| - | ||
| - private void initScene() { | ||
| - final StyleClassedTextArea editor = new StyleClassedTextArea( false ); | ||
| - final VirtualizedScrollPane<StyleClassedTextArea> scrollPane = new VirtualizedScrollPane<>( editor ); | ||
| - | ||
| - final BorderPane borderPane = new BorderPane(); | ||
| - borderPane.setPrefSize( 1024, 800 ); | ||
| - borderPane.setCenter( scrollPane ); | ||
| - | ||
| - setScene( new Scene( borderPane ) ); | ||
| - } | ||
| - | ||
| - private void initStage( Stage stage ) { | ||
| - stage.setScene( getScene() ); | ||
| - } | ||
| - | ||
| - private Scene getScene() { | ||
| - return this.scene; | ||
| - } | ||
| - | ||
| - private void setScene( Scene scene ) { | ||
| - this.scene = scene; | ||
| - } | ||
| - | ||
| - private static Application getApplication() { | ||
| - return app; | ||
| - } | ||
| - | ||
| - public static void showDocument( String uri ) { | ||
| - getApplication().getHostServices().showDocument( uri ); | ||
| - } | ||
| - | ||
| - protected InputStream asStream( String resource ) { | ||
| - return TestHarness.class.getResourceAsStream( resource ); | ||
| - } | ||
| -} | ||
| -/* | ||
| - * 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.test; | ||
| - | ||
| -import com.scrivenvar.definition.VariableTreeItem; | ||
| -import java.util.Collection; | ||
| -import java.util.HashMap; | ||
| -import java.util.Map; | ||
| -import static java.util.concurrent.ThreadLocalRandom.current; | ||
| -import java.util.concurrent.TimeUnit; | ||
| -import static java.util.concurrent.TimeUnit.DAYS; | ||
| -import static java.util.concurrent.TimeUnit.HOURS; | ||
| -import static java.util.concurrent.TimeUnit.MILLISECONDS; | ||
| -import static java.util.concurrent.TimeUnit.MINUTES; | ||
| -import static java.util.concurrent.TimeUnit.NANOSECONDS; | ||
| -import static java.util.concurrent.TimeUnit.SECONDS; | ||
| -import static javafx.application.Application.launch; | ||
| -import javafx.scene.control.TreeItem; | ||
| -import javafx.scene.control.TreeView; | ||
| -import javafx.stage.Stage; | ||
| -import org.ahocorasick.trie.*; | ||
| -import org.ahocorasick.trie.Trie.TrieBuilder; | ||
| -import static org.apache.commons.lang3.RandomStringUtils.randomNumeric; | ||
| -import org.apache.commons.lang3.StringUtils; | ||
| - | ||
| -/** | ||
| - * Tests substituting variable definitions with their values in a swath of text. | ||
| - * | ||
| - * @author White Magic Software, Ltd. | ||
| - */ | ||
| -public class TestVariableNameProcessor extends TestHarness { | ||
| - | ||
| - private final static int TEXT_SIZE = 1000000; | ||
| - private final static int MATCHES_DIVISOR = 1000; | ||
| - | ||
| - private final static StringBuilder SOURCE | ||
| - = new StringBuilder( randomNumeric( TEXT_SIZE ) ); | ||
| - | ||
| - private final static boolean DEBUG = false; | ||
| - | ||
| - public TestVariableNameProcessor() { | ||
| - } | ||
| - | ||
| - @Override | ||
| - public void start( final Stage stage ) throws Exception { | ||
| - super.start( stage ); | ||
| - | ||
| - final TreeView<String> treeView = createTreeView(); | ||
| - final Map<String, String> definitions = new HashMap<>(); | ||
| - | ||
| - populate( treeView.getRoot(), definitions ); | ||
| - injectVariables( definitions ); | ||
| - | ||
| - final String text = SOURCE.toString(); | ||
| - | ||
| - show( text ); | ||
| - | ||
| - long duration = System.nanoTime(); | ||
| - String result = testBorAhoCorasick( text, definitions ); | ||
| - duration = System.nanoTime() - duration; | ||
| - show( result ); | ||
| - System.out.println( elapsed( duration ) ); | ||
| - | ||
| - duration = System.nanoTime(); | ||
| - result = testStringUtils( text, definitions ); | ||
| - duration = System.nanoTime() - duration; | ||
| - show( result ); | ||
| - System.out.println( elapsed( duration ) ); | ||
| - | ||
| - throw new RuntimeException( "Complete" ); | ||
| - } | ||
| - | ||
| - private void show( final String s ) { | ||
| - if( DEBUG ) { | ||
| - System.out.printf( "%s%n%n", s ); | ||
| - } | ||
| - } | ||
| - | ||
| - private String testBorAhoCorasick( | ||
| - final String text, | ||
| - final Map<String, String> definitions ) { | ||
| - // Create a buffer sufficiently large that re-allocations are minimized. | ||
| - final StringBuilder sb = new StringBuilder( text.length() << 1 ); | ||
| - | ||
| - final TrieBuilder builder = Trie.builder(); | ||
| - builder.onlyWholeWords(); | ||
| - builder.removeOverlaps(); | ||
| - | ||
| - final String[] keys = keys( definitions ); | ||
| - | ||
| - for( final String key : keys ) { | ||
| - builder.addKeyword( key ); | ||
| - } | ||
| - | ||
| - final Trie trie = builder.build(); | ||
| - final Collection<Emit> emits = trie.parseText( text ); | ||
| - | ||
| - int prevIndex = 0; | ||
| - | ||
| - for( final Emit emit : emits ) { | ||
| - final int matchIndex = emit.getStart(); | ||
| - | ||
| - sb.append( text.substring( prevIndex, matchIndex ) ); | ||
| - sb.append( definitions.get( emit.getKeyword() ) ); | ||
| - prevIndex = emit.getEnd() + 1; | ||
| - } | ||
| - | ||
| - // Add the remainder of the string (contains no more matches). | ||
| - sb.append( text.substring( prevIndex ) ); | ||
| - | ||
| - return sb.toString(); | ||
| - } | ||
| - | ||
| - private String testStringUtils( | ||
| - final String text, final Map<String, String> definitions ) { | ||
| - final String[] keys = keys( definitions ); | ||
| - final String[] values = values( definitions ); | ||
| - | ||
| - return StringUtils.replaceEach( text, keys, values ); | ||
| - } | ||
| - | ||
| - private String[] keys( final Map<String, String> definitions ) { | ||
| - final int size = definitions.size(); | ||
| - return definitions.keySet().toArray( new String[ size ] ); | ||
| - } | ||
| - | ||
| - private String[] values( final Map<String, String> definitions ) { | ||
| - final int size = definitions.size(); | ||
| - return definitions.values().toArray( new String[ size ] ); | ||
| - } | ||
| - | ||
| - /** | ||
| - * Decomposes a period of time into days, hours, minutes, seconds, | ||
| - * milliseconds, and nanoseconds. | ||
| - * | ||
| - * @param duration Time in nanoseconds. | ||
| - * | ||
| - * @return A non-null, comma-separated string (without newline). | ||
| - */ | ||
| - public String elapsed( long duration ) { | ||
| - final TimeUnit scale = NANOSECONDS; | ||
| - | ||
| - long days = scale.toDays( duration ); | ||
| - duration -= DAYS.toMillis( days ); | ||
| - long hours = scale.toHours( duration ); | ||
| - duration -= HOURS.toMillis( hours ); | ||
| - long minutes = scale.toMinutes( duration ); | ||
| - duration -= MINUTES.toMillis( minutes ); | ||
| - long seconds = scale.toSeconds( duration ); | ||
| - duration -= SECONDS.toMillis( seconds ); | ||
| - long millis = scale.toMillis( duration ); | ||
| - duration -= MILLISECONDS.toMillis( seconds ); | ||
| - long nanos = scale.toNanos( duration ); | ||
| - | ||
| - return String.format( | ||
| - "%d days, %d hours, %d minutes, %d seconds, %d millis, %d nanos", | ||
| - days, hours, minutes, seconds, millis, nanos | ||
| - ); | ||
| - } | ||
| - | ||
| - private void injectVariables( final Map<String, String> definitions ) { | ||
| - for( int i = (SOURCE.length() / MATCHES_DIVISOR) + 1; i > 0; i-- ) { | ||
| - final int r = current().nextInt( 1, SOURCE.length() ); | ||
| - SOURCE.insert( r, randomKey( definitions ) ); | ||
| - } | ||
| - } | ||
| - | ||
| - private String randomKey( final Map<String, String> map ) { | ||
| - final Object[] keys = map.keySet().toArray(); | ||
| - final int r = current().nextInt( keys.length ); | ||
| - return keys[ r ].toString(); | ||
| - } | ||
| - | ||
| - private void populate( final TreeItem<String> parent, final Map<String, String> map ) { | ||
| - for( final TreeItem<String> child : parent.getChildren() ) { | ||
| - if( child.isLeaf() ) { | ||
| - final VariableTreeItem<String> item; | ||
| - | ||
| - if( child instanceof VariableTreeItem ) { | ||
| - item = ((VariableTreeItem<String>)child); | ||
| - } else { | ||
| - throw new IllegalArgumentException( | ||
| - "Child must be subclass of VariableTreeItem: " + child ); | ||
| - } | ||
| - | ||
| - final String key = asDefinition( item.toPath() ); | ||
| - final String value = child.getValue(); | ||
| - | ||
| - map.put( key, value ); | ||
| - } else { | ||
| - populate( child, map ); | ||
| - } | ||
| - } | ||
| - } | ||
| - | ||
| - private String asDefinition( final String key ) { | ||
| - return "$" + key + "$"; | ||
| - } | ||
| - | ||
| - public static void main( String[] args ) { | ||
| - launch( args ); | ||
| - } | ||
| -} | ||