/*
* Copyright 2013 eXo Platform SAS
*
* 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 juzu.impl.common;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */
public abstract class AbstractTrie<K, T extends AbstractTrie<K, T>> implements Iterable<K> {
/** . */
final T parent;
/** . */
final List<K> path;
/** . */
final K key;
/** The entries. */
private Map<K, T> entries;
protected AbstractTrie() {
this.parent = null;
this.path = Collections.emptyList();
this.key = null;
}
protected AbstractTrie(T parent, K key) {
ArrayList<K> path = new ArrayList<K>(parent.path.size() + 1);
path.addAll(parent.path);
path.add(key);
//
this.parent = parent;
this.path = Collections.unmodifiableList(path);
this.key = key;
}
protected abstract T create(T parent, K key);
public final T getParent() {
return parent;
}
public final K getKey() {
return key;
}
public final Iterator<K> iterator() {
return entries != null ? entries.keySet().iterator() : Tools.<K>emptyIterator();
}
public final Iterable<K> getPath() {
return path;
}
public final Iterator<T> getEntries() {
return entries != null ? entries.values().iterator() : Tools.<T>emptyIterator();
}
public final T get(K... keys) {
return get(keys, 0, keys.length);
}
public final T get(K key) {
if (entries != null) {
return entries.get(key);
}
return null;
}
public final T get(K[] keys, int from, int to) {
T ret;
if (from == to) {
ret = (T)this;
}
else {
K key = keys[from];
T entry = get(key);
ret = entry != null ? entry.get(keys, from + 1, to) : null;
}
return ret;
}
public final T get(Iterator<K> keys) {
T ret;
if (keys.hasNext()) {
K key = keys.next();
T entry = get(key);
ret = entry != null ? entry.get(keys) : null;
}
else {
ret = (T)this;
}
return ret;
}
public final T add(K key) {
T entry;
if (entries == null) {
entries = new HashMap<K, T>();
entry = null;
}
else {
entry = entries.get(key);
}
if (entry == null) {
entries.put(key, entry = create((T)this, key));
}
return entry;
}
public final T add(K... keys) {
return add(keys, 0, keys.length);
}
public final T add(K[] keys, int from, int to) {
if (from == to) {
return (T)this;
}
else {
K key = keys[from];
T entry = add(key);
return entry.add(keys, from + 1, to);
}
}
public final T add(Iterator<K> keys) {
if (keys.hasNext()) {
K key = keys.next();
T entry = add(key);
return entry.add(keys);
}
else {
return (T)this;
}
}
}