data tree CHANGE prepare updated validation flags

Except LYD_OPT_VAL_DATA_ONLY, none are implemented, only defined.
Operations (RPC/action/rpc-reply/notification) cannot be parsed
nor validated as they will have a separate function implemented.
Also, mandatory validation implemented.
diff --git a/src/validation.c b/src/validation.c
index 129af23..0ed4c62 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -160,26 +160,103 @@
 }
 
 static LY_ERR
-lyd_validate_children_r(struct lyd_node *sibling, const struct lysc_node *sparent, const struct lysc_module *mod, int options)
+lyd_validate_mandatory(const struct lysc_node *snode, struct lyd_node *sibling)
+{
+    struct lyd_node *node;
+    int is_choice = 0;
+
+    if (snode->nodetype == LYS_CHOICE) {
+        is_choice = 1;
+    }
+
+    for (node = sibling; node; node = node->next) {
+        if (is_choice) {
+            if (node->schema->parent && (node->schema->parent->nodetype & LYS_CASE) && (node->schema->parent->parent == snode)) {
+                /* case data instance found */
+                return LY_SUCCESS;
+            }
+        } else {
+            if (node->schema == snode) {
+                /* data instance found */
+                return LY_SUCCESS;
+            }
+        }
+    }
+
+    /* node instance not found */
+    LOGVAL(snode->module->ctx, LY_VLOG_LYSC, snode, LY_VCODE_NOMAND, snode->name);
+    return LY_EVALID;
+}
+
+static LY_ERR
+lyd_validate_minmax(const struct lysc_node *snode, uint32_t min, uint32_t max, struct lyd_node *sibling)
+{
+    /* TODO snode count in siblings */
+    return LY_SUCCESS;
+}
+
+static LY_ERR
+lyd_validate_unique(const struct lysc_node *snode, struct lysc_node_leaf ***uniques, struct lyd_node *sibling)
+{
+    /* TODO check uniques in siblings and children */
+    return LY_SUCCESS;
+}
+
+static LY_ERR
+lyd_validate_cases(const struct lysc_node_case *cases, struct lyd_node *sibling)
+{
+    /* TODO check there are nodes only from a single case,
+     * what if not? validation error or autodelete */
+    return LY_SUCCESS;
+}
+
+static LY_ERR
+lyd_validate_siblings_r(struct lyd_node *sibling, const struct lysc_node *sparent, const struct lysc_module *mod, int options)
 {
     LY_ERR ret;
     const struct lysc_node *snode = NULL;
+    struct lysc_node_list *slist;
     struct lyd_node *node;
 
-    while ((snode = lys_getnext(snode, sparent, mod, 0))) {
-        /* TODO mandatory - mandatory snode must exist */
-        /* TODO min/max elem - check snode element count */
-        /* TODO unique - check snode unique */
-        /* TODO choice - case duplicites/mandatory */
+    /* disabled nodes are skipped by lys_getnext */
+    while ((snode = lys_getnext(snode, sparent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
+        /* check mandatory existence */
+        if (snode->flags & LYS_MAND_TRUE) {
+            LY_CHECK_RET(lyd_validate_mandatory(snode, sibling));
+        }
+
+        /* check min-elements and max-elements */
+        if (snode->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
+            slist = (struct lysc_node_list *)snode;
+            if (slist->min || slist->max) {
+                LY_CHECK_RET(lyd_validate_minmax(snode, slist->min, slist->max, sibling));
+            }
+        }
+
+        /* check unique */
+        if (snode->nodetype == LYS_LIST) {
+            slist = (struct lysc_node_list *)snode;
+            if (slist->uniques) {
+                LY_CHECK_RET(lyd_validate_unique(snode, slist->uniques, sibling));
+            }
+        }
+
+        /* check case duplicites */
+        if (snode->nodetype == LYS_CHOICE) {
+            LY_CHECK_RET(lyd_validate_cases(((struct lysc_node_choice *)snode)->cases, sibling));
+        }
     }
 
     for (node = sibling; node; node = node->next) {
         /* TODO node's must */
         /* TODO node instance duplicites */
         /* TODO node status */
+        /* TODO node's if-features */
+        /* TODO node list keys */
+        /* node value including if-feature is checked by plugins */
 
         /* validate all children */
-        LY_CHECK_RET(lyd_validate_children_r((struct lyd_node *)lyd_node_children(sibling), node->schema, mod, options));
+        LY_CHECK_RET(lyd_validate_siblings_r((struct lyd_node *)lyd_node_children(sibling), node->schema, mod, options));
     }
 
     return LY_SUCCESS;
@@ -194,24 +271,35 @@
     const struct lys_module *mod;
     struct lyd_node *tree;
 
-    while ((mod = lyd_val_next_module(modules, mod_count, ctx, &i))) {
-        if (!mod->implemented) {
-            continue;
-        }
-
-        /* find data of this module, if any */
-        tree = NULL;
+    if (options & LYD_OPT_VAL_DATA_ONLY) {
         if (trees) {
             for (j = 0; j < LY_ARRAY_SIZE(trees); ++j) {
-                if (trees[j]->schema->module == mod) {
-                    tree = (struct lyd_node *)trees[j];
-                    break;
-                }
+                tree = (struct lyd_node *)trees[j];
+
+                /* validate all top-level nodes and then inner nodes recursively */
+                LY_CHECK_RET(lyd_validate_siblings_r(tree, NULL, tree->schema->module->compiled, options));
             }
         }
+    } else {
+        while ((mod = lyd_val_next_module(modules, mod_count, ctx, &i))) {
+            if (!mod->implemented) {
+                continue;
+            }
 
-        /* validate all top-level nodes and then inner nodes recursively */
-        LY_CHECK_RET(lyd_validate_children_r(tree, NULL, mod->compiled, options));
+            /* find data of this module, if any */
+            tree = NULL;
+            if (trees) {
+                for (j = 0; j < LY_ARRAY_SIZE(trees); ++j) {
+                    if (trees[j]->schema->module == mod) {
+                        tree = (struct lyd_node *)trees[j];
+                        break;
+                    }
+                }
+            }
+
+            /* validate all top-level nodes and then inner nodes recursively */
+            LY_CHECK_RET(lyd_validate_siblings_r(tree, NULL, mod->compiled, options));
+        }
     }
 
     return LY_SUCCESS;