package com.scrivenvar;
import com.scrivenvar.ui.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.lang.RandomStringUtils.randomNumeric;
import org.apache.commons.lang.StringUtils;
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();
final String result = testBorAhoCorasick( text, definitions );
duration = System.nanoTime() - duration;
show( result );
System.out.println( elapsed( duration ) );
System.exit( 0 );
}
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 ) {
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;
}
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 ] );
}
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 String key = asDefinition( ((VariableTreeItem<String>)child).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 );
}
}