Skip to content

Commit 5090334

Browse files
authored
Merge pull request #1 from wavesoftware/feature/complete-functionality
Complete functionality
2 parents 845442c + 3061a77 commit 5090334

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+2462
-5
lines changed

.editorconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# EditorConfig is awesome: http://EditorConfig.org
2+
3+
# top-most EditorConfig file
4+
root = true
5+
6+
# Unix-style newlines with a newline ending every file
7+
[*]
8+
end_of_line = lf
9+
insert_final_newline = true
10+
charset = utf-8
11+
indent_style = space
12+
indent_size = 2

.travis.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,12 @@
11
language: java
2+
script: ./mvnw install --fail-at-end
3+
matrix:
4+
include:
5+
- jdk: openjdk8
6+
env: JACOCO=true COVERALLS=true
7+
- jdk: oraclejdk8
8+
- jdk: oraclejdk9
9+
- jdk: openjdk8
10+
env: GDMSESSION=sonar
11+
- jdk: openjdk8
12+
env: SONAR=publish

pom.xml

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
<sonar.working.directory>${project.build.directory}/sonar</sonar.working.directory>
6868
<sonar.host.url>https://sonar.wavesoftware.pl</sonar.host.url>
6969
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
70-
<java.source.version>7</java.source.version>
70+
<java.source.version>8</java.source.version>
7171
<sonar.java.source>${java.source.version}</sonar.java.source>
7272
<maven.compiler.source>1.${java.source.version}</maven.compiler.source>
7373
<maven.compiler.target>${maven.compiler.source}</maven.compiler.target>
@@ -80,10 +80,12 @@
8080
</properties>
8181

8282
<dependencies>
83+
<!-- provided -->
8384
<dependency>
84-
<groupId>pl.wavesoftware</groupId>
85-
<artifactId>eid-exceptions</artifactId>
86-
<version>1.2.0</version>
85+
<groupId>javax.persistence</groupId>
86+
<artifactId>javax.persistence-api</artifactId>
87+
<version>2.2</version>
88+
<scope>provided</scope>
8789
</dependency>
8890
<dependency>
8991
<groupId>org.projectlombok</groupId>
@@ -92,7 +94,28 @@
9294
<scope>provided</scope>
9395
<optional>true</optional>
9496
</dependency>
97+
<dependency>
98+
<groupId>org.mapstruct</groupId>
99+
<artifactId>mapstruct-jdk8</artifactId>
100+
<version>[1.2.0.Final,2.0.0)</version>
101+
<scope>provided</scope>
102+
</dependency>
103+
<dependency>
104+
<groupId>org.mapstruct</groupId>
105+
<artifactId>mapstruct-processor</artifactId>
106+
<version>[1.2.0.Final,2.0.0)</version>
107+
<scope>provided</scope>
108+
<optional>true</optional>
109+
</dependency>
110+
111+
<!-- runtime -->
112+
<dependency>
113+
<groupId>pl.wavesoftware</groupId>
114+
<artifactId>eid-exceptions</artifactId>
115+
<version>1.2.0</version>
116+
</dependency>
95117

