com.google.security.fences.namespace.NamespaceTrie Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fences-maven-enforcer-rule Show documentation
Show all versions of fences-maven-enforcer-rule Show documentation
Augments Java's access control by checking that a Maven Project and all its
dependencies conform to a policy that specifies which classes/packages can
link to which others.
package com.google.security.fences.namespace;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
/**
* Maps package and class names to values.
*
* @param The value type stored at a Trie node.
* @param The type that can be added to a Trie node.
* This can be a part of the COMPLEX_VALUE allowing the trie to easily
* function as a MultiTrie.
*/
public final class NamespaceTrie {
final Entry root = new Entry(null);
final Supplier makeEmpty;
final Function> folder;
/**
* @param makeEmpty a supplier for empty complex values.
* @param folder combines a previous complex value and a simple value being
* added to a node together to produce the new complex value.
*/
public NamespaceTrie(
Supplier makeEmpty,
Function> folder) {
this.makeEmpty = makeEmpty;
this.folder = folder;
}
/** The minimal collection of entries that includes all overlapping ns. */
public Map overlapping(Namespace ns) {
Entry e = getEntry(ns, false, false);
ImmutableMap.Builder b =
ImmutableMap.builder();
if (e != null) {
e.addTransitively(ns, b);
}
return b.build();
}
/**
* The node specified by the given namespace if any.
*/
public Entry get(Namespace ns) {
return getEntry(ns, false, false);
}
/**
* Folds a simple value into the node specified by ns,
* creating a new node if necessary.
*/
public Entry put(Namespace ns, SIMPLE_VALUE simpleValue) {
Entry e = Preconditions.checkNotNull(
getEntry(ns, true, false));
e.putValue(this.makeEmpty, this.folder, simpleValue);
return e;
}
/**
* The value at namespace or one of its ancestors giving preferences to
* deeper nodes.
*/
public Entry getDeepest(Namespace ns) {
return getEntry(ns, false, true);
}
private Entry getEntry(
Namespace ns, boolean manufacture, boolean bestEffort) {
Entry parentEntry;
Optional parent = ns.getParent();
if (parent.isPresent()) {
parentEntry = getEntry(parent.get(), manufacture, bestEffort);
if (parentEntry == null) { return null; }
} else {
parentEntry = root;
}
Optional nameOpt = ns.getName();
if (nameOpt.isPresent()) {
String name = nameOpt.get();
@SuppressWarnings("synthetic-access")
SortedMap> children = parentEntry.children;
Entry child = children.get(name);
if (child == null) {
if (manufacture) {
child = new Entry(parentEntry);
children.put(name, child);
} else if (bestEffort) {
return parentEntry;
}
}
return child;
} else {
return parentEntry;
}
}
/**
* A diagnostic text representation of the trie with one line per entry.
*/
public String toTree() {
return root.toTree();
}
/** A trie entry. */
public static final class Entry {
private Optional value = Optional.absent();
private final Entry parent;
private final SortedMap> children =
new TreeMap>();
Entry(Entry parent) {
this.parent = parent;
}
void putValue(
Supplier emptyValue, Function> fold,
X newValuePart) {
T newValue = fold.apply(value.or(emptyValue)).apply(newValuePart);
value = Optional.of(newValue);
}
/** The value if any is specified. */
public Optional getValue() {
return value;
}
/** The parent entry or absent if this entry is the root of the trie. */
public Optional> getParent() {
return Optional.fromNullable(parent);
}
void addTransitively(Namespace ns, ImmutableMap.Builder out) {
if (value.isPresent()) {
out.put(ns, value.get());
}
for (Map.Entry> e : children.entrySet()) {
e.getValue().addTransitively(ns.child(e.getKey()), out);
}
}
@Override
public String toString() {
return toShallowString();
}
String toShallowString() {
return "Entry " + value;
}
/** A diagnostic string containing the entry in indented tree form. */
public String toTree() {
StringBuilder sb = new StringBuilder();
toTree(sb, 0);
return sb.toString();
}
/**
* Appends a diagnostic string containing the entry in indented tree form.
*
* @param sb receives the text of the tree
* @param n the indentation level.
*/
public void toTree(StringBuilder sb, int n) {
sb.append(toShallowString());
int childDepth = n + 1;
for (Map.Entry> e : children.entrySet()) {
sb.append('\n');
for (int i = childDepth; --i >= 0;) { sb.append(". "); }
sb.append(e.getKey()).append(" => ");
e.getValue().toTree(sb, childDepth);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy