Implement edit-config operations for NormalizedNode yang-data-api
[yangtools.git] / yang / yang-data-operations / src / main / java / org / opendaylight / yangtools / yang / data / operations / MapNodeModification.java
1 /*
2 * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3 *
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
7 */
8 package org.opendaylight.yangtools.yang.data.operations;
9
10 import java.util.Map;
11
12 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
13 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
14 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
15 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
16 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
17 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
18
19 import com.google.common.base.Optional;
20 import com.google.common.collect.Maps;
21
22 public class MapNodeModification implements Modification<ListSchemaNode, MapNode> {
23
24     public static final MapEntryNodeModification MAP_ENTRY_NODE_MODIFICATION = new MapEntryNodeModification();
25
26     @Override
27     public Optional<MapNode> modify(ListSchemaNode schema, Optional<MapNode> actual,
28                                     Optional<MapNode> modification, OperationStack operationStack) throws DataModificationException {
29
30         // Merge or None operation on parent, leaving actual if modification not present
31         if (modification.isPresent() == false)
32             return actual;
33
34         Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> resultNodes = Maps.newLinkedHashMap();
35         if(actual.isPresent())
36             resultNodes.putAll(mapEntries(actual.get()));
37
38         // TODO implement ordering for modification nodes
39
40         for (MapEntryNode mapEntryModification : modification.get().getValue()) {
41
42             operationStack.enteringNode(mapEntryModification);
43
44             InstanceIdentifier.NodeIdentifierWithPredicates entryKey = mapEntryModification.getIdentifier();
45
46             switch (operationStack.getCurrentOperation()) {
47             case NONE:
48                 DataModificationException.DataMissingException.check(schema.getQName(), actual, mapEntryModification);
49             case MERGE: {
50                 MapEntryNode mergedListNode;
51                 if (resultNodes.containsKey(entryKey)) {
52                     MapEntryNode actualEntry = resultNodes.get(entryKey);
53                     mergedListNode = MAP_ENTRY_NODE_MODIFICATION.modify(schema, Optional.of(actualEntry), Optional.of(mapEntryModification), operationStack).get();
54                 } else {
55                     mergedListNode = mapEntryModification;
56                 }
57
58                 resultNodes.put(mergedListNode.getIdentifier(), mergedListNode);
59                 break;
60             }
61             case CREATE: {
62                 DataModificationException.DataExistsException.check(schema.getQName(), actual, mapEntryModification);
63             }
64             case REPLACE: {
65                 resultNodes.put(entryKey, mapEntryModification);
66                 break;
67             }
68             case DELETE: {
69                 DataModificationException.DataMissingException.check(schema.getQName(), actual, mapEntryModification);
70             }
71             case REMOVE: {
72                 if (resultNodes.containsKey(entryKey)) {
73                     resultNodes.remove(entryKey);
74                 }
75                 break;
76             }
77             default:
78                 throw new UnsupportedOperationException(String.format("Unable to perform operation: %s on: %s, unknown", operationStack.getCurrentOperation(), schema));
79             }
80
81             operationStack.exitingNode(mapEntryModification);
82         }
83         return build(schema, resultNodes);
84     }
85
86     private Optional<MapNode> build(ListSchemaNode schema, Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> resultNodes) {
87         if(resultNodes.isEmpty())
88             return Optional.absent();
89
90         CollectionNodeBuilder<MapEntryNode, MapNode> b = Builders.mapBuilder(schema);
91
92         for (MapEntryNode child : resultNodes.values()) {
93             b.withChild(child);
94         }
95
96         return Optional.of(b.build());
97     }
98
99     private Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> mapEntries(MapNode mapNode) {
100         Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> mapped = Maps.newLinkedHashMap();
101
102         for (MapEntryNode mapEntryNode : mapNode.getValue()) {
103             mapped.put(mapEntryNode.getIdentifier(), mapEntryNode);
104         }
105
106         return mapped;
107     }
108
109 }