From 624cee48fcd92b27466e4fce9545fb9009a7ffd8 Mon Sep 17 00:00:00 2001 From: Shihyu Ho Date: Thu, 24 Mar 2022 17:17:31 +0800 Subject: [PATCH] feat: add bag to conetxt --- .../softleader/data/jpa/spec/SpecContext.java | 41 +++++++------- .../data/jpa/spec/SpecJoinContext.java | 53 +++++++++++++++++++ .../data/jpa/spec/domain/Context.java | 10 ++-- .../softleader/data/jpa/spec/domain/Join.java | 6 +-- .../data/jpa/spec/domain/JoinContext.java | 38 +++++++++++++ .../jpa/spec/domain/SimpleSpecification.java | 2 +- .../data/jpa/spec/ArchitectureCheckTest.java | 2 +- .../data/jpa/spec/IntegrationTest.java | 19 +++++-- 8 files changed, 139 insertions(+), 32 deletions(-) create mode 100644 mapper/src/main/java/tw/com/softleader/data/jpa/spec/SpecJoinContext.java create mode 100644 mapper/src/main/java/tw/com/softleader/data/jpa/spec/domain/JoinContext.java diff --git a/mapper/src/main/java/tw/com/softleader/data/jpa/spec/SpecContext.java b/mapper/src/main/java/tw/com/softleader/data/jpa/spec/SpecContext.java index 782fd3c..f7501ae 100644 --- a/mapper/src/main/java/tw/com/softleader/data/jpa/spec/SpecContext.java +++ b/mapper/src/main/java/tw/com/softleader/data/jpa/spec/SpecContext.java @@ -20,34 +20,37 @@ */ package tw.com.softleader.data.jpa.spec; +import static java.util.Optional.ofNullable; + import java.util.HashMap; import java.util.Map; -import java.util.function.Function; -import javax.persistence.criteria.Join; -import javax.persistence.criteria.Root; -import lombok.Synchronized; -import lombok.val; -import org.springframework.data.util.Pair; +import java.util.Optional; +import lombok.NonNull; import tw.com.softleader.data.jpa.spec.domain.Context; +import tw.com.softleader.data.jpa.spec.domain.JoinContext; class SpecContext implements Context { - private final Map>, javax.persistence.criteria.Join> joins = new HashMap<>(); - private final Map, Join>> lazyJoins = new HashMap<>(); + private final Map bag = new HashMap<>(); + private final JoinContext join = new SpecJoinContext(); + + @Override + public JoinContext join() { + return join; + } + + @Override + public Optional get(@NonNull String key) { + return ofNullable(bag.get(key)); + } @Override - @Synchronized - public Join getJoin(String key, Root root) { - val lazyJoin = lazyJoins.get(key); - if (lazyJoin == null) { - return null; - } - Pair> rootKey = Pair.of(key, root); - joins.computeIfAbsent(rootKey, k -> lazyJoin.apply(root)); - return joins.get(rootKey); + public Object put(@NonNull String key, @NonNull Object value) { + return bag.put(key, value); } - public void putLazyJoin(String key, Function, Join> lazyJoin) { - lazyJoins.put(key, lazyJoin); + @Override + public Object remove(@NonNull String key) { + return bag.remove(key); } } diff --git a/mapper/src/main/java/tw/com/softleader/data/jpa/spec/SpecJoinContext.java b/mapper/src/main/java/tw/com/softleader/data/jpa/spec/SpecJoinContext.java new file mode 100644 index 0000000..4d6c50c --- /dev/null +++ b/mapper/src/main/java/tw/com/softleader/data/jpa/spec/SpecJoinContext.java @@ -0,0 +1,53 @@ +/* + * Copyright © 2022 SoftLeader + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package tw.com.softleader.data.jpa.spec; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; +import javax.persistence.criteria.Join; +import javax.persistence.criteria.Root; +import lombok.Synchronized; +import lombok.val; +import org.springframework.data.util.Pair; +import tw.com.softleader.data.jpa.spec.domain.JoinContext; + +class SpecJoinContext implements JoinContext { + + private final Map>, Join> joins = new HashMap<>(); + private final Map, Join>> lazyJoins = new HashMap<>(); + + @Override + @Synchronized + public Join get(String key, Root root) { + val lazyJoin = lazyJoins.get(key); + if (lazyJoin == null) { + return null; + } + Pair> rootKey = Pair.of(key, root); + joins.computeIfAbsent(rootKey, k -> lazyJoin.apply(root)); + return joins.get(rootKey); + } + + public void putLazy(String key, Function, Join> lazyJoin) { + lazyJoins.put(key, lazyJoin); + } +} diff --git a/mapper/src/main/java/tw/com/softleader/data/jpa/spec/domain/Context.java b/mapper/src/main/java/tw/com/softleader/data/jpa/spec/domain/Context.java index 0a83696..05c0740 100644 --- a/mapper/src/main/java/tw/com/softleader/data/jpa/spec/domain/Context.java +++ b/mapper/src/main/java/tw/com/softleader/data/jpa/spec/domain/Context.java @@ -20,6 +20,7 @@ */ package tw.com.softleader.data.jpa.spec.domain; +import java.util.Optional; import java.util.function.Function; import javax.persistence.criteria.Join; import javax.persistence.criteria.Root; @@ -31,8 +32,11 @@ */ public interface Context { - @SuppressWarnings({ "rawtypes" }) - Join getJoin(String key, Root root); + JoinContext join(); - void putLazyJoin(String key, Function, Join> function); + Optional get(String key); + + Object put(String key, Object value); + + Object remove(String key); } diff --git a/mapper/src/main/java/tw/com/softleader/data/jpa/spec/domain/Join.java b/mapper/src/main/java/tw/com/softleader/data/jpa/spec/domain/Join.java index 4e43ec8..97aa100 100644 --- a/mapper/src/main/java/tw/com/softleader/data/jpa/spec/domain/Join.java +++ b/mapper/src/main/java/tw/com/softleader/data/jpa/spec/domain/Join.java @@ -59,13 +59,13 @@ public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuild private void join(Root root) { if (!pathToJoinOn.contains(".")) { - context.putLazyJoin(alias, r -> r.join(pathToJoinOn, joinType)); + context.join().putLazy(alias, r -> r.join(pathToJoinOn, joinType)); return; } val byDot = pathToJoinOn.split("\\."); val extractedAlias = byDot[0]; - val joined = context.getJoin(extractedAlias, root); + val joined = context.join().get(extractedAlias, root); if (joined == null) { throw new IllegalArgumentException( "Join definition with alias: '" + extractedAlias + "' not found! " + @@ -74,6 +74,6 @@ private void join(Root root) { } val extractedPathToJoin = byDot[1]; - context.putLazyJoin(alias, r -> joined.join(extractedPathToJoin, joinType)); + context.join().putLazy(alias, r -> joined.join(extractedPathToJoin, joinType)); } } diff --git a/mapper/src/main/java/tw/com/softleader/data/jpa/spec/domain/JoinContext.java b/mapper/src/main/java/tw/com/softleader/data/jpa/spec/domain/JoinContext.java new file mode 100644 index 0000000..ba5e93c --- /dev/null +++ b/mapper/src/main/java/tw/com/softleader/data/jpa/spec/domain/JoinContext.java @@ -0,0 +1,38 @@ +/* + * Copyright © 2022 SoftLeader + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package tw.com.softleader.data.jpa.spec.domain; + +import java.util.function.Function; +import javax.persistence.criteria.Join; +import javax.persistence.criteria.Root; + +/** + * Share data between specifications + * + * @author Matt Ho + */ +public interface JoinContext { + + @SuppressWarnings({ "rawtypes" }) + Join get(String key, Root root); + + void putLazy(String key, Function, Join> function); +} diff --git a/mapper/src/main/java/tw/com/softleader/data/jpa/spec/domain/SimpleSpecification.java b/mapper/src/main/java/tw/com/softleader/data/jpa/spec/domain/SimpleSpecification.java index f45da11..4ae1a79 100644 --- a/mapper/src/main/java/tw/com/softleader/data/jpa/spec/domain/SimpleSpecification.java +++ b/mapper/src/main/java/tw/com/softleader/data/jpa/spec/domain/SimpleSpecification.java @@ -69,7 +69,7 @@ protected Path getPath(Root root) { Path expr = null; for (String field : split) { if (expr == null) { - expr = ofNullable(context.getJoin(field, root)) + expr = ofNullable(context.join().get(field, root)) .map(joined -> (Path) joined) .orElseGet(() -> root.get(field)); continue; diff --git a/mapper/src/test/java/tw/com/softleader/data/jpa/spec/ArchitectureCheckTest.java b/mapper/src/test/java/tw/com/softleader/data/jpa/spec/ArchitectureCheckTest.java index daaecaf..939117c 100644 --- a/mapper/src/test/java/tw/com/softleader/data/jpa/spec/ArchitectureCheckTest.java +++ b/mapper/src/test/java/tw/com/softleader/data/jpa/spec/ArchitectureCheckTest.java @@ -96,7 +96,7 @@ static class GeneralCodingRules { static final ArchRule noClassesShouldThrowGenericExceptions = NO_CLASSES_SHOULD_THROW_GENERIC_EXCEPTIONS; @ArchTest - static final ArchRule noClassesShouldUseJodatime = NO_CLASSES_SHOULD_USE_JODATIME; + static final ArchRule noClassesShouldUseJodaTime = NO_CLASSES_SHOULD_USE_JODATIME; @ArchTest static final ArchRule noClassesShouldUseFieldInjection = NO_CLASSES_SHOULD_USE_FIELD_INJECTION; diff --git a/mapper/src/test/java/tw/com/softleader/data/jpa/spec/IntegrationTest.java b/mapper/src/test/java/tw/com/softleader/data/jpa/spec/IntegrationTest.java index 13e6c0c..22f44fc 100644 --- a/mapper/src/test/java/tw/com/softleader/data/jpa/spec/IntegrationTest.java +++ b/mapper/src/test/java/tw/com/softleader/data/jpa/spec/IntegrationTest.java @@ -26,13 +26,12 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import java.util.function.Function; -import javax.persistence.criteria.Join; -import javax.persistence.criteria.Root; +import java.util.Optional; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import tw.com.softleader.data.jpa.spec.domain.Context; +import tw.com.softleader.data.jpa.spec.domain.JoinContext; /** * Integration test with Spring Boot Data JPA @@ -57,12 +56,22 @@ class TestApplication { public static Context noopContext() { return new Context() { @Override - public Join getJoin(String key, Root root) { + public JoinContext join() { throw new UnsupportedOperationException(); } @Override - public void putLazyJoin(String key, Function, Join> function) { + public Optional get(String key) { + throw new UnsupportedOperationException(); + } + + @Override + public Object put(String key, Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public Object remove(String key) { throw new UnsupportedOperationException(); } };