Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize terminal operations #336

Merged
merged 5 commits into from
Jun 5, 2023
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
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());
}

}
Loading