1e69fbb774832a2805cf4940f3909205482133a8
[controller.git] / opendaylight / netconf / netconf-cli / src / main / java / org / opendaylight / controller / netconf / cli / reader / impl / ChoiceReader.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 static org.opendaylight.controller.netconf.cli.io.IOUtil.isSkipInput;
11
12 import com.google.common.base.Function;
13 import com.google.common.collect.Maps;
14 import java.io.IOException;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Set;
20 import jline.console.completer.Completer;
21 import jline.console.completer.StringsCompleter;
22 import org.opendaylight.controller.netconf.cli.CommandArgHandlerRegistry;
23 import org.opendaylight.controller.netconf.cli.io.BaseConsoleContext;
24 import org.opendaylight.controller.netconf.cli.io.ConsoleContext;
25 import org.opendaylight.controller.netconf.cli.io.ConsoleIO;
26 import org.opendaylight.controller.netconf.cli.reader.AbstractReader;
27 import org.opendaylight.controller.netconf.cli.reader.ReadingException;
28 import org.opendaylight.yangtools.yang.data.api.Node;
29 import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
30 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
31 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
32 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
33 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
34 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
35 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 public class ChoiceReader extends AbstractReader<ChoiceNode> {
40
41     private static final Logger LOG = LoggerFactory.getLogger(ChoiceReader.class);
42
43     private final CommandArgHandlerRegistry argumentHandlerRegistry;
44
45     public ChoiceReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
46             final SchemaContext schemaContext) {
47         super(console, schemaContext);
48         this.argumentHandlerRegistry = argumentHandlerRegistry;
49     }
50
51     public ChoiceReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
52             final SchemaContext schemaContext, final boolean readConfigNode) {
53         super(console, schemaContext, readConfigNode);
54         this.argumentHandlerRegistry = argumentHandlerRegistry;
55     }
56
57     @Override
58     public List<Node<?>> readWithContext(final ChoiceNode choiceNode) throws IOException, ReadingException {
59         final Map<String, ChoiceCaseNode> availableCases = collectAllCases(choiceNode);
60         console.formatLn("Select case for choice %s from: %s", choiceNode.getQName().getLocalName(),
61                 formatSet(availableCases.keySet()));
62
63         ChoiceCaseNode selectedCase = null;
64         final String rawValue = console.read();
65         if (isSkipInput(rawValue)) {
66             return Collections.emptyList();
67         }
68
69         selectedCase = availableCases.get(rawValue);
70         if (selectedCase == null) {
71             final String message = String.format("Incorrect value (%s) for choice %s was selected.", rawValue,
72                     choiceNode.getQName().getLocalName());
73             LOG.error(message);
74             throw new ReadingException(message);
75         }
76
77         return readSelectedCase(selectedCase);
78     }
79
80     protected List<Node<?>> readSelectedCase(final ChoiceCaseNode selectedCase) throws ReadingException {
81         // IF there is a case that contains only one Empty type leaf, create the
82         // leaf without question, since the case was selected
83         if (containsOnlyOneEmptyLeaf(selectedCase)) {
84             final Node<?> newNode = NodeFactory.createImmutableSimpleNode(selectedCase.getChildNodes().iterator()
85                     .next().getQName(), null, null);
86             return Collections.<Node<?>> singletonList(newNode);
87         }
88
89         final List<Node<?>> newNodes = new ArrayList<>();
90         for (final DataSchemaNode schemaNode : selectedCase.getChildNodes()) {
91             newNodes.addAll(argumentHandlerRegistry.getGenericReader(getSchemaContext(), getReadConfigNode()).read(
92                     schemaNode));
93         }
94         return newNodes;
95     }
96
97     private Object formatSet(final Set<String> values) {
98         final StringBuilder formatedValues = new StringBuilder();
99         for (final String value : values) {
100             formatedValues.append("\n  ");
101             formatedValues.append(value);
102         }
103         return formatedValues.toString();
104     }
105
106     private boolean containsOnlyOneEmptyLeaf(final ChoiceCaseNode selectedCase) {
107         if (selectedCase.getChildNodes().size() != 1) {
108             return false;
109         }
110         final DataSchemaNode next = selectedCase.getChildNodes().iterator().next();
111         if (next instanceof LeafSchemaNode) {
112             final TypeDefinition<?> type = ((LeafSchemaNode) next).getType();
113             if (isEmptyType(type)) {
114                 return true;
115             }
116         }
117         return false;
118     }
119
120     private Map<String, ChoiceCaseNode> collectAllCases(final ChoiceNode schemaNode) {
121         return Maps.uniqueIndex(schemaNode.getCases(), new Function<ChoiceCaseNode, String>() {
122             @Override
123             public String apply(final ChoiceCaseNode input) {
124                 return input.getQName().getLocalName();
125             }
126         });
127     }
128
129     @Override
130     protected ConsoleContext getContext(final ChoiceNode schemaNode) {
131         return new BaseConsoleContext<ChoiceNode>(schemaNode) {
132             @Override
133             public List<Completer> getAdditionalCompleters() {
134                 return Collections
135                         .<Completer> singletonList(new StringsCompleter(collectAllCases(schemaNode).keySet()));
136             }
137         };
138     }
139 }