/*
* This file is part of LanternServer, licensed under the MIT License (MIT).
*
* Copyright (c) LanternPowered <https://www.lanternpowered.org>
* Copyright (c) SpongePowered <https://www.spongepowered.org>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the Software), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.lanternpowered.server.data.value.processor;
import static com.google.common.base.Preconditions.checkNotNull;
import org.lanternpowered.server.data.value.ElementHolder;
import org.lanternpowered.server.data.value.IValueContainer;
import org.lanternpowered.server.util.functions.QuadFunction;
import org.lanternpowered.server.util.functions.TriFunction;
import org.spongepowered.api.data.DataTransactionResult;
import org.spongepowered.api.data.key.Key;
import org.spongepowered.api.data.value.BaseValue;
import org.spongepowered.api.data.value.mutable.Value;
import org.spongepowered.api.util.ResettableBuilder;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
public interface ValueProcessor<V extends BaseValue<E>, E> {
/**
* Get the {@link Predicate} that will check whether the target
* {@link IValueContainer} is supported.
*
* @return The applicable tester
*/
BiPredicate<Key<? extends V>, IValueContainer<?>> getApplicableTester();
/**
* Gets the handler that will be used to handle removed {@link Key}s.
*
* @return The remove handler
*/
BiFunction<Key<? extends V>, IValueContainer<?>, DataTransactionResult> getRemoveHandler();
/**
* Gets the handler that will be used to handle offered {@link Key}s with a element.
*
* @return The offer handler
*/
TriFunction<Key<? extends V>, IValueContainer<?>, E, DataTransactionResult> getOfferHandler();
/**
* Gets the handler that will be used to handle retrieved {@link Key}s.
*
* @return The retrieve handler
*/
BiFunction<Key<? extends V>, IValueContainer<?>, Optional<E>> getRetrieveHandler();
/**
* Gets the handler that will be used to handle retrieved {@link BaseValue}s.
*
* @return The value retrieve handler
*/
BiFunction<Key<? extends V>, IValueContainer<?>, Optional<V>> getValueRetrieveHandler();
/**
* Gets the handler that will be used to handle offered {@link BaseValue}s.
*
* @return The offer handler
*/
BiFunction<IValueContainer<?>, V, DataTransactionResult> getValueOfferHandler();
/**
* Gets the builder that will be used to create {@link BaseValue}s.
*
* @return The value builder
*/
TriFunction<Key<? extends V>, IValueContainer<?>, E, V> getValueBuilder();
/**
* Gets the default attached element {@link ValueProcessor}.
*
* @param <V> The value type
* @param <E> The element type
* @return The value processor
*/
@SuppressWarnings("unchecked")
static <V extends BaseValue<E>, E> ValueProcessor<V, E> getDefaultAttachedValueProcessor() {
return SimpleValueProcessor.AttachedElementBuilder.DEFAULT;
}
/**
* Gets the default attached element {@link ValueProcessor} that doesn't allow the removal of elements.
*
* @param <V> The value type
* @param <E> The element type
* @return The value processor
*/
@SuppressWarnings("unchecked")
static <V extends BaseValue<E>, E> ValueProcessor<V, E> getNonRemovableDefaultAttachedValueProcessor() {
return SimpleValueProcessor.AttachedElementBuilder.NON_REMOVABLE;
}
static <V extends BaseValue<E>, E> Builder<V, E> builder() {
return new SimpleValueProcessor.Builder<>();
}
static <V extends BaseValue<E>, E> AttachedElementBuilder<V, E> attachedElementBuilder() {
return new SimpleValueProcessor.AttachedElementBuilder<>();
}
interface BuilderBase<V extends BaseValue<E>, E, B extends BuilderBase<V, E, B>> extends ResettableBuilder<ValueProcessor<V, E>, B> {
/**
* Set the {@link BiPredicate} that will check whether the target
* {@link Key} is supported for {@link IValueContainer}.
*
* @param tester The applicable tester
* @return The builder for chaining
*/
B applicableTester(BiPredicate<Key<? extends V>, IValueContainer<?>> tester);
/**
* Set the {@link Predicate} that will check whether the target
* {@link IValueContainer} is supported.
*
* @param tester The applicable tester
* @return The builder for chaining
*/
default B applicableTester(Predicate<IValueContainer<?>> tester) {
return this.applicableTester((key, valueContainer) -> tester.test(valueContainer));
}
/**
* Sets the remove handler of this value processor, it will be called when someone attempts
* to remove a value with a specific {@link Key} from the {@link IValueContainer}.
*
* @param handler The remove handler
* @return The builder for chaining
*/
B removeHandler(BiFunction<Key<? extends V>, IValueContainer<?>, DataTransactionResult> handler);
/**
* Sets the remove handler of this value processor that will always fail.
*
* @return The builder for chaining
*/
default B failAlwaysRemoveHandler() {
return this.removeHandler(RemoveHandlers.failAlways());
}
/**
* Sets the offer handler of this value processor that will pass a {@link Value} through, it will be called when someone attempts
* to add or update a value for a specific {@link Key} to the {@link IValueContainer}.
*
* @param handler The offer handler
* @return The value processor for chaining
*/
B valueOfferHandler(BiFunction<IValueContainer<?>, V, DataTransactionResult> handler);
/**
* Sets the offer handler of this value processor, it will be called when someone attempts
* to add or update a value for a specific {@link Key} to the {@link IValueContainer}.
*
* @param handler The offer handler
* @return The value processor for chaining
*/
B offerHandler(TriFunction<Key<? extends V>, IValueContainer<?>, E, DataTransactionResult> handler);
/**
* Sets the retrieve handler of this value processor, it will be called when someone attempts
* to get a element for a specific {@link Key} from the {@link IValueContainer}.
*
* @param handler The retrieve handler
* @return The value processor for chaining
*/
B retrieveHandler(BiFunction<Key<? extends V>, IValueContainer<?>, Optional<E>> handler);
/**
* Sets the retrieve retrieve handler of this value processor, it will be called when someone attempts
* to get a {@link BaseValue} for a specific {@link Key} from the {@link IValueContainer}.
*
* @param handler The retrieve handler
* @return The value processor for chaining
*/
B valueRetrieveHandler(BiFunction<Key<? extends V>, IValueContainer<?>, Optional<V>> handler);
/**
* Sets the builder that should be used to create the {@link Value}s.
*
* @param builder The value builder
* @return The value processor for chaining
*/
B valueBuilder(TriFunction<Key<? extends V>, IValueContainer<?>, E, V> builder);
/**
* Builds a {@link ValueProcessor}.
*
* @return The value processor
*/
ValueProcessor<V, E> build();
}
interface Builder<V extends BaseValue<E>, E> extends BuilderBase<V, E, Builder<V, E>> {
}
/**
* A {@link ValueProcessor.Builder} that expects that there is a {@link ElementHolder} attached
* to the target key.
*
* @param <V> The value type
* @param <E> The element type
*/
interface AttachedElementBuilder<V extends BaseValue<E>, E> extends BuilderBase<V, E, AttachedElementBuilder<V, E>> {
/**
* Sets the offer handler.
*
* @param handler The offer handler
* @return The value processor for chaining
*/
default AttachedElementBuilder<V, E> offerHandler(QuadFunction<Key<? extends V>, IValueContainer<?>, ElementHolder<E>, E,
DataTransactionResult> handler) {
return this.offerHandler(((key, valueContainer, e) -> handler.apply(key, valueContainer, checkNotNull(valueContainer.getElementHolder(key)), e)));
}
/**
* Sets the remove handler.
*
* @param handler The remove handler
* @return The value processor for chaining
*/
default AttachedElementBuilder<V, E> removeHandler(TriFunction<Key<? extends V>, IValueContainer<?>, ElementHolder<E>,
DataTransactionResult> handler) {
return this.removeHandler(((key, valueContainer) -> handler.apply(key, valueContainer, checkNotNull(valueContainer.getElementHolder(key)))));
}
}
}