class AbstractFieldPredicate<ENTITY, FIELD extends Field<ENTITY>>
extends AbstractPredicate<ENTITY>
implements FieldPredicate<ENTITY> {

    private final PredicateType predicateType;
    private final FIELD field;
    private final Predicate<ENTITY> tester;

    protected AbstractFieldPredicate(
            final PredicateType predicateType,
            final FIELD field,
            final Predicate<ENTITY> tester) {

        this.predicateType = requireNonNull(predicateType);
        this.field         = requireNonNull(field);
        this.tester        = requireNonNull(tester);
    }

    protected final Predicate<ENTITY> getTester() {
        return tester;
    }

    @Override
    public boolean applyAsBoolean(ENTITY instance) {
        return tester.test(instance);
    }

    @Override
    public final PredicateType getPredicateType() {
        return predicateType;
    }

    @Override
    public final FIELD getField() {
        return field;
    }


    @Override
    public String toString() {<FILL_FUNCTION_BODY>}
}

        final ColumnIdentifier<ENTITY> cId = field.identifier();
        final StringBuilder sb = new StringBuilder();

        sb.append(getClass().getSimpleName())
            .append(" {")
            .append("field: ")
            .append(cId.getDbmsId()).append('.')
            .append(cId.getSchemaId()).append('.')
            .append(cId.getTableId()).append('.')
            .append(cId.getColumnId())
            .append(", type: '").append(predicateType).append("'");

        Cast.cast(this, Tuple.class).ifPresent(tuple -> {
            for (int i = 0; i < tuple.degree(); i++) {
                sb.append(", operand ").append(i)
                    .append(": ").append(tuple.get(i));
            }
        });

        return sb.append("}").toString();
    
<methods>public SpeedmentPredicate<ENTITY> and(Predicate<? super ENTITY>) ,public SpeedmentPredicate<ENTITY> or(Predicate<? super ENTITY>) <variables>