Optimize imports

Reformatted code (Java convention; tab is 4 spaces)
This commit is contained in:
robert-bor 2016-11-30 09:10:21 +01:00
parent 90d4645d49
commit b5aaa51fdd
12 changed files with 187 additions and 180 deletions

View File

@ -1,4 +1,5 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.ahocorasick</groupId> <groupId>org.ahocorasick</groupId>

View File

@ -75,9 +75,9 @@ public class IntervalNode {
} }
protected void addToOverlaps( protected void addToOverlaps(
final Intervalable interval, final Intervalable interval,
final List<Intervalable> overlaps, final List<Intervalable> overlaps,
final List<Intervalable> newOverlaps) { final List<Intervalable> newOverlaps) {
for (final Intervalable currentInterval : newOverlaps) { for (final Intervalable currentInterval : newOverlaps) {
if (!currentInterval.equals(interval)) { if (!currentInterval.equals(interval)) {
overlaps.add(currentInterval); overlaps.add(currentInterval);
@ -94,9 +94,9 @@ public class IntervalNode {
} }
protected List<Intervalable> checkForOverlaps( protected List<Intervalable> checkForOverlaps(
final Intervalable interval, final Direction direction) { final Intervalable interval, final Direction direction) {
final List<Intervalable> overlaps = new ArrayList<>(); final List<Intervalable> overlaps = new ArrayList<>();
for (final Intervalable currentInterval : this.intervals) { for (final Intervalable currentInterval : this.intervals) {
switch (direction) { switch (direction) {
case LEFT: case LEFT:
@ -111,13 +111,13 @@ public class IntervalNode {
break; break;
} }
} }
return overlaps; return overlaps;
} }
protected List<Intervalable> findOverlappingRanges(IntervalNode node, Intervalable interval) { protected List<Intervalable> findOverlappingRanges(IntervalNode node, Intervalable interval) {
return node == null return node == null
? Collections.<Intervalable>emptyList() ? Collections.<Intervalable>emptyList()
: node.findOverlaps( interval ); : node.findOverlaps(interval);
} }
} }

View File

@ -1,10 +1,11 @@
package org.ahocorasick.interval; package org.ahocorasick.interval;
import static java.util.Collections.sort;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import static java.util.Collections.sort;
public class IntervalTree { public class IntervalTree {
private final IntervalNode rootNode; private final IntervalNode rootNode;

View File

@ -7,11 +7,11 @@ public class IntervalableComparatorBySize implements Comparator<Intervalable> {
@Override @Override
public int compare(final Intervalable intervalable, final Intervalable intervalable2) { public int compare(final Intervalable intervalable, final Intervalable intervalable2) {
int comparison = intervalable2.size() - intervalable.size(); int comparison = intervalable2.size() - intervalable.size();
if (comparison == 0) { if (comparison == 0) {
comparison = intervalable.getStart() - intervalable2.getStart(); comparison = intervalable.getStart() - intervalable2.getStart();
} }
return comparison; return comparison;
} }

View File

@ -4,43 +4,51 @@ import java.util.*;
/** /**
* <p> * <p>
* A state has various important tasks it must attend to: * A state has various important tasks it must attend to:
* </p> * </p>
*
* <ul>
* <li>success; when a character points to another state, it must return that state</li>
* <li>failure; when a character has no matching state, the algorithm must be able to fall back on a
* state with less depth</li>
* <li>emits; when this state is passed and keywords have been matched, the matches must be
* 'emitted' so that they can be used later on.</li>
* </ul>
*
* <p> * <p>
* The root state is special in the sense that it has no failure state; it cannot fail. If it 'fails' * <ul>
* it will still parse the next character and start from the root node. This ensures that the algorithm * <li>success; when a character points to another state, it must return that state</li>
* always runs. All other states always have a fail state. * <li>failure; when a character has no matching state, the algorithm must be able to fall back on a
* state with less depth</li>
* <li>emits; when this state is passed and keywords have been matched, the matches must be
* 'emitted' so that they can be used later on.</li>
* </ul>
* <p>
* <p>
* The root state is special in the sense that it has no failure state; it cannot fail. If it 'fails'
* it will still parse the next character and start from the root node. This ensures that the algorithm
* always runs. All other states always have a fail state.
* </p> * </p>
* *
* @author Robert Bor * @author Robert Bor
*/ */
public class State { public class State {
/** effective the size of the keyword */ /**
* effective the size of the keyword
*/
private final int depth; private final int depth;
/** only used for the root state to refer to itself in case no matches have been found */ /**
* only used for the root state to refer to itself in case no matches have been found
*/
private final State rootState; private final State rootState;
/** /**
* referred to in the white paper as the 'goto' structure. From a state it is possible to go * referred to in the white paper as the 'goto' structure. From a state it is possible to go
* to other states, depending on the character passed. * to other states, depending on the character passed.
*/ */
private final Map<Character,State> success = new HashMap<>(); private final Map<Character, State> success = new HashMap<>();
/** if no matching states are found, the failure state will be returned */ /**
* if no matching states are found, the failure state will be returned
*/
private State failure; private State failure;
/** whenever this state is reached, it will emit the matches keywords for future reference */ /**
* whenever this state is reached, it will emit the matches keywords for future reference
*/
private Set<String> emits; private Set<String> emits;
public State() { public State() {
@ -54,11 +62,11 @@ public class State {
private State nextState(final Character character, final boolean ignoreRootState) { private State nextState(final Character character, final boolean ignoreRootState) {
State nextState = this.success.get(character); State nextState = this.success.get(character);
if (!ignoreRootState && nextState == null && this.rootState != null) { if (!ignoreRootState && nextState == null && this.rootState != null) {
nextState = this.rootState; nextState = this.rootState;
} }
return nextState; return nextState;
} }
@ -69,21 +77,21 @@ public class State {
public State nextStateIgnoreRootState(final Character character) { public State nextStateIgnoreRootState(final Character character) {
return nextState(character, true); return nextState(character, true);
} }
public State addState(final String keyword ) { public State addState(final String keyword) {
State state = this; State state = this;
for (final Character character : keyword.toCharArray()) { for (final Character character : keyword.toCharArray()) {
state = state.addState(character); state = state.addState(character);
} }
return state; return state;
} }
public State addState(final Character character) { public State addState(final Character character) {
State nextState = nextStateIgnoreRootState(character); State nextState = nextStateIgnoreRootState(character);
if (nextState == null) { if (nextState == null) {
nextState = new State(this.depth+1); nextState = new State(this.depth + 1);
this.success.put(character, nextState); this.success.put(character, nextState);
} }
return nextState; return nextState;
@ -107,7 +115,7 @@ public class State {
} }
public Collection<String> emit() { public Collection<String> emit() {
return this.emits == null ? Collections.<String> emptyList() : this.emits; return this.emits == null ? Collections.<String>emptyList() : this.emits;
} }
public State failure() { public State failure() {

View File

@ -1,22 +1,24 @@
package org.ahocorasick.trie; package org.ahocorasick.trie;
import static java.lang.Character.isAlphabetic;
import static java.lang.Character.isWhitespace;
import static java.lang.Character.toLowerCase;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingDeque;
import org.ahocorasick.interval.IntervalTree; import org.ahocorasick.interval.IntervalTree;
import org.ahocorasick.interval.Intervalable; import org.ahocorasick.interval.Intervalable;
import org.ahocorasick.trie.handler.DefaultEmitHandler; import org.ahocorasick.trie.handler.DefaultEmitHandler;
import org.ahocorasick.trie.handler.EmitHandler; import org.ahocorasick.trie.handler.EmitHandler;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingDeque;
import static java.lang.Character.*;
import java.lang.Character;
/** /**
* Based on the Aho-Corasick white paper, Bell technologies: * Based on the Aho-Corasick white paper, Bell technologies:
* http://cr.yp.to/bib/1975/aho.pdf * http://cr.yp.to/bib/1975/aho.pdf
* *
* @author Robert Bor * @author Robert Bor
*/ */
public class Trie { public class Trie {
@ -29,42 +31,41 @@ public class Trie {
this.trieConfig = trieConfig; this.trieConfig = trieConfig;
this.rootState = new State(); this.rootState = new State();
} }
/** /**
* Used by the builder to add a text search keyword. * Used by the builder to add a text search keyword.
* *
* @param keyword The search term to add to the list of search terms. * @param keyword The search term to add to the list of search terms.
*
* @throws NullPointerException if the keyword is null. * @throws NullPointerException if the keyword is null.
*/ */
private void addKeyword( String keyword ) { private void addKeyword(String keyword) {
if( keyword.length() > 0 ) { if (keyword.length() > 0) {
if( isCaseInsensitive() ) { if (isCaseInsensitive()) {
keyword = keyword.toLowerCase(); keyword = keyword.toLowerCase();
} }
addState( keyword ).addEmit( keyword ); addState(keyword).addEmit(keyword);
} }
} }
private State addState( final String keyword ) { private State addState(final String keyword) {
return getRootState().addState( keyword ); return getRootState().addState(keyword);
} }
public Collection<Token> tokenize(final String text) { public Collection<Token> tokenize(final String text) {
final Collection<Token> tokens = new ArrayList<>(); final Collection<Token> tokens = new ArrayList<>();
final Collection<Emit> collectedEmits = parseText(text); final Collection<Emit> collectedEmits = parseText(text);
int lastCollectedPosition = -1; int lastCollectedPosition = -1;
for (final Emit emit : collectedEmits) { for (final Emit emit : collectedEmits) {
if (emit.getStart() - lastCollectedPosition > 1) { if (emit.getStart() - lastCollectedPosition > 1) {
tokens.add(createFragment(emit, text, lastCollectedPosition)); tokens.add(createFragment(emit, text, lastCollectedPosition));
} }
tokens.add(createMatch(emit, text)); tokens.add(createMatch(emit, text));
lastCollectedPosition = emit.getEnd(); lastCollectedPosition = emit.getEnd();
} }
if (text.length() - lastCollectedPosition > 1) { if (text.length() - lastCollectedPosition > 1) {
tokens.add(createFragment(null, text, lastCollectedPosition)); tokens.add(createFragment(null, text, lastCollectedPosition));
} }
@ -73,14 +74,14 @@ public class Trie {
} }
private Token createFragment( private Token createFragment(
final Emit emit, final Emit emit,
final String text, final String text,
final int lastCollectedPosition) { final int lastCollectedPosition) {
return new FragmentToken(text.substring(lastCollectedPosition+1, emit == null ? text.length() : emit.getStart())); return new FragmentToken(text.substring(lastCollectedPosition + 1, emit == null ? text.length() : emit.getStart()));
} }
private Token createMatch(final Emit emit, final String text) { private Token createMatch(final Emit emit, final String text) {
return new MatchToken(text.substring(emit.getStart(), emit.getEnd()+1), emit); return new MatchToken(text.substring(emit.getStart(), emit.getEnd() + 1), emit);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -99,7 +100,7 @@ public class Trie {
} }
if (!trieConfig.isAllowOverlaps()) { if (!trieConfig.isAllowOverlaps()) {
IntervalTree intervalTree = new IntervalTree((List<Intervalable>)(List<?>)collectedEmits); IntervalTree intervalTree = new IntervalTree((List<Intervalable>) (List<?>) collectedEmits);
intervalTree.removeOverlaps((List<Intervalable>) (List<?>) collectedEmits); intervalTree.removeOverlaps((List<Intervalable>) (List<?>) collectedEmits);
} }
@ -112,15 +113,15 @@ public class Trie {
public void parseText(final CharSequence text, final EmitHandler emitHandler) { public void parseText(final CharSequence text, final EmitHandler emitHandler) {
State currentState = getRootState(); State currentState = getRootState();
for (int position = 0; position < text.length(); position++) { for (int position = 0; position < text.length(); position++) {
Character character = text.charAt(position); Character character = text.charAt(position);
// TODO: Maybe lowercase the entire string at once? // TODO: Maybe lowercase the entire string at once?
if (trieConfig.isCaseInsensitive()) { if (trieConfig.isCaseInsensitive()) {
character = toLowerCase(character); character = toLowerCase(character);
} }
currentState = getState(currentState, character); currentState = getState(currentState, character);
if (storeEmits(position, currentState, emitHandler) && trieConfig.isStopOnHit()) { if (storeEmits(position, currentState, emitHandler) && trieConfig.isStopOnHit()) {
return; return;
@ -138,18 +139,18 @@ public class Trie {
} else { } else {
// Fast path. Returns first match found. // Fast path. Returns first match found.
State currentState = getRootState(); State currentState = getRootState();
for (int position = 0; position < text.length(); position++) { for (int position = 0; position < text.length(); position++) {
Character character = text.charAt(position); Character character = text.charAt(position);
// TODO: Lowercase the entire string at once? // TODO: Lowercase the entire string at once?
if (trieConfig.isCaseInsensitive()) { if (trieConfig.isCaseInsensitive()) {
character = toLowerCase(character); character = toLowerCase(character);
} }
currentState = getState(currentState, character); currentState = getState(currentState, character);
Collection<String> emitStrs = currentState.emit(); Collection<String> emitStrs = currentState.emit();
if (emitStrs != null && !emitStrs.isEmpty()) { if (emitStrs != null && !emitStrs.isEmpty()) {
for (final String emitStr : emitStrs) { for (final String emitStr : emitStrs) {
final Emit emit = new Emit(position - emitStr.length() + 1, position, emitStr); final Emit emit = new Emit(position - emitStr.length() + 1, position, emitStr);
@ -164,26 +165,26 @@ public class Trie {
} }
} }
} }
return null; return null;
} }
private boolean isPartialMatch(final CharSequence searchText, final Emit emit) { private boolean isPartialMatch(final CharSequence searchText, final Emit emit) {
return (emit.getStart() != 0 && return (emit.getStart() != 0 &&
isAlphabetic(searchText.charAt(emit.getStart() - 1))) || isAlphabetic(searchText.charAt(emit.getStart() - 1))) ||
(emit.getEnd() + 1 != searchText.length() && (emit.getEnd() + 1 != searchText.length() &&
isAlphabetic(searchText.charAt(emit.getEnd() + 1))); isAlphabetic(searchText.charAt(emit.getEnd() + 1)));
} }
private void removePartialMatches(final CharSequence searchText, final List<Emit> collectedEmits) { private void removePartialMatches(final CharSequence searchText, final List<Emit> collectedEmits) {
final List<Emit> removeEmits = new ArrayList<>(); final List<Emit> removeEmits = new ArrayList<>();
for (final Emit emit : collectedEmits) { for (final Emit emit : collectedEmits) {
if (isPartialMatch(searchText, emit)) { if (isPartialMatch(searchText, emit)) {
removeEmits.add(emit); removeEmits.add(emit);
} }
} }
for (final Emit removeEmit : removeEmits) { for (final Emit removeEmit : removeEmits) {
collectedEmits.remove(removeEmit); collectedEmits.remove(removeEmit);
} }
@ -192,15 +193,15 @@ public class Trie {
private void removePartialMatchesWhiteSpaceSeparated(final CharSequence searchText, final List<Emit> collectedEmits) { private void removePartialMatchesWhiteSpaceSeparated(final CharSequence searchText, final List<Emit> collectedEmits) {
final long size = searchText.length(); final long size = searchText.length();
final List<Emit> removeEmits = new ArrayList<>(); final List<Emit> removeEmits = new ArrayList<>();
for (final Emit emit : collectedEmits) { for (final Emit emit : collectedEmits) {
if ((emit.getStart() == 0 || isWhitespace(searchText.charAt(emit.getStart() - 1))) && if ((emit.getStart() == 0 || isWhitespace(searchText.charAt(emit.getStart() - 1))) &&
(emit.getEnd() + 1 == size || isWhitespace(searchText.charAt(emit.getEnd() + 1)))) { (emit.getEnd() + 1 == size || isWhitespace(searchText.charAt(emit.getEnd() + 1)))) {
continue; continue;
} }
removeEmits.add(emit); removeEmits.add(emit);
} }
for (final Emit removeEmit : removeEmits) { for (final Emit removeEmit : removeEmits) {
collectedEmits.remove(removeEmit); collectedEmits.remove(removeEmit);
} }
@ -209,12 +210,12 @@ public class Trie {
private State getState(final State initialState, final Character character) { private State getState(final State initialState, final Character character) {
State currentState = initialState; State currentState = initialState;
State updatedState = currentState.nextState(character); State updatedState = currentState.nextState(character);
while (updatedState == null) { while (updatedState == null) {
currentState = currentState.failure(); currentState = currentState.failure();
updatedState = currentState.nextState(character); updatedState = currentState.nextState(character);
} }
return updatedState; return updatedState;
} }
@ -249,12 +250,12 @@ public class Trie {
} }
private boolean storeEmits( private boolean storeEmits(
final int position, final int position,
final State currentState, final State currentState,
final EmitHandler emitHandler) { final EmitHandler emitHandler) {
boolean emitted = false; boolean emitted = false;
final Collection<String> emits = currentState.emit(); final Collection<String> emits = currentState.emit();
// TODO: The check for empty might be superfluous. // TODO: The check for empty might be superfluous.
if (emits != null && !emits.isEmpty()) { if (emits != null && !emits.isEmpty()) {
for (final String emit : emits) { for (final String emit : emits) {
@ -262,22 +263,22 @@ public class Trie {
emitted = true; emitted = true;
} }
} }
return emitted; return emitted;
} }
private boolean isCaseInsensitive() { private boolean isCaseInsensitive() {
return trieConfig.isCaseInsensitive(); return trieConfig.isCaseInsensitive();
} }
private State getRootState() { private State getRootState() {
return this.rootState; return this.rootState;
} }
/** /**
* Constructs a TrieBuilder instance for configuring the Trie using a fluent * Constructs a TrieBuilder instance for configuring the Trie using a fluent
* interface. * interface.
* *
* @return The builder used to configure its Trie. * @return The builder used to configure its Trie.
*/ */
public static TrieBuilder builder() { public static TrieBuilder builder() {
@ -296,31 +297,30 @@ public class Trie {
/** /**
* Default (empty) constructor. * Default (empty) constructor.
*/ */
private TrieBuilder() {} private TrieBuilder() {
}
/** /**
* Adds a keyword to the Trie's list of text search keywords. * Adds a keyword to the Trie's list of text search keywords.
* *
* @param keyword The keyword to add to the list. * @param keyword The keyword to add to the list.
*
* @return This builder. * @return This builder.
* @throws NullPointerException if the keyword is null. * @throws NullPointerException if the keyword is null.
*/ */
public TrieBuilder addKeyword(final CharSequence keyword) { public TrieBuilder addKeyword(final CharSequence keyword) {
getTrie().addKeyword( keyword.toString() ); getTrie().addKeyword(keyword.toString());
return this; return this;
} }
/** /**
* Adds a list of keywords to the Trie's list of text search keywords. * Adds a list of keywords to the Trie's list of text search keywords.
* *
* @param keywords The keywords to add to the list. * @param keywords The keywords to add to the list.
*
* @return This builder. * @return This builder.
*/ */
public TrieBuilder addKeywords(final CharSequence... keywords) { public TrieBuilder addKeywords(final CharSequence... keywords) {
for( final CharSequence keyword : keywords ) { for (final CharSequence keyword : keywords) {
addKeyword( keyword ); addKeyword(keyword);
} }
return this; return this;
@ -328,19 +328,18 @@ public class Trie {
/** /**
* Adds a list of keywords to the Trie's list of text search keywords. * Adds a list of keywords to the Trie's list of text search keywords.
* *
* @param keywords The keywords to add to the list. * @param keywords The keywords to add to the list.
*
* @return This builder. * @return This builder.
*/ */
public TrieBuilder addKeywords(final Collection<CharSequence> keywords) { public TrieBuilder addKeywords(final Collection<CharSequence> keywords) {
return addKeywords( keywords.toArray( new CharSequence[ keywords.size() ] ) ); return addKeywords(keywords.toArray(new CharSequence[keywords.size()]));
} }
/** /**
* Configure the Trie to ignore case when searching for keywords in the * Configure the Trie to ignore case when searching for keywords in the
* text. * text.
* *
* @return This builder. * @return This builder.
*/ */
public TrieBuilder ignoreCase() { public TrieBuilder ignoreCase() {
@ -350,7 +349,7 @@ public class Trie {
/** /**
* Configure the Trie to ignore overlapping keywords. * Configure the Trie to ignore overlapping keywords.
* *
* @return This builder. * @return This builder.
*/ */
public TrieBuilder ignoreOverlaps() { public TrieBuilder ignoreOverlaps() {
@ -360,7 +359,7 @@ public class Trie {
/** /**
* Configure the Trie to match whole keywords in the text. * Configure the Trie to match whole keywords in the text.
* *
* @return This builder. * @return This builder.
*/ */
public TrieBuilder onlyWholeWords() { public TrieBuilder onlyWholeWords() {
@ -372,18 +371,18 @@ public class Trie {
* Configure the Trie to match whole keywords that are separated by * Configure the Trie to match whole keywords that are separated by
* whitespace in the text. For example, "this keyword thatkeyword" * whitespace in the text. For example, "this keyword thatkeyword"
* would only match the first occurrence of "keyword". * would only match the first occurrence of "keyword".
* *
* @return This builder. * @return This builder.
*/ */
public TrieBuilder onlyWholeWordsWhiteSpaceSeparated() { public TrieBuilder onlyWholeWordsWhiteSpaceSeparated() {
getTrieConfig().setOnlyWholeWordsWhiteSpaceSeparated(true); getTrieConfig().setOnlyWholeWordsWhiteSpaceSeparated(true);
return this; return this;
} }
/** /**
* Configure the Trie to stop searching for matches after the first * Configure the Trie to stop searching for matches after the first
* keyword is found in the text. * keyword is found in the text.
* *
* @return This builder. * @return This builder.
*/ */
public TrieBuilder onlyFirstMatch() { public TrieBuilder onlyFirstMatch() {
@ -393,27 +392,27 @@ public class Trie {
/** /**
* Construct the Trie using the builder settings. * Construct the Trie using the builder settings.
* *
* @return The configured Trie. * @return The configured Trie.
*/ */
public Trie build() { public Trie build() {
getTrie().constructFailureStates(); getTrie().constructFailureStates();
return getTrie(); return getTrie();
} }
private Trie getTrie() { private Trie getTrie() {
return this.trie; return this.trie;
} }
private TrieConfig getTrieConfig() { private TrieConfig getTrieConfig() {
return this.trieConfig; return this.trieConfig;
} }
/** /**
* @deprecated Use onlyFirstMatch() * @deprecated Use onlyFirstMatch()
*/ */
public TrieBuilder stopOnHit() { public TrieBuilder stopOnHit() {
return onlyFirstMatch(); return onlyFirstMatch();
} }
/** /**

View File

@ -1,8 +1,9 @@
package org.ahocorasick.trie.handler; package org.ahocorasick.trie.handler;
import org.ahocorasick.trie.Emit;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.ahocorasick.trie.Emit;
public class DefaultEmitHandler implements EmitHandler { public class DefaultEmitHandler implements EmitHandler {

View File

@ -2,11 +2,11 @@ package org.ahocorasick.interval;
import org.junit.Test; import org.junit.Test;
import java.util.*; import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.*;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
public class IntervalTest { public class IntervalTest {

View File

@ -3,10 +3,9 @@ package org.ahocorasick.interval;
import org.junit.Test; import org.junit.Test;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import static java.util.Collections.sort;
import java.util.List; import java.util.List;
import static java.util.Collections.sort;
import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertEquals;
public class IntervalableComparatorByPositionTest { public class IntervalableComparatorByPositionTest {
@ -14,9 +13,9 @@ public class IntervalableComparatorByPositionTest {
@Test @Test
public void sortOnPosition() { public void sortOnPosition() {
List<Intervalable> intervals = new ArrayList<>(); List<Intervalable> intervals = new ArrayList<>();
intervals.add(new Interval(4,5)); intervals.add(new Interval(4, 5));
intervals.add(new Interval(1,4)); intervals.add(new Interval(1, 4));
intervals.add(new Interval(3,8)); intervals.add(new Interval(3, 8));
sort(intervals, new IntervalableComparatorByPosition()); sort(intervals, new IntervalableComparatorByPosition());
assertEquals(4, intervals.get(0).size()); assertEquals(4, intervals.get(0).size());
assertEquals(6, intervals.get(1).size()); assertEquals(6, intervals.get(1).size());

View File

@ -3,11 +3,9 @@ package org.ahocorasick.interval;
import org.junit.Test; import org.junit.Test;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import static java.util.Collections.sort;
import static java.util.Collections.sort;
import java.util.List; import java.util.List;
import static java.util.Collections.sort;
import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertEquals;
public class IntervalableComparatorBySizeTest { public class IntervalableComparatorBySizeTest {
@ -15,9 +13,9 @@ public class IntervalableComparatorBySizeTest {
@Test @Test
public void sortOnSize() { public void sortOnSize() {
List<Intervalable> intervals = new ArrayList<>(); List<Intervalable> intervals = new ArrayList<>();
intervals.add(new Interval(4,5)); intervals.add(new Interval(4, 5));
intervals.add(new Interval(1,4)); intervals.add(new Interval(1, 4));
intervals.add(new Interval(3,8)); intervals.add(new Interval(3, 8));
sort(intervals, new IntervalableComparatorBySize()); sort(intervals, new IntervalableComparatorBySize());
assertEquals(6, intervals.get(0).size()); assertEquals(6, intervals.get(0).size());
assertEquals(4, intervals.get(1).size()); assertEquals(4, intervals.get(1).size());
@ -27,8 +25,8 @@ public class IntervalableComparatorBySizeTest {
@Test @Test
public void sortOnSizeThenPosition() { public void sortOnSizeThenPosition() {
List<Intervalable> intervals = new ArrayList<>(); List<Intervalable> intervals = new ArrayList<>();
intervals.add(new Interval(4,7)); intervals.add(new Interval(4, 7));
intervals.add(new Interval(2,5)); intervals.add(new Interval(2, 5));
sort(intervals, new IntervalableComparatorBySize()); sort(intervals, new IntervalableComparatorBySize());
assertEquals(2, intervals.get(0).getStart()); assertEquals(2, intervals.get(0).getStart());
assertEquals(4, intervals.get(1).getStart()); assertEquals(4, intervals.get(1).getStart());

View File

@ -1,6 +1,5 @@
package org.ahocorasick.trie; package org.ahocorasick.trie;
import org.ahocorasick.trie.State;
import org.junit.Test; import org.junit.Test;
import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertEquals;

View File

@ -1,36 +1,37 @@
package org.ahocorasick.trie; package org.ahocorasick.trie;
import org.ahocorasick.trie.handler.EmitHandler;
import org.junit.Test;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import static java.util.concurrent.ThreadLocalRandom.current; import static java.util.concurrent.ThreadLocalRandom.current;
import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertEquals;
import static org.ahocorasick.trie.Trie.builder; import static org.ahocorasick.trie.Trie.builder;
import org.ahocorasick.trie.handler.EmitHandler;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class TrieTest { public class TrieTest {
private final static String[] ALPHABET = new String[]{ private final static String[] ALPHABET = new String[]{
"abc", "bcd", "cde" "abc", "bcd", "cde"
}; };
private final static String[] PRONOUNS = new String[]{ private final static String[] PRONOUNS = new String[]{
"hers", "his", "she", "he" "hers", "his", "she", "he"
}; };
private final static String[] FOOD = new String[]{ private final static String[] FOOD = new String[]{
"veal", "cauliflower", "broccoli", "tomatoes" "veal", "cauliflower", "broccoli", "tomatoes"
}; };
private final static String[] GREEK_LETTERS = new String[]{ private final static String[] GREEK_LETTERS = new String[]{
"Alpha", "Beta", "Gamma" "Alpha", "Beta", "Gamma"
}; };
private final static String[] UNICODE = new String[]{ private final static String[] UNICODE = new String[]{
"turning", "once", "again", "börkü" "turning", "once", "again", "börkü"
}; };
@Test @Test
@ -408,7 +409,7 @@ public class TrieTest {
.onlyWholeWordsWhiteSpaceSeparated() .onlyWholeWordsWhiteSpaceSeparated()
.addKeyword("#sugar-123") .addKeyword("#sugar-123")
.build(); .build();
Collection < Emit > emits = trie.parseText("#sugar-123 #sugar-1234"); // left, middle, right test Collection<Emit> emits = trie.parseText("#sugar-123 #sugar-1234"); // left, middle, right test
assertEquals(1, emits.size()); // Match must not be made assertEquals(1, emits.size()); // Match must not be made
checkEmit(emits.iterator().next(), 0, 9, "#sugar-123"); checkEmit(emits.iterator().next(), 0, 9, "#sugar-123");
} }
@ -417,57 +418,57 @@ public class TrieTest {
public void testLargeString() { public void testLargeString() {
final int interval = 100; final int interval = 100;
final int textSize = 1000000; final int textSize = 1000000;
final String keyword = FOOD[ 1 ]; final String keyword = FOOD[1];
final StringBuilder text = randomNumbers( textSize ); final StringBuilder text = randomNumbers(textSize);
injectKeyword( text, keyword, interval ); injectKeyword(text, keyword, interval);
Trie trie = builder() Trie trie = builder()
.onlyWholeWords() .onlyWholeWords()
.addKeyword( keyword ) .addKeyword(keyword)
.build(); .build();
final Collection<Emit> emits = trie.parseText( text ); final Collection<Emit> emits = trie.parseText(text);
assertEquals( textSize / interval, emits.size() ); assertEquals(textSize / interval, emits.size());
} }
/** /**
* Generates a random sequence of ASCII numbers. * Generates a random sequence of ASCII numbers.
* *
* @param count The number of numbers to generate. * @param count The number of numbers to generate.
* @return A character sequence filled with random digits. * @return A character sequence filled with random digits.
*/ */
private StringBuilder randomNumbers( final int count ) { private StringBuilder randomNumbers(final int count) {
final StringBuilder sb = new StringBuilder( count ); final StringBuilder sb = new StringBuilder(count);
for( int i = count - 1; i >= 0; i-- ) { for (int i = count - 1; i >= 0; i--) {
sb.append( randomInt( 0, 10 ) ); sb.append(randomInt(0, 10));
} }
return sb; return sb;
} }
/** /**
* Injects keywords into a string builder. * Injects keywords into a string builder.
* *
* @param source Should contain a bunch of random data that cannot match * @param source Should contain a bunch of random data that cannot match
* any keyword. * any keyword.
* @param keyword A keyword to inject repeatedly in the text. * @param keyword A keyword to inject repeatedly in the text.
* @param interval How often to inject the keyword. * @param interval How often to inject the keyword.
*/ */
private void injectKeyword( private void injectKeyword(
final StringBuilder source, final StringBuilder source,
final String keyword, final String keyword,
final int interval ) { final int interval) {
final int length = source.length(); final int length = source.length();
for( int i = 0; i < length; i += interval ) { for (int i = 0; i < length; i += interval) {
source.replace( i, i + keyword.length(), keyword ); source.replace(i, i + keyword.length(), keyword);
} }
} }
private int randomInt( final int min, final int max ) { private int randomInt(final int min, final int max) {
return current().nextInt( min, max ); return current().nextInt(min, max);
} }
private void checkEmit(Emit next, int expectedStart, int expectedEnd, String expectedKeyword) { private void checkEmit(Emit next, int expectedStart, int expectedEnd, String expectedKeyword) {