
jsonvalues.Prism Maven / Gradle / Ivy
package jsonvalues;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
/**
A Prism is an optic that can be seen as a pair of functions:
{@code
- getOptional: S -> Optional
- reverseGet : T -> S
}
Typically a Prism encodes the relation between a Sum or CoProduct type and one of its element.
@param the source of a prism
@param the target of a prism */
public class Prism {
/**
get the target of a Prism or nothing if there is no target
*/
public final Function> getOptional;
/** get the modified source of a Prism */
public final Function reverseGet;
/**
check if there is no target
*/
public final Predicate isEmpty;
/**
check if there is a target
*/
public final Predicate nonEmpty;
/**
modify the target of a Prism with a function, returning the same source if the prism is not matching. Basically
it means we dont care about the success of the operation
*/
public final Function,Function> modify;
/**
modify the target of a Prism with a function, returning empty if the prism is not matching. Unless modify, we
need to know the success of the operation
*/
public final Function,Function>> modifyOpt;
/**
find if the target satisfies the predicate
*/
public final Function,Function>> find;
/**
check if there is a target and it satisfies the predicate
*/
public final Function,Predicate> exists;
/**
check if there is no target or the target satisfies the predicate
*/
public final Function,Predicate> all;
Prism(final Function> getOptional,
final Function reverseGet
) {
this.getOptional = getOptional;
this.reverseGet = reverseGet;
this.modify = f -> {
Objects.requireNonNull(f);
return v ->
{
final Optional opt = getOptional.apply(v);
if (opt.isPresent()) return reverseGet.apply(f.apply(opt.get()));
else return v;
};
};
this.modifyOpt = f -> {
return v ->
{
final Optional opt = getOptional.apply(v);
return opt.map(t -> reverseGet.apply(f.apply(t)));
};
};
this.isEmpty = target -> !getOptional.apply(target)
.isPresent();
this.nonEmpty = target -> getOptional.apply(target)
.isPresent();
this.find = predicate -> v -> getOptional.apply(v)
.filter(predicate);
this.exists = predicate -> v -> getOptional.apply(v)
.filter(predicate)
.isPresent();
this.all = predicate -> v ->
{
final Optional value = getOptional.apply(v);
return value.map(predicate::test)
.orElse(true);
};
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy