> pseudoScope = Map.of("normal", BooleanValue.of(false));
-
/**
* An {@link Attributes} identifying the (well-known) singleton pseudo-scope.
*
@@ -104,11 +93,6 @@ public abstract class Scopelet> implements AutoCloseable,
Attributes.of("None", pseudoScope, Map.of(), Map.of("None", List.of(qualifier(), SCOPE, SINGLETON_ID)));
- //
- // End experimental
- //
-
-
/*
* Instance fields.
*/
@@ -118,8 +102,6 @@ public abstract class Scopelet> implements AutoCloseable,
private volatile boolean closed;
- private final Attributes scopeId;
-
/*
* Constructors.
@@ -128,14 +110,9 @@ public abstract class Scopelet> implements AutoCloseable,
/**
* Creates a new {@link Scopelet}.
- *
- * @param scopeId an {@link Attributes} identifying the scope being implemented; must not be {@code null}
- *
- * @exception NullPointerException if {@code scopeId} is {@code null}
*/
- protected Scopelet(final Attributes scopeId) {
+ protected Scopelet() {
super();
- this.scopeId = Objects.requireNonNull(scopeId, "scopeId");
}
@@ -144,32 +121,6 @@ protected Scopelet(final Attributes scopeId) {
*/
- /**
- * Returns an {@link Id} representing this {@link Scopelet}.
- *
- * Implementations of this method must return determinate values.
- *
- * @return an {@link Id} representing this {@link Scopelet}; never {@code null}
- *
- * @see #bean()
- */
- public abstract Id id();
-
- /**
- * A convenience method that eturns a {@link Bean} for this {@link Scopelet}.
- *
- * This {@link Scopelet} will be used as the {@link Bean}'s {@linkplain Bean#factory() associated
- * Factory}. This {@link Scopelet}'s {@link #id() Id} will be used as the {@link Bean}'s {@linkplain
- * Bean#id() identifier}.
- *
- * @return a {@link Bean} for this {@link Scopelet}; never {@code null}
- *
- * @see #id()
- */
- public final Bean bean() {
- return new Bean<>(this.id(), this);
- }
-
/**
* Creates this {@link Scopelet} by simply returning it.
*
@@ -214,61 +165,12 @@ public final boolean destroys() {
return true;
}
- /**
- * Returns a hashcode for this {@link Scopelet}.
- *
- * @return a hashcode for this {@link Scopelet}
- */
- @Override // Object
- public int hashCode() {
- int hashCode = 17;
- hashCode = 31 * hashCode + this.id().hashCode();
- hashCode = 31 * hashCode + this.scopeId().hashCode();
- return hashCode;
- }
-
- /**
- * Returns {@code true} if and only if the supplied {@link Object} is not {@code null}, has the same class as this
- * {@link Scopelet}, has an {@link #id() Id} {@linkplain Id#equals(Object) equal to} that of this {@link Scopelet},
- * and a {@linkplain #scopeId() scope identifier} {@linkplain Attributes#equals(Object) equal to} that of this
- * {@link Scopelet}.
- *
- * @param other the {@link Object} to test; may be {@code null}
- *
- * @return {@code true} if and only if the supplied {@link Object} is not {@code null}, has the same class as this
- * {@link Scopelet}, has an {@link #id() Id} {@linkplain Id#equals(Object) equal to} that of this {@link Scopelet},
- * and a {@linkplain #scopeId() scope identifier} {@linkplain Attributes#equals(Object) equal to} that of this
- * {@link Scopelet}
- */
- @Override // Object
- public boolean equals(final Object other) {
- if (other == this) {
- return true;
- } else if (other != null && other.getClass().equals(this.getClass())) {
- final Scopelet> her = (Scopelet>)other;
- return
- Objects.equals(this.id(), her.id()) &&
- Objects.equals(this.scopeId(), her.scopeId());
- } else {
- return false;
- }
- }
-
/*
* Repository-like concerns.
*/
- /**
- * Returns the {@link Attributes} that identifies this {@link Scopelet}'s affiliated scope.
- *
- * @return the {@link Attributes} that identifies this {@link Scopelet}'s affiliated scope; never {@code null}
- */
- public final Attributes scopeId() {
- return this.scopeId;
- }
-
/**
* Returns {@code true} if and only if this {@link Scopelet} is active at the moment of the call.
*
@@ -305,6 +207,7 @@ public boolean active() {
*
* @see #instance(Object, Factory, Request)
*/
+ // @Deprecated // This method is not actually used but would need to exist for design flaws in CDI
public boolean containsId(final Object id) {
return (id instanceof Request> r ? this.instance(r) : this.instance(id, null, null)) != null;
}
@@ -359,8 +262,8 @@ public final I get(final Object id) {
* @see #instance(Object, Factory, Request)
*/
public final I instance(final Request request) {
- if (request == null) {
- return this.instance(null, null, null);
+ if (request == null || request.primordial()) {
+ return this.instance(null, null, request);
}
final Bean bean = request.beanReduction().bean();
return this.instance(bean.id(), bean.factory(), request);
@@ -391,8 +294,8 @@ public final I instance(final Request request) {
* Checks to see if this {@link Scopelet} {@linkplain #active() is active} and then removes any contextual instance
* stored under the supplied {@code id}, returning {@code true} if and only if removal actually took place.
*
- * The default implementation of this method always returns {@code false}. Subclasses are encouraged to override
- * it as appropriate.
+ * The default implementation of this method always returns {@code false}. Subclasses are
+ * encouraged to override it as appropriate.
*
* @param id an identifier; may be {@code null}
*
@@ -409,8 +312,11 @@ public boolean remove(final Object id) {
}
/**
- * Irrevocably closes this {@link Scopelet}, and, by doing so, notionally makes it irrevocably {@linkplain #active()
- * inactive}.
+ * Irrevocably closes this {@link Scopelet}, and, by doing so, notionally makes it irrevocably {@linkplain #closed()
+ * closed} and {@linkplain #active() inactive}.
+ *
+ * Overrides of this method must call {@link Scopelet#close() super.close()} as part of their implementation or
+ * undefined behavior may result.
*
* @see #closed()
*
@@ -429,6 +335,8 @@ public void close() {
*
* @return {@code true} if and only if at the moment of invocation this {@link Scopelet} is (irrevocably) closed (and
* therefore also {@linkplain #active() not active})
+ *
+ * @see #active()
*/
protected final boolean closed() {
return this.closed; // volatile read
diff --git a/src/main/java/org/microbean/scopelet/SingletonScopelet.java b/src/main/java/org/microbean/scopelet/SingletonScopelet.java
index df1bef9..9831622 100644
--- a/src/main/java/org/microbean/scopelet/SingletonScopelet.java
+++ b/src/main/java/org/microbean/scopelet/SingletonScopelet.java
@@ -19,19 +19,13 @@
import java.lang.constant.DynamicConstantDesc;
import java.lang.constant.MethodHandleDesc;
-import java.util.List;
import java.util.Objects;
import java.util.Optional;
-import org.microbean.bean.BeanTypeList;
-import org.microbean.bean.Id;
-
import org.microbean.construct.Domain;
import static java.lang.constant.ConstantDescs.BSM_INVOKE;
-import static org.microbean.assign.Qualifiers.anyQualifier;
-
/**
* A {@link MapBackedScopelet} implementation that caches singletons.
*
@@ -49,21 +43,10 @@ public class SingletonScopelet extends MapBackedScopelet impl
* @exception NullPointerException if {@code domain} is {@code null}
*/
public SingletonScopelet(final Domain domain) {
- super(SINGLETON_ID); // the scope we implement
+ super();
this.domain = Objects.requireNonNull(domain, "domain");
}
- @Override // Scopelet
- public Id id() {
- return
- new Id(BeanTypeList.of(this.domain,
- List.of(this.domain.declaredType(SingletonScopelet.class.getCanonicalName()),
- this.domain.declaredType(null,
- this.domain.typeElement(Scopelet.class.getCanonicalName()),
- this.domain.declaredType(SingletonScopelet.class.getCanonicalName())))),
- List.of(SINGLETON_ID, anyQualifier())); // qualifiers
- }
-
@Override // Constable
public Optional extends ConstantDesc> describeConstable() {
return (this.domain instanceof Constable c ? c.describeConstable() : Optional.empty())
diff --git a/src/test/java/org/microbean/scopelet/TestScopedInstances.java b/src/test/java/org/microbean/scopelet/TestScopedInstances.java
index 2ea4130..f11b4dd 100644
--- a/src/test/java/org/microbean/scopelet/TestScopedInstances.java
+++ b/src/test/java/org/microbean/scopelet/TestScopedInstances.java
@@ -30,6 +30,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -53,7 +54,7 @@ private TestScopedInstances() {
@BeforeAll
static final void setup() {
d = new DefaultDomain();
- i = new ScopedInstances(d, Selectable.of(), Reducer.ofFailing());
+ i = new ScopedInstances(d);
}
@Test
@@ -78,11 +79,18 @@ final void testIsScope() {
assertEquals(Attributes.of("None", Map.of("normal", BooleanValue.of(false)), Map.of(), Map.of()), i.findScopeId(a.attributes()));
}
+ @Test
+ final void testNoneIsNotPrimordial() {
+ assertSame(NONE_ID, i.findScopeId(List.of(NONE_ID)));
+ assertFalse(NONE_ID.attributes().contains(primordialQualifier()));
+ assertSame(SINGLETON_ID, i.findScopeId(NONE_ID.attributes()));
+ }
+
@Test
final void testSingletonIsPrimordial() {
- final Attributes singletonId = i.findScopeId(List.of(SINGLETON_ID));
- assertSame(SINGLETON_ID, singletonId);
+ assertSame(SINGLETON_ID, i.findScopeId(List.of(SINGLETON_ID)));
assertTrue(SINGLETON_ID.attributes().contains(primordialQualifier()));
+ assertNull(i.findScopeId(SINGLETON_ID.attributes()));
}
}