/* * Copyright 2010 NCHOVY * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.krakenapps.ahocorasick; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; public class TrieNode { private final int id; private Byte body; private TrieNode previous; private TrieNode[] next; private TrieNode failure; private Set<Pattern> patterns; public TrieNode(int id, Byte body, TrieNode previous) { this.id = id; this.body = body; this.previous = previous; this.next = new TrieNode[256]; this.patterns = new HashSet<Pattern>(); } public int getId() { return id; } public Byte getBody() { return body; } public TrieNode getPrevious() { return previous; } public Collection<TrieNode> getAllNext() { List<TrieNode> list = new ArrayList<TrieNode>(); for (int i = 0; i < 256; i++) if (next[i] != null) list.add(next[i]); return list; } public boolean hasNext(byte nextBody) { TrieNode n = next[(int) nextBody + 128]; return (n != null); } public TrieNode getNext(byte nextBody) { TrieNode node = this; while (node.next[(int) nextBody + 128] == null) { node = node.failure; if (node.id == 0) // root break; } return node.next[(int) nextBody + 128]; } public TrieNode addNext(int id, byte nextBody) throws IOException { if (hasNext(nextBody)) throw new IOException("already added"); TrieNode node = new TrieNode(id, nextBody, this); next[(int) nextBody + 128] = node; return node; } public TrieNode getFailure() { return failure; } public void setFailure(TrieNode failure) { this.failure = failure; } public Set<Pattern> getPatterns() { return getPatterns(false); } public Set<Pattern> getPatterns(boolean includeFailureSet) { Set<Pattern> p = null; if (includeFailureSet) { p = new HashSet<Pattern>(); if (id != 0) { p.addAll(patterns); p.addAll(failure.getPatterns(true)); } } else p = patterns; return p; } public void addPattern(Pattern pattern) { this.patterns.add(pattern); } public byte[] getKeyword() { return getKeywordInternal(0); } private byte[] getKeywordInternal(int depth) { if (id == 0) return new byte[depth]; byte[] b = failure.getKeywordInternal(depth + 1); b[depth] = body; return b; } }