if (requireUrlIfNotAlreadyPresent) { throw new IllegalStateException("Bundle "+bundleMetadata+" not previously registered, but URL is empty.", Maybe.Absent.getException(installedBundle));
/** Creates an absent whose {@link #get()} throws a {@link RuntimeException} * generated on demand from the given supplier */ public static <T> Maybe<T> absent(final Supplier<? extends RuntimeException> exceptionSupplier) { return new Absent<T>(Preconditions.checkNotNull(exceptionSupplier)); }
public static Maybe<String> regexReplacementImmediately(Object source, Object pattern, Object replacement) { Maybe<?> resolvedSource = resolveImmediately(source); if (resolvedSource.isAbsent()) return Absent.castAbsent(resolvedSource); String resolvedSourceStr = String.valueOf(resolvedSource.get()); Maybe<?> resolvedPattern = resolveImmediately(pattern); if (resolvedPattern.isAbsent()) return Absent.castAbsent(resolvedPattern); String resolvedPatternStr = String.valueOf(resolvedPattern.get()); Maybe<?> resolvedReplacement = resolveImmediately(replacement); if (resolvedReplacement.isAbsent()) return Absent.castAbsent(resolvedReplacement); String resolvedReplacementStr = String.valueOf(resolvedReplacement.get()); String result = new StringFunctions.RegexReplacer(resolvedPatternStr, resolvedReplacementStr).apply(resolvedSourceStr); return Maybe.of(result); }
/** tries to coerce a list; * returns null if it just doesn't apply, a {@link Maybe.Present} if it succeeded, * or {@link Maybe.Absent} with a good exception if it should have applied but couldn't */ @SuppressWarnings("unchecked") protected <T> Maybe<T> tryCoerceIterable(Object value, TypeToken<T> targetTypeToken, Class<? super T> targetType) { if (!(value instanceof Iterable) || !(Iterable.class.isAssignableFrom(targetTypeToken.getRawType()))) return null; Type[] arguments = ((ParameterizedType) targetTypeToken.getType()).getActualTypeArguments(); if (arguments.length != 1) { return Maybe.absent(new IllegalStateException("Unexpected number of parameters in iterable type: " + arguments)); } Collection<Object> coerced = Lists.newLinkedList(); TypeToken<?> listEntryType = TypeToken.of(arguments[0]); int i = 0; for (Object entry : (Iterable<?>) value) { Maybe<?> entryCoerced = tryCoerce(entry, listEntryType); if (entryCoerced.isPresent()) { coerced.add(entryCoerced.get()); } else { return Maybe.absent(new ClassCoercionException( "Could not coerce entry "+i+" in "+value+" to "+targetTypeToken, ((Maybe.Absent<T>)entryCoerced).getException())); } i++; } if (Set.class.isAssignableFrom(targetType)) { return Maybe.of((T) Sets.newLinkedHashSet(coerced)); } else { return Maybe.of((T) Lists.newArrayList(coerced)); } }
@Override @SuppressWarnings("unchecked") public <T> Maybe<T> tryCoerce(Object input, TypeToken<T> targetType) { if (!targetType.isArray()) return null; TypeToken<?> targetComponentType = targetType.getComponentType(); Iterable<?> castInput; if (input.getClass().isArray()) { castInput = Reflections.arrayToList(input); } else if (Iterable.class.isAssignableFrom(input.getClass())) { castInput = (Iterable<?>) input; } else { return null; } Object result = Array.newInstance(targetComponentType.getRawType(), Iterables.size(castInput)); int index = 0; for (Object member : castInput) { Maybe<?> coercedMember = coercer.tryCoerce(member, targetComponentType); if (coercedMember == null || coercedMember.isAbsent()) { RuntimeException cause = Maybe.Absent.getException(coercedMember); return Maybe.absent("Array member at index "+index+" cannot be coerced to "+targetComponentType, cause); } Array.set(result, index++, coercedMember.get()); } return (Maybe<T>) Maybe.of(result); } }
@SuppressWarnings("unchecked") protected <T> Maybe<T> tryCoerceMap(Object value, TypeToken<T> targetTypeToken) { if (!(value instanceof Map) || !(Map.class.isAssignableFrom(targetTypeToken.getRawType()))) return null; Type[] arguments = ((ParameterizedType) targetTypeToken.getType()).getActualTypeArguments(); if (arguments.length != 2) { throw new IllegalStateException("Unexpected number of parameters in map type: " + arguments); } Map<Object,Object> coerced = Maps.newLinkedHashMap(); TypeToken<?> mapKeyType = TypeToken.of(arguments[0]); TypeToken<?> mapValueType = TypeToken.of(arguments[1]); int i=0; for (Map.Entry<?,?> entry : ((Map<?,?>) value).entrySet()) { Maybe<?> k = tryCoerce(entry.getKey(), mapKeyType); if (k.isAbsent()) return Maybe.absent(new ClassCoercionException( "Could not coerce key of entry "+i+" in "+value+" to "+targetTypeToken, ((Maybe.Absent<T>)k).getException())); Maybe<?> v = tryCoerce(entry.getValue(), mapValueType); if (v.isAbsent()) return Maybe.absent(new ClassCoercionException( "Could not coerce value of entry "+i+" in "+value+" to "+targetTypeToken, ((Maybe.Absent<T>)v).getException())); coerced.put(k.get(), v.get()); i++; } return Maybe.of((T) Maps.newLinkedHashMap(coerced)); }
/** * For resolving a "simple" config key - i.e. where there's not custom logic inside a * {@link StructuredConfigKey} such as a {@link MapConfigKey}. For those, we'd need to do the * same as is in {@link #get(ConfigKey)}, but non-blocking! * See {@link #getNonBlockingResolvingStructuredKey(ConfigKey)}. */ protected <T> Maybe<T> getNonBlockingResolvingSimple(ConfigKey<T> key) { // TODO See AbstractConfigMapImpl.getConfigImpl, for how it looks up the "container" of the // key, so that it gets the right context entity etc. // getRaw returns Maybe(val) if the key was explicitly set (where val can be null) // or Absent if the config key was unset. Object unresolved = getRaw(key).or(key.getDefaultValue()); Maybe<Object> resolved = Tasks.resolving(unresolved) .as(Object.class) .immediately(true) .deep(true) .context(getContext()) .getMaybe(); if (resolved.isAbsent()) return Maybe.Absent.<T>castAbsent(resolved); // likely we don't need this coercion if we set as(key.getType()) above, // but that needs confirmation and quite a lot of testing return TypeCoercions.tryCoerce(resolved.get(), key.getTypeToken()); }
protected <T> Maybe<T> changeExceptionSupplier(Maybe<T> result) { return Maybe.Absent.changeExceptionSupplier(result, ClassCoercionException.class); }
public static <T> Maybe<T> newAbsentWithExceptionSupplier() { return Maybe.Absent.changeExceptionSupplier(Maybe.<T>absent(), ImmediateValueNotAvailableException.class); } public static <T> Maybe<T> newAbsentWrapping(String message, Maybe<?> inner) {
/** Finds the {@link Absent#getException()} if {@link #isAbsent()}, or null */ public static RuntimeException getException(Maybe<?> t) { return ((Maybe.Absent<?>)t).getException(); } }
@Override public T orThrowUnwrapped() { throw getException(); } public RuntimeException getException() {
public static <T> Maybe<T> changeExceptionSupplier(Maybe<T> original, final Class<? extends RuntimeException> type) { return changeExceptionSupplier(original, new Function<AnyExceptionSupplier<?>,Supplier<? extends RuntimeException>>() { @SuppressWarnings("unchecked") @Override public Supplier<? extends RuntimeException> apply(AnyExceptionSupplier<?> input) { if (type.isInstance(input)) return (Supplier<? extends RuntimeException>) input; return new AnyExceptionSupplier<RuntimeException>(type, input.getMessageSupplier(), input.getCause()); } }); } public static <T> Maybe<T> changeExceptionSupplier(Maybe<T> original, Function<AnyExceptionSupplier<?>,Supplier<? extends RuntimeException>> transform) {
public static Maybe<Function<String, String>> regexReplacementImmediately(Object pattern, Object replacement) { Maybe<?> resolvedPattern = resolveImmediately(pattern); if (resolvedPattern.isAbsent()) return Absent.castAbsent(resolvedPattern); String resolvedPatternStr = String.valueOf(resolvedPattern.get()); Maybe<?> resolvedReplacement = resolveImmediately(replacement); if (resolvedReplacement.isAbsent()) return Absent.castAbsent(resolvedReplacement); String resolvedReplacementStr = String.valueOf(resolvedReplacement.get()); RegexReplacer result = new StringFunctions.RegexReplacer(resolvedPatternStr, resolvedReplacementStr); return Maybe.<Function<String, String>>of(result); }
public static <T> Maybe<T> changeExceptionSupplier(Maybe<T> original, Function<AnyExceptionSupplier<?>,Supplier<? extends RuntimeException>> transform) { if (original.isPresent()) return original; final Supplier<? extends RuntimeException> supplier = ((Maybe.Absent<?>)original).getExceptionSupplier(); if (!(supplier instanceof AnyExceptionSupplier)) return original; return Maybe.absent(transform.apply((AnyExceptionSupplier<?>)supplier)); } /** Like {@link #cast(Maybe)} but allows any casting because that is valid for absents.
@Override public T get() { throw getException(); } @Override
/** Returns an absent indicator. No message is available and access does not include any reference to this creation. * Therefore it is fast and simple, but hard to work with if someone might {@link #get()} it and want a useful exception. * See also {@link #absentNoTrace(String)} to include a message with very low overhead, * or {@link #absentWithTrace(String)} or {@link #absent(Throwable)} for more control over the exception thrown. */ public static <T> Maybe<T> absent() { return new Maybe.Absent<T>(); }
/** * @throws ImmediateSupplier.ImmediateUnsupportedException if cannot evaluate this in a timely manner */ public static Maybe<String> formatStringImmediately(final String spec, final Object ...args) { List<Object> resolvedArgs = Lists.newArrayList(); for (Object arg : args) { Maybe<?> argVal = resolveImmediately(arg); if (argVal.isAbsent()) return Maybe.Absent.castAbsent(argVal); resolvedArgs.add(argVal.get()); } return Maybe.of(String.format(spec, resolvedArgs.toArray())); }
/** * @throws ImmediateSupplier.ImmediateUnsupportedException if cannot evaluate this in a timely manner */ public static Maybe<String> urlEncodeImmediately(Object arg) { Maybe<?> resolvedArg = resolveImmediately(arg); if (resolvedArg.isAbsent()) return Absent.castAbsent(resolvedArg); if (resolvedArg.isNull()) return Maybe.<String>of((String)null); String resolvedString = resolvedArg.get().toString(); return Maybe.of(Urls.encode(resolvedString)); }