+++ /dev/null
-*.log
-cache
+++ /dev/null
-usage:
-Submit address + port for initial TCP connection (PURE TCP CONNECTIONS ARE NOT SUPPORTED YET)
-Submit username + password in addition to address + port for initial SSH connection
-If no arguments(or unexpected combination) is submitted, cli will be started without initial connection
-To use with ODL controller, run with: java -jar netconf-cli-0.2.5-SNAPSHOT-executable.jar --server localhost --port 1830 --username admin --password admin
-
-Generic cli for netconf devices
-
-optional arguments:
- -h, --help show this help message and exit
-
-TCP:
- Base arguments to initiate TCP connection right away
-
- --server SERVER Netconf device ip-address/domain name
- --port PORT Netconf device port
-
-SSH:
- SSH credentials, if provided, initial connection will be attempted using SSH
-
- --username USERNAME Username for SSH connection
- --password PASSWORD Password for SSH connection
-------------------------------------------------------------------------
-
-To run the cli execute:
-
-java -jar netconf-cli-0.2.5-SNAPSHOT-executable.jar --username user --password password --server serverIP --port optionalPort
-
-The cli will connect to the remote device automatically.
-The initialization may take a few moments depending on the size of schemas provided by the device.
-To view the progress, one can take a look inside netconfcli.log file (All logs are in this file starting with level TRACE).
-Cli does not print any logging messages to the console, only to the file.
-
-------------------------------------------------------------------------
-
-Correct initialization + connection should display following output:
-
-[maros@localhost target]$ java -jar netconf-cli-0.2.5-SNAPSHOT-executable.jar --server localhost --port 1830 --username admin --password admin
-Connecting to localhost via SSH. Please wait.
-Cli is up, available commands:
-
-add-flow(sal-flow) add-group(sal-group)
-add-meter(sal-meter) begin-transaction(sal-remote)
-cancel-commit(ietf-netconf) cancel-toast(toaster)
-clear-toasts-made(toaster-provider-impl) close(netconf-cli)
-close-session(ietf-netconf) commit(ietf-netconf)
-connect(netconf-cli) copy-config(ietf-netconf)
-create-data-change-event-subscription(sal-remote) create-notification-stream(sal-remote)
-delete-config(ietf-netconf) discard-changes(ietf-netconf)
-disconnect(netconf-cli) edit-config(ietf-netconf)
-finish-transaction(flow-capable-transaction) get(ietf-netconf)
-get-aggregate-flow-statistics-from-flow-table-for-all-flows(opendaylight-flow-statistics) get-aggregate-flow-statistics-from-flow-table-for-given-match(opendaylight-flow-statistics)
-get-all-flow-statistics-from-flow-table(opendaylight-flow-statistics) get-all-flows-statistics-from-all-flow-tables(opendaylight-flow-statistics)
-get-all-group-statistics(opendaylight-group-statistics) get-all-meter-config-statistics(opendaylight-meter-statistics)
-get-all-meter-statistics(opendaylight-meter-statistics) get-all-node-connectors-statistics(opendaylight-port-statistics)
-get-all-queues-statistics-from-all-ports(opendaylight-queue-statistics) get-all-queues-statistics-from-given-port(opendaylight-queue-statistics)
-get-config(ietf-netconf) get-dead-events-count(threadpool-impl)
-get-flow-statistics-from-flow-table(opendaylight-flow-statistics) get-flow-tables-statistics(opendaylight-flow-table-statistics)
-get-group-description(opendaylight-group-statistics) get-group-features(opendaylight-group-statistics)
-get-group-statistics(opendaylight-group-statistics) get-meter-features(opendaylight-meter-statistics)
-get-meter-statistics(opendaylight-meter-statistics) get-next-transaction-id(flow-capable-transaction)
-get-node-connector-statistics(opendaylight-port-statistics) get-queue(sal-queue)
-get-queue-statistics-from-given-port(opendaylight-queue-statistics) get-schema(ietf-netconf-monitoring)
-help(netconf-cli) kill-session(ietf-netconf)
-lock(ietf-netconf) make-scrambled-with-wheat(kitchen-service-impl)
-make-toast(toaster) remove-flow(sal-flow)
-remove-group(sal-group) remove-meter(sal-meter)
-reset(config-logging) restock-toaster(toaster)
-shutdown(shutdown-impl) solicit-refresh(flow-topology-discovery)
-transmit-packet(packet-processing) unlock(ietf-netconf)
-update-flow(sal-flow) update-group(sal-group)
-update-meter(sal-meter) update-port(sal-port)
-update-table(sal-table) validate(ietf-netconf)
-
-netconf()>
-
-
-------------------------------------------------------------------------
-
-At this stage, any supported rpc can be invoked. To see all possible rpcs press TAB (serves as autocomplete). The output contains all the commands reported after at start-up
-
-------------------------------------------------------------------------
-
-Example step-by-step execution of get-config rpc:
-
-1. Type get-config, hit TAB, hit enter
-2. Cli will now walk all the input arguments of get-config rpc and ask for value
-3. Cli asks for filter value
-4. Submit filter (using TAB autocomplete) as a schema path or type "skip" (to not add any filter) and hit enter
-5. Cli asks for config source (e.g. which data-store to query)
-6. Use TAB to view options and submit either running or candidate data-store
-7. Cli will display configuration of the remote device e.g. :
-
-data {
- a {
- address {
- last-name a
- first-name o
- street aaaaa
- }
- address {
- last-name a
- first-name t
- }
- address {
- last-name a
- first-name y
- }
- }
-}
-
-
-------------------------------------------------------------------------
+++ /dev/null
-This file contains ODL controller specific examples:
-
-1A. Connecting to ODL controller automatically:
- a. Make sure ODL controller is running on your or any other accessible device
- b. Start the cli using this command (in folder controller/opendaylight/netconf/netconf-cli/target/):
- java -jar netconf-cli-0.2.5-SNAPSHOT-executable.jar --server localhost --port 1830 --username admin --password admin
- c. The cli will start up in aprox. 20 seconds (Schema download might take some time on the first connection, subsequent attempts should take less time)
- d. You should see the list of commands avaliable in the controller e.g.:
- add-flow(sal-flow) add-group(sal-group)
- add-meter(sal-meter) begin-transaction(sal-remote)
- cancel-commit(ietf-netconf) cancel-toast(toaster)
- clear-toasts-made(toaster-provider-impl) close(netconf-cli)
- close-session(ietf-netconf) commit(ietf-netconf)
- connect(netconf-cli) copy-config(ietf-netconf)
- create-data-change-event-subscription(sal-remote) ....
-
-
-1B. Connecting to ODL from the CLI:
- a. Make sure ODL controller is running on your or any other accessible device
- b. Start the cli using this command (in folder controller/opendaylight/netconf/netconf-cli/target/):
- java -jar netconf-cli-0.2.5-SNAPSHOT-executable.jar
- c. The cli will start app right away (few seconds)
- d. You should see only the basic commands e.g. connect, close, help, disconnect
- e. Type connect, hit TAB, hit ENTER
- f. Cli will ask for connect arguments: [address-name, address-port, user-name, user-password]
- g. Address-name
- The cli will ask what type of address you want to provide (domain-name or ip-address). This is caused by the yang model for connect command, the address-name is of type ietf-inet-types:host, which is a union of domain-name and ip-address.
- Submit "domain-name" (TAB can be used for autocompete)
- Now you need to provide value, submit "localhost" (TAB can be used for autocomplete, as "localhost" is the default value)
- h. Address-port
- Submit 1830 (default port for netconf SSH server in ODL)
- i. User-name
- Submit "admin"
- j. User-password
- Submit "admin"
- k. The connection will be up in aprox. 20 seconds (Schema download might take some time on the first connection, subsequent attempts should take less time)
- l. You should see the list of commands available in the controller
-
-
-2. Disconnecting from ODL in the CLI
- a. Execute scenario 1A or 1B
- b. Type "disconn", hit TAB, hit Enter
- c. You should see the following output:
- status Connection disconnected
- d. Use TAB to see available commands, only local commands are present now
- e. Now you can use the connect command(as in 1B) to connect again
-
-
-3. Using help command
- a. Help command can be executed in connected as well as disconnected state
- b. Type "help", hit TAB, hit Enter
- c. You should see the help conent containing the list of all available commands with description for each of them e.g.
- commands {
- commands [id=close(netconf-cli)] {
- id close(netconf-cli)
- description Close the whole cli
- }
- commands [id=help(netconf-cli)] {
- id help(netconf-cli)
- description Display help
- }
- commands [id=disconnect(netconf-cli)] {
- id disconnect(netconf-cli)
- description Disconnect from a netconf device that is currently connected
- }
- commands [id=connect(netconf-cli)] {
- id connect(netconf-cli)
- description Connect to a remote netconf device, if not connected yet. Connection initialization is blocking and might take some time, depending on amount of yang schemas in remote device.
- }
- }
-
-
-4. Executing get-config command (get-config(ietf-netconf))
- a. Execute scenario 1A or 1B
- b. Type "get-config", hit TAB, hit Enter
- c. Cli will ask for get-config arguments: [filter, source]
- d. Filter
- Submit "skip" (This will ignore the filter attribute, ODL does not support filtering at this moment, but will be supported in near future)
- e. Source
- You have to choose from candidate, running, startup. Submit running.
- f. You should see the whole configuration of the ODL e.g.:
- data {
- modules {
- module {
- module [name=toaster-provider-impl] {
- name toaster-provider-impl
- type (urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl?revision=2014-01-31)toaster-provider-impl
- choice configuration (toaster-provider-impl) {
- ...
-
-
-5. Executing get command (get(ietf-netconf))
- a. Execute scenario 1A or 1B
- b. Type "get(", hit TAB, hit Enter
- c. Cli will ask for get arguments: [filter]
- d. Filter
- Submit "skip" (This will ignore the filter attribute, ODL does not support filtering at this moment, but will be supported in near future)
- f. You should see the whole data-tree of the ODL
-
-
-6. Executing edit-config command (edit-config(ietf-netconf))
- a. Execute scenario 1A or 1B
- b. Type "edit", hit TAB, hit Enter
- c. Cli will ask for edit-config arguments: [default-operation, edit-content, error-option, target, test-option]
- d. Config
- Config contains the data to be edited
- 1. First you have to specify a path pointing to a concrete data node. Use TAB to help with autocomplete.
- Submit "modules(config)/module(config)/"
- Module node is of type list and now you have to construct a whole new list entry for the module list.
- 2. The cli will ask for these nodes: [configuration, name, type]
- Name - Submit any name e.g. newModule
- Type - For Type you have to pick from available module types in the ODL, hit TAB for hints
- Submit "threadfactory-naming(threadpool-impl)" to create a new instance of threadfactory in the ODL.
- Configuration - For configuration you have to pick from available module types again
- Submit "threadfactory-naming" to match previous module type
- The cli will now ask for threadfactory-naming specific configuration: [prefix]
- Prefix - Submit any string
-
- The cli will now if you want to create another module entry.
- Submit "N".
- e. Default-operation
- Submit "skip" to skip or pick from available e.g. merge, replace etc.
- f. Error-option
- Submit "skip" to skip option.
- g. Config-target
- This is a choice between running and candidate. Submit candidate to edit configuration only in the candidate datastore.
- h. Test-option
- Submit "skip" to skip option.
- i. You should see OK response
- j. You can check the candidate datastore change by executing get-config command as in scenario 4, but pick candidate as the source.
- k. You should see this module in the output:
- module [name=newModule] {
- name newModule
- type (urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl?revision=2013-04-05)threadfactory-naming
- choice configuration (threadfactory-naming) {
- name-prefix prefix
- }
- }
-
-
-7. Commiting changes from candidate to running datastore
- a. Execute scenario 6.
- b. Type commit, hit TAB, hit Enter
- c. Cli will ask for commit arguments: [confirm-timeout, confirmed, persist, persist-id]. We will skip all these arguments since they are not supported in ODL. Cli should be able to detect this and not ask for them. This is a TODO, by supporting feature/if-feature detection in the CLI.
- d. Confirm-timeout
- Skip
- e. Confirmed
- N
- f. Persist
- Skip
- g. Persist-id
- Skip
- h. You should see OK response
- i. You can check the candidate datastore change by executing get-config command as in scenario 4.
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
-
- This program and the accompanying materials are made available under the
- terms of the Eclipse Public License v1.0 which accompanies this distribution,
- and is available at http://www.eclipse.org/legal/epl-v10.html
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
- <parent>
- <groupId>org.opendaylight.odlparent</groupId>
- <artifactId>odlparent</artifactId>
- <version>2.0.5</version>
- <relativePath/>
- </parent>
-
- <groupId>org.opendaylight.netconf</groupId>
- <artifactId>netconf-cli</artifactId>
- <version>1.4.0-SNAPSHOT</version>
- <packaging>jar</packaging>
- <name>${project.artifactId}</name>
-
- <properties>
- <sonar.skip>true</sonar.skip>
- </properties>
-
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.netconf</groupId>
- <artifactId>netconf-artifacts</artifactId>
- <version>${project.version}</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.mdsal</groupId>
- <artifactId>mdsal-artifacts</artifactId>
- <version>2.4.0-SNAPSHOT</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yangtools-artifacts</artifactId>
- <version>1.2.0</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>mdsal-artifacts</artifactId>
- <version>1.7.0-SNAPSHOT</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
-
- <dependencies>
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-classic</artifactId>
- <!--TODO configure properly -->
- </dependency>
- <dependency>
- <groupId>jline</groupId>
- <artifactId>jline</artifactId>
- <version>2.11</version>
- </dependency>
- <dependency>
- <groupId>net.sourceforge.argparse4j</groupId>
- <artifactId>argparse4j</artifactId>
- <version>0.4.3</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-core-api</artifactId>
- </dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>sal-netconf-connector</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>mockito-configuration</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-data-impl</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-model-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-parser-impl</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-data-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-common</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-test-util</artifactId>
- <scope>compile</scope>
- </dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>netconf-client</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.mdsal</groupId>
- <artifactId>yang-binding</artifactId>
- </dependency>
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- </dependency>
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- <configuration>
- <archive>
- <manifest>
- <mainClass>org.opendaylight.netconf.cli.Main</mainClass>
- </manifest>
- </archive>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-shade-plugin</artifactId>
- <configuration></configuration>
- <executions>
- <execution>
- <goals>
- <goal>shade</goal>
- </goals>
- <phase>package</phase>
- <configuration>
- <transformers>
- <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
- <mainClass>org.opendaylight.netconf.cli.Main</mainClass>
- </transformer>
- </transformers>
- <shadedArtifactAttached>true</shadedArtifactAttached>
- <shadedClassifierName>executable</shadedClassifierName>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-checkstyle-plugin</artifactId>
- <configuration>
- <propertyExpansion>checkstyle.violationSeverity=error</propertyExpansion>
- </configuration>
- </plugin>
- </plugins>
- </build>
-</project>
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import jline.console.UserInterruptException;
-import jline.console.completer.Completer;
-import jline.console.completer.StringsCompleter;
-import org.opendaylight.netconf.cli.commands.Command;
-import org.opendaylight.netconf.cli.commands.CommandConstants;
-import org.opendaylight.netconf.cli.commands.CommandDispatcher;
-import org.opendaylight.netconf.cli.commands.CommandInvocationException;
-import org.opendaylight.netconf.cli.commands.input.Input;
-import org.opendaylight.netconf.cli.commands.input.InputDefinition;
-import org.opendaylight.netconf.cli.commands.output.Output;
-import org.opendaylight.netconf.cli.commands.output.OutputDefinition;
-import org.opendaylight.netconf.cli.io.ConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.cli.reader.ReadingException;
-import org.opendaylight.netconf.cli.writer.OutFormatter;
-import org.opendaylight.netconf.cli.writer.WriteException;
-import org.opendaylight.netconf.cli.writer.Writer;
-import org.opendaylight.netconf.cli.writer.impl.NormalizedNodeWriter;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
-
-/**
- * The top level cli state that dispatches command executions.
- */
-public class Cli implements Runnable {
- private final CommandDispatcher commandRegistry;
- private final CommandArgHandlerRegistry argumentHandlerRegistry;
- private final SchemaContextRegistry schemaContextRegistry;
- private final ConsoleIO consoleIO;
-
- public Cli(final ConsoleIO consoleIO, final CommandDispatcher commandRegistry,
- final CommandArgHandlerRegistry argumentHandlerRegistry,
- final SchemaContextRegistry schemaContextRegistry) {
- this.consoleIO = consoleIO;
- this.commandRegistry = commandRegistry;
- this.argumentHandlerRegistry = argumentHandlerRegistry;
- this.schemaContextRegistry = schemaContextRegistry;
- }
-
- @Override
- public void run() {
- try {
- consoleIO.writeLn("Cli is up, available commands:");
- final RootConsoleContext consoleContext = new RootConsoleContext(commandRegistry);
- consoleIO.enterContext(consoleContext);
- consoleIO.complete();
- consoleIO.writeLn("");
-
- while (true) {
- final String commandName = consoleIO.read();
- final Optional<Command> commandOpt = commandRegistry.getCommand(commandName);
-
- if (!commandOpt.isPresent()) {
- continue;
- }
-
- final Command command = commandOpt.get();
- try {
- consoleIO.enterContext(command.getConsoleContext());
- final Output response = command.invoke(handleInput(command.getInputDefinition()));
- handleOutput(command, response);
- } catch (final CommandInvocationException e) {
- consoleIO.write(e.getMessage());
- } catch (final UserInterruptException e) {
- consoleIO.writeLn("Command " + command.getCommandId() + " was terminated.");
- } finally {
- consoleIO.leaveContext();
- }
-
- }
- } catch (final IOException e) {
- throw new RuntimeException("IO failure", e);
- }
- }
-
- private void handleOutput(final Command command, final Output response) {
- final OutputDefinition outputDefinition = command.getOutputDefinition();
-
- final Writer<DataSchemaNode> outHandler = argumentHandlerRegistry.getGenericWriter();
- if (outputDefinition.isEmpty()) {
- handleEmptyOutput(command, response);
- } else {
- handleRegularOutput(response, outputDefinition, outHandler);
- }
- }
-
- private void handleRegularOutput(final Output response, final OutputDefinition outputDefinition,
- final Writer<DataSchemaNode> outHandler) {
- final Map<DataSchemaNode, List<NormalizedNode<?, ?>>> unwrap = response.unwrap(outputDefinition);
-
- for (final DataSchemaNode schemaNode : unwrap.keySet()) {
- Preconditions.checkNotNull(schemaNode);
-
- try {
-
- // FIXME move custom writer to GenericWriter/Serializers ...
- // this checks only first level
- final Optional<Class<? extends Writer<DataSchemaNode>>> customReaderClassOpt = tryGetCustomHandler(
- schemaNode);
-
- if (customReaderClassOpt.isPresent()) {
- final Writer<DataSchemaNode> customReaderInstance = argumentHandlerRegistry
- .getCustomWriter(customReaderClassOpt.get());
- Preconditions.checkNotNull(customReaderInstance, "Unknown custom writer: %s",
- customReaderClassOpt.get());
- customReaderInstance.write(schemaNode, unwrap.get(schemaNode));
- } else {
- outHandler.write(schemaNode, unwrap.get(schemaNode));
- }
-
- } catch (final WriteException e) {
- throw new IllegalStateException("Unable to write value for: " + schemaNode.getQName() + " from: "
- + unwrap.get(schemaNode), e);
- }
- }
- }
-
- private void handleEmptyOutput(final Command command, final Output response) {
- try {
- new NormalizedNodeWriter(consoleIO, new OutFormatter()).write(null,
- Collections.<NormalizedNode<?, ?>>singletonList(response.getOutput()));
- } catch (final WriteException e) {
- throw new IllegalStateException("Unable to write value for: " + response.getOutput().getNodeType()
- + " from: " + command.getCommandId(), e);
- }
- }
-
- private Input handleInput(final InputDefinition inputDefinition) {
- List<NormalizedNode<?, ?>> allArgs = Collections.emptyList();
- try {
- if (!inputDefinition.isEmpty()) {
- allArgs = argumentHandlerRegistry.getGenericReader(schemaContextRegistry.getLocalSchemaContext()).read(
- inputDefinition.getInput());
- }
- } catch (final ReadingException e) {
- throw new IllegalStateException("Unable to read value for: " + inputDefinition.getInput().getQName(), e);
- }
-
- return new Input(allArgs);
- }
-
- // TODO move tryGet to GenericWriter, GenericReader has the same code
- private <T> Optional<Class<? extends T>> tryGetCustomHandler(final DataSchemaNode dataSchemaNode) {
-
- for (final UnknownSchemaNode unknownSchemaNode : dataSchemaNode.getUnknownSchemaNodes()) {
-
- if (isExtenstionForCustomHandler(unknownSchemaNode)) {
- final String argumentHandlerClassName = unknownSchemaNode.getNodeParameter();
- try {
- final Class<?> argumentClass = Class.forName(argumentHandlerClassName);
- // TODO add check before cast
- return Optional.of((Class<? extends T>) argumentClass);
- } catch (final ClassNotFoundException e) {
- throw new IllegalArgumentException("Unknown custom reader class " + argumentHandlerClassName
- + " for: " + dataSchemaNode.getQName());
- }
- }
- }
-
- return Optional.absent();
- }
-
- private boolean isExtenstionForCustomHandler(final UnknownSchemaNode unknownSchemaNode) {
- final QName qName = unknownSchemaNode.getExtensionDefinition().getQName();
- return qName.equals(CommandConstants.ARG_HANDLER_EXT_QNAME);
- }
-
- private static final class RootConsoleContext implements ConsoleContext {
-
- private final Completer completer;
-
- RootConsoleContext(final CommandDispatcher commandRegistry) {
- completer = new CommandCompleter(commandRegistry);
- }
-
- @Override
- public Completer getCompleter() {
- return completer;
- }
-
- @Override
- public Optional<String> getPrompt() {
- return Optional.absent();
- }
-
- private class CommandCompleter extends StringsCompleter {
-
- private final CommandDispatcher commandRegistry;
-
- CommandCompleter(final CommandDispatcher commandRegistry) {
- this.commandRegistry = commandRegistry;
- }
-
- @Override
- public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
- getStrings().clear();
- getStrings().addAll(commandRegistry.getCommandIds());
- return super.complete(buffer, cursor, candidates);
- }
- }
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
-import java.util.Map;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.cli.reader.Reader;
-import org.opendaylight.netconf.cli.reader.custom.ConfigReader;
-import org.opendaylight.netconf.cli.reader.custom.EditContentReader;
-import org.opendaylight.netconf.cli.reader.custom.FilterReader;
-import org.opendaylight.netconf.cli.reader.custom.PasswordReader;
-import org.opendaylight.netconf.cli.reader.impl.GenericReader;
-import org.opendaylight.netconf.cli.writer.OutFormatter;
-import org.opendaylight.netconf.cli.writer.Writer;
-import org.opendaylight.netconf.cli.writer.custom.DataWriter;
-import org.opendaylight.netconf.cli.writer.impl.NormalizedNodeWriter;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-/**
- * Keeps custom and generic input/output arguments handlers. Custom handlers are
- * constructed lazily, due to remote schema context acquisition.
- */
-public class CommandArgHandlerRegistry {
-
- private final ConsoleIO consoleIO;
- private final SchemaContextRegistry schemaContextRegistry;
-
- private final Map<Class<? extends Reader<? extends DataSchemaNode>>, ReaderProvider> customReaders = Maps
- .newHashMap();
- private final Map<Class<? extends Writer<DataSchemaNode>>, WriterProvider> customWriters = Maps.newHashMap();
-
- public CommandArgHandlerRegistry(final ConsoleIO consoleIO, final SchemaContextRegistry schemaContextRegistry) {
- this.consoleIO = consoleIO;
- this.schemaContextRegistry = schemaContextRegistry;
-
- setUpReaders();
- setUpWriters();
- }
-
- private void setUpWriters() {
- customWriters.put(DataWriter.class, new DataWriterProvider());
- }
-
- private void setUpReaders() {
- customReaders.put(PasswordReader.class, new PasswordReaderProvider());
- customReaders.put(FilterReader.class, new FilterReaderProvider());
- customReaders.put(ConfigReader.class, new ConfigReaderProvider());
- customReaders.put(EditContentReader.class, new EditContentReaderProvider());
- }
-
- public synchronized Reader<? extends DataSchemaNode> getCustomReader(
- final Class<? extends Reader<DataSchemaNode>> readerType) {
- return customReaders.get(readerType).provide(consoleIO, this, schemaContextRegistry);
- }
-
- private static SchemaContext getRemoteSchema(final Class<?> handlerType,
- final SchemaContextRegistry schemaContextRegistry) {
- final Optional<SchemaContext> remoteSchemaContext = schemaContextRegistry.getRemoteSchemaContext();
- Preconditions.checkState(remoteSchemaContext.isPresent(),
- "Remote schema context not acquired yet, cannot get handler %s", handlerType);
- return remoteSchemaContext.get();
- }
-
- public synchronized Reader<DataSchemaNode> getGenericReader(final SchemaContext schemaContext) {
- return new GenericReader(consoleIO, this, schemaContext);
- }
-
- public synchronized Reader<DataSchemaNode> getGenericReader(final SchemaContext schemaContext,
- final boolean readConfigNode) {
- return new GenericReader(consoleIO, this, schemaContext, readConfigNode);
- }
-
- public synchronized Writer<DataSchemaNode> getCustomWriter(
- final Class<? extends Writer<DataSchemaNode>> writerType) {
- return customWriters.get(writerType).provide(
- consoleIO, getRemoteSchema(writerType, schemaContextRegistry), this);
- }
-
- public synchronized Writer<DataSchemaNode> getGenericWriter() {
- return new NormalizedNodeWriter(consoleIO, new OutFormatter());
- }
-
- /**
- * Reader providers, in order to construct readers lazily.
- */
- private interface ReaderProvider {
- Reader<? extends DataSchemaNode> provide(ConsoleIO consoleIO,
- CommandArgHandlerRegistry commandArgHandlerRegistry,
- SchemaContextRegistry schemaContextRegistry);
- }
-
- private static final class FilterReaderProvider implements ReaderProvider {
- @Override
- public Reader<? extends DataSchemaNode> provide(final ConsoleIO consoleIO,
- final CommandArgHandlerRegistry commandArgHandlerRegistry,
- final SchemaContextRegistry schemaContextRegistry) {
- return new FilterReader(consoleIO, getRemoteSchema(FilterReader.class, schemaContextRegistry));
- }
- }
-
- private static final class ConfigReaderProvider implements ReaderProvider {
- @Override
- public Reader<? extends DataSchemaNode> provide(final ConsoleIO consoleIO,
- final CommandArgHandlerRegistry commandArgHandlerRegistry,
- final SchemaContextRegistry schemaContextRegistry) {
- return new ConfigReader(consoleIO, getRemoteSchema(ConfigReader.class, schemaContextRegistry),
- commandArgHandlerRegistry);
- }
- }
-
- private static final class EditContentReaderProvider implements ReaderProvider {
- @Override
- public Reader<? extends DataSchemaNode> provide(final ConsoleIO consoleIO,
- final CommandArgHandlerRegistry commandArgHandlerRegistry,
- final SchemaContextRegistry schemaContextRegistry) {
- return new EditContentReader(consoleIO, commandArgHandlerRegistry, getRemoteSchema(EditContentReader.class,
- schemaContextRegistry));
- }
- }
-
- private static final class PasswordReaderProvider implements ReaderProvider {
- @Override
- public Reader<? extends DataSchemaNode> provide(final ConsoleIO consoleIO,
- final CommandArgHandlerRegistry commandArgHandlerRegistry,
- final SchemaContextRegistry schemaContextRegistry) {
- return new PasswordReader(consoleIO, schemaContextRegistry.getLocalSchemaContext());
- }
- }
-
- /**
- * Writer providers, in order to construct readers lazily.
- */
- private interface WriterProvider {
- Writer<DataSchemaNode> provide(ConsoleIO consoleIO, SchemaContext schema,
- CommandArgHandlerRegistry commandArgHandlerRegistry);
- }
-
- private class DataWriterProvider implements WriterProvider {
- @Override
- public Writer<DataSchemaNode> provide(final ConsoleIO consoleIO, final SchemaContext schema,
- final CommandArgHandlerRegistry commandArgHandlerRegistry) {
- return new DataWriter(consoleIO, new OutFormatter(), schema);
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli;
-
-import static com.google.common.base.Throwables.getStackTraceAsString;
-
-import com.google.common.base.Preconditions;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.UnknownHostException;
-import net.sourceforge.argparse4j.ArgumentParsers;
-import net.sourceforge.argparse4j.inf.ArgumentGroup;
-import net.sourceforge.argparse4j.inf.ArgumentParser;
-import net.sourceforge.argparse4j.inf.ArgumentParserException;
-import net.sourceforge.argparse4j.inf.Namespace;
-import org.opendaylight.netconf.cli.commands.CommandDispatcher;
-import org.opendaylight.netconf.cli.commands.local.Connect;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.cli.io.ConsoleIOImpl;
-import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
-import org.opendaylight.netconf.client.conf.NetconfClientConfigurationBuilder;
-import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.LoginPasswordHandler;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-/**
- * Parse arguments, start remote device connection and start CLI after the
- * connection is fully up.
- */
-public class Main {
-
- @SuppressWarnings("illegalCatch")
- public static void main(final String[] args) {
- final CliArgumentParser cliArgs = new CliArgumentParser();
- try {
- cliArgs.parse(args);
- } catch (final ArgumentParserException e) {
- // Just end the cli, exception was handled by the CliArgumentParser
- return;
- }
-
- final ConsoleIO consoleIO;
- try {
- consoleIO = new ConsoleIOImpl();
- } catch (final IOException e) {
- handleStartupException(e);
- return;
- }
-
- final SchemaContext localSchema = CommandDispatcher.parseSchema(CommandDispatcher.LOCAL_SCHEMA_PATHS);
- final SchemaContextRegistry schemaContextRegistry = new SchemaContextRegistry(localSchema);
-
- final CommandDispatcher commandDispatcher = new CommandDispatcher();
- final CommandArgHandlerRegistry argumentHandlerRegistry = new CommandArgHandlerRegistry(consoleIO,
- schemaContextRegistry);
- final NetconfDeviceConnectionManager connectionManager = new NetconfDeviceConnectionManager(commandDispatcher,
- argumentHandlerRegistry, schemaContextRegistry, consoleIO);
-
- commandDispatcher.addLocalCommands(connectionManager, localSchema, cliArgs.getConnectionTimeoutMs());
-
- switch (cliArgs.connectionArgsPresent()) {
- case TCP:
- // FIXME support pure TCP
- handleRunningException(new UnsupportedOperationException(
- "PURE TCP CONNECTIONS ARE NOT SUPPORTED YET, "
- + "USE SSH INSTEAD BY PROVIDING USERNAME AND PASSWORD AS WELL"));
- return;
- case SSH:
- writeStatus(consoleIO, "Connecting to %s via SSH. Please wait.", cliArgs.getAddress());
- connectionManager.connectBlocking(cliArgs.getAddress(), cliArgs.getServerAddress(),
- getClientSshConfig(cliArgs));
- break;
- case NONE:
- /* Do not connect initially */
- writeStatus(consoleIO, "No initial connection. To connect use the connect command");
- break;
- default:
- // NOOP
- break;
- }
-
- try {
- new Cli(consoleIO, commandDispatcher, argumentHandlerRegistry, schemaContextRegistry).run();
- } catch (final Exception e) {
- // TODO Running exceptions have to be handled properly
- handleRunningException(e);
- System.exit(0);
- }
- }
-
- private static NetconfClientConfigurationBuilder getClientConfig(final CliArgumentParser cliArgs) {
- return NetconfClientConfigurationBuilder.create().withAddress(cliArgs.getServerAddress())
- .withConnectionTimeoutMillis(cliArgs.getConnectionTimeoutMs())
- .withReconnectStrategy(Connect.getReconnectStrategy())
- .withProtocol(NetconfClientConfiguration.NetconfClientProtocol.TCP);
- }
-
- private static NetconfClientConfigurationBuilder getClientSshConfig(final CliArgumentParser cliArgs) {
- return NetconfClientConfigurationBuilder.create().withAddress(cliArgs.getServerAddress())
- .withConnectionTimeoutMillis(cliArgs.getConnectionTimeoutMs())
- .withReconnectStrategy(Connect.getReconnectStrategy())
- .withAuthHandler(cliArgs.getCredentials())
- .withProtocol(NetconfClientConfiguration.NetconfClientProtocol.SSH);
- }
-
- private static void handleStartupException(final IOException exc) {
- handleException(exc, "Unable to initialize CLI");
- }
-
- private static void handleException(final Exception exc, final String message) {
- System.console().writer().println(
- String.format("Error %s cause %s", message, getStackTraceAsString(exc.fillInStackTrace())));
- }
-
- private static void writeStatus(final ConsoleIO io, final String blueprint, final Object... args) {
- try {
- io.formatLn(blueprint, args);
- } catch (final IOException e) {
- handleStartupException(e);
- }
- }
-
- private static void handleRunningException(final Exception exc) {
- handleException(exc, "Unexpected CLI runtime exception");
- }
-
- private static final class CliArgumentParser {
-
- public static final String USERNAME = "username";
- public static final String PASSWORD = "password";
- public static final String SERVER = "server";
- public static final String PORT = "port";
-
- public static final String CONNECT_TIMEOUT = "connectionTimeout";
- public static final int DEFAULT_CONNECTION_TIMEOUT_MS = 50000;
-
- private final ArgumentParser parser;
- private Namespace parsed;
-
- @SuppressWarnings("checkstyle:lineLength")
- private CliArgumentParser() {
- parser = ArgumentParsers.newArgumentParser("Netconf cli").defaultHelp(true)
- .description("Generic cli for netconf devices")
- .usage("Submit address + port for initial TCP connection (PURE TCP CONNECTIONS ARE NOT SUPPORTED YET)\n"
- + "Submit username + password in addition to address + port for initial SSH connection\n"
- + "If no arguments(or unexpected combination) is submitted, cli will be started without initial connection\n"
- + "To use with ODL controller, run with: java -jar netconf-cli-0.2.5-SNAPSHOT-executable.jar --server localhost --port 1830 --username admin --password admin");
-
- final ArgumentGroup tcpGroup = parser.addArgumentGroup("TCP")
- .description("Base arguments to initiate TCP connection right away");
-
- tcpGroup.addArgument("--" + SERVER).help("Netconf device ip-address/domain name");
- tcpGroup.addArgument("--" + PORT).type(Integer.class).help("Netconf device port");
- tcpGroup.addArgument("--" + CONNECT_TIMEOUT)
- .type(Integer.class)
- .setDefault(DEFAULT_CONNECTION_TIMEOUT_MS)
- .help("Timeout(in ms) for connection to succeed, if the connection is not fully established by the time is up, "
- + "connection attempt is considered a failure. This attribute is not working as expected yet");
-
- final ArgumentGroup sshGroup = parser.addArgumentGroup("SSH")
- .description("SSH credentials, if provided, initial connection will be attempted using SSH");
-
- sshGroup.addArgument("--" + USERNAME).help("Username for SSH connection");
- sshGroup.addArgument("--" + PASSWORD).help("Password for SSH connection");
- }
-
- public void parse(final String[] args) throws ArgumentParserException {
- try {
- this.parsed = parser.parseArgs(args);
- } catch (final ArgumentParserException e) {
- parser.handleError(e);
- throw e;
- }
- }
-
- public InetSocketAddress getServerAddress() {
- try {
- return new InetSocketAddress(InetAddress.getByName(getAddress()), getPort());
- } catch (final UnknownHostException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- private Integer getPort() {
- checkParsed();
- return parsed.getInt(PORT);
- }
-
- private String getAddress() {
- checkParsed();
- return getString(SERVER);
- }
-
- private Integer getConnectionTimeoutMs() {
- checkParsed();
- return parsed.getInt(CONNECT_TIMEOUT);
- }
-
- private void checkParsed() {
- Preconditions.checkState(parsed != null, "No arguments were parsed yet");
- }
-
- public String getUsername() {
- checkParsed();
- return getString(USERNAME);
- }
-
- private String getString(final String key) {
- return parsed.getString(key);
- }
-
- public LoginPasswordHandler getCredentials() {
- return new LoginPasswordHandler(getUsername(), getPassword());
- }
-
- public String getPassword() {
- checkParsed();
- return getString(PASSWORD);
- }
-
- public InitialConnectionType connectionArgsPresent() {
- if (getAddress() != null && getPort() != null) {
- if (getUsername() != null && getPassword() != null) {
- return InitialConnectionType.SSH;
- }
- return InitialConnectionType.TCP;
- }
- return InitialConnectionType.NONE;
- }
-
- enum InitialConnectionType {
- TCP, SSH, NONE
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli;
-
-import com.google.common.base.Optional;
-import jline.console.completer.Completer;
-import jline.console.completer.NullCompleter;
-import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
-import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
-import org.opendaylight.netconf.cli.commands.CommandDispatcher;
-import org.opendaylight.netconf.cli.io.ConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-/**
- * Implementation of RemoteDeviceHandler. Integrates cli with
- * sal-netconf-connector.
- */
-public class NetconfDeviceConnectionHandler implements RemoteDeviceHandler<NetconfSessionPreferences> {
-
- private final CommandDispatcher commandDispatcher;
- private final SchemaContextRegistry schemaContextRegistry;
- private final ConsoleIO console;
- private final String deviceId;
-
- private boolean up = false;
-
- public NetconfDeviceConnectionHandler(final CommandDispatcher commandDispatcher,
- final SchemaContextRegistry schemaContextRegistry, final ConsoleIO console, final String deviceId) {
- this.commandDispatcher = commandDispatcher;
- this.schemaContextRegistry = schemaContextRegistry;
- this.console = console;
- this.deviceId = deviceId;
- }
-
- @Override
- public synchronized void onDeviceConnected(final SchemaContext context,
- final NetconfSessionPreferences preferences, final DOMRpcService rpcService) {
- console.enterRootContext(new ConsoleContext() {
-
- @Override
- public Optional<String> getPrompt() {
- return Optional.of(deviceId);
- }
-
- @Override
- public Completer getCompleter() {
- return new NullCompleter();
- }
- });
-
- // TODO Load schemas for base netconf + inet types from remote device if
- // possible
- // TODO detect netconf base version
- // TODO detect inet types version
- commandDispatcher.addRemoteCommands(rpcService, context);
- schemaContextRegistry.setRemoteSchemaContext(context);
- up = true;
- this.notify();
- }
-
- /**
- * Check if device is up.
- *
- * @return true if connection was fully established
- */
- public synchronized boolean isUp() {
- return up;
- }
-
- @Override
- public synchronized void onDeviceDisconnected() {
- console.leaveRootContext();
- commandDispatcher.removeRemoteCommands();
- schemaContextRegistry.setRemoteSchemaContext(null);
- up = false;
- }
-
- @Override
- public void onDeviceFailed(Throwable throwable) {
- // FIXME
- }
-
- @Override
- public void onNotification(DOMNotification domNotification) {}
-
- @Override
- public void close() {
- // FIXME
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli;
-
-import com.google.common.base.Preconditions;
-import io.netty.channel.nio.NioEventLoopGroup;
-import io.netty.util.HashedWheelTimer;
-import java.io.Closeable;
-import java.io.File;
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.util.Set;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import org.opendaylight.netconf.cli.commands.CommandDispatcher;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.client.NetconfClientDispatcherImpl;
-import org.opendaylight.netconf.client.conf.NetconfClientConfigurationBuilder;
-import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice;
-import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice.SchemaResourcesDTO;
-import org.opendaylight.netconf.sal.connect.netconf.NetconfDeviceBuilder;
-import org.opendaylight.netconf.sal.connect.netconf.NetconfStateSchemasResolverImpl;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
-import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory;
-import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceFilter;
-import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
-import org.opendaylight.yangtools.yang.model.repo.util.FilesystemSchemaSourceCache;
-import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
-import org.opendaylight.yangtools.yang.parser.util.TextToASTTransformer;
-
-/**
- * Manages connect/disconnect to 1 remote device.
- */
-public class NetconfDeviceConnectionManager implements Closeable {
-
- private final CommandDispatcher commandDispatcher;
- private final SchemaContextRegistry schemaContextRegistry;
- private final ConsoleIO console;
-
- private final ExecutorService executor;
- private final NioEventLoopGroup nettyThreadGroup;
- private final NetconfClientDispatcherImpl netconfClientDispatcher;
-
- private static final String CACHE = "cache/schema";
- private static final int RPC_LIMIT = 0;
-
- // Connection
- private NetconfDeviceConnectionHandler handler;
- private NetconfDevice device;
- private NetconfDeviceCommunicator listener;
-
- public NetconfDeviceConnectionManager(final CommandDispatcher commandDispatcher,
- final CommandArgHandlerRegistry argumentHandlerRegistry, final SchemaContextRegistry schemaContextRegistry,
- final ConsoleIO consoleIO) {
- this.commandDispatcher = commandDispatcher;
- this.schemaContextRegistry = schemaContextRegistry;
- this.console = consoleIO;
-
- executor = Executors.newSingleThreadExecutor();
- nettyThreadGroup = new NioEventLoopGroup();
- netconfClientDispatcher = new NetconfClientDispatcherImpl(nettyThreadGroup, nettyThreadGroup,
- new HashedWheelTimer());
- }
-
- // TODO we receive configBuilder in order to add SessionListener, Session
- // Listener should not be part of config
- public synchronized void connect(final String name, final InetSocketAddress address,
- final NetconfClientConfigurationBuilder configBuilder) {
- // TODO change IllegalState exceptions to custom ConnectionException
- Preconditions.checkState(listener == null, "Already connected");
-
- final RemoteDeviceId deviceId = new RemoteDeviceId(name, address);
-
- handler = new NetconfDeviceConnectionHandler(commandDispatcher, schemaContextRegistry,
- console, name);
-
- final SharedSchemaRepository repository = new SharedSchemaRepository("repo");
- final SchemaContextFactory schemaContextFactory = repository
- .createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT);
- final FilesystemSchemaSourceCache<YangTextSchemaSource> cache = new FilesystemSchemaSourceCache<>(
- repository, YangTextSchemaSource.class, new File(CACHE));
- repository.registerSchemaSourceListener(cache);
- repository.registerSchemaSourceListener(TextToASTTransformer.create(repository, repository));
- final SchemaResourcesDTO schemaResourcesDTO = new SchemaResourcesDTO(
- repository, repository, schemaContextFactory, new NetconfStateSchemasResolverImpl());
-
- device = new NetconfDeviceBuilder()
- .setReconnectOnSchemasChange(true)
- .setSchemaResourcesDTO(schemaResourcesDTO)
- .setGlobalProcessingExecutor(executor)
- .setId(deviceId)
- .setSalFacade(handler)
- .build();
- listener = new NetconfDeviceCommunicator(deviceId, device, RPC_LIMIT);
-
- configBuilder.withSessionListener(listener);
- listener.initializeRemoteConnection(netconfClientDispatcher, configBuilder.build());
- }
-
- /**
- * Blocks thread until connection is fully established.
- */
- public synchronized Set<String> connectBlocking(final String name, final InetSocketAddress address,
- final NetconfClientConfigurationBuilder configBuilder) {
- this.connect(name, address, configBuilder);
- synchronized (handler) {
- while (!handler.isUp()) {
- try {
- // TODO implement Timeout for unsuccessful connection
- handler.wait();
- } catch (final InterruptedException e) {
- Thread.currentThread().interrupt();
- throw new IllegalArgumentException(e);
- }
- }
- }
-
- return commandDispatcher.getRemoteCommandIds();
- }
-
- public synchronized void disconnect() {
- Preconditions.checkState(listener != null, "Not connected yet");
- Preconditions.checkState(handler.isUp(), "Not connected yet");
- listener.close();
- listener = null;
- device = null;
- handler.close();
- handler = null;
- }
-
- @Override
- public void close() throws IOException {
- executor.shutdownNow();
- nettyThreadGroup.shutdownGracefully();
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli;
-
-import com.google.common.base.Optional;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-/**
- * Contains the local schema context (containing local commands) and remote schema context (remote commands)
- *
- * <p>
- * Remote commands are set only after the connection is fully established. So classes using the remote schema context
- */
-public class SchemaContextRegistry {
-
- private final SchemaContext localSchemaContext;
- private SchemaContext remoteSchemaContext;
-
- public SchemaContextRegistry(final SchemaContext localSchemaContext) {
- this.localSchemaContext = localSchemaContext;
- }
-
- public synchronized Optional<SchemaContext> getRemoteSchemaContext() {
- return Optional.fromNullable(remoteSchemaContext);
- }
-
- public SchemaContext getLocalSchemaContext() {
- return localSchemaContext;
- }
-
- public synchronized void setRemoteSchemaContext(final SchemaContext remoteSchemaContext) {
- this.remoteSchemaContext = remoteSchemaContext;
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.commands;
-
-import com.google.common.base.Optional;
-import jline.console.completer.Completer;
-import jline.console.completer.NullCompleter;
-import org.opendaylight.netconf.cli.commands.input.InputDefinition;
-import org.opendaylight.netconf.cli.commands.output.OutputDefinition;
-import org.opendaylight.netconf.cli.io.ConsoleContext;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
-
-public abstract class AbstractCommand implements Command {
-
- private final QName qualifiedName;
- private final InputDefinition args;
- private final OutputDefinition output;
- private final String description;
-
- public AbstractCommand(final QName qualifiedName, final InputDefinition args, final OutputDefinition output,
- final String description) {
- this.qualifiedName = qualifiedName;
- this.args = args;
- this.output = output;
- this.description = description;
- }
-
- protected static OutputDefinition getOutputDefinition(final RpcDefinition rpcDefinition) {
- final ContainerSchemaNode output = rpcDefinition.getOutput();
- return output != null ? OutputDefinition.fromOutput(output) : OutputDefinition.empty();
- }
-
- @Override
- public OutputDefinition getOutputDefinition() {
- return output;
- }
-
- protected static InputDefinition getInputDefinition(final RpcDefinition rpcDefinition) {
- final ContainerSchemaNode input = rpcDefinition.getInput();
- return InputDefinition.fromInput(input);
- }
-
- @Override
- public InputDefinition getInputDefinition() {
- return args;
- }
-
- @Override
- public QName getCommandId() {
- return qualifiedName;
- }
-
- @Override
- public ConsoleContext getConsoleContext() {
- return new ConsoleContext() {
-
- @Override
- public Completer getCompleter() {
- return new NullCompleter();
- }
-
- @Override
- public Optional<String> getPrompt() {
- return Optional.of(qualifiedName.getLocalName());
- }
- };
- }
-
- @Override
- public Optional<String> getCommandDescription() {
- return Optional.fromNullable(description);
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.commands;
-
-import com.google.common.base.Optional;
-import org.opendaylight.netconf.cli.commands.input.Input;
-import org.opendaylight.netconf.cli.commands.input.InputDefinition;
-import org.opendaylight.netconf.cli.commands.output.Output;
-import org.opendaylight.netconf.cli.commands.output.OutputDefinition;
-import org.opendaylight.netconf.cli.io.ConsoleContext;
-import org.opendaylight.yangtools.yang.common.QName;
-
-/**
- * Local command e.g. help or remote rpc e.g. get-config must conform to this interface
- */
-public interface Command {
-
- Output invoke(Input inputArgs) throws CommandInvocationException;
-
- InputDefinition getInputDefinition();
-
- OutputDefinition getOutputDefinition();
-
- QName getCommandId();
-
- Optional<String> getCommandDescription();
-
- ConsoleContext getConsoleContext();
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.commands;
-
-import java.net.URI;
-import org.opendaylight.netconf.cli.io.IOUtil;
-import org.opendaylight.yangtools.yang.common.QName;
-
-public class CommandConstants {
-
- // Local command ids are defined here, this links the implementation to the rpc definition in yang
- // Better way needs to be found to provide this link instead of hardcoded QNames (e.g. yang extension)
- public static final QName HELP_QNAME = QName.create(
- URI.create("netconf:cli"), IOUtil.parseDate("2014-05-22"), "help");
- public static final QName CLOSE_QNAME = QName.create(HELP_QNAME, "close");
- public static final QName CONNECT_QNAME = QName.create(HELP_QNAME, "connect");
- public static final QName DISCONNECT_QNAME = QName.create(CONNECT_QNAME, "disconnect");
-
- public static final QName ARG_HANDLER_EXT_QNAME = QName.create(
- URI.create("urn:ietf:params:xml:ns:netconf:base:1.0:cli"), IOUtil.parseDate("2014-05-26"),
- "argument-handler");
-
- public static final QName NETCONF_BASE_QNAME = QName.create("urn:ietf:params:xml:ns:netconf:base:1.0", "2011-06-01",
- "netconf");
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.commands;
-
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import java.io.InputStream;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
-import org.opendaylight.netconf.cli.NetconfDeviceConnectionHandler;
-import org.opendaylight.netconf.cli.NetconfDeviceConnectionManager;
-import org.opendaylight.netconf.cli.commands.local.Close;
-import org.opendaylight.netconf.cli.commands.local.Connect;
-import org.opendaylight.netconf.cli.commands.local.Disconnect;
-import org.opendaylight.netconf.cli.commands.local.Help;
-import org.opendaylight.netconf.cli.commands.remote.RemoteCommand;
-import org.opendaylight.netconf.cli.io.IOUtil;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
-import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
-
-/**
- * The registry of available commands local + remote. Created from schema contexts.
- */
-public class CommandDispatcher {
-
- // TODO extract interface
-
- private final Map<QName, Command> localCommands = Maps.newHashMap();
- private final Map<String, QName> nameToQNameLocal = Maps.newHashMap();
-
- private final Map<QName, Command> remoteCommands = Maps.newHashMap();
- private final Map<String, QName> nameToQNameRemote = Maps.newHashMap();
-
- public synchronized Map<QName, Command> getCommands() {
- return Collections.unmodifiableMap(mergeCommands());
- }
-
- private Map<QName, Command> mergeCommands() {
- // TODO cache this merged map
- return mergeMaps(remoteCommands, localCommands);
- }
-
- private Map<String, QName> mergeCommandIds() {
- // TODO cache this merged map
- return mergeMaps(nameToQNameRemote, nameToQNameLocal);
- }
-
- private <K, V> Map<K, V> mergeMaps(final Map<K, V> remoteMap, final Map<K, V> localMap) {
- final Map<K, V> mergedCommands = Maps.newHashMap();
- mergedCommands.putAll(remoteMap);
- mergedCommands.putAll(localMap);
- return mergedCommands;
- }
-
- public synchronized Set<String> getCommandIds() {
- return mergeCommandIds().keySet();
- }
-
- public synchronized Set<String> getRemoteCommandIds() {
- return nameToQNameRemote.keySet();
- }
-
- public synchronized Optional<Command> getCommand(final String nameWithModule) {
- final QName commandQName = mergeCommandIds().get(nameWithModule);
- final Map<QName, Command> qNameCommandMap = mergeCommands();
- if (commandQName == null || !qNameCommandMap.containsKey(commandQName)) {
- return Optional.absent();
- }
-
- return Optional.of(qNameCommandMap.get(commandQName));
- }
-
- public synchronized Optional<Command> getCommand(final QName qualifiedName) {
- return Optional.fromNullable(mergeCommands().get(qualifiedName));
- }
-
- private static Optional<Command> getCommand(final Map<String, QName> commandNameMap,
- final Map<QName, Command> commands, final String nameWithModule) {
- final QName qName = commandNameMap.get(nameWithModule);
- if (qName == null) {
- return Optional.absent();
- }
- final Command command = commands.get(qName);
- if (command == null) {
- return Optional.absent();
- }
-
- return Optional.of(command);
- }
-
- public static final Collection<String> BASE_NETCONF_SCHEMA_PATHS = Lists.newArrayList(
- "/schema/remote/ietf-netconf.yang",
- "/schema/common/netconf-cli-ext.yang",
- "/schema/common/ietf-inet-types.yang");
-
- public synchronized void addRemoteCommands(final DOMRpcService rpcService, final SchemaContext remoteSchema) {
- this.addRemoteCommands(rpcService, remoteSchema, parseSchema(BASE_NETCONF_SCHEMA_PATHS));
- }
-
- public synchronized void addRemoteCommands(final DOMRpcService rpcService, final SchemaContext remoteSchema,
- final SchemaContext baseNetconfSchema) {
- for (final SchemaContext context : Lists.newArrayList(remoteSchema, baseNetconfSchema)) {
- for (final Module module : context.getModules()) {
- for (final RpcDefinition rpcDefinition : module.getRpcs()) {
- final Command command = RemoteCommand.fromRpc(rpcDefinition, rpcService);
- remoteCommands.put(rpcDefinition.getQName(), command);
- nameToQNameRemote.put(getCommandName(rpcDefinition, module), rpcDefinition.getQName());
- }
- }
- }
- }
-
- public synchronized void removeRemoteCommands() {
- remoteCommands.clear();
- nameToQNameRemote.clear();
- }
-
- public static final Collection<String> LOCAL_SCHEMA_PATHS = Lists.newArrayList(
- "/schema/local/netconf-cli.yang",
- "/schema/common/netconf-cli-ext.yang",
- "/schema/common/ietf-inet-types.yang");
-
- public synchronized void addLocalCommands(final NetconfDeviceConnectionManager connectionManager,
- final SchemaContext localSchema, final Integer connectionTimeout) {
- for (final Module module : localSchema.getModules()) {
- for (final RpcDefinition rpcDefinition : module.getRpcs()) {
-
- // FIXME make local commands extensible
- // e.g. by yang extension defining java class to be instantiated
- // problem is with command specific resources
- // e.g. Help would need command registry
- final Command localCommand;
- if (rpcDefinition.getQName().equals(CommandConstants.HELP_QNAME)) {
- localCommand = Help.create(rpcDefinition, this);
- } else if (rpcDefinition.getQName().equals(CommandConstants.CLOSE_QNAME)) {
- localCommand = Close.create(rpcDefinition);
- } else if (rpcDefinition.getQName().equals(CommandConstants.CONNECT_QNAME)) {
- localCommand = Connect.create(rpcDefinition, connectionManager, connectionTimeout);
- } else if (rpcDefinition.getQName().equals(CommandConstants.DISCONNECT_QNAME)) {
- localCommand = Disconnect.create(rpcDefinition, connectionManager);
- } else {
- throw new IllegalStateException(
- "No command implementation available for local command: " + rpcDefinition.getQName());
- }
-
- localCommands.put(localCommand.getCommandId(), localCommand);
- nameToQNameLocal.put(getCommandName(rpcDefinition, module), localCommand.getCommandId());
- }
- }
- }
-
- private static String getCommandName(final RpcDefinition rpcDefinition, final Module module) {
- return IOUtil.qNameToKeyString(rpcDefinition.getQName(), module.getName());
- }
-
- public static SchemaContext parseSchema(final Collection<String> yangPath) {
- final List<InputStream> streams = loadYangs(yangPath);
- final SchemaContext schemaContext;
- try {
- schemaContext = YangParserTestUtils.parseYangStreams(streams);
- } catch (ReactorException e) {
- throw new RuntimeException("Unable to build schema context from " + streams, e);
- }
- return schemaContext;
- }
-
- private static List<InputStream> loadYangs(final Collection<String> yangPaths) {
-
- return Lists.newArrayList(Collections2.transform(Lists.newArrayList(yangPaths),
- new Function<String, InputStream>() {
- @Override
- public InputStream apply(final String input) {
- final InputStream resourceAsStream = NetconfDeviceConnectionHandler.class
- .getResourceAsStream(input);
- Preconditions.checkNotNull(resourceAsStream, "File %s was null", input);
- return resourceAsStream;
- }
- }));
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.commands;
-
-import org.opendaylight.yangtools.yang.common.QName;
-
-public class CommandInvocationException extends Exception {
-
- public CommandInvocationException(final QName qualifiedName, final Throwable cause) {
- this("Command " + qualifiedName + " invocation failed: " + cause.getMessage(), cause);
- }
-
- protected CommandInvocationException(final String message, final Throwable cause) {
- super(message, cause);
- }
-
- public static class CommandTimeoutException extends CommandInvocationException {
-
- public CommandTimeoutException(final QName qualifiedName, final Throwable throwable) {
- super("Command " + qualifiedName + " timed out: " + throwable.getMessage(), throwable);
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.commands.input;
-
-import com.google.common.base.Preconditions;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
-
-/**
- * Input arguments for and rpc/command execution.
- */
-public class Input {
-
- private final List<NormalizedNode<?, ?>> args;
-
- private final Map<String, NormalizedNode<?, ?>> nameToArg = new HashMap<>();
-
- public Input(final List<NormalizedNode<?, ?>> args) {
- // FIXME empty Input should be constructed from static factory method
- if (args.isEmpty()) {
- this.args = Collections.emptyList();
- return;
- }
-
- final NormalizedNode<?, ?> input = args.iterator().next();
- Preconditions.checkArgument(
- input instanceof DataContainerChild<?, ?>, "Input container has to be of type Data Container Child.");
- this.args = new ArrayList<>((Collection<NormalizedNode<?, ?>>) input.getValue());
-
- for (final NormalizedNode<?, ?> arg : this.args) {
- nameToArg.put(arg.getNodeType().getLocalName(), arg);
- }
- }
-
- public NormalizedNode<?, ?> getArg(final String name) {
- return nameToArg.get(name);
- }
-
- public NormalizedNode<?, ?> wrap(final QName rpcQName) {
- //TODO just add the list as children to the node
- return ImmutableContainerNodeBuilder.create()
- .withNodeIdentifier(new NodeIdentifier(rpcQName))
- .withValue((Collection) args).build();
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.commands.input;
-
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-
-/**
- * The definition of input arguments represented by schema nodes parsed from
- * yang rpc definition.
- */
-public class InputDefinition {
-
- private final ContainerSchemaNode inputContainer;
-
- public InputDefinition(final ContainerSchemaNode inputContainer) {
- this.inputContainer = inputContainer;
- }
-
- public static InputDefinition fromInput(final ContainerSchemaNode input) {
- return new InputDefinition(input);
- }
-
- public ContainerSchemaNode getInput() {
- return inputContainer;
- }
-
- // FIXME add empty as in output
- public boolean isEmpty() {
- return inputContainer == null;
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.commands.local;
-
-import org.opendaylight.netconf.cli.commands.AbstractCommand;
-import org.opendaylight.netconf.cli.commands.Command;
-import org.opendaylight.netconf.cli.commands.CommandInvocationException;
-import org.opendaylight.netconf.cli.commands.input.Input;
-import org.opendaylight.netconf.cli.commands.input.InputDefinition;
-import org.opendaylight.netconf.cli.commands.output.Output;
-import org.opendaylight.netconf.cli.commands.output.OutputDefinition;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
-
-/**
- * Local command to shut down the cli.
- */
-public class Close extends AbstractCommand {
-
- public Close(final QName qualifiedName, final InputDefinition args, final OutputDefinition output,
- final String description) {
- super(qualifiedName, args, output, description);
- }
-
- @Override
- public Output invoke(final Input inputArgs) throws CommandInvocationException {
- // FIXME clean up, close session and then close
- System.exit(0);
- return null;
- }
-
- public static Command create(final RpcDefinition rpcDefinition) {
- return new Close(rpcDefinition.getQName(), getInputDefinition(rpcDefinition),
- getOutputDefinition(rpcDefinition), rpcDefinition.getDescription());
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.commands.local;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import io.netty.util.concurrent.GlobalEventExecutor;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Set;
-import org.opendaylight.netconf.cli.NetconfDeviceConnectionManager;
-import org.opendaylight.netconf.cli.commands.AbstractCommand;
-import org.opendaylight.netconf.cli.commands.Command;
-import org.opendaylight.netconf.cli.commands.input.Input;
-import org.opendaylight.netconf.cli.commands.input.InputDefinition;
-import org.opendaylight.netconf.cli.commands.output.Output;
-import org.opendaylight.netconf.cli.commands.output.OutputDefinition;
-import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
-import org.opendaylight.netconf.client.conf.NetconfClientConfigurationBuilder;
-import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.LoginPasswordHandler;
-import org.opendaylight.protocol.framework.NeverReconnectStrategy;
-import org.opendaylight.protocol.framework.ReconnectStrategy;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
-
-/**
- * Local command to connect to a remote device.
- */
-public class Connect extends AbstractCommand {
-
- private final NetconfDeviceConnectionManager connectManager;
- private final Integer connectionTimeout;
-
- private Connect(final QName qualifiedName, final InputDefinition args, final OutputDefinition output,
- final NetconfDeviceConnectionManager connectManager, final String description,
- final Integer connectionTimeout) {
- super(qualifiedName, args, output, description);
- this.connectManager = connectManager;
- this.connectionTimeout = connectionTimeout;
- }
-
- @Override
- public Output invoke(final Input inputArgs) {
- final NetconfClientConfigurationBuilder config = getConfig(inputArgs);
- return invoke(config, getArgument(inputArgs, "address-name", String.class), inputArgs);
- }
-
- private Output invoke(final NetconfClientConfigurationBuilder config,
- final String addressName, final Input inputArgs) {
- final Set<String> remoteCmds = connectManager.connectBlocking(addressName, getAdress(inputArgs), config);
-
- final ArrayList<DataContainerChild<?, ?>> output = Lists.newArrayList();
- output.add(ImmutableLeafNodeBuilder.create()
- .withNodeIdentifier(new NodeIdentifier(QName.create(getCommandId(), "status")))
- .withValue("Connection initiated").build());
-
- final ArrayList<LeafSetEntryNode<Object>> leafListChildren = Lists.newArrayList();
- for (final String cmdId : remoteCmds) {
- leafListChildren.add(ImmutableLeafSetEntryNodeBuilder.create()
- .withNodeIdentifier(new NodeWithValue(QName.create(getCommandId(), "remote-commands"), cmdId))
- .withValue(cmdId).build());
- }
-
- return new Output(ImmutableLeafSetNodeBuilder.create()
- .withNodeIdentifier(new NodeIdentifier(QName.create(getCommandId(), "remote-commands")))
- .withValue(leafListChildren).build());
- }
-
- private NetconfClientConfigurationBuilder getConfig(final Input inputArgs) {
-
- final ReconnectStrategy strategy = getReconnectStrategy();
-
- final String address = getArgument(inputArgs, "address-name", String.class);
- final Integer port = getArgument(inputArgs, "address-port", Integer.class);
- final String username = getArgument(inputArgs, "user-name", String.class);
- final String passwd = getArgument(inputArgs, "user-password", String.class);
-
- final InetSocketAddress inetAddress;
- try {
- inetAddress = new InetSocketAddress(InetAddress.getByName(address), port);
- } catch (final UnknownHostException e) {
- throw new IllegalArgumentException("Unable to use address: " + address, e);
- }
-
- return NetconfClientConfigurationBuilder.create().withAddress(inetAddress)
- .withConnectionTimeoutMillis(connectionTimeout)
- .withReconnectStrategy(strategy)
- .withAuthHandler(new LoginPasswordHandler(username, passwd))
- .withProtocol(NetconfClientConfiguration.NetconfClientProtocol.SSH);
- }
-
- private InetSocketAddress getAdress(final Input inputArgs) {
- final String address = getArgument(inputArgs, "address-name", String.class);
- final InetSocketAddress inetAddress;
- try {
- inetAddress = new InetSocketAddress(
- InetAddress.getByName(address), getArgument(inputArgs, "address-port", Integer.class));
- } catch (final UnknownHostException e) {
- throw new IllegalArgumentException("Unable to use address: " + address, e);
- }
- return inetAddress;
- }
-
- private <T> Optional<T> getArgumentOpt(final Input inputArgs, final String argName, final Class<T> type) {
- final QName argQName = QName.create(getCommandId(), argName);
- final NormalizedNode<?, ?> argumentNode = inputArgs.getArg(argName);
- if (argumentNode == null) {
- return Optional.absent();
- }
- Preconditions.checkArgument(argumentNode instanceof LeafNode, "Only simple type argument supported, %s",
- argQName);
-
- final Object value = argumentNode.getValue();
- Preconditions.checkArgument(type.isInstance(value), "Unexpected instance type: %s for argument: %s",
- value.getClass(), argQName);
- return Optional.of(type.cast(value));
- }
-
- private <T> T getArgument(final Input inputArgs, final String argName, final Class<T> type) {
- final Optional<T> argumentOpt = getArgumentOpt(inputArgs, argName, type);
- Preconditions.checkState(argumentOpt.isPresent(), "Argument: %s is missing but is required", argName);
- return argumentOpt.get();
- }
-
- public static ReconnectStrategy getReconnectStrategy() {
- // FIXME move to args either start-up args or input nodes for connect or both
- return new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, 1000);
- }
-
- public static Command create(final RpcDefinition rpcDefinition, final NetconfDeviceConnectionManager connectManager,
- final Integer connectionTimeout) {
- return new Connect(rpcDefinition.getQName(), getInputDefinition(rpcDefinition),
- getOutputDefinition(rpcDefinition), connectManager, rpcDefinition.getDescription(), connectionTimeout);
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.commands.local;
-
-import org.opendaylight.netconf.cli.NetconfDeviceConnectionManager;
-import org.opendaylight.netconf.cli.commands.AbstractCommand;
-import org.opendaylight.netconf.cli.commands.Command;
-import org.opendaylight.netconf.cli.commands.input.Input;
-import org.opendaylight.netconf.cli.commands.input.InputDefinition;
-import org.opendaylight.netconf.cli.commands.output.Output;
-import org.opendaylight.netconf.cli.commands.output.OutputDefinition;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
-
-/**
- * Local disconnect command.
- */
-public class Disconnect extends AbstractCommand {
-
- private final NetconfDeviceConnectionManager connectionManager;
-
- public Disconnect(final QName qualifiedName, final InputDefinition inputDefinition,
- final OutputDefinition outputDefinition, final NetconfDeviceConnectionManager connectionManager,
- final String description) {
- super(qualifiedName, inputDefinition, outputDefinition, description);
- this.connectionManager = connectionManager;
- }
-
- @Override
- public Output invoke(final Input inputArgs) {
- connectionManager.disconnect();
-
- return new Output(
- ImmutableContainerNodeBuilder.create()
- .withNodeIdentifier(new NodeIdentifier(getCommandId()))
- .withChild(ImmutableLeafNodeBuilder.create()
- .withNodeIdentifier(new NodeIdentifier(QName.create(getCommandId(), "status")))
- .withValue("Connection disconnected").build()).build());
- }
-
- public static Command create(final RpcDefinition rpcDefinition,
- final NetconfDeviceConnectionManager commandDispatcher) {
- return new Disconnect(rpcDefinition.getQName(), getInputDefinition(rpcDefinition),
- getOutputDefinition(rpcDefinition), commandDispatcher, rpcDefinition.getDescription());
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.commands.local;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import java.util.ArrayList;
-import java.util.List;
-import org.opendaylight.netconf.cli.commands.AbstractCommand;
-import org.opendaylight.netconf.cli.commands.Command;
-import org.opendaylight.netconf.cli.commands.CommandDispatcher;
-import org.opendaylight.netconf.cli.commands.input.Input;
-import org.opendaylight.netconf.cli.commands.input.InputDefinition;
-import org.opendaylight.netconf.cli.commands.output.Output;
-import org.opendaylight.netconf.cli.commands.output.OutputDefinition;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
-
-/**
- * Local Help command. Displays all commands with description.
- */
-public class Help extends AbstractCommand {
-
- private final CommandDispatcher commandDispatcher;
-
- public Help(final QName qualifiedName, final InputDefinition argsDefinition, final OutputDefinition output,
- final String description, final CommandDispatcher commandDispatcher) {
- super(qualifiedName, argsDefinition, output, description);
- this.commandDispatcher = commandDispatcher;
- }
-
- @Override
- public Output invoke(final Input inputArgs) {
- final ArrayList<MapEntryNode> value = Lists.newArrayList();
-
- for (final String id : commandDispatcher.getCommandIds()) {
- final Optional<Command> cmd = commandDispatcher.getCommand(id);
- Preconditions.checkState(cmd.isPresent(), "Command %s has to be present in command dispatcher", id);
- final Optional<String> description = cmd.get().getCommandDescription();
- final List<DataContainerChild<?, ?>> nameAndDescription = Lists.newArrayList();
- nameAndDescription.add(
- ImmutableLeafNodeBuilder.create()
- .withNodeIdentifier(new NodeIdentifier(QName.create(getCommandId(), "id")))
- .withValue(id).build());
- if (description.isPresent()) {
- nameAndDescription.add(
- ImmutableLeafNodeBuilder.create()
- .withNodeIdentifier(new NodeIdentifier(QName.create(getCommandId(), "description")))
- .withValue(description.get()).build());
- }
- value.add(ImmutableMapEntryNodeBuilder.create()
- .withValue(nameAndDescription)
- .withNodeIdentifier(
- new NodeIdentifierWithPredicates(QName.create(getCommandId(), "commands"),
- QName.create(getCommandId(), "id"), id)).build());
- }
- MapNode mappedHelp = ImmutableMapNodeBuilder.create()
- .withNodeIdentifier(new NodeIdentifier(QName.create(getCommandId(), "commands")))
- .withValue(value).build();
-
- return new Output(mappedHelp);
- }
-
- public static Command create(final RpcDefinition rpcDefinition, final CommandDispatcher commandDispatcher) {
- return new Help(rpcDefinition.getQName(), getInputDefinition(rpcDefinition), getOutputDefinition(rpcDefinition),
- rpcDefinition.getDescription(), commandDispatcher);
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.commands.output;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import java.util.List;
-import java.util.Map;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-
-/**
- * Output values for and rpc/command execution.
- */
-public class Output {
-
- private final NormalizedNode<?, ?> output;
-
- public Output(final NormalizedNode<?, ?> output) {
- if (output instanceof ContainerNode && output.getNodeType().getLocalName() == "rpc-reply") {
- this.output = ((ContainerNode) output).getValue().iterator().next();
- } else {
- this.output = output;
- }
- }
-
- public Map<DataSchemaNode, List<NormalizedNode<?, ?>>> unwrap(final OutputDefinition outputDefinition) {
- Preconditions.checkArgument(!outputDefinition.isEmpty());
-
- final Map<QName, DataSchemaNode> mappedSchemaNodes = mapOutput(outputDefinition);
- final Map<DataSchemaNode, List<NormalizedNode<?, ?>>> mappedNodesToSchema = Maps.newHashMap();
-
- final DataSchemaNode schemaNode = mappedSchemaNodes.get(output.getNodeType().withoutRevision());
- final List<NormalizedNode<?, ?>> list = mappedNodesToSchema.get(schemaNode) == null
- ? Lists.newArrayList() : mappedNodesToSchema.get(schemaNode);
- list.add(output);
- mappedNodesToSchema.put(schemaNode, list);
-
- return mappedNodesToSchema;
- }
-
- public NormalizedNode<?, ?> getOutput() {
- return output;
- }
-
- private Map<QName, DataSchemaNode> mapOutput(final OutputDefinition outputDefinition) {
- final Map<QName, DataSchemaNode> mapped = Maps.newHashMap();
- for (final DataSchemaNode dataSchemaNode : outputDefinition) {
- // without revision since data QNames come without revision
- mapped.put(dataSchemaNode.getQName().withoutRevision(), dataSchemaNode);
- }
-
- return mapped;
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.commands.output;
-
-import com.google.common.base.Preconditions;
-import java.util.Collections;
-import java.util.Iterator;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-
-/**
- * The definition of output elements represented by schema nodes parsed from yang rpc definition.
- */
-public class OutputDefinition implements Iterable<DataSchemaNode> {
-
- public static final OutputDefinition EMPTY_OUTPUT = new OutputDefinition(Collections.<DataSchemaNode>emptySet());
- private final Iterable<DataSchemaNode> childNodes;
-
- public OutputDefinition(final Iterable<DataSchemaNode> childNodes) {
- this.childNodes = childNodes;
- }
-
- @Override
- public Iterator<DataSchemaNode> iterator() {
- return childNodes.iterator();
- }
-
- public static OutputDefinition fromOutput(final ContainerSchemaNode output) {
- Preconditions.checkNotNull(output);
- return new OutputDefinition(output.getChildNodes());
- }
-
- public static OutputDefinition empty() {
- return EMPTY_OUTPUT;
- }
-
- public boolean isEmpty() {
- return this == EMPTY_OUTPUT;
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.commands.remote;
-
-import com.google.common.util.concurrent.CheckedFuture;
-import java.util.Collections;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import org.opendaylight.controller.md.sal.dom.api.DOMRpcException;
-import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
-import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
-import org.opendaylight.netconf.cli.commands.AbstractCommand;
-import org.opendaylight.netconf.cli.commands.Command;
-import org.opendaylight.netconf.cli.commands.CommandInvocationException;
-import org.opendaylight.netconf.cli.commands.input.Input;
-import org.opendaylight.netconf.cli.commands.input.InputDefinition;
-import org.opendaylight.netconf.cli.commands.output.Output;
-import org.opendaylight.netconf.cli.commands.output.OutputDefinition;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
-import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-
-/**
- * Generic remote command implementation that sends the rpc xml to the remote device and waits for response
- * Waiting is limited with TIMEOUT.
- */
-public class RemoteCommand extends AbstractCommand {
-
- // TODO make this configurable
- private static final long DEFAULT_TIMEOUT = 10000;
- private static final TimeUnit DEFAULT_TIMEOUT_UNIT = TimeUnit.MILLISECONDS;
- private final DOMRpcService rpcService;
-
- public RemoteCommand(final QName qualifiedName, final InputDefinition args, final OutputDefinition output,
- final String description, final DOMRpcService rpcService) {
- super(qualifiedName, args, output, description);
- this.rpcService = rpcService;
- }
-
- @Override
- public Output invoke(final Input inputArgs) throws CommandInvocationException {
- final CheckedFuture<DOMRpcResult, DOMRpcException> invokeRpc = rpcService.invokeRpc(
- SchemaPath.create(Collections.singletonList(getCommandId()), true), inputArgs.wrap(getCommandId()));
-
- try {
- return new Output(invokeRpc.get(DEFAULT_TIMEOUT, DEFAULT_TIMEOUT_UNIT).getResult());
- } catch (final ExecutionException e) {
- throw new CommandInvocationException(getCommandId(), e);
- } catch (final TimeoutException e) {
- // Request timed out, cancel request
- invokeRpc.cancel(true);
- throw new CommandInvocationException.CommandTimeoutException(getCommandId(), e);
- } catch (final InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
-
- public static Command fromRpc(final RpcDefinition rpcDefinition, final DOMRpcService rpcService) {
- final InputDefinition args = getInputDefinition(rpcDefinition);
- final OutputDefinition retVal = getOutputDefinition(rpcDefinition);
-
- return new RemoteCommand(rpcDefinition.getQName(), args, retVal, rpcDefinition.getDescription(), rpcService);
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.io;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import jline.console.completer.AggregateCompleter;
-import jline.console.completer.Completer;
-import jline.console.completer.StringsCompleter;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-
-public class BaseConsoleContext<T extends DataSchemaNode> implements ConsoleContext {
-
- private static final Completer SKIP_COMPLETER = new StringsCompleter(IOUtil.SKIP);
-
- private final T dataSchemaNode;
-
- public BaseConsoleContext(final T dataSchemaNode) {
- Preconditions.checkNotNull(dataSchemaNode);
- this.dataSchemaNode = dataSchemaNode;
- }
-
- @Override
- public Completer getCompleter() {
- final ArrayList<Completer> completers = Lists.newArrayList(SKIP_COMPLETER);
- completers.addAll(getAdditionalCompleters());
- return new AggregateCompleter(completers);
- }
-
- protected List<Completer> getAdditionalCompleters() {
- return Collections.emptyList();
- }
-
- @Override
- public Optional<String> getPrompt() {
- return Optional.of(dataSchemaNode.getQName().getLocalName());
- }
-
- protected T getDataSchemaNode() {
- return dataSchemaNode;
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.io;
-
-import com.google.common.base.Optional;
-import jline.console.completer.Completer;
-
-/**
- * Context to be set in the IO. Different prompts + completers are required in different contexts of the CLI.
- */
-public interface ConsoleContext {
-
- Completer getCompleter();
-
- Optional<String> getPrompt();
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.io;
-
-import java.io.IOException;
-
-/**
- * Definition of IO interface.
- */
-public interface ConsoleIO {
-
- String read() throws IOException;
-
- String read(Character mask) throws IOException;
-
- void write(CharSequence data) throws IOException;
-
- void writeLn(CharSequence data) throws IOException;
-
- void formatLn(String format, Object... args) throws IOException;
-
- void enterContext(ConsoleContext consoleContext);
-
- void enterRootContext(ConsoleContext consoleContext);
-
- void leaveContext();
-
- void leaveRootContext();
-
- void complete();
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.io;
-
-import static org.opendaylight.netconf.cli.io.IOUtil.PATH_SEPARATOR;
-import static org.opendaylight.netconf.cli.io.IOUtil.PROMPT_SUFIX;
-
-import com.google.common.base.Optional;
-import com.google.common.collect.Lists;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.IOException;
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Deque;
-import java.util.Iterator;
-import jline.console.ConsoleReader;
-import jline.console.completer.Completer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Jline based IO implementation.
- */
-public class ConsoleIOImpl implements ConsoleIO {
-
- private static final Logger LOG = LoggerFactory.getLogger(ConsoleIOImpl.class);
-
- private final ConsoleReader console;
- private final Deque<ConsoleContext> contexts = new ArrayDeque<>();
-
- public ConsoleIOImpl() throws IOException {
- console = new ConsoleReader();
- console.setHandleUserInterrupt(true);
- console.setPaginationEnabled(true);
- console.setHistoryEnabled(true);
-
- // TODO trifferedActions not supported by jline in current version
- // https://github.com/jline/jline2/issues/149
- console.addTriggeredAction('?', new QuestionMarkActionListener());
- }
-
- @Override
- public String read() throws IOException {
- return console.readLine().trim();
- }
-
- @Override
- public String read(final Character mask) throws IOException {
- return console.readLine(mask).trim();
- }
-
- @Override
- public void write(final CharSequence data) throws IOException {
- console.print(data);
- console.flush();
- }
-
- @Override
- public void writeLn(final CharSequence data) throws IOException {
- console.println(data);
- console.flush();
- }
-
- @Override
- public void formatLn(final String format, final Object... args) throws IOException {
- console.println(String.format(format, args));
- console.flush();
- }
-
- @Override
- public void enterContext(final ConsoleContext consoleContext) {
- contexts.push(consoleContext);
- enterCtx(consoleContext);
- }
-
-
- @Override
- public void enterRootContext(final ConsoleContext consoleContext) {
- contexts.addLast(consoleContext);
- enterCtx(consoleContext);
- }
-
- private void enterCtx(final ConsoleContext consoleContext) {
- setCompleter(consoleContext.getCompleter());
- console.setPrompt(buildPrompt());
- }
-
- @Override
- public void leaveContext() {
- contexts.pollFirst();
- leaveCtx();
- }
-
- @Override
- public void leaveRootContext() {
- contexts.pollLast();
- leaveCtx();
- }
-
- private void leaveCtx() {
- console.setPrompt(buildPrompt());
- if (contexts.peek() != null) {
- setCompleter(contexts.peek().getCompleter());
- }
- }
-
- protected String buildPrompt() {
- final StringBuilder newPrompt = new StringBuilder();
-
- final Iterator<ConsoleContext> descendingIterator = contexts.descendingIterator();
- while (descendingIterator.hasNext()) {
- final ConsoleContext consoleContext = descendingIterator.next();
- final Optional<String> promptPart = consoleContext.getPrompt();
- if (promptPart.isPresent()) {
- newPrompt.append(PATH_SEPARATOR);
- newPrompt.append(promptPart.get());
- }
- }
- if (newPrompt.length() == 0) {
- newPrompt.append(PATH_SEPARATOR);
- }
-
- newPrompt.append(PROMPT_SUFIX);
-
- return newPrompt.toString();
- }
-
- private void setCompleter(final Completer newCompleter) {
- for (final Completer concreteCompleter : console.getCompleters()) {
- console.removeCompleter(concreteCompleter);
- }
- console.addCompleter(newCompleter);
- }
-
- private class QuestionMarkActionListener implements ActionListener {
- @Override
- public void actionPerformed(final ActionEvent event) {
- ConsoleIOImpl.this.complete();
- }
- }
-
- public void complete() {
- final ArrayList<CharSequence> candidates = Lists.newArrayList();
- contexts.peek().getCompleter().complete("", 0, candidates);
- try {
- console.getCompletionHandler().complete(console, candidates, 0);
- } catch (final IOException ex) {
- throw new IllegalStateException("Unable to write to output", ex);
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.io;
-
-import java.text.ParseException;
-import java.util.Date;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import org.opendaylight.netconf.cli.reader.ReadingException;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-
-public class IOUtil {
-
- public static final String SKIP = "skip";
- public static final String PROMPT_SUFIX = ">";
- public static final String PATH_SEPARATOR = "/";
-
- private IOUtil() {}
-
- public static boolean isQName(final String qualifiedName) {
- final Matcher matcher = PATTERN.matcher(qualifiedName);
- return matcher.matches();
- }
-
- public static Date parseDate(final String revision) {
- try {
- return SimpleDateFormatUtil.getRevisionFormat().parse(revision);
- } catch (final ParseException e) {
- throw new IllegalArgumentException("Date not valid", e);
- }
- }
-
- public static String listType(final SchemaNode schemaNode) {
- if (schemaNode instanceof LeafListSchemaNode) {
- return "Leaf-list";
- } else if (schemaNode instanceof ListSchemaNode) {
- return "List";
- } else if (schemaNode instanceof LeafSchemaNode) {
- return "Leaf";
- }
- // FIXME throw exception on unexpected state, not null/emptyString
- return "";
- }
-
- public static String qNameToKeyString(final QName qualifiedName, final String moduleName) {
- return String.format("%s(%s)", qualifiedName.getLocalName(), moduleName);
- }
-
- // TODO test and check regex + review format of string for QName
- static final Pattern PATTERN = Pattern.compile("([^\\)]+)\\(([^\\)]+)\\)");
-
- public static QName qNameFromKeyString(final String qualifiedName, final Map<String, QName> mappedModules)
- throws ReadingException {
- final Matcher matcher = PATTERN.matcher(qualifiedName);
- if (!matcher.matches()) {
- final String message = String.format("QName in wrong format: %s should be: %s", qualifiedName, PATTERN);
- throw new ReadingException(message);
- }
- final QName base = mappedModules.get(matcher.group(2));
- if (base == null) {
- final String message = String.format("Module %s cannot be found", matcher.group(2));
- throw new ReadingException(message);
- }
- return QName.create(base, matcher.group(1));
- }
-
- public static boolean isSkipInput(final String rawValue) {
- return rawValue.equals(SKIP);
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.reader;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Strings;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-import jline.console.completer.Completer;
-import jline.console.completer.NullCompleter;
-import org.opendaylight.netconf.cli.io.ConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
-
-public abstract class AbstractReader<T extends DataSchemaNode> implements Reader<T> {
-
- public static final NullContext NULL_CONTEXT = new NullContext();
-
- // TODO make console private add protected getter
- protected ConsoleIO console;
- private final SchemaContext context;
- private boolean readConfigNode = false;
-
- public AbstractReader(final ConsoleIO console, final SchemaContext context) {
- this.console = console;
- this.context = context;
- }
-
- public AbstractReader(final ConsoleIO console, final SchemaContext context, final boolean readConfigNode) {
- this(console, context);
- this.readConfigNode = readConfigNode;
- }
-
- protected SchemaContext getSchemaContext() {
- return context;
- }
-
- protected ConsoleIO getConsole() {
- return console;
- }
-
- protected boolean getReadConfigNode() {
- return readConfigNode;
- }
-
- @Override
- public List<NormalizedNode<?, ?>> read(final T schemaNode) throws ReadingException {
- if (isReadingWanted(schemaNode)) {
- final ConsoleContext ctx = getContext(schemaNode);
- console.enterContext(ctx);
- try {
- return readWithContext(schemaNode);
- } catch (final IOException e) {
- throw new ReadingException("Unable to read data from input for " + schemaNode.getQName(), e);
- } finally {
- console.leaveContext();
- }
- }
- return Collections.emptyList();
- }
-
- private boolean isReadingWanted(final DataSchemaNode node) {
- return !readConfigNode || node.isConfiguration();
- }
-
- // TODO javadoc
-
- protected abstract List<NormalizedNode<?, ?>> readWithContext(T schemaNode) throws IOException, ReadingException;
-
- protected abstract ConsoleContext getContext(T schemaNode);
-
- protected Optional<String> getDefaultValue(final T schemaNode) {
- String defaultValue = null;
- if (schemaNode instanceof LeafSchemaNode) {
- defaultValue = ((LeafSchemaNode) schemaNode).getDefault();
- } else if (schemaNode instanceof ChoiceSchemaNode) {
- defaultValue = ((ChoiceSchemaNode) schemaNode).getDefaultCase();
- }
-
- return Optional.fromNullable(defaultValue);
- }
-
- protected boolean isEmptyInput(final String rawValue) {
- return Strings.isNullOrEmpty(rawValue);
- }
-
- protected static boolean isEmptyType(final TypeDefinition<?> type) {
- return type instanceof EmptyTypeDefinition;
- }
-
- private static class NullContext implements ConsoleContext {
- @Override
- public Completer getCompleter() {
- return new NullCompleter();
- }
-
- @Override
- public Optional<String> getPrompt() {
- return Optional.absent();
- }
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.reader;
-
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-
-/**
- * Marker interface to mark reader which can be used with GenericListReader.
- */
-public interface GenericListEntryReader<T extends DataSchemaNode> extends Reader<T> {
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.reader;
-
-import java.util.List;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-
-/**
- * Generic provider(reader) of input arguments for commands.
- */
-public interface Reader<T extends DataSchemaNode> {
-
- List<NormalizedNode<?, ?>> read(T schemaNode) throws ReadingException;
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.reader;
-
-public class ReadingException extends Exception {
-
- private static final long serialVersionUID = -298382323286156591L;
-
- public ReadingException(final String msg, final Exception ex) {
- super(msg, ex);
- }
-
- public ReadingException(final String msg) {
- super(msg);
- }
-
- public static class IncorrectValueException extends ReadingException {
-
- private static final long serialVersionUID = 164168437058431592L;
-
- public IncorrectValueException(final String msg) {
- super(msg);
- }
-
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.reader.custom;
-
-import static org.opendaylight.netconf.cli.io.IOUtil.isSkipInput;
-
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import java.io.IOException;
-import java.net.URI;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import jline.console.completer.Completer;
-import org.opendaylight.netconf.cli.CommandArgHandlerRegistry;
-import org.opendaylight.netconf.cli.io.BaseConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.cli.io.IOUtil;
-import org.opendaylight.netconf.cli.reader.AbstractReader;
-import org.opendaylight.netconf.cli.reader.ReadingException;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-/**
- * Custom reader implementation for filter elements in get/get-config rpcs. This
- * reader overrides the default anyxml reader and reads filter as a schema path.
- */
-public class ConfigReader extends AbstractReader<DataSchemaNode> {
-
- public static final String SEPARATOR = "/";
-
- private final CommandArgHandlerRegistry commandArgHandlerRegistry;
- private final Map<String, QName> mappedModules;
- private final Map<URI, QName> mappedModulesNamespace;
-
- public ConfigReader(final ConsoleIO console, final SchemaContext remoteSchemaContext,
- final CommandArgHandlerRegistry commandArgHandlerRegistry) {
- super(console, remoteSchemaContext);
- this.commandArgHandlerRegistry = commandArgHandlerRegistry;
-
- mappedModules = Maps.newHashMap();
- mappedModulesNamespace = Maps.newHashMap();
- for (final Module module : remoteSchemaContext.getModules()) {
- final QName moduleQName = QName.create(module.getNamespace(), module.getRevision(), module.getName());
- mappedModules.put(moduleQName.getLocalName(), moduleQName);
- mappedModulesNamespace.put(moduleQName.getNamespace(), moduleQName);
- }
- }
-
- // FIXME refactor + unite common code with FilterReader
-
- @Override
- protected List<NormalizedNode<?, ?>> readWithContext(final DataSchemaNode schemaNode)
- throws IOException, ReadingException {
- console.writeLn("Config " + schemaNode.getQName().getLocalName());
- console.writeLn("Submit path of the data to edit. Use TAB for autocomplete");
-
- final String rawValue = console.read();
-
- // FIXME isSkip check should be somewhere in abstractReader
- if (isSkipInput(rawValue) || Strings.isNullOrEmpty(rawValue)) {
- return Collections.emptyList();
- }
-
- final List<QName> filterPartsQNames = Lists.newArrayList();
-
- for (final String part : rawValue.split(SEPARATOR)) {
- final QName qName = IOUtil.qNameFromKeyString(part, mappedModules);
- filterPartsQNames.add(qName);
- }
-
- List<? extends NormalizedNode<?, ?>> previous = readInnerNode(rawValue);
-
- for (final QName qualifiedName : Lists.reverse(filterPartsQNames).subList(1, filterPartsQNames.size())) {
- previous = Collections.<NormalizedNode<?, ?>>singletonList(
- ImmutableContainerNodeBuilder.create()
- .withNodeIdentifier(new NodeIdentifier(qualifiedName))
- .withValue(previous == null ? Collections.emptyList() : (Collection) previous).build()
- );
- }
-
- if (previous == null) {
- return Collections.singletonList(null);
- }
-
- final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> builder = ImmutableContainerNodeBuilder
- .create();
- builder.withNodeIdentifier(new NodeIdentifier(schemaNode.getQName()));
- builder.withValue((Collection<DataContainerChild<?, ?>>) previous);
-
- return Collections.singletonList(builder.build());
- }
-
- private List<NormalizedNode<?, ?>> readInnerNode(final String pathString) throws ReadingException {
- final Optional<DataSchemaNode> schema = getCurrentNode(getSchemaContext(), pathString);
- Preconditions.checkState(schema.isPresent(), "Unable to find schema for %s", pathString);
- return commandArgHandlerRegistry.getGenericReader(getSchemaContext(), true).read(schema.get());
- }
-
- @Override
- protected ConsoleContext getContext(final DataSchemaNode schemaNode) {
- return new FilterConsoleContext(schemaNode, getSchemaContext());
- }
-
- private final class FilterConsoleContext extends BaseConsoleContext<DataSchemaNode> {
-
- private final SchemaContext remoteSchemaContext;
-
- FilterConsoleContext(final DataSchemaNode schemaNode, final SchemaContext remoteSchemaContext) {
- super(schemaNode);
- this.remoteSchemaContext = remoteSchemaContext;
- }
-
- @Override
- protected List<Completer> getAdditionalCompleters() {
- return Collections.singletonList(new FilterCompleter(remoteSchemaContext));
- }
- }
-
- private final class FilterCompleter implements Completer {
-
- private final SchemaContext remoteSchemaContext;
-
- FilterCompleter(final SchemaContext remoteSchemaContext) {
- this.remoteSchemaContext = remoteSchemaContext;
- }
-
- @Override
- public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
- final int idx = buffer.lastIndexOf(SEPARATOR);
-
- final Optional<DataSchemaNode> currentNode = getCurrentNode(remoteSchemaContext, buffer);
- if (currentNode.isPresent() && currentNode.get() instanceof DataNodeContainer) {
- final Collection<DataSchemaNode> childNodes = ((DataNodeContainer) currentNode.get()).getChildNodes();
- final Collection<String> transformed = Collections2.transform(childNodes,
- new Function<DataSchemaNode, String>() {
- @Override
- public String apply(final DataSchemaNode input) {
- return IOUtil.qNameToKeyString(input.getQName(),
- mappedModulesNamespace.get(input.getQName().getNamespace()).getLocalName());
- }
- });
-
- fillCandidates(buffer.substring(idx + 1), candidates, transformed);
- }
-
- return idx == -1 ? 0 : idx + 1;
- }
-
- private void fillCandidates(final String buffer, final List<CharSequence> candidates,
- final Collection<String> transformed) {
- final SortedSet<String> strings = new TreeSet<>(transformed);
-
- if (buffer == null) {
- candidates.addAll(strings);
- } else {
- for (final String match : strings.tailSet(buffer)) {
- if (!match.startsWith(buffer)) {
- break;
- }
- candidates.add(match);
- }
- }
-
- if (candidates.size() == 1) {
- candidates.set(0, candidates.get(0) + SEPARATOR);
- }
- }
-
- }
-
- private Optional<DataSchemaNode> getCurrentNode(DataSchemaNode parent, final String buffer) {
- for (final String part : buffer.split(SEPARATOR)) {
- if (!IOUtil.isQName(part)) {
- return Optional.of(parent);
- }
-
- final QName qName;
- try {
- qName = IOUtil.qNameFromKeyString(part, mappedModules);
- } catch (final ReadingException e) {
- return Optional.of(parent);
- }
- if (parent instanceof DataNodeContainer) {
- parent = ((DataNodeContainer) parent).getDataChildByName(qName);
- } else {
- // This should check if we are at the end of buffer ?
- return Optional.of(parent);
- }
- }
- return Optional.of(parent);
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.reader.custom;
-
-import com.google.common.base.Preconditions;
-import java.io.IOException;
-import java.util.List;
-import org.opendaylight.netconf.cli.CommandArgHandlerRegistry;
-import org.opendaylight.netconf.cli.commands.CommandConstants;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.cli.reader.ReadingException;
-import org.opendaylight.netconf.cli.reader.impl.ChoiceReader;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-public class EditContentReader extends ChoiceReader {
-
- public static final QName EDIT_CONTENT_QNAME = QName.create(CommandConstants.NETCONF_BASE_QNAME, "edit-content");
- public static final QName CONFIG_QNAME = QName.create(EDIT_CONTENT_QNAME, "config");
-
- // FIXME this could be removed if feature/if-feature are supported
-
- public EditContentReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
- final SchemaContext schemaContext) {
- super(console, argumentHandlerRegistry, schemaContext);
- }
-
- @Override
- public List<NormalizedNode<?, ?>> readWithContext(final ChoiceSchemaNode choiceNode)
- throws IOException, ReadingException {
- Preconditions.checkState(choiceNode.getQName().equals(EDIT_CONTENT_QNAME),
- "Unexpected choice %s, expected %s", choiceNode, EDIT_CONTENT_QNAME);
- final ChoiceCaseNode selectedCase = choiceNode.getCaseNodeByName(CONFIG_QNAME);
- Preconditions.checkNotNull(selectedCase,
- "Unexpected choice %s, expected %s that contains %s", choiceNode, EDIT_CONTENT_QNAME, CONFIG_QNAME);
- return readSelectedCase(selectedCase);
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.reader.custom;
-
-import static org.opendaylight.netconf.cli.io.IOUtil.isSkipInput;
-
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Strings;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import java.io.IOException;
-import java.net.URI;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import jline.console.completer.Completer;
-import org.opendaylight.netconf.cli.io.BaseConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.cli.io.IOUtil;
-import org.opendaylight.netconf.cli.reader.AbstractReader;
-import org.opendaylight.netconf.cli.reader.ReadingException;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Custom reader implementation for filter elements in get/get-config rpcs. This
- * reader overrides the default anyxml reader and reads filter as a schema path.
- */
-public class FilterReader extends AbstractReader<DataSchemaNode> {
-
- private static final Logger LOG = LoggerFactory.getLogger(FilterReader.class);
-
- public static final String SEPARATOR = "/";
-
- private final Map<String, QName> mappedModules;
- private final Map<URI, QName> mappedModulesNamespace;
-
- public FilterReader(final ConsoleIO console, final SchemaContext remoteSchemaContext) {
- super(console, remoteSchemaContext);
-
- mappedModules = Maps.newHashMap();
- mappedModulesNamespace = Maps.newHashMap();
- for (final Module module : remoteSchemaContext.getModules()) {
- final QName moduleQName = QName.create(module.getNamespace(), module.getRevision(), module.getName());
- mappedModules.put(moduleQName.getLocalName(), moduleQName);
- mappedModulesNamespace.put(moduleQName.getNamespace(), moduleQName);
- }
- }
-
- // FIXME refactor
-
- public static final QName FILTER_TYPE_QNAME = QName.create("urn:ietf:params:xml:ns:netconf:base:1.0", "2011-06-01",
- "type");
- public static final String FILTER_TYPE_VALUE_DEFAULT = "subtree";
-
- @Override
- protected List<NormalizedNode<?, ?>> readWithContext(final DataSchemaNode schemaNode)
- throws IOException, ReadingException {
- boolean redSuccessfuly = false;
- DataContainerChild<?, ?> newNode = null;
- do {
- console.writeLn("Filter " + schemaNode.getQName().getLocalName());
- console.writeLn("Submit path of the data to retrieve. Use TAB for autocomplete");
-
- final String rawValue = console.read();
-
- // FIXME skip should be somewhere in abstractReader
- if (isSkipInput(rawValue) || Strings.isNullOrEmpty(rawValue)) {
- return Collections.emptyList();
- }
-
- final List<QName> filterPartsQNames = Lists.newArrayList();
-
- try {
- for (final String part : rawValue.split(SEPARATOR)) {
- final QName qName = IOUtil.qNameFromKeyString(part, mappedModules);
- filterPartsQNames.add(qName);
- }
-
- DataContainerChild<?, ?> previous = null;
-
- for (final QName qualifiedName : Lists.reverse(filterPartsQNames)) {
- previous = ImmutableContainerNodeBuilder.create()
- .withNodeIdentifier(new NodeIdentifier(qualifiedName))
- .withValue(previous == null ? Collections.emptyList()
- : Collections.singletonList(previous)).build();
- }
-
- final Map<QName, String> attributes = Collections.singletonMap(FILTER_TYPE_QNAME,
- FILTER_TYPE_VALUE_DEFAULT);
- newNode = previous == null ? null : ImmutableContainerNodeBuilder.create()
- .withNodeIdentifier(new NodeIdentifier(schemaNode.getQName())).withChild(previous).build();
- redSuccessfuly = true;
- } catch (final ReadingException e) {
- final String message = "Specified filter path isn't correct.";
- LOG.error(message, e);
- console.writeLn(message);
- }
- } while (!redSuccessfuly);
- return Collections.singletonList(newNode);
- }
-
- @Override
- protected ConsoleContext getContext(final DataSchemaNode schemaNode) {
- return new FilterConsoleContext(schemaNode, getSchemaContext());
- }
-
- private final class FilterConsoleContext extends BaseConsoleContext<DataSchemaNode> {
-
- private final SchemaContext remoteSchemaContext;
-
- FilterConsoleContext(final DataSchemaNode schemaNode, final SchemaContext remoteSchemaContext) {
- super(schemaNode);
- this.remoteSchemaContext = remoteSchemaContext;
- }
-
- @Override
- protected List<Completer> getAdditionalCompleters() {
- return Collections.singletonList(new FilterCompleter(remoteSchemaContext));
- }
-
- }
-
- private final class FilterCompleter implements Completer {
-
- private final SchemaContext remoteSchemaContext;
-
- // TODO add skip to filter completer, better soulution would be to add
- // SKIP completer before context completer if possible
-
- FilterCompleter(final SchemaContext remoteSchemaContext) {
- this.remoteSchemaContext = remoteSchemaContext;
- }
-
- @Override
- public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
- final int idx = buffer.lastIndexOf(SEPARATOR);
-
- final Optional<DataNodeContainer> currentNode = getCurrentNode(remoteSchemaContext, buffer);
- if (currentNode.isPresent()) {
-
- final Collection<String> transformed = Collections2.transform(currentNode.get().getChildNodes(),
- new Function<DataSchemaNode, String>() {
- @Override
- public String apply(final DataSchemaNode input) {
- return IOUtil.qNameToKeyString(input.getQName(),
- mappedModulesNamespace.get(input.getQName().getNamespace()).getLocalName());
- }
- });
-
- fillCandidates(buffer.substring(idx + 1), candidates, transformed);
- }
-
- return idx == -1 ? 0 : idx + 1;
- }
-
- private void fillCandidates(final String buffer, final List<CharSequence> candidates,
- final Collection<String> transformed) {
- final SortedSet<String> strings = new TreeSet<>(transformed);
-
- if (buffer == null) {
- candidates.addAll(strings);
- } else {
- for (final String match : strings.tailSet(buffer)) {
- if (!match.startsWith(buffer)) {
- break;
- }
- candidates.add(match);
- }
- }
-
- if (candidates.size() == 1) {
- candidates.set(0, candidates.get(0) + SEPARATOR);
- }
- }
-
- private Optional<DataNodeContainer> getCurrentNode(DataNodeContainer parent, final String buffer) {
- for (final String part : buffer.split(SEPARATOR)) {
- if (!IOUtil.isQName(part)) {
- return Optional.of(parent);
- }
-
- QName qualifiedName;
- try {
- qualifiedName = IOUtil.qNameFromKeyString(part, mappedModules);
- } catch (final ReadingException e) {
- return Optional.of(parent);
- }
-
- final DataSchemaNode dataChildByName = parent.getDataChildByName(qualifiedName);
- if (dataChildByName instanceof DataNodeContainer) {
- parent = (DataNodeContainer) dataChildByName;
- } else {
- return Optional.absent();
- }
- }
- return Optional.of(parent);
- }
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.reader.custom;
-
-import com.google.common.base.Preconditions;
-import java.io.IOException;
-import jline.console.completer.Completer;
-import jline.console.completer.NullCompleter;
-import org.opendaylight.netconf.cli.io.BaseConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.cli.reader.impl.BasicDataHolderReader;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-
-public class PasswordReader extends BasicDataHolderReader<DataSchemaNode> {
-
- private static final char PASSWORD_MASK = '*';
-
- public PasswordReader(final ConsoleIO console, final SchemaContext schemaContext) {
- super(console, schemaContext);
- }
-
- @Override
- protected ConsoleContext getContext(final DataSchemaNode schemaNode) {
- return new BaseConsoleContext<DataSchemaNode>(schemaNode) {
- @Override
- public Completer getCompleter() {
- return new NullCompleter();
- }
- };
- }
-
- @Override
- protected TypeDefinition<?> getType(final DataSchemaNode schemaNode) {
- Preconditions.checkArgument(schemaNode instanceof LeafSchemaNode);
- return ((LeafSchemaNode)schemaNode).getType();
- }
-
- @Override
- protected String readValue() throws IOException {
- return console.read(PASSWORD_MASK);
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.reader.impl;
-
-import static org.opendaylight.netconf.cli.io.IOUtil.isSkipInput;
-import static org.opendaylight.netconf.cli.io.IOUtil.listType;
-
-import com.google.common.base.Optional;
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.List;
-import org.opendaylight.netconf.cli.io.BaseConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.cli.reader.AbstractReader;
-import org.opendaylight.netconf.cli.reader.ReadingException;
-import org.opendaylight.yangtools.util.xml.UntrustedXML;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
-import org.opendaylight.yangtools.yang.data.codec.xml.XmlParserStream;
-import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
-import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-public class AnyXmlReader extends AbstractReader<AnyXmlSchemaNode> {
-
- public AnyXmlReader(final ConsoleIO console, final SchemaContext schemaContext) {
- super(console, schemaContext);
- }
-
- public AnyXmlReader(final ConsoleIO console, final SchemaContext schemaContext, final boolean readConfigNode) {
- super(console, schemaContext, readConfigNode);
- }
-
- @Override
- protected List<NormalizedNode<?, ?>> readWithContext(final AnyXmlSchemaNode schemaNode)
- throws IOException, ReadingException {
- console.writeLn(listType(schemaNode) + " " + schemaNode.getQName().getLocalName());
-
- final String rawValue = console.read();
-
- DataContainerChild<?, ?> newNode = null;
- if (!isSkipInput(rawValue)) {
- final Optional<DataContainerChild<?, ?>> value = tryParse(rawValue, schemaNode);
-
- if (value.isPresent()) {
- newNode = ImmutableContainerNodeBuilder.create()
- .withNodeIdentifier(new NodeIdentifier(schemaNode.getQName()))
- .withChild(value.get()).build();
- } else {
- newNode = ImmutableLeafNodeBuilder.create().withNodeIdentifier(
- new NodeIdentifier(schemaNode.getQName())).withValue(rawValue).build();
- }
- }
-
- final List<NormalizedNode<?, ?>> newNodes = new ArrayList<>();
- newNodes.add(newNode);
- return newNodes;
- }
-
- @SuppressWarnings("checkstyle:IllegalCatch")
- private Optional<DataContainerChild<?, ?>> tryParse(final String rawValue, final AnyXmlSchemaNode schemaNode) {
- try {
- final NormalizedNodeResult resultHolder = new NormalizedNodeResult();
- final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder);
- final XmlParserStream xmlParser = XmlParserStream.create(writer, getSchemaContext(), schemaNode);
-
- xmlParser.parse(UntrustedXML.createXMLStreamReader(new StringReader(rawValue)));
- return Optional.of((DataContainerChild<?, ?>) resultHolder.getResult());
- } catch (final Exception e) {
- // TODO log
- return Optional.absent();
- }
- }
-
- @Override
- protected ConsoleContext getContext(final AnyXmlSchemaNode schemaNode) {
- return new BaseConsoleContext<>(schemaNode);
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.reader.impl;
-
-import static org.opendaylight.netconf.cli.io.IOUtil.isSkipInput;
-import static org.opendaylight.netconf.cli.io.IOUtil.listType;
-
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.collect.BiMap;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.HashBiMap;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-import jline.console.completer.Completer;
-import jline.console.completer.StringsCompleter;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.cli.io.IOUtil;
-import org.opendaylight.netconf.cli.reader.AbstractReader;
-import org.opendaylight.netconf.cli.reader.ReadingException;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair;
-import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public abstract class BasicDataHolderReader<T extends DataSchemaNode> extends AbstractReader<T> {
-
- private static final Logger LOG = LoggerFactory.getLogger(BasicDataHolderReader.class);
- private DataHolderCompleter currentCompleter;
-
- public BasicDataHolderReader(final ConsoleIO console, final SchemaContext schemaContext,
- final boolean readConfigNode) {
- super(console, schemaContext, readConfigNode);
- }
-
- public BasicDataHolderReader(final ConsoleIO console, final SchemaContext schemaContext) {
- super(console, schemaContext);
- }
-
- @Override
- public List<NormalizedNode<?, ?>> readWithContext(final T schemaNode) throws IOException, ReadingException {
- TypeDefinition<?> type = getType(schemaNode);
- console.formatLn("Submit %s %s(%s)", listType(schemaNode), schemaNode.getQName().getLocalName(),
- type.getQName().getLocalName());
-
- while (baseTypeFor(type) instanceof UnionTypeDefinition) {
- final Optional<TypeDefinition<?>> optionalTypeDef = new UnionTypeReader(console).read(type);
- if (!optionalTypeDef.isPresent()) {
- return postSkipOperations(schemaNode);
- }
- type = optionalTypeDef.get();
- }
-
- if (currentCompleter == null) {
- currentCompleter = getBaseCompleter(schemaNode);
- }
-
- // TODO what if type is leafref, instance-identifier?
-
- // Handle empty type leaf by question
- if (isEmptyType(type)) {
- final Optional<Boolean> shouldAddEmpty = new DecisionReader().read(console, "Add empty type leaf %s ?",
- schemaNode.getQName().getLocalName());
- if (shouldAddEmpty.isPresent()) {
- if (shouldAddEmpty.get()) {
- return wrapValue(schemaNode, "");
- } else {
- return Collections.emptyList();
- }
- } else {
- return postSkipOperations(schemaNode);
- }
- }
-
- final String rawValue = readValue();
- if (isSkipInput(rawValue)) {
- return postSkipOperations(schemaNode);
- }
-
- final Object resolvedValue = currentCompleter.resolveValue(rawValue);
-
- // Reset state TODO should be in finally
- currentCompleter = null;
- return wrapValue(schemaNode, resolvedValue);
- }
-
- private List<NormalizedNode<?, ?>> postSkipOperations(final DataSchemaNode schemaNode) throws IOException {
- console.formatLn("Skipping %s", schemaNode.getQName());
- return Collections.emptyList();
- }
-
- private TypeDefinition<?> baseTypeFor(final TypeDefinition<?> type) {
- if (type.getBaseType() != null) {
- return baseTypeFor(type.getBaseType());
- }
- return type;
- }
-
- protected String readValue() throws IOException {
- return console.read();
- }
-
- private List<NormalizedNode<?, ?>> wrapValue(final T schemaNode, final Object value) {
- final NormalizedNode<?, ?> newNode = ImmutableLeafNodeBuilder.create()
- .withNodeIdentifier(new NodeIdentifier(schemaNode.getQName()))
- .withValue(value).build();
- return Collections.<NormalizedNode<?, ?>>singletonList(newNode);
- }
-
- protected abstract TypeDefinition<?> getType(T schemaNode);
-
- protected final DataHolderCompleter getBaseCompleter(final T schemaNode) {
- final TypeDefinition<?> type = getType(schemaNode);
- final DataHolderCompleter currentCompleter;
-
- // Add enum completer
- if (type instanceof EnumTypeDefinition) {
- currentCompleter = new EnumDataHolderCompleter(type);
- } else if (type instanceof IdentityrefTypeDefinition) {
- currentCompleter = new IdentityRefDataHolderCompleter(type, getSchemaContext());
- } else {
- currentCompleter = new GeneralDataHolderCompleter(type);
- }
- this.currentCompleter = currentCompleter;
- return currentCompleter;
- }
-
- private interface DataHolderCompleter extends Completer {
- Object resolveValue(String rawValue) throws ReadingException;
- }
-
- private static class GeneralDataHolderCompleter implements DataHolderCompleter {
-
- private final Optional<TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>>> codec;
- private final TypeDefinition<?> type;
-
- GeneralDataHolderCompleter(final TypeDefinition<?> type) {
- this.type = type;
- codec = getCodecForType(type);
- }
-
- protected TypeDefinition<?> getType() {
- return type;
- }
-
- private static Optional<TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>>> getCodecForType(
- final TypeDefinition<?> type) {
- if (type != null) {
- return Optional.fromNullable(TypeDefinitionAwareCodec.from(type));
- }
- return Optional.absent();
- }
-
- @SuppressWarnings("illegalCatch")
- @Override
- public Object resolveValue(final String rawValue) throws ReadingException {
- try {
- return codec.isPresent() ? codec.get().deserialize(rawValue) : rawValue;
- } catch (final Exception e) {
- final String message = "It wasn't possible deserialize value " + rawValue + ".";
- LOG.error(message, e);
- throw new ReadingException(message, e);
- }
- }
-
- @Override
- public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
- return 0;
- }
- }
-
- private static final class EnumDataHolderCompleter extends GeneralDataHolderCompleter {
-
- EnumDataHolderCompleter(final TypeDefinition<?> type) {
- super(type);
- }
-
- @Override
- public Object resolveValue(final String rawValue) throws ReadingException {
- return super.resolveValue(rawValue);
- }
-
- @Override
- public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
- return new StringsCompleter(Collections2.transform(((EnumTypeDefinition) getType()).getValues(),
- EnumPair::getName)).complete(buffer, cursor, candidates);
- }
- }
-
- private static final class IdentityRefDataHolderCompleter extends GeneralDataHolderCompleter {
-
- private final BiMap<String, QName> identityMap;
-
- IdentityRefDataHolderCompleter(final TypeDefinition<?> type, final SchemaContext schemaContext) {
- super(type);
- this.identityMap = getIdentityMap(schemaContext);
- }
-
- private static BiMap<String, QName> getIdentityMap(final SchemaContext schemaContext) {
- final BiMap<String, QName> identityMap = HashBiMap.create();
- for (final Module module : schemaContext.getModules()) {
- for (final IdentitySchemaNode identity : module.getIdentities()) {
- identityMap.put(getIdentityName(identity, module), identity.getQName());
- }
- }
- return identityMap;
- }
-
- private static String getIdentityName(final IdentitySchemaNode rpcDefinition, final Module module) {
- return IOUtil.qNameToKeyString(rpcDefinition.getQName(), module.getName());
- }
-
- @Override
- public Object resolveValue(final String rawValue) throws ReadingException {
- final QName qName = identityMap.get(rawValue);
- if (qName == null) {
- throw new ReadingException("No identity found for " + rawValue + " available " + identityMap.keySet());
- }
- return qName;
- }
-
- @Override
- public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
-
- return new StringsCompleter(Collections2.transform(((IdentityrefTypeDefinition) getType()).getIdentity()
- .getDerivedIdentities(), new Function<IdentitySchemaNode, String>() {
- @Override
- public String apply(final IdentitySchemaNode input) {
- return identityMap.inverse().get(input.getQName());
- }
- })).complete(buffer, cursor, candidates);
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.reader.impl;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Maps;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import jline.console.completer.Completer;
-import jline.console.completer.StringsCompleter;
-import org.opendaylight.netconf.cli.CommandArgHandlerRegistry;
-import org.opendaylight.netconf.cli.io.BaseConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.cli.io.IOUtil;
-import org.opendaylight.netconf.cli.reader.AbstractReader;
-import org.opendaylight.netconf.cli.reader.ReadingException;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ChoiceReader extends AbstractReader<ChoiceSchemaNode> {
-
- private static final Logger LOG = LoggerFactory.getLogger(ChoiceReader.class);
-
- private final CommandArgHandlerRegistry argumentHandlerRegistry;
-
- public ChoiceReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
- final SchemaContext schemaContext) {
- super(console, schemaContext);
- this.argumentHandlerRegistry = argumentHandlerRegistry;
- }
-
- public ChoiceReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
- final SchemaContext schemaContext, final boolean readConfigNode) {
- super(console, schemaContext, readConfigNode);
- this.argumentHandlerRegistry = argumentHandlerRegistry;
- }
-
- @Override
- public List<NormalizedNode<?, ?>> readWithContext(final ChoiceSchemaNode choiceNode)
- throws IOException, ReadingException {
- final Map<String, ChoiceCaseNode> availableCases = collectAllCases(choiceNode);
- console.formatLn("Select case for choice %s from: %s", choiceNode.getQName().getLocalName(),
- formatSet(availableCases.keySet()));
-
- ChoiceCaseNode selectedCase = null;
- final String rawValue = console.read();
- if (IOUtil.isSkipInput(rawValue)) {
- return Collections.emptyList();
- }
-
- selectedCase = availableCases.get(rawValue);
- if (selectedCase == null) {
- final String message = String.format("Incorrect value (%s) for choice %s was selected.", rawValue,
- choiceNode.getQName().getLocalName());
- LOG.error(message);
- throw new ReadingException(message);
- }
-
- return Collections.<NormalizedNode<?, ?>>singletonList(
- ImmutableChoiceNodeBuilder.create()
- .withNodeIdentifier(new NodeIdentifier(choiceNode.getQName()))
- .withValue(((Collection) readSelectedCase(selectedCase))).build());
- }
-
- protected List<NormalizedNode<?, ?>> readSelectedCase(final ChoiceCaseNode selectedCase) throws ReadingException {
- // IF there is a case that contains only one Empty type leaf, create the
- // leaf without question, since the case was selected
- if (containsOnlyOneEmptyLeaf(selectedCase)) {
- final NormalizedNode<?, ?> newNode = ImmutableLeafNodeBuilder.create()
- .withNodeIdentifier(new NodeIdentifier(selectedCase.getChildNodes().iterator().next().getQName()))
- .build();
- return Collections.<NormalizedNode<?, ?>>singletonList(newNode);
- }
-
- final List<NormalizedNode<?, ?>> newNodes = new ArrayList<>();
- for (final DataSchemaNode schemaNode : selectedCase.getChildNodes()) {
- newNodes.addAll(argumentHandlerRegistry.getGenericReader(getSchemaContext(), getReadConfigNode()).read(
- schemaNode));
- }
- return newNodes;
- }
-
- private static Object formatSet(final Set<String> values) {
- final StringBuilder formatedValues = new StringBuilder();
- for (final String value : values) {
- formatedValues.append("\n ");
- formatedValues.append(value);
- }
- return formatedValues.toString();
- }
-
- private static boolean containsOnlyOneEmptyLeaf(final ChoiceCaseNode selectedCase) {
- if (selectedCase.getChildNodes().size() != 1) {
- return false;
- }
- final DataSchemaNode next = selectedCase.getChildNodes().iterator().next();
- if (next instanceof LeafSchemaNode) {
- final TypeDefinition<?> type = ((LeafSchemaNode) next).getType();
- if (isEmptyType(type)) {
- return true;
- }
- }
- return false;
- }
-
- private static Map<String, ChoiceCaseNode> collectAllCases(final ChoiceSchemaNode schemaNode) {
- return Maps.uniqueIndex(schemaNode.getCases(), new Function<ChoiceCaseNode, String>() {
- @Override
- public String apply(final ChoiceCaseNode input) {
- return input.getQName().getLocalName();
- }
- });
- }
-
- @Override
- protected ConsoleContext getContext(final ChoiceSchemaNode schemaNode) {
- return new BaseConsoleContext<ChoiceSchemaNode>(schemaNode) {
- @Override
- public List<Completer> getAdditionalCompleters() {
- return Collections.<Completer>singletonList(
- new StringsCompleter(collectAllCases(schemaNode).keySet()));
- }
- };
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.reader.impl;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.Lists;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Set;
-import org.opendaylight.netconf.cli.CommandArgHandlerRegistry;
-import org.opendaylight.netconf.cli.io.BaseConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.cli.reader.AbstractReader;
-import org.opendaylight.netconf.cli.reader.ReadingException;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-public class ContainerReader extends AbstractReader<ContainerSchemaNode> {
-
- private final CommandArgHandlerRegistry argumentHandlerRegistry;
- private static final InputArgsLocalNameComparator CONTAINER_CHILDS_SORTER = new InputArgsLocalNameComparator();
-
- public ContainerReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
- final SchemaContext schemaContext) {
- super(console, schemaContext);
- this.argumentHandlerRegistry = argumentHandlerRegistry;
- }
-
- public ContainerReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
- final SchemaContext schemaContext, final boolean readConfigNode) {
- super(console, schemaContext, readConfigNode);
- this.argumentHandlerRegistry = argumentHandlerRegistry;
- }
-
- @Override
- public List<NormalizedNode<?, ?>> readWithContext(final ContainerSchemaNode containerNode)
- throws IOException, ReadingException {
- console.formatLn("Submit child nodes for container: %s, %s", containerNode.getQName().getLocalName(),
- Collections2.transform(containerNode.getChildNodes(), new Function<DataSchemaNode, String>() {
- @Override
- public String apply(final DataSchemaNode input) {
- return input.getQName().getLocalName();
- }
- }));
- final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> builder = ImmutableContainerNodeBuilder
- .create();
- builder.withNodeIdentifier(new NodeIdentifier(containerNode.getQName()));
-
- final ArrayList<NormalizedNode<?, ?>> nodesToAdd = new ArrayList<>();
- final SeparatedNodes separatedNodes = SeparatedNodes.separateNodes(containerNode, getReadConfigNode());
- for (final DataSchemaNode childNode : sortChildren(separatedNodes.getMandatoryNotKey())) {
- final List<NormalizedNode<?, ?>> redNodes = argumentHandlerRegistry.getGenericReader(getSchemaContext(),
- getReadConfigNode()).read(childNode);
- if (redNodes.isEmpty()) {
- console.formatLn("No data specified for mandatory element %s.", childNode.getQName().getLocalName());
- return Collections.emptyList();
- } else {
- nodesToAdd.addAll(redNodes);
- }
- }
-
- for (final DataSchemaNode childNode : sortChildren(separatedNodes.getOthers())) {
- nodesToAdd.addAll(argumentHandlerRegistry.getGenericReader(getSchemaContext(),
- getReadConfigNode()).read(childNode));
- }
- return Collections.singletonList(builder.withValue((ArrayList) nodesToAdd).build());
- }
-
- private List<DataSchemaNode> sortChildren(final Set<DataSchemaNode> unsortedNodes) {
- final List<DataSchemaNode> childNodes = Lists.newArrayList(unsortedNodes);
- Collections.sort(childNodes, CONTAINER_CHILDS_SORTER);
- return childNodes;
- }
-
- @Override
- protected ConsoleContext getContext(final ContainerSchemaNode schemaNode) {
- return new BaseConsoleContext<>(schemaNode);
- }
-
- private static class InputArgsLocalNameComparator implements Comparator<DataSchemaNode> {
- @Override
- public int compare(final DataSchemaNode o1, final DataSchemaNode o2) {
- return o1.getQName().getLocalName().compareTo(o2.getQName().getLocalName());
- }
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.reader.impl;
-
-import static org.opendaylight.netconf.cli.io.IOUtil.SKIP;
-
-import com.google.common.base.Optional;
-import java.io.IOException;
-import jline.console.completer.AggregateCompleter;
-import jline.console.completer.Completer;
-import jline.console.completer.StringsCompleter;
-import jline.internal.Log;
-import org.opendaylight.netconf.cli.io.ConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.cli.io.IOUtil;
-import org.opendaylight.netconf.cli.reader.ReadingException;
-
-public class DecisionReader {
-
- private static final String YES = "Y";
- private static final String NO = "N";
- public static final Completer YES_NO_COMPLETER = new StringsCompleter(YES, NO);
-
- public Optional<Boolean> read(final ConsoleIO console, final String questionMessageBlueprint,
- final Object... questionMessageArgs) throws IOException, ReadingException {
- final ConsoleContext ctx = getContext();
- console.enterContext(ctx);
- try {
- console.formatLn(questionMessageBlueprint, questionMessageArgs);
- final String rawValue = console.read();
- if (YES.equals(rawValue.toUpperCase())) {
- return Optional.of(Boolean.TRUE);
- } else if (NO.equals(rawValue.toUpperCase())) {
- return Optional.of(Boolean.FALSE);
- } else if (SKIP.equals(rawValue)) {
- return Optional.absent();
- } else {
- final String message = String.format("Incorrect possibility (%s) was selected", rawValue);
- Log.error(message);
- throw new ReadingException(message);
- }
- } finally {
- console.leaveContext();
- }
- }
-
- private static ConsoleContext getContext() {
- return new ConsoleContext() {
-
- @Override
- public Optional<String> getPrompt() {
- return Optional.absent();
- }
-
- @Override
- public Completer getCompleter() {
- return new AggregateCompleter(YES_NO_COMPLETER, new StringsCompleter(IOUtil.SKIP));
- }
-
- };
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.reader.impl;
-
-import static org.opendaylight.netconf.cli.io.IOUtil.listType;
-
-import com.google.common.base.Optional;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import org.opendaylight.netconf.cli.io.BaseConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.cli.reader.AbstractReader;
-import org.opendaylight.netconf.cli.reader.GenericListEntryReader;
-import org.opendaylight.netconf.cli.reader.ReadingException;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class GenericListReader<T extends DataSchemaNode> extends AbstractReader<T> {
- private static final Logger LOG = LoggerFactory.getLogger(GenericListReader.class);
-
- private final GenericListEntryReader<T> concreteListEntryReader;
-
- public GenericListReader(final ConsoleIO console, final GenericListEntryReader<T> concreteListEntryReader,
- final SchemaContext schemaContext) {
- super(console, schemaContext);
- this.concreteListEntryReader = concreteListEntryReader;
- }
-
- public GenericListReader(final ConsoleIO console, final GenericListEntryReader<T> concreteListEntryReader,
- final SchemaContext schemaContext, final boolean readConfigNode) {
- super(console, schemaContext, readConfigNode);
- this.concreteListEntryReader = concreteListEntryReader;
- }
-
- @Override
- public List<NormalizedNode<?, ?>> readWithContext(final T schemaNode) throws IOException, ReadingException {
- final List<NormalizedNode<?, ?>> newNodes = new ArrayList<>();
- Optional<Boolean> readNextListEntry = Optional.of(Boolean.TRUE);
- console.formatLn("Reading collection type argument: %s", schemaNode.getQName().getLocalName());
- while (readNextListEntry.isPresent() && readNextListEntry.get()) {
- try {
- newNodes.addAll(concreteListEntryReader.read(schemaNode));
- } catch (final ReadingException e) {
- console.writeLn(e.getMessage());
- }
- readNextListEntry = new DecisionReader().read(console, "Add other entry to " + listType(schemaNode) + " "
- + schemaNode.getQName().getLocalName() + " " + " [Y|N]?");
- }
- console.formatLn("Collection type argument: %s read finished", schemaNode.getQName().getLocalName());
-
- return newNodes;
- }
-
- @Override
- protected ConsoleContext getContext(final T schemaNode) {
- return new BaseConsoleContext<>(schemaNode);
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.reader.impl;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import org.opendaylight.netconf.cli.CommandArgHandlerRegistry;
-import org.opendaylight.netconf.cli.commands.CommandConstants;
-import org.opendaylight.netconf.cli.io.ConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.cli.reader.AbstractReader;
-import org.opendaylight.netconf.cli.reader.GenericListEntryReader;
-import org.opendaylight.netconf.cli.reader.Reader;
-import org.opendaylight.netconf.cli.reader.ReadingException;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
-
-public class GenericReader extends AbstractReader<DataSchemaNode> {
-
- private final CommandArgHandlerRegistry argumentHandlerRegistry;
-
- public GenericReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
- final SchemaContext schemaContext) {
- super(console, schemaContext);
- this.argumentHandlerRegistry = argumentHandlerRegistry;
- }
-
- public GenericReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
- final SchemaContext schemaContext, final boolean readConfigNode) {
- super(console, schemaContext, readConfigNode);
- this.argumentHandlerRegistry = argumentHandlerRegistry;
- }
-
- @Override
- protected List<NormalizedNode<?, ?>> readWithContext(final DataSchemaNode schemaNode)
- throws IOException, ReadingException {
- final Optional<Class<? extends Reader<DataSchemaNode>>> customReaderClassOpt = tryGetCustomHandler(schemaNode);
-
- if (customReaderClassOpt.isPresent()) {
- // TODO resolve class cast of generic custom readers
- final Reader<DataSchemaNode> customReaderInstance = (Reader<DataSchemaNode>) argumentHandlerRegistry
- .getCustomReader(customReaderClassOpt.get());
- Preconditions.checkNotNull(customReaderInstance, "Unknown custom reader: %s", customReaderClassOpt.get());
- return customReaderInstance.read(schemaNode);
- } else {
- return readGeneric(schemaNode);
- }
-
- // TODO reuse instances
- }
-
- private List<NormalizedNode<?, ?>> readGeneric(final DataSchemaNode schemaNode)
- throws ReadingException, IOException {
- final List<NormalizedNode<?, ?>> newNodes = new ArrayList<>();
- boolean isRedCorrectly = false;
- do {
- try {
- if (schemaNode instanceof LeafSchemaNode) {
- return new LeafReader(console, getSchemaContext(), getReadConfigNode())
- .read((LeafSchemaNode) schemaNode);
- } else if (schemaNode instanceof ContainerSchemaNode) {
- return new ContainerReader(console, argumentHandlerRegistry, getSchemaContext(),
- getReadConfigNode()).read((ContainerSchemaNode) schemaNode);
- } else if (schemaNode instanceof ListSchemaNode) {
- final GenericListEntryReader<ListSchemaNode> entryReader = new ListEntryReader(console,
- argumentHandlerRegistry, getSchemaContext(), getReadConfigNode());
- return new GenericListReader<>(console, entryReader, getSchemaContext(), getReadConfigNode())
- .read((ListSchemaNode) schemaNode);
- } else if (schemaNode instanceof LeafListSchemaNode) {
- final GenericListEntryReader<LeafListSchemaNode> entryReader = new LeafListEntryReader(console,
- getSchemaContext(), getReadConfigNode());
- return new GenericListReader<>(console, entryReader, getSchemaContext(), getReadConfigNode())
- .read((LeafListSchemaNode) schemaNode);
- } else if (schemaNode instanceof ChoiceSchemaNode) {
- return new ChoiceReader(console, argumentHandlerRegistry, getSchemaContext(), getReadConfigNode())
- .read((ChoiceSchemaNode) schemaNode);
- } else if (schemaNode instanceof AnyXmlSchemaNode) {
- return new AnyXmlReader(console, getSchemaContext(), getReadConfigNode())
- .read((AnyXmlSchemaNode) schemaNode);
- }
- isRedCorrectly = true;
- } catch (final ReadingException e) {
- console.writeLn(e.getMessage());
- }
- } while (!isRedCorrectly);
- return newNodes;
- }
-
- @Override
- protected ConsoleContext getContext(final DataSchemaNode schemaNode) {
- // return null context, leave context to specific implementations
- return NULL_CONTEXT;
- }
-
- private <T> Optional<Class<? extends T>> tryGetCustomHandler(final DataSchemaNode dataSchemaNode) {
-
- for (final UnknownSchemaNode unknownSchemaNode : dataSchemaNode.getUnknownSchemaNodes()) {
-
- if (isExtenstionForCustomHandler(unknownSchemaNode)) {
- final String argumentHandlerClassName = unknownSchemaNode.getNodeParameter();
- try {
- final Class<?> argumentClass = Class.forName(argumentHandlerClassName);
- // TODO add check before cast
- return Optional.of((Class<? extends T>) argumentClass);
- } catch (final ClassNotFoundException e) {
- throw new IllegalArgumentException("Unknown custom reader class " + argumentHandlerClassName
- + " for: " + dataSchemaNode.getQName());
- }
- }
- }
-
- return Optional.absent();
- }
-
- private boolean isExtenstionForCustomHandler(final UnknownSchemaNode unknownSchemaNode) {
- final QName qName = unknownSchemaNode.getExtensionDefinition().getQName();
- return qName.equals(CommandConstants.ARG_HANDLER_EXT_QNAME);
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.netconf.cli.reader.impl;
-
-import com.google.common.base.Optional;
-import com.google.common.collect.Lists;
-import java.util.List;
-import jline.console.completer.Completer;
-import org.opendaylight.netconf.cli.io.BaseConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.cli.reader.GenericListEntryReader;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-
-class LeafListEntryReader extends BasicDataHolderReader<LeafListSchemaNode> implements
- GenericListEntryReader<LeafListSchemaNode> {
-
- LeafListEntryReader(final ConsoleIO console, final SchemaContext schemaContext) {
- super(console, schemaContext);
- }
-
- LeafListEntryReader(final ConsoleIO console, final SchemaContext schemaContext, final boolean readConfigNode) {
- super(console, schemaContext, readConfigNode);
- }
-
- @Override
- protected TypeDefinition<?> getType(final LeafListSchemaNode schemaNode) {
- return schemaNode.getType();
- }
-
- @Override
- protected ConsoleContext getContext(final LeafListSchemaNode schemaNode) {
- return new BaseConsoleContext<LeafListSchemaNode>(schemaNode) {
-
- @Override
- public Optional<String> getPrompt() {
- return Optional.of("[entry]");
- }
-
- @Override
- protected List<Completer> getAdditionalCompleters() {
- return Lists.newArrayList(getBaseCompleter(getDataSchemaNode()));
- }
- };
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.reader.impl;
-
-import com.google.common.base.Optional;
-import com.google.common.collect.Lists;
-import java.util.List;
-import jline.console.completer.Completer;
-import jline.console.completer.StringsCompleter;
-import org.opendaylight.netconf.cli.io.BaseConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-
-public class LeafReader extends BasicDataHolderReader<LeafSchemaNode> {
-
- public LeafReader(final ConsoleIO console, final SchemaContext schemaContext) {
- super(console, schemaContext);
- }
-
- public LeafReader(final ConsoleIO console, final SchemaContext schemaContext, final boolean readConfigNode) {
- super(console, schemaContext, readConfigNode);
- }
-
- @Override
- protected TypeDefinition<?> getType(final LeafSchemaNode schemaNode) {
- return schemaNode.getType();
- }
-
- @Override
- protected ConsoleContext getContext(final LeafSchemaNode schemaNode) {
- return new BaseConsoleContext<LeafSchemaNode>(schemaNode) {
- @Override
- public List<Completer> getAdditionalCompleters() {
- final List<Completer> completers = Lists.newArrayList(getBaseCompleter(schemaNode));
- final Optional<String> defaultValue = getDefaultValue(schemaNode);
- if (defaultValue.isPresent()) {
- completers.add(new StringsCompleter(defaultValue.get()));
- }
- return completers;
- }
- };
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.reader.impl;
-
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.collect.Collections2;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.opendaylight.netconf.cli.CommandArgHandlerRegistry;
-import org.opendaylight.netconf.cli.io.BaseConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.cli.reader.AbstractReader;
-import org.opendaylight.netconf.cli.reader.GenericListEntryReader;
-import org.opendaylight.netconf.cli.reader.ReadingException;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-class ListEntryReader extends AbstractReader<ListSchemaNode> implements GenericListEntryReader<ListSchemaNode> {
- private static final Logger LOG = LoggerFactory.getLogger(ListEntryReader.class);
-
- private final CommandArgHandlerRegistry argumentHandlerRegistry;
-
- ListEntryReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
- final SchemaContext schemaContext) {
- super(console, schemaContext);
- this.argumentHandlerRegistry = argumentHandlerRegistry;
- }
-
- ListEntryReader(final ConsoleIO console, final CommandArgHandlerRegistry argumentHandlerRegistry,
- final SchemaContext schemaContext, final boolean readConfigNode) {
- super(console, schemaContext, readConfigNode);
- this.argumentHandlerRegistry = argumentHandlerRegistry;
- }
-
- @Override
- public List<NormalizedNode<?, ?>> readWithContext(final ListSchemaNode listNode)
- throws IOException, ReadingException {
- console.formatLn("Submit child nodes for list entry: %s, %s", listNode.getQName().getLocalName(),
- Collections2.transform(listNode.getChildNodes(), new Function<DataSchemaNode, String>() {
- @Override
- public String apply(final DataSchemaNode input) {
- return input.getQName().getLocalName();
- }
- }));
-
- final String listName = listNode.getQName().getLocalName();
-
- final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> builder =
- ImmutableMapEntryNodeBuilder.create();
-// final CompositeNodeBuilder<ImmutableCompositeNode> compositeNodeBuilder = ImmutableCompositeNode.builder();
-// compositeNodeBuilder.setQName(listNode.getQName());
-
- final SeparatedNodes separatedChildNodes = SeparatedNodes.separateNodes(listNode, getReadConfigNode());
-
- final List<NormalizedNode<?, ?>> nodes = readKeys(separatedChildNodes.getKeyNodes());
- final Map<QName, Object> qnameToValues = new HashMap<>();
- for (NormalizedNode node : nodes) {
- qnameToValues.put(node.getNodeType(), node.getValue());
- }
- builder.withNodeIdentifier(new NodeIdentifierWithPredicates(listNode.getQName(), qnameToValues));
-
- nodes.addAll(readMandatoryNotKeys(separatedChildNodes.getMandatoryNotKey()));
- if (!separatedChildNodes.getOthers().isEmpty()) {
- final Optional<Boolean> readNodesWhichAreNotKey = new DecisionReader().read(console,
- "Add non-key, non-mandatory nodes to list %s? [Y|N]", listName);
- if (readNodesWhichAreNotKey.isPresent() && readNodesWhichAreNotKey.get()) {
- nodes.addAll(readNotKeys(separatedChildNodes.getOthers()));
- }
- }
-
- if (!nodes.isEmpty()) {
-// compositeNodeBuilder.addAll(nodes);
- builder.withValue((List) nodes);
- return Collections.<NormalizedNode<?, ?>>singletonList(
- ImmutableMapNodeBuilder.create()
- .withNodeIdentifier(new NodeIdentifier(listNode.getQName()))
- .withChild(builder.build()).build());
-// return Collections.<DataContainerChild<?, ?>> singletonList(compositeNodeBuilder.build());
- } else {
- return Collections.emptyList();
- }
- }
-
- private List<NormalizedNode<?, ?>> readKeys(final Set<DataSchemaNode> keys) throws ReadingException, IOException {
- final List<NormalizedNode<?, ?>> newNodes = new ArrayList<>();
- console.writeLn("Reading keys:");
- for (final DataSchemaNode key : keys) {
- final List<NormalizedNode<?, ?>> readKey = new LeafReader(console, getSchemaContext(), getReadConfigNode())
- .read((LeafSchemaNode) key);
- if (readKey.size() != 1) {
- final String message = String.format(
- "Value for key element %s has to be set. Creation of this entry is canceled.", key.getQName()
- .getLocalName());
- LOG.error(message);
- throw new ReadingException(message);
- }
- newNodes.addAll(readKey);
- }
-
- return newNodes;
- }
-
- private List<NormalizedNode<?, ?>> readMandatoryNotKeys(final Set<DataSchemaNode> mandatoryNotKeys)
- throws ReadingException, IOException {
- final List<NormalizedNode<?, ?>> newNodes = new ArrayList<>();
- console.writeLn("Reading mandatory not keys nodes:");
-
- for (final DataSchemaNode mandatoryNode : mandatoryNotKeys) {
- final List<NormalizedNode<?, ?>> redValue = argumentHandlerRegistry.getGenericReader(getSchemaContext(),
- getReadConfigNode()).read(mandatoryNode);
- if (redValue.isEmpty()) {
- final String message = String.format(
- "Value for mandatory element %s has to be set. Creation of this entry is canceled.",
- mandatoryNode.getQName().getLocalName());
- LOG.error(message);
- throw new ReadingException(message);
- }
- newNodes.addAll(redValue);
- }
- return newNodes;
- }
-
- private List<NormalizedNode<?, ?>> readNotKeys(final Set<DataSchemaNode> notKeys) throws ReadingException {
- final List<NormalizedNode<?, ?>> newNodes = new ArrayList<>();
- for (final DataSchemaNode notKey : notKeys) {
- newNodes.addAll(argumentHandlerRegistry.getGenericReader(getSchemaContext(), getReadConfigNode()).read(
- notKey));
- }
- return newNodes;
- }
-
- @Override
- protected ConsoleContext getContext(final ListSchemaNode schemaNode) {
- return new BaseConsoleContext<ListSchemaNode>(schemaNode) {
- @Override
- public Optional<String> getPrompt() {
- return Optional.of("[entry]");
- }
- };
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.reader.impl;
-
-import com.google.common.base.Preconditions;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-
-class SeparatedNodes {
- private final Set<DataSchemaNode> keyNodes;
- private final Set<DataSchemaNode> mandatoryNotKey;
- private final Set<DataSchemaNode> otherNodes;
-
- private SeparatedNodes(final Set<DataSchemaNode> keyNodes, final Set<DataSchemaNode> mandatoryNotKey,
- final Set<DataSchemaNode> otherNodes) {
- this.keyNodes = keyNodes;
- this.mandatoryNotKey = mandatoryNotKey;
- this.otherNodes = otherNodes;
- }
-
- public Set<DataSchemaNode> getKeyNodes() {
- return keyNodes;
- }
-
- public Set<DataSchemaNode> getMandatoryNotKey() {
- return mandatoryNotKey;
- }
-
- public Set<DataSchemaNode> getOthers() {
- return otherNodes;
- }
-
- static SeparatedNodes separateNodes(final DataNodeContainer dataNodeContainer) {
- return separateNodes(dataNodeContainer, false);
- }
-
- static SeparatedNodes separateNodes(final DataNodeContainer dataNodeContainer,
- final boolean removeConfigFalseNodes) {
- final Set<DataSchemaNode> keys = new HashSet<>();
- final Set<DataSchemaNode> mandatoryNotKeys = new HashSet<>();
- final Set<DataSchemaNode> others = new HashSet<>();
-
- List<QName> keyQNames = Collections.emptyList();
- if (dataNodeContainer instanceof ListSchemaNode) {
- keyQNames = ((ListSchemaNode) dataNodeContainer).getKeyDefinition();
- }
-
- for (final DataSchemaNode dataSchemaNode : dataNodeContainer.getChildNodes()) {
- if (removeConfigFalseNodes) {
- if (!dataSchemaNode.isConfiguration()) {
- continue;
- }
- }
- if (keyQNames.contains(dataSchemaNode.getQName())) {
- Preconditions.checkArgument(dataSchemaNode instanceof LeafSchemaNode);
- keys.add(dataSchemaNode);
- } else if (dataSchemaNode.getConstraints().isMandatory()) {
- mandatoryNotKeys.add(dataSchemaNode);
- } else {
- others.add(dataSchemaNode);
- }
- }
-
- return new SeparatedNodes(keys, mandatoryNotKeys, others);
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.reader.impl;
-
-import com.google.common.base.Optional;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import jline.console.completer.AggregateCompleter;
-import jline.console.completer.Completer;
-import jline.console.completer.StringsCompleter;
-import org.opendaylight.netconf.cli.io.ConsoleContext;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.cli.io.IOUtil;
-import org.opendaylight.netconf.cli.reader.ReadingException;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-class UnionTypeReader {
- private static final Logger LOG = LoggerFactory.getLogger(UnionTypeReader.class);
-
- private final ConsoleIO console;
-
- UnionTypeReader(final ConsoleIO console) {
- this.console = console;
- }
-
- public Optional<TypeDefinition<?>> read(final TypeDefinition<?> unionTypeDefinition) throws IOException,
- ReadingException {
- final ConsoleContext context = getContext(unionTypeDefinition);
- console.enterContext(context);
- try {
- final Map<String, TypeDefinition<?>> mapping = ((UnionConsoleContext) context).getMenuItemMapping();
- console.formatLn("The element is of type union. Choose concrete type from: %s", mapping.keySet());
-
- final String rawValue = console.read();
- if (IOUtil.isSkipInput(rawValue)) {
- return Optional.absent();
- }
- final TypeDefinition<?> value = mapping.get(rawValue);
- if (value != null) {
- return Optional.of(value);
- } else {
- final String message = String.format(
- "Incorrect type (%s) was specified for union type definition", rawValue);
- LOG.error(message);
- throw new ReadingException(message);
- }
- } finally {
- console.leaveContext();
- }
- }
-
- private UnionConsoleContext getContext(final TypeDefinition<?> typeDefinition) {
- return new UnionConsoleContext(typeDefinition);
- }
-
- private class UnionConsoleContext implements ConsoleContext {
-
- private final TypeDefinition<?> typeDef;
- private final Map<String, TypeDefinition<?>> menuItemsToTypeDefinitions = new HashMap<>();
-
- UnionConsoleContext(final TypeDefinition<?> typeDef) {
- this.typeDef = typeDef;
- }
-
- @Override
- public Optional<String> getPrompt() {
- return Optional.of("type[" + typeDef.getQName().getLocalName() + "]");
- }
-
- @Override
- public Completer getCompleter() {
- List<TypeDefinition<?>> subtypesForMenu = resolveSubtypesFrom(typeDef);
- if (subtypesForMenu.isEmpty()) {
- subtypesForMenu = Collections.singletonList(typeDef);
- }
- final Collection<String> menuItems = toMenuItem(subtypesForMenu);
- return new AggregateCompleter(new StringsCompleter(menuItems), new StringsCompleter(IOUtil.SKIP));
- }
-
- public Map<String, TypeDefinition<?>> getMenuItemMapping() {
- return menuItemsToTypeDefinitions;
- }
-
- private Collection<String> toMenuItem(final List<TypeDefinition<?>> allTypesBehindUnion) {
- final List<String> result = new ArrayList<String>();
- for (final TypeDefinition<?> type : allTypesBehindUnion) {
- final String menuItem = type.getQName().getLocalName();
- menuItemsToTypeDefinitions.put(menuItem, type);
- result.add(menuItem);
- }
- return result;
- }
-
- /**
- * If union type is found in potentialEndTypeCandidate as subtype then
- * it these subtypes become candidates.
- *
- * @param potentialEndTypeCandidate
- * candidate to node which has no union subtype
- */
- private List<TypeDefinition<?>> resolveSubtypesFrom(final TypeDefinition<?> potentialEndTypeCandidate) {
- if (potentialEndTypeCandidate instanceof UnionTypeDefinition) {
- return ((UnionTypeDefinition) potentialEndTypeCandidate).getTypes();
- }
- if (potentialEndTypeCandidate.getBaseType() == null) {
- return Collections.emptyList();
- }
- return resolveSubtypesFrom(potentialEndTypeCandidate.getBaseType());
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.writer;
-
-public class OutFormatter {
-
- public static final String INDENT_STEP = " ";
- public static final String COMPOSITE_OPEN_NODE = " {";
- public static final String COMPOSITE_CLOSE_NODE = "}";
- public static final String NEW_LINE = "\n";
-
- int indentLevel = -1;
- private String currentIndent = "";
-
- public OutFormatter indent(final StringBuilder buffer) {
- buffer.append(currentIndent);
- return this;
- }
-
- public OutFormatter openComposite(final StringBuilder buffer) {
- buffer.append(COMPOSITE_OPEN_NODE);
- return this;
- }
-
- public OutFormatter closeCompositeWithIndent(final StringBuilder buffer) {
- buffer.append(currentIndent);
- buffer.append(COMPOSITE_CLOSE_NODE);
- return this;
- }
-
- public OutFormatter newLine(final StringBuilder buffer) {
- buffer.append(NEW_LINE);
- return this;
- }
-
- private void prepareIndent() {
- final StringBuilder output = new StringBuilder();
- for (int i = 0; i < indentLevel; i++) {
- output.append(INDENT_STEP);
- }
- currentIndent = output.toString();
- }
-
- public OutFormatter increaseIndent() {
- indentLevel++;
- prepareIndent();
- return this;
- }
-
- public OutFormatter decreaseIndent() {
- indentLevel--;
- prepareIndent();
- return this;
- }
-
- public OutFormatter addStringWithIndent(final StringBuilder buffer, final String value) {
- indent(buffer);
- buffer.append(value);
- return this;
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.writer;
-
-public class WriteException extends Exception {
-
- private static final long serialVersionUID = 8401242676753560336L;
-
- public WriteException(final String msg, final Exception exc) {
- super(msg, exc);
- }
-
- public WriteException(final String msg) {
- super(msg);
- }
-
- public static class IncorrectNumberOfNodes extends WriteException {
- private static final long serialVersionUID = 8910285140705622920L;
-
- public IncorrectNumberOfNodes(final String msg) {
- super(msg);
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.writer;
-
-import java.util.List;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-
-/**
- * Generic handler(writer) of output elements for commands.
- */
-public interface Writer<T extends DataSchemaNode> {
-
- void write(T dataSchemaNode, List<NormalizedNode<?, ?>> dataNodes) throws WriteException;
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.writer.custom;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.cli.writer.OutFormatter;
-import org.opendaylight.netconf.cli.writer.WriteException;
-import org.opendaylight.netconf.cli.writer.impl.AbstractWriter;
-import org.opendaylight.netconf.cli.writer.impl.NormalizedNodeWriter;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-public class DataWriter extends AbstractWriter<DataSchemaNode> {
-
- private final OutFormatter out;
- private final SchemaContext remoteSchemaContext;
-
- public DataWriter(final ConsoleIO console, final OutFormatter out, final SchemaContext remoteSchemaContext) {
- super(console);
- this.out = out;
- this.remoteSchemaContext = remoteSchemaContext;
- }
-
- @Override
- protected void writeInner(final DataSchemaNode dataSchemaNode, final List<NormalizedNode<?, ?>> dataNodes)
- throws IOException, WriteException {
- Preconditions.checkArgument(dataNodes.size() == 1, "Expected only 1 element for data node");
- final NormalizedNode<?, ?> dataNode = dataNodes.get(0);
- Preconditions.checkArgument(dataNode instanceof ContainerNode, "Unexpected node type: %s, should be %s",
- dataNode, ContainerNode.class);
-
- StringBuilder output = new StringBuilder();
- out.increaseIndent().addStringWithIndent(
- output, dataSchemaNode.getQName().getLocalName()).openComposite(output);
- console.writeLn(output.toString());
-
- for (final Object childNodeObject : ((DataContainerNode) dataNode).getValue()) {
- final NormalizedNode<?, ?> childNode = (NormalizedNode<?, ?>) childNodeObject;
- final Optional<DataSchemaNode> schemaNode = SchemaUtils.findFirstSchema(childNode.getNodeType(),
- remoteSchemaContext.getDataDefinitions());
- Preconditions.checkState(schemaNode.isPresent(), "Unknown data node %s, not defined in schema",
- childNode.getNodeType());
- new NormalizedNodeWriter(console, out).write(schemaNode.get(), Collections.singletonList(childNode));
- }
-
- output = new StringBuilder();
- out.decreaseIndent().closeCompositeWithIndent(output);
- console.writeLn(output.toString());
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.writer.impl;
-
-import java.io.IOException;
-import java.util.List;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.cli.writer.WriteException;
-import org.opendaylight.netconf.cli.writer.Writer;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-
-public abstract class AbstractWriter<T extends DataSchemaNode> implements Writer<T> {
-
- protected ConsoleIO console;
-
- public AbstractWriter(final ConsoleIO console) {
- this.console = console;
- }
-
- @Override
- public void write(final T dataSchemaNode, final List<NormalizedNode<?, ?>> dataNodes) throws WriteException {
- try {
- writeInner(dataSchemaNode, dataNodes);
- } catch (final IOException e) {
- throw new WriteException("Unable to write data to output for " + dataSchemaNode.getQName(), e);
- }
- }
-
- protected abstract void writeInner(T dataSchemaNode, List<NormalizedNode<?, ?>> dataNodes)
- throws IOException, WriteException;
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.writer.impl;
-
-import com.google.common.base.Preconditions;
-import java.util.Collections;
-import org.opendaylight.netconf.cli.writer.OutFormatter;
-import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.AugmentationNodeBaseSerializer;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
-
-final class AugmentationNodeCliSerializer extends AugmentationNodeBaseSerializer<String> {
-
- private final NodeSerializerDispatcher<String> dispatcher;
- private final OutFormatter out;
-
- AugmentationNodeCliSerializer(final OutFormatter out, final NodeSerializerDispatcher<String> dispatcher) {
- this.out = Preconditions.checkNotNull(out);
- this.dispatcher = Preconditions.checkNotNull(dispatcher);
- }
-
- @Override
- public Iterable<String> serialize(final AugmentationSchema schema, final AugmentationNode node) {
- final StringBuilder output = new StringBuilder();
- out.increaseIndent();
- out.addStringWithIndent(output, "augment");
- out.openComposite(output);
- out.newLine(output);
-
- for (final String childOutput : super.serialize(schema, node)) {
- output.append(childOutput);
- out.newLine(output);
- }
-
- out.closeCompositeWithIndent(output);
- out.decreaseIndent();
- return Collections.singletonList(output.toString());
- }
-
- @Override
- protected NodeSerializerDispatcher<String> getNodeDispatcher() {
- return dispatcher;
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.writer.impl;
-
-import com.google.common.base.Preconditions;
-import java.util.Collections;
-import org.opendaylight.netconf.cli.writer.OutFormatter;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.ChoiceNodeBaseSerializer;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
-
-final class ChoiceNodeCliSerializer extends ChoiceNodeBaseSerializer<String> {
- private final NodeSerializerDispatcher<String> dispatcher;
- private final OutFormatter out;
-
- ChoiceNodeCliSerializer(final OutFormatter out, final NodeSerializerDispatcher<String> dispatcher) {
- this.out = Preconditions.checkNotNull(out);
- this.dispatcher = Preconditions.checkNotNull(dispatcher);
- }
-
- @Override
- public Iterable<String> serialize(final ChoiceSchemaNode schema, final ChoiceNode node) {
- final StringBuilder output = new StringBuilder();
- out.increaseIndent();
- out.addStringWithIndent(output, "choice ");
- output.append(schema.getQName().getLocalName());
- output.append(" (");
- output.append(detectCase(schema, node));
- output.append(") ");
- out.openComposite(output);
- out.newLine(output);
-
- for (final String childOutput : super.serialize(schema, node)) {
- output.append(childOutput);
- out.newLine(output);
- }
-
- out.closeCompositeWithIndent(output);
- out.decreaseIndent();
- return Collections.singletonList(output.toString());
- }
-
- private String detectCase(final ChoiceSchemaNode schema, final ChoiceNode node) {
- for (final DataContainerChild<? extends PathArgument, ?> caseChild : node.getValue()) {
- final QName presentChildQName = caseChild.getNodeType();
- for (final ChoiceCaseNode choiceCaseNode : schema.getCases()) {
- if (choiceCaseNode.getDataChildByName(presentChildQName) != null) {
- // Pick the first case that contains first child node
- return choiceCaseNode.getQName().getLocalName();
- }
- }
- }
-
- // Should not happen, nodes should come from one of the cases
- throw new IllegalStateException("Choice node " + node + " does not conform to choice schema " + schema);
- }
-
- @Override
- protected NodeSerializerDispatcher<String> getNodeDispatcher() {
- return dispatcher;
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.writer.impl;
-
-import org.opendaylight.netconf.cli.writer.OutFormatter;
-import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
-import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
-import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
-import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializerFactory;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
-import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
-import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-
-public final class CliOutputFromNormalizedNodeSerializerFactory implements FromNormalizedNodeSerializerFactory<String> {
- private final ContainerNodeCliSerializer containerSerializer;
- private final ChoiceNodeCliSerializer choiceSerializer;
- private final AugmentationNodeCliSerializer augmentSerializer;
- private final LeafNodeCliSerializer leafNodeSerializer;
- private final LeafSetNodeCliSerializer leafSetSerializer;
- private final MapNodeCliSerializer mapNodeSerializer;
- private final LeafSetEntryNodeCliSerializer leafSetEntryNodeSerializer;
- private final MapEntryNodeCliSerializer mapEntryNodeSerializer;
- final NodeSerializerDispatcher<String> dispatcher = new NodeCliSerializerDispatcher(this);
-
- private CliOutputFromNormalizedNodeSerializerFactory(final OutFormatter out, final XmlCodecProvider codecProvider) {
-
- containerSerializer = new ContainerNodeCliSerializer(out, dispatcher);
- choiceSerializer = new ChoiceNodeCliSerializer(out, dispatcher);
- augmentSerializer = new AugmentationNodeCliSerializer(out, dispatcher);
- leafNodeSerializer = new LeafNodeCliSerializer(out);
-
- leafSetEntryNodeSerializer = new LeafSetEntryNodeCliSerializer(out);
- leafSetSerializer = new LeafSetNodeCliSerializer(out, leafSetEntryNodeSerializer);
-
- mapEntryNodeSerializer = new MapEntryNodeCliSerializer(out, dispatcher);
- mapNodeSerializer = new MapNodeCliSerializer(out, mapEntryNodeSerializer);
- }
-
- public NodeSerializerDispatcher<String> getDispatcher() {
- return dispatcher;
- }
-
- public static CliOutputFromNormalizedNodeSerializerFactory getInstance(final OutFormatter out,
- final XmlCodecProvider codecProvider) {
- return new CliOutputFromNormalizedNodeSerializerFactory(out, codecProvider);
- }
-
- @Override
- public FromNormalizedNodeSerializer<String, AugmentationNode, AugmentationSchema> getAugmentationNodeSerializer() {
- return augmentSerializer;
- }
-
- @Override
- public FromNormalizedNodeSerializer<String, ChoiceNode, ChoiceSchemaNode> getChoiceNodeSerializer() {
- return choiceSerializer;
- }
-
- @Override
- public FromNormalizedNodeSerializer<String, ContainerNode, ContainerSchemaNode> getContainerNodeSerializer() {
- return containerSerializer;
- }
-
- @Override
- public FromNormalizedNodeSerializer<String, LeafNode<?>, LeafSchemaNode> getLeafNodeSerializer() {
- return leafNodeSerializer;
- }
-
- @Override
- public FromNormalizedNodeSerializer<
- String, LeafSetEntryNode<?>, LeafListSchemaNode> getLeafSetEntryNodeSerializer() {
- return leafSetEntryNodeSerializer;
- }
-
- @Override
- public FromNormalizedNodeSerializer<String, LeafSetNode<?>, LeafListSchemaNode> getLeafSetNodeSerializer() {
- return leafSetSerializer;
- }
-
- @Override
- public FromNormalizedNodeSerializer<String, MapEntryNode, ListSchemaNode> getMapEntryNodeSerializer() {
- return mapEntryNodeSerializer;
- }
-
- @Override
- public FromNormalizedNodeSerializer<String, UnkeyedListNode, ListSchemaNode> getUnkeyedListNodeSerializer() {
- return null;
- }
-
- @Override
- public FromNormalizedNodeSerializer<String, MapNode, ListSchemaNode> getMapNodeSerializer() {
- return mapNodeSerializer;
- }
-
- @Override
- public FromNormalizedNodeSerializer<String, AnyXmlNode, AnyXmlSchemaNode> getAnyXmlNodeSerializer() {
- throw new UnsupportedOperationException();
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.writer.impl;
-
-import com.google.common.base.Preconditions;
-import java.util.Collections;
-import org.opendaylight.netconf.cli.writer.OutFormatter;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.ContainerNodeBaseSerializer;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-
-final class ContainerNodeCliSerializer extends ContainerNodeBaseSerializer<String> {
-
- private final NodeSerializerDispatcher<String> dispatcher;
- private final OutFormatter out;
-
- ContainerNodeCliSerializer(final OutFormatter out, final NodeSerializerDispatcher<String> dispatcher) {
- this.out = Preconditions.checkNotNull(out);
- this.dispatcher = Preconditions.checkNotNull(dispatcher);
- }
-
- @Override
- public Iterable<String> serialize(final ContainerSchemaNode schema, final ContainerNode containerNode) {
- final StringBuilder output = new StringBuilder();
- out.increaseIndent();
- out.addStringWithIndent(output, containerNode.getNodeType().getLocalName());
- out.openComposite(output);
- out.newLine(output);
-
- for (final String childOutput : super.serialize(schema, containerNode)) {
- output.append(childOutput);
- out.newLine(output);
- }
-
- out.closeCompositeWithIndent(output);
- out.decreaseIndent();
- return Collections.singletonList(output.toString());
- }
-
- @Override
- protected NodeSerializerDispatcher<String> getNodeDispatcher() {
- return dispatcher;
- }
-
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.writer.impl;
-
-import com.google.common.base.Preconditions;
-import org.opendaylight.netconf.cli.writer.OutFormatter;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.LeafNodeBaseSerializer;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-
-final class LeafNodeCliSerializer extends LeafNodeBaseSerializer<String> {
- private final OutFormatter out;
-
- LeafNodeCliSerializer(final OutFormatter out) {
- this.out = Preconditions.checkNotNull(out);
- }
-
- @Override
- public String serializeLeaf(final LeafSchemaNode schema, final LeafNode<?> node) {
- final StringBuilder output = new StringBuilder();
- out.increaseIndent();
- out.addStringWithIndent(output, node.getNodeType().getLocalName());
- output.append(" ");
- output.append(node.getValue());
- out.decreaseIndent();
- return output.toString();
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.writer.impl;
-
-import org.opendaylight.netconf.cli.writer.OutFormatter;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.LeafSetEntryNodeBaseSerializer;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-
-final class LeafSetEntryNodeCliSerializer extends LeafSetEntryNodeBaseSerializer<String> {
-
- private final OutFormatter out;
-
- LeafSetEntryNodeCliSerializer(final OutFormatter out) {
- this.out = out;
- }
-
- @Override
- protected String serializeLeaf(final LeafListSchemaNode schema, final LeafSetEntryNode<?> node) {
- final StringBuilder output = new StringBuilder();
- out.increaseIndent();
- out.addStringWithIndent(output, node.getValue().toString());
- out.decreaseIndent();
- return output.toString();
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.writer.impl;
-
-import java.util.Collections;
-import org.opendaylight.netconf.cli.writer.OutFormatter;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-
-final class LeafSetNodeCliSerializer implements
- FromNormalizedNodeSerializer<String, LeafSetNode<?>, LeafListSchemaNode> {
- private final LeafSetEntryNodeCliSerializer leafSetEntryNodeSerializer;
- private final OutFormatter out;
-
- LeafSetNodeCliSerializer(final OutFormatter out, final LeafSetEntryNodeCliSerializer leafSetEntryNodeSerializer) {
- this.out = out;
- this.leafSetEntryNodeSerializer = leafSetEntryNodeSerializer;
- }
-
- @Override
- public Iterable<String> serialize(final LeafListSchemaNode schema, final LeafSetNode<?> node) {
- final StringBuilder output = new StringBuilder();
- out.increaseIndent();
- out.addStringWithIndent(output, node.getNodeType().getLocalName());
- out.openComposite(output);
- out.newLine(output);
- for (final LeafSetEntryNode<?> leafEntryNode : node.getValue()) {
- final Iterable<String> valueFromLeafSetEntry = leafSetEntryNodeSerializer.serialize(schema, leafEntryNode);
- output.append(valueFromLeafSetEntry.iterator().next());
- out.newLine(output);
- }
- out.closeCompositeWithIndent(output);
- out.decreaseIndent();
- return Collections.singletonList(output.toString());
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.writer.impl;
-
-import com.google.common.base.Preconditions;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Map.Entry;
-import org.opendaylight.netconf.cli.writer.OutFormatter;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.ListEntryNodeBaseSerializer;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-
-final class MapEntryNodeCliSerializer extends ListEntryNodeBaseSerializer<String,MapEntryNode> {
-
- private final NodeSerializerDispatcher<String> dispatcher;
- private final OutFormatter out;
-
- MapEntryNodeCliSerializer(final OutFormatter out, final NodeSerializerDispatcher<String> dispatcher) {
- this.out = Preconditions.checkNotNull(out);
- this.dispatcher = Preconditions.checkNotNull(dispatcher);
- }
-
- @Override
- public Iterable<String> serialize(final ListSchemaNode schema, final MapEntryNode node) {
- final StringBuilder output = new StringBuilder();
- out.increaseIndent();
- out.addStringWithIndent(output, node.getNodeType().getLocalName());
- serializeKeysIfPresent(node, output);
-
- out.openComposite(output);
- out.newLine(output);
-
- for (final String childOutput : super.serialize(schema, node)) {
- output.append(childOutput);
- out.newLine(output);
- }
-
- out.closeCompositeWithIndent(output);
- out.newLine(output);
- out.decreaseIndent();
- return Collections.singletonList(output.toString());
- }
-
- private void serializeKeysIfPresent(final MapEntryNode node, final StringBuilder output) {
- final Map<QName, Object> keyValues = node.getIdentifier().getKeyValues();
- if (keyValues.isEmpty()) {
- return;
- }
-
- int index = 0;
- output.append(" [");
- for (final Entry<QName, Object> keys : keyValues.entrySet()) {
- output.append(keys.getKey().getLocalName());
- output.append("=");
- output.append(keys.getValue().toString());
- if (++index != keyValues.size()) {
- output.append(", ");
- }
- }
- output.append("]");
- }
-
- @Override
- protected NodeSerializerDispatcher<String> getNodeDispatcher() {
- return dispatcher;
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.writer.impl;
-
-import com.google.common.base.Preconditions;
-import java.util.Collections;
-import org.opendaylight.netconf.cli.writer.OutFormatter;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-
-final class MapNodeCliSerializer implements FromNormalizedNodeSerializer<String, MapNode, ListSchemaNode> {
-
- private final FromNormalizedNodeSerializer<String, MapEntryNode, ListSchemaNode> mapEntrySerializer;
- private final OutFormatter out;
-
- MapNodeCliSerializer(final OutFormatter out, final MapEntryNodeCliSerializer mapEntrySerializer) {
- this.out = Preconditions.checkNotNull(out);
- this.mapEntrySerializer = mapEntrySerializer;
- }
-
- @Override
- public Iterable<String> serialize(final ListSchemaNode schema, final MapNode node) {
- final StringBuilder output = new StringBuilder();
-
- out.increaseIndent();
- out.addStringWithIndent(output, node.getNodeType().getLocalName());
- output.append(" ");
- out.openComposite(output);
- out.newLine(output);
-
- for (final MapEntryNode mapEntryNode : node.getValue()) {
- final Iterable<String> valueFromLeafSetEntry = mapEntrySerializer.serialize(schema, mapEntryNode);
- output.append(valueFromLeafSetEntry.iterator().next());
- }
-
- out.closeCompositeWithIndent(output);
- out.decreaseIndent();
-
- return Collections.singletonList(output.toString());
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.writer.impl;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
-import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MixinNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializerFactory;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
-import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-
-public class NodeCliSerializerDispatcher implements NodeSerializerDispatcher<String> {
- private final FromNormalizedNodeSerializerFactory<String> factory;
-
- public NodeCliSerializerDispatcher(final FromNormalizedNodeSerializerFactory<String> factory) {
- this.factory = Preconditions.checkNotNull(factory);
- }
-
- @Override
- public final Iterable<String> dispatchChildElement(final Object childSchema,
- final DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild) {
- if (dataContainerChild instanceof ContainerNode) {
- return onContainerNode(childSchema, dataContainerChild);
- } else if (dataContainerChild instanceof LeafNode<?>) {
- return onLeafNode(childSchema, dataContainerChild);
- } else if (dataContainerChild instanceof MixinNode) {
- if (dataContainerChild instanceof LeafSetNode<?>) {
- return onLeafListNode(childSchema, dataContainerChild);
- } else if (dataContainerChild instanceof MapNode) {
- return onListNode(childSchema, dataContainerChild);
- } else if (dataContainerChild instanceof ChoiceNode) {
- return onChoiceNode(childSchema, dataContainerChild);
- } else if (dataContainerChild instanceof AugmentationNode) {
- return onAugmentationSchema(childSchema, dataContainerChild);
- }
- }
- throw new IllegalArgumentException("Unable to serialize " + childSchema);
- }
-
- private Iterable<String> onAugmentationSchema(final Object childSchema,
- final DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild) {
- checkSchemaCompatibility(childSchema, AugmentationSchema.class, dataContainerChild);
- return factory.getAugmentationNodeSerializer().serialize((AugmentationSchema) childSchema,
- (AugmentationNode) dataContainerChild);
- }
-
- private Iterable<String> onChoiceNode(final Object childSchema,
- final DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild) {
- checkSchemaCompatibility(childSchema, ChoiceSchemaNode.class, dataContainerChild);
- return factory.getChoiceNodeSerializer().serialize(
- (ChoiceSchemaNode) childSchema, (ChoiceNode) dataContainerChild);
- }
-
- private Iterable<String> onListNode(final Object childSchema,
- final DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild) {
- checkSchemaCompatibility(childSchema, ListSchemaNode.class, dataContainerChild);
- return factory.getMapNodeSerializer().serialize((ListSchemaNode) childSchema, (MapNode) dataContainerChild);
- }
-
- private Iterable<String> onLeafListNode(final Object childSchema,
- final DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild) {
- checkSchemaCompatibility(childSchema, LeafListSchemaNode.class, dataContainerChild);
- return factory.getLeafSetNodeSerializer().serialize((LeafListSchemaNode) childSchema,
- (LeafSetNode<?>) dataContainerChild);
- }
-
- private Iterable<String> onLeafNode(final Object childSchema,
- final DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild) {
- checkSchemaCompatibility(childSchema, LeafSchemaNode.class, dataContainerChild);
- final Iterable<String> elements = factory.getLeafNodeSerializer().serialize((LeafSchemaNode) childSchema,
- (LeafNode<?>) dataContainerChild);
- checkOnlyOneSerializedElement(elements, dataContainerChild);
- return elements;
- }
-
- private static void checkOnlyOneSerializedElement(final Iterable<?> elements,
- final DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild) {
- final int size = Iterables.size(elements);
- Preconditions.checkArgument(size == 1,
- "Unexpected count of elements for entry serialized from: %s, should be 1, was: %s", dataContainerChild,
- size);
- }
-
- private Iterable<String> onContainerNode(final Object childSchema,
- final DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild) {
- checkSchemaCompatibility(childSchema, ContainerSchemaNode.class, dataContainerChild);
-
- final Iterable<String> elements = factory.getContainerNodeSerializer().serialize(
- (ContainerSchemaNode) childSchema, (ContainerNode) dataContainerChild);
- checkOnlyOneSerializedElement(elements, dataContainerChild);
- return elements;
- }
-
- private static void checkSchemaCompatibility(final Object childSchema, final Class<?> containerSchemaNodeClass,
- final DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild) {
- Preconditions.checkArgument(containerSchemaNodeClass.isAssignableFrom(childSchema.getClass()),
- "Incompatible schema: %s with node: %s, expected: %s", childSchema, dataContainerChild,
- containerSchemaNodeClass);
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.writer.impl;
-
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.List;
-import org.opendaylight.netconf.cli.io.ConsoleIO;
-import org.opendaylight.netconf.cli.writer.OutFormatter;
-import org.opendaylight.netconf.cli.writer.WriteException;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class NormalizedNodeWriter extends AbstractWriter<DataSchemaNode> {
-
- private static final Logger LOG = LoggerFactory.getLogger(NormalizedNodeWriter.class);
- private final OutFormatter out;
-
- public NormalizedNodeWriter(final ConsoleIO console, final OutFormatter out) {
- super(console);
- this.out = out;
- }
-
- public void writeInner(final DataSchemaNode dataSchemaNode, final List<NormalizedNode<?, ?>> dataNodes)
- throws WriteException, IOException {
- //Preconditions.checkState(dataNodes.size() == 1);
- // TODO - add getDispatcher method to CnSnToNormalizedNodeParserFactory
- // to be able call dispatchChildElement
- final NormalizedNode<?, ?> dataContainerChild = dataNodes.get(0);
-
- if (dataContainerChild != null) {
- console.writeLn(serializeToCliOutput(dataContainerChild, dataSchemaNode));
- }
-
- }
-
- private String serializeToCliOutput(final NormalizedNode<?, ?> dataContainerChild,
- final DataSchemaNode childSchema) {
- final CliOutputFromNormalizedNodeSerializerFactory factorySerialization =
- CliOutputFromNormalizedNodeSerializerFactory.getInstance(out, DomUtils.defaultValueCodecProvider());
- final NodeSerializerDispatcher<String> dispatcher = factorySerialization.getDispatcher();
- final Iterable<String> result = dispatcher.dispatchChildElement(childSchema,
- (DataContainerChild<?, ?>) dataContainerChild);
-
- if (result == null) {
- return "";
- }
-
- final Iterator<String> output = result.iterator();
- if (!output.hasNext()) {
- return "";
- }
-
- return output.next();
- }
-
-}
+++ /dev/null
-
-<configuration scan="true">
- <appender name="netconfcli.log" class="ch.qos.logback.core.FileAppender">
- <file>netconfcli.log</file>
-
- <encoder>
- <pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level
- %logger{35} - %msg%n</pattern>
- </encoder>
-
- </appender>
-
- <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
- <!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder
- by default -->
- <encoder>
- <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
- </pattern>
- </encoder>
- </appender>
-
-
-
- <root level="trace">
- <appender-ref ref="netconfcli.log" />
- <!-- <appender-ref ref="STDOUT" /> -->
- </root>
-
- <!-- <logger name="org.opendaylight.yangtools.yang.model.api" level="TRACE"
- additivity="false"> <appender-ref ref="netconfcli.log" /> </logger> -->
-</configuration>
+++ /dev/null
-module ietf-inet-types {
-
- namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types";
- prefix "inet";
-
- organization
- "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
-
- contact
- "WG Web: <http://tools.ietf.org/wg/netmod/>
- WG List: <mailto:netmod@ietf.org>
-
- WG Chair: David Partain
- <mailto:david.partain@ericsson.com>
-
- WG Chair: David Kessens
- <mailto:david.kessens@nsn.com>
-
- Editor: Juergen Schoenwaelder
- <mailto:j.schoenwaelder@jacobs-university.de>";
-
- description
- "This module contains a collection of generally useful derived
- YANG data types for Internet addresses and related things.
-
- Copyright (c) 2010 IETF Trust and the persons identified as
- authors of the code. All rights reserved.
-
-
-
- Redistribution and use in source and binary forms, with or without
- modification, is permitted pursuant to, and subject to the license
- terms contained in, the Simplified BSD License set forth in Section
- 4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
- (http://trustee.ietf.org/license-info).
-
- This version of this YANG module is part of RFC 6021; see
- the RFC itself for full legal notices.";
-
- revision 2010-09-24 {
- description
- "Initial revision.";
- reference
- "RFC 6021: Common YANG Data Types";
- }
-
- /*** collection of protocol field related types ***/
-
- typedef ip-version {
- type enumeration {
- enum unknown {
- value "0";
- description
- "An unknown or unspecified version of the Internet protocol.";
- }
- enum ipv4 {
- value "1";
- description
- "The IPv4 protocol as defined in RFC 791.";
- }
- enum ipv6 {
- value "2";
- description
- "The IPv6 protocol as defined in RFC 2460.";
- }
- }
- description
- "This value represents the version of the IP protocol.
-
- In the value set and its semantics, this type is equivalent
- to the InetVersion textual convention of the SMIv2.";
- reference
- "RFC 791: Internet Protocol
- RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
- RFC 4001: Textual Conventions for Internet Network Addresses";
- }
-
- typedef dscp {
- type uint8 {
- range "0..63";
- }
- description
- "The dscp type represents a Differentiated Services Code-Point
- that may be used for marking packets in a traffic stream.
-
- In the value set and its semantics, this type is equivalent
- to the Dscp textual convention of the SMIv2.";
- reference
- "RFC 3289: Management Information Base for the Differentiated
- Services Architecture
- RFC 2474: Definition of the Differentiated Services Field
- (DS Field) in the IPv4 and IPv6 Headers
- RFC 2780: IANA Allocation Guidelines For Values In
- the Internet Protocol and Related Headers";
- }
-
- typedef ipv6-flow-label {
- type uint32 {
- range "0..1048575";
- }
- description
- "The flow-label type represents flow identifier or Flow Label
- in an IPv6 packet header that may be used to discriminate
- traffic flows.
-
- In the value set and its semantics, this type is equivalent
- to the IPv6FlowLabel textual convention of the SMIv2.";
- reference
- "RFC 3595: Textual Conventions for IPv6 Flow Label
- RFC 2460: Internet Protocol, Version 6 (IPv6) Specification";
- }
-
- typedef port-number {
- type uint16 {
- range "0..65535";
- }
- description
- "The port-number type represents a 16-bit port number of an
- Internet transport layer protocol such as UDP, TCP, DCCP, or
- SCTP. Port numbers are assigned by IANA. A current list of
- all assignments is available from <http://www.iana.org/>.
-
- Note that the port number value zero is reserved by IANA. In
- situations where the value zero does not make sense, it can
- be excluded by subtyping the port-number type.
-
- In the value set and its semantics, this type is equivalent
- to the InetPortNumber textual convention of the SMIv2.";
- reference
- "RFC 768: User Datagram Protocol
- RFC 793: Transmission Control Protocol
- RFC 4960: Stream Control Transmission Protocol
- RFC 4340: Datagram Congestion Control Protocol (DCCP)
- RFC 4001: Textual Conventions for Internet Network Addresses";
- }
-
- /*** collection of autonomous system related types ***/
-
- typedef as-number {
- type uint32;
- description
- "The as-number type represents autonomous system numbers
- which identify an Autonomous System (AS). An AS is a set
- of routers under a single technical administration, using
- an interior gateway protocol and common metrics to route
- packets within the AS, and using an exterior gateway
- protocol to route packets to other ASs'. IANA maintains
- the AS number space and has delegated large parts to the
- regional registries.
-
- Autonomous system numbers were originally limited to 16
- bits. BGP extensions have enlarged the autonomous system
- number space to 32 bits. This type therefore uses an uint32
- base type without a range restriction in order to support
- a larger autonomous system number space.
-
- In the value set and its semantics, this type is equivalent
- to the InetAutonomousSystemNumber textual convention of
- the SMIv2.";
- reference
- "RFC 1930: Guidelines for creation, selection, and registration
- of an Autonomous System (AS)
- RFC 4271: A Border Gateway Protocol 4 (BGP-4)
- RFC 4893: BGP Support for Four-octet AS Number Space
- RFC 4001: Textual Conventions for Internet Network Addresses";
- }
-
- /*** collection of IP address and hostname related types ***/
-
- typedef ip-address {
- type union {
- type inet:ipv4-address;
- type inet:ipv6-address;
- }
- description
- "The ip-address type represents an IP address and is IP
- version neutral. The format of the textual representations
- implies the IP version.";
- }
-
- typedef ipv4-address {
- type string {
- pattern
- '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
- + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
- + '(%[\p{N}\p{L}]+)?';
- }
- description
- "The ipv4-address type represents an IPv4 address in
- dotted-quad notation. The IPv4 address may include a zone
- index, separated by a % sign.
-
- The zone index is used to disambiguate identical address
- values. For link-local addresses, the zone index will
- typically be the interface index number or the name of an
- interface. If the zone index is not present, the default
- zone of the device will be used.
-
- The canonical format for the zone index is the numerical
- format";
- }
-
- typedef ipv6-address {
- type string {
- pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
- + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
- + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
- + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
- + '(%[\p{N}\p{L}]+)?';
- pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
- + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
- + '(%.+)?';
- }
- description
- "The ipv6-address type represents an IPv6 address in full,
- mixed, shortened, and shortened-mixed notation. The IPv6
- address may include a zone index, separated by a % sign.
-
-
-
-
-
- The zone index is used to disambiguate identical address
- values. For link-local addresses, the zone index will
- typically be the interface index number or the name of an
- interface. If the zone index is not present, the default
- zone of the device will be used.
-
- The canonical format of IPv6 addresses uses the compressed
- format described in RFC 4291, Section 2.2, item 2 with the
- following additional rules: the :: substitution must be
- applied to the longest sequence of all-zero 16-bit chunks
- in an IPv6 address. If there is a tie, the first sequence
- of all-zero 16-bit chunks is replaced by ::. Single
- all-zero 16-bit chunks are not compressed. The canonical
- format uses lowercase characters and leading zeros are
- not allowed. The canonical format for the zone index is
- the numerical format as described in RFC 4007, Section
- 11.2.";
- reference
- "RFC 4291: IP Version 6 Addressing Architecture
- RFC 4007: IPv6 Scoped Address Architecture
- RFC 5952: A Recommendation for IPv6 Address Text Representation";
- }
-
- typedef ip-prefix {
- type union {
- type inet:ipv4-prefix;
- type inet:ipv6-prefix;
- }
- description
- "The ip-prefix type represents an IP prefix and is IP
- version neutral. The format of the textual representations
- implies the IP version.";
- }
-
- typedef ipv4-prefix {
- type string {
- pattern
- '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
- + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
- + '/(([0-9])|([1-2][0-9])|(3[0-2]))';
- }
- description
- "The ipv4-prefix type represents an IPv4 address prefix.
- The prefix length is given by the number following the
- slash character and must be less than or equal to 32.
-
-
-
- A prefix length value of n corresponds to an IP address
- mask that has n contiguous 1-bits from the most
- significant bit (MSB) and all other bits set to 0.
-
- The canonical format of an IPv4 prefix has all bits of
- the IPv4 address set to zero that are not part of the
- IPv4 prefix.";
- }
-
- typedef ipv6-prefix {
- type string {
- pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
- + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
- + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
- + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
- + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))';
- pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
- + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
- + '(/.+)';
- }
- description
- "The ipv6-prefix type represents an IPv6 address prefix.
- The prefix length is given by the number following the
- slash character and must be less than or equal 128.
-
- A prefix length value of n corresponds to an IP address
- mask that has n contiguous 1-bits from the most
- significant bit (MSB) and all other bits set to 0.
-
- The IPv6 address should have all bits that do not belong
- to the prefix set to zero.
-
- The canonical format of an IPv6 prefix has all bits of
- the IPv6 address set to zero that are not part of the
- IPv6 prefix. Furthermore, IPv6 address is represented
- in the compressed format described in RFC 4291, Section
- 2.2, item 2 with the following additional rules: the ::
- substitution must be applied to the longest sequence of
- all-zero 16-bit chunks in an IPv6 address. If there is
- a tie, the first sequence of all-zero 16-bit chunks is
- replaced by ::. Single all-zero 16-bit chunks are not
- compressed. The canonical format uses lowercase
- characters and leading zeros are not allowed.";
- reference
- "RFC 4291: IP Version 6 Addressing Architecture";
- }
-
-
- /*** collection of domain name and URI types ***/
-
- typedef domain-name {
- type string {
- pattern '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
- + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
- + '|\.';
- length "1..253";
- }
- description
- "The domain-name type represents a DNS domain name. The
- name SHOULD be fully qualified whenever possible.
-
- Internet domain names are only loosely specified. Section
- 3.5 of RFC 1034 recommends a syntax (modified in Section
- 2.1 of RFC 1123). The pattern above is intended to allow
- for current practice in domain name use, and some possible
- future expansion. It is designed to hold various types of
- domain names, including names used for A or AAAA records
- (host names) and other records, such as SRV records. Note
- that Internet host names have a stricter syntax (described
- in RFC 952) than the DNS recommendations in RFCs 1034 and
- 1123, and that systems that want to store host names in
- schema nodes using the domain-name type are recommended to
- adhere to this stricter standard to ensure interoperability.
-
- The encoding of DNS names in the DNS protocol is limited
- to 255 characters. Since the encoding consists of labels
- prefixed by a length bytes and there is a trailing NULL
- byte, only 253 characters can appear in the textual dotted
- notation.
-
- The description clause of schema nodes using the domain-name
- type MUST describe when and how these names are resolved to
- IP addresses. Note that the resolution of a domain-name value
- may require to query multiple DNS records (e.g., A for IPv4
- and AAAA for IPv6). The order of the resolution process and
- which DNS record takes precedence can either be defined
- explicitely or it may depend on the configuration of the
- resolver.
-
- Domain-name values use the US-ASCII encoding. Their canonical
- format uses lowercase US-ASCII characters. Internationalized
- domain names MUST be encoded in punycode as described in RFC
- 3492";
- reference
- "RFC 952: DoD Internet Host Table Specification
- RFC 1034: Domain Names - Concepts and Facilities
- RFC 1123: Requirements for Internet Hosts -- Application
- and Support
- RFC 2782: A DNS RR for specifying the location of services
- (DNS SRV)
- RFC 3492: Punycode: A Bootstring encoding of Unicode for
- Internationalized Domain Names in Applications
- (IDNA)
- RFC 5891: Internationalizing Domain Names in Applications
- (IDNA): Protocol";
- }
-
- typedef host {
- type union {
- type inet:ip-address;
- type inet:domain-name;
- }
- description
- "The host type represents either an IP address or a DNS
- domain name.";
- }
-
- typedef uri {
- type string;
- description
- "The uri type represents a Uniform Resource Identifier
- (URI) as defined by STD 66.
-
- Objects using the uri type MUST be in US-ASCII encoding,
- and MUST be normalized as described by RFC 3986 Sections
- 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary
- percent-encoding is removed, and all case-insensitive
- characters are set to lowercase except for hexadecimal
- digits, which are normalized to uppercase as described in
- Section 6.2.2.1.
-
- The purpose of this normalization is to help provide
- unique URIs. Note that this normalization is not
- sufficient to provide uniqueness. Two URIs that are
- textually distinct after this normalization may still be
- equivalent.
-
- Objects using the uri type may restrict the schemes that
- they permit. For example, 'data:' and 'urn:' schemes
- might not be appropriate.
-
- A zero-length URI is not a valid URI. This can be used to
- express 'URI absent' where required.
-
- In the value set and its semantics, this type is equivalent
- to the Uri SMIv2 textual convention defined in RFC 5017.";
- reference
- "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax
- RFC 3305: Report from the Joint W3C/IETF URI Planning Interest
- Group: Uniform Resource Identifiers (URIs), URLs,
- and Uniform Resource Names (URNs): Clarifications
- and Recommendations
- RFC 5017: MIB Textual Conventions for Uniform Resource
- Identifiers (URIs)";
- }
-
-}
+++ /dev/null
-module netconf-cli-ext {
-
- namespace "urn:ietf:params:xml:ns:netconf:base:1.0:cli";
-
- prefix cliext;
-
- revision 2014-05-26 {
- description
- "Initial revision";
- }
-
- extension argument-handler {
- description
- "Links custom argument reader to an input argument";
- argument "name";
- }
-
-}
+++ /dev/null
-module netconf-cli {
-
- namespace "netconf:cli";
- prefix ncli;
-
- import ietf-inet-types { prefix inet; revision-date 2013-07-15; }
- import netconf-cli-ext { prefix cliext; revision-date 2014-05-26; }
-
-
- revision 2014-05-22 {
- description
- "Initial revision.";
- }
-
- extension java-class {
- description
- "This could be used to link between rpc yang definition and custom command implementation";
-
- argument "name";
- }
-
- rpc help {
- description
- "Display help";
-
- output {
- list commands {
-
- key "id";
- leaf id {
- type string;
- }
- leaf description {
- type string;
- }
- }
- }
- }
-
- rpc close {
- description
- "Close the whole cli";
- }
-
- rpc connect {
-
- description
- "Connect to a remote netconf device, if not connected yet. Connection initialization is blocking and might take some time, depending on amount of yang schemas in remote device.";
-
- input {
-
- // TODO yangtools keep input arguments unordered so the ordering in cli is random
- leaf address-name {
- type inet:host;
- default localhost;
- }
-
- leaf address-port {
- type inet:port-number;
- default 830;
- }
-
- leaf user-name {
- type string;
- }
-
- leaf user-password {
- cliext:argument-handler PasswordReader;
- type string;
- }
- }
-
- output {
- leaf status {
- type string;
- }
-
- leaf-list remote-commands {
- type string;
- }
- }
- }
-
-
- rpc disconnect {
-
- description
- "Disconnect from a netconf device that is currently connected";
-
- output {
- leaf status {
- type string;
- }
- }
- }
-
-}
+++ /dev/null
-module ietf-netconf {
-
- // the namespace for NETCONF XML definitions is unchanged
- // from RFC 4741, which this document replaces
- namespace "urn:ietf:params:xml:ns:netconf:base:1.0";
-
- prefix nc;
-
- import ietf-inet-types {
- prefix inet;
- }
-
- import netconf-cli-ext { prefix cliext; revision-date 2014-05-26; }
-
-
- organization
- "IETF NETCONF (Network Configuration) Working Group";
-
- contact
- "WG Web: <http://tools.ietf.org/wg/netconf/>
- WG List: <netconf@ietf.org>
-
- WG Chair: Bert Wijnen
- <bertietf@bwijnen.net>
-
- WG Chair: Mehmet Ersue
- <mehmet.ersue@nsn.com>
-
- Editor: Martin Bjorklund
- <mbj@tail-f.com>
-
- Editor: Juergen Schoenwaelder
- <j.schoenwaelder@jacobs-university.de>
-
- Editor: Andy Bierman
- <andy.bierman@brocade.com>";
- description
- "NETCONF Protocol Data Types and Protocol Operations.
-
- Copyright (c) 2011 IETF Trust and the persons identified as
- the document authors. All rights reserved.
-
- Redistribution and use in source and binary forms, with or
- without modification, is permitted pursuant to, and subject
- to the license terms contained in, the Simplified BSD License
- set forth in Section 4.c of the IETF Trust's Legal Provisions
- Relating to IETF Documents
- (http://trustee.ietf.org/license-info).
-
- This version of this YANG module is part of RFC 6241; see
- the RFC itself for full legal notices.";
- revision 2011-06-01 {
- description
- "Initial revision";
- reference
- "RFC 6241: Network Configuration Protocol";
- }
-
- extension get-filter-element-attributes {
- description
- "If this extension is present within an 'anyxml'
- statement named 'filter', which must be conceptually
- defined within the RPC input section for the <get>
- and <get-config> protocol operations, then the
- following unqualified XML attribute is supported
- within the <filter> element, within a <get> or
- <get-config> protocol operation:
-
- type : optional attribute with allowed
- value strings 'subtree' and 'xpath'.
- If missing, the default value is 'subtree'.
-
- If the 'xpath' feature is supported, then the
- following unqualified XML attribute is
- also supported:
-
- select: optional attribute containing a
- string representing an XPath expression.
- The 'type' attribute must be equal to 'xpath'
- if this attribute is present.";
- }
-
- // NETCONF capabilities defined as features
- feature writable-running {
- description
- "NETCONF :writable-running capability;
- If the server advertises the :writable-running
- capability for a session, then this feature must
- also be enabled for that session. Otherwise,
- this feature must not be enabled.";
- reference "RFC 6241, Section 8.2";
- }
-
- feature candidate {
- description
- "NETCONF :candidate capability;
- If the server advertises the :candidate
- capability for a session, then this feature must
- also be enabled for that session. Otherwise,
- this feature must not be enabled.";
- reference "RFC 6241, Section 8.3";
- }
-
- feature confirmed-commit {
- if-feature candidate;
- description
- "NETCONF :confirmed-commit:1.1 capability;
- If the server advertises the :confirmed-commit:1.1
- capability for a session, then this feature must
- also be enabled for that session. Otherwise,
- this feature must not be enabled.";
-
- reference "RFC 6241, Section 8.4";
- }
-
- feature rollback-on-error {
- description
- "NETCONF :rollback-on-error capability;
- If the server advertises the :rollback-on-error
- capability for a session, then this feature must
- also be enabled for that session. Otherwise,
- this feature must not be enabled.";
- reference "RFC 6241, Section 8.5";
- }
-
- feature validate {
- description
- "NETCONF :validate:1.1 capability;
- If the server advertises the :validate:1.1
- capability for a session, then this feature must
- also be enabled for that session. Otherwise,
- this feature must not be enabled.";
- reference "RFC 6241, Section 8.6";
- }
-
- feature startup {
- description
- "NETCONF :startup capability;
- If the server advertises the :startup
- capability for a session, then this feature must
- also be enabled for that session. Otherwise,
- this feature must not be enabled.";
- reference "RFC 6241, Section 8.7";
- }
-
- feature url {
- description
- "NETCONF :url capability;
- If the server advertises the :url
- capability for a session, then this feature must
- also be enabled for that session. Otherwise,
- this feature must not be enabled.";
- reference "RFC 6241, Section 8.8";
- }
-
- feature xpath {
- description
- "NETCONF :xpath capability;
- If the server advertises the :xpath
- capability for a session, then this feature must
- also be enabled for that session. Otherwise,
- this feature must not be enabled.";
- reference "RFC 6241, Section 8.9";
- }
-
- // NETCONF Simple Types
-
- typedef session-id-type {
- type uint32 {
- range "1..max";
- }
- description
- "NETCONF Session Id";
- }
-
- typedef session-id-or-zero-type {
- type uint32;
- description
- "NETCONF Session Id or Zero to indicate none";
- }
- typedef error-tag-type {
- type enumeration {
- enum in-use {
- description
- "The request requires a resource that
- already is in use.";
- }
- enum invalid-value {
- description
- "The request specifies an unacceptable value for one
- or more parameters.";
- }
- enum too-big {
- description
- "The request or response (that would be generated) is
- too large for the implementation to handle.";
- }
- enum missing-attribute {
- description
- "An expected attribute is missing.";
- }
- enum bad-attribute {
- description
- "An attribute value is not correct; e.g., wrong type,
- out of range, pattern mismatch.";
- }
- enum unknown-attribute {
- description
- "An unexpected attribute is present.";
- }
- enum missing-element {
- description
- "An expected element is missing.";
- }
- enum bad-element {
- description
- "An element value is not correct; e.g., wrong type,
- out of range, pattern mismatch.";
- }
- enum unknown-element {
- description
- "An unexpected element is present.";
- }
- enum unknown-namespace {
- description
- "An unexpected namespace is present.";
- }
- enum access-denied {
- description
- "Access to the requested protocol operation or
- data model is denied because authorization failed.";
- }
- enum lock-denied {
- description
- "Access to the requested lock is denied because the
- lock is currently held by another entity.";
- }
- enum resource-denied {
- description
- "Request could not be completed because of
- insufficient resources.";
- }
- enum rollback-failed {
- description
- "Request to roll back some configuration change (via
- rollback-on-error or <discard-changes> operations)
- was not completed for some reason.";
-
- }
- enum data-exists {
- description
- "Request could not be completed because the relevant
- data model content already exists. For example,
- a 'create' operation was attempted on data that
- already exists.";
- }
- enum data-missing {
- description
- "Request could not be completed because the relevant
- data model content does not exist. For example,
- a 'delete' operation was attempted on
- data that does not exist.";
- }
- enum operation-not-supported {
- description
- "Request could not be completed because the requested
- operation is not supported by this implementation.";
- }
- enum operation-failed {
- description
- "Request could not be completed because the requested
- operation failed for some reason not covered by
- any other error condition.";
- }
- enum partial-operation {
- description
- "This error-tag is obsolete, and SHOULD NOT be sent
- by servers conforming to this document.";
- }
- enum malformed-message {
- description
- "A message could not be handled because it failed to
- be parsed correctly. For example, the message is not
- well-formed XML or it uses an invalid character set.";
- }
- }
- description "NETCONF Error Tag";
- reference "RFC 6241, Appendix A";
- }
-
- typedef error-severity-type {
- type enumeration {
- enum error {
- description "Error severity";
- }
- enum warning {
- description "Warning severity";
- }
- }
- description "NETCONF Error Severity";
- reference "RFC 6241, Section 4.3";
- }
-
- typedef edit-operation-type {
- type enumeration {
- enum merge {
- description
- "The configuration data identified by the
- element containing this attribute is merged
- with the configuration at the corresponding
- level in the configuration datastore identified
- by the target parameter.";
- }
- enum replace {
- description
- "The configuration data identified by the element
- containing this attribute replaces any related
- configuration in the configuration datastore
- identified by the target parameter. If no such
- configuration data exists in the configuration
- datastore, it is created. Unlike a
- <copy-config> operation, which replaces the
- entire target configuration, only the configuration
- actually present in the config parameter is affected.";
- }
- enum create {
- description
- "The configuration data identified by the element
- containing this attribute is added to the
- configuration if and only if the configuration
- data does not already exist in the configuration
- datastore. If the configuration data exists, an
- <rpc-error> element is returned with an
- <error-tag> value of 'data-exists'.";
- }
- enum delete {
- description
- "The configuration data identified by the element
- containing this attribute is deleted from the
- configuration if and only if the configuration
- data currently exists in the configuration
- datastore. If the configuration data does not
- exist, an <rpc-error> element is returned with
- an <error-tag> value of 'data-missing'.";
- }
- enum remove {
- description
- "The configuration data identified by the element
- containing this attribute is deleted from the
- configuration if the configuration
- data currently exists in the configuration
- datastore. If the configuration data does not
- exist, the 'remove' operation is silently ignored
- by the server.";
- }
- }
- default "merge";
- description "NETCONF 'operation' attribute values";
- reference "RFC 6241, Section 7.2";
- }
-
- // NETCONF Standard Protocol Operations
-
- rpc get-config {
- description
- "Retrieve all or part of a specified configuration.";
-
- reference "RFC 6241, Section 7.1";
-
- input {
- container source {
- description
- "Particular configuration to retrieve.";
-
- choice config-source {
- mandatory true;
- description
- "The configuration to retrieve.";
- leaf candidate {
- if-feature candidate;
- type empty;
- description
- "The candidate configuration is the config source.";
- }
- leaf running {
- type empty;
- description
- "The running configuration is the config source.";
- }
- leaf startup {
- if-feature startup;
- type empty;
- description
- "The startup configuration is the config source.
- This is optional-to-implement on the server because
- not all servers will support filtering for this
- datastore.";
- }
- }
- }
-
- anyxml filter {
- description
- "Subtree or XPath filter to use.";
- nc:get-filter-element-attributes;
- // TODO this extension should be augmented (anyxml nodes cannot be augmented)
- // or we can identify custom input/output arguments by schemaPath defined for custom handlers
- cliext:argument-handler FilterReader;
- }
- }
-
- output {
- anyxml data {
- description
- "Copy of the source datastore subset that matched
- the filter criteria (if any). An empty data container
- indicates that the request did not produce any results.";
- cliext:argument-handler DataWriter;
- }
- }
- }
-
- rpc edit-config {
- description
- "The <edit-config> operation loads all or part of a specified
- configuration to the specified target configuration.";
-
- reference "RFC 6241, Section 7.2";
-
- input {
- container target {
- description
- "Particular configuration to edit.";
-
- choice config-target {
- mandatory true;
- description
- "The configuration target.";
-
- leaf candidate {
- if-feature candidate;
- type empty;
- description
- "The candidate configuration is the config target.";
- }
- leaf running {
- if-feature writable-running;
- type empty;
- description
- "The running configuration is the config source.";
- }
- }
- }
-
- leaf default-operation {
- type enumeration {
- enum merge {
- description
- "The default operation is merge.";
- }
- enum replace {
- description
- "The default operation is replace.";
- }
- enum none {
- description
- "There is no default operation.";
- }
- }
- default "merge";
- description
- "The default operation to use.";
- }
-
- leaf test-option {
- if-feature validate;
- type enumeration {
- enum test-then-set {
- description
- "The server will test and then set if no errors.";
- }
- enum set {
- description
- "The server will set without a test first.";
- }
-
- enum test-only {
- description
- "The server will only test and not set, even
- if there are no errors.";
- }
- }
- default "test-then-set";
- description
- "The test option to use.";
- }
-
- leaf error-option {
- type enumeration {
- enum stop-on-error {
- description
- "The server will stop on errors.";
- }
- enum continue-on-error {
- description
- "The server may continue on errors.";
- }
- enum rollback-on-error {
- description
- "The server will roll back on errors.
- This value can only be used if the 'rollback-on-error'
- feature is supported.";
- }
- }
- default "stop-on-error";
- description
- "The error option to use.";
- }
-
- choice edit-content {
- mandatory true;
- description
- "The content for the edit operation.";
-
- cliext:argument-handler EditContentReader;
-
- anyxml config {
- description
- "Inline Config content.";
- cliext:argument-handler ConfigReader;
- }
-
- leaf url {
- if-feature url;
- type inet:uri;
- description
- "URL-based config content.";
- }
- }
- }
- }
-
- rpc copy-config {
- description
- "Create or replace an entire configuration datastore with the
- contents of another complete configuration datastore.";
-
- reference "RFC 6241, Section 7.3";
-
- input {
- container target {
- description
- "Particular configuration to copy to.";
-
- choice config-target {
- mandatory true;
- description
- "The configuration target of the copy operation.";
-
- leaf candidate {
- if-feature candidate;
- type empty;
- description
- "The candidate configuration is the config target.";
- }
- leaf running {
- if-feature writable-running;
- type empty;
- description
- "The running configuration is the config target.
- This is optional-to-implement on the server.";
- }
- leaf startup {
- if-feature startup;
- type empty;
- description
- "The startup configuration is the config target.";
- }
- leaf url {
- if-feature url;
- type inet:uri;
- description
- "The URL-based configuration is the config target.";
- }
- }
- }
-
- container source {
- description
- "Particular configuration to copy from.";
-
- choice config-source {
- mandatory true;
- description
- "The configuration source for the copy operation.";
-
- leaf candidate {
- if-feature candidate;
- type empty;
- description
- "The candidate configuration is the config source.";
- }
- leaf running {
- type empty;
- description
- "The running configuration is the config source.";
- }
- leaf startup {
- if-feature startup;
- type empty;
- description
- "The startup configuration is the config source.";
- }
- leaf url {
- if-feature url;
- type inet:uri;
- description
- "The URL-based configuration is the config source.";
- }
- anyxml config {
- description
- "Inline Config content: <config> element. Represents
- an entire configuration datastore, not
- a subset of the running datastore.";
- }
- }
- }
- }
- }
-
- rpc delete-config {
- description
- "Delete a configuration datastore.";
-
- reference "RFC 6241, Section 7.4";
-
- input {
- container target {
- description
- "Particular configuration to delete.";
-
- choice config-target {
- mandatory true;
- description
- "The configuration target to delete.";
-
- leaf startup {
- if-feature startup;
- type empty;
- description
- "The startup configuration is the config target.";
- }
- leaf url {
- if-feature url;
- type inet:uri;
- description
- "The URL-based configuration is the config target.";
- }
- }
- }
- }
- }
-
- rpc lock {
- description
- "The lock operation allows the client to lock the configuration
- system of a device.";
-
- reference "RFC 6241, Section 7.5";
-
- input {
- container target {
- description
- "Particular configuration to lock.";
-
- choice config-target {
- mandatory true;
- description
- "The configuration target to lock.";
-
- leaf candidate {
- if-feature candidate;
- type empty;
- description
- "The candidate configuration is the config target.";
- }
- leaf running {
- type empty;
- description
- "The running configuration is the config target.";
- }
- leaf startup {
- if-feature startup;
- type empty;
- description
- "The startup configuration is the config target.";
- }
- }
- }
- }
- }
-
- rpc unlock {
- description
- "The unlock operation is used to release a configuration lock,
- previously obtained with the 'lock' operation.";
-
- reference "RFC 6241, Section 7.6";
-
- input {
- container target {
- description
- "Particular configuration to unlock.";
-
- choice config-target {
- mandatory true;
- description
- "The configuration target to unlock.";
-
- leaf candidate {
- if-feature candidate;
- type empty;
- description
- "The candidate configuration is the config target.";
- }
- leaf running {
- type empty;
- description
- "The running configuration is the config target.";
- }
- leaf startup {
- if-feature startup;
- type empty;
- description
- "The startup configuration is the config target.";
- }
- }
- }
- }
- }
-
- rpc get {
- description
- "Retrieve running configuration and device state information.";
-
- reference "RFC 6241, Section 7.7";
-
- input {
- anyxml filter {
- description
- "This parameter specifies the portion of the system
- configuration and state data to retrieve.";
- nc:get-filter-element-attributes;
- // TODO this extension should be augmented (anyxml nodes cannot be augmented)
- cliext:argument-handler FilterReader;
- }
- }
-
- output {
- anyxml data {
- description
- "Copy of the running datastore subset and/or state
- data that matched the filter criteria (if any).
- An empty data container indicates that the request did not
- produce any results.";
-
- cliext:argument-handler DataWriter;
-
- }
- }
- }
-
- rpc close-session {
- description
- "Request graceful termination of a NETCONF session.";
-
- reference "RFC 6241, Section 7.8";
- }
-
- rpc kill-session {
- description
- "Force the termination of a NETCONF session.";
-
- reference "RFC 6241, Section 7.9";
-
- input {
- leaf session-id {
- type session-id-type;
- mandatory true;
- description
- "Particular session to kill.";
- }
- }
- }
-
- rpc commit {
- if-feature candidate;
-
- description
- "Commit the candidate configuration as the device's new
- current configuration.";
-
- reference "RFC 6241, Section 8.3.4.1";
-
- input {
- leaf confirmed {
- if-feature confirmed-commit;
- type empty;
- description
- "Requests a confirmed commit.";
- reference "RFC 6241, Section 8.3.4.1";
- }
-
- leaf confirm-timeout {
- if-feature confirmed-commit;
- type uint32 {
- range "1..max";
- }
- units "seconds";
- default "600"; // 10 minutes
- description
- "The timeout interval for a confirmed commit.";
- reference "RFC 6241, Section 8.3.4.1";
- }
-
- leaf persist {
- if-feature confirmed-commit;
- type string;
- description
- "This parameter is used to make a confirmed commit
- persistent. A persistent confirmed commit is not aborted
- if the NETCONF session terminates. The only way to abort
- a persistent confirmed commit is to let the timer expire,
- or to use the <cancel-commit> operation.
-
- The value of this parameter is a token that must be given
- in the 'persist-id' parameter of <commit> or
- <cancel-commit> operations in order to confirm or cancel
- the persistent confirmed commit.
-
- The token should be a random string.";
- reference "RFC 6241, Section 8.3.4.1";
- }
-
- leaf persist-id {
- if-feature confirmed-commit;
- type string;
- description
- "This parameter is given in order to commit a persistent
- confirmed commit. The value must be equal to the value
- given in the 'persist' parameter to the <commit> operation.
- If it does not match, the operation fails with an
- 'invalid-value' error.";
- reference "RFC 6241, Section 8.3.4.1";
- }
-
- }
- }
-
- rpc discard-changes {
- if-feature candidate;
-
- description
- "Revert the candidate configuration to the current
- running configuration.";
- reference "RFC 6241, Section 8.3.4.2";
- }
-
- rpc cancel-commit {
- if-feature confirmed-commit;
- description
- "This operation is used to cancel an ongoing confirmed commit.
- If the confirmed commit is persistent, the parameter
- 'persist-id' must be given, and it must match the value of the
- 'persist' parameter.";
- reference "RFC 6241, Section 8.4.4.1";
-
- input {
- leaf persist-id {
- type string;
- description
- "This parameter is given in order to cancel a persistent
- confirmed commit. The value must be equal to the value
- given in the 'persist' parameter to the <commit> operation.
- If it does not match, the operation fails with an
- 'invalid-value' error.";
- }
- }
- }
-
- rpc validate {
- if-feature validate;
-
- description
- "Validates the contents of the specified configuration.";
-
- reference "RFC 6241, Section 8.6.4.1";
-
- input {
- container source {
- description
- "Particular configuration to validate.";
-
- choice config-source {
- mandatory true;
- description
- "The configuration source to validate.";
-
- leaf candidate {
- if-feature candidate;
- type empty;
- description
- "The candidate configuration is the config source.";
- }
- leaf running {
- type empty;
- description
- "The running configuration is the config source.";
- }
- leaf startup {
- if-feature startup;
- type empty;
- description
- "The startup configuration is the config source.";
- }
- leaf url {
- if-feature url;
- type inet:uri;
- description
- "The URL-based configuration is the config source.";
- }
- anyxml config {
- description
- "Inline Config content: <config> element. Represents
- an entire configuration datastore, not
- a subset of the running datastore.";
- }
- }
- }
- }
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli;
-
-import java.io.IOException;
-import java.util.Deque;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.opendaylight.netconf.cli.io.ConsoleIOImpl;
-
-public class ConsoleIOTestImpl extends ConsoleIOImpl {
-
- Map<String, Deque<String>> inputValues = new HashMap<>();
- String lastMessage;
- private final List<ValueForMessage> valuesForMessages;
-
- public ConsoleIOTestImpl(final Map<String, Deque<String>> inputValues,
- final List<ValueForMessage> valuesForMessages) throws IOException {
- this.inputValues = inputValues;
- this.valuesForMessages = valuesForMessages;
- }
-
- StringBuilder output = new StringBuilder();
-
- @Override
- public String read() throws IOException {
- final String prompt = buildPrompt();
- output.append(prompt);
- System.console().writer().print(prompt);
-
- String value = inputValues.get(prompt).pollFirst();
- if (value == null) {
- value = getValueForLastMessage();
- }
-
- value = value != null ? value : "****NO VALUE****";
-
- output.append(value + "\n");
- System.console().writer().println(value + "\n");
- return value;
- }
-
- private String getValueForLastMessage() {
- for (final ValueForMessage valueForMessage : valuesForMessages) {
- if (containsLastMessageKeyWords(valueForMessage.getKeyWords())) {
- return valueForMessage.getValue();
- }
- }
- return null;
- }
-
- private boolean containsLastMessageKeyWords(final List<String> keyWords) {
- for (final String keyWord : keyWords) {
- if (!lastMessage.contains(keyWord)) {
- return false;
- }
- }
- return true;
- }
-
- @Override
- public void write(final CharSequence data) throws IOException {
- output.append(data);
- lastMessage = (String) data;
- System.console().writer().print(data);
- }
-
- @Override
- public void writeLn(final CharSequence data) throws IOException {
- write(data);
- output.append("\n");
- System.console().writer().print("\n");
- }
-
- public String getConsoleOutput() {
- return output.toString();
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli;
-
-import static org.junit.Assert.assertNotNull;
-import static org.opendaylight.netconf.cli.io.IOUtil.PROMPT_SUFIX;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Deque;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
-
-@Ignore
-public class NetconfCliTest {
-
- private static SchemaContext loadSchemaContext(final String resourceDirectory) throws Exception {
- final URI uri = NetconfCliTest.class.getResource(resourceDirectory).toURI();
- final File testDir = new File(uri);
- final String[] fileList = testDir.list();
- if (fileList == null) {
- throw new FileNotFoundException(resourceDirectory);
- }
- final List<InputStream> streams = new ArrayList<>();
- for (final String fileName : fileList) {
- NetconfCliTest.class.getResourceAsStream(fileName);
- }
- return YangParserTestUtils.parseYangStreams(streams);
- }
-
- @Test
- public void cliTest() throws Exception {
-
- final SchemaContext schemaContext = loadSchemaContext("/schema-context");
- assertNotNull(schemaContext);
-
- final DataSchemaNode cont1 = findTopLevelElement("ns:model1", "2014-05-14", "cont1", schemaContext);
- final Map<String, Deque<String>> values = new HashMap<>();
-
- values.put(prompt("/cont1/cont11/lst111/[entry]/lf1111"), value("55", "32"));
- values.put(prompt("/cont1/cont11/lst111/[entry]"), value("Y", "Y"));
- values.put(prompt("/cont1/cont11/lst111/[entry]/cont111/lf1112"),
- value("value for lf1112", "2value for lf1112"));
- values.put(prompt("/cont1/cont11/lst111/[entry]/cont111/lflst1111"), value("Y", "N", "Y", "N"));
- values.put(prompt("/cont1/cont11/lst111/[entry]/cont111/lflst1111/[entry]"), value("10", "15", "20", "30"));
-
- values.put(prompt("/cont1/cont11/lst111"), value("Y", "N"));
-
- values.put(prompt("/cont1/cont12/chcA"), value("AB"));
- values.put(prompt("/cont1/cont12/chcA/cont12AB1/lf12AB1"), value("value for lf12AB1"));
-
- values.put(prompt("/cont1/cont12/lst121/[entry]/lf1211"), value("value for lf12112", "2value for lf12112"));
- values.put(prompt("/cont1/cont12/lst121/[entry]"), value("Y", "Y"));
- values.put(prompt("/cont1/cont12/lst121/[entry]/lst1211"), value("Y", "N", "Y", "N"));
- values.put(prompt("/cont1/cont12/lst121/[entry]/lst1211/[entry]"), value("Y", "Y", "Y", "Y"));
- values.put(prompt("/cont1/cont12/lst121/[entry]/lst1211/[entry]/lf12111"), value("5", "10", "21", "50"));
- values.put(prompt("/cont1/cont12/lst121/[entry]/lst1211/[entry]/lf12112"),
- value("value for lf12112", "2value for lf12112", "3value for lf12112", "4value for lf12112"));
-
- values.put(prompt("/cont1/cont12/lst121"), value("Y", "N"));
-
- values.put(prompt("/cont1/cont12/lst122"), value("Y", "N"));
-
- values.put(prompt("/cont1/lst11"), value("Y", "Y", "N"));
- values.put(prompt("/cont1/lst11/[entry]"), value("Y", "Y", "Y"));
- values.put(prompt("/cont1/lst11/[entry]/lf111"),
- value("1value for lf111", "2value for lf111", "3value for lf111"));
-
- values.put(prompt("/cont1/cont12/data"), value("<el1><el11>value</el11><el12>value1</el12></el1>"));
-
- final List<ValueForMessage> valuesForMessages = new ArrayList<>();
- valuesForMessages.add(new ValueForMessage("Y", "lst111", "[Y|N]"));
- valuesForMessages.add(new ValueForMessage("Y", "lst121", "[Y|N]"));
- valuesForMessages.add(new ValueForMessage("Y", "lst11", "[Y|N]"));
-
- final ConsoleIOTestImpl console = new ConsoleIOTestImpl(values, valuesForMessages);
-
-// final List<Node<?>> redData = new GenericReader(console, new CommandArgHandlerRegistry(console,
-// new SchemaContextRegistry(schemaContext)), schemaContext).read(cont1);
-// assertNotNull(redData);
-// assertEquals(1, redData.size());
-//
-// assertTrue(redData.get(0) instanceof CompositeNode);
-// final CompositeNode redTopLevelNode = (CompositeNode) redData.get(0);
-
- //new NormalizedNodeWriter(console, new OutFormatter()).write(cont1, redData);
-
- }
-
- private static Deque<String> value(final String... values) {
- return new ArrayDeque<>(Arrays.asList(values));
- }
-
- private static String prompt(final String path) {
- return "/localhost" + path + PROMPT_SUFIX;
- }
-
- private static DataSchemaNode findTopLevelElement(final String namespace, final String revision,
- final String topLevelElement, final SchemaContext schemaContext) {
- final QName requiredElement = QName.create(namespace, revision, topLevelElement);
- for (final DataSchemaNode dataSchemaNode : schemaContext.getChildNodes()) {
- if (dataSchemaNode.getQName().equals(requiredElement)) {
- return dataSchemaNode;
- }
- }
- return null;
-
- }
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli;
-
-import java.util.Arrays;
-import java.util.List;
-
-class ValueForMessage {
- List<String> messageKeyWords;
- String value;
-
- ValueForMessage(final String value, final String... messageKeyWords) {
- this.messageKeyWords = Arrays.asList(messageKeyWords);
- this.value = value;
- }
-
- public List<String> getKeyWords() {
- return messageKeyWords;
- }
-
- public String getValue() {
- return value;
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.cli.io;
-
-import com.google.common.collect.Maps;
-import java.util.Map;
-import org.junit.Assert;
-import org.junit.Test;
-import org.opendaylight.netconf.cli.commands.CommandConstants;
-import org.opendaylight.yangtools.yang.common.QName;
-
-public class IOUtilTest {
-
- @Test
- public void testQNameFromKeyStringNew() throws Exception {
- final String s = IOUtil.qNameToKeyString(CommandConstants.HELP_QNAME, "module");
- final Map<String, QName> modulesMap = Maps.newHashMap();
- modulesMap.put("module", QName.create(CommandConstants.HELP_QNAME, "module"));
- final QName qName = IOUtil.qNameFromKeyString(s, modulesMap);
- Assert.assertEquals(CommandConstants.HELP_QNAME, qName);
- }
-}
+++ /dev/null
- module ietf-inet-types {
-
- namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types";
- prefix "inet";
-
- organization
- "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
-
- contact
- "WG Web: <http://tools.ietf.org/wg/netmod/>
- WG List: <mailto:netmod@ietf.org>
-
- WG Chair: David Partain
- <mailto:david.partain@ericsson.com>
-
- WG Chair: David Kessens
- <mailto:david.kessens@nsn.com>
-
- Editor: Juergen Schoenwaelder
- <mailto:j.schoenwaelder@jacobs-university.de>";
-
- description
- "This module contains a collection of generally useful derived
- YANG data types for Internet addresses and related things.
-
- Copyright (c) 2010 IETF Trust and the persons identified as
- authors of the code. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, is permitted pursuant to, and subject to the license
- terms contained in, the Simplified BSD License set forth in Section
- 4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
- (http://trustee.ietf.org/license-info).
-
- This version of this YANG module is part of RFC 6021; see
- the RFC itself for full legal notices.";
-
- revision 2010-09-24 {
- description
- "Initial revision.";
- reference
- "RFC 6021: Common YANG Data Types";
- }
-
- /*** collection of protocol field related types ***/
-
- typedef ip-version {
- type enumeration {
- enum unknown {
- value "0";
- description
- "An unknown or unspecified version of the Internet protocol.";
- }
- enum ipv4 {
- value "1";
- description
- "The IPv4 protocol as defined in RFC 791.";
- }
- enum ipv6 {
- value "2";
- description
- "The IPv6 protocol as defined in RFC 2460.";
- }
- }
- description
- "This value represents the version of the IP protocol.
-
- In the value set and its semantics, this type is equivalent
- to the InetVersion textual convention of the SMIv2.";
- reference
- "RFC 791: Internet Protocol
- RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
- RFC 4001: Textual Conventions for Internet Network Addresses";
- }
-
- typedef dscp {
- type uint8 {
- range "0..63";
- }
- description
- "The dscp type represents a Differentiated Services Code-Point
- that may be used for marking packets in a traffic stream.
-
- In the value set and its semantics, this type is equivalent
- to the Dscp textual convention of the SMIv2.";
- reference
- "RFC 3289: Management Information Base for the Differentiated
- Services Architecture
- RFC 2474: Definition of the Differentiated Services Field
- (DS Field) in the IPv4 and IPv6 Headers
- RFC 2780: IANA Allocation Guidelines For Values In
- the Internet Protocol and Related Headers";
- }
-
- typedef ipv6-flow-label {
- type uint32 {
- range "0..1048575";
- }
- description
- "The flow-label type represents flow identifier or Flow Label
- in an IPv6 packet header that may be used to discriminate
- traffic flows.
-
- In the value set and its semantics, this type is equivalent
- to the IPv6FlowLabel textual convention of the SMIv2.";
- reference
- "RFC 3595: Textual Conventions for IPv6 Flow Label
- RFC 2460: Internet Protocol, Version 6 (IPv6) Specification";
- }
-
- typedef port-number {
- type uint16 {
- range "0..65535";
- }
- description
- "The port-number type represents a 16-bit port number of an
- Internet transport layer protocol such as UDP, TCP, DCCP, or
- SCTP. Port numbers are assigned by IANA. A current list of
- all assignments is available from <http://www.iana.org/>.
-
- Note that the port number value zero is reserved by IANA. In
- situations where the value zero does not make sense, it can
- be excluded by subtyping the port-number type.
-
- In the value set and its semantics, this type is equivalent
- to the InetPortNumber textual convention of the SMIv2.";
- reference
- "RFC 768: User Datagram Protocol
- RFC 793: Transmission Control Protocol
- RFC 4960: Stream Control Transmission Protocol
- RFC 4340: Datagram Congestion Control Protocol (DCCP)
- RFC 4001: Textual Conventions for Internet Network Addresses";
- }
-
- /*** collection of autonomous system related types ***/
-
- typedef as-number {
- type uint32;
- description
- "The as-number type represents autonomous system numbers
- which identify an Autonomous System (AS). An AS is a set
- of routers under a single technical administration, using
- an interior gateway protocol and common metrics to route
- packets within the AS, and using an exterior gateway
- protocol to route packets to other ASs'. IANA maintains
- the AS number space and has delegated large parts to the
- regional registries.
-
- Autonomous system numbers were originally limited to 16
- bits. BGP extensions have enlarged the autonomous system
- number space to 32 bits. This type therefore uses an uint32
- base type without a range restriction in order to support
- a larger autonomous system number space.
-
- In the value set and its semantics, this type is equivalent
- to the InetAutonomousSystemNumber textual convention of
- the SMIv2.";
- reference
- "RFC 1930: Guidelines for creation, selection, and registration
- of an Autonomous System (AS)
- RFC 4271: A Border Gateway Protocol 4 (BGP-4)
- RFC 4893: BGP Support for Four-octet AS Number Space
- RFC 4001: Textual Conventions for Internet Network Addresses";
- }
-
- /*** collection of IP address and hostname related types ***/
-
- typedef ip-address {
- type union {
- type inet:ipv4-address;
- type inet:ipv6-address;
- }
- description
- "The ip-address type represents an IP address and is IP
- version neutral. The format of the textual representations
- implies the IP version.";
- }
-
- typedef ipv4-address {
- type string {
- pattern
- '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
- + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
- + '(%[\p{N}\p{L}]+)?';
- }
- description
- "The ipv4-address type represents an IPv4 address in
- dotted-quad notation. The IPv4 address may include a zone
- index, separated by a % sign.
-
- The zone index is used to disambiguate identical address
- values. For link-local addresses, the zone index will
- typically be the interface index number or the name of an
- interface. If the zone index is not present, the default
- zone of the device will be used.
-
- The canonical format for the zone index is the numerical
- format";
- }
-
- typedef ipv6-address {
- type string {
- pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
- + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
- + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
- + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
- + '(%[\p{N}\p{L}]+)?';
- pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
- + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
- + '(%.+)?';
- }
- description
- "The ipv6-address type represents an IPv6 address in full,
- mixed, shortened, and shortened-mixed notation. The IPv6
- address may include a zone index, separated by a % sign.
-
- The zone index is used to disambiguate identical address
- values. For link-local addresses, the zone index will
- typically be the interface index number or the name of an
- interface. If the zone index is not present, the default
- zone of the device will be used.
-
- The canonical format of IPv6 addresses uses the compressed
- format described in RFC 4291, Section 2.2, item 2 with the
- following additional rules: the :: substitution must be
- applied to the longest sequence of all-zero 16-bit chunks
- in an IPv6 address. If there is a tie, the first sequence
- of all-zero 16-bit chunks is replaced by ::. Single
- all-zero 16-bit chunks are not compressed. The canonical
- format uses lowercase characters and leading zeros are
- not allowed. The canonical format for the zone index is
- the numerical format as described in RFC 4007, Section
- 11.2.";
- reference
- "RFC 4291: IP Version 6 Addressing Architecture
- RFC 4007: IPv6 Scoped Address Architecture
- RFC 5952: A Recommendation for IPv6 Address Text Representation";
- }
-
- typedef ip-prefix {
- type union {
- type inet:ipv4-prefix;
- type inet:ipv6-prefix;
- }
- description
- "The ip-prefix type represents an IP prefix and is IP
- version neutral. The format of the textual representations
- implies the IP version.";
- }
-
- typedef ipv4-prefix {
- type string {
- pattern
- '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
- + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
- + '/(([0-9])|([1-2][0-9])|(3[0-2]))';
- }
- description
- "The ipv4-prefix type represents an IPv4 address prefix.
- The prefix length is given by the number following the
- slash character and must be less than or equal to 32.
-
- A prefix length value of n corresponds to an IP address
- mask that has n contiguous 1-bits from the most
- significant bit (MSB) and all other bits set to 0.
-
- The canonical format of an IPv4 prefix has all bits of
- the IPv4 address set to zero that are not part of the
- IPv4 prefix.";
- }
-
- typedef ipv6-prefix {
- type string {
- pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
- + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
- + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
- + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
- + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))';
- pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
- + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
- + '(/.+)';
- }
- description
- "The ipv6-prefix type represents an IPv6 address prefix.
- The prefix length is given by the number following the
- slash character and must be less than or equal 128.
-
- A prefix length value of n corresponds to an IP address
- mask that has n contiguous 1-bits from the most
- significant bit (MSB) and all other bits set to 0.
-
- The IPv6 address should have all bits that do not belong
- to the prefix set to zero.
-
- The canonical format of an IPv6 prefix has all bits of
- the IPv6 address set to zero that are not part of the
- IPv6 prefix. Furthermore, IPv6 address is represented
- in the compressed format described in RFC 4291, Section
- 2.2, item 2 with the following additional rules: the ::
- substitution must be applied to the longest sequence of
- all-zero 16-bit chunks in an IPv6 address. If there is
- a tie, the first sequence of all-zero 16-bit chunks is
- replaced by ::. Single all-zero 16-bit chunks are not
- compressed. The canonical format uses lowercase
- characters and leading zeros are not allowed.";
- reference
- "RFC 4291: IP Version 6 Addressing Architecture";
- }
-
- /*** collection of domain name and URI types ***/
-
- typedef domain-name {
- type string {
- pattern '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
- + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
- + '|\.';
- length "1..253";
- }
- description
- "The domain-name type represents a DNS domain name. The
- name SHOULD be fully qualified whenever possible.
-
- Internet domain names are only loosely specified. Section
- 3.5 of RFC 1034 recommends a syntax (modified in Section
- 2.1 of RFC 1123). The pattern above is intended to allow
- for current practice in domain name use, and some possible
- future expansion. It is designed to hold various types of
- domain names, including names used for A or AAAA records
- (host names) and other records, such as SRV records. Note
- that Internet host names have a stricter syntax (described
- in RFC 952) than the DNS recommendations in RFCs 1034 and
- 1123, and that systems that want to store host names in
- schema nodes using the domain-name type are recommended to
- adhere to this stricter standard to ensure interoperability.
-
- The encoding of DNS names in the DNS protocol is limited
- to 255 characters. Since the encoding consists of labels
- prefixed by a length bytes and there is a trailing NULL
- byte, only 253 characters can appear in the textual dotted
- notation.
-
- The description clause of schema nodes using the domain-name
- type MUST describe when and how these names are resolved to
- IP addresses. Note that the resolution of a domain-name value
- may require to query multiple DNS records (e.g., A for IPv4
- and AAAA for IPv6). The order of the resolution process and
- which DNS record takes precedence can either be defined
- explicitely or it may depend on the configuration of the
- resolver.
-
- Domain-name values use the US-ASCII encoding. Their canonical
- format uses lowercase US-ASCII characters. Internationalized
- domain names MUST be encoded in punycode as described in RFC
- 3492";
- reference
- "RFC 952: DoD Internet Host Table Specification
- RFC 1034: Domain Names - Concepts and Facilities
- RFC 1123: Requirements for Internet Hosts -- Application
- and Support
- RFC 2782: A DNS RR for specifying the location of services
- (DNS SRV)
- RFC 3492: Punycode: A Bootstring encoding of Unicode for
- Internationalized Domain Names in Applications
- (IDNA)
- RFC 5891: Internationalizing Domain Names in Applications
- (IDNA): Protocol";
- }
-
- typedef host {
- type union {
- type inet:ip-address;
- type inet:domain-name;
- }
- description
- "The host type represents either an IP address or a DNS
- domain name.";
- }
-
- typedef uri {
- type string;
- description
- "The uri type represents a Uniform Resource Identifier
- (URI) as defined by STD 66.
-
- Objects using the uri type MUST be in US-ASCII encoding,
- and MUST be normalized as described by RFC 3986 Sections
- 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary
- percent-encoding is removed, and all case-insensitive
- characters are set to lowercase except for hexadecimal
- digits, which are normalized to uppercase as described in
- Section 6.2.2.1.
-
- The purpose of this normalization is to help provide
- unique URIs. Note that this normalization is not
- sufficient to provide uniqueness. Two URIs that are
- textually distinct after this normalization may still be
- equivalent.
-
- Objects using the uri type may restrict the schemes that
- they permit. For example, 'data:' and 'urn:' schemes
- might not be appropriate.
-
- A zero-length URI is not a valid URI. This can be used to
- express 'URI absent' where required.
-
- In the value set and its semantics, this type is equivalent
- to the Uri SMIv2 textual convention defined in RFC 5017.";
- reference
- "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax
- RFC 3305: Report from the Joint W3C/IETF URI Planning Interest
- Group: Uniform Resource Identifiers (URIs), URLs,
- and Uniform Resource Names (URNs): Clarifications
- and Recommendations
- RFC 5017: MIB Textual Conventions for Uniform Resource
- Identifiers (URIs)";
- }
-
- }
+++ /dev/null
-module ietf-netconf {
-
- // the namespace for NETCONF XML definitions is unchanged
- // from RFC 4741, which this document replaces
- namespace "urn:ietf:params:xml:ns:netconf:base:1.0";
-
- prefix nc;
-
- import ietf-inet-types {
- prefix inet;
- }
-
- organization
- "IETF NETCONF (Network Configuration) Working Group";
-
- contact
- "WG Web: <http://tools.ietf.org/wg/netconf/>
- WG List: <netconf@ietf.org>
-
- WG Chair: Bert Wijnen
- <bertietf@bwijnen.net>
-
- WG Chair: Mehmet Ersue
- <mehmet.ersue@nsn.com>
-
- Editor: Martin Bjorklund
- <mbj@tail-f.com>
-
- Editor: Juergen Schoenwaelder
- <j.schoenwaelder@jacobs-university.de>
-
- Editor: Andy Bierman
- <andy.bierman@brocade.com>";
- description
- "NETCONF Protocol Data Types and Protocol Operations.
-
- Copyright (c) 2011 IETF Trust and the persons identified as
- the document authors. All rights reserved.
-
- Redistribution and use in source and binary forms, with or
- without modification, is permitted pursuant to, and subject
- to the license terms contained in, the Simplified BSD License
- set forth in Section 4.c of the IETF Trust's Legal Provisions
- Relating to IETF Documents
- (http://trustee.ietf.org/license-info).
-
- This version of this YANG module is part of RFC 6241; see
- the RFC itself for full legal notices.";
- revision 2011-06-01 {
- description
- "Initial revision";
- reference
- "RFC 6241: Network Configuration Protocol";
- }
-
- extension get-filter-element-attributes {
- description
- "If this extension is present within an 'anyxml'
- statement named 'filter', which must be conceptually
- defined within the RPC input section for the <get>
- and <get-config> protocol operations, then the
- following unqualified XML attribute is supported
- within the <filter> element, within a <get> or
- <get-config> protocol operation:
-
- type : optional attribute with allowed
- value strings 'subtree' and 'xpath'.
- If missing, the default value is 'subtree'.
-
- If the 'xpath' feature is supported, then the
- following unqualified XML attribute is
- also supported:
-
- select: optional attribute containing a
- string representing an XPath expression.
- The 'type' attribute must be equal to 'xpath'
- if this attribute is present.";
- }
-
- // NETCONF capabilities defined as features
- feature writable-running {
- description
- "NETCONF :writable-running capability;
- If the server advertises the :writable-running
- capability for a session, then this feature must
- also be enabled for that session. Otherwise,
- this feature must not be enabled.";
- reference "RFC 6241, Section 8.2";
- }
-
- feature candidate {
- description
- "NETCONF :candidate capability;
- If the server advertises the :candidate
- capability for a session, then this feature must
- also be enabled for that session. Otherwise,
- this feature must not be enabled.";
- reference "RFC 6241, Section 8.3";
- }
-
- feature confirmed-commit {
- if-feature candidate;
- description
- "NETCONF :confirmed-commit:1.1 capability;
- If the server advertises the :confirmed-commit:1.1
- capability for a session, then this feature must
- also be enabled for that session. Otherwise,
- this feature must not be enabled.";
-
- reference "RFC 6241, Section 8.4";
- }
-
- feature rollback-on-error {
- description
- "NETCONF :rollback-on-error capability;
- If the server advertises the :rollback-on-error
- capability for a session, then this feature must
- also be enabled for that session. Otherwise,
- this feature must not be enabled.";
- reference "RFC 6241, Section 8.5";
- }
-
- feature validate {
- description
- "NETCONF :validate:1.1 capability;
- If the server advertises the :validate:1.1
- capability for a session, then this feature must
- also be enabled for that session. Otherwise,
- this feature must not be enabled.";
- reference "RFC 6241, Section 8.6";
- }
-
- feature startup {
- description
- "NETCONF :startup capability;
- If the server advertises the :startup
- capability for a session, then this feature must
- also be enabled for that session. Otherwise,
- this feature must not be enabled.";
- reference "RFC 6241, Section 8.7";
- }
-
- feature url {
- description
- "NETCONF :url capability;
- If the server advertises the :url
- capability for a session, then this feature must
- also be enabled for that session. Otherwise,
- this feature must not be enabled.";
- reference "RFC 6241, Section 8.8";
- }
-
- feature xpath {
- description
- "NETCONF :xpath capability;
- If the server advertises the :xpath
- capability for a session, then this feature must
- also be enabled for that session. Otherwise,
- this feature must not be enabled.";
- reference "RFC 6241, Section 8.9";
- }
-
- // NETCONF Simple Types
-
- typedef session-id-type {
- type uint32 {
- range "1..max";
- }
- description
- "NETCONF Session Id";
- }
-
- typedef session-id-or-zero-type {
- type uint32;
- description
- "NETCONF Session Id or Zero to indicate none";
- }
- typedef error-tag-type {
- type enumeration {
- enum in-use {
- description
- "The request requires a resource that
- already is in use.";
- }
- enum invalid-value {
- description
- "The request specifies an unacceptable value for one
- or more parameters.";
- }
- enum too-big {
- description
- "The request or response (that would be generated) is
- too large for the implementation to handle.";
- }
- enum missing-attribute {
- description
- "An expected attribute is missing.";
- }
- enum bad-attribute {
- description
- "An attribute value is not correct; e.g., wrong type,
- out of range, pattern mismatch.";
- }
- enum unknown-attribute {
- description
- "An unexpected attribute is present.";
- }
- enum missing-element {
- description
- "An expected element is missing.";
- }
- enum bad-element {
- description
- "An element value is not correct; e.g., wrong type,
- out of range, pattern mismatch.";
- }
- enum unknown-element {
- description
- "An unexpected element is present.";
- }
- enum unknown-namespace {
- description
- "An unexpected namespace is present.";
- }
- enum access-denied {
- description
- "Access to the requested protocol operation or
- data model is denied because authorization failed.";
- }
- enum lock-denied {
- description
- "Access to the requested lock is denied because the
- lock is currently held by another entity.";
- }
- enum resource-denied {
- description
- "Request could not be completed because of
- insufficient resources.";
- }
- enum rollback-failed {
- description
- "Request to roll back some configuration change (via
- rollback-on-error or <discard-changes> operations)
- was not completed for some reason.";
-
- }
- enum data-exists {
- description
- "Request could not be completed because the relevant
- data model content already exists. For example,
- a 'create' operation was attempted on data that
- already exists.";
- }
- enum data-missing {
- description
- "Request could not be completed because the relevant
- data model content does not exist. For example,
- a 'delete' operation was attempted on
- data that does not exist.";
- }
- enum operation-not-supported {
- description
- "Request could not be completed because the requested
- operation is not supported by this implementation.";
- }
- enum operation-failed {
- description
- "Request could not be completed because the requested
- operation failed for some reason not covered by
- any other error condition.";
- }
- enum partial-operation {
- description
- "This error-tag is obsolete, and SHOULD NOT be sent
- by servers conforming to this document.";
- }
- enum malformed-message {
- description
- "A message could not be handled because it failed to
- be parsed correctly. For example, the message is not
- well-formed XML or it uses an invalid character set.";
- }
- }
- description "NETCONF Error Tag";
- reference "RFC 6241, Appendix A";
- }
-
- typedef error-severity-type {
- type enumeration {
- enum error {
- description "Error severity";
- }
- enum warning {
- description "Warning severity";
- }
- }
- description "NETCONF Error Severity";
- reference "RFC 6241, Section 4.3";
- }
-
- typedef edit-operation-type {
- type enumeration {
- enum merge {
- description
- "The configuration data identified by the
- element containing this attribute is merged
- with the configuration at the corresponding
- level in the configuration datastore identified
- by the target parameter.";
- }
- enum replace {
- description
- "The configuration data identified by the element
- containing this attribute replaces any related
- configuration in the configuration datastore
- identified by the target parameter. If no such
- configuration data exists in the configuration
- datastore, it is created. Unlike a
- <copy-config> operation, which replaces the
- entire target configuration, only the configuration
- actually present in the config parameter is affected.";
- }
- enum create {
- description
- "The configuration data identified by the element
- containing this attribute is added to the
- configuration if and only if the configuration
- data does not already exist in the configuration
- datastore. If the configuration data exists, an
- <rpc-error> element is returned with an
- <error-tag> value of 'data-exists'.";
- }
- enum delete {
- description
- "The configuration data identified by the element
- containing this attribute is deleted from the
- configuration if and only if the configuration
- data currently exists in the configuration
- datastore. If the configuration data does not
- exist, an <rpc-error> element is returned with
- an <error-tag> value of 'data-missing'.";
- }
- enum remove {
- description
- "The configuration data identified by the element
- containing this attribute is deleted from the
- configuration if the configuration
- data currently exists in the configuration
- datastore. If the configuration data does not
- exist, the 'remove' operation is silently ignored
- by the server.";
- }
- }
- default "merge";
- description "NETCONF 'operation' attribute values";
- reference "RFC 6241, Section 7.2";
- }
-
- // NETCONF Standard Protocol Operations
-
- rpc get-config {
- description
- "Retrieve all or part of a specified configuration.";
-
- reference "RFC 6241, Section 7.1";
-
- input {
- container source {
- description
- "Particular configuration to retrieve.";
-
- choice config-source {
- mandatory true;
- description
- "The configuration to retrieve.";
- leaf candidate {
- if-feature candidate;
- type empty;
- description
- "The candidate configuration is the config source.";
- }
- leaf running {
- type empty;
- description
- "The running configuration is the config source.";
- }
- leaf startup {
- if-feature startup;
- type empty;
- description
- "The startup configuration is the config source.
- This is optional-to-implement on the server because
- not all servers will support filtering for this
- datastore.";
- }
- }
- }
-
- anyxml filter {
- description
- "Subtree or XPath filter to use.";
- nc:get-filter-element-attributes;
- }
- }
-
- output {
- anyxml data {
- description
- "Copy of the source datastore subset that matched
- the filter criteria (if any). An empty data container
- indicates that the request did not produce any results.";
- }
- }
- }
-
- rpc edit-config {
- description
- "The <edit-config> operation loads all or part of a specified
- configuration to the specified target configuration.";
-
- reference "RFC 6241, Section 7.2";
-
- input {
- container target {
- description
- "Particular configuration to edit.";
-
- choice config-target {
- mandatory true;
- description
- "The configuration target.";
-
- leaf candidate {
- if-feature candidate;
- type empty;
- description
- "The candidate configuration is the config target.";
- }
- leaf running {
- if-feature writable-running;
- type empty;
- description
- "The running configuration is the config source.";
- }
- }
- }
-
- leaf default-operation {
- type enumeration {
- enum merge {
- description
- "The default operation is merge.";
- }
- enum replace {
- description
- "The default operation is replace.";
- }
- enum none {
- description
- "There is no default operation.";
- }
- }
- default "merge";
- description
- "The default operation to use.";
- }
-
- leaf test-option {
- if-feature validate;
- type enumeration {
- enum test-then-set {
- description
- "The server will test and then set if no errors.";
- }
- enum set {
- description
- "The server will set without a test first.";
- }
-
- enum test-only {
- description
- "The server will only test and not set, even
- if there are no errors.";
- }
- }
- default "test-then-set";
- description
- "The test option to use.";
- }
-
- leaf error-option {
- type enumeration {
- enum stop-on-error {
- description
- "The server will stop on errors.";
- }
- enum continue-on-error {
- description
- "The server may continue on errors.";
- }
- enum rollback-on-error {
- description
- "The server will roll back on errors.
- This value can only be used if the 'rollback-on-error'
- feature is supported.";
- }
- }
- default "stop-on-error";
- description
- "The error option to use.";
- }
-
- choice edit-content {
- mandatory true;
- description
- "The content for the edit operation.";
-
- anyxml config {
- description
- "Inline Config content.";
- }
- leaf url {
- if-feature url;
- type inet:uri;
- description
- "URL-based config content.";
- }
- }
- }
- }
-
- rpc copy-config {
- description
- "Create or replace an entire configuration datastore with the
- contents of another complete configuration datastore.";
-
- reference "RFC 6241, Section 7.3";
-
- input {
- container target {
- description
- "Particular configuration to copy to.";
-
- choice config-target {
- mandatory true;
- description
- "The configuration target of the copy operation.";
-
- leaf candidate {
- if-feature candidate;
- type empty;
- description
- "The candidate configuration is the config target.";
- }
- leaf running {
- if-feature writable-running;
- type empty;
- description
- "The running configuration is the config target.
- This is optional-to-implement on the server.";
- }
- leaf startup {
- if-feature startup;
- type empty;
- description
- "The startup configuration is the config target.";
- }
- leaf url {
- if-feature url;
- type inet:uri;
- description
- "The URL-based configuration is the config target.";
- }
- }
- }
-
- container source {
- description
- "Particular configuration to copy from.";
-
- choice config-source {
- mandatory true;
- description
- "The configuration source for the copy operation.";
-
- leaf candidate {
- if-feature candidate;
- type empty;
- description
- "The candidate configuration is the config source.";
- }
- leaf running {
- type empty;
- description
- "The running configuration is the config source.";
- }
- leaf startup {
- if-feature startup;
- type empty;
- description
- "The startup configuration is the config source.";
- }
- leaf url {
- if-feature url;
- type inet:uri;
- description
- "The URL-based configuration is the config source.";
- }
- anyxml config {
- description
- "Inline Config content: <config> element. Represents
- an entire configuration datastore, not
- a subset of the running datastore.";
- }
- }
- }
- }
- }
-
- rpc delete-config {
- description
- "Delete a configuration datastore.";
-
- reference "RFC 6241, Section 7.4";
-
- input {
- container target {
- description
- "Particular configuration to delete.";
-
- choice config-target {
- mandatory true;
- description
- "The configuration target to delete.";
-
- leaf startup {
- if-feature startup;
- type empty;
- description
- "The startup configuration is the config target.";
- }
- leaf url {
- if-feature url;
- type inet:uri;
- description
- "The URL-based configuration is the config target.";
- }
- }
- }
- }
- }
-
- rpc lock {
- description
- "The lock operation allows the client to lock the configuration
- system of a device.";
-
- reference "RFC 6241, Section 7.5";
-
- input {
- container target {
- description
- "Particular configuration to lock.";
-
- choice config-target {
- mandatory true;
- description
- "The configuration target to lock.";
-
- leaf candidate {
- if-feature candidate;
- type empty;
- description
- "The candidate configuration is the config target.";
- }
- leaf running {
- type empty;
- description
- "The running configuration is the config target.";
- }
- leaf startup {
- if-feature startup;
- type empty;
- description
- "The startup configuration is the config target.";
- }
- }
- }
- }
- }
-
- rpc unlock {
- description
- "The unlock operation is used to release a configuration lock,
- previously obtained with the 'lock' operation.";
-
- reference "RFC 6241, Section 7.6";
-
- input {
- container target {
- description
- "Particular configuration to unlock.";
-
- choice config-target {
- mandatory true;
- description
- "The configuration target to unlock.";
-
- leaf candidate {
- if-feature candidate;
- type empty;
- description
- "The candidate configuration is the config target.";
- }
- leaf running {
- type empty;
- description
- "The running configuration is the config target.";
- }
- leaf startup {
- if-feature startup;
- type empty;
- description
- "The startup configuration is the config target.";
- }
- }
- }
- }
- }
-
- rpc get {
- description
- "Retrieve running configuration and device state information.";
-
- reference "RFC 6241, Section 7.7";
-
- input {
- anyxml filter {
- description
- "This parameter specifies the portion of the system
- configuration and state data to retrieve.";
- nc:get-filter-element-attributes;
- }
- }
-
- output {
- anyxml data {
- description
- "Copy of the running datastore subset and/or state
- data that matched the filter criteria (if any).
- An empty data container indicates that the request did not
- produce any results.";
- }
- }
- }
-
- rpc close-session {
- description
- "Request graceful termination of a NETCONF session.";
-
- reference "RFC 6241, Section 7.8";
- }
-
- rpc kill-session {
- description
- "Force the termination of a NETCONF session.";
-
- reference "RFC 6241, Section 7.9";
-
- input {
- leaf session-id {
- type session-id-type;
- mandatory true;
- description
- "Particular session to kill.";
- }
- }
- }
-
- rpc commit {
- if-feature candidate;
-
- description
- "Commit the candidate configuration as the device's new
- current configuration.";
-
- reference "RFC 6241, Section 8.3.4.1";
-
- input {
- leaf confirmed {
- if-feature confirmed-commit;
- type empty;
- description
- "Requests a confirmed commit.";
- reference "RFC 6241, Section 8.3.4.1";
- }
-
- leaf confirm-timeout {
- if-feature confirmed-commit;
- type uint32 {
- range "1..max";
- }
- units "seconds";
- default "600"; // 10 minutes
- description
- "The timeout interval for a confirmed commit.";
- reference "RFC 6241, Section 8.3.4.1";
- }
-
- leaf persist {
- if-feature confirmed-commit;
- type string;
- description
- "This parameter is used to make a confirmed commit
- persistent. A persistent confirmed commit is not aborted
- if the NETCONF session terminates. The only way to abort
- a persistent confirmed commit is to let the timer expire,
- or to use the <cancel-commit> operation.
-
- The value of this parameter is a token that must be given
- in the 'persist-id' parameter of <commit> or
- <cancel-commit> operations in order to confirm or cancel
- the persistent confirmed commit.
-
- The token should be a random string.";
- reference "RFC 6241, Section 8.3.4.1";
- }
-
- leaf persist-id {
- if-feature confirmed-commit;
- type string;
- description
- "This parameter is given in order to commit a persistent
- confirmed commit. The value must be equal to the value
- given in the 'persist' parameter to the <commit> operation.
- If it does not match, the operation fails with an
- 'invalid-value' error.";
- reference "RFC 6241, Section 8.3.4.1";
- }
-
- }
- }
-
- rpc discard-changes {
- if-feature candidate;
-
- description
- "Revert the candidate configuration to the current
- running configuration.";
- reference "RFC 6241, Section 8.3.4.2";
- }
-
- rpc cancel-commit {
- if-feature confirmed-commit;
- description
- "This operation is used to cancel an ongoing confirmed commit.
- If the confirmed commit is persistent, the parameter
- 'persist-id' must be given, and it must match the value of the
- 'persist' parameter.";
- reference "RFC 6241, Section 8.4.4.1";
-
- input {
- leaf persist-id {
- type string;
- description
- "This parameter is given in order to cancel a persistent
- confirmed commit. The value must be equal to the value
- given in the 'persist' parameter to the <commit> operation.
- If it does not match, the operation fails with an
- 'invalid-value' error.";
- }
- }
- }
-
- rpc validate {
- if-feature validate;
-
- description
- "Validates the contents of the specified configuration.";
-
- reference "RFC 6241, Section 8.6.4.1";
-
- input {
- container source {
- description
- "Particular configuration to validate.";
-
- choice config-source {
- mandatory true;
- description
- "The configuration source to validate.";
-
- leaf candidate {
- if-feature candidate;
- type empty;
- description
- "The candidate configuration is the config source.";
- }
- leaf running {
- type empty;
- description
- "The running configuration is the config source.";
- }
- leaf startup {
- if-feature startup;
- type empty;
- description
- "The startup configuration is the config source.";
- }
- leaf url {
- if-feature url;
- type inet:uri;
- description
- "The URL-based configuration is the config source.";
- }
- anyxml config {
- description
- "Inline Config content: <config> element. Represents
- an entire configuration datastore, not
- a subset of the running datastore.";
- }
- }
- }
- }
- }
-
-}
+++ /dev/null
-module model1 {
- namespace "ns:model1";
- prefix "mod1";
-
- revision "2014-05-14" {
- }
-
- container cont1 {
- container cont11 {
- list lst111 {
- key lf1111;
- leaf lf1111 {
- type int32;
- }
- container cont111 {
- leaf lf1112 {
- type string;
- }
- leaf-list lflst1111 {
- type int8;
- }
- }
- }
- }
-
- container cont12 {
- list lst121 {
- key lf1211;
- leaf lf1211 {
- type string;
- }
- list lst1211 {
- leaf lf12111 {
- type uint8;
- }
- leaf lf12112 {
- type string;
- }
- }
- }
- choice chcA {
- case AA {
- leaf lf12AA1 {
- type string;
- }
- }
- case AB {
- container cont12AB1 {
- leaf lf12AB1 {
- type string;
- }
- }
- }
- leaf lf121 { //should be standalone case
- type string;
- }
- }
- list lst122 {
- }
- }
- }
-
- container cont2 {
- container cont23 {
- }
- }
-
- container contA {
- }
-
- container contB {
- }
-
-}
\ No newline at end of file
+++ /dev/null
-module model2 {
- namespace "ns:model2";
- prefix "mod2";
-
- import model1 {prefix model1; revision-date 2014-05-14;}
-
- revision "2014-05-14" {
- }
-
- container contA {
- }
-
- container contB {
- }
-
- augment "/model1:cont2" {
- container cont21 {
- }
-
- container cont22 {
- }
- }
-
- augment "/model1:cont1" {
- list lst11 {
- leaf lf111 {
- type string;
- }
- }
- }
-
-}
\ No newline at end of file
<name>${project.artifactId}</name>
<modules>
- <module>netconf-cli</module>
<module>netconf-testtool</module>
</modules>
</project>