cdc.applic.dictionaries.impl.SectionStructureImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cdc-applic-dictionaries-impl Show documentation
Show all versions of cdc-applic-dictionaries-impl Show documentation
Applicabilities Dictionaries Implementation.
The newest version!
package cdc.applic.dictionaries.impl;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import cdc.applic.dictionaries.Dictionary;
import cdc.applic.dictionaries.Registry;
import cdc.applic.expressions.literals.SName;
import cdc.graphs.core.GraphPath;
import cdc.graphs.core.SlimGraph;
import cdc.util.debug.Printables;
import cdc.util.debug.Verbosity;
import cdc.util.lang.Checks;
import cdc.util.paths.Path;
public class SectionStructureImpl implements SectionStructure {
private static final String PATH = "path";
private final RepositoryImpl repository;
/** The associated dictionary. */
private final AbstractDictionaryImpl dictionary;
/** The parent when it is unique (policy). */
private final AbstractDictionaryImpl parent;
/** All parents, even when it is unique */
private final List parents = new ArrayList<>();
/** Sorted ancestors, from itself to farthest ancestors. */
private final List ancestors = new ArrayList<>();
/** Sorted descendants, from itself to farthest descendants. */
private final List descendants = new ArrayList<>();
/** Paths from all ancestors to this dictionary. */
private final List> pathsFromAncestors = new ArrayList<>();
/** Name of the dictionary. */
private final String name;
private final SName prefix;
/** Path of the dictionary. */
private final Path path;
/** Description of the dictionary. */
private final DescriptionImpl description = new DescriptionImpl();
/** List of children dictionaries. */
protected final List children = new ArrayList<>();
SectionStructureImpl(RepositoryImpl repository,
AbstractDictionaryImpl dictionary,
String name,
SName prefix,
AbstractDictionaryImpl parent,
List parents) {
Checks.isTrue(Path.isValidName(name), "Invalid dictionary name " + name);
Checks.isNotNull(parents, "parents");
this.repository = Checks.isNotNull(repository, "repository");
this.dictionary = Checks.isNotNull(dictionary, "dictionary");
this.parent = parent;
this.name = name;
this.prefix = prefix;
if (parent == null) {
this.path = new Path(Path.SLASH + name);
} else {
this.path = new Path(parent.structure.path.toString() + Path.SLASH + name);
}
this.parents.addAll(parents);
for (final AbstractDictionaryImpl p : parents) {
p.structure.children.add(dictionary);
}
}
void build() {
// First compute ancestors
ancestors.addAll(SlimGraph.topologicalSort(dictionary,
x -> x.structure.parents));
Checks.assertTrue(!ancestors.isEmpty() && ancestors.get(0) == dictionary, "Implementation error");
// Then update descendants of all ancestors
// Note: is this useful? At the time of creation of a dictionary, it does not have any descendants.
for (final AbstractDictionaryImpl ancestor : ancestors) {
ancestor.structure.updateDescendants();
}
// Compute paths from ancestors.
for (final AbstractDictionaryImpl p : parents) {
// 1) Take paths of parents and add this dictionary
for (final GraphPath parentPath : p.structure.pathsFromAncestors) {
final GraphPath newPath = GraphPath.builder(AbstractDictionaryImpl.class)
.push(parentPath)
.push(dictionary)
.build();
pathsFromAncestors.add(newPath);
}
// 2) take parents and add this dictionary.
final GraphPath newPath = GraphPath.builder(AbstractDictionaryImpl.class)
.push(p, dictionary)
.build();
pathsFromAncestors.add(newPath);
}
}
private final void updateDescendants() {
descendants.clear();
descendants.addAll(SlimGraph.topologicalSort(dictionary,
x -> x.structure.children));
Checks.assertTrue(!descendants.isEmpty() && descendants.get(0) == dictionary, "Implementation error");
}
void setParents(List parents) {
Checks.assertTrue(this.parent == null, "Setting parents of a policy.");
Checks.assertTrue(this.parents.isEmpty(), "Setting parents too late (already attached to parents).");
Checks.assertTrue(this.children.isEmpty(), "Setting parents too late (already has children).");
this.ancestors.clear();
this.pathsFromAncestors.clear();
this.parents.addAll(parents);
for (final AbstractDictionaryImpl p : parents) {
p.structure.children.add(dictionary);
}
build();
}
@Override
public RepositoryImpl getRepository() {
return repository;
}
public AbstractDictionaryImpl getParent() {
return parent;
}
@Override
public List getParents() {
return parents;
}
@Override
public List getParents(Class cls) {
return parents.stream()
.filter(cls::isInstance)
.map(cls::cast)
.toList();
}
@Override
public List getSortedAncestors(boolean self) {
if (self) {
return ancestors;
} else {
return ancestors.subList(1, ancestors.size());
}
}
/**
* Explores all paths that start on a specific ancestor and reach this dictionary.
*
* @param ancestor The ancestor.
* @param consumer The path consumer.
*/
void explorePathsFromAncestor(AbstractDictionaryImpl ancestor,
Consumer> consumer) {
for (final GraphPath p : pathsFromAncestors) {
if (p.getItems().get(0) == ancestor) {
consumer.accept(p);
}
}
}
/**
* Explores all paths that start on a root dictionary and reach this dictionary.
*
* @param consumer The path consumer.
*/
void explorePathsFromRoots(Consumer> consumer) {
for (final GraphPath p : pathsFromAncestors) {
if (!p.getItems().get(0).hasParents()) {
consumer.accept(p);
}
}
}
@Override
public List getSortedDescendants(boolean self) {
if (self) {
return descendants;
} else {
return descendants.subList(1, descendants.size());
}
}
@Override
public DescriptionImpl getDescription() {
return description;
}
@Override
public String getDesignation() {
return (dictionary instanceof Registry ? "Registry " : "Policy ") + getPath();
}
@Override
public String getName() {
return name;
}
@Override
public Optional getPrefix() {
return Optional.ofNullable(prefix);
}
@Override
public boolean isDeclaredPrefix(SName prefix) {
if (prefix == null) {
return false;
} else {
// WARNING: we do a linear search
// Would be faster with a set, but practically may be sufficient
for (final AbstractDictionaryImpl ancestor : getRegistry().getSortedAncestors(true)) {
if (prefix.equals(ancestor.getPrefix().orElse(null))) {
return true;
}
}
return false;
}
}
@Override
public Path getPath() {
return path;
}
@Override
public RegistryImpl getRegistry() {
return dictionary instanceof final RegistryImpl x
? x
: getParent().getRegistry();
}
@Override
public D getDictionary(Path path,
Class cls) {
Checks.isNotNull(path, PATH);
Checks.isNotNull(cls, "cls");
final Path p;
if (path.isAbsolute()) {
p = path;
} else {
p = new Path(getPath().toString() + Path.SLASH + path).normalize();
}
return getRepository().getDictionary(p, cls);
}
@Override
public D getDictionary(String path,
Class cls) {
return getDictionary(Path.of(path), cls);
}
@Override
public AbstractDictionaryImpl getDictionary(Path path) {
return getDictionary(path, AbstractDictionaryImpl.class);
}
@Override
public AbstractDictionaryImpl getDictionary(String path) {
Checks.isNotNull(path, PATH);
return getDictionary(Path.of(path));
}
@Override
public RegistryImpl getRegistry(Path path) {
return getDictionary(path, RegistryImpl.class);
}
@Override
public RegistryImpl getRegistry(String path) {
Checks.isNotNull(path, PATH);
return getRegistry(Path.of(path));
}
@Override
public PolicyImpl getPolicy(Path path) {
return getDictionary(path, PolicyImpl.class);
}
@Override
public PolicyImpl getPolicy(String path) {
Checks.isNotNull(path, PATH);
return getPolicy(new Path(path));
}
@Override
public List getChildren() {
return children;
}
@Override
public List getChildren(Class cls) {
return children.stream()
.filter(cls::isInstance)
.map(cls::cast)
.toList();
}
@Override
public PolicyImpl.Builder policy() {
return PolicyImpl.builder(dictionary);
}
@Override
public void printLocalStructure(PrintStream out,
int level,
Verbosity verbosity) {
final String k = dictionary instanceof RegistryImpl ? "Registry" : "Policy";
Printables.indent(out, level);
out.println(k + " '" + getName() + "'");
Printables.indent(out, level + 1);
out.println("Caches serial: " + dictionary.getCachesSerial());
Printables.indent(out, level + 1);
out.println("Prefix: " + getPrefix());
Printables.indent(out, level + 1);
out.println("Context: " + dictionary.getContextExpression());
Printables.indent(out, level + 1);
out.println("Parents (" + getParents().size() + ")");
for (final Dictionary p : getParents()) {
Printables.indent(out, level + 2);
out.println("'" + p.getName() + "'");
}
Printables.indent(out, level + 1);
out.println("Sorted Ancestors : "
+ getSortedAncestors(false).stream()
.map(x -> x.getPath().toString())
.collect(Collectors.joining(", ", "[", "]")));
Printables.indent(out, level + 1);
out.println("Sorted Descendants : "
+ getSortedDescendants(false).stream()
.map(x -> x.getPath().toString())
.collect(Collectors.joining(", ", "[", "]")));
Printables.indent(out, level + 1);
out.println("Paths from ancestors (" + pathsFromAncestors.size() + ")");
for (final GraphPath p : pathsFromAncestors) {
Printables.indent(out, level + 2);
out.println(p);
}
}
@Override
public void printChildrenPolicies(PrintStream out,
int level,
Verbosity verbosity) {
Printables.indent(out, level);
out.println("Policies (" + getChildren(PolicyImpl.class).size() + ")");
for (final PolicyImpl policy : getChildren(PolicyImpl.class)) {
policy.print(out, level + 1, verbosity);
}
}
}