Merge pull request #46 from robert-bor/feature/badges-and-quality

Dev tooling enabled
This commit is contained in:
Robert Bor 2016-11-30 08:47:08 +01:00 committed by GitHub
commit a89a6bac95
15 changed files with 286 additions and 196 deletions

6
.travis.yml Normal file
View File

@ -0,0 +1,6 @@
language: java
install: mvn install -DskipTests=true -Dgpg.skip=true
jdk:
- oraclejdk8
after_success:
- bash <(curl -s https://codecov.io/bash)

View File

@ -1,6 +1,12 @@
Aho-Corasick Aho-Corasick
============ ============
[![Build Status](https://travis-ci.org/robert-bor/aho-corasick.svg?branch=master)](https://travis-ci.org/robert-bor/aho-corasick)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/0f65bfb641f745a4b301b85d028a4a8d)](https://www.codacy.com/app/bor-robert/aho-corasick)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.ahocorasick/ahocorasick/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.ahocorasick/ahocorasick)
[![Javadoc](https://javadoc-emblem.rhcloud.com/doc/org.ahocorasick/ahocorasick/badge.svg)](http://www.javadoc.io/doc/org.ahocorasick/ahocorasick)
[![Apache 2](http://img.shields.io/badge/license-Apache%202-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0)
Dependency Dependency
---------- ----------
Include this dependency in your POM. Be sure to check for the latest version in Maven Central. Include this dependency in your POM. Be sure to check for the latest version in Maven Central.

113
pom.xml
View File

@ -10,11 +10,16 @@
<inceptionYear>2014</inceptionYear> <inceptionYear>2014</inceptionYear>
<url>http://ahocorasick.org</url> <url>http://ahocorasick.org</url>
<parent> <distributionManagement>
<groupId>org.sonatype.oss</groupId> <snapshotRepository>
<artifactId>oss-parent</artifactId> <id>ossrh</id>
<version>7</version> <url>https://oss.sonatype.org/content/repositories/snapshots</url>
</parent> </snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<organization> <organization>
<name>42 BV</name> <name>42 BV</name>
@ -39,9 +44,15 @@
<name>Robert Bor</name> <name>Robert Bor</name>
<organization>42</organization> <organization>42</organization>
</developer> </developer>
<developer>
<name></name>
</developer>
</developers> </developers>
<properties> <properties>
<java.version>1.7</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.version>4.10</junit.version> <junit.version>4.10</junit.version>
<!-- Reporting --> <!-- Reporting -->
<maven.cobertura.version>2.5.2</maven.cobertura.version> <maven.cobertura.version>2.5.2</maven.cobertura.version>
@ -63,15 +74,19 @@
</dependencies> </dependencies>
<build> <build>
<defaultGoal>install</defaultGoal> <defaultGoal>install</defaultGoal>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.sonatype.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId> <artifactId>nexus-staging-maven-plugin</artifactId>
<version>2.4</version> <version>1.6.7</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>false</autoReleaseAfterClose>
</configuration>
</plugin> </plugin>
<plugin> <plugin>
@ -79,30 +94,76 @@
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version> <version>3.6.0</version>
<configuration> <configuration>
<source>1.7</source> <source>${java.version}</source>
<target>1.7</target> <target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration> </configuration>
</plugin> </plugin>
</plugins>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>${maven.cobertura.version}</version>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>${maven.javadoc.version}</version> <version>2.9.1</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.7.201606060606</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin> </plugin>
</plugins> </plugins>
</reporting> </build>
</project> </project>

View File

@ -9,7 +9,7 @@ public class Interval implements Intervalable {
* Constructs an interval with a start and end position. * Constructs an interval with a start and end position.
* *
* @param start The interval's starting text position. * @param start The interval's starting text position.
* @param end The interval's ending text position. * @param end The interval's ending text position.
*/ */
public Interval(final int start, final int end) { public Interval(final int start, final int end) {
this.start = start; this.start = start;
@ -51,7 +51,7 @@ public class Interval implements Intervalable {
*/ */
public boolean overlapsWith(final Interval other) { public boolean overlapsWith(final Interval other) {
return this.start <= other.getEnd() && return this.start <= other.getEnd() &&
this.end >= other.getStart(); this.end >= other.getStart();
} }
public boolean overlapsWith(int point) { public boolean overlapsWith(int point) {
@ -63,9 +63,9 @@ public class Interval implements Intervalable {
if (!(o instanceof Intervalable)) { if (!(o instanceof Intervalable)) {
return false; return false;
} }
Intervalable other = (Intervalable)o; Intervalable other = (Intervalable) o;
return this.start == other.getStart() && return this.start == other.getStart() &&
this.end == other.getEnd(); this.end == other.getEnd();
} }
@Override @Override
@ -78,7 +78,7 @@ public class Interval implements Intervalable {
if (!(o instanceof Intervalable)) { if (!(o instanceof Intervalable)) {
return -1; return -1;
} }
Intervalable other = (Intervalable)o; Intervalable other = (Intervalable) o;
int comparison = this.start - other.getStart(); int comparison = this.start - other.getStart();
return comparison != 0 ? comparison : this.end - other.getEnd(); return comparison != 0 ? comparison : this.end - other.getEnd();
} }

View File

@ -6,7 +6,7 @@ import java.util.List;
public class IntervalNode { public class IntervalNode {
private enum Direction { LEFT, RIGHT } private enum Direction {LEFT, RIGHT}
private IntervalNode left = null; private IntervalNode left = null;
private IntervalNode right = null; private IntervalNode right = null;
@ -93,12 +93,12 @@ public class IntervalNode {
List<Intervalable> overlaps = new ArrayList<Intervalable>(); List<Intervalable> overlaps = new ArrayList<Intervalable>();
for (Intervalable currentInterval : this.intervals) { for (Intervalable currentInterval : this.intervals) {
switch (direction) { switch (direction) {
case LEFT : case LEFT:
if (currentInterval.getStart() <= interval.getEnd()) { if (currentInterval.getStart() <= interval.getEnd()) {
overlaps.add(currentInterval); overlaps.add(currentInterval);
} }
break; break;
case RIGHT : case RIGHT:
if (currentInterval.getEnd() >= interval.getStart()) { if (currentInterval.getEnd() >= interval.getStart()) {
overlaps.add(currentInterval); overlaps.add(currentInterval);
} }

View File

@ -3,7 +3,9 @@ package org.ahocorasick.interval;
public interface Intervalable extends Comparable { public interface Intervalable extends Comparable {
public int getStart(); public int getStart();
public int getEnd(); public int getEnd();
public int size(); public int size();
} }

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() {
@ -70,20 +78,20 @@ public class State {
return nextState(character, true); return nextState(character, true);
} }
public State addState( String keyword ) { public State addState(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(Character character) { public State addState(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,11 +1,13 @@
package org.ahocorasick.trie; package org.ahocorasick.trie;
import static java.lang.Character.isWhitespace; import static java.lang.Character.isWhitespace;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.LinkedBlockingDeque; 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;
@ -32,16 +34,15 @@ public class Trie {
* 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.isEmpty() ) { if (keyword.isEmpty()) {
return; return;
} }
if( isCaseInsensitive() ) { if (isCaseInsensitive()) {
keyword = keyword.toLowerCase(); keyword = keyword.toLowerCase();
} }
addState(keyword).addEmit(keyword); addState(keyword).addEmit(keyword);
@ -52,10 +53,10 @@ public class Trie {
* *
* @param keywords List of search term to add to the list of search terms. * @param keywords List of search term to add to the list of search terms.
*/ */
private void addKeywords( final String[] keywords ) { private void addKeywords(final String[] keywords) {
for( final String keyword : keywords ) { for (final String keyword : keywords) {
addKeyword( keyword ); addKeyword(keyword);
} }
} }
/** /**
@ -63,10 +64,10 @@ public class Trie {
* *
* @param keywords List of search term to add to the list of search terms. * @param keywords List of search term to add to the list of search terms.
*/ */
private void addKeywords( final Collection<String> keywords ) { private void addKeywords(final Collection<String> keywords) {
for( final String keyword : keywords ) { for (final String keyword : keywords) {
addKeyword( keyword ); addKeyword(keyword);
} }
} }
private State addState(final String keyword) { private State addState(final String keyword) {
@ -95,11 +96,11 @@ public class Trie {
} }
private Token createFragment(final Emit emit, final String text, final int lastCollectedPosition) { private Token createFragment(final Emit emit, final String text, 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(Emit emit, String text) { private Token createMatch(Emit emit, 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")
@ -118,7 +119,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);
} }
@ -189,9 +190,9 @@ public class Trie {
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 &&
Character.isAlphabetic(searchText.charAt(emit.getStart() - 1))) || Character.isAlphabetic(searchText.charAt(emit.getStart() - 1))) ||
(emit.getEnd() + 1 != searchText.length() && (emit.getEnd() + 1 != searchText.length() &&
Character.isAlphabetic(searchText.charAt(emit.getEnd() + 1))); Character.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) {
@ -214,7 +215,7 @@ public class Trie {
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);
@ -282,11 +283,11 @@ public class Trie {
} }
private boolean isCaseInsensitive() { private boolean isCaseInsensitive() {
return trieConfig.isCaseInsensitive(); return trieConfig.isCaseInsensitive();
} }
private State getRootState() { private State getRootState() {
return this.rootState; return this.rootState;
} }
/** /**
@ -307,13 +308,13 @@ 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.
*/ */
@ -326,24 +327,22 @@ 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 String... keywords) { public TrieBuilder addKeywords(final String... keywords) {
this.trie.addKeywords(keywords); this.trie.addKeywords(keywords);
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 Collection<String> keywords) { public TrieBuilder addKeywords(final Collection<String> keywords) {
this.trie.addKeywords(keywords); this.trie.addKeywords(keywords);
return this; return this;
} }
/** /**
@ -411,18 +410,16 @@ public class Trie {
} }
/** /**
* @deprecated Use ignoreCase()
*
* @return This builder. * @return This builder.
* @deprecated Use ignoreCase()
*/ */
public TrieBuilder caseInsensitive() { public TrieBuilder caseInsensitive() {
return ignoreCase(); return ignoreCase();
} }
/** /**
* @deprecated Use ignoreOverlaps()
*
* @return This builder. * @return This builder.
* @deprecated Use ignoreOverlaps()
*/ */
public TrieBuilder removeOverlaps() { public TrieBuilder removeOverlaps() {
return ignoreOverlaps(); return ignoreOverlaps();

View File

@ -12,9 +12,13 @@ public class TrieConfig {
private boolean stopOnHit = false; private boolean stopOnHit = false;
public boolean isStopOnHit() { return stopOnHit; } public boolean isStopOnHit() {
return stopOnHit;
}
public void setStopOnHit(boolean stopOnHit) { this.stopOnHit = stopOnHit; } public void setStopOnHit(boolean stopOnHit) {
this.stopOnHit = stopOnHit;
}
public boolean isAllowOverlaps() { public boolean isAllowOverlaps() {
return allowOverlaps; return allowOverlaps;
@ -32,7 +36,9 @@ public class TrieConfig {
this.onlyWholeWords = onlyWholeWords; this.onlyWholeWords = onlyWholeWords;
} }
public boolean isOnlyWholeWordsWhiteSpaceSeparated() { return onlyWholeWordsWhiteSpaceSeparated; } public boolean isOnlyWholeWordsWhiteSpaceSeparated() {
return onlyWholeWordsWhiteSpaceSeparated;
}
public void setOnlyWholeWordsWhiteSpaceSeparated(boolean onlyWholeWordsWhiteSpaceSeparated) { public void setOnlyWholeWordsWhiteSpaceSeparated(boolean onlyWholeWordsWhiteSpaceSeparated) {
this.onlyWholeWordsWhiteSpaceSeparated = onlyWholeWordsWhiteSpaceSeparated; this.onlyWholeWordsWhiteSpaceSeparated = onlyWholeWordsWhiteSpaceSeparated;

View File

@ -12,19 +12,19 @@ public class IntervalTest {
@Test @Test
public void construct() { public void construct() {
Interval i = new Interval(1,3); Interval i = new Interval(1, 3);
assertEquals(1, i.getStart()); assertEquals(1, i.getStart());
assertEquals(3, i.getEnd()); assertEquals(3, i.getEnd());
} }
@Test @Test
public void size() { public void size() {
assertEquals(3, new Interval(0,2).size()); assertEquals(3, new Interval(0, 2).size());
} }
@Test @Test
public void intervaloverlaps() { public void intervaloverlaps() {
assertTrue(new Interval(1,3).overlapsWith(new Interval(2,4))); assertTrue(new Interval(1, 3).overlapsWith(new Interval(2, 4)));
} }
@Test @Test
@ -34,7 +34,7 @@ public class IntervalTest {
@Test @Test
public void pointOverlaps() { public void pointOverlaps() {
assertTrue(new Interval(1,3).overlapsWith(2)); assertTrue(new Interval(1, 3).overlapsWith(2));
} }
@Test @Test

View File

@ -20,7 +20,7 @@ public class IntervalTreeTest {
intervals.add(new Interval(4, 6)); intervals.add(new Interval(4, 6));
intervals.add(new Interval(5, 7)); intervals.add(new Interval(5, 7));
IntervalTree intervalTree = new IntervalTree(intervals); IntervalTree intervalTree = new IntervalTree(intervals);
List<Intervalable> overlaps = intervalTree.findOverlaps(new Interval(1,3)); List<Intervalable> overlaps = intervalTree.findOverlaps(new Interval(1, 3));
assertEquals(3, overlaps.size()); assertEquals(3, overlaps.size());
Iterator<Intervalable> overlapsIt = overlaps.iterator(); Iterator<Intervalable> overlapsIt = overlaps.iterator();
assertOverlap(overlapsIt.next(), 2, 4); assertOverlap(overlapsIt.next(), 2, 4);

View File

@ -13,9 +13,9 @@ public class IntervalableComparatorByPositionTest {
@Test @Test
public void sortOnPosition() { public void sortOnPosition() {
List<Intervalable> intervals = new ArrayList<Intervalable>(); List<Intervalable> intervals = new ArrayList<Intervalable>();
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));
Collections.sort(intervals, new IntervalableComparatorByPosition()); Collections.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

@ -13,9 +13,9 @@ public class IntervalableComparatorBySizeTest {
@Test @Test
public void sortOnSize() { public void sortOnSize() {
List<Intervalable> intervals = new ArrayList<Intervalable>(); List<Intervalable> intervals = new ArrayList<Intervalable>();
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));
Collections.sort(intervals, new IntervalableComparatorBySize()); Collections.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());
@ -25,8 +25,8 @@ public class IntervalableComparatorBySizeTest {
@Test @Test
public void sortOnSizeThenPosition() { public void sortOnSizeThenPosition() {
List<Intervalable> intervals = new ArrayList<Intervalable>(); List<Intervalable> intervals = new ArrayList<Intervalable>();
intervals.add(new Interval(4,7)); intervals.add(new Interval(4, 7));
intervals.add(new Interval(2,5)); intervals.add(new Interval(2, 5));
Collections.sort(intervals, new IntervalableComparatorBySize()); Collections.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

@ -11,9 +11,9 @@ public class StateTest {
public void constructSequenceOfCharacters() { public void constructSequenceOfCharacters() {
State rootState = new State(); State rootState = new State();
rootState rootState
.addState('a') .addState('a')
.addState('b') .addState('b')
.addState('c'); .addState('c');
State currentState = rootState.nextState('a'); State currentState = rootState.nextState('a');
assertEquals(1, currentState.getDepth()); assertEquals(1, currentState.getDepth());
currentState = currentState.nextState('b'); currentState = currentState.nextState('b');

View File

@ -5,30 +5,34 @@ 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 java.util.concurrent.ThreadLocalRandom;
import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertEquals;
import org.ahocorasick.trie.handler.EmitHandler; import org.ahocorasick.trie.handler.EmitHandler;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import org.junit.Test; 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
@ -406,7 +410,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");
} }
@ -415,19 +419,19 @@ 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 = Trie.builder() Trie 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());
} }
/** /**
@ -436,11 +440,11 @@ public class TrieTest {
* @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( int count ) { private StringBuilder randomNumbers(int count) {
final StringBuilder sb = new StringBuilder( count ); final StringBuilder sb = new StringBuilder(count);
while( --count > 0 ) { while (--count > 0) {
sb.append( randomInt( 0, 10 ) ); sb.append(randomInt(0, 10));
} }
return sb; return sb;
@ -449,23 +453,23 @@ public class TrieTest {
/** /**
* 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 ThreadLocalRandom.current().nextInt( min, max ); return ThreadLocalRandom.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) {