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;
35 public class YangDataOperations {
37 public static CompositeNode merge(final DataSchemaNode schema,
38 final CompositeNode stored, final CompositeNode modified,
39 final boolean config) {
44 Preconditions.checkArgument(schema instanceof ListSchemaNode
45 || schema instanceof ContainerSchemaNode,
46 "Supplied node is not data node container.");
48 return YangDataOperations.mergeContainer((DataNodeContainer) schema,
49 stored, modified, config);
52 private static Iterable<? extends Node<?>> _mergeMultiple(
53 final LeafSchemaNode node, final List<Node<?>> original,
54 final List<Node<?>> modified, final boolean configurational) {
55 checkArgument(original.size() == 1);
56 checkArgument(modified.size() == 1);
61 private static Iterable<? extends Node<?>> _mergeMultiple(
62 final LeafListSchemaNode node, final List<Node<?>> original,
63 final List<Node<?>> modified, final boolean configurational) {
67 private static Iterable<? extends Node<?>> _mergeMultiple(
68 final ContainerSchemaNode node, final List<Node<?>> original,
69 final List<Node<?>> modified, final boolean configurational) {
70 checkArgument(original.size() == 1);
71 checkArgument(modified.size() == 1);
72 return Collections.singletonList(merge(node,
73 (CompositeNode) original.get(0),
74 (CompositeNode) modified.get(0), configurational));
77 private static Iterable<? extends Node<?>> _mergeMultiple(
78 final ListSchemaNode node, final List<Node<?>> original,
79 final List<Node<?>> modified, final boolean configurational) {
81 if (node.getKeyDefinition() == null
82 || node.getKeyDefinition().isEmpty()) {
85 @SuppressWarnings({ "unchecked", "rawtypes" })
86 final Map<Map<QName, Object>, CompositeNode> originalMap = YangDataUtils
87 .toIndexMap((List) original, node.getKeyDefinition());
88 @SuppressWarnings({ "unchecked", "rawtypes" })
89 final Map<Map<QName, Object>, CompositeNode> modifiedMap = YangDataUtils
90 .toIndexMap((List) modified, node.getKeyDefinition());
92 final List<Node<?>> mergedNodes = new ArrayList<Node<?>>(
93 original.size() + modified.size());
94 for (final Map.Entry<Map<QName, Object>, CompositeNode> entry : modifiedMap
96 final CompositeNode originalEntry = originalMap.get(entry.getKey());
97 if (originalEntry != null) {
98 originalMap.remove(entry.getKey());
99 mergedNodes.add(merge(node, originalEntry, entry.getValue(),
102 mergedNodes.add(entry.getValue());
105 mergedNodes.addAll(originalMap.values());
109 private static Iterable<? extends Node<?>> mergeMultiple(
110 final DataSchemaNode node, final List<Node<?>> original,
111 final List<Node<?>> modified, final boolean configurational) {
112 if (node instanceof ContainerSchemaNode) {
113 return _mergeMultiple((ContainerSchemaNode) node, original,
114 modified, configurational);
115 } else if (node instanceof LeafListSchemaNode) {
116 return _mergeMultiple((LeafListSchemaNode) node, original,
117 modified, configurational);
118 } else if (node instanceof LeafSchemaNode) {
119 return _mergeMultiple((LeafSchemaNode) node, original, modified,
121 } else if (node instanceof ListSchemaNode) {
122 return _mergeMultiple((ListSchemaNode) node, original, modified,
125 throw new IllegalArgumentException("Unhandled parameter types: "
126 + Arrays.<Object> asList(node, original, modified,
127 configurational).toString());
131 private static CompositeNode mergeContainer(final DataNodeContainer schema,
132 final CompositeNode stored, final CompositeNode modified,
133 final boolean config) {
134 if (stored == null) {
137 Preconditions.checkNotNull(stored);
138 Preconditions.checkNotNull(modified);
139 Preconditions.checkArgument(Objects.equals(stored.getNodeType(),
140 modified.getNodeType()));
142 final List<Node<?>> mergedChildNodes = new ArrayList<Node<?>>(stored
143 .getValue().size() + modified.getValue().size());
144 final Set<QName> toProcess = new HashSet<QName>(stored.keySet());
145 toProcess.addAll(modified.keySet());
147 for (QName qname : toProcess) {
148 final DataSchemaNode schemaChild = schema.getDataChildByName(qname);
149 final List<Node<?>> storedChildren = stored.get(qname);
150 final List<Node<?>> modifiedChildren = modified.get(qname);
152 if (modifiedChildren != null && !modifiedChildren.isEmpty()) {
153 if (storedChildren == null || storedChildren.isEmpty()
154 || schemaChild == null) {
155 mergedChildNodes.addAll(modifiedChildren);
157 final Iterable<? extends Node<?>> _mergeMultiple = mergeMultiple(
158 schemaChild, storedChildren, modifiedChildren,
160 Iterables.addAll(mergedChildNodes, _mergeMultiple);
162 } else if (storedChildren != null && !storedChildren.isEmpty()) {
163 mergedChildNodes.addAll(storedChildren);
166 return new CompositeNodeTOImpl(stored.getNodeType(), null,