This is an automated email from the ASF dual-hosted git repository. ahuber pushed a commit to branch v3 in repository https://gitbox.apache.org/repos/asf/causeway.git
The following commit(s) were added to refs/heads/v3 by this push: new 9323a558dc7 CAUSEWAY-2297: flattens SpecificationCache 9323a558dc7 is described below commit 9323a558dc7376d5f6a0e7044c529a05263eed39 Author: Andi Huber <ahu...@apache.org> AuthorDate: Tue Nov 12 15:40:59 2024 +0100 CAUSEWAY-2297: flattens SpecificationCache --- .../metamodel/specloader/SpecificationCache.java | 83 ++++++++++++-- .../specloader/SpecificationCacheDefault.java | 119 --------------------- .../specloader/SpecificationLoaderDefault.java | 2 +- .../core/metamodel/specloader/_LogUtil.java | 4 +- .../specloader/SpecificationCacheDefaultTest.java | 6 +- 5 files changed, 78 insertions(+), 136 deletions(-) diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationCache.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationCache.java index 5eeae8ee83d..8ab9ea40cb4 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationCache.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationCache.java @@ -18,27 +18,90 @@ */ package org.apache.causeway.core.metamodel.specloader; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; +import org.springframework.lang.Nullable; + import org.apache.causeway.commons.collections.Can; +import org.apache.causeway.commons.internal.collections.snapshot._VersionedList; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; -interface SpecificationCache<T extends ObjectSpecification> { +import lombok.NonNull; + +record SpecificationCache( + Map<Class<?>, ObjectSpecification> specByClass, + // optimization: specialized list to keep track of any additions to the cache fast + _VersionedList<ObjectSpecification> vList) { + + SpecificationCache() { + this(new HashMap<>(), new _VersionedList<>()); + } + + Optional<ObjectSpecification> lookup(final Class<?> cls) { + synchronized(this) { + return Optional.ofNullable(specByClass.get(cls)); + } + } + + ObjectSpecification computeIfAbsent( + final Class<?> cls, + final Function<Class<?>, ObjectSpecification> mappingFunction) { + synchronized(this) { + var spec = specByClass.get(cls); + if(spec==null) { + spec = mappingFunction.apply(cls); + internalPut(spec); + } + return spec; + } + } + + void clear() { + synchronized(this) { + specByClass.clear(); + vList.clear(); + } + } + + Can<ObjectSpecification> snapshotSpecs() { + synchronized(this) { + return Can.ofCollection(specByClass.values()); + } + } - Optional<T> lookup(Class<?> cls); + ObjectSpecification remove(@NonNull final Class<?> cls) { + synchronized(this) { + var removed = specByClass.remove(cls); + if(removed!=null) { + vList.clear(); // invalidate + vList.addAll(specByClass.values()); + } + return removed; + } + } - T computeIfAbsent(Class<?> cls, Function<Class<?>, T> mappingFunction); + void forEachConcurrent(final Consumer<ObjectSpecification> onSpec) { + vList.forEachConcurrent(onSpec); + } - T remove(Class<?> cls); + void forEach(final Consumer<ObjectSpecification> onSpec) { + vList.forEach(onSpec); + } - void clear(); + // -- HELPER - /** @returns thread-safe defensive copy */ - Can<T> snapshotSpecs(); + private void internalPut(@Nullable final ObjectSpecification spec) { + if(spec==null) return; - void forEach(Consumer<T> onSpec); - void forEachConcurrent(Consumer<T> onSpec); + var cls = spec.getCorrespondingClass(); + var existing = specByClass.put(cls, spec); + if(existing==null) { + vList.add(spec); // add to vList only if we don't have it already + } + } -} \ No newline at end of file +} diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationCacheDefault.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationCacheDefault.java deleted file mode 100644 index b5d0af88931..00000000000 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationCacheDefault.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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 org.apache.causeway.core.metamodel.specloader; - -import java.util.Map; -import java.util.Optional; -import java.util.function.Consumer; -import java.util.function.Function; - -import org.springframework.lang.Nullable; - -import org.apache.causeway.commons.collections.Can; -import org.apache.causeway.commons.internal.collections._Maps; -import org.apache.causeway.commons.internal.collections.snapshot._VersionedList; -import org.apache.causeway.core.metamodel.spec.ObjectSpecification; - -import lombok.NonNull; - -class SpecificationCacheDefault<T extends ObjectSpecification> implements SpecificationCache<T> { - - private final Map<Class<?>, T> specByClass = _Maps.newHashMap(); - - // optimization: specialized list to keep track of any additions to the cache fast - private final _VersionedList<T> vList = new _VersionedList<>(); - - @Override - public Optional<T> lookup(final Class<?> cls) { - synchronized(this) { - return Optional.ofNullable(specByClass.get(cls)); - } - } - - @Override - public T computeIfAbsent( - final Class<?> cls, - final Function<Class<?>, T> mappingFunction) { - synchronized(this) { - T spec = specByClass.get(cls); - if(spec==null) { - spec = mappingFunction.apply(cls); - internalPut(spec); - -//debug -// if(cls.getSimpleName().equals("MarkupStream")) { -// System.out.println("!!! MarkupStream"); -// } - - } - return spec; - } - } - - @Override - public void clear() { - synchronized(this) { - specByClass.clear(); - vList.clear(); - } - } - - @Override - public Can<T> snapshotSpecs() { - synchronized(this) { - return Can.ofCollection(specByClass.values()); - } - } - - @Override - public T remove(@NonNull final Class<?> cls) { - synchronized(this) { - final T removed = specByClass.remove(cls); - if(removed!=null) { - vList.clear(); // invalidate - vList.addAll(specByClass.values()); - } - return removed; - } - } - - @Override - public void forEachConcurrent(final Consumer<T> onSpec) { - vList.forEachConcurrent(onSpec); - } - - @Override - public void forEach(final Consumer<T> onSpec) { - vList.forEach(onSpec); - } - - // -- HELPER - - private void internalPut(@Nullable final T spec) { - if(spec==null) { - return; - } - var cls = spec.getCorrespondingClass(); - var existing = specByClass.put(cls, spec); - if(existing==null) { - vList.add(spec); // add to vList only if we don't have it already - } - } - -} diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationLoaderDefault.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationLoaderDefault.java index a25ffd0b9dc..8628af0ff64 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationLoaderDefault.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationLoaderDefault.java @@ -132,7 +132,7 @@ implements private FacetProcessor facetProcessor; - private final SpecificationCache<ObjectSpecification> cache = new SpecificationCacheDefault<>(); + private final SpecificationCache cache = new SpecificationCache(); private final LogicalTypeResolver logicalTypeResolver = new LogicalTypeResolverDefault(); /** diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/_LogUtil.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/_LogUtil.java index d2c1f319421..041a2df6025 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/_LogUtil.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/_LogUtil.java @@ -33,7 +33,7 @@ final class _LogUtil { void logBefore( final Logger log, - final SpecificationCache<ObjectSpecification> cache, + final SpecificationCache cache, final List<? extends ObjectSpecification> scanned) { if(!log.isDebugEnabled()) { @@ -60,7 +60,7 @@ final class _LogUtil { void logAfter( final Logger log, - final SpecificationCache<ObjectSpecification> cache, + final SpecificationCache cache, final Collection<? extends ObjectSpecification> scanned) { if(!log.isDebugEnabled()) { diff --git a/core/metamodel/src/test/java/org/apache/causeway/core/metamodel/specloader/SpecificationCacheDefaultTest.java b/core/metamodel/src/test/java/org/apache/causeway/core/metamodel/specloader/SpecificationCacheDefaultTest.java index 94239580925..970e7bfe0a5 100644 --- a/core/metamodel/src/test/java/org/apache/causeway/core/metamodel/specloader/SpecificationCacheDefaultTest.java +++ b/core/metamodel/src/test/java/org/apache/causeway/core/metamodel/specloader/SpecificationCacheDefaultTest.java @@ -39,10 +39,8 @@ class SpecificationCacheDefaultTest { ObjectSpecification customerSpec; ObjectSpecification orderSpec; - private SpecificationCache<ObjectSpecification> specificationCache = - new SpecificationCacheDefault<>(); - private LogicalTypeResolver logicalTypeResolver = - new LogicalTypeResolverDefault(); + private SpecificationCache specificationCache = new SpecificationCache(); + private LogicalTypeResolver logicalTypeResolver = new LogicalTypeResolverDefault(); @SuppressWarnings({ "unchecked", "rawtypes" }) @BeforeEach