Skip to content

Commit

Permalink
Merge pull request #336 from speedment/terminal
Browse files Browse the repository at this point in the history
Optimize terminal operations
  • Loading branch information
julgus committed Jun 5, 2023
2 parents 3977c3b + 2c4d615 commit 53c513c
Show file tree
Hide file tree
Showing 21 changed files with 840 additions and 13 deletions.
6 changes: 6 additions & 0 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@
<version>${jpa-streamer.version}</version>
</dependency>

<dependency>
<groupId>com.speedment.jpastreamer</groupId>
<artifactId>termopmodifier-standard</artifactId>
<version>${jpa-streamer.version}</version>
</dependency>

<dependency>
<groupId>com.speedment.jpastreamer</groupId>
<artifactId>announcer</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,19 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
return false;
}

roundEnv.getElementsAnnotatedWith(Entity.class).stream()
Set<? extends Element> entities = roundEnv.getElementsAnnotatedWith(Entity.class);

if (entities.isEmpty()) {
System.out.format("[JPAStreamer Field Generator Processor] Found no classes annotated with jakarta.persistence.Entity.\n");
return true;
}

entities.stream()
.filter(ae -> ae.getKind() == ElementKind.CLASS)
.forEach(ae -> {
try {
final String entityName = ae.asType().toString();
System.out.format("[JPAStreamer Field Generator Processor] Generating class for: %s\n", entityName);
final String shortEntityName = shortName(entityName);

final String prefix = processingEnv.getOptions().getOrDefault("jpaStreamerPrefix", "");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
*/
package com.speedment.jpastreamer.pipeline.intermediate;

import com.speedment.jpastreamer.pipeline.terminal.TerminalOperation;

import java.util.Comparator;
import java.util.function.*;
import java.util.stream.DoubleStream;
Expand All @@ -22,8 +24,7 @@
public interface IntermediateOperationFactory {

<T> IntermediateOperation<Stream<T>, Stream<T>> createFilter(Predicate<? super T> predicate);



<T, R> IntermediateOperation<Stream<T>, Stream<R>> createMap(Function<? super T, ? extends R> mapper);

<T> IntermediateOperation<Stream<T>, IntStream> createMapToInt(ToIntFunction<? super T> mapper);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.speedment.jpastreamer.pipeline.intermediate.IntermediateOperation;
import com.speedment.jpastreamer.pipeline.intermediate.IntermediateOperationFactory;
import com.speedment.jpastreamer.pipeline.intermediate.IntermediateOperationType;
import com.speedment.jpastreamer.pipeline.terminal.TerminalOperation;

import java.util.Comparator;
import java.util.function.*;
Expand Down Expand Up @@ -51,7 +52,6 @@ public <T> IntermediateOperation<Stream<T>, Stream<T>> createFilter(final Predic
Stream.class,
function,
predicate);

}

@Override
Expand Down
8 changes: 6 additions & 2 deletions provider/renderer-standard/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,23 @@
<groupId>com.speedment.jpastreamer</groupId>
<artifactId>interopoptimizer</artifactId>
</dependency>

<dependency>
<groupId>com.speedment.jpastreamer</groupId>
<artifactId>rootfactory</artifactId>
</dependency>

<dependency>
<groupId>com.speedment.jpastreamer</groupId>
<artifactId>termopmodifier</artifactId>
</dependency>

<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>${jakarta.version}</version>
</dependency>


</dependencies>


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.speedment.jpastreamer.rootfactory.RootFactory;
import com.speedment.jpastreamer.streamconfiguration.StreamConfiguration;

import com.speedment.jpastreamer.termopmodifier.TerminalOperationModifierFactory;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.TypedQuery;
Expand All @@ -48,6 +49,7 @@ final class StandardRenderer implements Renderer {
private final CriteriaFactory criteriaFactory;

private final IntermediateOperationOptimizerFactory intermediateOperationOptimizerFactory;
private final TerminalOperationModifierFactory terminalOperationModifierFactory;

private final MergerFactory mergerFactory;

Expand All @@ -59,19 +61,22 @@ final class StandardRenderer implements Renderer {
this.entityManager = requireNonNull(entityManagerSupplier).get();
this.criteriaFactory = RootFactory.getOrThrow(CriteriaFactory.class, ServiceLoader::load);
this.intermediateOperationOptimizerFactory = RootFactory.getOrThrow(IntermediateOperationOptimizerFactory.class, ServiceLoader::load);
this.terminalOperationModifierFactory = RootFactory.getOrThrow(TerminalOperationModifierFactory.class, ServiceLoader::load);
this.mergerFactory = RootFactory.getOrThrow(MergerFactory.class, ServiceLoader::load);
}

StandardRenderer(final EntityManager entityManager) {
this.entityManager = entityManager;
this.criteriaFactory = RootFactory.getOrThrow(CriteriaFactory.class, ServiceLoader::load);
this.intermediateOperationOptimizerFactory = RootFactory.getOrThrow(IntermediateOperationOptimizerFactory.class, ServiceLoader::load);
this.terminalOperationModifierFactory = RootFactory.getOrThrow(TerminalOperationModifierFactory.class, ServiceLoader::load);
this.mergerFactory = RootFactory.getOrThrow(MergerFactory.class, ServiceLoader::load);
}

@Override
@SuppressWarnings("unchecked")
public <E, T, S extends BaseStream<T, S>> RenderResult<E, T, S> render(final Pipeline<E> pipeline, final StreamConfiguration<E> streamConfiguration) {
modifyPipeline(pipeline);
optimizePipeline(pipeline);

final Class<E> entityClass = pipeline.root();
Expand Down Expand Up @@ -180,7 +185,11 @@ private <E, T, S extends BaseStream<T, S>> S replay(final Stream<E> stream, fina
return decorated;
*/
}


private <T> void modifyPipeline(final Pipeline<T> pipeline) {
terminalOperationModifierFactory.get().modify(pipeline);
}

private <T> void optimizePipeline(final Pipeline<T> pipeline) {
intermediateOperationOptimizerFactory.stream().forEach(intermediateOperationOptimizer -> intermediateOperationOptimizer.optimize(pipeline));
}
Expand Down
1 change: 1 addition & 0 deletions provider/renderer-standard/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
requires jpastreamer.criteria;
requires jpastreamer.merger;
requires jpastreamer.interopoptimizer;
requires jpastreamer.termopmodifier;

uses CriteriaFactory;
uses MergerFactory;
Expand Down
18 changes: 18 additions & 0 deletions provider/termopmodifier-standard/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,28 @@
</description>

<dependencies>

<dependency>
<groupId>com.speedment.jpastreamer</groupId>
<artifactId>termopmodifier</artifactId>
</dependency>

<dependency>
<groupId>com.speedment.jpastreamer</groupId>
<artifactId>rootfactory</artifactId>
</dependency>

<dependency>
<groupId>com.speedment.jpastreamer</groupId>
<artifactId>pipeline-standard</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.speedment.jpastreamer</groupId>
<artifactId>field</artifactId>
</dependency>

</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ public final class InternalTerminalOperatorModifierFactory implements TerminalOp
public TerminalOperationModifier get() {
return singleton;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,93 @@
*/
package com.speedment.jpastreamer.termopmodifier.standard.internal;

import com.speedment.jpastreamer.field.predicate.SpeedmentPredicate;
import com.speedment.jpastreamer.pipeline.Pipeline;
import com.speedment.jpastreamer.pipeline.intermediate.IntermediateOperationFactory;
import com.speedment.jpastreamer.pipeline.terminal.TerminalOperation;
import com.speedment.jpastreamer.pipeline.terminal.TerminalOperationFactory;
import com.speedment.jpastreamer.pipeline.terminal.TerminalOperationType;
import com.speedment.jpastreamer.rootfactory.RootFactory;
import com.speedment.jpastreamer.termopmodifier.TerminalOperationModifier;

import java.util.Optional;
import java.util.ServiceLoader;

import static java.util.Objects.requireNonNull;

final class StandardTerminalOperatorModifier implements TerminalOperationModifier {

private final IntermediateOperationFactory intermediateOperationFactory;
private final TerminalOperationFactory terminalOperationFactory;

StandardTerminalOperatorModifier() {
this.intermediateOperationFactory = RootFactory.getOrThrow(IntermediateOperationFactory.class, ServiceLoader::load);
this.terminalOperationFactory = RootFactory.getOrThrow(TerminalOperationFactory.class, ServiceLoader::load);
}

@Override
public <T> Pipeline<T> modify(Pipeline<T> pipeline) {
requireNonNull(pipeline);
// For now, just return whatever we get.

final TerminalOperationType terminalOperationType = pipeline.terminatingOperation().type();

switch (terminalOperationType) {
case ANY_MATCH:
return modifyAnyMatch(pipeline);
case NONE_MATCH:
return modifyNoneMatch(pipeline);
case FIND_FIRST:
return modifyFindFirst(pipeline);
case FIND_ANY:
return modifyFindAny(pipeline);
default:
return pipeline;
}
}

private <T> Pipeline<T> modifyAnyMatch(Pipeline<T> pipeline) {
this.<T>getPredicate(pipeline.terminatingOperation()).ifPresent(speedmentPredicate -> {
pipeline.intermediateOperations().add(intermediateOperationFactory.createFilter(speedmentPredicate));
pipeline.intermediateOperations().add(intermediateOperationFactory.createLimit(1));
pipeline.terminatingOperation(terminalOperationFactory.createAnyMatch(p -> true));
});
return pipeline;
}

private <T> Pipeline<T> modifyNoneMatch(Pipeline<T> pipeline) {
this.<T>getPredicate(pipeline.terminatingOperation()).ifPresent(speedmentPredicate -> {
pipeline.intermediateOperations().add(intermediateOperationFactory.createFilter(speedmentPredicate));
pipeline.intermediateOperations().add(intermediateOperationFactory.createLimit(1));
// NoneMatch() - If the stream is empty then true is returned and the predicate is not evaluated.
// If the expression is evaluated => There is a match and the expression is always false.
pipeline.terminatingOperation(terminalOperationFactory.createNoneMatch(e -> true));
});
return pipeline;
}

private <T> Pipeline<T> modifyFindFirst(Pipeline<T> pipeline) {
pipeline.intermediateOperations().add(intermediateOperationFactory.createLimit(1));
return pipeline;
}

private <T> Pipeline<T> modifyFindAny(Pipeline<T> pipeline) {
pipeline.ordered(false);
pipeline.intermediateOperations().add(intermediateOperationFactory.createLimit(1));
return pipeline;
}

private <T> Optional<SpeedmentPredicate<T>> getPredicate(final TerminalOperation<?, ?> operation) {
final Object[] arguments = operation.arguments();

if (arguments.length != 1) {
return Optional.empty();
}

if (arguments[0] instanceof SpeedmentPredicate) {
return Optional.of((SpeedmentPredicate<T>) arguments[0]);
}

return Optional.empty();
}

}
10 changes: 10 additions & 0 deletions provider/termopmodifier-standard/src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import com.speedment.jpastreamer.pipeline.PipelineFactory;
import com.speedment.jpastreamer.pipeline.intermediate.IntermediateOperationFactory;
import com.speedment.jpastreamer.pipeline.terminal.TerminalOperationFactory;
import com.speedment.jpastreamer.termopmodifier.TerminalOperationModifierFactory;
import com.speedment.jpastreamer.termopmodifier.standard.StandardTerminalOperatorModifierFactory;

Expand All @@ -15,8 +18,15 @@
*/
module jpastreamer.termopmodifier.standard {
requires transitive jpastreamer.termopmodifier;
requires jpastreamer.rootfactory;
requires jpastreamer.pipeline;
requires jpastreamer.field;

exports com.speedment.jpastreamer.termopmodifier.standard;

uses PipelineFactory;
uses TerminalOperationFactory;
uses IntermediateOperationFactory;

provides TerminalOperationModifierFactory with StandardTerminalOperatorModifierFactory;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.speedment.jpastreamer.termopmodifier.standard;

import com.speedment.jpastreamer.termopmodifier.TerminalOperationModifierFactory;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertNotNull;

public class StandardTerminalOperationModifierFactoryTest {

@Test
void get() {
final TerminalOperationModifierFactory terminalOperationModifierFactory = new StandardTerminalOperatorModifierFactory();
assertNotNull(terminalOperationModifierFactory.get());
}

}

0 comments on commit 53c513c

Please sign in to comment.