From: lsedlak Date: Wed, 3 Jul 2013 15:37:59 +0000 (+0200) Subject: Added support to generate types from Choices and Cases added by augmentation. X-Git-Tag: releasepom-0.1.0~312^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=dbb76fc3dd402304e093025d107f7e9bf620bdbe Added support to generate types from Choices and Cases added by augmentation. Added implementation into BindingGeneratorImpl to suppor of generating Generated Types for Choices and Cases from augmentations; Extended ChoiceNode API and ChoiceNodeBuilder to getCaseNodeByName methods; Fixed findSchemaNodeForGivenPath in SchemaContextUtil to support of traversal through Choice and Case nodes in data schema tree; Signed-off-by: Lukas Sedlak --- diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/BindingGeneratorImpl.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/BindingGeneratorImpl.java index 8b680509dd..ebefa1067e 100644 --- a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/BindingGeneratorImpl.java +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/generator/impl/BindingGeneratorImpl.java @@ -523,20 +523,38 @@ public final class BindingGeneratorImpl implements BindingGenerator { if ((targetSchemaNode != null) && (targetSchemaNode.getQName() != null) && (targetSchemaNode.getQName().getLocalName() != null)) { final Module targetModule = findParentModule(schemaContext, targetSchemaNode); - final String targetBasePackage = moduleNamespaceToPackageName(targetModule); final String targetPackageName = packageNameForGeneratedType(targetBasePackage, targetSchemaNode.getPath()); - final String targetSchemaNodeName = targetSchemaNode.getQName().getLocalName(); final Set augChildNodes = augSchema.getChildNodes(); - final GeneratedTypeBuilder augTypeBuilder = addRawAugmentGenTypeDefinition(augmentPackageName, - targetPackageName, targetSchemaNodeName, augSchema); - if (augTypeBuilder != null) { - genTypes.add(augTypeBuilder.toInstance()); + + if (!(targetSchemaNode instanceof ChoiceNode)) { + final GeneratedTypeBuilder augTypeBuilder = addRawAugmentGenTypeDefinition(augmentPackageName, + targetPackageName, targetSchemaNodeName, augSchema); + final GeneratedType augType = augTypeBuilder.toInstance(); + genTypes.add(augType); + } else { + final Type refChoiceType = new ReferencedTypeImpl(targetPackageName, + parseToClassName(targetSchemaNodeName)); + final ChoiceNode choiceTarget = (ChoiceNode) targetSchemaNode; + final Set choiceCaseNodes = choiceTarget.getCases(); + genTypes.addAll(augmentCasesToGenTypes(augmentPackageName, refChoiceType, choiceCaseNodes)); } genTypes.addAll(augmentationBodyToGenTypes(augmentPackageName, augChildNodes)); + } + return genTypes; + } + private List augmentCasesToGenTypes(final String augmentPackageName, final Type refChoiceType, + final Set choiceCaseNodes) { + if (augmentPackageName == null) { + throw new IllegalArgumentException("Augment Package Name string cannot be NULL!"); } + if (choiceCaseNodes == null) { + throw new IllegalArgumentException("Set of Choice Case Nodes cannot be NULL!"); + } + final List genTypes = generateTypesFromAugmentedChoiceCases(augmentPackageName, refChoiceType, + choiceCaseNodes); return genTypes; } @@ -576,23 +594,35 @@ public final class BindingGeneratorImpl implements BindingGenerator { } else if (childNode instanceof ListSchemaNode) { genTypes.addAll(listToGenType(augBasePackageName, (ListSchemaNode) childNode)); } + } else if (childNode instanceof ChoiceNode) { + final ChoiceNode choice = (ChoiceNode) childNode; + for (final ChoiceCaseNode caseNode : choice.getCases()) { + augSchemaIts.add(new DataNodeIterator(caseNode)); + } + genTypes.addAll(choiceToGeneratedType(augBasePackageName, (ChoiceNode) childNode)); } } for (final DataNodeIterator it : augSchemaIts) { final List augContainers = it.allContainers(); final List augLists = it.allLists(); + final List augChoices = it.allChoices(); - if ((augContainers != null) && !augContainers.isEmpty()) { + if (augContainers != null) { for (final ContainerSchemaNode container : augContainers) { genTypes.add(containerToGenType(augBasePackageName, container)); } } - if ((augLists != null) && !augLists.isEmpty()) { + if (augLists != null) { for (final ListSchemaNode list : augLists) { genTypes.addAll(listToGenType(augBasePackageName, list)); } } + if (augChoices != null) { + for (final ChoiceNode choice : augChoices) { + genTypes.addAll(choiceToGeneratedType(augBasePackageName, choice)); + } + } } return genTypes; } @@ -719,7 +749,37 @@ public final class BindingGeneratorImpl implements BindingGenerator { final List generatedTypes = new ArrayList<>(); for (final ChoiceCaseNode caseNode : caseNodes) { - if (caseNode != null) { + if (caseNode != null && !caseNode.isAddedByUses()) { + final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath()); + final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode); + caseTypeBuilder.addImplementsType(refChoiceType); + + final Set childNodes = caseNode.getChildNodes(); + if (childNodes != null) { + resolveDataSchemaNodes(basePackageName, caseTypeBuilder, childNodes); + } + generatedTypes.add(caseTypeBuilder.toInstance()); + } + } + + return generatedTypes; + } + + private List generateTypesFromAugmentedChoiceCases(final String basePackageName, + final Type refChoiceType, final Set caseNodes) { + if (basePackageName == null) { + throw new IllegalArgumentException("Base Package Name cannot be NULL!"); + } + if (refChoiceType == null) { + throw new IllegalArgumentException("Referenced Choice Type cannot be NULL!"); + } + if (caseNodes == null) { + throw new IllegalArgumentException("Set of Choice Case Nodes cannot be NULL!"); + } + + final List generatedTypes = new ArrayList<>(); + for (final ChoiceCaseNode caseNode : caseNodes) { + if (caseNode != null && caseNode.isAugmenting()) { final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath()); final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode); caseTypeBuilder.addImplementsType(refChoiceType); @@ -862,11 +922,13 @@ public final class BindingGeneratorImpl implements BindingGenerator { } /** - * Method instantiates new Generated Type Builder and sets the implements definitions of Data Object and - * Augmentable. - * - * @param packageName Generated Type Package Name - * @param schemaNode Schema Node definition + * Method instantiates new Generated Type Builder and sets the implements + * definitions of Data Object and Augmentable. + * + * @param packageName + * Generated Type Package Name + * @param schemaNode + * Schema Node definition * @return Generated Type Builder instance for Schema Node definition */ private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode) { @@ -877,7 +939,7 @@ public final class BindingGeneratorImpl implements BindingGenerator { } /** - * + * * @param packageName * @param schemaNode * @return diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/generator/impl/ChoiceCaseGenTypesTest.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/generator/impl/ChoiceCaseGenTypesTest.java index e800b5b8c7..9db19fdfb5 100644 --- a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/generator/impl/ChoiceCaseGenTypesTest.java +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/generator/impl/ChoiceCaseGenTypesTest.java @@ -52,9 +52,5 @@ public class ChoiceCaseGenTypesTest { assertNotNull("genTypes is null", genTypes); assertFalse("genTypes is empty", genTypes.isEmpty()); - - //Expected 23 types from ietf-netconf-monitoring - //Expected 14 types from ietf-yang-types - //Expected 14 types from ietf-inet-types } } diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/choice-case-type-test-models/augment-monitoring@2013-07-01.yang b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/choice-case-type-test-models/augment-monitoring@2013-07-01.yang index 17cf07c49a..4683598c6b 100644 --- a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/choice-case-type-test-models/augment-monitoring@2013-07-01.yang +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/choice-case-type-test-models/augment-monitoring@2013-07-01.yang @@ -3,7 +3,7 @@ module augment-monitoring { namespace "urn:ietf:params:xml:ns:yang:augment-monitoring"; prefix "amon"; - import ietf-netconf-monitoring { prefix nm; } + import choice-monitoring { prefix nm; } organization "OPEN DAYLIGHT"; contact "http://www.opendaylight.org/"; diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/choice-case-type-test-models/choice-monitoring@2013-07-01.yang b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/choice-case-type-test-models/choice-monitoring@2013-07-01.yang new file mode 100644 index 0000000000..2362783edd --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/choice-case-type-test-models/choice-monitoring@2013-07-01.yang @@ -0,0 +1,129 @@ +module choice-monitoring { + yang-version 1; + namespace "urn:ietf:params:xml:ns:yang:choice-monitoring"; + prefix "ncm"; + + import ietf-yang-types { prefix yang; } + import ietf-inet-types { prefix inet; } + + organization "OPEN DAYLIGHT"; + contact "http://www.opendaylight.org/"; + + description + "Test model for testing of resolving choice, case nodes and generation types from them."; + + revision 2013-07-01 { + + } + + typedef tls-fingerprint-type { + type string { + pattern '([0-9a-fA-F]){2}(:([0-9a-fA-F]){2})*'; + } + } + + typedef netconf-datastore-type { + type enumeration { + enum running; + enum candidate; + enum startup; + } + } + + container netconf-state { + config false; + + container datastores { + list datastore { + key name; + + leaf name { + type netconf-datastore-type; + } + container locks { + choice lock-type { + + case global-lock { + container global-lock { + + leaf locked-by-session { + type uint32; + mandatory true; + } + + leaf locked-time { + type yang:date-and-time; + mandatory true; + } + + container capabilities { + leaf-list capability { + type inet:uri; + } + } + } + } + + case partial-lock { + list partial-lock { + key lock-id; + + leaf lock-id { + type uint32; + } + leaf-list select { + type yang:xpath1.0; + min-elements 1; + } + leaf-list locked-node { + type string; + } + } + } + + case fingerprint { + choice algorithm-and-hash { + mandatory true; + case md5 { + leaf md5 { + type tls-fingerprint-type; + } + } + + case sha1 { + leaf sha1 { + type tls-fingerprint-type; + } + } + + case sha224 { + leaf sha224 { + type tls-fingerprint-type; + } + } + + case sha256 { + leaf sha256 { + type tls-fingerprint-type; + } + } + + case sha384 { + leaf sha384 { + type tls-fingerprint-type; + } + } + + case sha512 { + leaf sha512 { + type tls-fingerprint-type; + } + } + } + } + } + } + } + } + } +} diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/choice-case-type-test-models/ietf-netconf-monitoring@2010-10-04.yang b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/choice-case-type-test-models/ietf-netconf-monitoring@2010-10-04.yang deleted file mode 100644 index 695fb1dd38..0000000000 --- a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/choice-case-type-test-models/ietf-netconf-monitoring@2010-10-04.yang +++ /dev/null @@ -1,254 +0,0 @@ -module ietf-netconf-monitoring { - - namespace "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring"; - prefix "ncm"; - - import ietf-yang-types { prefix yang; } - import ietf-inet-types { prefix inet; } - - organization - "IETF NETCONF (Network Configuration) Working Group"; - - contact - "WG Web: - WG List: - - WG Chair: Mehmet Ersue - - - WG Chair: Bert Wijnen - - - Editor: Mark Scott - - - Editor: Martin Bjorklund - "; - - description - "NETCONF Monitoring Module. - All elements in this module are read-only. - - 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 6022; see - the RFC itself for full legal notices."; - - revision 2010-10-04 { - description - "Initial revision."; - reference - "RFC 6022: YANG Module for NETCONF Monitoring"; - } - - typedef tls-fingerprint-type { - type string { - pattern '([0-9a-fA-F]){2}(:([0-9a-fA-F]){2})*'; - } - description - "A cryptographic signature (fingerprint) value that can be used to - uniquely reference other data of potentially arbitrary length."; - } - - typedef netconf-datastore-type { - type enumeration { - enum running; - enum candidate; - enum startup; - } - description - "Enumeration of possible NETCONF datastore types."; - reference - "RFC 4741: NETCONF Configuration Protocol"; - } - - container netconf-state { - config false; - description - "The netconf-state container is the root of the monitoring - data model."; - - container datastores { - description - "Contains the list of NETCONF configuration datastores."; - - list datastore { - key name; - description - "List of NETCONF configuration datastores supported by - the NETCONF server and related information."; - - leaf name { - type netconf-datastore-type; - description - "Name of the datastore associated with this list entry."; - } - container locks { - presence - "This container is present only if the datastore - is locked."; - description - "The NETCONF and operations allow - a client to lock specific resources in a datastore. The - NETCONF server will prevent changes to the locked - resources by all sessions except the one that acquired - the lock(s). - - Monitoring information is provided for each datastore - entry including details such as the session that acquired - the lock, the type of lock (global or partial) and the - list of locked resources. Multiple locks per datastore - are supported."; - - choice lock-type { - description - "Indicates if a global lock or a set of partial locks - are set."; - - case global-lock { - container global-lock { - description - "Present if the global lock is set."; - - leaf locked-by-session { - type uint32; - mandatory true; - description - "The session ID of the session that has locked - this resource. Both a global lock and a partial - lock MUST contain the NETCONF session-id. - - If the lock is held by a session that is not managed - by the NETCONF server (e.g., a CLI session), a session - id of 0 (zero) is reported."; - reference - "RFC 4741: NETCONF Configuration Protocol"; - } - leaf locked-time { - type yang:date-and-time; - mandatory true; - description - "The date and time of when the resource was - locked."; - } - - container capabilities { - description - "Contains the list of NETCONF capabilities supported by the - server."; - - leaf-list capability { - type inet:uri; - description - "List of NETCONF capabilities supported by the server."; - } - } - } - } - - case partial-lock { - list partial-lock { - key lock-id; - description - "List of partial locks."; - reference - "RFC 5717: Partial Lock Remote Procedure Call (RPC) for - NETCONF"; - - leaf lock-id { - type uint32; - description - "This is the lock id returned in the - response."; - } - leaf-list select { - type yang:xpath1.0; - min-elements 1; - description - "The xpath expression that was used to request - the lock. The select expression indicates the - original intended scope of the lock."; - } - leaf-list locked-node { - type string; - description - "The list of instance-identifiers (i.e., the - locked nodes). The scope of the partial lock is defined by the list - of locked nodes."; - } - } - } - - case fingerprint { - choice algorithm-and-hash { - mandatory true; - case md5 { - leaf md5 { - type tls-fingerprint-type; - } - } - - case sha1 { - leaf sha1 { - type tls-fingerprint-type; - } - } - - case sha224 { - leaf sha224 { - type tls-fingerprint-type; - } - } - - case sha256 { - leaf sha256 { - type tls-fingerprint-type; - } - } - - case sha384 { - leaf sha384 { - type tls-fingerprint-type; - } - } - - case sha512 { - leaf sha512 { - type tls-fingerprint-type; - } - } - - description - "Specifies the signature algorithm and cryptographic - signature (fingerprint) used to identify an X.509 - certificate. - - Implementations of this YANG module MAY, but are not - required to, implement all of these cryptographic signature - algorithms. Implementations of this YANG module MUST - implement at least one of these cryptographic signature - algorithms. - - The available choices may be extended in the future as - stronger cryptographic signature algorithms become - available and are deemed necessary."; - - reference - "RFC 5246: The Transport Layer Security (TLS) Protocol - Version 1.2; Section 7.4.1.4.1, Signature Algorithms"; - } // choice algorithm-and-hash - } - } - } - } - } - } -} diff --git a/opendaylight/sal/yang-prototype/code-generator/samples/maven-code-gen-sample/src/main/yang/augment-monitoring@2013-07-01.yang b/opendaylight/sal/yang-prototype/code-generator/samples/maven-code-gen-sample/src/main/yang/augment-monitoring@2013-07-01.yang new file mode 100644 index 0000000000..4683598c6b --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/samples/maven-code-gen-sample/src/main/yang/augment-monitoring@2013-07-01.yang @@ -0,0 +1,88 @@ +module augment-monitoring { + yang-version 1; + namespace "urn:ietf:params:xml:ns:yang:augment-monitoring"; + prefix "amon"; + + import choice-monitoring { prefix nm; } + + organization "OPEN DAYLIGHT"; + contact "http://www.opendaylight.org/"; + + revision "2013-07-01" { + reference "NO REF"; + } + + augment "/nm:netconf-state/nm:datastores/nm:datastore/nm:locks/nm:lock-type" { + case autonomous-lock { + container autonomous-def { + leaf lock-id { + type int32; + } + + leaf lock-time { + type uint32; + } + } + } + + case anonymous-lock { + leaf lock-time { + type uint32; + } + } + + leaf leaf-aug-case { + type string; + } + } + + augment "/nm:netconf-state/nm:datastores/nm:datastore/nm:locks/nm:lock-type/nm:partial-lock" { + choice aug-case-by-choice { + case foo { + leaf foo { + type string; + } + } + + case bar { + leaf bar { + type boolean; + } + } + } + } + + augment "/nm:netconf-state/nm:datastores/nm:datastore" { + choice storage-format { + case xml { + container xml-def { + leaf file-name { + type string; + } + } + } + + case yang { + leaf yang-file-name { + type string; + } + } + + case unknown-files { + list files { + key "file-name"; + + leaf file-name { + type string; + } + + container file-data { + leaf utf8-data { + type string; + } + } + } + } + } + } +} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/code-generator/samples/maven-code-gen-sample/src/main/yang/choice-monitoring@2013-07-01.yang b/opendaylight/sal/yang-prototype/code-generator/samples/maven-code-gen-sample/src/main/yang/choice-monitoring@2013-07-01.yang new file mode 100644 index 0000000000..2362783edd --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/samples/maven-code-gen-sample/src/main/yang/choice-monitoring@2013-07-01.yang @@ -0,0 +1,129 @@ +module choice-monitoring { + yang-version 1; + namespace "urn:ietf:params:xml:ns:yang:choice-monitoring"; + prefix "ncm"; + + import ietf-yang-types { prefix yang; } + import ietf-inet-types { prefix inet; } + + organization "OPEN DAYLIGHT"; + contact "http://www.opendaylight.org/"; + + description + "Test model for testing of resolving choice, case nodes and generation types from them."; + + revision 2013-07-01 { + + } + + typedef tls-fingerprint-type { + type string { + pattern '([0-9a-fA-F]){2}(:([0-9a-fA-F]){2})*'; + } + } + + typedef netconf-datastore-type { + type enumeration { + enum running; + enum candidate; + enum startup; + } + } + + container netconf-state { + config false; + + container datastores { + list datastore { + key name; + + leaf name { + type netconf-datastore-type; + } + container locks { + choice lock-type { + + case global-lock { + container global-lock { + + leaf locked-by-session { + type uint32; + mandatory true; + } + + leaf locked-time { + type yang:date-and-time; + mandatory true; + } + + container capabilities { + leaf-list capability { + type inet:uri; + } + } + } + } + + case partial-lock { + list partial-lock { + key lock-id; + + leaf lock-id { + type uint32; + } + leaf-list select { + type yang:xpath1.0; + min-elements 1; + } + leaf-list locked-node { + type string; + } + } + } + + case fingerprint { + choice algorithm-and-hash { + mandatory true; + case md5 { + leaf md5 { + type tls-fingerprint-type; + } + } + + case sha1 { + leaf sha1 { + type tls-fingerprint-type; + } + } + + case sha224 { + leaf sha224 { + type tls-fingerprint-type; + } + } + + case sha256 { + leaf sha256 { + type tls-fingerprint-type; + } + } + + case sha384 { + leaf sha384 { + type tls-fingerprint-type; + } + } + + case sha512 { + leaf sha512 { + type tls-fingerprint-type; + } + } + } + } + } + } + } + } + } +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/ChoiceBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/ChoiceBuilder.java index 1b4283a463..01acc11f23 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/ChoiceBuilder.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/parser/builder/impl/ChoiceBuilder.java @@ -376,6 +376,36 @@ public final class ChoiceBuilder extends AbstractSchemaNodeBuilder implements Da return cases; } + @Override + public ChoiceCaseNode getCaseNodeByName(final QName name) { + if (name == null) { + throw new IllegalArgumentException("Choice Case QName cannot be NULL!"); + } + for (final ChoiceCaseNode caseNode : cases) { + if (caseNode != null) { + if (name.equals(caseNode.getQName())) { + return caseNode; + } + } + } + return null; + } + + @Override + public ChoiceCaseNode getCaseNodeByName(final String name) { + if (name == null) { + throw new IllegalArgumentException("Choice Case string Name cannot be NULL!"); + } + for (final ChoiceCaseNode caseNode : cases) { + if (caseNode != null && (caseNode.getQName() != null)) { + if (name.equals(caseNode.getQName().getLocalName())) { + return caseNode; + } + } + } + return null; + } + private void setCases(Set cases) { if (cases != null) { this.cases = cases; diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ChoiceNode.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ChoiceNode.java index ee4163da48..140ef84c6c 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ChoiceNode.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ChoiceNode.java @@ -7,6 +7,8 @@ */ package org.opendaylight.controller.yang.model.api; +import org.opendaylight.controller.yang.common.QName; + import java.util.Set; /** @@ -20,6 +22,22 @@ public interface ChoiceNode extends DataSchemaNode, AugmentationTarget { */ Set getCases(); + /** + * @param name + * QName of seeked Choice Case Node + * @return child case node of this Choice if child with given name is + * present, null otherwise + */ + ChoiceCaseNode getCaseNodeByName(QName name); + + /** + * @param name + * name of seeked child as String + * @return child case node (or local name of case node) of this Choice if child with given name is + * present, null otherwise + */ + ChoiceCaseNode getCaseNodeByName(String name); + String getDefaultCase(); } diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/SchemaContextUtil.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/SchemaContextUtil.java index 13c2ba7cb5..44ef804e2c 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/SchemaContextUtil.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/SchemaContextUtil.java @@ -14,21 +14,12 @@ import java.util.Queue; import java.util.Set; import org.opendaylight.controller.yang.common.QName; -import org.opendaylight.controller.yang.model.api.ContainerSchemaNode; -import org.opendaylight.controller.yang.model.api.DataNodeContainer; -import org.opendaylight.controller.yang.model.api.DataSchemaNode; -import org.opendaylight.controller.yang.model.api.ListSchemaNode; -import org.opendaylight.controller.yang.model.api.Module; -import org.opendaylight.controller.yang.model.api.ModuleImport; -import org.opendaylight.controller.yang.model.api.RevisionAwareXPath; -import org.opendaylight.controller.yang.model.api.SchemaContext; -import org.opendaylight.controller.yang.model.api.SchemaNode; -import org.opendaylight.controller.yang.model.api.SchemaPath; -import org.opendaylight.controller.yang.model.api.TypeDefinition; +import org.opendaylight.controller.yang.model.api.*; public final class SchemaContextUtil { - private SchemaContextUtil() {} + private SchemaContextUtil() { + } public static DataSchemaNode findDataSchemaNode(final SchemaContext context, final SchemaPath schemaPath) { if (schemaPath != null) { @@ -52,11 +43,9 @@ public final class SchemaContextUtil { // TODO: function to escape conditions in path } if (nonCondXPath.isAbsolute()) { - final Queue qnamedPath = xpathToQNamePath(context, module, - strXPath); + final Queue qnamedPath = xpathToQNamePath(context, module, strXPath); if (qnamedPath != null) { - final DataSchemaNode dataNode = findSchemaNodeForGivenPath(context, - module, qnamedPath); + final DataSchemaNode dataNode = findSchemaNodeForGivenPath(context, module, qnamedPath); return dataNode; } } @@ -65,20 +54,16 @@ public final class SchemaContextUtil { return null; } - public static DataSchemaNode findDataSchemaNodeForRelativeXPath(final SchemaContext context, - final Module module, final SchemaNode actualSchemaNode, - final RevisionAwareXPath relativeXPath) { - if ((actualSchemaNode != null) && (relativeXPath != null) - && !relativeXPath.isAbsolute()) { + public static DataSchemaNode findDataSchemaNodeForRelativeXPath(final SchemaContext context, final Module module, + final SchemaNode actualSchemaNode, final RevisionAwareXPath relativeXPath) { + if ((actualSchemaNode != null) && (relativeXPath != null) && !relativeXPath.isAbsolute()) { final SchemaPath actualNodePath = actualSchemaNode.getPath(); if (actualNodePath != null) { - final Queue qnamePath = resolveRelativeXPath(context, module, - relativeXPath, actualNodePath); + final Queue qnamePath = resolveRelativeXPath(context, module, relativeXPath, actualNodePath); if (qnamePath != null) { - final DataSchemaNode dataNode = findSchemaNodeForGivenPath(context, - module, qnamePath); + final DataSchemaNode dataNode = findSchemaNodeForGivenPath(context, module, qnamePath); return dataNode; } } @@ -87,8 +72,7 @@ public final class SchemaContextUtil { return null; } - private static Module resolveModuleFromSchemaPath(final SchemaContext - context, final SchemaPath schemaPath) { + private static Module resolveModuleFromSchemaPath(final SchemaContext context, final SchemaPath schemaPath) { if ((schemaPath != null) && (schemaPath.getPath() != null)) { final List path = schemaPath.getPath(); if (!path.isEmpty()) { @@ -102,11 +86,10 @@ public final class SchemaContextUtil { return null; } - public static Module findParentModuleForTypeDefinition( - final SchemaContext context, final TypeDefinition type) { + public static Module findParentModuleForTypeDefinition(final SchemaContext context, final TypeDefinition type) { final SchemaPath schemaPath = type.getPath(); if ((schemaPath != null) && (schemaPath.getPath() != null)) { - if(type instanceof ExtendedType) { + if (type instanceof ExtendedType) { List path = schemaPath.getPath(); final QName qname = path.get(path.size() - 1); @@ -136,14 +119,14 @@ public final class SchemaContextUtil { final SchemaPath schemaPath = schemaNode.getPath(); if (schemaPath == null) { - throw new IllegalStateException("Schema Path for Schema Node is not " + - "set properly (Schema Path is NULL)"); + throw new IllegalStateException("Schema Path for Schema Node is not " + + "set properly (Schema Path is NULL)"); } final List qnamedPath = schemaPath.getPath(); if (qnamedPath == null || qnamedPath.isEmpty()) { - throw new IllegalStateException("Schema Path contains invalid state of path parts." + - "The Schema Path MUST contain at least ONE QName which defines namespace and Local name" + - "of path."); + throw new IllegalStateException("Schema Path contains invalid state of path parts." + + "The Schema Path MUST contain at least ONE QName which defines namespace and Local name" + + "of path."); } final QName qname = qnamedPath.get(qnamedPath.size() - 1); return context.findModuleByNamespace(qname.getNamespace()); @@ -151,12 +134,11 @@ public final class SchemaContextUtil { private static DataSchemaNode findSchemaNodeForGivenPath(final SchemaContext context, final Module module, final Queue qnamedPath) { - if ((module != null) && (module.getNamespace() != null) - && (qnamedPath != null)) { + if ((module != null) && (module.getNamespace() != null) && (qnamedPath != null)) { DataNodeContainer nextNode = module; final URI moduleNamespace = module.getNamespace(); - QName childNodeQName = null; + QName childNodeQName; DataSchemaNode schemaNode = null; while ((nextNode != null) && !qnamedPath.isEmpty()) { childNodeQName = qnamedPath.peek(); @@ -169,14 +151,20 @@ public final class SchemaContextUtil { nextNode = (ContainerSchemaNode) schemaNode; } else if (schemaNode instanceof ListSchemaNode) { nextNode = (ListSchemaNode) schemaNode; + } else if (schemaNode instanceof ChoiceNode) { + final ChoiceNode choice = (ChoiceNode) schemaNode; + qnamedPath.poll(); + if (!qnamedPath.isEmpty()) { + childNodeQName = qnamedPath.peek(); + nextNode = choice.getCaseNodeByName(childNodeQName); + schemaNode = (DataSchemaNode)nextNode; + } } else { nextNode = null; } } else if (!childNodeNamespace.equals(moduleNamespace)) { - final Module nextModule = context - .findModuleByNamespace(childNodeNamespace); - schemaNode = findSchemaNodeForGivenPath(context, nextModule, - qnamedPath); + final Module nextModule = context.findModuleByNamespace(childNodeNamespace); + schemaNode = findSchemaNodeForGivenPath(context, nextModule, qnamedPath); return schemaNode; } qnamedPath.poll(); @@ -207,22 +195,18 @@ public final class SchemaContextUtil { if (parentModule != null && prefixedPathPart != null) { if (prefixedPathPart.contains(":")) { final String[] prefixedName = prefixedPathPart.split(":"); - final Module module = resolveModuleForPrefix(context, parentModule, - prefixedName[0]); + final Module module = resolveModuleForPrefix(context, parentModule, prefixedName[0]); if (module != null) { - return new QName(module.getNamespace(), module - .getRevision(), prefixedName[1]); + return new QName(module.getNamespace(), module.getRevision(), prefixedName[1]); } } else { - return new QName(parentModule.getNamespace(), - parentModule.getRevision(), prefixedPathPart); + return new QName(parentModule.getNamespace(), parentModule.getRevision(), prefixedPathPart); } } return null; } - private static Module resolveModuleForPrefix(final SchemaContext context, final Module module, - final String prefix) { + private static Module resolveModuleForPrefix(final SchemaContext context, final Module module, final String prefix) { if ((module != null) && (prefix != null)) { if (prefix.equals(module.getPrefix())) { return module; @@ -232,8 +216,7 @@ public final class SchemaContextUtil { for (final ModuleImport mi : imports) { if (prefix.equals(mi.getPrefix())) { - return context.findModuleByName(mi.getModuleName(), - mi.getRevision()); + return context.findModuleByName(mi.getModuleName(), mi.getRevision()); } } } @@ -241,12 +224,10 @@ public final class SchemaContextUtil { } private static Queue resolveRelativeXPath(final SchemaContext context, final Module module, - final RevisionAwareXPath relativeXPath, - final SchemaPath leafrefSchemaPath) { + final RevisionAwareXPath relativeXPath, final SchemaPath leafrefSchemaPath) { final Queue absolutePath = new LinkedList<>(); - if ((module != null) && (relativeXPath != null) && !relativeXPath.isAbsolute() - && (leafrefSchemaPath != null)) { + if ((module != null) && (relativeXPath != null) && !relativeXPath.isAbsolute() && (leafrefSchemaPath != null)) { final String strXPath = relativeXPath.toString(); if (strXPath != null) { final String[] xpaths = strXPath.split("/");