-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
new container trees and named container trees
- Loading branch information
Showing
6 changed files
with
332 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
198 changes: 198 additions & 0 deletions
198
src/main/java/pro/komaru/tridot/core/struct/data/tree/ContainerTree.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
package pro.komaru.tridot.core.struct.data.tree; | ||
|
||
import pro.komaru.tridot.core.struct.data.Seq; | ||
import pro.komaru.tridot.core.struct.func.Boolf; | ||
|
||
import java.util.LinkedList; | ||
import java.util.Queue; | ||
|
||
@SuppressWarnings("rawtypes,unchecked") | ||
public class ContainerTree<A> implements ITree<A> { | ||
private final Seq<A> children; | ||
private final Seq<ContainerTree<A>> containers; | ||
|
||
public ContainerTree<A> parent = null; | ||
|
||
public ContainerTree() { | ||
children = Seq.with(); | ||
containers = Seq.with(); | ||
} | ||
|
||
|
||
/** | ||
* Adds all elements as children of this container tree | ||
* @param all elements to add | ||
*/ | ||
@SafeVarargs | ||
public final ContainerTree<A> add(A... all) { | ||
children.add(all); | ||
|
||
return this; | ||
} | ||
/** | ||
* Adds element as a child of this container tree | ||
* @param child element to add | ||
*/ | ||
public ContainerTree<A> add(A child) { | ||
children.add(child); | ||
return this; | ||
} | ||
|
||
/** | ||
* Adds element as a subcontainer of this container tree | ||
* @param child element to add | ||
*/ | ||
public ContainerTree<A> add(ContainerTree<A> child) { | ||
containers.add(child); | ||
child.parent = this; | ||
return this; | ||
} | ||
|
||
/** | ||
* Adds all elements as children of this container tree if they don't exist yet | ||
* @param all elements to add | ||
*/ | ||
@SafeVarargs | ||
public final ContainerTree<A> addUnique(A... all) { | ||
for (A a : all) { | ||
addUnique(a); | ||
} | ||
return this; | ||
} | ||
/** | ||
* Adds element as a child of this container tree if it doesn't exist yet | ||
* @param child element to add | ||
*/ | ||
public ContainerTree<A> addUnique(A child) { | ||
children.addUnique(child); | ||
return this; | ||
} | ||
|
||
/** | ||
* Finds a child of this container using a filter function | ||
* @param filter filter function | ||
* @return child object | ||
*/ | ||
@Override | ||
public A child(Boolf<A> filter) { | ||
return children().find(filter); | ||
} | ||
/** | ||
* Finds a child in all containers of this tree using a filter function | ||
* @param filter filter function | ||
* @return child object | ||
*/ | ||
@Override | ||
public A childDeep(Boolf<A> filter,boolean depthSearch) { | ||
A child = children().find(filter); | ||
if(depthSearch) { | ||
if (child == null) { | ||
for (ITree<A> container : containers) { | ||
A other = container.childDeep(filter); | ||
if (other != null) { | ||
return other; | ||
} | ||
} | ||
} | ||
} else { | ||
Queue<ContainerTree<A>> queue = new LinkedList<>(); | ||
queue.add(this); | ||
|
||
while (!queue.isEmpty()) { | ||
ContainerTree<A> current = queue.poll(); | ||
A other = current.children().find(filter); | ||
if (other != null) { | ||
return other; | ||
} | ||
queue.addAll(current.containers.list()); | ||
} | ||
} | ||
return child; | ||
} | ||
|
||
/** | ||
* Finds a child in all containers of this tree using a filter function, in a BFS method | ||
* @param filter filter function | ||
* @return child object | ||
*/ | ||
@Override | ||
public A childDeep(Boolf<A> filter) { | ||
return childDeep(filter,false); | ||
} | ||
|
||
/** | ||
* Clears all tree | ||
*/ | ||
@Override | ||
public void clean() { | ||
children().clear(); | ||
containers.each(e -> e.parent = null); //bye-bye! | ||
containers().clear(); | ||
} | ||
|
||
|
||
/** | ||
* @return Children Seq | ||
*/ | ||
@Override | ||
public Seq<A> children() { | ||
return children; | ||
} | ||
|
||
/** | ||
* @return Children of this tree and subcontainers' children | ||
*/ | ||
@Override | ||
public Seq<A> childrenDeep() { | ||
Seq<A> all = Seq.with(); | ||
all.addAll(children()); | ||
for (ITree<A> container : containers()) | ||
all.addAll(container.childrenDeep()); | ||
return all; | ||
} | ||
|
||
/** | ||
* @return Subcontainer Seq | ||
*/ | ||
public Seq<ContainerTree<A>> containers() { | ||
return containers; | ||
} | ||
|
||
/** | ||
* @return All containers of this tree | ||
*/ | ||
public Seq<ContainerTree<A>> containersDeep() { | ||
Seq<ContainerTree<A>> all = Seq.with(); | ||
all.addAll(containers()); | ||
for (ContainerTree<A> other : containers()) | ||
all.addAll(other.containers); | ||
return all; | ||
} | ||
|
||
|
||
@Override | ||
public String toString() { | ||
String name = this instanceof NamedContTree<?> a ? a.name : "***"; | ||
StringBuilder sb = new StringBuilder("\u001B[33m[" + name + "]\u001B[0m"); | ||
sb.append("\n"); | ||
for (ContainerTree<A> cont : containers) { | ||
Seq<String> lines = Seq.with(cont.toString().lines().map(e -> " " + e).toList()); | ||
if(!lines.isEmpty()) { | ||
lines.set(0,lines.get(0).replaceFirst(" ","")); | ||
} | ||
sb.append("\u001B[33m-\u001B[0m"); | ||
sb.append(String.join("\n", lines)); | ||
sb.append("\n"); | ||
} | ||
for (A child : children) { | ||
Seq<String> lines = Seq.with(child.toString().lines().map(e -> " " + e).toList()); | ||
if(!lines.isEmpty()) { | ||
lines.set(0,lines.get(0).replaceFirst(" ","")); | ||
} | ||
sb.append("\u001B[37m*\u001B[0m"); | ||
sb.append(String.join("\n", lines)); | ||
sb.append("\n"); | ||
} | ||
return sb.toString(); | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
src/main/java/pro/komaru/tridot/core/struct/data/tree/INamedTree.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package pro.komaru.tridot.core.struct.data.tree; | ||
|
||
public interface INamedTree { | ||
String name(); | ||
} |
35 changes: 35 additions & 0 deletions
35
src/main/java/pro/komaru/tridot/core/struct/data/tree/ITree.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package pro.komaru.tridot.core.struct.data.tree; | ||
|
||
import pro.komaru.tridot.core.struct.data.Seq; | ||
import pro.komaru.tridot.core.struct.func.Boolf; | ||
|
||
public interface ITree<A> { | ||
Seq<A> children(); | ||
Seq<A> childrenDeep(); | ||
|
||
A child(Boolf<A> filter); | ||
|
||
|
||
/** | ||
* Deepfinding a child using a filter in either BFS or DFS | ||
* @param filter filter function | ||
* @param depthSearch if true, then it uses DFS instead of BFS | ||
* @return child object | ||
*/ | ||
A childDeep(Boolf<A> filter, boolean depthSearch); | ||
|
||
default A childDeep(Boolf<A> filter) { | ||
return childDeep(filter,false); | ||
}; | ||
default A child(Boolf<A> filter, boolean deep, boolean depthSearch) { | ||
return deep ? childDeep(filter,depthSearch) : child(filter); | ||
} | ||
default A child(Boolf<A> filter, boolean deep) { | ||
return child(filter,deep,false); | ||
} | ||
|
||
/** | ||
* Clears all tree | ||
*/ | ||
void clean(); | ||
} |
80 changes: 80 additions & 0 deletions
80
src/main/java/pro/komaru/tridot/core/struct/data/tree/NamedContTree.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package pro.komaru.tridot.core.struct.data.tree; | ||
|
||
import pro.komaru.tridot.core.struct.Structs; | ||
import pro.komaru.tridot.core.struct.data.Seq; | ||
|
||
import java.util.HashMap; | ||
|
||
public class NamedContTree<A> extends ContainerTree<A> implements INamedTree { | ||
public final String name; | ||
|
||
private final HashMap<String,Object> PATH_CACHE = | ||
new HashMap<>(); | ||
|
||
public NamedContTree(String name) { | ||
this.name = name; | ||
} | ||
|
||
@Override | ||
public NamedContTree<A> add(A child) { | ||
return (NamedContTree<A>) super.add(child); | ||
} | ||
|
||
@Override | ||
public NamedContTree<A> add(ContainerTree<A> child) { | ||
return (NamedContTree<A>) super.add(child); | ||
} | ||
|
||
@Override | ||
public NamedContTree<A> addUnique(A child) { | ||
return (NamedContTree<A>) super.addUnique(child); | ||
} | ||
|
||
public NamedContTree<A> cd(boolean autoCreate, String... path) { | ||
if(path == null || path.length == 0) return this; | ||
if(path[0].equals("..")) return ((NamedContTree<A>) parent).cd(autoCreate,Structs.pop(path)); | ||
for (NamedContTree<A> cont : namedContainers()) { | ||
if(cont.name.equals(path[0])) | ||
return cont.cd(autoCreate,Structs.pop(path)); | ||
} | ||
if(autoCreate) { | ||
NamedContTree<A> newTree = new NamedContTree<>(path[0]); | ||
containers().add(newTree); | ||
newTree.parent = this; | ||
return newTree.cd(true,Structs.pop(path)); | ||
} | ||
return null; | ||
} | ||
public NamedContTree<A> cd(boolean autoCreate,String path) { | ||
return cd(autoCreate,path.split("/")); | ||
} | ||
public NamedContTree<A> cd(String... path) { | ||
return cd(true,path); | ||
} | ||
public NamedContTree<A> cd(String path) { | ||
return cd(true,path); | ||
} | ||
|
||
public static void main(String[] args) { | ||
NamedContTree<String> main = new NamedContTree<>("main"); | ||
main | ||
.cd("a") | ||
.add("A section!") | ||
.cd("../b") | ||
.add("B section!") | ||
.cd("../a/c") | ||
.add("C section!") | ||
.cd("../..") | ||
.add("End section!"); | ||
System.out.println(main); | ||
} | ||
|
||
public Seq<NamedContTree<A>> namedContainers() { | ||
return Structs.cast(containers().select(e -> e instanceof NamedContTree)); | ||
} | ||
|
||
@Override | ||
public String name() { | ||
return name; | ||
} | ||
} |