making/yavi

How to validate if a field is set?

atkawa7 opened this issue · 2 comments

Hi @making. Got a question

I have class that has two fields. How do I validate whether one field is set. The two fields cannot be set at the same time and both cannot be null as well. How do I validate this so that when both are set I get an error These two fields cannot be set concurrently and These two fields cannot be null when both are null

 public static class Document {
        private String fileId;
        private String url;

        public String getFileId() {
            return fileId;
        }

        public void setFileId(String fileId) {
            this.fileId = fileId;
        }

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }
    }

Here is what I have and it helps but its not outputting the correct message

import am.ik.yavi.builder.ValidatorBuilder;
import am.ik.yavi.constraint.CharSequenceConstraint;
import am.ik.yavi.core.Constraint;
import am.ik.yavi.core.ConstraintViolation;

import java.util.Objects;

import static java.util.Objects.isNull;

public class SampleMain {

    public static class Document {
        private String fileId;
        private String url;

        public String getFileId() {
            return fileId;
        }

        public void setFileId(String fileId) {
            this.fileId = fileId;
        }

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }
    }


    public static void main(String[] args) {
        var result  = ValidatorBuilder.of(Document.class)
                .constraintOnCondition((document, constraintContext) ->
                        isNull(document.getFileId()), b -> b.constraint(Document::getUrl, "url", c->c.notBlank().url()))
                .constraintOnCondition((document, constraintContext) ->
                        Objects.nonNull(document.getFileId()), b -> b.constraint(Document::getUrl, "url", Constraint::isNull))
                .constraintOnCondition((document, constraintContext) -> isNull(document.getUrl()),
                        b -> b.constraint(Document::getFileId, "fileId", CharSequenceConstraint::notBlank))
                .constraintOnCondition((document, constraintContext) -> Objects.nonNull(document.getUrl()), b -> b.constraint(Document::getFileId, "fileId", CharSequenceConstraint::isNull))
                .build();

        var document  = new Document();
        document.setUrl("https://example.com");
        document.setFileId("xxxxxxxxxxxxxxxxx");

        var errors  = result.validate(document);

        for (ConstraintViolation error : errors) {
            System.out.println(error.detail());
        }
    }
}
ViolationDetail{key='object.isNull', args=[url, https://example.com], defaultMessage='"url" must be null'}
ViolationDetail{key='object.isNull', args=[fileId, xxxxxxxxxxxxxxxxx], defaultMessage='"fileId" must be null'}

It sounds like a usecase for cross-field validation
https://yavi.ik.am/#cross-field-validation

@making Thanks this is perfect for my case. Closing this

 public static void main(String[] args) {
        var result  =
                of(Document.class)
                        .constraintOnTarget(document -> isNull(document.getUrl()) || isNull(document.getFileId()),
                                "url", "url.bothNonNull", "Both \"url\"  and \"fileId\" must not be set")
                        .constraintOnTarget(document -> nonNull(document.getUrl()) || nonNull(document.getFileId()),
                                "url", "url.bothNotNull", "Both \"url\"  and \"fileId\" must not be null")

                        .build();

        var document  = new Document();
        document.setUrl("https://example.com");
        document.setFileId("xxxxxxxxxxxxxxxxx");



        var errors  = result.validate(document);

        for (ConstraintViolation error : errors) {
            System.out.println(error.message());
        }
    }

Result ->

Both "url"  and "fileId" must not be set