+
+ @Override
+ void verifyStructure(final NormalizedNode<?, ?> writtenValue, final boolean verifyChildren) {
+ if(verifyChildrenStructure() && verifyChildren) {
+ enforceCases(writtenValue);
+ }
+ super.verifyStructure(writtenValue, verifyChildren);
+ }
+
+ private void enforceCases(final TreeNode tree) {
+ enforceCases(tree.getData());
+ }
+
+ private void enforceCases(final NormalizedNode<?, ?> normalizedNode) {
+ Verify.verify(normalizedNode instanceof ChoiceNode);
+ final Collection<DataContainerChild<?, ?>> children = ((ChoiceNode) normalizedNode).getValue();
+ if (!children.isEmpty()) {
+ final DataContainerChild<?, ?> firstChild = children.iterator().next();
+ final CaseEnforcer enforcer = caseEnforcers.get(firstChild.getIdentifier());
+ Verify.verifyNotNull(enforcer, "Case enforcer cannot be null. Most probably, child node %s of choice node %s does not belong in current tree type.", firstChild.getIdentifier(), normalizedNode.getIdentifier());
+
+ // Make sure no leaves from other cases are present
+ for (CaseEnforcer other : exclusions.get(enforcer)) {
+ for (NodeIdentifier id : other.getChildIdentifiers()) {
+ final Optional<NormalizedNode<?, ?>> maybeChild = NormalizedNodes.getDirectChild(normalizedNode, id);
+ Preconditions.checkArgument(!maybeChild.isPresent(),
+ "Child %s (from case %s) implies non-presence of child %s (from case %s), which is %s",
+ firstChild.getIdentifier(), enforcer, id, other, maybeChild.orNull());
+ }
+ }
+
+ // Make sure all mandatory children are present
+ enforcer.enforceOnTreeNode(normalizedNode);
+ }
+ }
+
+ @Override
+ protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta, final Version version) {
+ final TreeNode ret = super.applyMerge(modification, currentMeta, version);
+ enforceCases(ret);
+ return ret;
+ }
+
+ @Override
+ protected TreeNode applyWrite(final ModifiedNode modification, final Optional<TreeNode> currentMeta,
+ final Version version) {
+ final TreeNode ret = super.applyWrite(modification, currentMeta, version);
+ enforceCases(ret);
+ return ret;
+ }
+
+ @Override
+ protected TreeNode applyTouch(final ModifiedNode modification, final TreeNode currentMeta, final Version version) {
+ final TreeNode ret = super.applyTouch(modification, currentMeta, version);
+ enforceCases(ret);
+ return ret;
+ }