package de.marhali.easyi18n.model;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
/**
* Translation tree node. Manages child nodes which can be translations or also
* nodes which can lead to another translation or node.
* Navigation inside a node can be upward and downward. To construct the full
* translation key (full-key) every parent needs to be resolved recursively.
*
* Whether the children nodes should be sorted is determined by the parent node.
* For root nodes (empty parent) the {@link java.util.Map}-Type must be specified
* to determine which sorting should be applied.
* @author marhali
*/
public class TranslationNode {
@Nullable
private TranslationNode parent;
@NotNull
private Map children;
@NotNull
private TranslationValue value;
public TranslationNode(boolean sort) {
this(sort ? new TreeMap<>() : new LinkedHashMap<>());
}
/**
* Root node initializer. E.g. see {@link java.util.TreeMap} or {@link java.util.HashMap}
* @param children Decide which implementation should be used (sorted, non-sorted)
*/
public TranslationNode(@NotNull Map children) {
this.parent = null;
this.children = children;
this.value = new TranslationValue();
}
/**
* @return true if this node is considered as root node
*/
public boolean isRoot() {
return this.parent == null;
}
/**
* @return true if this node does not lead to other children nodes (just contains {@link Translation} itself).
* The root node is never treated as a leaf node.
*/
public boolean isLeaf() {
return this.children.isEmpty() && !this.isRoot();
}
public void setParent(@Nullable TranslationNode parent) {
this.parent = parent;
}
public @NotNull TranslationValue getValue() {
return value;
}
public void setValue(@NotNull TranslationValue value) {
this.children.clear();
this.value = value;
}
public @NotNull Map getChildren() {
return this.children;
}
public void setChildren(@NotNull String key, @NotNull TranslationNode node) {
node.setParent(this); // Track parent if adding children's
this.value.clear();
this.children.put(key, node);
}
@SuppressWarnings("unchecked")
public @NotNull TranslationNode setChildren(@NotNull String key) {
try {
TranslationNode node = new TranslationNode(this.children.getClass().getDeclaredConstructor().newInstance());
this.setChildren(key, node);
return node;
} catch(Exception e) {
e.printStackTrace();
throw new RuntimeException("Cannot create children of map type " + this.children.getClass().getSimpleName());
}
}
public void setChildren(@NotNull String key, @NotNull TranslationValue translation) {
this.setChildren(key).setValue(translation);
}
public @NotNull TranslationNode getOrCreateChildren(@NotNull String key) {
TranslationNode node = this.children.get(key);
if(node == null) {
node = this.setChildren(key);
}
return node;
}
public void removeChildren(@NotNull String key) {
this.children.remove(key);
}
@Override
public String toString() {
return "TranslationNode{" +
"parent=" + parent +
", children=" + children.keySet() +
", value=" + value +
'}';
}
}