Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
package io.koraframework.application.graph.internal;

import io.koraframework.application.graph.All;
import io.koraframework.application.graph.Graph;
import io.koraframework.application.graph.NodeWithMapper;
import io.koraframework.application.graph.PromiseOf;
import io.koraframework.application.graph.*;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.function.Function;

public final class AllPromisesImpl<T> implements All<PromiseOf<T>> {
private final Graph graph;
private final ArrayList<PromiseWrapper<?, T>> values;

@SafeVarargs
public AllPromisesImpl(Graph graph, NodeWithMapper<?, T>... nodes) {
this.graph = graph;
this.values = new ArrayList<>(nodes.length);
for (var node : nodes) {
this.values.add(new PromiseWrapper<>(graph, node));
}
}

private record PromiseWrapper<N, V>(PromiseOf<? extends N> promise, Function<N, V> mapper) {
private record PromiseWrapper<N, V>(PromiseOf<? extends N> promise, Function<N, V> mapper, Node<? extends N> node) {
public PromiseWrapper(Graph graph, NodeWithMapper<N, V> element) {
var promise = graph.promiseOf(element.node());
this(promise, element.mapper());
this(promise, element.mapper(), element.node());
}

public PromiseOf<V> get() {
Expand All @@ -33,18 +32,14 @@ public PromiseOf<V> get() {

@Override
public Iterator<PromiseOf<T>> iterator() {
var it = values.iterator();
return new Iterator<>() {
@Override
public boolean hasNext() {
return it.hasNext();
var list = new ArrayList<PromiseOf<T>>();
for (var value : this.values) {
var condition = value.node().condition();
if (condition == null || condition.apply(graph) instanceof GraphCondition.ConditionResult.Matched) {
list.add(value.get());
}

@Override
public PromiseOf<T> next() {
return it.next().get();
}
};
}
return list.iterator();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import io.koraframework.application.graph.All;
import io.koraframework.application.graph.Graph;
import io.koraframework.application.graph.GraphCondition;
import io.koraframework.application.graph.NodeWithMapper;

import java.util.ArrayList;
Expand All @@ -15,7 +16,10 @@ public final class AllSimpleImpl<T> implements All<T> {
public AllSimpleImpl(Graph graph, NodeWithMapper<?, T>... nodes) {
this.values = new ArrayList<T>(nodes.length);
for (var node : nodes) {
this.values.add(get(graph, node));
var condition = node.node().condition();
if (condition == null || condition.apply(graph) instanceof GraphCondition.ConditionResult.Matched) {
this.values.add(get(graph, node));
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
package io.koraframework.application.graph.internal;

import io.koraframework.application.graph.All;
import io.koraframework.application.graph.Graph;
import io.koraframework.application.graph.NodeWithMapper;
import io.koraframework.application.graph.ValueOf;
import io.koraframework.application.graph.*;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.function.Function;

public final class AllValuesImpl<T> implements All<ValueOf<T>> {
private final Graph graph;
private final ArrayList<ValueWrapper<?, T>> values;

@SafeVarargs
public AllValuesImpl(Graph graph, NodeWithMapper<?, T>... nodes) {
this.graph = graph;
this.values = new ArrayList<>(nodes.length);
for (var node : nodes) {
this.values.add(new ValueWrapper<>(graph, node));
}
}

private record ValueWrapper<N, V>(ValueOf<? extends N> value, Function<N, V> mapper) {
private record ValueWrapper<N, V>(ValueOf<? extends N> value, Function<N, V> mapper, Node<? extends N> node) {
public ValueWrapper(Graph graph, NodeWithMapper<N, V> element) {
var promise = graph.valueOf(element.node());
this(promise, element.mapper());
this(promise, element.mapper(), element.node());
}

public ValueOf<V> get() {
Expand All @@ -33,17 +32,13 @@ public ValueOf<V> get() {

@Override
public Iterator<ValueOf<T>> iterator() {
var it = this.values.iterator();
return new Iterator<>() {
@Override
public boolean hasNext() {
return it.hasNext();
var list = new ArrayList<ValueOf<T>>();
for (var value : this.values) {
var condition = value.node().condition();
if (condition == null || condition.apply(graph) instanceof GraphCondition.ConditionResult.Matched) {
list.add(value.get());
}

@Override
public ValueOf<T> next() {
return it.next().get();
}
};
}
return list.iterator();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ public void processCondition() {
} else {
condition = new HashSet<>(this.parentConditions);
condition.add(this.declaration.condition());
condition.remove(UNCONDITIONALLY);
}

for (var dependency : this.dependencies) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ static int maxDependencyIndex(ComponentDependency dependency) {
.min(Comparator.naturalOrder())
.orElse(-1);
assert conditionIndex > maxDependency;
System.arraycopy(resolvedComponents, maxDependency + 1, resolvedComponents, maxDependency + 2, conditionIndex - maxDependency);
System.arraycopy(resolvedComponents, maxDependency + 1, resolvedComponents, maxDependency + 2, conditionIndex - maxDependency - 1);
resolvedComponents[maxDependency + 1] = condition;
for (int i = maxDependency + 1; i <= conditionIndex; i++) {
resolvedComponents[i].setIndex(i);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,55 @@ public class TestClass2 {}
}
}
}

@Test
public void testConditionalWithAll() {
var draw = compile("""
import io.koraframework.application.graph.All;import io.koraframework.application.graph.PromiseOf;import io.koraframework.application.graph.ValueOf;@KoraApp
public interface ExampleApplication {
@Root
default Object root(All<TestInterface> o1, All<PromiseOf<TestInterface>> o2, All<ValueOf<TestInterface>> o3) {
o1.forEach(java.util.Objects::requireNonNull);
o2.forEach(java.util.Objects::requireNonNull);
o3.forEach(java.util.Objects::requireNonNull);
return o2.iterator().next();
}

@Tag(io.koraframework.kora.app.annotation.processor.ConditionalComponentTest.MatchesCondition.class)
default GraphCondition matches() { return new io.koraframework.kora.app.annotation.processor.ConditionalComponentTest.MatchesCondition(); }

@Tag(io.koraframework.kora.app.annotation.processor.ConditionalComponentTest.FailedCondition.class)
default GraphCondition failed() { return new io.koraframework.kora.app.annotation.processor.ConditionalComponentTest.FailedCondition(); }
}
""", """
@Component
@Conditional(tag = io.koraframework.kora.app.annotation.processor.ConditionalComponentTest.MatchesCondition.class)
public class TestClass1 implements TestInterface{
}
""", """
@Component
@Conditional(tag = io.koraframework.kora.app.annotation.processor.ConditionalComponentTest.FailedCondition.class)
public class TestClass2 implements TestInterface{
}
""", """
public interface TestInterface {}
""");
assertThat(draw.getNodes()).hasSize(5);
var graph = draw.init();
var class1Node = draw.getNodes()
.stream()
.filter(n -> n.type().toString().contains("TestClass1"))
.findFirst()
.get();
var class2Node = draw.getNodes()
.stream()
.filter(n -> n.type().toString().contains("TestClass2"))
.findFirst()
.get();
Assertions.assertThat(graph.get(class1Node)).isNotNull();
Assertions.assertThatThrownBy(() -> graph.get(class2Node))
.hasMessage("Node value was not initialized: test");
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class ResolvedComponent(
else -> {
val set = HashSet(this.parentConditions)
set.add(this.declaration.condition)
set.remove(unconditionally)
set
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class ResolvedComponents() {
.map { maxDependencyIndex(it) }
.minOrNull() ?: -1
require(conditionIndex > maxDependency)
resolvedComponents.copyInto(resolvedComponents, maxDependency + 1, maxDependency + 2, conditionIndex - maxDependency)
resolvedComponents.copyInto(resolvedComponents, maxDependency + 1, maxDependency + 2, conditionIndex - maxDependency - 1)
resolvedComponents[maxDependency + 1] = condition;
for (i in maxDependency + 1..conditionIndex) {
resolvedComponents[i]?.setIndex(i)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,45 @@ class ConditionalComponentTest : AbstractKoraAppProcessorTest() {
}
}

@Test
fun testConditionalWithAll() {
val draw = compile(
"""
@KoraApp
interface ExampleApplication {
@Root
fun root(o1: All<TestInterface>, o2: All<PromiseOf<TestInterface>>, o3: All<ValueOf<TestInterface>>): Any {
o1.forEach(java.util.Objects::requireNonNull)
o2.forEach(java.util.Objects::requireNonNull)
o3.forEach(java.util.Objects::requireNonNull)
return o2.iterator().next()
}

@Tag(io.koraframework.kora.app.ksp.ConditionalComponentTest.MatchesCondition::class)
fun matches(): GraphCondition { return io.koraframework.kora.app.ksp.ConditionalComponentTest.MatchesCondition() }

@Tag(io.koraframework.kora.app.ksp.ConditionalComponentTest.FailedCondition::class)
fun failed(): GraphCondition { return io.koraframework.kora.app.ksp.ConditionalComponentTest.FailedCondition() }
}

""".trimIndent(), """
@Component
@Conditional(tag = io.koraframework.kora.app.ksp.ConditionalComponentTest.MatchesCondition::class)
class TestClass1: TestInterface
""".trimIndent(), """
@Component
@Conditional(tag = io.koraframework.kora.app.ksp.ConditionalComponentTest.FailedCondition::class)
class TestClass2: TestInterface
""".trimIndent(), """
interface TestInterface
""".trimIndent()
)
assertThat(draw.nodes).hasSize(5)
val graph = draw.init()
val class1Node = draw.nodes.first { it.type().toString().contains("TestClass1") }
val class2Node = draw.nodes.first { it.type().toString().contains("TestClass2") }
assertThat(graph.get(class1Node)).isNotNull()
assertThatThrownBy { graph.get(class2Node) }
.hasMessage("Node value was not initialized: test")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ abstract class AbstractSymbolProcessorTest {
s.indexOf("{", it + 1),
s.indexOf(":", it + 1),
s.indexOf("<", it + 1),
s.length - 1
)
.map { it1 -> it to it1 }
}
Expand Down
Loading