package tc.oc.commons.core.inspect;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Optional;
import java.util.stream.Stream;
import com.google.common.collect.Maps;
import tc.oc.commons.core.stream.BiStream;
import tc.oc.commons.core.util.Chain;
import tc.oc.commons.core.util.Optionals;
public interface Inspectable {
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface Inspect {
/**
* Override property name
*/
String name() default "";
/**
* Exclude nulls and empty {@link Optional}s
*/
boolean optional() default true;
/**
* Expand arrays and collections
*/
boolean deep() default true;
/**
* Only identify, don't inspect
*/
boolean brief() default false;
/**
* Quote string/character values
*/
boolean quote() default true;
/**
* Flatten child properties into parent
*/
boolean inline() default false;
}
default String identify() {
return Optionals.reduce(inspectType(), inspectIdentity(), (type, id) -> type + ":" + id);
}
default String inspect() {
final TextInspector inspector = new TextInspector();
return inspect(inspector, Inspection.defaults());
}
default <R> R inspect(Inspector<R> inspector, Inspection options) {
return options.inspect(inspector, this, Chain.empty());
}
default String inspectType() {
return getClass().getSimpleName();
}
default Optional<String> inspectIdentity() {
return Optional.empty();
}
default <R> BiStream<String, R> inspectProperties(Inspector<R> inspector, Chain<Object> visited) {
return BiStream.from(inspectableProperties().flatMap(property -> property.flatValues(this)))
.map((property, value) -> property.name(),
(property, value) -> property.options().inspect(inspector, value, visited.push(this)));
}
default Stream<? extends InspectableProperty> inspectableProperties() {
return ReflectiveProperty.all(getClass()).stream();
}
class Impl implements Inspectable {
@Override public String toString() {
return inspect();
}
}
}