blob: 3c519698c90d7f6cee4b41043ad37f5bc6dfe9a7 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.jackrabbit.vault.util;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* <code>Tree</code>...
*/
public class Tree<E> {
private final char separator;
private Node<E> root = new Node<E>(null, "");
public Tree() {
this('/');
}
public Tree(char separator) {
this.separator = separator;
}
public void clear() {
root.elem = null;
root.children.clear();
}
public E put(String path, E elem) {
E previous;
Node<E> n = get(path, true);
previous = n.elem;
n.elem = elem;
return previous;
}
public E get(String path) {
Node<E> n = get(path, false);
return n == null ? null : n.elem;
}
public Node<E> getNode(String path) {
return get(path, false);
}
public E remove(String path) {
Node<E> n = get(path, false);
if (n == null) {
return null;
}
E previous = n.elem;
n.elem = null;
n.prune();
return previous;
}
private Node<E> get(String path, boolean create) {
String[] segs = Text.explode(path, separator);
Node<E> n = root;
for (String name: segs) {
Node<E> c = n.get(name, create);
if (c == null) {
return null;
}
n = c;
}
return n;
}
public void removeChildren(String path) {
Node<E> n = get(path, false);
if (n != null) {
n.removeChildren();
}
}
public Map<String, E> map() {
Map<String, E> map = new LinkedHashMap<String, E>();
fill(map, root, "");
return map;
}
public String getRootPath() {
Node<E> n = root;
StringBuffer path = new StringBuffer();
while (n.elem == null && n.children.size() == 1) {
n = n.children.values().iterator().next();
path.append(separator).append(n.name);
}
if (path.length() == 0) {
path.append(separator);
}
return path.toString();
}
public Node<E> getRootNode() {
Node<E> n = root;
while (n.elem == null && n.children.size() == 1) {
n = n.children.values().iterator().next();
}
return n;
}
private void fill(Map<String, E> map, Node<E> node, String parentPath) {
String path;
if (parentPath.length() != 1) {
// stupid check for root path
path = parentPath + separator + node.name;
} else {
path = parentPath + node.name;
}
if (node.elem != null) {
map.put(path, node.elem);
}
for (Node<E> child: node.children.values()) {
fill(map, child, path);
}
}
public static class Node<E> {
private String name;
private E elem;
private final Node parent;
private final Map<String, Node<E>> children = new LinkedHashMap<String, Node<E>>();
private Node(Node parent, String name) {
this.parent = parent;
this.name = name;
}
private Node<E> get(String name, boolean create) {
Node<E> child = children.get(name);
if (child == null && create) {
child = new Node<E>(this, name);
children.put(name, child);
}
return child;
}
private Node<E> remove(String name) {
return children.remove(name);
}
private void prune() {
if (children.isEmpty() && elem == null && parent != null) {
parent.remove(this.name);
parent.prune();
}
}
private void removeChildren() {
children.clear();
prune();
}
public String getName() {
return name;
}
public E getElem() {
return elem;
}
public Node getParent() {
return parent;
}
public Map<String, Node<E>> getChildren() {
return children;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("Node");
sb.append("{name='").append(name).append('\'');
sb.append(", elem=").append(elem);
sb.append(", children=").append(children.keySet());
sb.append('}');
return sb.toString();
}
}
}