/** * @return the first resolved value instance of {@code type}. * If not found returns {@link Maybe#absent()} either due to * the end reached or a resolve error. To check if there was a * resolve error call {@code peek().isAbsent()}. */ public <S> Maybe<S> next(Class<S> type) { while (hasNext()) { Maybe<Object> item = next(); if (item.isAbsent() || type.isInstance(item.get())) { @SuppressWarnings("unchecked") Maybe<S> typedItem = (Maybe<S>) item; return typedItem; } } return Maybe.absent("Did not find items of type " + type + " in " + resolver); }
ValueResolverIterator<Integer> iter = resolver.iterator(); assertTrue(iter.hasNext(), "expected o1"); Maybe<Object> o1Actual = iter.next(); assertEquals(o1Actual.get(), o1Expected); assertEquals(o1Actual, iter.peek()); assertTrue(iter.hasNext()); Maybe<Object> o2Actual = iter.next(); assertEquals(o2Actual.get(), o2Expected); assertEquals(o2Actual, iter.peek()); assertTrue(iter.hasNext()); Maybe<Object> o3Actual = iter.next(); assertEquals(o3Actual.get(), o3Expected); assertEquals(o3Actual, iter.peek()); iter.next(); Asserts.shouldHaveFailedPreviously("no more elements in iterator"); } catch (NoSuchElementException e) {
@Test(dataProvider="resolveTypes") public void testNull(ResolveType resolveType) { ValueResolver<Void> resolver = Tasks.resolving(null) .as(Void.class) .context(app) .immediately(resolveType.isImmediate()); assertNull(resolver.get()); ValueResolverIterator<Void> iter = resolver.iterator(); assertTrue(iter.hasNext()); assertNull(iter.next().get()); assertFalse(iter.hasNext()); Maybe<Object> voidOrLast = resolver.iterator().nextOrLast(Void.class); assertNull(voidOrLast.get()); Maybe<Void> voidItem = resolver.iterator().next(Void.class); assertTrue(voidItem.isAbsent()); Maybe<Void> lastItem = resolver.iterator().last(); assertNull(lastItem.get()); }
/** * @return the first resolved value satisfying the {@code stopCondition}. * If none is found return the last element. */ public Maybe<Object> nextOrLast(Predicate<Object> stopCondition) { if (!hasNext()) { return prev; } Maybe<Object> item; do { item = next(); if (item.isAbsent() || stopCondition.apply(item.get())) { return item; } } while (hasNext()); return item; }
ValueResolverIterator<Object> iter = resolver.iterator(); assertTrue(iter.hasNext(), "expected wrapper"); Maybe<Object> wrapperActual = iter.next(); assertEquals(wrapperActual.get(), wrapperExpected); assertEquals(wrapperActual, iter.peek()); assertTrue(iter.hasNext()); Maybe<Object> failingActual = iter.next(); assertEquals(failingActual.get(), failingExpected); assertEquals(failingActual, iter.peek()); assertTrue(iter.hasNext()); Maybe<Object> absent = iter.next(); assertTrue(absent.isAbsent()); iter.next(); Asserts.shouldHaveFailedPreviously("no more elements in iterator"); } catch (NoSuchElementException e) {
/** * @return the last element of the iterator reached either because * resolving no longer possible or there was a resolve error. */ @SuppressWarnings("unchecked") public Maybe<T> last() { Maybe<Object> last = peek(); while (hasNext()) { last = next(); if (last.isAbsent()) { return (Maybe<T>) last; } } return coerceValue(last, resolver.getType()); }
private static ReleaseableLatch waitForLatch(EntityInternal entity, ConfigKey<Boolean> configKey) { Maybe<?> rawValue = entity.config().getRaw(configKey); if (rawValue.isAbsent()) { return ReleaseableLatch.NOP; } else { ValueResolverIterator<Boolean> iter = resolveLatchIterator(entity, rawValue.get(), configKey); // The iterator is used to prevent coercion; the value should always be the last one, but iter.last() will return a coerced Boolean Maybe<ReleaseableLatch> releasableLatchMaybe = iter.next(ReleaseableLatch.class); if (releasableLatchMaybe.isPresent()) { ReleaseableLatch latch = releasableLatchMaybe.get(); log.debug("{} finished waiting for {} (value {}); waiting to acquire the latch", new Object[] {entity, configKey, latch}); Tasks.setBlockingDetails("Acquiring " + configKey + " " + latch); try { latch.acquire(entity); } finally { Tasks.resetBlockingDetails(); } log.debug("{} Acquired latch {} (value {}); continuing...", new Object[] {entity, configKey, latch}); return latch; } else { // If iter.next() above returned absent due to a resolve error next line will throw with the cause Boolean val = iter.last().get(); if (rawValue != null) log.debug("{} finished waiting for {} (value {}); continuing...", new Object[] {entity, configKey, val}); return ReleaseableLatch.NOP; } } }
@Test(dataProvider="resolveTypes") public void testNextTypeNotFound(ResolveType resolveType) { FailingImmediateAndDeferredSupplier failingExpected = new FailingImmediateAndDeferredSupplier(); WrappingImmediateAndDeferredSupplier wrapperExpected = new WrappingImmediateAndDeferredSupplier(failingExpected); ValueResolver<Object> resolver = Tasks.resolving(wrapperExpected) .as(Object.class) .context(app) .immediately(resolveType.isImmediate()); ValueResolverIterator<Object> iter = resolver.iterator(); Maybe<Void> actual = iter.next(Void.class); assertFalse(actual.isPresent()); assertEquals(actual, iter.last()); } }
@Test(dataProvider="resolveTypes") public void testNextTypeFound(ResolveType resolveType) { FailingImmediateAndDeferredSupplier failingExpected = new FailingImmediateAndDeferredSupplier(); WrappingImmediateAndDeferredSupplier wrapperExpected = new WrappingImmediateAndDeferredSupplier(failingExpected); ValueResolver<Object> resolver = Tasks.resolving(wrapperExpected) .as(Object.class) .context(app) .immediately(resolveType.isImmediate()); ValueResolverIterator<Object> iter = resolver.iterator(); Maybe<FailingImmediateAndDeferredSupplier> actual = iter.next(FailingImmediateAndDeferredSupplier.class); assertTrue(actual.isPresent()); assertNotEquals(actual, iter.last()); }