Simplify boolean expressions
[netconf.git] / netconf / tools / netconf-cli / src / main / java / org / opendaylight / netconf / cli / commands / CommandDispatcher.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.netconf.cli.commands;
9
10 import com.google.common.base.Function;
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import com.google.common.collect.Collections2;
14 import com.google.common.collect.Lists;
15 import com.google.common.collect.Maps;
16 import java.io.InputStream;
17 import java.util.Collection;
18 import java.util.Collections;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Set;
22 import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
23 import org.opendaylight.netconf.cli.NetconfDeviceConnectionHandler;
24 import org.opendaylight.netconf.cli.NetconfDeviceConnectionManager;
25 import org.opendaylight.netconf.cli.commands.local.Close;
26 import org.opendaylight.netconf.cli.commands.local.Connect;
27 import org.opendaylight.netconf.cli.commands.local.Disconnect;
28 import org.opendaylight.netconf.cli.commands.local.Help;
29 import org.opendaylight.netconf.cli.commands.remote.RemoteCommand;
30 import org.opendaylight.netconf.cli.io.IOUtil;
31 import org.opendaylight.yangtools.yang.common.QName;
32 import org.opendaylight.yangtools.yang.model.api.Module;
33 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
34 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
35 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
36 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
37
38 /**
39  * The registry of available commands local + remote. Created from schema contexts.
40  */
41 public class CommandDispatcher {
42
43     // TODO extract interface
44
45     private final Map<QName, Command> localCommands = Maps.newHashMap();
46     private final Map<String, QName> nameToQNameLocal = Maps.newHashMap();
47
48     private final Map<QName, Command> remoteCommands = Maps.newHashMap();
49     private final Map<String, QName> nameToQNameRemote = Maps.newHashMap();
50
51     public synchronized Map<QName, Command> getCommands() {
52         return Collections.unmodifiableMap(mergeCommands());
53     }
54
55     private Map<QName, Command> mergeCommands() {
56         // TODO cache this merged map
57         return mergeMaps(remoteCommands, localCommands);
58     }
59
60     private Map<String, QName> mergeCommandIds() {
61         // TODO cache this merged map
62         return mergeMaps(nameToQNameRemote, nameToQNameLocal);
63     }
64
65     private <K, V> Map<K, V> mergeMaps(final Map<K, V> remoteMap, final Map<K, V> localMap) {
66         final Map<K, V> mergedCommands = Maps.newHashMap();
67         mergedCommands.putAll(remoteMap);
68         mergedCommands.putAll(localMap);
69         return mergedCommands;
70     }
71
72     public synchronized Set<String> getCommandIds() {
73         return mergeCommandIds().keySet();
74     }
75
76     public synchronized Set<String> getRemoteCommandIds() {
77         return nameToQNameRemote.keySet();
78     }
79
80     public synchronized Optional<Command> getCommand(final String nameWithModule) {
81         final QName commandQName = mergeCommandIds().get(nameWithModule);
82         final Map<QName, Command> qNameCommandMap = mergeCommands();
83         if (commandQName == null || !qNameCommandMap.containsKey(commandQName)) {
84             return Optional.absent();
85         }
86
87         return Optional.of(qNameCommandMap.get(commandQName));
88     }
89
90     public synchronized Optional<Command> getCommand(final QName qualifiedName) {
91         return Optional.fromNullable(mergeCommands().get(qualifiedName));
92     }
93
94     private static Optional<Command> getCommand(final Map<String, QName> commandNameMap,
95                                                 final Map<QName, Command> commands, final String nameWithModule) {
96         final QName qName = commandNameMap.get(nameWithModule);
97         if (qName == null) {
98             return Optional.absent();
99         }
100         final Command command = commands.get(qName);
101         if (command == null) {
102             return Optional.absent();
103         }
104
105         return Optional.of(command);
106     }
107
108     public static final Collection<String> BASE_NETCONF_SCHEMA_PATHS = Lists.newArrayList(
109         "/schema/remote/ietf-netconf.yang",
110         "/schema/common/netconf-cli-ext.yang",
111         "/schema/common/ietf-inet-types.yang");
112
113     public synchronized void addRemoteCommands(final DOMRpcService rpcService, final SchemaContext remoteSchema) {
114         this.addRemoteCommands(rpcService, remoteSchema, parseSchema(BASE_NETCONF_SCHEMA_PATHS));
115     }
116
117     public synchronized void addRemoteCommands(final DOMRpcService rpcService, final SchemaContext remoteSchema,
118                                                final SchemaContext baseNetconfSchema) {
119         for (final SchemaContext context : Lists.newArrayList(remoteSchema, baseNetconfSchema)) {
120             for (final Module module : context.getModules()) {
121                 for (final RpcDefinition rpcDefinition : module.getRpcs()) {
122                     final Command command = RemoteCommand.fromRpc(rpcDefinition, rpcService);
123                     remoteCommands.put(rpcDefinition.getQName(), command);
124                     nameToQNameRemote.put(getCommandName(rpcDefinition, module), rpcDefinition.getQName());
125                 }
126             }
127         }
128     }
129
130     public synchronized void removeRemoteCommands() {
131         remoteCommands.clear();
132         nameToQNameRemote.clear();
133     }
134
135     public static final Collection<String> LOCAL_SCHEMA_PATHS = Lists.newArrayList(
136         "/schema/local/netconf-cli.yang",
137         "/schema/common/netconf-cli-ext.yang",
138         "/schema/common/ietf-inet-types.yang");
139
140     public synchronized void addLocalCommands(final NetconfDeviceConnectionManager connectionManager,
141                                               final SchemaContext localSchema, final Integer connectionTimeout) {
142         for (final Module module : localSchema.getModules()) {
143             for (final RpcDefinition rpcDefinition : module.getRpcs()) {
144
145                 // FIXME make local commands extensible
146                 // e.g. by yang extension defining java class to be instantiated
147                 // problem is with command specific resources
148                 // e.g. Help would need command registry
149                 final Command localCommand;
150                 if (rpcDefinition.getQName().equals(CommandConstants.HELP_QNAME)) {
151                     localCommand = Help.create(rpcDefinition, this);
152                 } else if (rpcDefinition.getQName().equals(CommandConstants.CLOSE_QNAME)) {
153                     localCommand = Close.create(rpcDefinition);
154                 } else if (rpcDefinition.getQName().equals(CommandConstants.CONNECT_QNAME)) {
155                     localCommand = Connect.create(rpcDefinition, connectionManager, connectionTimeout);
156                 } else if (rpcDefinition.getQName().equals(CommandConstants.DISCONNECT_QNAME)) {
157                     localCommand = Disconnect.create(rpcDefinition, connectionManager);
158                 } else {
159                     throw new IllegalStateException(
160                         "No command implementation available for local command: " + rpcDefinition.getQName());
161                 }
162
163                 localCommands.put(localCommand.getCommandId(), localCommand);
164                 nameToQNameLocal.put(getCommandName(rpcDefinition, module), localCommand.getCommandId());
165             }
166         }
167     }
168
169     private static String getCommandName(final RpcDefinition rpcDefinition, final Module module) {
170         return IOUtil.qNameToKeyString(rpcDefinition.getQName(), module.getName());
171     }
172
173     public static SchemaContext parseSchema(final Collection<String> yangPath) {
174         final List<InputStream> streams = loadYangs(yangPath);
175         final SchemaContext schemaContext;
176         try {
177             schemaContext = YangParserTestUtils.parseYangStreams(streams);
178         } catch (ReactorException e) {
179             throw new RuntimeException("Unable to build schema context from " + streams, e);
180         }
181         return schemaContext;
182     }
183
184     private static List<InputStream> loadYangs(final Collection<String> yangPaths) {
185
186         return Lists.newArrayList(Collections2.transform(Lists.newArrayList(yangPaths),
187                 new Function<String, InputStream>() {
188                     @Override
189                     public InputStream apply(final String input) {
190                         final InputStream resourceAsStream = NetconfDeviceConnectionHandler.class
191                             .getResourceAsStream(input);
192                         Preconditions.checkNotNull(resourceAsStream, "File %s was null", input);
193                         return resourceAsStream;
194                     }
195                 }));
196     }
197 }