-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
867 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<groupId>net.iryndin</groupId> | ||
<artifactId>computetree</artifactId> | ||
<version>1.0</version> | ||
|
||
<properties> | ||
<project.build.source>UTF-8</project.build.source> | ||
|
||
<maven.compiler.source>1.8</maven.compiler.source> | ||
<maven.compiler.target>1.8</maven.compiler.target> | ||
<maven.compiler.fork>true</maven.compiler.fork> | ||
|
||
<guava.version>19.0</guava.version> | ||
<snakeyaml.version>1.17</snakeyaml.version> | ||
<commons.io.version>2.5</commons.io.version> | ||
<slf4j.version>1.7.22</slf4j.version> | ||
<logback.version>1.1.9</logback.version> | ||
<junit.version>4.11</junit.version> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>com.google.guava</groupId> | ||
<artifactId>guava</artifactId> | ||
<version>${guava.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.yaml</groupId> | ||
<artifactId>snakeyaml</artifactId> | ||
<version>${snakeyaml.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>commons-io</groupId> | ||
<artifactId>commons-io</artifactId> | ||
<version>${commons.io.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.slf4j</groupId> | ||
<artifactId>slf4j-api</artifactId> | ||
<version>${slf4j.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>ch.qos.logback</groupId> | ||
<artifactId>logback-classic</artifactId> | ||
<version>${logback.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>junit</groupId> | ||
<artifactId>junit</artifactId> | ||
<version>${junit.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
</project> |
80 changes: 80 additions & 0 deletions
80
computetree/src/main/java/net/iryndin/computetree/Main.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 net.iryndin.computetree; | ||
|
||
import com.google.common.base.Optional; | ||
import net.iryndin.computetree.api.INode; | ||
import net.iryndin.computetree.api.INodeRegistry; | ||
import net.iryndin.computetree.api.ITreeResult; | ||
import net.iryndin.computetree.core.TreeComputation; | ||
import net.iryndin.computetree.core.YamlTreeReader; | ||
import net.iryndin.computetree.node.DebugNode; | ||
import org.apache.commons.io.IOUtils; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.io.InputStream; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
/** | ||
* @author iryndin | ||
* @since 25/01/17 | ||
*/ | ||
public class Main { | ||
|
||
final static Logger log = LoggerFactory.getLogger(Main.class); | ||
|
||
public static void main(String[] args) throws Exception { | ||
String yaml; | ||
try (InputStream is = Main.class.getClassLoader().getResourceAsStream("tree.yaml")) { | ||
yaml = IOUtils.toString(is, StandardCharsets.UTF_8); | ||
} | ||
YamlTreeReader ytr = new YamlTreeReader(yaml); | ||
String start = ytr.getStartNodeId(); | ||
INodeRegistry registry = ytr.createNodeRegistry(); | ||
try (TreeComputation tc = new TreeComputation(registry)) { | ||
Optional<ITreeResult> tr = tc.compute(start); | ||
if (tr.isPresent()) { | ||
log.info("TreeResult: " + tr.get()); | ||
} else { | ||
log.info("TreeResult is absent!"); | ||
} | ||
} | ||
} | ||
|
||
/* | ||
static INodeRegistry createINodeRegistry() { | ||
return new INodeRegistry() { | ||
@Override | ||
public Optional<INode> getNode(String id) { | ||
log.debug("Try to get node by id: '{}'", id); | ||
switch (id) { | ||
case "valid": return Optional.of(new DebugNode("valid")); | ||
case "wanted": return Optional.of(new DebugNode("wanted")); | ||
} | ||
log.debug("No nodes by id: '{}'", id); | ||
return Optional.absent(); | ||
} | ||
@Override | ||
public Optional<List<String>> getNodeResults(String id, String result) { | ||
switch (id) { | ||
case "valid": | ||
switch (result) { | ||
case "success": return Optional.of(Arrays.asList("wanted", "terror")); | ||
case "notValid": return Optional.of(Arrays.asList("end")); | ||
default: return Optional.absent(); | ||
} | ||
case "wanted": | ||
switch (result) { | ||
case "success": return Optional.of(Arrays.asList("wantedLocal", "wantedIntl")); | ||
default: return Optional.absent(); | ||
} | ||
} | ||
return Optional.absent(); | ||
} | ||
}; | ||
} | ||
*/ | ||
} |
30 changes: 30 additions & 0 deletions
30
computetree/src/main/java/net/iryndin/computetree/api/INode.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,30 @@ | ||
package net.iryndin.computetree.api; | ||
|
||
|
||
import com.google.common.base.Optional; | ||
|
||
/** | ||
* @author iryndin | ||
* @since 20/01/17 | ||
*/ | ||
public interface INode { | ||
/** | ||
* Get node ID | ||
* @return node ID | ||
*/ | ||
String getId(); | ||
|
||
/** | ||
* Set node ID | ||
* @param nodeId node ID | ||
*/ | ||
void setId(String nodeId); | ||
|
||
/** | ||
* Node computation is made here. | ||
* @param treeResult reference to tree result object. This tree result object can be modified during | ||
* node computation. | ||
* @return result of node computation | ||
*/ | ||
INodeResult compute(ITreeResult treeResult); | ||
} |
14 changes: 14 additions & 0 deletions
14
computetree/src/main/java/net/iryndin/computetree/api/INodeRegistry.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,14 @@ | ||
package net.iryndin.computetree.api; | ||
|
||
import com.google.common.base.Optional; | ||
|
||
import java.util.List; | ||
|
||
/** | ||
* @author iryndin | ||
* @since 20/01/17 | ||
*/ | ||
public interface INodeRegistry { | ||
Optional<INode> getNode(String id); | ||
Optional<List<String>> getNodeResults(String id, String result); | ||
} |
35 changes: 35 additions & 0 deletions
35
computetree/src/main/java/net/iryndin/computetree/api/INodeResult.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 net.iryndin.computetree.api; | ||
|
||
import com.google.common.base.Optional; | ||
|
||
import java.util.Map; | ||
|
||
/** | ||
* @author iryndin | ||
* @since 20/01/17 | ||
*/ | ||
public interface INodeResult { | ||
String getNodeId(); | ||
String getValue(); | ||
Optional<Map<Object, Object>> getData(); | ||
|
||
static INodeResult createEmptyNodeResult(String nodeId, String result) { | ||
return new INodeResult() { | ||
|
||
@Override | ||
public String getNodeId() { | ||
return nodeId; | ||
} | ||
|
||
@Override | ||
public String getValue() { | ||
return result; | ||
} | ||
|
||
@Override | ||
public Optional<Map<Object, Object>> getData() { | ||
return Optional.absent(); | ||
} | ||
}; | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
computetree/src/main/java/net/iryndin/computetree/api/ITreeResult.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,13 @@ | ||
package net.iryndin.computetree.api; | ||
|
||
import java.util.Set; | ||
|
||
/** | ||
* @author iryndin | ||
* @since 20/01/17 | ||
*/ | ||
public interface ITreeResult { | ||
void put(String id, Object data); | ||
Object get(String id); | ||
Set<String> keys(); | ||
} |
129 changes: 129 additions & 0 deletions
129
computetree/src/main/java/net/iryndin/computetree/core/TreeComputation.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,129 @@ | ||
package net.iryndin.computetree.core; | ||
|
||
import com.google.common.base.Joiner; | ||
import com.google.common.base.Optional; | ||
import com.google.common.collect.Lists; | ||
import net.iryndin.computetree.api.INode; | ||
import net.iryndin.computetree.api.INodeRegistry; | ||
import net.iryndin.computetree.api.INodeResult; | ||
import net.iryndin.computetree.api.ITreeResult; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.concurrent.Callable; | ||
import java.util.concurrent.ExecutionException; | ||
import java.util.concurrent.ExecutorService; | ||
import java.util.concurrent.Executors; | ||
import java.util.concurrent.Future; | ||
import java.util.stream.Collectors; | ||
|
||
/** | ||
* @author iryndin | ||
* @since 20/01/17 | ||
*/ | ||
public class TreeComputation implements AutoCloseable { | ||
|
||
final static Logger log = LoggerFactory.getLogger(TreeComputation.class); | ||
|
||
private final INodeRegistry registry; | ||
private final ExecutorService executorService; | ||
|
||
public TreeComputation(INodeRegistry registry) { | ||
this(registry, Executors.newCachedThreadPool()); | ||
} | ||
|
||
public TreeComputation(INodeRegistry registry, ExecutorService executorService) { | ||
this.registry = registry; | ||
this.executorService = executorService; | ||
} | ||
|
||
@Override | ||
public void close() throws Exception { | ||
log.info("Closing TreeComputation..."); | ||
executorService.shutdown(); | ||
log.info("TreeComputation closed"); | ||
} | ||
|
||
public Optional<ITreeResult> compute(String start) throws Exception { | ||
log.info("Start tree computation, start node ID: '{}'", start); | ||
// 1. get configured and created node by node ID | ||
Optional<INode> node = registry.getNode(start); | ||
if (node.isPresent()) { | ||
// 2. Create empty TreeResult | ||
ITreeResult treeResult = new TreeResultImpl(); | ||
log.debug("Start node: {}", node.get()); | ||
// 3. Start tree computation | ||
computeRecursive(Collections.singletonList(node.get()), treeResult); | ||
return Optional.of(treeResult); | ||
} else { | ||
log.info("Cannot find node with ID: '{}'", start); | ||
} | ||
return Optional.absent(); | ||
} | ||
|
||
private void computeRecursive(List<INode> nodes, ITreeResult treeResult) throws ExecutionException, InterruptedException { | ||
if (nodes.isEmpty()) { | ||
log.debug("Empty list of nodes passed"); | ||
return; | ||
} | ||
log.debug("Going to compute following nodes: '{}'", | ||
Joiner.on(",").join(nodes.stream().map(n -> n.getId()).collect(Collectors.toList()))); | ||
List<NodeComputationCallable> callables = nodes.stream() | ||
.map(node -> new NodeComputationCallable(node, treeResult)) | ||
.collect(Collectors.toList()); | ||
|
||
List<Future<INodeResult>> futures = executorService.invokeAll(callables); | ||
|
||
List<INodeResult> results = Lists.newArrayListWithCapacity(futures.size()); | ||
for (Future<INodeResult> f : futures) { | ||
results.add(f.get()); | ||
} | ||
|
||
List<INode> treeNodes = results.stream() | ||
.map(res -> { | ||
Optional<List<String>> nodeResults = registry.getNodeResults(res.getNodeId(), res.getValue()); | ||
if (nodeResults.isPresent()) { | ||
log.debug("Results from registry by nodeID '{}' and result '{}': '{}'", | ||
res.getNodeId(), res.getValue(), Joiner.on(",").join(nodeResults.get())); | ||
} else { | ||
log.debug("No results from registry by nodeID '{}' and result '{}'", res.getNodeId(), res.getValue()); | ||
} | ||
return nodeResults.orNull(); | ||
}) | ||
.filter(x -> x != null) | ||
.flatMap(x -> x.stream()) | ||
.map(nodeId -> { | ||
log.debug("Going to search node by id: {}", nodeId); | ||
return registry.getNode(nodeId).orNull(); | ||
}) | ||
.filter(node -> node != null) | ||
.collect(Collectors.toList()); | ||
|
||
if (!treeNodes.isEmpty()) { | ||
computeRecursive(treeNodes, treeResult); | ||
} else { | ||
log.debug("Empty list of nodes, do not pass it to computation"); | ||
} | ||
} | ||
|
||
/** | ||
* This class wraps node computation call | ||
*/ | ||
static class NodeComputationCallable implements Callable<INodeResult> { | ||
|
||
private final INode node; | ||
private final ITreeResult treeResult; | ||
|
||
public NodeComputationCallable(INode node, ITreeResult treeResult) { | ||
this.node = node; | ||
this.treeResult = treeResult; | ||
} | ||
|
||
@Override | ||
public INodeResult call() throws Exception { | ||
return node.compute(treeResult); | ||
} | ||
} | ||
} |
Oops, something went wrong.