From 00c520a3a75f2091f1d2382b4e99aaa698137f52 Mon Sep 17 00:00:00 2001 From: Simon Chemouil Date: Mon, 16 Oct 2017 18:02:42 +0200 Subject: [PATCH] Issue #2: ADTMirror: a Service + SPI to do ADT reflexion --- pom.xml | 66 +++++-------------- .../primeval/reflex/service/adt/ADTInfo.java | 13 ++++ .../reflex/service/adt/ADTMirror.java | 10 +++ .../service/adt/internal/ADTMirrorImpl.java | 61 +++++++++++++++++ .../reflex/service/adt/package-info.java | 5 ++ .../service/adt/spi/ADTMirrorProvider.java | 12 ++++ .../reflex/service/adt/spi/package-info.java | 5 ++ 7 files changed, 121 insertions(+), 51 deletions(-) create mode 100644 src/main/java/io/primeval/reflex/service/adt/ADTInfo.java create mode 100644 src/main/java/io/primeval/reflex/service/adt/ADTMirror.java create mode 100644 src/main/java/io/primeval/reflex/service/adt/internal/ADTMirrorImpl.java create mode 100644 src/main/java/io/primeval/reflex/service/adt/package-info.java create mode 100644 src/main/java/io/primeval/reflex/service/adt/spi/ADTMirrorProvider.java create mode 100644 src/main/java/io/primeval/reflex/service/adt/spi/package-info.java diff --git a/pom.xml b/pom.xml index e28d31c..fa333af 100644 --- a/pom.xml +++ b/pom.xml @@ -27,6 +27,11 @@ provided + + org.osgi + osgi.cmpn + 6.0.0 + org.slf4j @@ -35,13 +40,12 @@ provided - org.ow2.asm asm 5.2 - + junit @@ -63,56 +67,16 @@ - - - - biz.aQute.bnd - bnd-maven-plugin - - - - - - release - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.10.3 - - - generate-javadoc - package - - jar - - false - - - - true - false - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - attach-sources - - jar-no-fork - - - - - - - - + + + + biz.aQute.bnd + bnd-maven-plugin + + + + diff --git a/src/main/java/io/primeval/reflex/service/adt/ADTInfo.java b/src/main/java/io/primeval/reflex/service/adt/ADTInfo.java new file mode 100644 index 0000000..c3b410f --- /dev/null +++ b/src/main/java/io/primeval/reflex/service/adt/ADTInfo.java @@ -0,0 +1,13 @@ +package io.primeval.reflex.service.adt; + +public abstract class ADTInfo { + + public abstract Class rootType(); + + public abstract String typeName(Class clazz); + + public abstract Class classFor(String typeName); + + public abstract String selectorName(); + +} diff --git a/src/main/java/io/primeval/reflex/service/adt/ADTMirror.java b/src/main/java/io/primeval/reflex/service/adt/ADTMirror.java new file mode 100644 index 0000000..8d5b8d2 --- /dev/null +++ b/src/main/java/io/primeval/reflex/service/adt/ADTMirror.java @@ -0,0 +1,10 @@ +package io.primeval.reflex.service.adt; + +import java.util.Optional; + +public interface ADTMirror { + + Optional getInfo(Class raw); + + +} diff --git a/src/main/java/io/primeval/reflex/service/adt/internal/ADTMirrorImpl.java b/src/main/java/io/primeval/reflex/service/adt/internal/ADTMirrorImpl.java new file mode 100644 index 0000000..620b909 --- /dev/null +++ b/src/main/java/io/primeval/reflex/service/adt/internal/ADTMirrorImpl.java @@ -0,0 +1,61 @@ +package io.primeval.reflex.service.adt.internal; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.osgi.service.component.annotations.ReferencePolicyOption; + +import io.primeval.reflex.service.adt.ADTInfo; +import io.primeval.reflex.service.adt.ADTMirror; +import io.primeval.reflex.service.adt.spi.ADTMirrorProvider; + +@Component(immediate = true) +public final class ADTMirrorImpl implements ADTMirror { + + public final List providers = new CopyOnWriteArrayList<>(); + + // Switch to evicting cache... need primeval-cache :-) + // Cache only ADTTypes, and make ADT checking fast! + private final Map, ADTInfo> adtCache = new ConcurrentHashMap<>(); + + // A bloomfilter-like structure would be neat to keep failed ADT-checks without using too much mem + + // Right now excluding java.* types, should make this configurable? + + @Override + public Optional getInfo(Class raw) { + if (raw.getName().startsWith("java.")) { + return Optional.empty(); + } + return Optional.ofNullable(adtCache.computeIfAbsent(raw, k -> computeADTInfo(k))); + } + + private ADTInfo computeADTInfo(Class raw) { + for (ADTMirrorProvider prov : providers) { + if (prov.isADT(raw)) { + ADTInfo info = computeADTInfoForProvider(prov, raw); + return info; + } + } + return null; + } + + private ADTInfo computeADTInfoForProvider(ADTMirrorProvider prov, Class raw) { + return prov.getInfo(raw, + k -> adtCache.computeIfAbsent(k, k2 -> computeADTInfoForProvider(prov, k2))); + } + + // Static policy to invalidate cache when a new provider joins! + @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.STATIC, policyOption = ReferencePolicyOption.GREEDY) + public void addADTMirrorProvider(ADTMirrorProvider adtMirrorProvider) { + providers.add(adtMirrorProvider); + } + +} diff --git a/src/main/java/io/primeval/reflex/service/adt/package-info.java b/src/main/java/io/primeval/reflex/service/adt/package-info.java new file mode 100644 index 0000000..d7c00b0 --- /dev/null +++ b/src/main/java/io/primeval/reflex/service/adt/package-info.java @@ -0,0 +1,5 @@ +@Version("1.0") +package io.primeval.reflex.service.adt; + +import org.osgi.annotation.versioning.Version; + diff --git a/src/main/java/io/primeval/reflex/service/adt/spi/ADTMirrorProvider.java b/src/main/java/io/primeval/reflex/service/adt/spi/ADTMirrorProvider.java new file mode 100644 index 0000000..b7a82d3 --- /dev/null +++ b/src/main/java/io/primeval/reflex/service/adt/spi/ADTMirrorProvider.java @@ -0,0 +1,12 @@ +package io.primeval.reflex.service.adt.spi; + +import java.util.function.Function; + +import io.primeval.reflex.service.adt.ADTInfo; + +public interface ADTMirrorProvider { + + ADTInfo getInfo(Class raw, Function, ADTInfo> callback); + + boolean isADT(Class raw); +} diff --git a/src/main/java/io/primeval/reflex/service/adt/spi/package-info.java b/src/main/java/io/primeval/reflex/service/adt/spi/package-info.java new file mode 100644 index 0000000..8eb2ffe --- /dev/null +++ b/src/main/java/io/primeval/reflex/service/adt/spi/package-info.java @@ -0,0 +1,5 @@ +@Version("1.0") +package io.primeval.reflex.service.adt.spi; + +import org.osgi.annotation.versioning.Version; +