Merge "BUG 2799: SPI for EventSources"
[controller.git] / opendaylight / netconf / netconf-cli / src / main / java / org / opendaylight / controller / netconf / cli / reader / impl / ListEntryReader.java
1 /*
2  * Copyright (c) 2014 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.controller.netconf.cli.reader.impl;
9
10 import com.google.common.base.Function;
11 import com.google.common.base.Optional;
12 import com.google.common.collect.Collections2;
13 import java.io.IOException;
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.HashMap;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Set;
20 import org.opendaylight.controller.netconf.cli.CommandArgHandlerRegistry;
21 import org.opendaylight.controller.netconf.cli.io.BaseConsoleContext;
22 import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
23 import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
24 import org.opendaylight.controller.netconf.cli.reader.AbstractReader;
25 import org.opendaylight.controller.netconf.cli.reader.GenericListEntryReader;
26 import org.opendaylight.controller.netconf.cli.reader.ReadingException;
27 import org.opendaylight.yangtools.yang.common.QName;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
29 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
30 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
32 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
33 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
34 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
35 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
36 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
37 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
38 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 class ListEntryReader extends AbstractReader<ListSchemaNode> implements GenericListEntryReader<ListSchemaNode> {
43     private static final Logger LOG = LoggerFactory.getLogger(ListEntryReader.class);
44
45     private final CommandArgHandlerRegistry argumentHandlerRegistry;
46
47     public ListEntryReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
48             final SchemaContext schemaContext) {
49         super(console, schemaContext);
50         this.argumentHandlerRegistry = argumentHandlerRegistry;
51     }
52
53     public ListEntryReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
54             final SchemaContext schemaContext, final boolean readConfigNode) {
55         super(console, schemaContext, readConfigNode);
56         this.argumentHandlerRegistry = argumentHandlerRegistry;
57     }
58
59     @Override
60     public List<NormalizedNode<?, ?>> readWithContext(final ListSchemaNode listNode) throws IOException, ReadingException {
61         console.formatLn("Submit child nodes for list entry: %s, %s", listNode.getQName().getLocalName(),
62                 Collections2.transform(listNode.getChildNodes(), new Function<DataSchemaNode, String>() {
63                     @Override
64                     public String apply(final DataSchemaNode input) {
65                         return input.getQName().getLocalName();
66                     }
67                 }));
68
69         final String listName = listNode.getQName().getLocalName();
70
71         final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> builder =
72                 ImmutableMapEntryNodeBuilder.create();
73 //        final CompositeNodeBuilder<ImmutableCompositeNode> compositeNodeBuilder = ImmutableCompositeNode.builder();
74 //        compositeNodeBuilder.setQName(listNode.getQName());
75
76         final SeparatedNodes separatedChildNodes = SeparatedNodes.separateNodes(listNode, getReadConfigNode());
77
78         final List<NormalizedNode<?, ?>> nodes = readKeys(separatedChildNodes.getKeyNodes());
79         final Map<QName, Object> qnameToValues = new HashMap<>();
80         for (NormalizedNode node : nodes) {
81             qnameToValues.put(node.getNodeType(), node.getValue());
82         }
83         builder.withNodeIdentifier(new NodeIdentifierWithPredicates(listNode.getQName(), qnameToValues));
84
85         nodes.addAll(readMandatoryNotKeys(separatedChildNodes.getMandatoryNotKey()));
86         if (!separatedChildNodes.getOthers().isEmpty()) {
87             final Optional<Boolean> readNodesWhichAreNotKey = new DecisionReader().read(console,
88                     "Add non-key, non-mandatory nodes to list %s? [Y|N]", listName);
89             if (readNodesWhichAreNotKey.isPresent() && readNodesWhichAreNotKey.get()) {
90                 nodes.addAll(readNotKeys(separatedChildNodes.getOthers()));
91             }
92         }
93
94         if (!nodes.isEmpty()) {
95 //            compositeNodeBuilder.addAll(nodes);
96             builder.withValue((List) nodes);
97             return Collections.<NormalizedNode<?, ?>>singletonList(
98                     ImmutableMapNodeBuilder.create()
99                             .withNodeIdentifier(new NodeIdentifier(listNode.getQName()))
100                             .withChild(builder.build()).build());
101 //            return Collections.<DataContainerChild<?, ?>> singletonList(compositeNodeBuilder.toInstance());
102         } else {
103             return Collections.emptyList();
104         }
105     }
106
107     private List<NormalizedNode<?, ?>> readKeys(final Set<DataSchemaNode> keys) throws ReadingException, IOException {
108         final List<NormalizedNode<?, ?>> newNodes = new ArrayList<>();
109         console.writeLn("Reading keys:");
110         for (final DataSchemaNode key : keys) {
111             final List<NormalizedNode<?, ?>> readKey = new LeafReader(console, getSchemaContext(), getReadConfigNode())
112                     .read((LeafSchemaNode) key);
113             if (readKey.size() != 1) {
114                 final String message = String.format(
115                         "Value for key element %s has to be set. Creation of this entry is canceled.", key.getQName()
116                                 .getLocalName());
117                 LOG.error(message);
118                 throw new ReadingException(message);
119             }
120             newNodes.addAll(readKey);
121         }
122
123         return newNodes;
124     }
125
126     private List<NormalizedNode<?, ?>> readMandatoryNotKeys(final Set<DataSchemaNode> mandatoryNotKeys) throws ReadingException,
127             IOException {
128         final List<NormalizedNode<?, ?>> newNodes = new ArrayList<>();
129         console.writeLn("Reading mandatory not keys nodes:");
130
131         for (final DataSchemaNode mandatoryNode : mandatoryNotKeys) {
132             final List<NormalizedNode<?, ?>> redValue = argumentHandlerRegistry.getGenericReader(getSchemaContext(),
133                     getReadConfigNode()).read(mandatoryNode);
134             if (redValue.isEmpty()) {
135                 final String message = String.format(
136                         "Value for mandatory element %s has to be set. Creation of this entry is canceled.",
137                         mandatoryNode.getQName().getLocalName());
138                 LOG.error(message);
139                 throw new ReadingException(message);
140             }
141             newNodes.addAll(redValue);
142         }
143         return newNodes;
144     }
145
146     private List<NormalizedNode<?, ?>> readNotKeys(final Set<DataSchemaNode> notKeys) throws ReadingException {
147         final List<NormalizedNode<?, ?>> newNodes = new ArrayList<>();
148         for (final DataSchemaNode notKey : notKeys) {
149             newNodes.addAll(argumentHandlerRegistry.getGenericReader(getSchemaContext(), getReadConfigNode()).read(
150                     notKey));
151         }
152         return newNodes;
153     }
154
155     @Override
156     protected ConsoleContext getContext(final ListSchemaNode schemaNode) {
157         return new BaseConsoleContext<ListSchemaNode>(schemaNode) {
158             @Override
159             public Optional<String> getPrompt() {
160                 return Optional.of("[entry]");
161             }
162         };
163     }
164
165 }