io.neba.api.resourcemodels.Lazy Maven / Gradle / Ivy
Show all versions of io.neba.neba-api Show documentation
/*
Copyright 2013 the original author or authors.
Licensed 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 io.neba.api.resourcemodels;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import static java.util.Objects.requireNonNull;
/**
*
* Declares lazy-loading 1:1 relationships in resource models. In addition, as lazy-loading always has to deal with nonexistent values, this
* interface both features a {@link java.util.Optional} representation via {@link #asOptional()} and provides the same API semantics
* as {@link java.util.Optional} for convenience.
*
*
* NEBA automatically detects {@link Lazy} fields and provides a suitable lazy-loading implementation.
* Note that this interface is not required to lazy-load collections, as NEBA automatically
* provides collection-typed members, such as {@link io.neba.api.annotations.Reference}
* or {@link io.neba.api.annotations.Children} collections, as lazy-loading proxies.
*
*
* To declare a lazy reference from resource model "A" to resource model "B", write:
*
*
* @{@link io.neba.api.annotations.ResourceModel}(types = "...")
* public class A {
* @{@link io.neba.api.annotations.Reference}
* private Lazy<B> b;
* }
*
*
* This interface may also be used to explicitly lazy-load collection-typed resource model relationships, such as
* {@link io.neba.api.annotations.Children} or {@link io.neba.api.annotations.Reference} collections:
*
*
* @{@link io.neba.api.annotations.ResourceModel}(types = "...")
* public class A {
* @{@link io.neba.api.annotations.Children}
* private Lazy<List<B>> children;
* }
*
*
* However, collection-typed relationships are automatically provided as lazy-loading proxies, thus there usually is no
* reason to make them {@link Lazy}.
*
*
* @since 4.3.0
* @param the type of the lazy-loaded object.
* @author Olaf Otto
*/
public interface Lazy {
/**
* @return a {@link java.util.Optional} representation of the lazy-loaded value, never null
.
*/
@Nonnull
java.util.Optional asOptional();
/**
* @see java.util.Optional#get
*/
@Nonnull
default T get() {
return asOptional().get();
}
/**
* @see java.util.Optional#isPresent
*/
default boolean isPresent() {
return asOptional().isPresent();
}
/**
* @see java.util.Optional#ifPresent
*/
default void ifPresent(Consumer super T> c) {
asOptional().ifPresent(c);
}
/**
* @see java.util.Optional#filter
*/
@Nonnull
default Lazy filter(Predicate super T> predicate) {
return () -> asOptional().filter(predicate);
}
/**
* @see java.util.Optional#map
*/
@Nonnull
default Lazy map(Function super T, ? extends U> f) {
return () -> asOptional().map(f);
}
/**
* @see java.util.Optional#flatMap
*/
@Nonnull
default Lazy flatMap(Function super T, Lazy> f) {
requireNonNull(f);
if (!isPresent()) {
return java.util.Optional::empty;
} else {
return requireNonNull(f.apply(get()));
}
}
/**
* @see java.util.Optional#orElse
*/
@CheckForNull
default T orElse(T other) {
return asOptional().orElse(other);
}
/**
* @see java.util.Optional#orElseGet
*/
@CheckForNull
default T orElseGet(Supplier extends T> other) {
return asOptional().orElseGet(other);
}
/**
* @see java.util.Optional#orElseThrow
*/
@Nonnull
default T orElseThrow(Supplier extends X> exceptionSupplier) throws X {
return asOptional().orElseThrow(exceptionSupplier);
}
}