2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.sal.dom.broker.util;
10 import static com.google.common.base.Preconditions.checkArgument;
12 import com.google.common.base.Preconditions;
13 import com.google.common.collect.Iterables;
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.Collections;
18 import java.util.HashSet;
19 import java.util.List;
21 import java.util.Objects;
24 import org.opendaylight.yangtools.yang.common.QName;
25 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
26 import org.opendaylight.yangtools.yang.data.api.Node;
27 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
28 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
29 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
30 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
31 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
32 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
33 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
36 public class YangDataOperations {
38 public static CompositeNode merge(final DataSchemaNode schema,
39 final CompositeNode stored, final CompositeNode modified,
40 final boolean config) {
45 Preconditions.checkArgument(schema instanceof ListSchemaNode
46 || schema instanceof ContainerSchemaNode,
47 "Supplied node is not data node container.");
49 return YangDataOperations.mergeContainer((DataNodeContainer) schema,
50 stored, modified, config);
53 private static Iterable<? extends Node<?>> _mergeMultiple(
54 final LeafSchemaNode node, final List<Node<?>> original,
55 final List<Node<?>> modified, final boolean configurational) {
56 checkArgument(original.size() == 1);
57 checkArgument(modified.size() == 1);
62 private static Iterable<? extends Node<?>> _mergeMultiple(
63 final LeafListSchemaNode node, final List<Node<?>> original,
64 final List<Node<?>> modified, final boolean configurational) {
68 private static Iterable<? extends Node<?>> _mergeMultiple(
69 final ContainerSchemaNode node, final List<Node<?>> original,
70 final List<Node<?>> modified, final boolean configurational) {
71 checkArgument(original.size() == 1);
72 checkArgument(modified.size() == 1);
73 return Collections.singletonList(merge(node,
74 (CompositeNode) original.get(0),
75 (CompositeNode) modified.get(0), configurational));
78 private static Iterable<? extends Node<?>> _mergeMultiple(
79 final ListSchemaNode node, final List<Node<?>> original,
80 final List<Node<?>> modified, final boolean configurational) {
82 if (node.getKeyDefinition() == null
83 || node.getKeyDefinition().isEmpty()) {
86 @SuppressWarnings({ "unchecked", "rawtypes" })
87 final Map<Map<QName, Object>, CompositeNode> originalMap = YangDataUtils
88 .toIndexMap((List) original, node.getKeyDefinition());
89 @SuppressWarnings({ "unchecked", "rawtypes" })
90 final Map<Map<QName, Object>, CompositeNode> modifiedMap = YangDataUtils
91 .toIndexMap((List) modified, node.getKeyDefinition());
93 final List<Node<?>> mergedNodes = new ArrayList<Node<?>>(
94 original.size() + modified.size());
95 for (final Map.Entry<Map<QName, Object>, CompositeNode> entry : modifiedMap
97 final CompositeNode originalEntry = originalMap.get(entry.getKey());
98 if (originalEntry != null) {
99 originalMap.remove(entry.getKey());
100 mergedNodes.add(merge(node, originalEntry, entry.getValue(),
103 mergedNodes.add(entry.getValue());
106 mergedNodes.addAll(originalMap.values());
110 private static Iterable<? extends Node<?>> mergeMultiple(
111 final DataSchemaNode node, final List<Node<?>> original,
112 final List<Node<?>> modified, final boolean configurational) {
113 if (node instanceof ContainerSchemaNode) {
114 return _mergeMultiple((ContainerSchemaNode) node, original,
115 modified, configurational);
116 } else if (node instanceof LeafListSchemaNode) {
117 return _mergeMultiple((LeafListSchemaNode) node, original,
118 modified, configurational);
119 } else if (node instanceof LeafSchemaNode) {
120 return _mergeMultiple((LeafSchemaNode) node, original, modified,
122 } else if (node instanceof ListSchemaNode) {
123 return _mergeMultiple((ListSchemaNode) node, original, modified,
126 throw new IllegalArgumentException("Unhandled parameter types: "
127 + Arrays.<Object> asList(node, original, modified,
128 configurational).toString());
132 private static CompositeNode mergeContainer(final DataNodeContainer schema,
133 final CompositeNode stored, final CompositeNode modified,
134 final boolean config) {
135 if (stored == null) {
138 Preconditions.checkNotNull(stored);
139 Preconditions.checkNotNull(modified);
140 Preconditions.checkArgument(Objects.equals(stored.getNodeType(),
141 modified.getNodeType()));
143 final List<Node<?>> mergedChildNodes = new ArrayList<Node<?>>(stored
144 .getValue().size() + modified.getValue().size());
145 final Set<QName> toProcess = new HashSet<QName>(stored.keySet());
146 toProcess.addAll(modified.keySet());
148 for (QName qname : toProcess) {
149 final DataSchemaNode schemaChild = schema.getDataChildByName(qname);
150 final List<Node<?>> storedChildren = stored.get(qname);
151 final List<Node<?>> modifiedChildren = modified.get(qname);
153 if (modifiedChildren != null && !modifiedChildren.isEmpty()) {
154 if (storedChildren == null || storedChildren.isEmpty()
155 || schemaChild == null) {
156 mergedChildNodes.addAll(modifiedChildren);
158 final Iterable<? extends Node<?>> _mergeMultiple = mergeMultiple(
159 schemaChild, storedChildren, modifiedChildren,
161 Iterables.addAll(mergedChildNodes, _mergeMultiple);
163 } else if (storedChildren != null && !storedChildren.isEmpty()) {
164 mergedChildNodes.addAll(storedChildren);
167 return new CompositeNodeTOImpl(stored.getNodeType(), null,