118+
<!-- test -->
96119
<dependency>
97120
<groupId>junit</groupId>
98121
<artifactId>junit</artifactId>
@@ -102,7 +125,25 @@
102125
<dependency>
103126
<groupId>org.assertj</groupId>
104127
<artifactId>assertj-core</artifactId>
105-
<version>2.5.0</version>
128+
<version>3.9.1</version>
129+
<scope>test</scope>
130+
</dependency>
131+
<dependency>
132+
<groupId>org.mockito</groupId>
133+
<artifactId>mockito-core</artifactId>
134+
<version>2.18.3</version>
135+
<scope>test</scope>
136+
</dependency>
137+
<dependency>
138+
<groupId>com.google.inject</groupId>
139+
<artifactId>guice</artifactId>
140+
<version>4.2.0</version>
141+
<scope>test</scope>
142+
</dependency>
143+
<dependency>
144+
<groupId>org.hibernate</groupId>
145+
<artifactId>hibernate-core</artifactId>
146+
<version>5.2.17.Final</version>
106147
<scope>test</scope>
107148
</dependency>
108149
</dependencies>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package pl.wavesoftware.lang;
2+
3+
import java.util.Objects;
4+
import java.util.function.Consumer;
5+
6+
/**
7+
* Represents an operation that accepts tree input arguments and returns no
8+
* result. This is the tree-arity specialization of {@link Consumer}.
9+
* Unlike most other functional interfaces, {@code TriConsumer} is expected
10+
* to operate via side-effects.
11+
*
12+
* <p>This is a <a href="package-summary.html">functional interface</a>
13+
* whose functional method is {@link #accept(Object, Object, Object)}.
14+
*
15+
* @param <T> the type of the first argument to the operation
16+
* @param <U> the type of the second argument to the operation
17+
* @param <V> the type of the third argument to the operation
18+
*
19+
* @see Consumer
20+
* @author <a href="mailto:[email protected]">Krzysztof Suszynski</a>
21+
* @since 25.04.18
22+
*/
23+
@FunctionalInterface
24+
public interface TriConsumer<T, U, V> {
25+
/**
26+
* Performs this operation on the given arguments.
27+
*
28+
* @param t the first input argument
29+
* @param u the second input argument
30+
* @param v the third input argument
31+
*/
32+
void accept(T t, U u, V v);
33+
34+
/**
35+
* Returns a composed {@code TriConsumer} that performs, in sequence, this
36+
* operation followed by the {@code after} operation. If performing either
37+
* operation throws an exception, it is relayed to the caller of the
38+
* composed operation. If performing this operation throws an exception,
39+
* the {@code after} operation will not be performed.
40+
*
41+
* @param after the operation to perform after this operation
42+
* @return a composed {@code TriConsumer} that performs in sequence this
43+
* operation followed by the {@code after} operation
44+
* @throws NullPointerException if {@code after} is null
45+
*/
46+
default TriConsumer<T, U, V> andThen(TriConsumer<? super T, ? super U, ? super V> after) {
47+
Objects.requireNonNull(after);
48+
49+
return (f, s, t) -> {
50+
accept(f, s, t);
51+
after.accept(f, s, t);
52+
};
53+
}
54+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* @author <a href="[email protected]">Krzysztof Suszyński</a>
3+
* @since 2018-05-03
4+
*/
5+
@ParametersAreNonnullByDefault
6+
package pl.wavesoftware.lang;
7+
8+
import javax.annotation.ParametersAreNonnullByDefault;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package pl.wavesoftware.utils.mapstruct.jpa;
2+
3+
import pl.wavesoftware.lang.TriConsumer;
4+
5+
/**
6+
* @author <a href="[email protected]">Krzysztof Suszyński</a>
7+
* @since 2018-05-02
8+
*/
9+
public abstract class AbstractCompositeContextMapping<I, O> extends AbstractMapping<I, O, CompositeContext> {
10+
protected AbstractCompositeContextMapping(Class<I> sourceClass,
11+
Class<O> targetClass) {
12+
super(sourceClass, targetClass, CompositeContext.class);
13+
}
14+
15+
public static <I, O> AbstractCompositeContextMapping<I, O> mapperFor(
16+
Class<I> inputClass,
17+
Class<O> outputClass,
18+
TriConsumer<I, O, CompositeContext> consumer) {
19+
20+
return new AbstractCompositeContextMapping<I, O>(inputClass, outputClass) {
21+
@Override
22+
public void accept(I input, O output, CompositeContext context) {
23+
consumer.accept(input, output, context);
24+
}
25+
};
26+
}
27+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package pl.wavesoftware.utils.mapstruct.jpa;
2+
3+
import lombok.RequiredArgsConstructor;
4+
5+
import javax.annotation.Nullable;
6+
import java.util.function.Supplier;
7+
8+
/**
9+
* @author <a href="[email protected]">Krzysztof Suszyński</a>
10+
* @since 2018-05-03
11+
*/
12+
public abstract class AbstractCompositeContextProvider
13+
implements MapStructContextProvider<CompositeContext> {
14+
15+
@Override
16+
public CompositeContext createNewContext() {
17+
StoringMappingContext cyclicGraphCtx = new CyclicGraphContext();
18+
CompositeContextBuilder contextBuilder = CompositeContext.builder();
19+
Supplier<CompositeContext> contextSupplier = new StoringMappingContextSupplier(contextBuilder);
20+
Mappings.MappingsBuilder mappingsBuilder = Mappings.builder();
21+
for (MappingProvider<?, ?, ?> mappingProvider : getMappingProviders()) {
22+
mappingsBuilder.addMapping(mappingProvider.provide());
23+
}
24+
JpaMappingContext jpaContext = getJpaMappingContextFactory()
25+
.produce(
26+
contextSupplier,
27+
mappingsBuilder.build(),
28+
getIdentifierCollector()
29+
);
30+
31+
contextBuilder.addContext(cyclicGraphCtx);
32+
contextBuilder.addContext(jpaContext);
33+
34+
return contextSupplier.get();
35+
}
36+
37+
protected abstract JpaMappingContextFactory getJpaMappingContextFactory();
38+
protected abstract Iterable<MappingProvider> getMappingProviders();
39+
protected abstract IdentifierCollector getIdentifierCollector();
40+
41+
@RequiredArgsConstructor
42+
private static final class StoringMappingContextSupplier implements Supplier<CompositeContext> {
43+
private final CompositeContextBuilder contextBuilder;
44+
@Nullable
45+
private CompositeContext context;
46+
47+
@Override
48+
public CompositeContext get() {
49+
if (context == null) {
50+
context = contextBuilder.build();
51+
}
52+
return context;
53+
}
54+
}
55+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package pl.wavesoftware.utils.mapstruct.jpa;
2+
3+
import lombok.Getter;
4+
import lombok.RequiredArgsConstructor;
5+
6+
/**
7+
* @author <a href="mailto:[email protected]">Krzysztof Suszynski</a>
8+
* @since 25.04.18
9+
*/
10+
@Getter
11+
@RequiredArgsConstructor
12+
public abstract class AbstractMapping<I, O, C> implements Mapping<I, O, C> {
13+
private final Class<I> sourceClass;
14+
private final Class<O> targetClass;
15+
private final Class<C> contextClass;
16+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package pl.wavesoftware.utils.mapstruct.jpa;
2+
3+
import org.mapstruct.BeforeMapping;
4+
import org.mapstruct.MappingTarget;
5+
import org.mapstruct.TargetType;
6+
7+
import javax.annotation.Nullable;
8+
import java.util.ArrayList;
9+
import java.util.Arrays;
10+
import java.util.Collections;
11+
import java.util.List;
12+
import java.util.Optional;
13+
14+
/**
15+
* A composite mapping context that can utilize multiple mapping contexts.
16+
*
17+
* @author <a href="mailto:[email protected]">Krzysztof Suszynski</a>
18+
* @since 02.05.18
19+
*/
20+
public final class CompositeContext implements MapStructContext {
21+
private final List<MappingContext> mappingContexts = new ArrayList<>();
22+
23+
/**
24+
* You can pass multiple mapping contexts to be used in this composite mapping context
25+
*
26+
* @param mappingContexts a array of mapping contexts
27+
*/
28+
public CompositeContext(MappingContext... mappingContexts) {
29+
Collections.addAll(this.mappingContexts, mappingContexts);
30+
}
31+
32+
/**
33+
* A builder interface for {@link CompositeContext}.
34+
*
35+
* @return a builder interface
36+
*/
37+
public static CompositeContextBuilder builder() {
38+
return new CompositeContextBuilderImpl();
39+
}
40+
41+
@Override
42+
@BeforeMapping
43+
public void storeMappedInstance(Object source,
44+
@MappingTarget Object target) {
45+
for (MappingContext mappingContext : mappingContexts) {
46+
if (mappingContext instanceof StoringMappingContext) {
47+
StoringMappingContext.class.cast(mappingContext)
48+
.storeMappedInstance(source, target);
49+
}
50+
}
51+
}
52+
53+
@Override
54+
@Nullable
55+
@BeforeMapping
56+
public <T> T getMappedInstance(Object source,
57+
@TargetType Class<T> targetType) {
58+
return getMappedInstanceOptional(source, targetType)
59+
.orElse(null);
60+
}
61+
62+
@Override
63+
public <T> Optional<T> getMappedInstanceOptional(Object source,
64+
Class<T> targetType) {
65+
for (MappingContext mappingContext : mappingContexts) {
66+
Optional<T> instance = mappingContext.getMappedInstanceOptional(source, targetType);
67+
if (instance.isPresent()) {
68+
return instance;
69+
}
70+
}
71+
return Optional.empty();
72+
}
73+
74+
private static final class CompositeContextBuilderImpl implements CompositeContextBuilder {
75+
private final List<MappingContext> mappingContexts = new ArrayList<>();
76+
77+
@Override
78+
public CompositeContextBuilderImpl addContext(MappingContext... mappingContexts) {
79+
this.mappingContexts.addAll(
80+
Arrays.asList(mappingContexts)
81+
);
82+
return this;
83+
}
84+
85+
@Override
86+
public CompositeContext build() {
87+
return new CompositeContext(
88+
mappingContexts.toArray(new MappingContext[0])
89+
);
90+
}
91+
}
92+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package pl.wavesoftware.utils.mapstruct.jpa;
2+
3+
/**
4+
* @author <a href="mailto:[email protected]">Krzysztof Suszynski</a>
5+
* @since 04.05.18
6+
*/
7+
public interface CompositeContextBuilder {
8+
CompositeContextBuilder addContext(MappingContext... mappingContexts);
9+
CompositeContext build();
10+
}

0 commit comments

Comments
 (0)