From: Tony Tkacik Date: Mon, 16 Mar 2015 07:13:14 +0000 (+0000) Subject: Merge "BUG-2829: make static QName field hold a cached reference" X-Git-Tag: release/lithium~233 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=24dab42c40a325745944c0e9f4fe1d64783f9d25;hp=5a86454fa5c6983e77be28d599f115e27a903f09;p=yangtools.git Merge "BUG-2829: make static QName field hold a cached reference" --- diff --git a/code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/TypeProviderImpl.java b/code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/TypeProviderImpl.java index b393c13367..11edd05925 100644 --- a/code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/TypeProviderImpl.java +++ b/code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/TypeProviderImpl.java @@ -621,7 +621,7 @@ public final class TypeProviderImpl implements TypeProvider { */ private void resolveTypeDefsFromContext() { final Set modules = schemaContext.getModules(); - Preconditions.checkArgument(modules != null, "Sef of Modules cannot be NULL!"); + Preconditions.checkArgument(modules != null, "Set of Modules cannot be NULL!"); final Module[] modulesArray = new Module[modules.size()]; int i = 0; for (Module modul : modules) { @@ -635,8 +635,7 @@ public final class TypeProviderImpl implements TypeProvider { if (dateTypeMap == null) { dateTypeMap = new HashMap<>(); } - final Map typeMap = new HashMap<>(); - dateTypeMap.put(module.getRevision(), typeMap); + dateTypeMap.put(module.getRevision(), Collections.emptyMap()); genTypeDefsContextMap.put(module.getName(), dateTypeMap); } @@ -731,8 +730,12 @@ public final class TypeProviderImpl implements TypeProvider { } if (returnType != null) { final Map> modulesByDate = genTypeDefsContextMap.get(moduleName); - final Map typeMap = modulesByDate.get(moduleRevision); + Map typeMap = modulesByDate.get(moduleRevision); if (typeMap != null) { + if (typeMap.isEmpty()) { + typeMap = new HashMap<>(4); + modulesByDate.put(moduleRevision, typeMap); + } typeMap.put(typedefName, returnType); } return returnType; diff --git a/common/artifacts/pom.xml b/common/artifacts/pom.xml index 3d2643e75b..177ff6d3bc 100644 --- a/common/artifacts/pom.xml +++ b/common/artifacts/pom.xml @@ -157,6 +157,11 @@ ietf-yang-types-20130715 2013.07.15.7-SNAPSHOT + + org.opendaylight.yangtools.model + ietf-interfaces + 2014.05.08.7-SNAPSHOT + org.opendaylight.yangtools.model ietf-restconf diff --git a/common/features/pom.xml b/common/features/pom.xml index 385312defc..ee0221b39d 100644 --- a/common/features/pom.xml +++ b/common/features/pom.xml @@ -38,6 +38,10 @@ org.opendaylight.yangtools.model ietf-inet-types + + org.opendaylight.yangtools.model + ietf-interfaces + org.opendaylight.yangtools.model ietf-restconf diff --git a/common/features/src/main/features/features.xml b/common/features/src/main/features/features.xml index 673c7bced9..0725979012 100644 --- a/common/features/src/main/features/features.xml +++ b/common/features/src/main/features/features.xml @@ -22,6 +22,7 @@ odl-yangtools-binding mvn:org.opendaylight.yangtools.model/ietf-inet-types/{{VERSION}} + mvn:org.opendaylight.yangtools.model/ietf-interfaces/{{VERSION}} mvn:org.opendaylight.yangtools.model/ietf-yang-types/{{VERSION}} mvn:org.opendaylight.yangtools.model/ietf-yang-types-20130715/{{VERSION}} mvn:org.opendaylight.yangtools.model/ietf-restconf/{{VERSION}} diff --git a/model/ietf/ietf-interfaces/pom.xml b/model/ietf/ietf-interfaces/pom.xml new file mode 100644 index 0000000000..4044cec629 --- /dev/null +++ b/model/ietf/ietf-interfaces/pom.xml @@ -0,0 +1,54 @@ + + + + + + + model-ietf + org.opendaylight.yangtools.model + 0.7.0-SNAPSHOT + + + 4.0.0 + ietf-interfaces + 2014.05.08.7-SNAPSHOT + ${project.artifactId} + ${project.artifactId} + + + + org.opendaylight.yangtools.model + ietf-inet-types + + + org.opendaylight.yangtools.model + ietf-yang-types + + + + + + + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.groupId}.${project.artifactId} + + + + + + + + diff --git a/model/ietf/ietf-interfaces/src/main/yang/ietf-interfaces.yang b/model/ietf/ietf-interfaces/src/main/yang/ietf-interfaces.yang new file mode 100644 index 0000000000..ad64425f7a --- /dev/null +++ b/model/ietf/ietf-interfaces/src/main/yang/ietf-interfaces.yang @@ -0,0 +1,725 @@ +module ietf-interfaces { + + namespace "urn:ietf:params:xml:ns:yang:ietf-interfaces"; + prefix if; + + import ietf-yang-types { + prefix yang; + } + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + WG Chair: Thomas Nadeau + + + WG Chair: Juergen Schoenwaelder + + + Editor: Martin Bjorklund + "; + + description + "This module contains a collection of YANG definitions for + managing network interfaces. + + Copyright (c) 2014 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 7223; see + the RFC itself for full legal notices."; + + revision 2014-05-08 { + description + "Initial revision."; + reference + "RFC 7223: A YANG Data Model for Interface Management"; + } + + /* + * Typedefs + */ + + typedef interface-ref { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + description + "This type is used by data models that need to reference + configured interfaces."; + } + + typedef interface-state-ref { + type leafref { + path "/if:interfaces-state/if:interface/if:name"; + } + description + "This type is used by data models that need to reference + the operationally present interfaces."; + } + + /* + * Identities + */ + + identity interface-type { + description + "Base identity from which specific interface types are + derived."; + } + + /* + * Features + */ + + feature arbitrary-names { + description + "This feature indicates that the device allows user-controlled + interfaces to be named arbitrarily."; + } + feature pre-provisioning { + description + "This feature indicates that the device supports + pre-provisioning of interface configuration, i.e., it is + possible to configure an interface whose physical interface + hardware is not present on the device."; + } + + feature if-mib { + description + "This feature indicates that the device implements + the IF-MIB."; + reference + "RFC 2863: The Interfaces Group MIB"; + } + + /* + * Configuration data nodes + */ + + container interfaces { + description + "Interface configuration parameters."; + + list interface { + key "name"; + + description + "The list of configured interfaces on the device. + + The operational state of an interface is available in the + /interfaces-state/interface list. If the configuration of a + system-controlled interface cannot be used by the system + (e.g., the interface hardware present does not match the + interface type), then the configuration is not applied to + the system-controlled interface shown in the + /interfaces-state/interface list. If the configuration + of a user-controlled interface cannot be used by the system, + the configured interface is not instantiated in the + /interfaces-state/interface list."; + + leaf name { + type string; + description + "The name of the interface. + + A device MAY restrict the allowed values for this leaf, + possibly depending on the type of the interface. + For system-controlled interfaces, this leaf is the + device-specific name of the interface. The 'config false' + list /interfaces-state/interface contains the currently + existing interfaces on the device. + + If a client tries to create configuration for a + system-controlled interface that is not present in the + /interfaces-state/interface list, the server MAY reject + the request if the implementation does not support + pre-provisioning of interfaces or if the name refers to + an interface that can never exist in the system. A + NETCONF server MUST reply with an rpc-error with the + error-tag 'invalid-value' in this case. + + If the device supports pre-provisioning of interface + configuration, the 'pre-provisioning' feature is + advertised. + + If the device allows arbitrarily named user-controlled + interfaces, the 'arbitrary-names' feature is advertised. + + When a configured user-controlled interface is created by + the system, it is instantiated with the same name in the + /interface-state/interface list."; + } + + leaf description { + type string; + description + "A textual description of the interface. + + A server implementation MAY map this leaf to the ifAlias + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and ifAlias. The definition of + such a mechanism is outside the scope of this document. + + Since ifAlias is defined to be stored in non-volatile + storage, the MIB implementation MUST map ifAlias to the + value of 'description' in the persistently stored + datastore. + + Specifically, if the device supports ':startup', when + ifAlias is read the device MUST return the value of + 'description' in the 'startup' datastore, and when it is + written, it MUST be written to the 'running' and 'startup' + datastores. Note that it is up to the implementation to + + decide whether to modify this single leaf in 'startup' or + perform an implicit copy-config from 'running' to + 'startup'. + + If the device does not support ':startup', ifAlias MUST + be mapped to the 'description' leaf in the 'running' + datastore."; + reference + "RFC 2863: The Interfaces Group MIB - ifAlias"; + } + + leaf type { + type identityref { + base interface-type; + } + mandatory true; + description + "The type of the interface. + + When an interface entry is created, a server MAY + initialize the type leaf with a valid value, e.g., if it + is possible to derive the type from the name of the + interface. + + If a client tries to set the type of an interface to a + value that can never be used by the system, e.g., if the + type is not supported or if the type does not match the + name of the interface, the server MUST reject the request. + A NETCONF server MUST reply with an rpc-error with the + error-tag 'invalid-value' in this case."; + reference + "RFC 2863: The Interfaces Group MIB - ifType"; + } + + leaf enabled { + type boolean; + default "true"; + description + "This leaf contains the configured, desired state of the + interface. + + Systems that implement the IF-MIB use the value of this + leaf in the 'running' datastore to set + IF-MIB.ifAdminStatus to 'up' or 'down' after an ifEntry + has been initialized, as described in RFC 2863. + + + + Changes in this leaf in the 'running' datastore are + reflected in ifAdminStatus, but if ifAdminStatus is + changed over SNMP, this leaf is not affected."; + reference + "RFC 2863: The Interfaces Group MIB - ifAdminStatus"; + } + + leaf link-up-down-trap-enable { + if-feature if-mib; + type enumeration { + enum enabled { + value 1; + } + enum disabled { + value 2; + } + } + description + "Controls whether linkUp/linkDown SNMP notifications + should be generated for this interface. + + If this node is not configured, the value 'enabled' is + operationally used by the server for interfaces that do + not operate on top of any other interface (i.e., there are + no 'lower-layer-if' entries), and 'disabled' otherwise."; + reference + "RFC 2863: The Interfaces Group MIB - + ifLinkUpDownTrapEnable"; + } + } + } + + /* + * Operational state data nodes + */ + + container interfaces-state { + config false; + description + "Data nodes for the operational state of interfaces."; + + list interface { + key "name"; + + + + + + description + "The list of interfaces on the device. + + System-controlled interfaces created by the system are + always present in this list, whether they are configured or + not."; + + leaf name { + type string; + description + "The name of the interface. + + A server implementation MAY map this leaf to the ifName + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and ifName. The definition of + such a mechanism is outside the scope of this document."; + reference + "RFC 2863: The Interfaces Group MIB - ifName"; + } + + leaf type { + type identityref { + base interface-type; + } + mandatory true; + description + "The type of the interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifType"; + } + + leaf admin-status { + if-feature if-mib; + type enumeration { + enum up { + value 1; + description + "Ready to pass packets."; + } + enum down { + value 2; + description + "Not ready to pass packets and not in some test mode."; + } + + + + enum testing { + value 3; + description + "In some test mode."; + } + } + mandatory true; + description + "The desired state of the interface. + + This leaf has the same read semantics as ifAdminStatus."; + reference + "RFC 2863: The Interfaces Group MIB - ifAdminStatus"; + } + + leaf oper-status { + type enumeration { + enum up { + value 1; + description + "Ready to pass packets."; + } + enum down { + value 2; + description + "The interface does not pass any packets."; + } + enum testing { + value 3; + description + "In some test mode. No operational packets can + be passed."; + } + enum unknown { + value 4; + description + "Status cannot be determined for some reason."; + } + enum dormant { + value 5; + description + "Waiting for some external event."; + } + enum not-present { + value 6; + description + "Some component (typically hardware) is missing."; + } + enum lower-layer-down { + value 7; + description + "Down due to state of lower-layer interface(s)."; + } + } + mandatory true; + description + "The current operational state of the interface. + + This leaf has the same semantics as ifOperStatus."; + reference + "RFC 2863: The Interfaces Group MIB - ifOperStatus"; + } + + leaf last-change { + type yang:date-and-time; + description + "The time the interface entered its current operational + state. If the current state was entered prior to the + last re-initialization of the local network management + subsystem, then this node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - ifLastChange"; + } + + leaf if-index { + if-feature if-mib; + type int32 { + range "1..2147483647"; + } + mandatory true; + description + "The ifIndex value for the ifEntry represented by this + interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifIndex"; + } + + leaf phys-address { + type yang:phys-address; + description + "The interface's address at its protocol sub-layer. For + example, for an 802.x interface, this object normally + contains a Media Access Control (MAC) address. The + interface's media-specific modules must define the bit + + + and byte ordering and the format of the value of this + object. For interfaces that do not have such an address + (e.g., a serial line), this node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - ifPhysAddress"; + } + + leaf-list higher-layer-if { + type interface-state-ref; + description + "A list of references to interfaces layered on top of this + interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifStackTable"; + } + + leaf-list lower-layer-if { + type interface-state-ref; + description + "A list of references to interfaces layered underneath this + interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifStackTable"; + } + + leaf speed { + type yang:gauge64; + units "bits/second"; + description + "An estimate of the interface's current bandwidth in bits + per second. For interfaces that do not vary in + bandwidth or for those where no accurate estimation can + be made, this node should contain the nominal bandwidth. + For interfaces that have no concept of bandwidth, this + node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - + ifSpeed, ifHighSpeed"; + } + + + + + + + + + + container statistics { + description + "A collection of interface-related statistics objects."; + + leaf discontinuity-time { + type yang:date-and-time; + mandatory true; + description + "The time on the most recent occasion at which any one or + more of this interface's counters suffered a + discontinuity. If no such discontinuities have occurred + since the last re-initialization of the local management + subsystem, then this node contains the time the local + management subsystem re-initialized itself."; + } + + leaf in-octets { + type yang:counter64; + description + "The total number of octets received on the interface, + including framing characters. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system, and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCInOctets"; + } + + leaf in-unicast-pkts { + type yang:counter64; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were not addressed to a + multicast or broadcast address at this sub-layer. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system, and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCInUcastPkts"; + } + + + + + leaf in-broadcast-pkts { + type yang:counter64; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were addressed to a broadcast + address at this sub-layer. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system, and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCInBroadcastPkts"; + } + + leaf in-multicast-pkts { + type yang:counter64; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were addressed to a multicast + address at this sub-layer. For a MAC-layer protocol, + this includes both Group and Functional addresses. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system, and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCInMulticastPkts"; + } + + leaf in-discards { + type yang:counter32; + description + "The number of inbound packets that were chosen to be + discarded even though no errors had been detected to + prevent their being deliverable to a higher-layer + protocol. One possible reason for discarding such a + packet could be to free up buffer space. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system, and at + other times as indicated by the value of + 'discontinuity-time'."; + + + reference + "RFC 2863: The Interfaces Group MIB - ifInDiscards"; + } + + leaf in-errors { + type yang:counter32; + description + "For packet-oriented interfaces, the number of inbound + packets that contained errors preventing them from being + deliverable to a higher-layer protocol. For character- + oriented or fixed-length interfaces, the number of + inbound transmission units that contained errors + preventing them from being deliverable to a higher-layer + protocol. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system, and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifInErrors"; + } + + leaf in-unknown-protos { + type yang:counter32; + description + "For packet-oriented interfaces, the number of packets + received via the interface that were discarded because + of an unknown or unsupported protocol. For + character-oriented or fixed-length interfaces that + support protocol multiplexing, the number of + transmission units received via the interface that were + discarded because of an unknown or unsupported protocol. + For any interface that does not support protocol + multiplexing, this counter is not present. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system, and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifInUnknownProtos"; + } + + + + + + leaf out-octets { + type yang:counter64; + description + "The total number of octets transmitted out of the + interface, including framing characters. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system, and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCOutOctets"; + } + + leaf out-unicast-pkts { + type yang:counter64; + description + "The total number of packets that higher-level protocols + requested be transmitted, and that were not addressed + to a multicast or broadcast address at this sub-layer, + including those that were discarded or not sent. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system, and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCOutUcastPkts"; + } + + leaf out-broadcast-pkts { + type yang:counter64; + description + "The total number of packets that higher-level protocols + requested be transmitted, and that were addressed to a + broadcast address at this sub-layer, including those + that were discarded or not sent. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system, and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCOutBroadcastPkts"; + } + + + leaf out-multicast-pkts { + type yang:counter64; + description + "The total number of packets that higher-level protocols + requested be transmitted, and that were addressed to a + multicast address at this sub-layer, including those + that were discarded or not sent. For a MAC-layer + protocol, this includes both Group and Functional + addresses. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system, and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCOutMulticastPkts"; + } + + leaf out-discards { + type yang:counter32; + description + "The number of outbound packets that were chosen to be + discarded even though no errors had been detected to + prevent their being transmitted. One possible reason + for discarding such a packet could be to free up buffer + space. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system, and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifOutDiscards"; + } + + leaf out-errors { + type yang:counter32; + description + "For packet-oriented interfaces, the number of outbound + packets that could not be transmitted because of errors. + For character-oriented or fixed-length interfaces, the + number of outbound transmission units that could not be + transmitted because of errors. + + + + + Discontinuities in the value of this counter can occur + at re-initialization of the management system, and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifOutErrors"; + } + } + } + } +} diff --git a/model/ietf/pom.xml b/model/ietf/pom.xml index fe4328cd02..5677b0c11b 100644 --- a/model/ietf/pom.xml +++ b/model/ietf/pom.xml @@ -23,6 +23,7 @@ ietf-inet-types + ietf-interfaces ietf-yang-types ietf-yang-types-20130715 ietf-ted diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/ChoiceNodeDataWithSchema.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/ChoiceNodeDataWithSchema.java index cacc6727de..b7ab6fa19b 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/ChoiceNodeDataWithSchema.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/ChoiceNodeDataWithSchema.java @@ -27,8 +27,8 @@ class ChoiceNodeDataWithSchema extends CompositeNodeDataWithSchema { } @Override - protected CompositeNodeDataWithSchema addCompositeChild(final DataSchemaNode schema, final boolean rootListItem) { - final CaseNodeDataWithSchema newChild = new CaseNodeDataWithSchema((ChoiceCaseNode) schema); + protected CompositeNodeDataWithSchema addCompositeChild(final DataSchemaNode schema) { + CaseNodeDataWithSchema newChild = new CaseNodeDataWithSchema((ChoiceCaseNode) schema); caseNodeDataWithSchema = newChild; addCompositeChild(newChild); return newChild; diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/CompositeNodeDataWithSchema.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/CompositeNodeDataWithSchema.java index c071bbde82..70612910d6 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/CompositeNodeDataWithSchema.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/CompositeNodeDataWithSchema.java @@ -59,14 +59,14 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema { super(schema); } - public AbstractNodeDataWithSchema addChild(final Deque schemas, final boolean rootListItem) { + public AbstractNodeDataWithSchema addChild(final Deque schemas) { Preconditions.checkArgument(!schemas.isEmpty(), "Expecting at least one schema"); // Pop the first node... final DataSchemaNode schema = schemas.pop(); if (schemas.isEmpty()) { // Simple, direct node - return addChild(schema,rootListItem); + return addChild(schema); } // The choice/case mess, reuse what we already popped @@ -95,12 +95,12 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema { CompositeNodeDataWithSchema caseNodeDataWithSchema = findChoice(childNodes, choiceCandidate, caseCandidate); if (caseNodeDataWithSchema == null) { - final ChoiceNodeDataWithSchema choiceNodeDataWithSchema = new ChoiceNodeDataWithSchema(choiceNode); + ChoiceNodeDataWithSchema choiceNodeDataWithSchema = new ChoiceNodeDataWithSchema(choiceNode); addChild(choiceNodeDataWithSchema); - caseNodeDataWithSchema = choiceNodeDataWithSchema.addCompositeChild(caseNode,rootListItem); + caseNodeDataWithSchema = choiceNodeDataWithSchema.addCompositeChild(caseNode); } - return caseNodeDataWithSchema.addChild(schemas, rootListItem); + return caseNodeDataWithSchema.addChild(schemas); } private AbstractNodeDataWithSchema addSimpleChild(final DataSchemaNode schema) { @@ -128,10 +128,10 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema { private CaseNodeDataWithSchema findChoice(final Collection childNodes, final DataSchemaNode choiceCandidate, final DataSchemaNode caseCandidate) { if (childNodes != null) { - for (final AbstractNodeDataWithSchema nodeDataWithSchema : childNodes) { + for (AbstractNodeDataWithSchema nodeDataWithSchema : childNodes) { if (nodeDataWithSchema instanceof ChoiceNodeDataWithSchema && nodeDataWithSchema.getSchema().getQName().equals(choiceCandidate.getQName())) { - final CaseNodeDataWithSchema casePrevious = ((ChoiceNodeDataWithSchema) nodeDataWithSchema).getCase(); + CaseNodeDataWithSchema casePrevious = ((ChoiceNodeDataWithSchema) nodeDataWithSchema).getCase(); Preconditions.checkArgument(casePrevious.getSchema().getQName().equals(caseCandidate.getQName()), "Data from case %s are specified but other data from case %s were specified erlier. Data aren't from the same case.", @@ -144,20 +144,10 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema { return null; } - AbstractNodeDataWithSchema addCompositeChild(final DataSchemaNode schema, final boolean rootListItem) { + AbstractNodeDataWithSchema addCompositeChild(final DataSchemaNode schema) { CompositeNodeDataWithSchema newChild; if (schema instanceof ListSchemaNode) { newChild = new ListNodeDataWithSchema(schema); - /* - * If we are reading root we may want to emit map also for object which represent one list - * item. - * */ - if(rootListItem) { - addCompositeChild(newChild); - final ListEntryNodeDataWithSchema entry = new ListEntryNodeDataWithSchema(schema); - newChild.addChild(entry); - return entry; - } } else if (schema instanceof LeafListSchemaNode) { newChild = new LeafListNodeDataWithSchema(schema); } else if (schema instanceof ContainerSchemaNode) { @@ -170,7 +160,7 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema { } void addCompositeChild(final CompositeNodeDataWithSchema newChild) { - final AugmentationSchema augSchema = findCorrespondingAugment(getSchema(), newChild.getSchema()); + AugmentationSchema augSchema = findCorrespondingAugment(getSchema(), newChild.getSchema()); if (augSchema != null) { augmentationsToChild.put(augSchema, newChild); } else { @@ -178,9 +168,9 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema { } } - private AbstractNodeDataWithSchema addChild(final DataSchemaNode schema, final boolean rootListItem) { - final AbstractNodeDataWithSchema newChild = addSimpleChild(schema); - return newChild == null ? addCompositeChild(schema,rootListItem) : newChild; + private AbstractNodeDataWithSchema addChild(final DataSchemaNode schema) { + AbstractNodeDataWithSchema newChild = addSimpleChild(schema); + return newChild == null ? addCompositeChild(schema) : newChild; } public void addChild(final AbstractNodeDataWithSchema newChild) { @@ -201,8 +191,8 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema { */ AugmentationSchema findCorrespondingAugment(final DataSchemaNode parent, final DataSchemaNode child) { if (parent instanceof AugmentationTarget && !((parent instanceof ChoiceCaseNode) || (parent instanceof ChoiceSchemaNode))) { - for (final AugmentationSchema augmentation : ((AugmentationTarget) parent).getAvailableAugmentations()) { - final DataSchemaNode childInAugmentation = augmentation.getDataChildByName(child.getQName()); + for (AugmentationSchema augmentation : ((AugmentationTarget) parent).getAvailableAugmentations()) { + DataSchemaNode childInAugmentation = augmentation.getDataChildByName(child.getQName()); if (childInAugmentation != null) { return augmentation; } @@ -213,15 +203,15 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema { @Override public void write(final NormalizedNodeStreamWriter writer) throws IOException { - for (final AbstractNodeDataWithSchema child : children) { + for (AbstractNodeDataWithSchema child : children) { child.write(writer); } - for (final Entry> augmentationToChild : augmentationsToChild.asMap().entrySet()) { + for (Entry> augmentationToChild : augmentationsToChild.asMap().entrySet()) { final Collection childsFromAgumentation = augmentationToChild.getValue(); if (!childsFromAgumentation.isEmpty()) { writer.startAugmentationNode(toAugmentationIdentifier(augmentationToChild.getKey())); - for (final AbstractNodeDataWithSchema nodeDataWithSchema : childsFromAgumentation) { + for (AbstractNodeDataWithSchema nodeDataWithSchema : childsFromAgumentation) { nodeDataWithSchema.write(writer); } diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonParserStream.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonParserStream.java index f56d6d2344..4934161bd2 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonParserStream.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonParserStream.java @@ -83,7 +83,7 @@ public final class JsonParserStream implements Closeable, Flushable { reader.peek(); isEmpty = false; final CompositeNodeDataWithSchema compositeNodeDataWithSchema = new CompositeNodeDataWithSchema(parentNode); - read(reader, compositeNodeDataWithSchema,true); + read(reader, compositeNodeDataWithSchema); compositeNodeDataWithSchema.write(writer); return this; @@ -115,7 +115,7 @@ public final class JsonParserStream implements Closeable, Flushable { ((SimpleNodeDataWithSchema) parent).setValue(translatedValue); } - public void read(final JsonReader in, final AbstractNodeDataWithSchema parent, final boolean rootRead) throws IOException { + public void read(final JsonReader in, AbstractNodeDataWithSchema parent) throws IOException { switch (in.peek()) { case STRING: case NUMBER: @@ -131,21 +131,24 @@ public final class JsonParserStream implements Closeable, Flushable { case BEGIN_ARRAY: in.beginArray(); while (in.hasNext()) { - AbstractNodeDataWithSchema newChild = null; - if (parent instanceof ListNodeDataWithSchema) { - newChild = new ListEntryNodeDataWithSchema(parent.getSchema()); - ((CompositeNodeDataWithSchema) parent).addChild(newChild); - } else if (parent instanceof LeafListNodeDataWithSchema) { - newChild = new LeafListEntryNodeDataWithSchema(parent.getSchema()); - ((CompositeNodeDataWithSchema) parent).addChild(newChild); - } - read(in, newChild,false); + final AbstractNodeDataWithSchema newChild = newArrayEntry(parent); + read(in, newChild); } in.endArray(); return; case BEGIN_OBJECT: final Set namesakes = new HashSet<>(); in.beginObject(); + /* + * This allows parsing of incorrectly /as showcased/ + * in testconf nesting of list items - eg. + * lists with one value are sometimes serialized + * without wrapping array. + * + */ + if(isArray(parent)) { + parent = newArrayEntry(parent); + } while (in.hasNext()) { final String jsonElementName = in.nextName(); final NamespaceAndName namespaceAndName = resolveNamespace(jsonElementName, parent.getSchema()); @@ -162,13 +165,16 @@ public final class JsonParserStream implements Closeable, Flushable { + getCurrentNamespace() + " doesn't exist."); } - AbstractNodeDataWithSchema newChild; - newChild = ((CompositeNodeDataWithSchema) parent).addChild(childDataSchemaNodes,rootRead); -// FIXME:anyxml data shouldn't be skipped but should be loaded somehow. will be specified after 17AUG2014 + final AbstractNodeDataWithSchema newChild = ((CompositeNodeDataWithSchema) parent).addChild(childDataSchemaNodes); + /* + * FIXME:anyxml data shouldn't be skipped but should be loaded somehow. + * will be able to load anyxml which conforms to YANG data using these + * parser, for other anyxml will be harder. + */ if (newChild instanceof AnyXmlNodeDataWithSchema) { in.skipValue(); } else { - read(in, newChild,false); + read(in, newChild); } removeNamespace(); } @@ -182,6 +188,23 @@ public final class JsonParserStream implements Closeable, Flushable { } } + private boolean isArray(final AbstractNodeDataWithSchema parent) { + return parent instanceof ListNodeDataWithSchema || parent instanceof ListNodeDataWithSchema; + } + + private AbstractNodeDataWithSchema newArrayEntry(final AbstractNodeDataWithSchema parent) { + AbstractNodeDataWithSchema newChild; + if (parent instanceof ListNodeDataWithSchema) { + newChild = new ListEntryNodeDataWithSchema(parent.getSchema()); + } else if (parent instanceof LeafListNodeDataWithSchema) { + newChild = new LeafListEntryNodeDataWithSchema(parent.getSchema()); + } else { + throw new IllegalStateException("Incorrec nesting caused by parser."); + } + ((CompositeNodeDataWithSchema) parent).addChild(newChild); + return newChild; + } + private Object translateValueByType(final String value, final DataSchemaNode node) { final TypeDefinition typeDefinition = typeDefinition(node); if (typeDefinition == null) { diff --git a/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonStreamToNormalizedNodeTest.java b/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonStreamToNormalizedNodeTest.java index 6fb7b1ed34..c1ff375d23 100644 --- a/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonStreamToNormalizedNodeTest.java +++ b/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonStreamToNormalizedNodeTest.java @@ -200,6 +200,19 @@ public class JsonStreamToNormalizedNodeTest { assertNotNull(transformedInput); } + @Test + public void listItemWithArray() throws IOException, URISyntaxException { + final String inputJson = loadTextFile("/complexjson/keyed-list-yang-json-behaviour.json"); + + final NormalizedNodeResult result = new NormalizedNodeResult(); + final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result); + final SchemaNode parentNode = schemaContext.getDataChildByName("cont1"); + final JsonParserStream jsonParser = JsonParserStream.create(streamWriter, schemaContext, parentNode); + jsonParser.parse(new JsonReader(new StringReader(inputJson))); + final NormalizedNode transformedInput = result.getResult(); + assertNotNull(transformedInput); + } + private void verifyTransformationToNormalizedNode(final String inputJson, final NormalizedNode awaitedStructure) { final NormalizedNodeResult result = new NormalizedNodeResult(); diff --git a/yang/yang-data-codec-gson/src/test/resources/complexjson/keyed-list-yang-json-behaviour.json b/yang/yang-data-codec-gson/src/test/resources/complexjson/keyed-list-yang-json-behaviour.json new file mode 100644 index 0000000000..af6b3ec275 --- /dev/null +++ b/yang/yang-data-codec-gson/src/test/resources/complexjson/keyed-list-yang-json-behaviour.json @@ -0,0 +1,8 @@ +{ + "lst11": [{ + "key111":"key111 value", + "lf112":"/complexjson:cont1/complexjson:lflst11[.='foo']", + "lf113":"lf113 value", + "lf111":"lf111 value" + }] +}