Bug 2444 - fix of several issues in yang-model-export 16/57816/12
authorPeter Kajsa <pkajsa@cisco.com>
Thu, 25 May 2017 13:42:57 +0000 (15:42 +0200)
committerRobert Varga <nite@hq.sk>
Tue, 13 Jun 2017 15:10:47 +0000 (15:10 +0000)
Add Yin export of:
- action, anydata and modifier statements
- must statement in notification, input and output
- description and reference in import statements
- notification statements in data nodes
- unique statement in list statements
- optional of organisation and contact statements
- require-instance statement in leafref specification
- length statement in binary specification
- multiple base identities in identity-ref type
  and identity definition
- default values in leaf-list statement

Change-Id: I1e1662716caaf8fe118bb7db55148bc13ee81951
Signed-off-by: Peter Kajsa <pkajsa@cisco.com>
37 files changed:
yang/yang-model-export/src/main/java/org/opendaylight/yangtools/yang/model/export/SchemaContextEmitter.java
yang/yang-model-export/src/main/java/org/opendaylight/yangtools/yang/model/export/SchemaToStatementWriterAdaptor.java
yang/yang-model-export/src/main/java/org/opendaylight/yangtools/yang/model/export/YangModuleWriter.java [moved from yang/yang-model-export/src/main/java/org/opendaylight/yangtools/yang/model/export/Rfc6020ModuleWriter.java with 90% similarity]
yang/yang-model-export/src/test/java/org/opendaylight/yangtools/yang/model/export/test/Bug2444Test.java [new file with mode: 0644]
yang/yang-model-export/src/test/java/org/opendaylight/yangtools/yang/model/export/test/SchemaContextEmitterTest.java
yang/yang-model-export/src/test/java/org/opendaylight/yangtools/yang/model/export/test/YinExportTestUtils.java [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yang/action.yang [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yang/anydata.yang [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yang/binary-spec.yang [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yang/default.yang [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yang/identities.yang [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yang/import-yang1.yang [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yang/import.yang [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yang/leafref-yang1.yang [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yang/leafref.yang [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yang/modifier-yang1.yang [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yang/modifier.yang [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yang/must-yang1.yang [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yang/must.yang [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yang/notification.yang [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yang/unique.yang [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yin/action@1970-01-01.yin [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yin/anydata@1970-01-01.yin [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yin/binary-spec@1970-01-01.yin [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yin/default@1970-01-01.yin [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yin/identities@1970-01-01.yin [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yin/import-yang1@1970-01-01.yin [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yin/import@1970-01-01.yin [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yin/leafref-yang1@1970-01-01.yin [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yin/leafref@1970-01-01.yin [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yin/modifier-yang1@1970-01-01.yin [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yin/modifier@1970-01-01.yin [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yin/must-yang1@1970-01-01.yin [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yin/must@1970-01-01.yin [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yin/notification@1970-01-01.yin [new file with mode: 0644]
yang/yang-model-export/src/test/resources/bugs/bug2444/yin/unique@1970-01-01.yin [new file with mode: 0644]
yang/yang-model-export/src/test/resources/schema-context-emitter-test/foo.yin

index 9df4a6db7f33e283bb3ce0de5e8e97941ea9fd6e..96a18596daf6a40f5c13a2b4221a4ad15a9cae90 100644 (file)
@@ -13,6 +13,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.primitives.UnsignedInteger;
 import java.net.URI;
+import java.util.Collection;
 import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
@@ -24,6 +25,9 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.NotThreadSafe;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.YangVersion;
+import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
+import org.opendaylight.yangtools.yang.model.api.AnyDataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
@@ -45,6 +49,7 @@ import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
 import org.opendaylight.yangtools.yang.model.api.MustDefinition;
 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+import org.opendaylight.yangtools.yang.model.api.OperationDefinition;
 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@@ -52,6 +57,7 @@ import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.Status;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.UniqueConstraint;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.UsesNode;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
@@ -70,6 +76,7 @@ import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefi
 import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
+import org.opendaylight.yangtools.yang.model.api.type.ModifierKind;
 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
@@ -81,26 +88,31 @@ import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
 @NotThreadSafe
 class SchemaContextEmitter {
 
-    private final Rfc6020ModuleWriter writer;
+    private final YangModuleWriter writer;
     private final boolean emitInstantiated;
     private final boolean emitUses;
     private final Map<QName, StatementDefinition> extensions;
+    private final YangVersion yangVersion;
 
-    SchemaContextEmitter(final Rfc6020ModuleWriter writer, final Map<QName, StatementDefinition> extensions) {
-        this(writer, extensions,false, true);
+    SchemaContextEmitter(final YangModuleWriter writer, final Map<QName, StatementDefinition> extensions,
+            final YangVersion yangVersion) {
+        this(writer, extensions, yangVersion, false, true);
     }
 
-    SchemaContextEmitter(final Rfc6020ModuleWriter writer, final Map<QName, StatementDefinition> extensions, final boolean emitInstantiated, final boolean emitUses) {
+    SchemaContextEmitter(final YangModuleWriter writer, final Map<QName, StatementDefinition> extensions,
+            final YangVersion yangVersion, final boolean emitInstantiated, final boolean emitUses) {
         this.writer = Preconditions.checkNotNull(writer);
         this.emitInstantiated = emitInstantiated;
         this.emitUses = emitUses;
         this.extensions = Preconditions.checkNotNull(extensions);
+        this.yangVersion = yangVersion;
     }
 
-    static void writeToStatementWriter(final Module module, final SchemaContext ctx, final StatementTextWriter statementWriter) {
-        final Rfc6020ModuleWriter yangSchemaWriter = SchemaToStatementWriterAdaptor.from(statementWriter);
+    static void writeToStatementWriter(final Module module, final SchemaContext ctx,
+            final StatementTextWriter statementWriter) {
+        final YangModuleWriter yangSchemaWriter = SchemaToStatementWriterAdaptor.from(statementWriter);
         final Map<QName, StatementDefinition> extensions = ExtensionStatement.mapFrom(ctx.getExtensions());
-        new SchemaContextEmitter(yangSchemaWriter,extensions).emitModule(module);
+        new SchemaContextEmitter(yangSchemaWriter, extensions, YangVersion.parse(module.getYangVersion()).orElse(null)).emitModule(module);
     }
 
     void emitModule(final Module input) {
@@ -141,9 +153,8 @@ class SchemaContextEmitter {
     }
 
     private void emitMetaNodes(final Module input) {
-
-        emitOrganizationNode(input.getOrganization()); // FIXME: BUG-2444: Optional
-        emitContact(input.getContact()); // FIXME: BUG-2444: Optional
+        emitOrganizationNode(input.getOrganization());
+        emitContact(input.getContact());
         emitDescriptionNode(input.getDescription());
         emitReferenceNode(input.getReference());
     }
@@ -177,6 +188,9 @@ class SchemaContextEmitter {
         for (final IdentitySchemaNode identity : input.getIdentities()) {
             emitIdentity(identity);
         }
+        for (final Deviation deviation : input.getDeviations()) {
+            emitDeviation(deviation);
+        }
 
         emitDataNodeContainer(input);
 
@@ -186,13 +200,8 @@ class SchemaContextEmitter {
         for (final RpcDefinition rpc : input.getRpcs()) {
             emitRpc(rpc);
         }
-        for (final NotificationDefinition notification : input.getNotifications()) {
-            emitNotificationNode(notification);
-        }
-        for (final Deviation deviation : input.getDeviations()) {
-            emitDeviation(deviation);
-        }
 
+        emitNotifications(input.getNotifications());
     }
 
     private void emitDataNodeContainer(final DataNodeContainer input) {
@@ -228,6 +237,8 @@ class SchemaContextEmitter {
             emitChoice((ChoiceSchemaNode) child);
         } else if (child instanceof AnyXmlSchemaNode) {
             emitAnyxml((AnyXmlSchemaNode) child);
+        } else if (child instanceof AnyDataSchemaNode) {
+            emitAnydata((AnyDataSchemaNode) child);
         } else {
             throw new UnsupportedOperationException("Not supported DataSchemaNode type " + child.getClass());
         }
@@ -240,6 +251,8 @@ class SchemaContextEmitter {
 
     private void emitImport(final ModuleImport importNode) {
         writer.startImportNode(importNode.getModuleName());
+        emitDescriptionNode(importNode.getDescription());
+        emitReferenceNode(importNode.getReference());
         emitPrefixNode(importNode.getPrefix());
         emitRevisionDateNode(importNode.getRevision());
         writer.endNode();
@@ -287,15 +300,17 @@ class SchemaContextEmitter {
     }
 
     private void emitOrganizationNode(final String input) {
-        writer.startOrganizationNode(input);
-        writer.endNode();
-
+        if (!Strings.isNullOrEmpty(input)) {
+            writer.startOrganizationNode(input);
+            writer.endNode();
+        }
     }
 
     private void emitContact(final String input) {
-        writer.startContactNode(input);
-        writer.endNode();
-
+        if (!Strings.isNullOrEmpty(input)) {
+            writer.startContactNode(input);
+            writer.endNode();
+        }
     }
 
     private void emitDescriptionNode(@Nullable final String input) {
@@ -364,20 +379,22 @@ class SchemaContextEmitter {
 
     private void emitIdentity(final IdentitySchemaNode identity) {
         writer.startIdentityNode(identity.getQName());
-        if (identity.getBaseIdentity() != null) {
-            emitBase(identity.getBaseIdentity().getQName());
-        }
+        emitBaseIdentities(identity.getBaseIdentities());
         emitStatusNode(identity.getStatus());
         emitDescriptionNode(identity.getDescription());
         emitReferenceNode(identity.getReference());
         writer.endNode();
+    }
 
+    private void emitBaseIdentities(final Set<IdentitySchemaNode> identities) {
+        for (final IdentitySchemaNode identitySchemaNode : identities) {
+            emitBase(identitySchemaNode.getQName());
+        }
     }
 
     private void emitBase(final QName qName) {
         writer.startBaseNode(qName);
         writer.endNode();
-
     }
 
     private void emitFeature(final FeatureDefinition definition) {
@@ -461,8 +478,7 @@ class SchemaContextEmitter {
         } else if (typeDef instanceof UnionTypeDefinition) {
             emitUnionSpecification((UnionTypeDefinition) typeDef);
         } else if (typeDef instanceof BinaryTypeDefinition) {
-            // FIXME: BUG-2444:  Is this realy NOOP?
-            // should at least support length statement
+            emitLength(((BinaryTypeDefinition) typeDef).getLengthConstraints());
         } else if (typeDef instanceof BooleanTypeDefinition || typeDef instanceof EmptyTypeDefinition) {
             // NOOP
         } else {
@@ -583,11 +599,23 @@ class SchemaContextEmitter {
         // FIXME: BUG-2444: Optional
         emitErrorAppTagNode(pattern.getErrorAppTag());
         emitDescriptionNode(pattern.getDescription());
-        // FIXME: BUG-2444: Optional
-        emitReferenceNode(pattern.getReference());
+        emitModifier(pattern.getModifier());
         writer.endNode();
     }
 
+    private void emitModifier(final ModifierKind modifier) {
+        if(modifier != null) {
+            writer.startModifierNode(modifier);
+            writer.endNode();
+        }
+    }
+
+    private void emitDefaultNodes(final Collection<String> defaults) {
+        for (final String defaultValue : defaults) {
+            emitDefaultNode(defaultValue);
+        }
+    }
+
     private void emitDefaultNode(@Nullable final Object object) {
         if (object != null) {
             writer.startDefaultNode(object.toString());
@@ -612,8 +640,9 @@ class SchemaContextEmitter {
 
     private void emitLeafrefSpecification(final LeafrefTypeDefinition typeDefinition) {
         emitPathNode(typeDefinition.getPathStatement());
-        // FIXME: BUG-2444: requireInstanceNode /Optional removed with (RFC6020 - Errata ID 2949)
-        // Added in Yang 1.1
+        if (YangVersion.VERSION_1_1 == yangVersion) {
+            emitRequireInstanceNode(typeDefinition.requireInstance());
+        }
     }
 
     private void emitPathNode(final RevisionAwareXPath revisionAwareXPath) {
@@ -631,7 +660,7 @@ class SchemaContextEmitter {
     }
 
     private void emitIdentityrefSpecification(final IdentityrefTypeDefinition typeDefinition) {
-        emitBase(typeDefinition.getIdentity().getQName());
+        emitBaseIdentities(typeDefinition.getIdentities());
     }
 
     private void emitUnionSpecification(final UnionTypeDefinition typeDefinition) {
@@ -753,6 +782,8 @@ class SchemaContextEmitter {
         emitDocumentedNode(grouping);
         emitDataNodeContainer(grouping);
         emitUnknownStatementNodes(grouping.getUnknownSchemaNodes());
+        emitNotifications(grouping.getNotifications());
+        emitActions(grouping.getActions());
         writer.endNode();
 
     }
@@ -770,6 +801,8 @@ class SchemaContextEmitter {
         emitDocumentedNode(child);
         emitDataNodeContainer(child);
         emitUnknownStatementNodes(child.getUnknownSchemaNodes());
+        emitNotifications(child.getNotifications());
+        emitActions(child.getActions());
         writer.endNode();
 
     }
@@ -779,7 +812,6 @@ class SchemaContextEmitter {
         for (final MustDefinition mustCondition : constraints.getMustConstraints()) {
             emitMust(mustCondition);
         }
-
     }
 
     private void emitLeaf(final LeafSchemaNode child) {
@@ -804,10 +836,11 @@ class SchemaContextEmitter {
         emitWhen(child.getConstraints().getWhenCondition());
         // FIXME: BUG-2444: *(ifFeatureNode )
         emitTypeNode(child.getPath(), child.getType());
+        emitUnitsNode(child.getType().getUnits());
         // FIXME: BUG-2444: unitsNode /Optional
         emitMustNodes(child.getConstraints().getMustConstraints());
         emitConfigNode(child.isConfiguration());
-
+        emitDefaultNodes(child.getDefaults());
         emitMinElementsNode(child.getConstraints().getMinElements());
         emitMaxElementsNode(child.getConstraints().getMaxElements());
         emitOrderedBy(child.isUserOrdered());
@@ -824,7 +857,7 @@ class SchemaContextEmitter {
         // FIXME: BUG-2444: *(ifFeatureNode )
         emitMustNodes(child.getConstraints().getMustConstraints());
         emitKey(child.getKeyDefinition());
-        // FIXME: BUG-2444: *(uniqueNode )
+        emitUniqueConstraints(child.getUniqueConstraints());
         emitConfigNode(child.isConfiguration());
         emitMinElementsNode(child.getConstraints().getMinElements());
         emitMaxElementsNode(child.getConstraints().getMaxElements());
@@ -832,6 +865,8 @@ class SchemaContextEmitter {
         emitDocumentedNode(child);
         emitDataNodeContainer(child);
         emitUnknownStatementNodes(child.getUnknownSchemaNodes());
+        emitNotifications(child.getNotifications());
+        emitActions(child.getActions());
         writer.endNode();
 
     }
@@ -849,10 +884,15 @@ class SchemaContextEmitter {
         }
     }
 
-    @SuppressWarnings("unused")
-    private void emitUnique(final String input) {
-        // FIXME: BUG-2444: writer.startUniqueNode(uniqueArgStr)); Nodeend
+    private void emitUniqueConstraints(final Collection<UniqueConstraint> uniqueConstraints) {
+        for (final UniqueConstraint uniqueConstraint : uniqueConstraints) {
+            emitUnique(uniqueConstraint);
+        }
+    }
 
+    private void emitUnique(final UniqueConstraint uniqueConstraint) {
+        writer.startUniqueNode(uniqueConstraint);
+        writer.endNode();
     }
 
     private void emitChoice(final ChoiceSchemaNode choice) {
@@ -885,18 +925,26 @@ class SchemaContextEmitter {
 
     }
 
-    private void emitAnyxml(final AnyXmlSchemaNode child) {
-        writer.startAnyxmlNode(child.getQName());
+    private void emitAnyxml(final AnyXmlSchemaNode anyxml) {
+        writer.startAnyxmlNode(anyxml.getQName());
+        emitBodyOfDataSchemaNode(anyxml);
+        writer.endNode();
+    }
 
-        emitWhen(child.getConstraints().getWhenCondition());
-        // FIXME: BUG-2444: *(ifFeatureNode )
-        emitMustNodes(child.getConstraints().getMustConstraints());
-        emitConfigNode(child.isConfiguration());
-        emitMandatoryNode(child.getConstraints().isMandatory());
-        emitDocumentedNode(child);
-        emitUnknownStatementNodes(child.getUnknownSchemaNodes());
+    private void emitAnydata(final AnyDataSchemaNode anydata) {
+        writer.startAnydataNode(anydata.getQName());
+        emitBodyOfDataSchemaNode(anydata);
         writer.endNode();
+    }
 
+    private void emitBodyOfDataSchemaNode(final DataSchemaNode dataSchemaNode) {
+        emitWhen(dataSchemaNode.getConstraints().getWhenCondition());
+        // FIXME: BUG-2444: *(ifFeatureNode )
+        emitMustNodes(dataSchemaNode.getConstraints().getMustConstraints());
+        emitConfigNode(dataSchemaNode.isConfiguration());
+        emitMandatoryNode(dataSchemaNode.getConstraints().isMandatory());
+        emitDocumentedNode(dataSchemaNode);
+        emitUnknownStatementNodes(dataSchemaNode.getUnknownSchemaNodes());
     }
 
     private void emitUsesNode(final UsesNode usesNode) {
@@ -1088,6 +1136,8 @@ class SchemaContextEmitter {
             }
         }
         emitUnknownStatementNodes(augmentation.getUnknownSchemaNodes());
+        emitNotifications(augmentation.getNotifications());
+        emitActions(augmentation.getActions());
         writer.endNode();
     }
 
@@ -1129,6 +1179,11 @@ class SchemaContextEmitter {
 
     private void emitRpc(final RpcDefinition rpc) {
         writer.startRpcNode(rpc.getQName());
+        emitOperationBody(rpc);
+        writer.endNode();
+    }
+
+    private void emitOperationBody(final OperationDefinition rpc) {
         // FIXME: BUG-2444: *(ifFeatureNode )
         emitStatusNode(rpc.getStatus());
         emitDescriptionNode(rpc.getDescription());
@@ -1143,13 +1198,24 @@ class SchemaContextEmitter {
         emitInput(rpc.getInput());
         emitOutput(rpc.getOutput());
         emitUnknownStatementNodes(rpc.getUnknownSchemaNodes());
-        writer.endNode();
+    }
 
+    private void emitActions(final Set<ActionDefinition> actions) {
+        for (final ActionDefinition actionDefinition : actions) {
+            emitAction(actionDefinition);
+        }
+    }
+
+    private void emitAction(final ActionDefinition action) {
+        writer.startActionNode(action.getQName());
+        emitOperationBody(action);
+        writer.endNode();
     }
 
     private void emitInput(@Nonnull final ContainerSchemaNode input) {
         if (isExplicitStatement(input)) {
             writer.startInputNode();
+            emitConstraints(input.getConstraints());
             emitDataNodeContainer(input);
             emitUnknownStatementNodes(input.getUnknownSchemaNodes());
             writer.endNode();
@@ -1160,6 +1226,7 @@ class SchemaContextEmitter {
     private void emitOutput(@Nonnull final ContainerSchemaNode output) {
         if (isExplicitStatement(output)) {
             writer.startOutputNode();
+            emitConstraints(output.getConstraints());
             emitDataNodeContainer(output);
             emitUnknownStatementNodes(output.getUnknownSchemaNodes());
             writer.endNode();
@@ -1172,9 +1239,16 @@ class SchemaContextEmitter {
                 && ((EffectiveStatement<?, ?>) node).getDeclared().getStatementSource() == StatementSource.DECLARATION;
     }
 
+    private void emitNotifications(final Set<NotificationDefinition> notifications) {
+        for (final NotificationDefinition notification : notifications) {
+            emitNotificationNode(notification);
+        }
+    }
+
     private void emitNotificationNode(final NotificationDefinition notification) {
         writer.startNotificationNode(notification.getQName());
         // FIXME: BUG-2444: *(ifFeatureNode )
+        emitConstraints(notification.getConstraints());
         emitDocumentedNode(notification);
         emitDataNodeContainer(notification);
         emitUnknownStatementNodes(notification.getUnknownSchemaNodes());
index a73f07d375929fa647435cd94764bb2b4fa5f694..20a7242cff19326435a37bdf654a867b17ea9380 100644 (file)
@@ -9,8 +9,10 @@ package org.opendaylight.yangtools.yang.model.export;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
 import com.google.common.primitives.UnsignedInteger;
 import java.net.URI;
+import java.util.Collection;
 import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
@@ -18,14 +20,17 @@ import javax.annotation.concurrent.NotThreadSafe;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
-import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.UniqueConstraint;
+import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Relative;
+import org.opendaylight.yangtools.yang.model.api.type.ModifierKind;
 
 @Beta
 @NotThreadSafe
-final class SchemaToStatementWriterAdaptor implements Rfc6020ModuleWriter {
+final class SchemaToStatementWriterAdaptor implements YangModuleWriter {
 
     private final StatementTextWriter writer;
 
@@ -33,7 +38,7 @@ final class SchemaToStatementWriterAdaptor implements Rfc6020ModuleWriter {
         this.writer = Preconditions.checkNotNull(writer);
     }
 
-    public static Rfc6020ModuleWriter from(final StatementTextWriter writer) {
+    public static YangModuleWriter from(final StatementTextWriter writer) {
         return new SchemaToStatementWriterAdaptor(writer);
     }
 
@@ -406,4 +411,39 @@ final class SchemaToStatementWriterAdaptor implements Rfc6020ModuleWriter {
         writer.startStatement(YangStmtMapping.WHEN);
         writer.writeArgument(revisionAwareXPath);
     }
+
+    @Override
+    public void startAnydataNode(final QName qName) {
+        writer.startStatement(YangStmtMapping.ANYDATA);
+        writer.writeArgument(qName);
+    }
+
+    @Override
+    public void startActionNode(final QName qName) {
+        writer.startStatement(YangStmtMapping.ACTION);
+        writer.writeArgument(qName);
+    }
+
+    @Override
+    public void startModifierNode(final ModifierKind modifier) {
+        writer.startStatement(YangStmtMapping.MODIFIER);
+        writer.writeArgument(modifier.getKeyword());
+    }
+
+    @Override
+    public void startUniqueNode(final UniqueConstraint uniqueConstraint) {
+        writer.startStatement(YangStmtMapping.UNIQUE);
+        final StringBuilder uniqueStr = new StringBuilder();
+        final Collection<Relative> tag = uniqueConstraint.getTag();
+
+        final Iterator<Relative> iter = tag.iterator();
+        while (iter.hasNext()) {
+            uniqueStr.append(
+                    String.join("/", Iterables.transform(iter.next().getPathFromRoot(), qn -> qn.getLocalName())));
+            if (iter.hasNext()) {
+                uniqueStr.append(' ');
+            }
+        }
+        writer.writeArgument(uniqueStr.toString());
+    }
 }
similarity index 90%
rename from yang/yang-model-export/src/main/java/org/opendaylight/yangtools/yang/model/export/Rfc6020ModuleWriter.java
rename to yang/yang-model-export/src/main/java/org/opendaylight/yangtools/yang/model/export/YangModuleWriter.java
index 9c1444ae8c9532dbd64e1c45db30e0c823ae5f17..64305aa76926608ecb5df05f1d227a7ac3860ba1 100644 (file)
@@ -15,9 +15,11 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.UniqueConstraint;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.ModifierKind;
 
-interface Rfc6020ModuleWriter {
+interface YangModuleWriter {
 
     void endNode();
 
@@ -141,4 +143,12 @@ interface Rfc6020ModuleWriter {
 
     void startWhenNode(RevisionAwareXPath revisionAwareXPath);
 
+    void startAnydataNode(QName qName);
+
+    void startActionNode(QName qName);
+
+    void startModifierNode(ModifierKind modifier);
+
+    void startUniqueNode(UniqueConstraint uniqueConstraint);
+
 }
diff --git a/yang/yang-model-export/src/test/java/org/opendaylight/yangtools/yang/model/export/test/Bug2444Test.java b/yang/yang-model-export/src/test/java/org/opendaylight/yangtools/yang/model/export/test/Bug2444Test.java
new file mode 100644 (file)
index 0000000..f629b96
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017 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.yangtools.yang.model.export.test;
+
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import org.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.ElementNameAndAttributeQualifier;
+import org.custommonkey.xmlunit.XMLAssert;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.export.YinExportUtils;
+import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+public class Bug2444Test {
+    @Test
+    public void test() throws Exception {
+        final SchemaContext schema = YangParserTestUtils.parseYangSources("/bugs/bug2444/yang");
+        assertNotNull(schema);
+
+        final File outDir = new File("target/bug2444-export");
+        outDir.mkdirs();
+
+        for (final Module module : schema.getModules()) {
+            exportModule(schema, module, outDir);
+
+            final OutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+            final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(byteArrayOutputStream);
+            try {
+                YinExportUtils.writeModuleToOutputStream(schema, module, bufferedOutputStream);
+                final String output = byteArrayOutputStream.toString();
+                assertNotNull(output);
+                assertNotEquals(0, output.length());
+
+                final Document doc = YinExportTestUtils.loadDocument(String.format("/bugs/bug2444/yin/%s@%s.yin",
+                        module.getName(), SimpleDateFormatUtil.getRevisionFormat().format(module.getRevision())));
+                assertXMLEquals(doc, output);
+            } finally {
+                byteArrayOutputStream.close();
+                bufferedOutputStream.close();
+            }
+        }
+    }
+
+    private static void assertXMLEquals(final Document expectedXMLDoc, final String output)
+            throws SAXException, IOException {
+        final String expected = YinExportTestUtils.toString(expectedXMLDoc.getDocumentElement());
+
+        XMLUnit.setIgnoreWhitespace(true);
+        XMLUnit.setNormalize(true);
+        XMLUnit.setNormalizeWhitespace(true);
+
+        final Diff diff = new Diff(expected, output);
+        diff.overrideElementQualifier(new ElementNameAndAttributeQualifier());
+        XMLAssert.assertXMLEqual(diff, true);
+    }
+
+    private static File exportModule(final SchemaContext schemaContext, final Module module, final File outDir)
+            throws Exception {
+        final File outFile = new File(outDir, YinExportUtils.wellFormedYinName(module.getName(), module.getRevision()));
+        try (OutputStream output = new FileOutputStream(outFile)) {
+            YinExportUtils.writeModuleToOutputStream(schemaContext, module, output);
+        }
+        return outFile;
+    }
+}
index d9707d6c18df9d65f95916114a083f7f6189e2c6..1b421f793f4d754065d361cffcf2608eca843e64 100644 (file)
@@ -12,35 +12,23 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 
-import com.google.common.base.Preconditions;
 import java.io.BufferedOutputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.OutputStream;
-import java.io.StringWriter;
 import java.net.URISyntaxException;
 import javax.xml.stream.XMLStreamException;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.TransformerFactoryConfigurationError;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
 import org.custommonkey.xmlunit.Diff;
 import org.custommonkey.xmlunit.ElementNameAndAttributeQualifier;
 import org.custommonkey.xmlunit.XMLAssert;
 import org.custommonkey.xmlunit.XMLUnit;
 import org.junit.Test;
-import org.opendaylight.yangtools.util.xml.UntrustedXML;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.export.YinExportUtils;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
 import org.w3c.dom.Document;
-import org.w3c.dom.Node;
 import org.xml.sax.SAXException;
 
 public class SchemaContextEmitterTest {
@@ -55,7 +43,7 @@ public class SchemaContextEmitterTest {
         final OutputStream byteArrayOutputStream = new ByteArrayOutputStream();
         final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(byteArrayOutputStream);
 
-        for (Module module : schemaContext.getModules()) {
+        for (final Module module : schemaContext.getModules()) {
             YinExportUtils.writeModuleToOutputStream(schemaContext, module, bufferedOutputStream);
         }
 
@@ -63,8 +51,8 @@ public class SchemaContextEmitterTest {
         assertNotNull(output);
         assertNotEquals(0, output.length());
 
-        final Document doc = loadDocument("/schema-context-emitter-test/foo.yin");
-        final String expected = toString(doc.getDocumentElement());
+        final Document doc = YinExportTestUtils.loadDocument("/schema-context-emitter-test/foo.yin");
+        final String expected = YinExportTestUtils.toString(doc.getDocumentElement());
 
         XMLUnit.setIgnoreWhitespace(true);
         XMLUnit.setNormalize(true);
@@ -73,33 +61,4 @@ public class SchemaContextEmitterTest {
         diff.overrideElementQualifier(new ElementNameAndAttributeQualifier());
         XMLAssert.assertXMLEqual(diff, true);
     }
-
-    private static Document loadDocument(final String xmlPath) throws IOException, SAXException {
-        final InputStream resourceAsStream = SchemaContextEmitterTest.class.getResourceAsStream(xmlPath);
-        final Document currentConfigElement = readXmlToDocument(resourceAsStream);
-        Preconditions.checkNotNull(currentConfigElement);
-        return currentConfigElement;
-    }
-
-    private static Document readXmlToDocument(final InputStream xmlContent) throws IOException, SAXException {
-        final Document doc = UntrustedXML.newDocumentBuilder().parse(xmlContent);
-        doc.getDocumentElement().normalize();
-        return doc;
-    }
-
-    private static String toString(final Node xml) {
-        try {
-            final Transformer transformer = TransformerFactory.newInstance().newTransformer();
-            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
-            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
-
-            final StreamResult result = new StreamResult(new StringWriter());
-            final DOMSource source = new DOMSource(xml);
-            transformer.transform(source, result);
-
-            return result.getWriter().toString();
-        } catch (IllegalArgumentException | TransformerFactoryConfigurationError | TransformerException e) {
-            throw new RuntimeException("Unable to serialize xml element " + xml, e);
-        }
-    }
 }
diff --git a/yang/yang-model-export/src/test/java/org/opendaylight/yangtools/yang/model/export/test/YinExportTestUtils.java b/yang/yang-model-export/src/test/java/org/opendaylight/yangtools/yang/model/export/test/YinExportTestUtils.java
new file mode 100644 (file)
index 0000000..6141bcf
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017 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.yangtools.yang.model.export.test;
+
+import com.google.common.base.Preconditions;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import org.opendaylight.yangtools.util.xml.UntrustedXML;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+public class YinExportTestUtils {
+
+    private YinExportTestUtils() {
+        throw new UnsupportedOperationException("Utility class");
+    }
+
+    static Document loadDocument(final String xmlPath) throws IOException, SAXException {
+        final InputStream resourceAsStream = SchemaContextEmitterTest.class.getResourceAsStream(xmlPath);
+        final Document currentConfigElement = readXmlToDocument(resourceAsStream);
+        Preconditions.checkNotNull(currentConfigElement);
+        return currentConfigElement;
+    }
+
+    static Document readXmlToDocument(final InputStream xmlContent) throws IOException, SAXException {
+        final Document doc = UntrustedXML.newDocumentBuilder().parse(xmlContent);
+        doc.getDocumentElement().normalize();
+        return doc;
+    }
+
+    static String toString(final Node xml) {
+        try {
+            final Transformer transformer = TransformerFactory.newInstance().newTransformer();
+            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
+
+            final StreamResult result = new StreamResult(new StringWriter());
+            final DOMSource source = new DOMSource(xml);
+            transformer.transform(source, result);
+
+            return result.getWriter().toString();
+        } catch (IllegalArgumentException | TransformerFactoryConfigurationError | TransformerException e) {
+            throw new RuntimeException("Unable to serialize xml element " + xml, e);
+        }
+    }
+}
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/action.yang b/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/action.yang
new file mode 100644 (file)
index 0000000..92a8a92
--- /dev/null
@@ -0,0 +1,34 @@
+module action {
+    namespace action;
+    prefix ac;
+    yang-version 1.1;
+
+    container root {
+        action a {
+            if-feature "my-feature-1 or my-feature-2";
+            status deprecated;
+            description "decs";
+            reference "ref";
+            typedef my-type {
+                type string;
+            }
+            grouping my-grp {
+                container con-in-grp {
+                }
+            }
+            input {
+                container i {
+                }
+            }
+            output {
+                container o {
+                }
+            }
+            ac:my-ext "arg-val";
+        }
+    }
+    
+    extension my-ext {
+        argument my-arg;
+    }
+}
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/anydata.yang b/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/anydata.yang
new file mode 100644 (file)
index 0000000..f9d8708
--- /dev/null
@@ -0,0 +1,21 @@
+module anydata {
+    namespace anydata;
+    prefix ad;
+    yang-version 1.1;
+
+    anydata my-anydata {
+        when "1!=0";
+        must "1=1";
+        config true;
+        mandatory true;
+        if-feature "my-feature-1 or my-feature-2";
+        status deprecated;
+        description "decs";
+        reference "ref";
+        ad:my-ext "arg-val";
+    }
+
+    extension my-ext {
+        argument my-arg;
+    }
+}
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/binary-spec.yang b/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/binary-spec.yang
new file mode 100644 (file)
index 0000000..3aba0a1
--- /dev/null
@@ -0,0 +1,15 @@
+module binary-spec {
+    namespace "binary-spec";
+    prefix bin;
+
+    leaf bin-leaf {
+        type binary {
+            length "1..99";
+        }
+    }
+
+    leaf bin-leaf-2 {
+        type binary {
+        }
+    }
+}
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/default.yang b/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/default.yang
new file mode 100644 (file)
index 0000000..375771a
--- /dev/null
@@ -0,0 +1,16 @@
+module default {
+    namespace default;
+    prefix def;
+    yang-version 1.1;
+
+    leaf-list my-leaflist-1 {
+        type string;
+        default "def-val-1";
+        default "def-val-2";
+        default "def-val-3";
+    }
+
+    leaf-list my-leaflist-2 {
+        type string;
+    }
+}
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/identities.yang b/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/identities.yang
new file mode 100644 (file)
index 0000000..0fd4882
--- /dev/null
@@ -0,0 +1,29 @@
+module identities {
+    namespace identities;
+    prefix iden;
+    yang-version 1.1;
+
+    identity id-a;
+    identity id-b;
+    identity id-c;
+
+    identity derived-id {
+        base id-a;
+        base id-b;
+        base id-c;
+    }
+
+    leaf idref-leaf {
+        type identityref {
+            base id-a;
+            base id-b;
+            base id-c;
+        }
+    }
+
+    leaf idref-leaf-2 {
+        type identityref {
+            base derived-id;
+        }
+    }
+}
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/import-yang1.yang b/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/import-yang1.yang
new file mode 100644 (file)
index 0000000..c7f76ae
--- /dev/null
@@ -0,0 +1,7 @@
+module import-yang1 {
+    namespace "import-yang1";
+    prefix iy1;
+    yang-version 1;
+
+    import action { prefix ac; revision-date 1970-01-01; }
+}
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/import.yang b/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/import.yang
new file mode 100644 (file)
index 0000000..db1f786
--- /dev/null
@@ -0,0 +1,7 @@
+module import {
+    namespace "import";
+    prefix i;
+    yang-version 1.1;
+
+    import action { description "txt"; reference "ref"; prefix ac; revision-date 1970-01-01; }
+}
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/leafref-yang1.yang b/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/leafref-yang1.yang
new file mode 100644 (file)
index 0000000..8831696
--- /dev/null
@@ -0,0 +1,15 @@
+module leafref-yang1 {
+    namespace leafref-yang1;
+    prefix lr;
+    yang-version 1;
+
+    leaf my-leafref-3 {
+        type leafref {
+            path "/target";
+        }
+    }
+
+    leaf target {
+        type string;
+    }
+}
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/leafref.yang b/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/leafref.yang
new file mode 100644 (file)
index 0000000..6ab20b1
--- /dev/null
@@ -0,0 +1,29 @@
+module leafref {
+    namespace leafref;
+    prefix lr;
+    yang-version 1.1;
+
+    leaf my-leafref {
+        type leafref {
+            path "/target";
+            require-instance false;
+        }
+    }
+
+    leaf my-leafref-2 {
+        type leafref {
+            path "/target";
+            require-instance true;
+        }
+    }
+
+    leaf my-leafref-3 {
+        type leafref {
+            path "/target";
+        }
+    }
+
+    leaf target {
+        type string;
+    }
+}
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/modifier-yang1.yang b/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/modifier-yang1.yang
new file mode 100644 (file)
index 0000000..1cfae57
--- /dev/null
@@ -0,0 +1,11 @@
+module modifier-yang1 {
+    namespace modifier-yang1;
+    prefix my1;
+    yang-version 1;
+
+    leaf my-leaf {
+        type string {
+            pattern ".*";
+        }
+    }
+}
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/modifier.yang b/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/modifier.yang
new file mode 100644 (file)
index 0000000..b3002dd
--- /dev/null
@@ -0,0 +1,13 @@
+module modifier {
+    namespace modifier;
+    prefix m;
+    yang-version 1.1;
+
+    leaf my-leaf {
+        type string {
+            pattern ".*" {
+                modifier invert-match;
+            }
+        }
+    }
+}
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/must-yang1.yang b/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/must-yang1.yang
new file mode 100644 (file)
index 0000000..015a342
--- /dev/null
@@ -0,0 +1,15 @@
+module must-yang1 {
+    namespace "must-yang1";
+    prefix muy1;
+    yang-version 1;
+
+    notification n {
+    }
+
+    rpc r {
+        input {
+        }
+        output {
+        }
+    }
+}
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/must.yang b/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/must.yang
new file mode 100644 (file)
index 0000000..ec66c42
--- /dev/null
@@ -0,0 +1,29 @@
+module must {
+    namespace "must";
+    prefix mu;
+    yang-version 1.1;
+
+    notification n {
+        must "1!=0";
+    }
+
+    rpc r {
+        input {
+            must "1!=0";
+        }
+        output {
+            must "1!=0";
+        }
+    }
+
+    container root {
+        action a {
+            input {
+                must "1!=0";
+            }
+            output {
+                must "1!=0";
+            }
+        }
+    }
+}
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/notification.yang b/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/notification.yang
new file mode 100644 (file)
index 0000000..647aa71
--- /dev/null
@@ -0,0 +1,35 @@
+module notification {
+    namespace "notification";
+    prefix n;
+    yang-version 1.1;
+
+    notification n1 {
+        container c {
+        }
+    }
+
+    container r {
+        notification n2 {
+        }
+    }
+
+    list l {
+        key "id";
+        leaf id {
+            type int16;
+        }
+        notification n3 {
+        }
+    }
+
+    augment "/r" {
+        uses grp;
+        notification n4 {
+        }
+    }
+
+    grouping grp {
+        notification n5 {
+        }
+    }
+}
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/unique.yang b/yang/yang-model-export/src/test/resources/bugs/bug2444/yang/unique.yang
new file mode 100644 (file)
index 0000000..01ba622
--- /dev/null
@@ -0,0 +1,29 @@
+module unique {
+    namespace unique;
+    prefix u;
+
+    list l {
+        key id;
+        leaf id {
+            type string;
+        }
+
+        unique "c1/c2/my-leaf-2";
+        unique "my-container/my-leaf-3";
+        leaf my-leaf-1 {
+            type string;
+        }
+        container c1 {
+            container c2 {
+                leaf my-leaf-2 {
+                    type string;
+                }
+            }
+        }
+        container my-container {
+            leaf my-leaf-3 {
+                type string;
+            }
+        }
+    }
+}
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/action@1970-01-01.yin b/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/action@1970-01-01.yin
new file mode 100644 (file)
index 0000000..134f0cd
--- /dev/null
@@ -0,0 +1,54 @@
+<module xmlns="urn:ietf:params:xml:ns:yang:yin:1" xmlns:ac="action"
+    name="action">
+    <yang-version value="1.1"></yang-version>
+    <namespace uri="action"></namespace>
+    <prefix value="ac"></prefix>
+    <revision date="1970-01-01"></revision>
+    <extension name="my-ext">
+        <argument name="my-arg">
+            <yin-element value="false"></yin-element>
+        </argument>
+        <status value="current"></status>
+    </extension>
+    <container name="root">
+        <presence value="false"></presence>
+        <config value="true"></config>
+        <status value="current"></status>
+        <action name="a">
+            <status value="deprecated"></status>
+            <description>
+                <text>decs</text>
+            </description>
+            <reference>
+                <text>ref</text>
+            </reference>
+            <typedef name="my-type">
+                <type name="string"></type>
+                <status value="current"></status>
+            </typedef>
+            <grouping name="my-grp">
+                <status value="current"></status>
+                <container name="con-in-grp">
+                    <presence value="false"></presence>
+                    <config value="true"></config>
+                    <status value="current"></status>
+                </container>
+            </grouping>
+            <input>
+                <container name="i">
+                    <presence value="false"></presence>
+                    <config value="true"></config>
+                    <status value="current"></status>
+                </container>
+            </input>
+            <output>
+                <container name="o">
+                    <presence value="false"></presence>
+                    <config value="true"></config>
+                    <status value="current"></status>
+                </container>
+            </output>
+            <ac:my-ext ac:my-arg="arg-val"></ac:my-ext>
+        </action>
+    </container>
+</module>
\ No newline at end of file
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/anydata@1970-01-01.yin b/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/anydata@1970-01-01.yin
new file mode 100644 (file)
index 0000000..3b03bfd
--- /dev/null
@@ -0,0 +1,27 @@
+<module xmlns="urn:ietf:params:xml:ns:yang:yin:1" xmlns:ad="anydata"
+    name="anydata">
+    <yang-version value="1.1"></yang-version>
+    <namespace uri="anydata"></namespace>
+    <prefix value="ad"></prefix>
+    <revision date="1970-01-01"></revision>
+    <extension name="my-ext">
+        <argument name="my-arg">
+            <yin-element value="false"></yin-element>
+        </argument>
+        <status value="current"></status>
+    </extension>
+    <anydata name="my-anydata">
+        <when condition="1!=0"></when>
+        <must condition="1=1"></must>
+        <config value="true"></config>
+        <mandatory value="true"></mandatory>
+        <status value="deprecated"></status>
+        <description>
+            <text>decs</text>
+        </description>
+        <reference>
+            <text>ref</text>
+        </reference>
+        <ad:my-ext ad:my-arg="arg-val"></ad:my-ext>
+    </anydata>
+</module>
\ No newline at end of file
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/binary-spec@1970-01-01.yin b/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/binary-spec@1970-01-01.yin
new file mode 100644 (file)
index 0000000..25dcb84
--- /dev/null
@@ -0,0 +1,27 @@
+<module xmlns="urn:ietf:params:xml:ns:yang:yin:1" xmlns:bin="binary-spec"
+    name="binary-spec">
+    <yang-version value="1"></yang-version>
+    <namespace uri="binary-spec"></namespace>
+    <prefix value="bin"></prefix>
+    <revision date="1970-01-01"></revision>
+    <leaf name="bin-leaf">
+        <type name="binary">
+            <length value="1..99">
+                <error-message>
+                    <value>The argument is out of bounds &lt;1, 99&gt;
+                    </value>
+                </error-message>
+                <error-app-tag value="length-out-of-specified-bounds"></error-app-tag>
+            </length>
+        </type>
+        <config value="true"></config>
+        <mandatory value="false"></mandatory>
+        <status value="current"></status>
+    </leaf>
+    <leaf name="bin-leaf-2">
+        <type name="binary"></type>
+        <config value="true"></config>
+        <mandatory value="false"></mandatory>
+        <status value="current"></status>
+    </leaf>
+</module>
\ No newline at end of file
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/default@1970-01-01.yin b/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/default@1970-01-01.yin
new file mode 100644 (file)
index 0000000..4b30a32
--- /dev/null
@@ -0,0 +1,22 @@
+<module xmlns="urn:ietf:params:xml:ns:yang:yin:1" xmlns:def="default"
+    name="default">
+    <yang-version value="1.1"></yang-version>
+    <namespace uri="default"></namespace>
+    <prefix value="def"></prefix>
+    <revision date="1970-01-01"></revision>
+    <leaf-list name="my-leaflist-1">
+        <type name="string"></type>
+        <config value="true"></config>
+        <default value="def-val-1"></default>
+        <default value="def-val-2"></default>
+        <default value="def-val-3"></default>
+        <ordered-by value="system"></ordered-by>
+        <status value="current"></status>
+    </leaf-list>
+    <leaf-list name="my-leaflist-2">
+        <type name="string"></type>
+        <config value="true"></config>
+        <ordered-by value="system"></ordered-by>
+        <status value="current"></status>
+    </leaf-list>
+</module>
\ No newline at end of file
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/identities@1970-01-01.yin b/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/identities@1970-01-01.yin
new file mode 100644 (file)
index 0000000..a590545
--- /dev/null
@@ -0,0 +1,40 @@
+<module xmlns="urn:ietf:params:xml:ns:yang:yin:1" xmlns:iden="identities"
+    name="identities">
+    <yang-version value="1.1"></yang-version>
+    <namespace uri="identities"></namespace>
+    <prefix value="iden"></prefix>
+    <revision date="1970-01-01"></revision>
+    <identity name="id-a">
+        <status value="current"></status>
+    </identity>
+    <identity name="id-b">
+        <status value="current"></status>
+    </identity>
+    <identity name="id-c">
+        <status value="current"></status>
+    </identity>
+    <identity name="derived-id">
+        <base name="id-a"></base>
+        <base name="id-b"></base>
+        <base name="id-c"></base>
+        <status value="current"></status>
+    </identity>
+    <leaf name="idref-leaf">
+        <type name="identityref">
+            <base name="id-a"></base>
+            <base name="id-b"></base>
+            <base name="id-c"></base>
+        </type>
+        <config value="true"></config>
+        <mandatory value="false"></mandatory>
+        <status value="current"></status>
+    </leaf>
+    <leaf name="idref-leaf-2">
+        <type name="identityref">
+            <base name="derived-id"></base>
+        </type>
+        <config value="true"></config>
+        <mandatory value="false"></mandatory>
+        <status value="current"></status>
+    </leaf>
+</module>
\ No newline at end of file
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/import-yang1@1970-01-01.yin b/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/import-yang1@1970-01-01.yin
new file mode 100644 (file)
index 0000000..135dc09
--- /dev/null
@@ -0,0 +1,11 @@
+<module xmlns="urn:ietf:params:xml:ns:yang:yin:1" xmlns:iy1="import-yang1"
+    xmlns:ac="action" name="import-yang1">
+    <yang-version value="1"></yang-version>
+    <namespace uri="import-yang1"></namespace>
+    <prefix value="iy1"></prefix>
+    <import module="action">
+        <prefix value="ac"></prefix>
+        <revision-date date="1970-01-01"></revision-date>
+    </import>
+    <revision date="1970-01-01"></revision>
+</module>
\ No newline at end of file
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/import@1970-01-01.yin b/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/import@1970-01-01.yin
new file mode 100644 (file)
index 0000000..8b6520b
--- /dev/null
@@ -0,0 +1,17 @@
+<module xmlns="urn:ietf:params:xml:ns:yang:yin:1" xmlns:i="import"
+    xmlns:ac="action" name="import">
+    <yang-version value="1.1"></yang-version>
+    <namespace uri="import"></namespace>
+    <prefix value="i"></prefix>
+    <import module="action">
+        <description>
+            <text>txt</text>
+        </description>
+        <reference>
+            <text>ref</text>
+        </reference>
+        <prefix value="ac"></prefix>
+        <revision-date date="1970-01-01"></revision-date>
+    </import>
+    <revision date="1970-01-01"></revision>
+</module>
\ No newline at end of file
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/leafref-yang1@1970-01-01.yin b/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/leafref-yang1@1970-01-01.yin
new file mode 100644 (file)
index 0000000..c04d24d
--- /dev/null
@@ -0,0 +1,21 @@
+<module xmlns="urn:ietf:params:xml:ns:yang:yin:1" xmlns:lr="leafref-yang1"
+    name="leafref-yang1">
+    <yang-version value="1"></yang-version>
+    <namespace uri="leafref-yang1"></namespace>
+    <prefix value="lr"></prefix>
+    <revision date="1970-01-01"></revision>
+    <leaf name="my-leafref-3">
+        <type name="leafref">
+            <path value="/target"></path>
+        </type>
+        <config value="true"></config>
+        <mandatory value="false"></mandatory>
+        <status value="current"></status>
+    </leaf>
+    <leaf name="target">
+        <type name="string"></type>
+        <config value="true"></config>
+        <mandatory value="false"></mandatory>
+        <status value="current"></status>
+    </leaf>
+</module>
\ No newline at end of file
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/leafref@1970-01-01.yin b/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/leafref@1970-01-01.yin
new file mode 100644 (file)
index 0000000..6b46b4f
--- /dev/null
@@ -0,0 +1,40 @@
+<module xmlns="urn:ietf:params:xml:ns:yang:yin:1" xmlns:lr="leafref"
+    name="leafref">
+    <yang-version value="1.1"></yang-version>
+    <namespace uri="leafref"></namespace>
+    <prefix value="lr"></prefix>
+    <revision date="1970-01-01"></revision>
+    <leaf name="my-leafref">
+        <type name="leafref">
+            <path value="/target"></path>
+            <require-instance value="false"></require-instance>
+        </type>
+        <config value="true"></config>
+        <mandatory value="false"></mandatory>
+        <status value="current"></status>
+    </leaf>
+    <leaf name="my-leafref-2">
+        <type name="leafref">
+            <path value="/target"></path>
+            <require-instance value="true"></require-instance>
+        </type>
+        <config value="true"></config>
+        <mandatory value="false"></mandatory>
+        <status value="current"></status>
+    </leaf>
+    <leaf name="my-leafref-3">
+        <type name="leafref">
+            <path value="/target"></path>
+            <require-instance value="false"></require-instance>
+        </type>
+        <config value="true"></config>
+        <mandatory value="false"></mandatory>
+        <status value="current"></status>
+    </leaf>
+    <leaf name="target">
+        <type name="string"></type>
+        <config value="true"></config>
+        <mandatory value="false"></mandatory>
+        <status value="current"></status>
+    </leaf>
+</module>
\ No newline at end of file
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/modifier-yang1@1970-01-01.yin b/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/modifier-yang1@1970-01-01.yin
new file mode 100644 (file)
index 0000000..55b167b
--- /dev/null
@@ -0,0 +1,28 @@
+<module xmlns="urn:ietf:params:xml:ns:yang:yin:1" xmlns:my1="modifier-yang1"
+    name="modifier-yang1">
+    <yang-version value="1"></yang-version>
+    <namespace uri="modifier-yang1"></namespace>
+    <prefix value="my1"></prefix>
+    <revision date="1970-01-01"></revision>
+    <leaf name="my-leaf">
+        <type name="string">
+            <length value="0..2147483647">
+                <error-message>
+                    <value>The argument is out of bounds &lt;0,
+                        2147483647&gt;</value>
+                </error-message>
+                <error-app-tag value="length-out-of-specified-bounds"></error-app-tag>
+            </length>
+            <pattern value=".*">
+                <error-message>
+                    <value>Supplied value does not match the regular
+                        expression ^.*$.</value>
+                </error-message>
+                <error-app-tag value="invalid-regular-expression"></error-app-tag>
+            </pattern>
+        </type>
+        <config value="true"></config>
+        <mandatory value="false"></mandatory>
+        <status value="current"></status>
+    </leaf>
+</module>
\ No newline at end of file
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/modifier@1970-01-01.yin b/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/modifier@1970-01-01.yin
new file mode 100644 (file)
index 0000000..d31a2e8
--- /dev/null
@@ -0,0 +1,29 @@
+<module xmlns="urn:ietf:params:xml:ns:yang:yin:1" xmlns:m="modifier"
+    name="modifier">
+    <yang-version value="1.1"></yang-version>
+    <namespace uri="modifier"></namespace>
+    <prefix value="m"></prefix>
+    <revision date="1970-01-01"></revision>
+    <leaf name="my-leaf">
+        <type name="string">
+            <length value="0..2147483647">
+                <error-message>
+                    <value>The argument is out of bounds &lt;0,
+                        2147483647&gt;</value>
+                </error-message>
+                <error-app-tag value="length-out-of-specified-bounds"></error-app-tag>
+            </length>
+            <pattern value=".*">
+                <error-message>
+                    <value>Supplied value does not match the regular
+                        expression ^.*$.</value>
+                </error-message>
+                <error-app-tag value="invalid-regular-expression"></error-app-tag>
+                <modifier value="invert-match"></modifier>
+            </pattern>
+        </type>
+        <config value="true"></config>
+        <mandatory value="false"></mandatory>
+        <status value="current"></status>
+    </leaf>
+</module>
\ No newline at end of file
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/must-yang1@1970-01-01.yin b/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/must-yang1@1970-01-01.yin
new file mode 100644 (file)
index 0000000..7cf963f
--- /dev/null
@@ -0,0 +1,15 @@
+<module xmlns="urn:ietf:params:xml:ns:yang:yin:1" xmlns:muy1="must-yang1"
+    name="must-yang1">
+    <yang-version value="1"></yang-version>
+    <namespace uri="must-yang1"></namespace>
+    <prefix value="muy1"></prefix>
+    <revision date="1970-01-01"></revision>
+    <rpc name="r">
+        <status value="current"></status>
+        <input></input>
+        <output></output>
+    </rpc>
+    <notification name="n">
+        <status value="current"></status>
+    </notification>
+</module>
\ No newline at end of file
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/must@1970-01-01.yin b/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/must@1970-01-01.yin
new file mode 100644 (file)
index 0000000..ba63fb1
--- /dev/null
@@ -0,0 +1,34 @@
+<module xmlns="urn:ietf:params:xml:ns:yang:yin:1" xmlns:mu="must"
+    name="must">
+    <yang-version value="1.1"></yang-version>
+    <namespace uri="must"></namespace>
+    <prefix value="mu"></prefix>
+    <revision date="1970-01-01"></revision>
+    <container name="root">
+        <presence value="false"></presence>
+        <config value="true"></config>
+        <status value="current"></status>
+        <action name="a">
+            <status value="current"></status>
+            <input>
+                <must condition="1!=0"></must>
+            </input>
+            <output>
+                <must condition="1!=0"></must>
+            </output>
+        </action>
+    </container>
+    <rpc name="r">
+        <status value="current"></status>
+        <input>
+            <must condition="1!=0"></must>
+        </input>
+        <output>
+            <must condition="1!=0"></must>
+        </output>
+    </rpc>
+    <notification name="n">
+        <must condition="1!=0"></must>
+        <status value="current"></status>
+    </notification>
+</module>
\ No newline at end of file
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/notification@1970-01-01.yin b/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/notification@1970-01-01.yin
new file mode 100644 (file)
index 0000000..0653b65
--- /dev/null
@@ -0,0 +1,60 @@
+<module xmlns="urn:ietf:params:xml:ns:yang:yin:1" xmlns:n="notification"
+    name="notification">
+    <yang-version value="1.1"></yang-version>
+    <namespace uri="notification"></namespace>
+    <prefix value="n"></prefix>
+    <revision date="1970-01-01"></revision>
+    <grouping name="grp">
+        <status value="current"></status>
+        <notification name="n5">
+            <status value="current"></status>
+        </notification>
+    </grouping>
+    <container name="r">
+        <presence value="false"></presence>
+        <config value="true"></config>
+        <status value="current"></status>
+        <notification name="n2">
+            <status value="current"></status>
+        </notification>
+        <notification name="n4">
+            <status value="current"></status>
+        </notification>
+        <notification name="n5">
+            <status value="current"></status>
+        </notification>
+    </container>
+    <list name="l">
+        <key value="id"></key>
+        <config value="true"></config>
+        <ordered-by value="system"></ordered-by>
+        <status value="current"></status>
+        <leaf name="id">
+            <type name="int16"></type>
+            <config value="true"></config>
+            <mandatory value="false"></mandatory>
+            <status value="current"></status>
+        </leaf>
+        <notification name="n3">
+            <status value="current"></status>
+        </notification>
+    </list>
+    <augment target-node="/r">
+        <status value="current"></status>
+        <uses name="grp"></uses>
+        <notification name="n5">
+            <status value="current"></status>
+        </notification>
+        <notification name="n4">
+            <status value="current"></status>
+        </notification>
+    </augment>
+    <notification name="n1">
+        <status value="current"></status>
+        <container name="c">
+            <presence value="false"></presence>
+            <config value="true"></config>
+            <status value="current"></status>
+        </container>
+    </notification>
+</module>
\ No newline at end of file
diff --git a/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/unique@1970-01-01.yin b/yang/yang-model-export/src/test/resources/bugs/bug2444/yin/unique@1970-01-01.yin
new file mode 100644 (file)
index 0000000..bab20f3
--- /dev/null
@@ -0,0 +1,54 @@
+<module xmlns="urn:ietf:params:xml:ns:yang:yin:1" xmlns:u="unique"
+    name="unique">
+    <yang-version value="1"></yang-version>
+    <namespace uri="unique"></namespace>
+    <prefix value="u"></prefix>
+    <revision date="1970-01-01"></revision>
+    <list name="l">
+        <key value="id"></key>
+        <unique tag="c1/c2/my-leaf-2"></unique>
+        <unique tag="my-container/my-leaf-3"></unique>
+        <config value="true"></config>
+        <ordered-by value="system"></ordered-by>
+        <status value="current"></status>
+        <leaf name="id">
+            <type name="string"></type>
+            <config value="true"></config>
+            <mandatory value="false"></mandatory>
+            <status value="current"></status>
+        </leaf>
+        <leaf name="my-leaf-1">
+            <type name="string"></type>
+            <config value="true"></config>
+            <mandatory value="false"></mandatory>
+            <status value="current"></status>
+        </leaf>
+        <container name="c1">
+            <presence value="false"></presence>
+            <config value="true"></config>
+            <status value="current"></status>
+            <container name="c2">
+                <presence value="false"></presence>
+                <config value="true"></config>
+                <status value="current"></status>
+                <leaf name="my-leaf-2">
+                    <type name="string"></type>
+                    <config value="true"></config>
+                    <mandatory value="false"></mandatory>
+                    <status value="current"></status>
+                </leaf>
+            </container>
+        </container>
+        <container name="my-container">
+            <presence value="false"></presence>
+            <config value="true"></config>
+            <status value="current"></status>
+            <leaf name="my-leaf-3">
+                <type name="string"></type>
+                <config value="true"></config>
+                <mandatory value="false"></mandatory>
+                <status value="current"></status>
+            </leaf>
+        </container>
+    </list>
+</module>
\ No newline at end of file
index 4b39d76f9eff9d728faee8c5def769de5b61f1c7..b070218452963740aaf8fb87a8513f541b717de2 100644 (file)
@@ -2,12 +2,6 @@
     <yang-version value="1"></yang-version>
     <namespace uri="foo-namespace"></namespace>
     <prefix value="foo-prefix"></prefix>
-    <organization>
-        <text></text>
-    </organization>
-    <contact>
-        <text></text>
-    </contact>
     <revision date="2016-08-05"></revision>
     <extension name="test-extension">
         <status value="current"></status>