From 6e72d221f55cfac71ee6e594b62cb5af9672614a Mon Sep 17 00:00:00 2001 From: Martin Vitez Date: Tue, 16 Apr 2013 10:43:34 +0200 Subject: [PATCH] Refactored YANG types resolving. Fixed YANG union type parsing. Refactored code after PMD check. Fixed organization statement in test files. Signed-off-by: Martin Vitez --- .../yang/types/test/GeneratedTypesTest.java | 15 +- .../builder/api/AbstractTypeAwareBuilder.java | 32 + .../parser/builder/api/TypeAwareBuilder.java | 9 +- .../builder/api/TypeDefinitionBuilder.java | 45 +- .../impl/ContainerSchemaNodeBuilder.java | 21 +- .../impl/LeafListSchemaNodeBuilder.java | 60 +- .../builder/impl/LeafSchemaNodeBuilder.java | 57 +- .../parser/builder/impl/ModuleBuilder.java | 2095 ++++++++------- .../parser/builder/impl/TypedefBuilder.java | 333 +-- .../parser/builder/impl/UnionTypeBuilder.java | 151 +- .../parser/impl/YangModelParserImpl.java | 1600 ++++++------ .../impl/YangModelParserListenerImpl.java | 87 +- .../model/parser/util/TypeConstraints.java | 13 +- .../parser/util/YangModelBuilderUtil.java | 2239 +++++++++-------- .../model/parser/util/YangParseException.java | 4 + .../impl/ContainerSchemaNodeBuilderTest.java | 111 - .../impl/LeafListSchemaNodeBuilderTest.java | 91 - .../impl/LeafSchemaNodeBuilderTest.java | 90 - .../impl/ListSchemaNodeBuilderTest.java | 118 - .../parser/impl/TypesResolutionTest.java | 426 ++-- .../impl/YangModelParserListenerTest.java | 271 -- .../parser/impl/YangModelParserTest.java | 528 ++-- .../src/test/resources/model/testfile1.yang | 148 +- .../src/test/resources/model/testfile2.yang | 279 +- .../types/custom-types-test@2012-4-4.yang | 41 +- .../yang/model/api/TypeDefinition.java | 2 +- .../yang/model/util/ExtendedType.java | 61 + .../controller/yang/model/util/Leafref.java | 28 +- 28 files changed, 4326 insertions(+), 4629 deletions(-) create mode 100644 opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/api/AbstractTypeAwareBuilder.java delete mode 100644 opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/builder/impl/ContainerSchemaNodeBuilderTest.java delete mode 100644 opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/builder/impl/LeafListSchemaNodeBuilderTest.java delete mode 100644 opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/builder/impl/LeafSchemaNodeBuilderTest.java delete mode 100644 opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/builder/impl/ListSchemaNodeBuilderTest.java delete mode 100644 opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserListenerTest.java diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/yang/types/test/GeneratedTypesTest.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/yang/types/test/GeneratedTypesTest.java index 077db920f5..4480f25316 100644 --- a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/yang/types/test/GeneratedTypesTest.java +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/yang/types/test/GeneratedTypesTest.java @@ -7,12 +7,12 @@ */ package org.opendaylight.controller.sal.binding.yang.types.test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import java.util.List; import java.util.Set; +import org.junit.Ignore; import org.junit.Test; import org.opendaylight.controller.sal.binding.generator.api.BindingGenerator; import org.opendaylight.controller.sal.binding.generator.impl.BindingGeneratorImpl; @@ -52,7 +52,8 @@ public class GeneratedTypesTest { assertTrue(genTypes != null); assertEquals(11, genTypes.size()); } - + + @Ignore @Test public void testLeafrefResolving() { final String topologyPath = getClass().getResource( @@ -82,19 +83,19 @@ public class GeneratedTypesTest { topologyPath, interfacesPath, inetTypesPath, yangTypesPath); assertTrue(context != null); assertEquals(4, context.getModules().size()); - + final BindingGenerator bindingGen = new BindingGeneratorImpl(); final List genTypes = bindingGen.generateTypes(context); - + assertEquals(21, genTypes.size()); assertTrue(genTypes != null); - + for (final Type genType : genTypes) { if (genType.getName().equals("Interface") && genType instanceof GeneratedType) { // System.out.println(((GeneratedType)genType).getMethodDefinitions().toString()); } else if (genType.getName().equals("NetworkLink") && genType instanceof GeneratedType) { // System.out.println(((GeneratedType)genType).getMethodDefinitions().toString()); - } + } } } diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/api/AbstractTypeAwareBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/api/AbstractTypeAwareBuilder.java new file mode 100644 index 0000000000..35446ced15 --- /dev/null +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/api/AbstractTypeAwareBuilder.java @@ -0,0 +1,32 @@ +package org.opendaylight.controller.yang.model.parser.builder.api; + +import org.opendaylight.controller.yang.model.api.TypeDefinition; + +public class AbstractTypeAwareBuilder implements TypeAwareBuilder { + + protected TypeDefinition type; + protected TypeDefinitionBuilder typedef; + + @Override + public TypeDefinition getType() { + return type; + } + + @Override + public TypeDefinitionBuilder getTypedef() { + return typedef; + } + + @Override + public void setType(TypeDefinition type) { + this.type = type; + this.typedef = null; + } + + @Override + public void setType(TypeDefinitionBuilder typedef) { + this.typedef = typedef; + this.type = null; + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/api/TypeAwareBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/api/TypeAwareBuilder.java index ac51e5796d..73f2cf28ca 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/api/TypeAwareBuilder.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/api/TypeAwareBuilder.java @@ -15,7 +15,12 @@ import org.opendaylight.controller.yang.model.api.TypeDefinition; */ public interface TypeAwareBuilder { - TypeDefinition getType(); - void setType(TypeDefinition type); + TypeDefinition getType(); + + TypeDefinitionBuilder getTypedef(); + + void setType(TypeDefinition type); + + void setType(TypeDefinitionBuilder typedef); } diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/api/TypeDefinitionBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/api/TypeDefinitionBuilder.java index a303b969a6..a18fa8b4d6 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/api/TypeDefinitionBuilder.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/api/TypeDefinitionBuilder.java @@ -7,22 +7,59 @@ */ package org.opendaylight.controller.yang.model.parser.builder.api; +import java.util.List; + import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; import org.opendaylight.controller.yang.model.api.TypeDefinition; +import org.opendaylight.controller.yang.model.api.type.LengthConstraint; +import org.opendaylight.controller.yang.model.api.type.PatternConstraint; +import org.opendaylight.controller.yang.model.api.type.RangeConstraint; +import org.opendaylight.controller.yang.model.parser.builder.impl.UnknownSchemaNodeBuilder; /** * Interface for builders of 'typedef' statement. */ -public interface TypeDefinitionBuilder { +public interface TypeDefinitionBuilder extends TypeAwareBuilder, + SchemaNodeBuilder { + + TypeDefinition build(); QName getQName(); - TypeDefinition getBaseType(); + SchemaPath getPath(); - TypeDefinition build(); + String getDescription(); - void setUnits(String units); + String getReference(); + + Status getStatus(); + + List getRanges(); + + void setRanges(List ranges); + + List getLengths(); + + void setLengths(List lengths); + + List getPatterns(); + + void setPatterns(List patterns); + + Integer getFractionDigits(); + + void setFractionDigits(Integer fractionDigits); + + List getUnknownNodes(); + + Object getDefaultValue(); void setDefaultValue(Object defaultValue); + String getUnits(); + + void setUnits(String units); + } diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/ContainerSchemaNodeBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/ContainerSchemaNodeBuilder.java index 9b965daae6..eed8437fdd 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/ContainerSchemaNodeBuilder.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/ContainerSchemaNodeBuilder.java @@ -55,28 +55,28 @@ public class ContainerSchemaNodeBuilder extends AbstractChildNodeBuilder @Override public ContainerSchemaNode build() { // CHILD NODES - Map childs = new HashMap(); + final Map childs = new HashMap(); for (DataSchemaNodeBuilder node : childNodes) { childs.put(node.getQName(), node.build()); } instance.setChildNodes(childs); // GROUPINGS - Set groupingDefinitions = new HashSet(); + final Set groupingDefinitions = new HashSet(); for (GroupingBuilder builder : groupings) { groupingDefinitions.add(builder.build()); } instance.setGroupings(groupingDefinitions); // TYPEDEFS - Set> typedefs = new HashSet>(); + final Set> typedefs = new HashSet>(); for (TypeDefinitionBuilder entry : addedTypedefs) { typedefs.add(entry.build()); } instance.setTypeDefinitions(typedefs); // USES - Set uses = new HashSet(); + final Set uses = new HashSet(); for (UsesNodeBuilder builder : addedUsesNodes) { uses.add(builder.build()); } @@ -84,7 +84,7 @@ public class ContainerSchemaNodeBuilder extends AbstractChildNodeBuilder // UNKNOWN NODES final List unknownNodes = new ArrayList(); - for(UnknownSchemaNodeBuilder b : addedUnknownNodes) { + for (UnknownSchemaNodeBuilder b : addedUnknownNodes) { unknownNodes.add(b.build()); } instance.setUnknownSchemaNodes(unknownNodes); @@ -169,7 +169,7 @@ public class ContainerSchemaNodeBuilder extends AbstractChildNodeBuilder private Set groupings = Collections.emptySet(); private Set> typeDefinitions = Collections.emptySet(); private Set uses = Collections.emptySet(); - private List unknownSchemaNodes = Collections.emptyList(); + private List unknownNodes = Collections.emptyList(); private boolean presence; private ContainerSchemaNodeImpl(QName qname) { @@ -330,12 +330,13 @@ public class ContainerSchemaNodeBuilder extends AbstractChildNodeBuilder @Override public List getUnknownSchemaNodes() { - return unknownSchemaNodes; + return unknownNodes; } - private void setUnknownSchemaNodes(List unknownSchemaNodes) { - if(unknownSchemaNodes != null) { - this.unknownSchemaNodes = unknownSchemaNodes; + private void setUnknownSchemaNodes( + List unknownSchemaNodes) { + if (unknownSchemaNodes != null) { + this.unknownNodes = unknownSchemaNodes; } } diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/LeafListSchemaNodeBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/LeafListSchemaNodeBuilder.java index 5a9fdb5815..12c976b774 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/LeafListSchemaNodeBuilder.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/LeafListSchemaNodeBuilder.java @@ -18,18 +18,17 @@ import org.opendaylight.controller.yang.model.api.SchemaPath; import org.opendaylight.controller.yang.model.api.Status; import org.opendaylight.controller.yang.model.api.TypeDefinition; import org.opendaylight.controller.yang.model.api.UnknownSchemaNode; +import org.opendaylight.controller.yang.model.parser.builder.api.AbstractTypeAwareBuilder; import org.opendaylight.controller.yang.model.parser.builder.api.DataSchemaNodeBuilder; import org.opendaylight.controller.yang.model.parser.builder.api.SchemaNodeBuilder; -import org.opendaylight.controller.yang.model.parser.builder.api.TypeAwareBuilder; -public class LeafListSchemaNodeBuilder implements SchemaNodeBuilder, - TypeAwareBuilder, DataSchemaNodeBuilder { +public class LeafListSchemaNodeBuilder extends AbstractTypeAwareBuilder implements SchemaNodeBuilder, + DataSchemaNodeBuilder { private final LeafListSchemaNodeImpl instance; private final QName qname; - private final ConstraintsBuilder constraintsBuilder = new ConstraintsBuilder(); + private final ConstraintsBuilder constraints = new ConstraintsBuilder(); private final List addedUnknownNodes = new ArrayList(); - private TypeDefinition type; LeafListSchemaNodeBuilder(QName qname) { this.qname = qname; @@ -38,7 +37,21 @@ public class LeafListSchemaNodeBuilder implements SchemaNodeBuilder, @Override public LeafListSchemaNode build() { - instance.setConstraints(constraintsBuilder.build()); + instance.setConstraints(constraints.build()); + + if(type == null) { + instance.setType(typedef.build()); + } else { + instance.setType(type); + } + + // UNKNOWN NODES + final List unknownNodes = new ArrayList(); + for (UnknownSchemaNodeBuilder b : addedUnknownNodes) { + unknownNodes.add(b.build()); + } + instance.setUnknownSchemaNodes(unknownNodes); + return instance; } @@ -69,17 +82,6 @@ public class LeafListSchemaNodeBuilder implements SchemaNodeBuilder, } } - @Override - public TypeDefinition getType() { - return type; - } - - @Override - public void setType(TypeDefinition type) { - this.type = type; - instance.setType(type); - } - @Override public void setAugmenting(boolean augmenting) { instance.setAugmenting(augmenting); @@ -92,7 +94,7 @@ public class LeafListSchemaNodeBuilder implements SchemaNodeBuilder, @Override public ConstraintsBuilder getConstraintsBuilder() { - return constraintsBuilder; + return constraints; } public void setUserOrdered(boolean userOrdered) { @@ -112,10 +114,11 @@ public class LeafListSchemaNodeBuilder implements SchemaNodeBuilder, private Status status = Status.CURRENT; private boolean augmenting; private boolean configuration; - private ConstraintDefinition constraints; + private ConstraintDefinition constraintsDef; private TypeDefinition type; private boolean userOrdered; - private List unknownSchemaNodes = Collections.emptyList(); + private List unknownNodes = Collections + .emptyList(); private LeafListSchemaNodeImpl(QName qname) { this.qname = qname; @@ -182,11 +185,11 @@ public class LeafListSchemaNodeBuilder implements SchemaNodeBuilder, @Override public ConstraintDefinition getConstraints() { - return constraints; + return constraintsDef; } - private void setConstraints(ConstraintDefinition constraints) { - this.constraints = constraints; + private void setConstraints(ConstraintDefinition constraintsDef) { + this.constraintsDef = constraintsDef; } @Override @@ -209,12 +212,13 @@ public class LeafListSchemaNodeBuilder implements SchemaNodeBuilder, @Override public List getUnknownSchemaNodes() { - return unknownSchemaNodes; + return unknownNodes; } - private void setUnknownSchemaNodes(List unknownSchemaNodes) { - if(unknownSchemaNodes != null) { - this.unknownSchemaNodes = unknownSchemaNodes; + private void setUnknownSchemaNodes( + List unknownNodes) { + if (unknownNodes != null) { + this.unknownNodes = unknownNodes; } } @@ -268,7 +272,7 @@ public class LeafListSchemaNodeBuilder implements SchemaNodeBuilder, sb.append(", status=" + status); sb.append(", augmenting=" + augmenting); sb.append(", configuration=" + configuration); - sb.append(", constraints=" + constraints); + sb.append(", constraints=" + constraintsDef); sb.append(", type=" + type); sb.append(", userOrdered=" + userOrdered); sb.append("]"); diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/LeafSchemaNodeBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/LeafSchemaNodeBuilder.java index bd18ba50a3..6146550257 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/LeafSchemaNodeBuilder.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/LeafSchemaNodeBuilder.java @@ -18,18 +18,16 @@ import org.opendaylight.controller.yang.model.api.SchemaPath; import org.opendaylight.controller.yang.model.api.Status; import org.opendaylight.controller.yang.model.api.TypeDefinition; import org.opendaylight.controller.yang.model.api.UnknownSchemaNode; +import org.opendaylight.controller.yang.model.parser.builder.api.AbstractTypeAwareBuilder; import org.opendaylight.controller.yang.model.parser.builder.api.DataSchemaNodeBuilder; import org.opendaylight.controller.yang.model.parser.builder.api.SchemaNodeBuilder; -import org.opendaylight.controller.yang.model.parser.builder.api.TypeAwareBuilder; - -public class LeafSchemaNodeBuilder implements DataSchemaNodeBuilder, - SchemaNodeBuilder, TypeAwareBuilder { +public class LeafSchemaNodeBuilder extends AbstractTypeAwareBuilder implements DataSchemaNodeBuilder, + SchemaNodeBuilder { private final QName qname; private final LeafSchemaNodeImpl instance; - private final ConstraintsBuilder constraintsBuilder = new ConstraintsBuilder(); + private final ConstraintsBuilder constraints = new ConstraintsBuilder(); private final List addedUnknownNodes = new ArrayList(); - private TypeDefinition type; LeafSchemaNodeBuilder(QName qname) { this.qname = qname; @@ -38,6 +36,12 @@ public class LeafSchemaNodeBuilder implements DataSchemaNodeBuilder, @Override public LeafSchemaNode build() { + if(type == null) { + instance.setType(typedef.build()); + } else { + instance.setType(type); + } + // UNKNOWN NODES final List unknownNodes = new ArrayList(); for(UnknownSchemaNodeBuilder b : addedUnknownNodes) { @@ -45,7 +49,7 @@ public class LeafSchemaNodeBuilder implements DataSchemaNodeBuilder, } instance.setUnknownSchemaNodes(unknownNodes); - instance.setConstraints(constraintsBuilder.build()); + instance.setConstraints(constraints.build()); return instance; } @@ -88,23 +92,12 @@ public class LeafSchemaNodeBuilder implements DataSchemaNodeBuilder, @Override public ConstraintsBuilder getConstraintsBuilder() { - return constraintsBuilder; - } - - @Override - public TypeDefinition getType() { - return type; - } - - @Override - public void setType(TypeDefinition type) { - this.type = type; - instance.setType(type); + return constraints; } @Override - public void addUnknownSchemaNode(UnknownSchemaNodeBuilder unknownSchemaNodeBuilder) { - addedUnknownNodes.add(unknownSchemaNodeBuilder); + public void addUnknownSchemaNode(UnknownSchemaNodeBuilder unknownNode) { + addedUnknownNodes.add(unknownNode); } private class LeafSchemaNodeImpl implements LeafSchemaNode { @@ -115,9 +108,9 @@ public class LeafSchemaNodeBuilder implements DataSchemaNodeBuilder, private Status status = Status.CURRENT; private boolean augmenting; private boolean configuration; - private ConstraintDefinition constraints; + private ConstraintDefinition constraintsDef; private TypeDefinition type; - private List unknownSchemaNodes = Collections.emptyList(); + private List unknownNodes = Collections.emptyList(); private LeafSchemaNodeImpl(QName qname) { this.qname = qname; @@ -186,11 +179,11 @@ public class LeafSchemaNodeBuilder implements DataSchemaNodeBuilder, @Override public ConstraintDefinition getConstraints() { - return constraints; + return constraintsDef; } - private void setConstraints(ConstraintDefinition constraints) { - this.constraints = constraints; + private void setConstraints(ConstraintDefinition constraintsDef) { + this.constraintsDef = constraintsDef; } @Override @@ -204,12 +197,12 @@ public class LeafSchemaNodeBuilder implements DataSchemaNodeBuilder, @Override public List getUnknownSchemaNodes() { - return unknownSchemaNodes; + return unknownNodes; } - private void setUnknownSchemaNodes(List unknownSchemaNodes) { - if(unknownSchemaNodes != null) { - this.unknownSchemaNodes = unknownSchemaNodes; + private void setUnknownSchemaNodes(List unknownNodes) { + if(unknownNodes != null) { + this.unknownNodes = unknownNodes; } } @@ -263,9 +256,9 @@ public class LeafSchemaNodeBuilder implements DataSchemaNodeBuilder, sb.append(", status=" + status); sb.append(", augmenting=" + augmenting); sb.append(", configuration=" + configuration); - sb.append(", constraints=" + constraints); + sb.append(", constraints=" + constraintsDef); sb.append(", type=" + type); - sb.append(", constraints=" + constraints); + sb.append(", constraints=" + constraintsDef); sb.append("]"); return sb.toString(); } diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/ModuleBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/ModuleBuilder.java index d22295ae66..86adcdd71d 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/ModuleBuilder.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/ModuleBuilder.java @@ -1,1049 +1,1046 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.yang.model.parser.builder.impl; - -import java.net.URI; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.opendaylight.controller.yang.common.QName; -import org.opendaylight.controller.yang.model.api.AugmentationSchema; -import org.opendaylight.controller.yang.model.api.DataSchemaNode; -import org.opendaylight.controller.yang.model.api.Deviation; -import org.opendaylight.controller.yang.model.api.ExtensionDefinition; -import org.opendaylight.controller.yang.model.api.FeatureDefinition; -import org.opendaylight.controller.yang.model.api.GroupingDefinition; -import org.opendaylight.controller.yang.model.api.IdentitySchemaNode; -import org.opendaylight.controller.yang.model.api.Module; -import org.opendaylight.controller.yang.model.api.ModuleImport; -import org.opendaylight.controller.yang.model.api.NotificationDefinition; -import org.opendaylight.controller.yang.model.api.RpcDefinition; -import org.opendaylight.controller.yang.model.api.TypeDefinition; -import org.opendaylight.controller.yang.model.api.UsesNode; -import org.opendaylight.controller.yang.model.parser.builder.api.AugmentationSchemaBuilder; -import org.opendaylight.controller.yang.model.parser.builder.api.Builder; -import org.opendaylight.controller.yang.model.parser.builder.api.ChildNodeBuilder; -import org.opendaylight.controller.yang.model.parser.builder.api.DataSchemaNodeBuilder; -import org.opendaylight.controller.yang.model.parser.builder.api.GroupingBuilder; -import org.opendaylight.controller.yang.model.parser.builder.api.TypeAwareBuilder; -import org.opendaylight.controller.yang.model.parser.builder.api.TypeDefinitionAwareBuilder; -import org.opendaylight.controller.yang.model.parser.builder.api.TypeDefinitionBuilder; -import org.opendaylight.controller.yang.model.parser.builder.api.UsesNodeBuilder; - -/** - * This builder builds Module object. If this module is dependent on external - * module/modules, these dependencies must be resolved before module is built, - * otherwise result may not be valid. - */ -public class ModuleBuilder implements Builder { - - private final ModuleImpl instance; - private final String name; - private String prefix; - private Date revision; - - private final Set imports = new HashSet(); - private Set augmentations; - - /** - * All nodes, that can contain other nodes - */ - private final Map, Builder> moduleNodes = new HashMap, Builder>(); - - /** - * Holds all child (DataSchemaNode) nodes: anyxml, choice, case, container, - * list, leaf, leaf-list. - */ - private final Map, DataSchemaNodeBuilder> addedChilds = new HashMap, DataSchemaNodeBuilder>(); - - private final Map, GroupingBuilder> addedGroupings = new HashMap, GroupingBuilder>(); - private final Set addedAugments = new HashSet(); - private final Map, UsesNodeBuilder> addedUsesNodes = new HashMap, UsesNodeBuilder>(); - private final Map, RpcDefinitionBuilder> addedRpcs = new HashMap, RpcDefinitionBuilder>(); - private final Set addedNotifications = new HashSet(); - private final Set addedIdentities = new HashSet(); - private final Map, FeatureBuilder> addedFeatures = new HashMap, FeatureBuilder>(); - private final Map addedDeviations = new HashMap(); - private final Map, TypeDefinitionBuilder> addedTypedefs = new HashMap, TypeDefinitionBuilder>(); - private final List addedExtensions = new ArrayList(); - - private final Map, TypeAwareBuilder> dirtyNodes = new HashMap, TypeAwareBuilder>(); - private final Map, UnionTypeBuilder> unionTypes = new HashMap, UnionTypeBuilder>(); - - public ModuleBuilder(String name) { - this.name = name; - instance = new ModuleImpl(name); - } - - - /** - * Build new Module object based on this builder. - */ - @Override - public Module build() { - instance.setImports(imports); - - // TYPEDEFS - final Set> typedefs = buildModuleTypedefs(addedTypedefs); - instance.setTypeDefinitions(typedefs); - - // CHILD NODES - final Map childNodes = buildModuleChildNodes(addedChilds); - instance.setChildNodes(childNodes); - - // GROUPINGS - final Set groupings = buildModuleGroupings(addedGroupings); - instance.setGroupings(groupings); - - // USES - final Set usesNodeDefinitions = buildUsesNodes(addedUsesNodes); - instance.setUses(usesNodeDefinitions); - - // FEATURES - final Set features = buildModuleFeatures(addedFeatures); - instance.setFeatures(features); - - // NOTIFICATIONS - final Set notifications = new HashSet(); - for (NotificationBuilder entry : addedNotifications) { - notifications.add((NotificationDefinition) entry.build()); - } - instance.setNotifications(notifications); - - // AUGMENTATIONS - instance.setAugmentations(augmentations); - - // RPCs - final Set rpcs = buildModuleRpcs(addedRpcs); - instance.setRpcs(rpcs); - - // DEVIATIONS - final Set deviations = new HashSet(); - for (Map.Entry entry : addedDeviations - .entrySet()) { - deviations.add(entry.getValue().build()); - } - instance.setDeviations(deviations); - - // EXTENSIONS - final List extensions = new ArrayList(); - for(ExtensionBuilder b : addedExtensions) { - extensions.add(b.build()); - } - instance.setExtensionSchemaNodes(extensions); - - // IDENTITIES - final Set identities = new HashSet(); - for(IdentitySchemaNodeBuilder idBuilder : addedIdentities) { - identities.add(idBuilder.build()); - } - instance.setIdentities(identities); - - return instance; - } - - public Builder getNode(List path) { - return moduleNodes.get(path); - } - - public Map, TypeAwareBuilder> getDirtyNodes() { - return dirtyNodes; - } - - public Set getAddedAugments() { - return addedAugments; - } - - public Set getAddedIdentities() { - return addedIdentities; - } - - public String getName() { - return name; - } - - public String getPrefix() { - return prefix; - } - - public Date getRevision() { - return revision; - } - - public void addDirtyNode(List path) { - List dirtyNodePath = new ArrayList(path); - TypeAwareBuilder nodeBuilder = (TypeAwareBuilder) moduleNodes - .get(dirtyNodePath); - dirtyNodes.put(dirtyNodePath, nodeBuilder); - } - - public void setNamespace(URI namespace) { - instance.setNamespace(namespace); - } - - public void setRevision(Date revision) { - this.revision = revision; - instance.setRevision(revision); - } - - public void setPrefix(String prefix) { - this.prefix = prefix; - instance.setPrefix(prefix); - } - - public void setYangVersion(String yangVersion) { - instance.setYangVersion(yangVersion); - } - - public void setDescription(String description) { - instance.setDescription(description); - } - - public void setReference(String reference) { - instance.setReference(reference); - } - - public void setOrganization(String organization) { - instance.setOrganization(organization); - } - - public void setContact(String contact) { - instance.setContact(contact); - } - - public void setAugmentations(Set augmentations) { - this.augmentations = augmentations; - } - - public boolean addModuleImport(final String moduleName, - final Date revision, final String prefix) { - ModuleImport moduleImport = createModuleImport(moduleName, revision, - prefix); - return imports.add(moduleImport); - } - - public Set getModuleImports() { - return imports; - } - - public ExtensionBuilder addExtension(QName qname) { - ExtensionBuilder builder = new ExtensionBuilder(qname); - return builder; - } - - public ContainerSchemaNodeBuilder addContainerNode(QName containerName, - List parentPath) { - List pathToNode = new ArrayList(parentPath); - - ContainerSchemaNodeBuilder containerBuilder = new ContainerSchemaNodeBuilder( - containerName); - - ChildNodeBuilder parent = (ChildNodeBuilder) moduleNodes - .get(pathToNode); - if (parent != null) { - if(parent instanceof AugmentationSchemaBuilder) { - containerBuilder.setAugmenting(true); - } - parent.addChildNode(containerBuilder); - } - - pathToNode.add(containerName.getLocalName()); - moduleNodes.put(pathToNode, containerBuilder); - addedChilds.put(pathToNode, containerBuilder); - - return containerBuilder; - } - - public ListSchemaNodeBuilder addListNode(QName listName, - List parentPath) { - List pathToNode = new ArrayList(parentPath); - - ListSchemaNodeBuilder listBuilder = new ListSchemaNodeBuilder(listName); - - ChildNodeBuilder parent = (ChildNodeBuilder) moduleNodes - .get(pathToNode); - if (parent != null) { - if(parent instanceof AugmentationSchemaBuilder) { - listBuilder.setAugmenting(true); - } - parent.addChildNode(listBuilder); - } - - pathToNode.add(listName.getLocalName()); - moduleNodes.put(pathToNode, listBuilder); - addedChilds.put(pathToNode, listBuilder); - - return listBuilder; - } - - public LeafSchemaNodeBuilder addLeafNode(QName leafName, - List parentPath) { - List pathToNode = new ArrayList(parentPath); - - LeafSchemaNodeBuilder leafBuilder = new LeafSchemaNodeBuilder(leafName); - - ChildNodeBuilder parent = (ChildNodeBuilder) moduleNodes.get(pathToNode); - if (parent != null) { - if(parent instanceof AugmentationSchemaBuilder) { - leafBuilder.setAugmenting(true); - } - parent.addChildNode(leafBuilder); - } - - pathToNode.add(leafName.getLocalName()); - addedChilds.put(pathToNode, leafBuilder); - moduleNodes.put(pathToNode, leafBuilder); - - return leafBuilder; - } - - public LeafListSchemaNodeBuilder addLeafListNode(QName leafListName, - List parentPath) { - List pathToNode = new ArrayList(parentPath); - - LeafListSchemaNodeBuilder leafListBuilder = new LeafListSchemaNodeBuilder( - leafListName); - ChildNodeBuilder parent = (ChildNodeBuilder) moduleNodes.get(pathToNode); - if (parent != null) { - if(parent instanceof AugmentationSchemaBuilder) { - leafListBuilder.setAugmenting(true); - } - parent.addChildNode(leafListBuilder); - } - - pathToNode.add(leafListName.getLocalName()); - addedChilds.put(pathToNode, leafListBuilder); - moduleNodes.put(pathToNode, leafListBuilder); - - return leafListBuilder; - } - - public GroupingBuilder addGrouping(QName qname, List parentPath) { - List pathToGroup = new ArrayList(parentPath); - - GroupingBuilder builder = new GroupingBuilderImpl(qname); - ChildNodeBuilder parentNodeBuilder = (ChildNodeBuilder) moduleNodes.get(pathToGroup); - if (parentNodeBuilder != null) { - parentNodeBuilder.addGrouping(builder); - } - - pathToGroup.add(qname.getLocalName()); - moduleNodes.put(pathToGroup, builder); - addedGroupings.put(pathToGroup, builder); - - return builder; - } - - public AugmentationSchemaBuilder addAugment(String name, - List parentPath) { - List pathToAugment = new ArrayList(parentPath); - - AugmentationSchemaBuilder builder = new AugmentationSchemaBuilderImpl(name); - - // augment can only be in 'module' or 'uses' statement - UsesNodeBuilder parent = addedUsesNodes.get(pathToAugment); - if (parent != null) { - parent.addAugment(builder); - } - - pathToAugment.add(name); - moduleNodes.put(pathToAugment, builder); - addedAugments.add(builder); - - return builder; - } - - public UsesNodeBuilder addUsesNode(String groupingPathStr, - List parentPath) { - List pathToUses = new ArrayList(parentPath); - - UsesNodeBuilder usesBuilder = new UsesNodeBuilderImpl(groupingPathStr); - - ChildNodeBuilder parent = (ChildNodeBuilder) moduleNodes.get(pathToUses); - if (parent != null) { - if(parent instanceof AugmentationSchemaBuilder) { - usesBuilder.setAugmenting(true); - } - parent.addUsesNode(usesBuilder); - } - - pathToUses.add(groupingPathStr); - addedUsesNodes.put(pathToUses, usesBuilder); - - return usesBuilder; - } - - public RpcDefinitionBuilder addRpc(QName qname, List parentPath) { - List pathToRpc = new ArrayList(parentPath); - - RpcDefinitionBuilder rpcBuilder = new RpcDefinitionBuilder(qname); - - pathToRpc.add(qname.getLocalName()); - addedRpcs.put(pathToRpc, rpcBuilder); - - QName inputQName = new QName(qname.getNamespace(), qname.getRevision(), - qname.getPrefix(), "input"); - ContainerSchemaNodeBuilder inputBuilder = new ContainerSchemaNodeBuilder(inputQName); - List pathToInput = new ArrayList(pathToRpc); - pathToInput.add("input"); - moduleNodes.put(pathToInput, inputBuilder); - rpcBuilder.setInput(inputBuilder); - - QName outputQName = new QName(qname.getNamespace(), - qname.getRevision(), qname.getPrefix(), "output"); - ContainerSchemaNodeBuilder outputBuilder = new ContainerSchemaNodeBuilder(outputQName); - List pathToOutput = new ArrayList(pathToRpc); - pathToOutput.add("output"); - moduleNodes.put(pathToOutput, outputBuilder); - rpcBuilder.setOutput(outputBuilder); - - return rpcBuilder; - } - - public NotificationBuilder addNotification(QName notificationName, - List parentPath) { - List pathToNotification = new ArrayList(parentPath); - - NotificationBuilder notificationBuilder = new NotificationBuilder( - notificationName); - - pathToNotification.add(notificationName.getLocalName()); - moduleNodes.put(pathToNotification, notificationBuilder); - addedNotifications.add(notificationBuilder); - - return notificationBuilder; - } - - public FeatureBuilder addFeature(QName featureName, List parentPath) { - List pathToFeature = new ArrayList(parentPath); - pathToFeature.add(featureName.getLocalName()); - - FeatureBuilder builder = new FeatureBuilder(featureName); - addedFeatures.put(pathToFeature, builder); - return builder; - } - - public TypedefBuilder addTypedef(QName typeDefName, List parentPath) { - List pathToType = new ArrayList(parentPath); - TypedefBuilder builder = new TypedefBuilder(typeDefName); - TypeDefinitionAwareBuilder parent = (TypeDefinitionAwareBuilder) moduleNodes.get(pathToType); - if (parent != null) { - parent.addTypedef(builder); - } - pathToType.add(typeDefName.getLocalName()); - addedTypedefs.put(pathToType, builder); - moduleNodes.put(pathToType, builder); - return builder; - } - - public Set getModuleTypedefs() { - Set typedefs = new HashSet(); - for (Map.Entry, TypeDefinitionBuilder> entry : addedTypedefs.entrySet()) { - if (entry.getKey().size() == 2) { - typedefs.add(entry.getValue()); - } - } - return typedefs; - } - - public void setType(TypeDefinition type, List parentPath) { - TypeAwareBuilder parent = (TypeAwareBuilder) moduleNodes.get(parentPath); - parent.setType(type); - } - - public void addUnionType(List parentPath) { - TypeAwareBuilder parent = (TypeAwareBuilder) moduleNodes.get(parentPath); - UnionTypeBuilder union = new UnionTypeBuilder(); - parent.setType(union.build()); - - List path = new ArrayList(parentPath); - path.add("union"); - - unionTypes.put(path, union); - moduleNodes.put(path, union); - } - - public DeviationBuilder addDeviation(String targetPath) { - DeviationBuilder builder = new DeviationBuilder(targetPath); - addedDeviations.put(targetPath, builder); - return builder; - } - - public IdentitySchemaNodeBuilder addIdentity(QName qname) { - IdentitySchemaNodeBuilder builder = new IdentitySchemaNodeBuilder(qname); - addedIdentities.add(builder); - - return builder; - } - - public void addConfiguration(boolean configuration, List parentPath) { - Builder builder = moduleNodes.get(parentPath); - if (builder instanceof DeviationBuilder) { - // skip - // TODO - } else { - DataSchemaNodeBuilder configBuilder = (DataSchemaNodeBuilder) moduleNodes.get(parentPath); - configBuilder.setConfiguration(configuration); - } - } - - public UnknownSchemaNodeBuilder addUnknownSchemaNode(QName qname, List parentPath) { - UnknownSchemaNodeBuilder builder = new UnknownSchemaNodeBuilder(qname); - return builder; - } - - - private class ModuleImpl implements Module { - private URI namespace; - private final String name; - private Date revision; - private String prefix; - private String yangVersion; - private String description; - private String reference; - private String organization; - private String contact; - private Set imports = Collections.emptySet(); - private Set features = Collections.emptySet(); - private Set> typeDefinitions = Collections.emptySet(); - private Set notifications = Collections.emptySet(); - private Set augmentations = Collections.emptySet(); - private Set rpcs = Collections.emptySet(); - private Set deviations = Collections.emptySet(); - private Map childNodes = Collections.emptyMap(); - private Set groupings = Collections.emptySet(); - private Set uses = Collections.emptySet(); - private List extensionSchemaNodes = Collections.emptyList(); - private Set identities = Collections.emptySet(); - - private ModuleImpl(String name) { - this.name = name; - } - - @Override - public URI getNamespace() { - return namespace; - } - - private void setNamespace(URI namespace) { - this.namespace = namespace; - } - - @Override - public String getName() { - return name; - } - - @Override - public Date getRevision() { - return revision; - } - - private void setRevision(Date revision) { - this.revision = revision; - } - - @Override - public String getPrefix() { - return prefix; - } - - private void setPrefix(String prefix) { - this.prefix = prefix; - } - - @Override - public String getYangVersion() { - return yangVersion; - } - - private void setYangVersion(String yangVersion) { - this.yangVersion = yangVersion; - } - - @Override - public String getDescription() { - return description; - } - - private void setDescription(String description) { - this.description = description; - } - - @Override - public String getReference() { - return reference; - } - - private void setReference(String reference) { - this.reference = reference; - } - - @Override - public String getOrganization() { - return organization; - } - - private void setOrganization(String organization) { - this.organization = organization; - } - - @Override - public String getContact() { - return contact; - } - - private void setContact(String contact) { - this.contact = contact; - } - - @Override - public Set getImports() { - return imports; - } - - private void setImports(Set imports) { - if(imports != null) { - this.imports = imports; - } - } - - @Override - public Set getFeatures() { - return features; - } - - private void setFeatures(Set features) { - if(features != null) { - this.features = features; - } - } - - @Override - public Set> getTypeDefinitions() { - return typeDefinitions; - } - - private void setTypeDefinitions(Set> typeDefinitions) { - if(typeDefinitions != null) { - this.typeDefinitions = typeDefinitions; - } - } - - @Override - public Set getNotifications() { - return notifications; - } - - private void setNotifications(Set notifications) { - if(notifications != null) { - this.notifications = notifications; - } - } - - @Override - public Set getAugmentations() { - return augmentations; - } - - private void setAugmentations(Set augmentations) { - if(augmentations != null) { - this.augmentations = augmentations; - } - } - - @Override - public Set getRpcs() { - return rpcs; - } - - private void setRpcs(Set rpcs) { - if(rpcs != null) { - this.rpcs = rpcs; - } - } - - @Override - public Set getDeviations() { - return deviations; - } - - private void setDeviations(Set deviations) { - if(deviations != null) { - this.deviations = deviations; - } - } - - @Override - public Set getChildNodes() { - return new HashSet(childNodes.values()); - } - - private void setChildNodes(Map childNodes) { - if(childNodes != null) { - this.childNodes = childNodes; - } - } - - @Override - public Set getGroupings() { - return groupings; - } - - private void setGroupings(Set groupings) { - if(groupings != null) { - this.groupings = groupings; - } - } - - @Override - public Set getUses() { - return uses; - } - - private void setUses(Set uses) { - if(uses != null) { - this.uses = uses; - } - } - - @Override - public List getExtensionSchemaNodes() { - return extensionSchemaNodes; - } - - private void setExtensionSchemaNodes(List extensionSchemaNodes) { - if(extensionSchemaNodes != null) { - this.extensionSchemaNodes = extensionSchemaNodes; - } - } - - @Override - public Set getIdentities() { - return identities; - } - - private void setIdentities(Set identities) { - if(identities != null) { - this.identities = identities; - } - } - - @Override - public DataSchemaNode getDataChildByName(QName name) { - return childNodes.get(name); - } - - @Override - public DataSchemaNode getDataChildByName(String name) { - DataSchemaNode result = null; - for (Map.Entry entry : childNodes.entrySet()) { - if (entry.getKey().getLocalName().equals(name)) { - result = entry.getValue(); - break; - } - } - return result; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((namespace == null) ? 0 : namespace.hashCode()); - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + ((revision == null) ? 0 : revision.hashCode()); - result = prime * result + ((prefix == null) ? 0 : prefix.hashCode()); - result = prime * result + ((yangVersion == null) ? 0 : yangVersion.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - ModuleImpl other = (ModuleImpl) obj; - if (namespace == null) { - if (other.namespace != null) { - return false; - } - } else if (!namespace.equals(other.namespace)) { - return false; - } - if (name == null) { - if (other.name != null) { - return false; - } - } else if (!name.equals(other.name)) { - return false; - } - if (revision == null) { - if (other.revision != null) { - return false; - } - } else if (!revision.equals(other.revision)) { - return false; - } - if (prefix == null) { - if (other.prefix != null) { - return false; - } - } else if (!prefix.equals(other.prefix)) { - return false; - } - if (yangVersion == null) { - if (other.yangVersion != null) { - return false; - } - } else if (!yangVersion.equals(other.yangVersion)) { - return false; - } - return true; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder( - ModuleImpl.class.getSimpleName()); - sb.append("[\n"); - sb.append("name=" + name + ",\n"); - sb.append("namespace=" + namespace + ",\n"); - sb.append("revision=" + revision + ",\n"); - sb.append("prefix=" + prefix + ",\n"); - sb.append("yangVersion=" + yangVersion + ",\n"); - sb.append("description=" + description + ",\n"); - sb.append("reference=" + reference + ",\n"); - sb.append("organization=" + organization + ",\n"); - sb.append("contact=" + contact + ",\n"); - sb.append("childNodes=" + childNodes.values() + ",\n"); - sb.append("groupings=" + groupings + ",\n"); - sb.append("imports=" + imports + ",\n"); - sb.append("features=" + features + ",\n"); - sb.append("typeDefinitions=" + typeDefinitions + ",\n"); - sb.append("notifications=" + notifications + ",\n"); - sb.append("augmentations=" + augmentations + ",\n"); - sb.append("rpcs=" + rpcs + ",\n"); - sb.append("deviations=" + deviations + "\n"); - sb.append("uses=" + uses + "\n"); - sb.append("]"); - return sb.toString(); - } - } - - private ModuleImport createModuleImport(final String moduleName, - final Date revision, final String prefix) { - ModuleImport moduleImport = new ModuleImport() { - @Override - public String getModuleName() { - return moduleName; - } - - @Override - public Date getRevision() { - return revision; - } - - @Override - public String getPrefix() { - return prefix; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result - + ((moduleName == null) ? 0 : moduleName.hashCode()); - result = prime * result - + ((revision == null) ? 0 : revision.hashCode()); - result = prime * result - + ((prefix == null) ? 0 : prefix.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - ModuleImport other = (ModuleImport) obj; - if (getModuleName() == null) { - if (other.getModuleName() != null) { - return false; - } - } else if (!getModuleName().equals(other.getModuleName())) { - return false; - } - if (getRevision() == null) { - if (other.getRevision() != null) { - return false; - } - } else if (!getRevision().equals(other.getRevision())) { - return false; - } - if (getPrefix() == null) { - if (other.getPrefix() != null) { - return false; - } - } else if (!getPrefix().equals(other.getPrefix())) { - return false; - } - return true; - } - - @Override - public String toString() { - return "ModuleImport[moduleName=" + moduleName + ", revision=" - + revision + ", prefix=" + prefix + "]"; - } - }; - return moduleImport; - } - - /** - * Traverse through given addedChilds and add only direct module childs. - * Direct module child path size is 2 (1. module name, 2. child name). - * - * @param addedChilds - * @return map of children, where key is child QName and value is child - * itself - */ - private Map buildModuleChildNodes( - Map, DataSchemaNodeBuilder> addedChilds) { - final Map childNodes = new HashMap(); - for (Map.Entry, DataSchemaNodeBuilder> entry : addedChilds - .entrySet()) { - if (entry.getKey().size() == 2) { - DataSchemaNode node = entry.getValue().build(); - QName qname = entry.getValue().getQName(); - childNodes.put(qname, node); - } - } - return childNodes; - } - - /** - * Traverse through given addedGroupings and add only direct module - * groupings. Direct module grouping path size is 2 (1. module name, 2. - * grouping name). - * - * @param addedGroupings - * @return set of built GroupingDefinition objects - */ - private Set buildModuleGroupings( - Map, GroupingBuilder> addedGroupings) { - final Set groupings = new HashSet(); - for (Map.Entry, GroupingBuilder> entry : addedGroupings - .entrySet()) { - if (entry.getKey().size() == 2) { - groupings.add(entry.getValue().build()); - } - } - return groupings; - } - - /** - * Traverse through given addedRpcs and build RpcDefinition objects. - * - * @param addedRpcs - * @return set of built RpcDefinition objects - */ - private Set buildModuleRpcs( - Map, RpcDefinitionBuilder> addedRpcs) { - final Set rpcs = new HashSet(); - RpcDefinitionBuilder builder; - for (Map.Entry, RpcDefinitionBuilder> entry : addedRpcs - .entrySet()) { - builder = entry.getValue(); - RpcDefinition rpc = builder.build(); - rpcs.add(rpc); - } - return rpcs; - } - - /** - * Traverse through given addedTypedefs and add only direct module typedef - * statements. Direct module typedef path size is 2 (1. module name, 2. - * typedef name). - * - * @param addedTypedefs - * @return set of built module typedef statements - */ - private Set> buildModuleTypedefs( - Map, TypeDefinitionBuilder> addedTypedefs) { - Set> typedefs = new HashSet>(); - for (Map.Entry, TypeDefinitionBuilder> entry : addedTypedefs - .entrySet()) { - if (entry.getKey().size() == 2) { - TypeDefinition> node = entry - .getValue().build(); - typedefs.add(node); - } - } - return typedefs; - } - - /** - * Traverse through given addedUsesNodes and add only direct module uses - * nodes. Direct module uses node path size is 2 (1. module name, 2. uses - * name). - * - * @param addedUsesNodes - * @return set of built module uses nodes - */ - private Set buildUsesNodes( - Map, UsesNodeBuilder> addedUsesNodes) { - final Set usesNodeDefinitions = new HashSet(); - for (Map.Entry, UsesNodeBuilder> entry : addedUsesNodes - .entrySet()) { - if (entry.getKey().size() == 2) { - usesNodeDefinitions.add(entry.getValue().build()); - } - } - return usesNodeDefinitions; - } - - /** - * Traverse through given addedFeatures and add only direct module features. - * Direct module feature path size is 2 (1. module name, 2. feature name). - * - * @param addedFeatures - * @return set of built module features - */ - private Set buildModuleFeatures( - Map, FeatureBuilder> addedFeatures) { - Set features = new HashSet(); - for (Map.Entry, FeatureBuilder> entry : addedFeatures - .entrySet()) { - if (entry.getKey().size() == 2) { - features.add(entry.getValue().build()); - } - } - return features; - } - -} +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.yang.model.parser.builder.impl; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.AugmentationSchema; +import org.opendaylight.controller.yang.model.api.DataSchemaNode; +import org.opendaylight.controller.yang.model.api.Deviation; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.FeatureDefinition; +import org.opendaylight.controller.yang.model.api.GroupingDefinition; +import org.opendaylight.controller.yang.model.api.IdentitySchemaNode; +import org.opendaylight.controller.yang.model.api.Module; +import org.opendaylight.controller.yang.model.api.ModuleImport; +import org.opendaylight.controller.yang.model.api.NotificationDefinition; +import org.opendaylight.controller.yang.model.api.RpcDefinition; +import org.opendaylight.controller.yang.model.api.TypeDefinition; +import org.opendaylight.controller.yang.model.api.UsesNode; +import org.opendaylight.controller.yang.model.parser.builder.api.AugmentationSchemaBuilder; +import org.opendaylight.controller.yang.model.parser.builder.api.Builder; +import org.opendaylight.controller.yang.model.parser.builder.api.ChildNodeBuilder; +import org.opendaylight.controller.yang.model.parser.builder.api.DataSchemaNodeBuilder; +import org.opendaylight.controller.yang.model.parser.builder.api.GroupingBuilder; +import org.opendaylight.controller.yang.model.parser.builder.api.TypeAwareBuilder; +import org.opendaylight.controller.yang.model.parser.builder.api.TypeDefinitionAwareBuilder; +import org.opendaylight.controller.yang.model.parser.builder.api.TypeDefinitionBuilder; +import org.opendaylight.controller.yang.model.parser.builder.api.UsesNodeBuilder; +import org.opendaylight.controller.yang.model.parser.util.YangParseException; + +/** + * This builder builds Module object. If this module is dependent on external + * module/modules, these dependencies must be resolved before module is built, + * otherwise result may not be valid. + */ +public class ModuleBuilder implements Builder { + + private final ModuleImpl instance; + private final String name; + private String prefix; + private Date revision; + + private final Set imports = new HashSet(); + private Set augmentations; + + /** + * All nodes, that can contain other nodes + */ + private final Map, Builder> moduleNodes = new HashMap, Builder>(); + + /** + * Holds all child (DataSchemaNode) nodes: anyxml, choice, case, container, + * list, leaf, leaf-list. + */ + private final Map, DataSchemaNodeBuilder> addedChilds = new HashMap, DataSchemaNodeBuilder>(); + + private final Map, GroupingBuilder> addedGroupings = new HashMap, GroupingBuilder>(); + private final Set addedAugments = new HashSet(); + private final Map, UsesNodeBuilder> addedUsesNodes = new HashMap, UsesNodeBuilder>(); + private final Map, RpcDefinitionBuilder> addedRpcs = new HashMap, RpcDefinitionBuilder>(); + private final Set addedNotifications = new HashSet(); + private final Set addedIdentities = new HashSet(); + private final Map, FeatureBuilder> addedFeatures = new HashMap, FeatureBuilder>(); + private final Map addedDeviations = new HashMap(); + private final Map, TypeDefinitionBuilder> addedTypedefs = new HashMap, TypeDefinitionBuilder>(); + private final List addedExtensions = new ArrayList(); + + private final Map, TypeAwareBuilder> dirtyNodes = new HashMap, TypeAwareBuilder>(); + + public ModuleBuilder(String name) { + this.name = name; + instance = new ModuleImpl(name); + } + + + /** + * Build new Module object based on this builder. + */ + @Override + public Module build() { + instance.setImports(imports); + + // TYPEDEFS + final Set> typedefs = buildModuleTypedefs(addedTypedefs); + instance.setTypeDefinitions(typedefs); + + // CHILD NODES + final Map childNodes = buildModuleChildNodes(addedChilds); + instance.setChildNodes(childNodes); + + // GROUPINGS + final Set groupings = buildModuleGroupings(addedGroupings); + instance.setGroupings(groupings); + + // USES + final Set usesDefinitions = buildUsesNodes(addedUsesNodes); + instance.setUses(usesDefinitions); + + // FEATURES + final Set features = buildModuleFeatures(addedFeatures); + instance.setFeatures(features); + + // NOTIFICATIONS + final Set notifications = new HashSet(); + for (NotificationBuilder entry : addedNotifications) { + notifications.add((NotificationDefinition) entry.build()); + } + instance.setNotifications(notifications); + + // AUGMENTATIONS + instance.setAugmentations(augmentations); + + // RPCs + final Set rpcs = buildModuleRpcs(addedRpcs); + instance.setRpcs(rpcs); + + // DEVIATIONS + final Set deviations = new HashSet(); + for (Map.Entry entry : addedDeviations + .entrySet()) { + deviations.add(entry.getValue().build()); + } + instance.setDeviations(deviations); + + // EXTENSIONS + final List extensions = new ArrayList(); + for(ExtensionBuilder b : addedExtensions) { + extensions.add(b.build()); + } + instance.setExtensionSchemaNodes(extensions); + + // IDENTITIES + final Set identities = new HashSet(); + for(IdentitySchemaNodeBuilder idBuilder : addedIdentities) { + identities.add(idBuilder.build()); + } + instance.setIdentities(identities); + + return instance; + } + + public Builder getNode(List path) { + return moduleNodes.get(path); + } + + public Map, TypeAwareBuilder> getDirtyNodes() { + return dirtyNodes; + } + + public Set getAddedAugments() { + return addedAugments; + } + + public Set getAddedIdentities() { + return addedIdentities; + } + + public String getName() { + return name; + } + + public String getPrefix() { + return prefix; + } + + public Date getRevision() { + return revision; + } + + public void addDirtyNode(List path) { + List dirtyNodePath = new ArrayList(path); + TypeAwareBuilder nodeBuilder = (TypeAwareBuilder) moduleNodes + .get(dirtyNodePath); + dirtyNodes.put(dirtyNodePath, nodeBuilder); + } + + public void setNamespace(URI namespace) { + instance.setNamespace(namespace); + } + + public void setRevision(Date revision) { + this.revision = revision; + instance.setRevision(revision); + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + instance.setPrefix(prefix); + } + + public void setYangVersion(String yangVersion) { + instance.setYangVersion(yangVersion); + } + + public void setDescription(String description) { + instance.setDescription(description); + } + + public void setReference(String reference) { + instance.setReference(reference); + } + + public void setOrganization(String organization) { + instance.setOrganization(organization); + } + + public void setContact(String contact) { + instance.setContact(contact); + } + + public void setAugmentations(Set augmentations) { + this.augmentations = augmentations; + } + + public boolean addModuleImport(final String moduleName, + final Date revision, final String prefix) { + ModuleImport moduleImport = createModuleImport(moduleName, revision, + prefix); + return imports.add(moduleImport); + } + + public Set getModuleImports() { + return imports; + } + + public ExtensionBuilder addExtension(QName qname) { + return new ExtensionBuilder(qname); + } + + public ContainerSchemaNodeBuilder addContainerNode(QName containerName, + List parentPath) { + List pathToNode = new ArrayList(parentPath); + + ContainerSchemaNodeBuilder containerBuilder = new ContainerSchemaNodeBuilder( + containerName); + + ChildNodeBuilder parent = (ChildNodeBuilder) moduleNodes + .get(pathToNode); + if (parent != null) { + if(parent instanceof AugmentationSchemaBuilder) { + containerBuilder.setAugmenting(true); + } + parent.addChildNode(containerBuilder); + } + + pathToNode.add(containerName.getLocalName()); + moduleNodes.put(pathToNode, containerBuilder); + addedChilds.put(pathToNode, containerBuilder); + + return containerBuilder; + } + + public ListSchemaNodeBuilder addListNode(QName listName, + List parentPath) { + List pathToNode = new ArrayList(parentPath); + + ListSchemaNodeBuilder listBuilder = new ListSchemaNodeBuilder(listName); + + ChildNodeBuilder parent = (ChildNodeBuilder) moduleNodes + .get(pathToNode); + if (parent != null) { + if(parent instanceof AugmentationSchemaBuilder) { + listBuilder.setAugmenting(true); + } + parent.addChildNode(listBuilder); + } + + pathToNode.add(listName.getLocalName()); + moduleNodes.put(pathToNode, listBuilder); + addedChilds.put(pathToNode, listBuilder); + + return listBuilder; + } + + public LeafSchemaNodeBuilder addLeafNode(QName leafName, + List parentPath) { + List pathToNode = new ArrayList(parentPath); + + LeafSchemaNodeBuilder leafBuilder = new LeafSchemaNodeBuilder(leafName); + + ChildNodeBuilder parent = (ChildNodeBuilder) moduleNodes.get(pathToNode); + if (parent != null) { + if(parent instanceof AugmentationSchemaBuilder) { + leafBuilder.setAugmenting(true); + } + parent.addChildNode(leafBuilder); + } + + pathToNode.add(leafName.getLocalName()); + addedChilds.put(pathToNode, leafBuilder); + moduleNodes.put(pathToNode, leafBuilder); + + return leafBuilder; + } + + public LeafListSchemaNodeBuilder addLeafListNode(QName leafListName, + List parentPath) { + List pathToNode = new ArrayList(parentPath); + + LeafListSchemaNodeBuilder leafListBuilder = new LeafListSchemaNodeBuilder( + leafListName); + ChildNodeBuilder parent = (ChildNodeBuilder) moduleNodes.get(pathToNode); + if (parent != null) { + if(parent instanceof AugmentationSchemaBuilder) { + leafListBuilder.setAugmenting(true); + } + parent.addChildNode(leafListBuilder); + } + + pathToNode.add(leafListName.getLocalName()); + addedChilds.put(pathToNode, leafListBuilder); + moduleNodes.put(pathToNode, leafListBuilder); + + return leafListBuilder; + } + + public GroupingBuilder addGrouping(QName qname, List parentPath) { + List pathToGroup = new ArrayList(parentPath); + + GroupingBuilder builder = new GroupingBuilderImpl(qname); + ChildNodeBuilder parentNodeBuilder = (ChildNodeBuilder) moduleNodes.get(pathToGroup); + if (parentNodeBuilder != null) { + parentNodeBuilder.addGrouping(builder); + } + + pathToGroup.add(qname.getLocalName()); + moduleNodes.put(pathToGroup, builder); + addedGroupings.put(pathToGroup, builder); + + return builder; + } + + public AugmentationSchemaBuilder addAugment(String name, + List parentPath) { + List pathToAugment = new ArrayList(parentPath); + + AugmentationSchemaBuilder builder = new AugmentationSchemaBuilderImpl(name); + + // augment can only be in 'module' or 'uses' statement + UsesNodeBuilder parent = addedUsesNodes.get(pathToAugment); + if (parent != null) { + parent.addAugment(builder); + } + + pathToAugment.add(name); + moduleNodes.put(pathToAugment, builder); + addedAugments.add(builder); + + return builder; + } + + public UsesNodeBuilder addUsesNode(String groupingPathStr, + List parentPath) { + List pathToUses = new ArrayList(parentPath); + + UsesNodeBuilder usesBuilder = new UsesNodeBuilderImpl(groupingPathStr); + + ChildNodeBuilder parent = (ChildNodeBuilder) moduleNodes.get(pathToUses); + if (parent != null) { + parent.addUsesNode(usesBuilder); + } + + pathToUses.add(groupingPathStr); + addedUsesNodes.put(pathToUses, usesBuilder); + + return usesBuilder; + } + + public RpcDefinitionBuilder addRpc(QName qname, List parentPath) { + List pathToRpc = new ArrayList(parentPath); + + RpcDefinitionBuilder rpcBuilder = new RpcDefinitionBuilder(qname); + + pathToRpc.add(qname.getLocalName()); + addedRpcs.put(pathToRpc, rpcBuilder); + + QName inputQName = new QName(qname.getNamespace(), qname.getRevision(), + qname.getPrefix(), "input"); + ContainerSchemaNodeBuilder inputBuilder = new ContainerSchemaNodeBuilder(inputQName); + List pathToInput = new ArrayList(pathToRpc); + pathToInput.add("input"); + moduleNodes.put(pathToInput, inputBuilder); + rpcBuilder.setInput(inputBuilder); + + QName outputQName = new QName(qname.getNamespace(), + qname.getRevision(), qname.getPrefix(), "output"); + ContainerSchemaNodeBuilder outputBuilder = new ContainerSchemaNodeBuilder(outputQName); + List pathToOutput = new ArrayList(pathToRpc); + pathToOutput.add("output"); + moduleNodes.put(pathToOutput, outputBuilder); + rpcBuilder.setOutput(outputBuilder); + + return rpcBuilder; + } + + public NotificationBuilder addNotification(QName notificationName, + List parentPath) { + List pathToNotification = new ArrayList(parentPath); + + NotificationBuilder builder = new NotificationBuilder( + notificationName); + + pathToNotification.add(notificationName.getLocalName()); + moduleNodes.put(pathToNotification, builder); + addedNotifications.add(builder); + + return builder; + } + + public FeatureBuilder addFeature(QName featureName, List parentPath) { + List pathToFeature = new ArrayList(parentPath); + pathToFeature.add(featureName.getLocalName()); + + FeatureBuilder builder = new FeatureBuilder(featureName); + addedFeatures.put(pathToFeature, builder); + return builder; + } + + public TypedefBuilder addTypedef(QName typeDefName, List parentPath) { + List pathToType = new ArrayList(parentPath); + TypedefBuilder builder = new TypedefBuilder(typeDefName); + TypeDefinitionAwareBuilder parent = (TypeDefinitionAwareBuilder) moduleNodes.get(pathToType); + if (parent != null) { + parent.addTypedef(builder); + } + pathToType.add(typeDefName.getLocalName()); + addedTypedefs.put(pathToType, builder); + moduleNodes.put(pathToType, builder); + return builder; + } + + public Set getModuleTypedefs() { + Set typedefs = new HashSet(); + for (Map.Entry, TypeDefinitionBuilder> entry : addedTypedefs.entrySet()) { + if (entry.getKey().size() == 2) { + typedefs.add(entry.getValue()); + } + } + return typedefs; + } + + public void setType(TypeDefinition type, List parentPath) { + TypeAwareBuilder parent = (TypeAwareBuilder) moduleNodes.get(parentPath); + if(parent == null) { + throw new YangParseException("Failed to set type '"+ type.getQName().getLocalName() +"'. Parent node not found."); + } + parent.setType(type); + } + + public void addUnionType(List parentPath) { + TypeAwareBuilder parent = (TypeAwareBuilder) moduleNodes.get(parentPath); + UnionTypeBuilder union = new UnionTypeBuilder(); + parent.setType(union); + + List path = new ArrayList(parentPath); + path.add("union"); + + moduleNodes.put(path, union); + } + + public DeviationBuilder addDeviation(String targetPath) { + DeviationBuilder builder = new DeviationBuilder(targetPath); + addedDeviations.put(targetPath, builder); + return builder; + } + + public IdentitySchemaNodeBuilder addIdentity(QName qname) { + IdentitySchemaNodeBuilder builder = new IdentitySchemaNodeBuilder(qname); + addedIdentities.add(builder); + return builder; + } + + public void addConfiguration(boolean configuration, List parentPath) { + Builder builder = moduleNodes.get(parentPath); + if (builder instanceof DeviationBuilder) { + // skip + // TODO + } else { + DataSchemaNodeBuilder configBuilder = (DataSchemaNodeBuilder) moduleNodes.get(parentPath); + configBuilder.setConfiguration(configuration); + } + } + + public UnknownSchemaNodeBuilder addUnknownSchemaNode(QName qname, List parentPath) { + return new UnknownSchemaNodeBuilder(qname); + } + + + private class ModuleImpl implements Module { + private URI namespace; + private final String name; + private Date revision; + private String prefix; + private String yangVersion; + private String description; + private String reference; + private String organization; + private String contact; + private Set imports = Collections.emptySet(); + private Set features = Collections.emptySet(); + private Set> typeDefinitions = Collections.emptySet(); + private Set notifications = Collections.emptySet(); + private Set augmentations = Collections.emptySet(); + private Set rpcs = Collections.emptySet(); + private Set deviations = Collections.emptySet(); + private Map childNodes = Collections.emptyMap(); + private Set groupings = Collections.emptySet(); + private Set uses = Collections.emptySet(); + private List extensionNodes = Collections.emptyList(); + private Set identities = Collections.emptySet(); + + private ModuleImpl(String name) { + this.name = name; + } + + @Override + public URI getNamespace() { + return namespace; + } + + private void setNamespace(URI namespace) { + this.namespace = namespace; + } + + @Override + public String getName() { + return name; + } + + @Override + public Date getRevision() { + return revision; + } + + private void setRevision(Date revision) { + this.revision = revision; + } + + @Override + public String getPrefix() { + return prefix; + } + + private void setPrefix(String prefix) { + this.prefix = prefix; + } + + @Override + public String getYangVersion() { + return yangVersion; + } + + private void setYangVersion(String yangVersion) { + this.yangVersion = yangVersion; + } + + @Override + public String getDescription() { + return description; + } + + private void setDescription(String description) { + this.description = description; + } + + @Override + public String getReference() { + return reference; + } + + private void setReference(String reference) { + this.reference = reference; + } + + @Override + public String getOrganization() { + return organization; + } + + private void setOrganization(String organization) { + this.organization = organization; + } + + @Override + public String getContact() { + return contact; + } + + private void setContact(String contact) { + this.contact = contact; + } + + @Override + public Set getImports() { + return imports; + } + + private void setImports(Set imports) { + if(imports != null) { + this.imports = imports; + } + } + + @Override + public Set getFeatures() { + return features; + } + + private void setFeatures(Set features) { + if(features != null) { + this.features = features; + } + } + + @Override + public Set> getTypeDefinitions() { + return typeDefinitions; + } + + private void setTypeDefinitions(Set> typeDefinitions) { + if(typeDefinitions != null) { + this.typeDefinitions = typeDefinitions; + } + } + + @Override + public Set getNotifications() { + return notifications; + } + + private void setNotifications(Set notifications) { + if(notifications != null) { + this.notifications = notifications; + } + } + + @Override + public Set getAugmentations() { + return augmentations; + } + + private void setAugmentations(Set augmentations) { + if(augmentations != null) { + this.augmentations = augmentations; + } + } + + @Override + public Set getRpcs() { + return rpcs; + } + + private void setRpcs(Set rpcs) { + if(rpcs != null) { + this.rpcs = rpcs; + } + } + + @Override + public Set getDeviations() { + return deviations; + } + + private void setDeviations(Set deviations) { + if(deviations != null) { + this.deviations = deviations; + } + } + + @Override + public Set getChildNodes() { + return new HashSet(childNodes.values()); + } + + private void setChildNodes(Map childNodes) { + if(childNodes != null) { + this.childNodes = childNodes; + } + } + + @Override + public Set getGroupings() { + return groupings; + } + + private void setGroupings(Set groupings) { + if(groupings != null) { + this.groupings = groupings; + } + } + + @Override + public Set getUses() { + return uses; + } + + private void setUses(Set uses) { + if(uses != null) { + this.uses = uses; + } + } + + @Override + public List getExtensionSchemaNodes() { + return extensionNodes; + } + + private void setExtensionSchemaNodes(List extensionSchemaNodes) { + if(extensionSchemaNodes != null) { + this.extensionNodes = extensionSchemaNodes; + } + } + + @Override + public Set getIdentities() { + return identities; + } + + private void setIdentities(Set identities) { + if(identities != null) { + this.identities = identities; + } + } + + @Override + public DataSchemaNode getDataChildByName(QName name) { + return childNodes.get(name); + } + + @Override + public DataSchemaNode getDataChildByName(String name) { + DataSchemaNode result = null; + for (Map.Entry entry : childNodes.entrySet()) { + if (entry.getKey().getLocalName().equals(name)) { + result = entry.getValue(); + break; + } + } + return result; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((namespace == null) ? 0 : namespace.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((revision == null) ? 0 : revision.hashCode()); + result = prime * result + ((prefix == null) ? 0 : prefix.hashCode()); + result = prime * result + ((yangVersion == null) ? 0 : yangVersion.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ModuleImpl other = (ModuleImpl) obj; + if (namespace == null) { + if (other.namespace != null) { + return false; + } + } else if (!namespace.equals(other.namespace)) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + if (revision == null) { + if (other.revision != null) { + return false; + } + } else if (!revision.equals(other.revision)) { + return false; + } + if (prefix == null) { + if (other.prefix != null) { + return false; + } + } else if (!prefix.equals(other.prefix)) { + return false; + } + if (yangVersion == null) { + if (other.yangVersion != null) { + return false; + } + } else if (!yangVersion.equals(other.yangVersion)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder( + ModuleImpl.class.getSimpleName()); + sb.append("[\n"); + sb.append("name=" + name + ",\n"); + sb.append("namespace=" + namespace + ",\n"); + sb.append("revision=" + revision + ",\n"); + sb.append("prefix=" + prefix + ",\n"); + sb.append("yangVersion=" + yangVersion + ",\n"); + sb.append("description=" + description + ",\n"); + sb.append("reference=" + reference + ",\n"); + sb.append("organization=" + organization + ",\n"); + sb.append("contact=" + contact + ",\n"); + sb.append("childNodes=" + childNodes.values() + ",\n"); + sb.append("groupings=" + groupings + ",\n"); + sb.append("imports=" + imports + ",\n"); + sb.append("features=" + features + ",\n"); + sb.append("typeDefinitions=" + typeDefinitions + ",\n"); + sb.append("notifications=" + notifications + ",\n"); + sb.append("augmentations=" + augmentations + ",\n"); + sb.append("rpcs=" + rpcs + ",\n"); + sb.append("deviations=" + deviations + "\n"); + sb.append("uses=" + uses + "\n"); + sb.append("]"); + return sb.toString(); + } + } + + private ModuleImport createModuleImport(final String moduleName, + final Date revision, final String prefix) { + ModuleImport moduleImport = new ModuleImport() { + @Override + public String getModuleName() { + return moduleName; + } + + @Override + public Date getRevision() { + return revision; + } + + @Override + public String getPrefix() { + return prefix; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((moduleName == null) ? 0 : moduleName.hashCode()); + result = prime * result + + ((revision == null) ? 0 : revision.hashCode()); + result = prime * result + + ((prefix == null) ? 0 : prefix.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ModuleImport other = (ModuleImport) obj; + if (getModuleName() == null) { + if (other.getModuleName() != null) { + return false; + } + } else if (!getModuleName().equals(other.getModuleName())) { + return false; + } + if (getRevision() == null) { + if (other.getRevision() != null) { + return false; + } + } else if (!getRevision().equals(other.getRevision())) { + return false; + } + if (getPrefix() == null) { + if (other.getPrefix() != null) { + return false; + } + } else if (!getPrefix().equals(other.getPrefix())) { + return false; + } + return true; + } + + @Override + public String toString() { + return "ModuleImport[moduleName=" + moduleName + ", revision=" + + revision + ", prefix=" + prefix + "]"; + } + }; + return moduleImport; + } + + /** + * Traverse through given addedChilds and add only direct module childs. + * Direct module child path size is 2 (1. module name, 2. child name). + * + * @param addedChilds + * @return map of children, where key is child QName and value is child + * itself + */ + private Map buildModuleChildNodes( + Map, DataSchemaNodeBuilder> addedChilds) { + final Map childNodes = new HashMap(); + for (Map.Entry, DataSchemaNodeBuilder> entry : addedChilds.entrySet()) { + List path = entry.getKey(); + DataSchemaNodeBuilder child = entry.getValue(); + if (path.size() == 2) { + DataSchemaNode node = child.build(); + QName qname = node.getQName(); + childNodes.put(qname, node); + } + } + return childNodes; + } + + /** + * Traverse through given addedGroupings and add only direct module + * groupings. Direct module grouping path size is 2 (1. module name, 2. + * grouping name). + * + * @param addedGroupings + * @return set of built GroupingDefinition objects + */ + private Set buildModuleGroupings( + Map, GroupingBuilder> addedGroupings) { + final Set groupings = new HashSet(); + for (Map.Entry, GroupingBuilder> entry : addedGroupings + .entrySet()) { + if (entry.getKey().size() == 2) { + groupings.add(entry.getValue().build()); + } + } + return groupings; + } + + /** + * Traverse through given addedRpcs and build RpcDefinition objects. + * + * @param addedRpcs + * @return set of built RpcDefinition objects + */ + private Set buildModuleRpcs( + Map, RpcDefinitionBuilder> addedRpcs) { + final Set rpcs = new HashSet(); + RpcDefinitionBuilder builder; + for (Map.Entry, RpcDefinitionBuilder> entry : addedRpcs + .entrySet()) { + builder = entry.getValue(); + RpcDefinition rpc = builder.build(); + rpcs.add(rpc); + } + return rpcs; + } + + /** + * Traverse through given addedTypedefs and add only direct module typedef + * statements. Direct module typedef path size is 2 (1. module name, 2. + * typedef name). + * + * @param addedTypedefs + * @return set of built module typedef statements + */ + private Set> buildModuleTypedefs( + Map, TypeDefinitionBuilder> addedTypedefs) { + Set> typedefs = new HashSet>(); + for (Map.Entry, TypeDefinitionBuilder> entry : addedTypedefs.entrySet()) { + List key = entry.getKey(); + TypeDefinitionBuilder typedefBuilder = entry.getValue(); + if (key.size() == 2) { + TypeDefinition> node = typedefBuilder.build(); + typedefs.add(node); + } + } + return typedefs; + } + + /** + * Traverse through given addedUsesNodes and add only direct module uses + * nodes. Direct module uses node path size is 2 (1. module name, 2. uses + * name). + * + * @param addedUsesNodes + * @return set of built module uses nodes + */ + private Set buildUsesNodes( + Map, UsesNodeBuilder> addedUsesNodes) { + final Set usesNodeDefinitions = new HashSet(); + for (Map.Entry, UsesNodeBuilder> entry : addedUsesNodes + .entrySet()) { + if (entry.getKey().size() == 2) { + usesNodeDefinitions.add(entry.getValue().build()); + } + } + return usesNodeDefinitions; + } + + /** + * Traverse through given addedFeatures and add only direct module features. + * Direct module feature path size is 2 (1. module name, 2. feature name). + * + * @param addedFeatures + * @return set of built module features + */ + private Set buildModuleFeatures( + Map, FeatureBuilder> addedFeatures) { + Set features = new HashSet(); + for (Map.Entry, FeatureBuilder> entry : addedFeatures + .entrySet()) { + if (entry.getKey().size() == 2) { + features.add(entry.getValue().build()); + } + } + return features; + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/TypedefBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/TypedefBuilder.java index f8020b1524..64df8c265a 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/TypedefBuilder.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/TypedefBuilder.java @@ -7,6 +7,7 @@ */ package org.opendaylight.controller.yang.model.parser.builder.impl; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -15,18 +16,25 @@ import org.opendaylight.controller.yang.model.api.SchemaPath; import org.opendaylight.controller.yang.model.api.Status; import org.opendaylight.controller.yang.model.api.TypeDefinition; import org.opendaylight.controller.yang.model.api.UnknownSchemaNode; -import org.opendaylight.controller.yang.model.parser.builder.api.SchemaNodeBuilder; -import org.opendaylight.controller.yang.model.parser.builder.api.TypeAwareBuilder; +import org.opendaylight.controller.yang.model.api.type.LengthConstraint; +import org.opendaylight.controller.yang.model.api.type.PatternConstraint; +import org.opendaylight.controller.yang.model.api.type.RangeConstraint; +import org.opendaylight.controller.yang.model.parser.builder.api.AbstractTypeAwareBuilder; import org.opendaylight.controller.yang.model.parser.builder.api.TypeDefinitionBuilder; +import org.opendaylight.controller.yang.model.parser.util.YangParseException; +import org.opendaylight.controller.yang.model.util.ExtendedType; import org.opendaylight.controller.yang.model.util.UnknownType; -import org.opendaylight.controller.yang.model.util.YangTypesConverter; - -public class TypedefBuilder implements TypeDefinitionBuilder, - SchemaNodeBuilder, TypeAwareBuilder { +public class TypedefBuilder extends AbstractTypeAwareBuilder implements + TypeDefinitionBuilder { private final QName qname; private SchemaPath schemaPath; - private TypeDefinition baseType; + + private final List addedUnknownNodes = new ArrayList(); + private List ranges = Collections.emptyList(); + private List lengths = Collections.emptyList(); + private List patterns = Collections.emptyList(); + private Integer fractionDigits = null; private String description; private String reference; @@ -34,36 +42,41 @@ public class TypedefBuilder implements TypeDefinitionBuilder, private String units; private Object defaultValue; - TypedefBuilder(QName qname) { + public TypedefBuilder(QName qname) { this.qname = qname; } @Override public TypeDefinition> build() { - final TypeDefinition type = YangTypesConverter - .javaTypeForBaseYangType(qname); - if (type != null) { - return type; + TypeDefinition result = null; + ExtendedType.Builder typeBuilder = null; + if ((type == null || type instanceof UnknownType) && typedef == null) { + throw new YangParseException("Unresolved type: '" + + qname.getLocalName() + "'."); + } + if (type == null || type instanceof UnknownType) { + typeBuilder = new ExtendedType.Builder(qname, typedef.build(), + description, reference); } else { - if (baseType != null) { - // typedef - TypeDefinitionImpl instance = new TypeDefinitionImpl(qname); - instance.setDescription(description); - instance.setReference(reference); - instance.setStatus(status); - instance.setPath(schemaPath); - instance.setBaseType(baseType); - instance.setUnits(units); - instance.setDefaultValue(defaultValue); - return instance; - } else { - // type - final UnknownType.Builder unknownBuilder = new UnknownType.Builder( - qname, description, reference); - unknownBuilder.status(status); - return unknownBuilder.build(); - } + typeBuilder = new ExtendedType.Builder(qname, type, description, + reference); + } + typeBuilder.status(status); + typeBuilder.units(units); + typeBuilder.defaultValue(defaultValue); + + typeBuilder.ranges(ranges); + typeBuilder.lengths(lengths); + typeBuilder.patterns(patterns); + + // UNKNOWN NODES + final List unknownNodes = new ArrayList(); + for (UnknownSchemaNodeBuilder b : addedUnknownNodes) { + unknownNodes.add(b.build()); } + typeBuilder.unknownSchemaNodes(unknownNodes); + result = typeBuilder.build(); + return result; } @Override @@ -71,21 +84,41 @@ public class TypedefBuilder implements TypeDefinitionBuilder, return qname; } + @Override + public SchemaPath getPath() { + return schemaPath; + } + @Override public void setPath(final SchemaPath schemaPath) { this.schemaPath = schemaPath; } + @Override + public String getDescription() { + return description; + } + @Override public void setDescription(final String description) { this.description = description; } + @Override + public String getReference() { + return reference; + } + @Override public void setReference(final String reference) { this.reference = reference; } + @Override + public Status getStatus() { + return status; + } + @Override public void setStatus(final Status status) { if (status != null) { @@ -93,221 +126,93 @@ public class TypedefBuilder implements TypeDefinitionBuilder, } } + @Override + public String getUnits() { + return units; + } + @Override public void setUnits(String units) { this.units = units; } @Override - public void setDefaultValue(Object defaultValue) { - this.defaultValue = defaultValue; + public Object getDefaultValue() { + return defaultValue; } @Override - public TypeDefinition getType() { - return baseType; + public void setDefaultValue(Object defaultValue) { + this.defaultValue = defaultValue; } @Override - public void setType(TypeDefinition baseType) { - this.baseType = baseType; + public List getUnknownNodes() { + return addedUnknownNodes; } @Override - public TypeDefinition getBaseType() { - return baseType; + public void addUnknownSchemaNode(UnknownSchemaNodeBuilder unknownNode) { + addedUnknownNodes.add(unknownNode); } @Override - public void addUnknownSchemaNode(UnknownSchemaNodeBuilder unknownSchemaNodeBuilder) { - // TODO + public List getRanges() { + return ranges; } - private static class TypeDefinitionImpl> - implements TypeDefinition { - - private final QName qname; - private SchemaPath path; - private String description; - private String reference; - private Status status = Status.CURRENT; - private Object defaultValue; - private T baseType; - private String units; - private List unknownSchemaNodes = Collections.emptyList(); - - private TypeDefinitionImpl(QName qname) { - this.qname = qname; - } - - @Override - public QName getQName() { - return qname; - } - - @Override - public SchemaPath getPath() { - return path; - } - - private void setPath(SchemaPath path) { - this.path = path; - } - - @Override - public String getDescription() { - return description; - } - - private void setDescription(String description) { - this.description = description; - } - - @Override - public String getReference() { - return reference; - } - - private void setReference(String reference) { - this.reference = reference; - } - - @Override - public Status getStatus() { - return status; - } - - private void setStatus(Status status) { - this.status = status; - } - - @Override - public T getBaseType() { - return baseType; - } - - private void setBaseType(T type) { - this.baseType = type; - } - - @Override - public String getUnits() { - return units; + @Override + public void setRanges(List ranges) { + if (ranges != null) { + this.ranges = ranges; } + } - private void setUnits(String units) { - this.units = units; - } + @Override + public List getLengths() { + return lengths; + } - @Override - public Object getDefaultValue() { - return defaultValue; + @Override + public void setLengths(List lengths) { + if (lengths != null) { + this.lengths = lengths; } + } - private void setDefaultValue(Object defaultValue) { - this.defaultValue = defaultValue; - } + @Override + public List getPatterns() { + return patterns; + } - @Override - public List getUnknownSchemaNodes() { - return unknownSchemaNodes; + @Override + public void setPatterns(List patterns) { + if (patterns != null) { + this.patterns = patterns; } + } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((qname == null) ? 0 : qname.hashCode()); - result = prime * result + ((path == null) ? 0 : path.hashCode()); - result = prime * result - + ((description == null) ? 0 : description.hashCode()); - result = prime * result - + ((reference == null) ? 0 : reference.hashCode()); - result = prime * result - + ((status == null) ? 0 : status.hashCode()); - result = prime * result - + ((baseType == null) ? 0 : baseType.hashCode()); - result = prime * result + ((units == null) ? 0 : units.hashCode()); - return result; - } + @Override + public Integer getFractionDigits() { + return fractionDigits; + } - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - TypeDefinitionImpl other = (TypeDefinitionImpl) obj; - if (qname == null) { - if (other.qname != null) { - return false; - } - } else if (!qname.equals(other.qname)) { - return false; - } - if (path == null) { - if (other.path != null) { - return false; - } - } else if (!path.equals(other.path)) { - return false; - } - if (description == null) { - if (other.description != null) { - return false; - } - } else if (!description.equals(other.description)) { - return false; - } - if (reference == null) { - if (other.reference != null) { - return false; - } - } else if (!reference.equals(other.reference)) { - return false; - } - if (status == null) { - if (other.status != null) { - return false; - } - } else if (!status.equals(other.status)) { - return false; - } - if (baseType == null) { - if (other.baseType != null) { - return false; - } - } else if (!baseType.equals(other.baseType)) { - return false; - } - if (units == null) { - if (other.units != null) { - return false; - } - } else if (!units.equals(other.units)) { - return false; - } - return true; - } + @Override + public void setFractionDigits(Integer fractionDigits) { + this.fractionDigits = fractionDigits; + } - @Override - public String toString() { - final StringBuilder sb = new StringBuilder( - TypeDefinitionImpl.class.getSimpleName()); - sb.append("["); - sb.append("qname=" + qname); - sb.append(", path=" + path); - sb.append(", description=" + description); - sb.append(", reference=" + reference); - sb.append(", status=" + status); - sb.append(", baseType=" + baseType + "]"); - return sb.toString(); + @Override + public String toString() { + String result = "TypedefBuilder[" + qname.getLocalName(); + result += ", type="; + if (type == null) { + result += typedef; + } else { + result += type; } + result += "]"; + return result; } } diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/UnionTypeBuilder.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/UnionTypeBuilder.java index 4e0cb506f2..697fb399b0 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/UnionTypeBuilder.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/builder/impl/UnionTypeBuilder.java @@ -8,17 +8,29 @@ package org.opendaylight.controller.yang.model.parser.builder.impl; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; import org.opendaylight.controller.yang.model.api.TypeDefinition; +import org.opendaylight.controller.yang.model.api.type.LengthConstraint; +import org.opendaylight.controller.yang.model.api.type.PatternConstraint; +import org.opendaylight.controller.yang.model.api.type.RangeConstraint; +import org.opendaylight.controller.yang.model.parser.builder.api.AbstractTypeAwareBuilder; import org.opendaylight.controller.yang.model.parser.builder.api.Builder; -import org.opendaylight.controller.yang.model.parser.builder.api.TypeAwareBuilder; import org.opendaylight.controller.yang.model.parser.builder.api.TypeDefinitionBuilder; import org.opendaylight.controller.yang.model.util.UnionType; -public class UnionTypeBuilder implements TypeAwareBuilder, TypeDefinitionBuilder, Builder { - +/** + * Builder for YANG union type. User can add type to this union as + * TypeDefinition object (resolved type) or in form of TypeDefinitionBuilder. + * When build is called, types in builder form will be transformed to + * TypeDefinition objects and add to resolved types. + */ +public class UnionTypeBuilder extends AbstractTypeAwareBuilder implements + TypeDefinitionBuilder, Builder { private final List> types; private final List typedefs; private final UnionType instance; @@ -35,7 +47,16 @@ public class UnionTypeBuilder implements TypeAwareBuilder, TypeDefinitionBuilder @Override public TypeDefinition getType() { - return instance; + return null; + } + + public List getTypedefs() { + return Collections.unmodifiableList(typedefs); + } + + @Override + public TypeDefinitionBuilder getTypedef() { + return null; } @Override @@ -43,18 +64,45 @@ public class UnionTypeBuilder implements TypeAwareBuilder, TypeDefinitionBuilder types.add(type); } - public void addType(TypeDefinitionBuilder tdb) { + @Override + public void setType(TypeDefinitionBuilder tdb) { typedefs.add(tdb); } @Override public UnionType build() { - for(TypeDefinitionBuilder tdb : typedefs) { + for (TypeDefinitionBuilder tdb : typedefs) { types.add(tdb.build()); } return instance; } + @Override + public void setPath(SchemaPath schemaPath) { + // TODO Auto-generated method stub + } + + @Override + public void setDescription(String description) { + // TODO Auto-generated method stub + } + + @Override + public void setReference(String reference) { + // TODO Auto-generated method stub + } + + @Override + public void setStatus(Status status) { + // TODO Auto-generated method stub + } + + @Override + public void addUnknownSchemaNode( + UnknownSchemaNodeBuilder unknownSchemaNodeBuilder) { + // TODO Auto-generated method stub + } + @Override public QName getQName() { // TODO Auto-generated method stub @@ -62,21 +110,108 @@ public class UnionTypeBuilder implements TypeAwareBuilder, TypeDefinitionBuilder } @Override - public TypeDefinition getBaseType() { + public SchemaPath getPath() { // TODO Auto-generated method stub return null; } @Override - public void setUnits(String units) { + public String getDescription() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getReference() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Status getStatus() { + // TODO Auto-generated method stub + return null; + } + + @Override + public List getRanges() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setRanges(List ranges) { + // TODO Auto-generated method stub + } + + @Override + public List getLengths() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setLengths(List lengths) { + // TODO Auto-generated method stub + } + + @Override + public List getPatterns() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setPatterns(List patterns) { + // TODO Auto-generated method stub + } + + @Override + public Integer getFractionDigits() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setFractionDigits(Integer fractionDigits) { // TODO Auto-generated method stub + } + @Override + public List getUnknownNodes() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Object getDefaultValue() { + // TODO Auto-generated method stub + return null; } @Override public void setDefaultValue(Object defaultValue) { // TODO Auto-generated method stub + } + + @Override + public String getUnits() { + // TODO Auto-generated method stub + return null; + } + @Override + public void setUnits(String units) { + // TODO Auto-generated method stub + } + + @Override + public String toString() { + String result = "UnionTypeBuilder["; + result += ", types=" + types; + result += ", typedefs=" + typedefs; + result += "]"; + return result; } } diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserImpl.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserImpl.java index 5cc9f8e4aa..27a65c1168 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserImpl.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserImpl.java @@ -1,812 +1,788 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.yang.model.parser.impl; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; - -import org.antlr.v4.runtime.ANTLRInputStream; -import org.antlr.v4.runtime.CommonTokenStream; -import org.antlr.v4.runtime.tree.ParseTree; -import org.antlr.v4.runtime.tree.ParseTreeWalker; -import org.opendaylight.controller.antlrv4.code.gen.YangLexer; -import org.opendaylight.controller.antlrv4.code.gen.YangParser; -import org.opendaylight.controller.yang.common.QName; -import org.opendaylight.controller.yang.model.api.AugmentationSchema; -import org.opendaylight.controller.yang.model.api.DataSchemaNode; -import org.opendaylight.controller.yang.model.api.ExtensionDefinition; -import org.opendaylight.controller.yang.model.api.Module; -import org.opendaylight.controller.yang.model.api.ModuleImport; -import org.opendaylight.controller.yang.model.api.NotificationDefinition; -import org.opendaylight.controller.yang.model.api.RpcDefinition; -import org.opendaylight.controller.yang.model.api.SchemaContext; -import org.opendaylight.controller.yang.model.api.SchemaPath; -import org.opendaylight.controller.yang.model.api.TypeDefinition; -import org.opendaylight.controller.yang.model.api.type.BinaryTypeDefinition; -import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition; -import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition.Bit; -import org.opendaylight.controller.yang.model.api.type.DecimalTypeDefinition; -import org.opendaylight.controller.yang.model.api.type.IntegerTypeDefinition; -import org.opendaylight.controller.yang.model.api.type.LengthConstraint; -import org.opendaylight.controller.yang.model.api.type.PatternConstraint; -import org.opendaylight.controller.yang.model.api.type.RangeConstraint; -import org.opendaylight.controller.yang.model.api.type.StringTypeDefinition; -import org.opendaylight.controller.yang.model.parser.api.YangModelParser; -import org.opendaylight.controller.yang.model.parser.builder.api.AugmentationSchemaBuilder; -import org.opendaylight.controller.yang.model.parser.builder.api.AugmentationTargetBuilder; -import org.opendaylight.controller.yang.model.parser.builder.api.ChildNodeBuilder; -import org.opendaylight.controller.yang.model.parser.builder.api.DataSchemaNodeBuilder; -import org.opendaylight.controller.yang.model.parser.builder.api.TypeAwareBuilder; -import org.opendaylight.controller.yang.model.parser.builder.api.TypeDefinitionBuilder; -import org.opendaylight.controller.yang.model.parser.builder.impl.IdentitySchemaNodeBuilder; -import org.opendaylight.controller.yang.model.parser.builder.impl.ModuleBuilder; -import org.opendaylight.controller.yang.model.parser.builder.impl.UnionTypeBuilder; -import org.opendaylight.controller.yang.model.util.BaseConstraints; -import org.opendaylight.controller.yang.model.util.BinaryType; -import org.opendaylight.controller.yang.model.util.BitsType; -import org.opendaylight.controller.yang.model.util.StringType; -import org.opendaylight.controller.yang.model.util.UnknownType; -import org.opendaylight.controller.yang.model.util.YangTypesConverter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class YangModelParserImpl implements YangModelParser { - - private static final Logger logger = LoggerFactory - .getLogger(YangModelParserImpl.class); - - @Override - public Module parseYangModel(String yangFile) { - final Map> modules = resolveModuleBuildersFromStreams(yangFile); - Set result = build(modules); - return result.iterator().next(); - } - - @Override - public Set parseYangModels(String... yangFiles) { - final Map> modules = resolveModuleBuildersFromStreams(yangFiles); - Set result = build(modules); - return result; - } - - @Override - public Set parseYangModelsFromStreams( - InputStream... yangModelStreams) { - final Map> modules = resolveModuleBuildersFromStreams(yangModelStreams); - Set result = build(modules); - return result; - } - - @Override - public SchemaContext resolveSchemaContext(Set modules) { - return new SchemaContextImpl(modules); - } - - private Map> resolveModuleBuildersFromStreams( - String... yangFiles) { - InputStream[] streams = new InputStream[yangFiles.length]; - for (int i = 0; i < yangFiles.length; i++) { - final String yangFileName = yangFiles[i]; - final File yangFile = new File(yangFileName); - FileInputStream inStream = null; - try { - inStream = new FileInputStream(yangFile); - } catch (FileNotFoundException e) { - logger.warn("Exception while reading yang stream: " + inStream, - e); - } - streams[i] = inStream; - } - return resolveModuleBuildersFromStreams(streams); - } - - private Map> resolveModuleBuildersFromStreams( - InputStream... yangFiles) { - final Map> modules = new HashMap>(); - final ParseTreeWalker walker = new ParseTreeWalker(); - final List trees = parseStreams(yangFiles); - final ModuleBuilder[] builders = new ModuleBuilder[trees.size()]; - - for (int i = 0; i < trees.size(); i++) { - final YangModelParserListenerImpl yangModelParser = new YangModelParserListenerImpl(); - walker.walk(yangModelParser, trees.get(i)); - builders[i] = yangModelParser.getModuleBuilder(); - } - - for (ModuleBuilder builder : builders) { - final String builderName = builder.getName(); - Date builderRevision = builder.getRevision(); - if (builderRevision == null) { - builderRevision = createEpochTime(); - } - TreeMap builderByRevision = modules - .get(builderName); - if (builderByRevision == null) { - builderByRevision = new TreeMap(); - } - builderByRevision.put(builderRevision, builder); - modules.put(builderName, builderByRevision); - } - return modules; - } - - private List parseStreams(InputStream... yangStreams) { - List trees = new ArrayList(); - for (InputStream yangStream : yangStreams) { - trees.add(parseStream(yangStream)); - } - return trees; - } - - private ParseTree parseStream(InputStream yangStream) { - ParseTree result = null; - try { - final ANTLRInputStream input = new ANTLRInputStream(yangStream); - final YangLexer lexer = new YangLexer(input); - final CommonTokenStream tokens = new CommonTokenStream(lexer); - final YangParser parser = new YangParser(tokens); - result = parser.yang(); - } catch (IOException e) { - logger.warn("Exception while reading yang file: " + yangStream, e); - } - return result; - } - - private Set build(Map> modules) { - // first validate - for (Map.Entry> entry : modules - .entrySet()) { - for (Map.Entry childEntry : entry.getValue() - .entrySet()) { - ModuleBuilder moduleBuilder = childEntry.getValue(); - validateBuilder(modules, moduleBuilder); - } - } - // then build - final Set result = new HashSet(); - for (Map.Entry> entry : modules - .entrySet()) { - final Map modulesByRevision = new HashMap(); - for (Map.Entry childEntry : entry.getValue() - .entrySet()) { - ModuleBuilder moduleBuilder = childEntry.getValue(); - modulesByRevision.put(childEntry.getKey(), - moduleBuilder.build()); - result.add(moduleBuilder.build()); - } - } - - return result; - } - - private void validateBuilder( - Map> modules, - ModuleBuilder builder) { - resolveTypedefs(modules, builder); - resolveAugments(modules, builder); - resolveIdentities(modules, builder); - } - - /** - * Search for dirty nodes (node which contains UnknownType) and resolve - * unknown types. - * - * @param modules - * all available modules - * @param module - * current module - */ - private void resolveTypedefs( - Map> modules, - ModuleBuilder module) { - Map, TypeAwareBuilder> dirtyNodes = module.getDirtyNodes(); - if (dirtyNodes.size() == 0) { - return; - } else { - for (Map.Entry, TypeAwareBuilder> entry : dirtyNodes - .entrySet()) { - TypeAwareBuilder typeToResolve = entry.getValue(); - - if (typeToResolve instanceof UnionTypeBuilder) { - resolveUnionTypeBuilder(modules, module, - (UnionTypeBuilder) typeToResolve); - } else { - UnknownType ut = (UnknownType) typeToResolve.getType(); - TypeDefinition resolvedType = findTargetType(ut, - modules, module); - typeToResolve.setType(resolvedType); - } - } - } - } - - private UnionTypeBuilder resolveUnionTypeBuilder( - Map> modules, - ModuleBuilder builder, UnionTypeBuilder unionTypeBuilderToResolve) { - List> resolvedTypes = new ArrayList>(); - List> typesToRemove = new ArrayList>(); - - for (TypeDefinition td : unionTypeBuilderToResolve.getTypes()) { - if (td instanceof UnknownType) { - TypeDefinition resolvedType = findTargetType( - (UnknownType) td, modules, builder); - resolvedTypes.add(resolvedType); - typesToRemove.add(td); - } - } - - List> unionTypeBuilderTypes = unionTypeBuilderToResolve - .getTypes(); - unionTypeBuilderTypes.addAll(resolvedTypes); - unionTypeBuilderTypes.removeAll(typesToRemove); - - return unionTypeBuilderToResolve; - } - - private TypeDefinition findTargetType(UnknownType ut, - Map> modules, - ModuleBuilder builder) { - - Map foundedTypeDefinitionBuilder = findTypeDefinitionBuilderWithConstraints( - modules, ut, builder); - TypeDefinitionBuilder targetType = foundedTypeDefinitionBuilder - .entrySet().iterator().next().getKey(); - TypeConstraints constraints = foundedTypeDefinitionBuilder.entrySet() - .iterator().next().getValue(); - - TypeDefinition targetTypeBaseType = targetType.getBaseType(); - - // RANGE - List ranges = ut.getRangeStatements(); - resolveRanges(ranges, targetType, modules, builder); - // LENGTH - List lengths = ut.getLengthStatements(); - resolveLengths(lengths, targetType, modules, builder); - // PATTERN - List patterns = ut.getPatterns(); - // Fraction Digits - Integer fractionDigits = ut.getFractionDigits(); - - targetTypeBaseType = mergeConstraints(targetTypeBaseType, constraints, ranges, lengths, - patterns, fractionDigits); - - return targetTypeBaseType; - } - - /** - * Merge curent constraints with founded type constraints - * - * @param targetTypeBaseType - * @param constraints - * @param ranges - * @param lengths - * @param patterns - * @param fractionDigits - */ - private TypeDefinition mergeConstraints(TypeDefinition targetTypeBaseType, - TypeConstraints constraints, List ranges, - List lengths, List patterns, - Integer fractionDigits) { - String targetTypeBaseTypeName = targetTypeBaseType.getQName() - .getLocalName(); - // enumeration, leafref and identityref omitted because they have no - // restrictions - if (targetTypeBaseType instanceof DecimalTypeDefinition) { - List fullRanges = new ArrayList(); - fullRanges.addAll(constraints.getRanges()); - fullRanges.addAll(ranges); - Integer fd = fractionDigits == null ? constraints - .getFractionDigits() : fractionDigits; - targetTypeBaseType = YangTypesConverter - .javaTypeForBaseYangDecimal64Type(fullRanges, fd); - } else if (targetTypeBaseType instanceof IntegerTypeDefinition) { - List fullRanges = new ArrayList(); - fullRanges.addAll(constraints.getRanges()); - fullRanges.addAll(ranges); - if (targetTypeBaseTypeName.startsWith("int")) { - targetTypeBaseType = YangTypesConverter - .javaTypeForBaseYangSignedIntegerType( - targetTypeBaseTypeName, fullRanges); - } else { - targetTypeBaseType = YangTypesConverter - .javaTypeForBaseYangUnsignedIntegerType( - targetTypeBaseTypeName, fullRanges); - } - } else if (targetTypeBaseType instanceof StringTypeDefinition) { - List fullLengths = new ArrayList(); - fullLengths.addAll(constraints.getLengths()); - fullLengths.addAll(lengths); - List fullPatterns = new ArrayList(); - fullPatterns.addAll(constraints.getPatterns()); - fullPatterns.addAll(patterns); - targetTypeBaseType = new StringType(fullLengths, fullPatterns); - } else if (targetTypeBaseType instanceof BitsTypeDefinition) { - BitsTypeDefinition bitsType = (BitsTypeDefinition) targetTypeBaseType; - List bits = bitsType.getBits(); - targetTypeBaseType = new BitsType(bits); - } else if (targetTypeBaseType instanceof BinaryTypeDefinition) { - targetTypeBaseType = new BinaryType(null, lengths, null); - } - return targetTypeBaseType; - } - - private TypeDefinitionBuilder findTypeDefinitionBuilder( - Map> modules, - UnknownType unknownType, ModuleBuilder builder) { - Map result = findTypeDefinitionBuilderWithConstraints( - modules, unknownType, builder); - return result.entrySet().iterator().next().getKey(); - } - - private Map findTypeDefinitionBuilderWithConstraints( - Map> modules, - UnknownType unknownType, ModuleBuilder builder) { - return findTypeDefinitionBuilderWithConstraints(new TypeConstraints(), - modules, unknownType, builder); - } - - /** - * Traverse through all referenced types chain until base YANG type is - * founded. - * - * @param constraints - * current type constraints - * @param modules - * all available modules - * @param unknownType - * unknown type - * @param builder - * current module - * @return map, where key is type referenced and value is its constraints - */ - private Map findTypeDefinitionBuilderWithConstraints( - TypeConstraints constraints, - Map> modules, - UnknownType unknownType, ModuleBuilder builder) { - Map result = new HashMap(); - QName unknownTypeQName = unknownType.getQName(); - String unknownTypeName = unknownTypeQName.getLocalName(); - String unknownTypePrefix = unknownTypeQName.getPrefix(); - - // search for module which contains referenced typedef - ModuleBuilder dependentModuleBuilder; - if (unknownTypePrefix.equals(builder.getPrefix())) { - dependentModuleBuilder = builder; - } else { - dependentModuleBuilder = findDependentModule(modules, builder, - unknownTypePrefix); - } - - // pull all typedef statements from dependent module... - final Set typedefs = dependentModuleBuilder - .getModuleTypedefs(); - // and search for referenced typedef - TypeDefinitionBuilder lookedUpBuilder = null; - for (TypeDefinitionBuilder tdb : typedefs) { - QName qname = tdb.getQName(); - if (qname.getLocalName().equals(unknownTypeName)) { - lookedUpBuilder = tdb; - break; - } - } - - // if referenced type is UnknownType again, search recursively with - // current constraints - TypeDefinition referencedType = lookedUpBuilder.getBaseType(); - if (referencedType instanceof UnknownType) { - UnknownType unknown = (UnknownType) lookedUpBuilder.getBaseType(); - - final List ranges = unknown.getRangeStatements(); - constraints.addRanges(ranges); - final List lengths = unknown - .getLengthStatements(); - constraints.addLengths(lengths); - final List patterns = unknown.getPatterns(); - constraints.addPatterns(patterns); - return findTypeDefinitionBuilderWithConstraints(constraints, - modules, unknown, dependentModuleBuilder); - } else { - // pull restriction from this base type and add them to - // 'constraints' - if (referencedType instanceof DecimalTypeDefinition) { - constraints.addRanges(((DecimalTypeDefinition) referencedType) - .getRangeStatements()); - constraints - .setFractionDigits(((DecimalTypeDefinition) referencedType) - .getFractionDigits()); - } else if (referencedType instanceof IntegerTypeDefinition) { - constraints.addRanges(((IntegerTypeDefinition) referencedType) - .getRangeStatements()); - } else if (referencedType instanceof StringTypeDefinition) { - constraints.addPatterns(((StringTypeDefinition) referencedType) - .getPatterns()); - } else if (referencedType instanceof BinaryTypeDefinition) { - constraints.addLengths(((BinaryTypeDefinition) referencedType) - .getLengthConstraints()); - } - result.put(lookedUpBuilder, constraints); - return result; - } - } - - /** - * Go through all augmentation definitions and resolve them. This means find - * referenced node and add child nodes to it. - * - * @param modules - * all available modules - * @param module - * current module - */ - private void resolveAugments( - Map> modules, - ModuleBuilder module) { - Set augmentBuilders = module - .getAddedAugments(); - - Set augments = new HashSet(); - for (AugmentationSchemaBuilder augmentBuilder : augmentBuilders) { - SchemaPath augmentTargetSchemaPath = augmentBuilder.getTargetPath(); - String prefix = null; - List augmentTargetPath = new ArrayList(); - - for (QName pathPart : augmentTargetSchemaPath.getPath()) { - prefix = pathPart.getPrefix(); - augmentTargetPath.add(pathPart.getLocalName()); - } - ModuleBuilder dependentModule = findDependentModule(modules, - module, prefix); - // - augmentTargetPath.add(0, dependentModule.getName()); - // - - - AugmentationTargetBuilder augmentTarget = (AugmentationTargetBuilder) dependentModule - .getNode(augmentTargetPath); - AugmentationSchema result = augmentBuilder.build(); - augmentTarget.addAugmentation(result); - fillAugmentTarget(augmentBuilder, (ChildNodeBuilder) augmentTarget); - augments.add(result); - } - module.setAugmentations(augments); - } - - /** - * Add all augment's child nodes to given target. - * - * @param augment - * @param target - */ - private void fillAugmentTarget(AugmentationSchemaBuilder augment, - ChildNodeBuilder target) { - for (DataSchemaNodeBuilder builder : augment.getChildNodes()) { - builder.setAugmenting(true); - target.addChildNode(builder); - } - } - - /** - * Go through identity statements defined in current module and resolve - * their 'base' statement if present. - * - * @param modules - * all modules - * @param module - * module being resolved - */ - private void resolveIdentities( - Map> modules, - ModuleBuilder module) { - Set identities = module.getAddedIdentities(); - for (IdentitySchemaNodeBuilder identity : identities) { - String baseIdentityName = identity.getBaseIdentityName(); - if (baseIdentityName != null) { - String baseIdentityPrefix = null; - String baseIdentityLocalName = null; - if (baseIdentityName.contains(":")) { - String[] splitted = baseIdentityName.split(":"); - baseIdentityPrefix = splitted[0]; - baseIdentityLocalName = splitted[1]; - } else { - baseIdentityPrefix = module.getPrefix(); - baseIdentityLocalName = baseIdentityName; - } - ModuleBuilder dependentModule; - if (baseIdentityPrefix.equals(module.getPrefix())) { - dependentModule = module; - } else { - dependentModule = findDependentModule(modules, module, - baseIdentityPrefix); - } - - Set dependentModuleIdentities = dependentModule - .getAddedIdentities(); - for (IdentitySchemaNodeBuilder idBuilder : dependentModuleIdentities) { - if (idBuilder.getQName().getLocalName() - .equals(baseIdentityLocalName)) { - identity.setBaseIdentity(idBuilder); - } - } - } - } - } - - /** - * Find dependent module based on given prefix - * - * @param modules - * all available modules - * @param module - * current module - * @param prefix - * target module prefix - * @return dependent module builder - */ - private ModuleBuilder findDependentModule( - Map> modules, - ModuleBuilder module, String prefix) { - ModuleImport dependentModuleImport = getModuleImport(module, prefix); - String dependentModuleName = dependentModuleImport.getModuleName(); - Date dependentModuleRevision = dependentModuleImport.getRevision(); - - TreeMap moduleBuildersByRevision = modules - .get(dependentModuleName); - ModuleBuilder dependentModule; - if (dependentModuleRevision == null) { - dependentModule = moduleBuildersByRevision.lastEntry().getValue(); - } else { - dependentModule = moduleBuildersByRevision - .get(dependentModuleRevision); - } - return dependentModule; - } - - /** - * Get module import referenced by given prefix. - * - * @param builder - * module to search - * @param prefix - * prefix associated with import - * @return ModuleImport based on given prefix - */ - private ModuleImport getModuleImport(ModuleBuilder builder, String prefix) { - ModuleImport moduleImport = null; - for (ModuleImport mi : builder.getModuleImports()) { - if (mi.getPrefix().equals(prefix)) { - moduleImport = mi; - break; - } - } - return moduleImport; - } - - /** - * Helper method for resolving special 'min' or 'max' values in range - * constraint - * - * @param ranges - * ranges to resolve - * @param targetType - * target type - * @param modules - * all available modules - * @param builder - * current module - */ - private void resolveRanges(List ranges, - TypeDefinitionBuilder targetType, - Map> modules, - ModuleBuilder builder) { - if (ranges != null && ranges.size() > 0) { - Long min = (Long) ranges.get(0).getMin(); - Long max = (Long) ranges.get(ranges.size() - 1).getMax(); - // if range contains one of the special values 'min' or 'max' - if (min.equals(Long.MIN_VALUE) || max.equals(Long.MAX_VALUE)) { - Long[] values = parseRangeConstraint(targetType, modules, - builder); - if (min.equals(Long.MIN_VALUE)) { - min = values[0]; - RangeConstraint oldFirst = ranges.get(0); - RangeConstraint newFirst = BaseConstraints.rangeConstraint( - min, oldFirst.getMax(), oldFirst.getDescription(), - oldFirst.getReference()); - ranges.set(0, newFirst); - } - if (max.equals(Long.MAX_VALUE)) { - max = values[1]; - RangeConstraint oldLast = ranges.get(ranges.size() - 1); - RangeConstraint newLast = BaseConstraints.rangeConstraint( - oldLast.getMin(), max, oldLast.getDescription(), - oldLast.getReference()); - ranges.set(ranges.size() - 1, newLast); - } - } - } - } - - /** - * Helper method for resolving special 'min' or 'max' values in length - * constraint - * - * @param lengths - * lengths to resolve - * @param targetType - * target type - * @param modules - * all available modules - * @param builder - * current module - */ - private void resolveLengths(List lengths, - TypeDefinitionBuilder targetType, - Map> modules, - ModuleBuilder builder) { - if (lengths != null && lengths.size() > 0) { - Long min = lengths.get(0).getMin().longValue(); - Long max = lengths.get(lengths.size() - 1).getMax().longValue(); - // if length contains one of the special values 'min' or 'max' - if (min.equals(Long.MIN_VALUE) || max.equals(Long.MAX_VALUE)) { - Long[] values = parseRangeConstraint(targetType, modules, - builder); - if (min.equals(Long.MIN_VALUE)) { - min = values[0]; - LengthConstraint oldFirst = lengths.get(0); - LengthConstraint newFirst = BaseConstraints - .lengthConstraint(min, oldFirst.getMax(), - oldFirst.getDescription(), - oldFirst.getReference()); - lengths.set(0, newFirst); - } - if (max.equals(Long.MAX_VALUE)) { - max = values[1]; - LengthConstraint oldLast = lengths.get(lengths.size() - 1); - LengthConstraint newLast = BaseConstraints - .lengthConstraint(oldLast.getMin(), max, - oldLast.getDescription(), - oldLast.getReference()); - lengths.set(lengths.size() - 1, newLast); - } - } - } - } - - private Long[] parseRangeConstraint(TypeDefinitionBuilder targetType, - Map> modules, - ModuleBuilder builder) { - TypeDefinition targetBaseType = targetType.getBaseType(); - - if (targetBaseType instanceof IntegerTypeDefinition) { - IntegerTypeDefinition itd = (IntegerTypeDefinition) targetBaseType; - List ranges = itd.getRangeStatements(); - Long min = (Long) ranges.get(0).getMin(); - Long max = (Long) ranges.get(ranges.size() - 1).getMax(); - return new Long[] { min, max }; - } else if (targetBaseType instanceof DecimalTypeDefinition) { - DecimalTypeDefinition dtd = (DecimalTypeDefinition) targetBaseType; - List ranges = dtd.getRangeStatements(); - Long min = (Long) ranges.get(0).getMin(); - Long max = (Long) ranges.get(ranges.size() - 1).getMax(); - return new Long[] { min, max }; - } else { - return parseRangeConstraint( - findTypeDefinitionBuilder(modules, - (UnknownType) targetBaseType, builder), modules, - builder); - } - } - - private Date createEpochTime() { - Calendar c = Calendar.getInstance(); - c.setTimeInMillis(0); - return c.getTime(); - } - - private static class SchemaContextImpl implements SchemaContext { - private final Set modules; - - private SchemaContextImpl(Set modules) { - this.modules = modules; - } - - @Override - public Set getDataDefinitions() { - final Set dataDefs = new HashSet(); - for (Module m : modules) { - dataDefs.addAll(m.getChildNodes()); - } - return dataDefs; - } - - @Override - public Set getModules() { - return modules; - } - - @Override - public Set getNotifications() { - final Set notifications = new HashSet(); - for (Module m : modules) { - notifications.addAll(m.getNotifications()); - } - return notifications; - } - - @Override - public Set getOperations() { - final Set rpcs = new HashSet(); - for (Module m : modules) { - rpcs.addAll(m.getRpcs()); - } - return rpcs; - } - - @Override - public Set getExtensions() { - final Set extensions = new HashSet(); - for (Module m : modules) { - extensions.addAll(m.getExtensionSchemaNodes()); - } - return extensions; - } - } - - private static class TypeConstraints { - private final List ranges = new ArrayList(); - private final List lengths = new ArrayList(); - private final List patterns = new ArrayList(); - private Integer fractionDigits; - - public List getRanges() { - return ranges; - } - - public void addRanges(List ranges) { - this.ranges.addAll(0, ranges); - } - - public List getLengths() { - return lengths; - } - - public void addLengths(List lengths) { - this.lengths.addAll(0, lengths); - } - - public List getPatterns() { - return patterns; - } - - public void addPatterns(List patterns) { - this.patterns.addAll(0, patterns); - } - - public Integer getFractionDigits() { - return fractionDigits; - } - - public void setFractionDigits(Integer fractionDigits) { - if (fractionDigits != null) { - this.fractionDigits = fractionDigits; - } - } - } - -} +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.yang.model.parser.impl; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +import org.antlr.v4.runtime.ANTLRInputStream; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.ParseTreeWalker; +import org.opendaylight.controller.antlrv4.code.gen.YangLexer; +import org.opendaylight.controller.antlrv4.code.gen.YangParser; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.AugmentationSchema; +import org.opendaylight.controller.yang.model.api.DataSchemaNode; +import org.opendaylight.controller.yang.model.api.ExtensionDefinition; +import org.opendaylight.controller.yang.model.api.Module; +import org.opendaylight.controller.yang.model.api.ModuleImport; +import org.opendaylight.controller.yang.model.api.NotificationDefinition; +import org.opendaylight.controller.yang.model.api.RpcDefinition; +import org.opendaylight.controller.yang.model.api.SchemaContext; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.TypeDefinition; +import org.opendaylight.controller.yang.model.api.type.BinaryTypeDefinition; +import org.opendaylight.controller.yang.model.api.type.DecimalTypeDefinition; +import org.opendaylight.controller.yang.model.api.type.IntegerTypeDefinition; +import org.opendaylight.controller.yang.model.api.type.LengthConstraint; +import org.opendaylight.controller.yang.model.api.type.PatternConstraint; +import org.opendaylight.controller.yang.model.api.type.RangeConstraint; +import org.opendaylight.controller.yang.model.api.type.StringTypeDefinition; +import org.opendaylight.controller.yang.model.parser.api.YangModelParser; +import org.opendaylight.controller.yang.model.parser.builder.api.AugmentationSchemaBuilder; +import org.opendaylight.controller.yang.model.parser.builder.api.AugmentationTargetBuilder; +import org.opendaylight.controller.yang.model.parser.builder.api.ChildNodeBuilder; +import org.opendaylight.controller.yang.model.parser.builder.api.DataSchemaNodeBuilder; +import org.opendaylight.controller.yang.model.parser.builder.api.TypeAwareBuilder; +import org.opendaylight.controller.yang.model.parser.builder.api.TypeDefinitionBuilder; +import org.opendaylight.controller.yang.model.parser.builder.impl.IdentitySchemaNodeBuilder; +import org.opendaylight.controller.yang.model.parser.builder.impl.ModuleBuilder; +import org.opendaylight.controller.yang.model.parser.builder.impl.TypedefBuilder; +import org.opendaylight.controller.yang.model.parser.builder.impl.UnionTypeBuilder; +import org.opendaylight.controller.yang.model.parser.util.TypeConstraints; +import org.opendaylight.controller.yang.model.parser.util.YangParseException; +import org.opendaylight.controller.yang.model.util.ExtendedType; +import org.opendaylight.controller.yang.model.util.UnknownType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class YangModelParserImpl implements YangModelParser { + + private static final Logger logger = LoggerFactory + .getLogger(YangModelParserImpl.class); + + @Override + public Module parseYangModel(final String yangFile) { + final Map> modules = resolveModuleBuildersFromStreams(yangFile); + final Set result = build(modules); + return result.iterator().next(); + } + + @Override + public Set parseYangModels(final String... yangFiles) { + final Map> modules = resolveModuleBuildersFromStreams(yangFiles); + return build(modules); + } + + @Override + public Set parseYangModelsFromStreams( + final InputStream... yangModelStreams) { + final Map> modules = resolveModuleBuildersFromStreams(yangModelStreams); + return build(modules); + } + + @Override + public SchemaContext resolveSchemaContext(final Set modules) { + return new SchemaContextImpl(modules); + } + + private Map> resolveModuleBuildersFromStreams( + String... yangFiles) { + InputStream[] streams = new InputStream[yangFiles.length]; + FileInputStream inStream = null; + for (int i = 0; i < yangFiles.length; i++) { + final String yangFileName = yangFiles[i]; + final File yangFile = new File(yangFileName); + try { + inStream = new FileInputStream(yangFile); + } catch (FileNotFoundException e) { + logger.warn("Exception while reading yang stream: " + inStream, + e); + } + streams[i] = inStream; + } + return resolveModuleBuildersFromStreams(streams); + } + + private Map> resolveModuleBuildersFromStreams( + InputStream... yangFiles) { + final Map> modules = new HashMap>(); + final ParseTreeWalker walker = new ParseTreeWalker(); + final List trees = parseStreams(yangFiles); + final ModuleBuilder[] builders = new ModuleBuilder[trees.size()]; + + YangModelParserListenerImpl yangModelParser = null; + for (int i = 0; i < trees.size(); i++) { + yangModelParser = new YangModelParserListenerImpl(); + walker.walk(yangModelParser, trees.get(i)); + builders[i] = yangModelParser.getModuleBuilder(); + } + + for (ModuleBuilder builder : builders) { + final String builderName = builder.getName(); + Date builderRevision = builder.getRevision(); + if (builderRevision == null) { + builderRevision = createEpochTime(); + } + TreeMap builderByRevision = modules + .get(builderName); + if (builderByRevision == null) { + builderByRevision = new TreeMap(); + } + builderByRevision.put(builderRevision, builder); + modules.put(builderName, builderByRevision); + } + return modules; + } + + private List parseStreams(InputStream... yangStreams) { + final List trees = new ArrayList(); + for (InputStream yangStream : yangStreams) { + trees.add(parseStream(yangStream)); + } + return trees; + } + + private ParseTree parseStream(InputStream yangStream) { + ParseTree result = null; + try { + final ANTLRInputStream input = new ANTLRInputStream(yangStream); + final YangLexer lexer = new YangLexer(input); + final CommonTokenStream tokens = new CommonTokenStream(lexer); + final YangParser parser = new YangParser(tokens); + result = parser.yang(); + } catch (IOException e) { + logger.warn("Exception while reading yang file: " + yangStream, e); + } + return result; + } + + private Set build(Map> modules) { + // validate + for (Map.Entry> entry : modules + .entrySet()) { + for (Map.Entry childEntry : entry.getValue() + .entrySet()) { + ModuleBuilder moduleBuilder = childEntry.getValue(); + validateModule(modules, moduleBuilder); + } + } + + // build + final Set result = new HashSet(); + for (Map.Entry> entry : modules + .entrySet()) { + final Map modulesByRevision = new HashMap(); + for (Map.Entry childEntry : entry.getValue() + .entrySet()) { + ModuleBuilder moduleBuilder = childEntry.getValue(); + Module module = moduleBuilder.build(); + modulesByRevision.put(childEntry.getKey(), module); + result.add(module); + } + } + return result; + } + + private void validateModule( + Map> modules, + ModuleBuilder builder) { + resolveDirtyNodes(modules, builder); + resolveAugments(modules, builder); + resolveIdentities(modules, builder); + } + + /** + * Search for dirty nodes (node which contains UnknownType) and resolve + * unknown types. + * + * @param modules + * all available modules + * @param module + * current module + */ + private void resolveDirtyNodes( + Map> modules, + ModuleBuilder module) { + final Map, TypeAwareBuilder> dirtyNodes = module + .getDirtyNodes(); + if (!dirtyNodes.isEmpty()) { + for (Map.Entry, TypeAwareBuilder> entry : dirtyNodes + .entrySet()) { + + TypeAwareBuilder typeToResolve = entry.getValue(); + if (typeToResolve instanceof UnionTypeBuilder) { + UnionTypeBuilder union = (UnionTypeBuilder) typeToResolve; + List> unionTypes = union.getTypes(); + List toRemove = new ArrayList(); + for (TypeDefinition td : unionTypes) { + if (td instanceof UnknownType) { + UnknownType unknownType = (UnknownType) td; + TypeDefinitionBuilder resolvedType = findTargetTypeUnion( + typeToResolve, unknownType, modules, module); + union.setType(resolvedType); + toRemove.add(unknownType); + } + } + unionTypes.removeAll(toRemove); + } else { + TypeDefinitionBuilder resolvedType = findTargetType( + typeToResolve, modules, module); + typeToResolve.setType(resolvedType); + } + } + } + } + + private TypeDefinitionBuilder findTargetType( + TypeAwareBuilder typeToResolve, + Map> modules, + ModuleBuilder builder) { + TypeConstraints constraints = new TypeConstraints(); + + TypeDefinitionBuilder targetType = findTypedef(typeToResolve, modules, + builder); + TypeConstraints tConstraints = findConstraints(typeToResolve, + constraints, modules, builder); + targetType.setRanges(tConstraints.getRange()); + targetType.setLengths(tConstraints.getLength()); + targetType.setPatterns(tConstraints.getPatterns()); + targetType.setFractionDigits(tConstraints.getFractionDigits()); + + return targetType; + } + + private TypeDefinitionBuilder findTargetTypeUnion( + TypeAwareBuilder typeToResolve, UnknownType unknownType, + Map> modules, + ModuleBuilder builder) { + TypeConstraints constraints = new TypeConstraints(); + + TypeDefinitionBuilder targetType = findTypedefUnion(typeToResolve, + unknownType, modules, builder); + TypeConstraints tConstraints = findConstraints(typeToResolve, + constraints, modules, builder); + targetType.setRanges(tConstraints.getRange()); + targetType.setLengths(tConstraints.getLength()); + targetType.setPatterns(tConstraints.getPatterns()); + targetType.setFractionDigits(tConstraints.getFractionDigits()); + + return targetType; + } + + private TypeDefinitionBuilder findTypedef(TypeAwareBuilder typeToResolve, + Map> modules, + ModuleBuilder builder) { + + TypeDefinition baseTypeToResolve = typeToResolve.getType(); + if (baseTypeToResolve != null + && !(baseTypeToResolve instanceof UnknownType)) { + return (TypeDefinitionBuilder) typeToResolve; + } + + UnknownType unknownType = (UnknownType) typeToResolve.getType(); + + QName unknownTypeQName = unknownType.getQName(); + String unknownTypeName = unknownTypeQName.getLocalName(); + String unknownTypePrefix = unknownTypeQName.getPrefix(); + + // search for module which contains referenced typedef + ModuleBuilder dependentModule = findDependentModule(modules, builder, + unknownTypePrefix); + TypeDefinitionBuilder lookedUpBuilder = findTypedefBuilder( + dependentModule.getModuleTypedefs(), unknownTypeName); + + TypeDefinitionBuilder lookedUpBuilderCopy = copyTypedefBuilder( + lookedUpBuilder, typeToResolve instanceof TypeDefinitionBuilder); + TypeDefinitionBuilder resolvedCopy = resolveCopiedBuilder( + lookedUpBuilderCopy, modules, dependentModule); + return resolvedCopy; + } + + private TypeDefinitionBuilder findTypedefUnion( + TypeAwareBuilder typeToResolve, UnknownType unknownType, + Map> modules, + ModuleBuilder builder) { + + TypeDefinition baseTypeToResolve = typeToResolve.getType(); + if (baseTypeToResolve != null + && !(baseTypeToResolve instanceof UnknownType)) { + return (TypeDefinitionBuilder) typeToResolve; + } + + QName unknownTypeQName = unknownType.getQName(); + String unknownTypeName = unknownTypeQName.getLocalName(); + String unknownTypePrefix = unknownTypeQName.getPrefix(); + + // search for module which contains referenced typedef + ModuleBuilder dependentModule = findDependentModule(modules, builder, + unknownTypePrefix); + TypeDefinitionBuilder lookedUpBuilder = findTypedefBuilder( + dependentModule.getModuleTypedefs(), unknownTypeName); + + TypeDefinitionBuilder lookedUpBuilderCopy = copyTypedefBuilder( + lookedUpBuilder, typeToResolve instanceof TypeDefinitionBuilder); + TypeDefinitionBuilder resolvedCopy = resolveCopiedBuilder( + lookedUpBuilderCopy, modules, dependentModule); + return resolvedCopy; + } + + private TypeDefinitionBuilder copyTypedefBuilder(TypeDefinitionBuilder old, + boolean seekByTypedefBuilder) { + if (old instanceof UnionTypeBuilder) { + UnionTypeBuilder oldUnion = (UnionTypeBuilder) old; + UnionTypeBuilder newUnion = new UnionTypeBuilder(); + for (TypeDefinition td : oldUnion.getTypes()) { + newUnion.setType(td); + } + for (TypeDefinitionBuilder tdb : oldUnion.getTypedefs()) { + newUnion.setType(copyTypedefBuilder(tdb, true)); + } + return newUnion; + } + + QName oldQName = old.getQName(); + QName newQName = new QName(oldQName.getNamespace(), + oldQName.getRevision(), oldQName.getPrefix(), + oldQName.getLocalName()); + TypeDefinitionBuilder tdb = new TypedefBuilder(newQName); + + tdb.setRanges(old.getRanges()); + tdb.setLengths(old.getLengths()); + tdb.setPatterns(old.getPatterns()); + + TypeDefinition oldType = old.getType(); + if (oldType == null) { + tdb.setType(old.getTypedef()); + } else { + tdb.setType(oldType); + } + + if (!seekByTypedefBuilder) { + tdb.setDescription(old.getDescription()); + tdb.setReference(old.getReference()); + tdb.setStatus(old.getStatus()); + tdb.setDefaultValue(old.getDefaultValue()); + tdb.setUnits(old.getUnits()); + } + return tdb; + } + + private TypeDefinitionBuilder resolveCopiedBuilder( + TypeDefinitionBuilder copied, + Map> modules, + ModuleBuilder builder) { + + if (copied instanceof UnionTypeBuilder) { + UnionTypeBuilder union = (UnionTypeBuilder) copied; + List> unionTypes = union.getTypes(); + List toRemove = new ArrayList(); + for (TypeDefinition td : unionTypes) { + if (td instanceof UnknownType) { + UnknownType unknownType = (UnknownType) td; + TypeDefinitionBuilder resolvedType = findTargetTypeUnion( + union, unknownType, modules, builder); + union.setType(resolvedType); + toRemove.add(unknownType); + } + } + unionTypes.removeAll(toRemove); + + return union; + } + + TypeDefinition base = copied.getType(); + TypeDefinitionBuilder baseTdb = copied.getTypedef(); + if (base != null && !(base instanceof UnknownType)) { + return copied; + } else if (base instanceof UnknownType) { + UnknownType unknownType = (UnknownType) base; + QName unknownTypeQName = unknownType.getQName(); + String unknownTypePrefix = unknownTypeQName.getPrefix(); + ModuleBuilder dependentModule = findDependentModule(modules, + builder, unknownTypePrefix); + TypeDefinitionBuilder unknownTypeBuilder = findTypedef(copied, + modules, dependentModule); + copied.setType(unknownTypeBuilder); + return copied; + } else if (base == null && baseTdb != null) { + // make a copy of baseTypeDef and call again + TypeDefinitionBuilder baseTdbCopy = copyTypedefBuilder(baseTdb, + true); + TypeDefinitionBuilder baseTdbCopyResolved = resolveCopiedBuilder( + baseTdbCopy, modules, builder); + copied.setType(baseTdbCopyResolved); + return copied; + } else { + throw new IllegalStateException( + "TypeDefinitionBuilder in unexpected state"); + } + } + + private TypeDefinitionBuilder findTypedef(QName unknownTypeQName, + Map> modules, + ModuleBuilder builder) { + + String unknownTypeName = unknownTypeQName.getLocalName(); + String unknownTypePrefix = unknownTypeQName.getPrefix(); + + // search for module which contains referenced typedef + ModuleBuilder dependentModule = findDependentModule(modules, builder, + unknownTypePrefix); + + TypeDefinitionBuilder lookedUpBuilder = findTypedefBuilder( + dependentModule.getModuleTypedefs(), unknownTypeName); + + TypeDefinitionBuilder copied = copyTypedefBuilder(lookedUpBuilder, true); + return copied; + } + + private TypeConstraints findConstraints(TypeAwareBuilder typeToResolve, + TypeConstraints constraints, + Map> modules, + ModuleBuilder builder) { + + // union type cannot be restricted + if (typeToResolve instanceof UnionTypeBuilder) { + return constraints; + } + + // if referenced type is UnknownType again, search recursively with + // current constraints + TypeDefinition referencedType = typeToResolve.getType(); + if (referencedType == null) { + TypeDefinitionBuilder tdb = (TypeDefinitionBuilder) typeToResolve; + final List ranges = tdb.getRanges(); + constraints.addRanges(ranges); + final List lengths = tdb.getLengths(); + constraints.addLengths(lengths); + final List patterns = tdb.getPatterns(); + constraints.addPatterns(patterns); + final Integer fractionDigits = tdb.getFractionDigits(); + constraints.setFractionDigits(fractionDigits); + return constraints; + } else if (referencedType instanceof ExtendedType) { + ExtendedType ext = (ExtendedType) referencedType; + final List ranges = ext.getRanges(); + constraints.addRanges(ranges); + final List lengths = ext.getLengths(); + constraints.addLengths(lengths); + final List patterns = ext.getPatterns(); + constraints.addPatterns(patterns); + final Integer fractionDigits = ext.getFractionDigits(); + constraints.setFractionDigits(fractionDigits); + return findConstraints( + findTypedef(ext.getQName(), modules, builder), constraints, + modules, builder); + } else if (referencedType instanceof UnknownType) { + UnknownType unknown = (UnknownType) referencedType; + + final List ranges = unknown.getRangeStatements(); + constraints.addRanges(ranges); + final List lengths = unknown + .getLengthStatements(); + constraints.addLengths(lengths); + final List patterns = unknown.getPatterns(); + constraints.addPatterns(patterns); + final Integer fractionDigits = unknown.getFractionDigits(); + constraints.setFractionDigits(fractionDigits); + + String unknownTypePrefix = unknown.getQName().getPrefix(); + if (unknownTypePrefix == null || "".equals(unknownTypePrefix)) { + unknownTypePrefix = builder.getPrefix(); + } + ModuleBuilder dependentModule = findDependentModule(modules, + builder, unknown.getQName().getPrefix()); + TypeDefinitionBuilder unknownTypeBuilder = findTypedef( + unknown.getQName(), modules, builder); + return findConstraints(unknownTypeBuilder, constraints, modules, + dependentModule); + } else { + // HANDLE BASE YANG TYPE + mergeConstraints(referencedType, constraints); + return constraints; + } + + } + + /** + * Go through all typedef statements from given module and search for one + * with given name + * + * @param typedefs + * typedef statements to search + * @param name + * name of searched typedef + * @return typedef with name equals to given name + */ + private TypeDefinitionBuilder findTypedefBuilder( + Set typedefs, String name) { + TypeDefinitionBuilder result = null; + for (TypeDefinitionBuilder td : typedefs) { + if (td.getQName().getLocalName().equals(name)) { + result = td; + break; + } + } + if (result == null) { + throw new YangParseException( + "Target module does not contain typedef '" + name + "'."); + } + return result; + } + + /** + * Pull restriction from referenced type and add them to given constraints + * + * @param referencedType + * @param constraints + */ + private void mergeConstraints(TypeDefinition referencedType, + TypeConstraints constraints) { + + if (referencedType instanceof DecimalTypeDefinition) { + constraints.addRanges(((DecimalTypeDefinition) referencedType) + .getRangeStatements()); + constraints + .setFractionDigits(((DecimalTypeDefinition) referencedType) + .getFractionDigits()); + } else if (referencedType instanceof IntegerTypeDefinition) { + constraints.addRanges(((IntegerTypeDefinition) referencedType) + .getRangeStatements()); + } else if (referencedType instanceof StringTypeDefinition) { + constraints.addPatterns(((StringTypeDefinition) referencedType) + .getPatterns()); + constraints.addLengths(((StringTypeDefinition) referencedType) + .getLengthStatements()); + } else if (referencedType instanceof BinaryTypeDefinition) { + constraints.addLengths(((BinaryTypeDefinition) referencedType) + .getLengthConstraints()); + } + } + + /** + * Go through all augmentation definitions and resolve them. This means find + * referenced node and add child nodes to it. + * + * @param modules + * all available modules + * @param module + * current module + */ + private void resolveAugments( + Map> modules, + ModuleBuilder module) { + Set augmentBuilders = module + .getAddedAugments(); + + Set augments = new HashSet(); + for (AugmentationSchemaBuilder augmentBuilder : augmentBuilders) { + SchemaPath augmentTargetSchemaPath = augmentBuilder.getTargetPath(); + String prefix = null; + List augmentTargetPath = new ArrayList(); + + for (QName pathPart : augmentTargetSchemaPath.getPath()) { + prefix = pathPart.getPrefix(); + augmentTargetPath.add(pathPart.getLocalName()); + } + ModuleBuilder dependentModule = findDependentModule(modules, + module, prefix); + augmentTargetPath.add(0, dependentModule.getName()); + + AugmentationTargetBuilder augmentTarget = (AugmentationTargetBuilder) dependentModule + .getNode(augmentTargetPath); + AugmentationSchema result = augmentBuilder.build(); + augmentTarget.addAugmentation(result); + fillAugmentTarget(augmentBuilder, (ChildNodeBuilder) augmentTarget); + augments.add(result); + } + module.setAugmentations(augments); + } + + /** + * Add all augment's child nodes to given target. + * + * @param augment + * @param target + */ + private void fillAugmentTarget(AugmentationSchemaBuilder augment, + ChildNodeBuilder target) { + for (DataSchemaNodeBuilder builder : augment.getChildNodes()) { + builder.setAugmenting(true); + target.addChildNode(builder); + } + } + + /** + * Go through identity statements defined in current module and resolve + * their 'base' statement if present. + * + * @param modules + * all modules + * @param module + * module being resolved + */ + private void resolveIdentities( + Map> modules, + ModuleBuilder module) { + Set identities = module.getAddedIdentities(); + for (IdentitySchemaNodeBuilder identity : identities) { + String baseIdentityName = identity.getBaseIdentityName(); + if (baseIdentityName != null) { + String baseIdentityPrefix = null; + String baseIdentityLocalName = null; + if (baseIdentityName.contains(":")) { + String[] splitted = baseIdentityName.split(":"); + baseIdentityPrefix = splitted[0]; + baseIdentityLocalName = splitted[1]; + } else { + baseIdentityPrefix = module.getPrefix(); + baseIdentityLocalName = baseIdentityName; + } + ModuleBuilder dependentModule = findDependentModule(modules, + module, baseIdentityPrefix); + + Set dependentModuleIdentities = dependentModule + .getAddedIdentities(); + for (IdentitySchemaNodeBuilder idBuilder : dependentModuleIdentities) { + if (idBuilder.getQName().getLocalName() + .equals(baseIdentityLocalName)) { + identity.setBaseIdentity(idBuilder); + } + } + } + } + } + + /** + * Find dependent module based on given prefix + * + * @param modules + * all available modules + * @param module + * current module + * @param prefix + * target module prefix + * @return + */ + private ModuleBuilder findDependentModule( + Map> modules, + ModuleBuilder module, String prefix) { + ModuleBuilder dependentModule = null; + Date dependentModuleRevision = null; + + if (prefix.equals(module.getPrefix())) { + dependentModule = module; + } else { + ModuleImport dependentModuleImport = getModuleImport(module, prefix); + if (dependentModuleImport == null) { + throw new YangParseException("No import found with prefix '" + + prefix + "' in module " + module.getName() + "'."); + } + String dependentModuleName = dependentModuleImport.getModuleName(); + dependentModuleRevision = dependentModuleImport.getRevision(); + + TreeMap moduleBuildersByRevision = modules + .get(dependentModuleName); + if (dependentModuleRevision == null) { + dependentModule = moduleBuildersByRevision.lastEntry() + .getValue(); + } else { + dependentModule = moduleBuildersByRevision + .get(dependentModuleRevision); + } + } + + if (dependentModule == null) { + throw new YangParseException( + "Failed to find dependent module with prefix '" + prefix + + "' and revision '" + dependentModuleRevision + + "'."); + } + return dependentModule; + } + + /** + * Get module import referenced by given prefix. + * + * @param builder + * module to search + * @param prefix + * prefix associated with import + * @return ModuleImport based on given prefix + */ + private ModuleImport getModuleImport(ModuleBuilder builder, String prefix) { + ModuleImport moduleImport = null; + for (ModuleImport mi : builder.getModuleImports()) { + if (mi.getPrefix().equals(prefix)) { + moduleImport = mi; + break; + } + } + return moduleImport; + } + + private Date createEpochTime() { + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(0); + return calendar.getTime(); + } + + private static class SchemaContextImpl implements SchemaContext { + private final Set modules; + + private SchemaContextImpl(Set modules) { + this.modules = modules; + } + + @Override + public Set getDataDefinitions() { + final Set dataDefs = new HashSet(); + for (Module m : modules) { + dataDefs.addAll(m.getChildNodes()); + } + return dataDefs; + } + + @Override + public Set getModules() { + return modules; + } + + @Override + public Set getNotifications() { + final Set notifications = new HashSet(); + for (Module m : modules) { + notifications.addAll(m.getNotifications()); + } + return notifications; + } + + @Override + public Set getOperations() { + final Set rpcs = new HashSet(); + for (Module m : modules) { + rpcs.addAll(m.getRpcs()); + } + return rpcs; + } + + @Override + public Set getExtensions() { + final Set extensions = new HashSet(); + for (Module m : modules) { + extensions.addAll(m.getExtensionSchemaNodes()); + } + return extensions; + } + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserListenerImpl.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserListenerImpl.java index 6ff69eee51..6d51868d98 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserListenerImpl.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserListenerImpl.java @@ -13,15 +13,14 @@ import java.net.URI; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Stack; -import java.util.TreeMap; import org.antlr.v4.runtime.tree.ParseTree; import org.opendaylight.controller.antlrv4.code.gen.YangParser; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Argument_stmtContext; import org.opendaylight.controller.antlrv4.code.gen.YangParser.Base_stmtContext; import org.opendaylight.controller.antlrv4.code.gen.YangParser.Contact_stmtContext; import org.opendaylight.controller.antlrv4.code.gen.YangParser.Container_stmtContext; @@ -47,7 +46,6 @@ import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtCont import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtsContext; import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_stmtContext; import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_body_stmtsContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Union_specificationContext; import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yang_version_stmtContext; import org.opendaylight.controller.antlrv4.code.gen.YangParserBaseListener; import org.opendaylight.controller.yang.common.QName; @@ -88,7 +86,6 @@ final class YangModelParserListenerImpl extends YangParserBaseListener { "yyyy-mm-dd"); private final Stack actualPath = new Stack(); - @Override public void enterModule_stmt(YangParser.Module_stmtContext ctx) { moduleName = stringFromNode(ctx); @@ -123,7 +120,7 @@ final class YangModelParserListenerImpl extends YangParserBaseListener { @Override public void enterModule_header_stmts(final Module_header_stmtsContext ctx) { super.enterModule_header_stmts(ctx); - + String yangVersion = null; for (int i = 0; i < ctx.getChildCount(); ++i) { final ParseTree treeNode = ctx.getChild(i); @@ -138,7 +135,7 @@ final class YangModelParserListenerImpl extends YangParserBaseListener { yangVersion = stringFromNode(treeNode); } } - + if (yangVersion == null) { yangVersion = "1"; } @@ -204,7 +201,7 @@ final class YangModelParserListenerImpl extends YangParserBaseListener { logger.warn(message); } } - + @Override public void enterImport_stmt(Import_stmtContext ctx) { super.enterImport_stmt(ctx); @@ -260,10 +257,23 @@ final class YangModelParserListenerImpl extends YangParserBaseListener { @Override public void enterExtension_stmt(YangParser.Extension_stmtContext ctx) { - String argument = stringFromNode(ctx); - QName qname = new QName(namespace, revision, yangModelPrefix, argument); + String extName = stringFromNode(ctx); + QName qname = new QName(namespace, revision, yangModelPrefix, extName); ExtensionBuilder builder = moduleBuilder.addExtension(qname); parseSchemaNodeArgs(ctx, builder); + + String argument = null; + boolean yin = false; + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree child = ctx.getChild(i); + if (child instanceof Argument_stmtContext) { + argument = stringFromNode(child); + yin = parseYinValue((Argument_stmtContext) child); + break; + } + } + builder.setArgument(argument); + builder.setYinElement(yin); } @Override @@ -290,20 +300,7 @@ final class YangModelParserListenerImpl extends YangParserBaseListener { @Override public void enterType_stmt(YangParser.Type_stmtContext ctx) { String typeName = stringFromNode(ctx); - QName typeQName; - if (typeName.contains(":")) { - String[] splittedName = typeName.split(":"); - String prefix = splittedName[0]; - String name = splittedName[1]; - if (prefix.equals(yangModelPrefix)) { - typeQName = new QName(namespace, revision, prefix, name); - } else { - typeQName = new QName(null, null, prefix, name); - } - } else { - typeQName = new QName(namespace, revision, yangModelPrefix, - typeName); - } + QName typeQName = parseQName(typeName); TypeDefinition type = null; Type_body_stmtsContext typeBody = null; @@ -315,38 +312,46 @@ final class YangModelParserListenerImpl extends YangParserBaseListener { } // if this is base yang type... - if(YangTypesConverter.isBaseYangType(typeName)) { + if (YangTypesConverter.isBaseYangType(typeName)) { if (typeBody == null) { // if there are no constraints, just grab default base yang type type = YangTypesConverter.javaTypeForBaseYangType(typeName); - moduleBuilder.setType(type, actualPath); + moduleBuilder.setType(type, getActualPath()); } else { - if(typeName.equals("union")) { - List types = new ArrayList(); - for(int i = 0; i < typeBody.getChildCount(); i++) { - ParseTree unionSpec = typeBody.getChild(i); - if(unionSpec instanceof Union_specificationContext) { - for(int j = 0; j < unionSpec.getChildCount(); j++) { - ParseTree typeSpec = unionSpec.getChild(j); - types.add(stringFromNode(typeSpec)); - } - } - } - moduleBuilder.addUnionType(actualPath); + if ("union".equals(typeName)) { + moduleBuilder.addUnionType(getActualPath()); } else { - type = parseTypeBody(typeName, typeBody, actualPath, namespace, revision, yangModelPrefix); - moduleBuilder.setType(type, actualPath); + type = parseTypeBody(typeName, typeBody, getActualPath(), + namespace, revision, yangModelPrefix); + moduleBuilder.setType(type, getActualPath()); } } } else { type = parseUnknownTypeBody(typeQName, typeBody); // mark parent node of this type statement as dirty - moduleBuilder.addDirtyNode(actualPath); - moduleBuilder.setType(type, actualPath); + moduleBuilder.addDirtyNode(getActualPath()); + moduleBuilder.setType(type, getActualPath()); } updatePath(typeName); + } + private QName parseQName(String typeName) { + QName typeQName; + if (typeName.contains(":")) { + String[] splittedName = typeName.split(":"); + String prefix = splittedName[0]; + String name = splittedName[1]; + if (prefix.equals(yangModelPrefix)) { + typeQName = new QName(namespace, revision, prefix, name); + } else { + typeQName = new QName(null, null, prefix, name); + } + } else { + typeQName = new QName(namespace, revision, yangModelPrefix, + typeName); + } + return typeQName; } @Override diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/TypeConstraints.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/TypeConstraints.java index 9e5fcbe771..0f26da886b 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/TypeConstraints.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/TypeConstraints.java @@ -8,6 +8,7 @@ package org.opendaylight.controller.yang.model.parser.util; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.opendaylight.controller.yang.model.api.type.LengthConstraint; @@ -29,6 +30,11 @@ public final class TypeConstraints { } public List getRange() { + if(ranges.isEmpty()) { + List result = Collections.emptyList(); + return result; + } + List resolved = ranges.get(0); RangeConstraint firstRange = resolved.get(0); RangeConstraint lastRange = resolved.get(resolved.size() - 1); @@ -103,6 +109,11 @@ public final class TypeConstraints { } public List getLength() { + if(lengths.isEmpty()) { + List result = Collections.emptyList(); + return result; + } + List resolved = lengths.get(0); LengthConstraint firstLength = resolved.get(0); LengthConstraint lastLength = resolved.get(resolved.size() - 1); @@ -185,7 +196,7 @@ public final class TypeConstraints { } public void setFractionDigits(Integer fractionDigits) { - if (fractionDigits != null) { + if (this.fractionDigits == null) { this.fractionDigits = fractionDigits; } } diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/YangModelBuilderUtil.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/YangModelBuilderUtil.java index 89422ff9c6..cbeed0959e 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/YangModelBuilderUtil.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/YangModelBuilderUtil.java @@ -1,1115 +1,1124 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/eplv10.html - */ -package org.opendaylight.controller.yang.model.parser.util; - -import java.net.URI; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Stack; - -import org.antlr.v4.runtime.tree.ParseTree; -import org.opendaylight.controller.antlrv4.code.gen.YangParser; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Bit_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Bits_specificationContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Config_argContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Config_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Decimal64_specificationContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Description_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Enum_specificationContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Enum_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Fraction_digits_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leafref_specificationContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Length_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_argContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Max_elements_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Min_elements_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Must_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Numerical_restrictionsContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_argContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Path_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Pattern_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Position_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Range_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Reference_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Require_instance_argContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Require_instance_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_argContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.StringContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.String_restrictionsContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_body_stmtsContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.Units_stmtContext; -import org.opendaylight.controller.antlrv4.code.gen.YangParser.When_stmtContext; -import org.opendaylight.controller.yang.common.QName; -import org.opendaylight.controller.yang.model.api.RevisionAwareXPath; -import org.opendaylight.controller.yang.model.api.SchemaPath; -import org.opendaylight.controller.yang.model.api.Status; -import org.opendaylight.controller.yang.model.api.TypeDefinition; -import org.opendaylight.controller.yang.model.api.UnknownSchemaNode; -import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition; -import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition; -import org.opendaylight.controller.yang.model.api.type.LengthConstraint; -import org.opendaylight.controller.yang.model.api.type.PatternConstraint; -import org.opendaylight.controller.yang.model.api.type.RangeConstraint; -import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition.Bit; -import org.opendaylight.controller.yang.model.parser.builder.api.SchemaNodeBuilder; -import org.opendaylight.controller.yang.model.parser.builder.impl.ConstraintsBuilder; -import org.opendaylight.controller.yang.model.util.BaseConstraints; -import org.opendaylight.controller.yang.model.util.BinaryType; -import org.opendaylight.controller.yang.model.util.BitsType; -import org.opendaylight.controller.yang.model.util.EnumerationType; -import org.opendaylight.controller.yang.model.util.InstanceIdentifier; -import org.opendaylight.controller.yang.model.util.Leafref; -import org.opendaylight.controller.yang.model.util.RevisionAwareXPathImpl; -import org.opendaylight.controller.yang.model.util.StringType; -import org.opendaylight.controller.yang.model.util.UnknownType; -import org.opendaylight.controller.yang.model.util.YangTypesConverter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class YangModelBuilderUtil { - - private static final Logger logger = LoggerFactory - .getLogger(YangModelBuilderUtil.class); - - /** - * Parse given tree and get first string value. - * - * @param treeNode - * tree to parse - * @return first string value from given tree - */ - public static String stringFromNode(final ParseTree treeNode) { - final String result = ""; - for (int i = 0; i < treeNode.getChildCount(); ++i) { - if (treeNode.getChild(i) instanceof StringContext) { - final StringContext context = (StringContext) treeNode - .getChild(i); - if (context != null) { - return context.getChild(0).getText().replace("\"", ""); - } - } - } - return result; - } - - /** - * Parse 'description', 'reference' and 'status' statements and fill in - * given builder. - * - * @param ctx - * context to parse - * @param builder - * builder to fill in with parsed statements - */ - public static void parseSchemaNodeArgs(ParseTree ctx, - SchemaNodeBuilder builder) { - for (int i = 0; i < ctx.getChildCount(); i++) { - ParseTree child = ctx.getChild(i); - if (child instanceof Description_stmtContext) { - String desc = stringFromNode(child); - builder.setDescription(desc); - } else if (child instanceof Reference_stmtContext) { - String ref = stringFromNode(child); - builder.setReference(ref); - } else if (child instanceof Status_stmtContext) { - Status status = parseStatus((Status_stmtContext) child); - builder.setStatus(status); - } - } - } - - /** - * Parse given context and return its value; - * - * @param ctx - * status context - * @return value parsed from context - */ - public static Status parseStatus(Status_stmtContext ctx) { - for (int i = 0; i < ctx.getChildCount(); i++) { - ParseTree statusArg = ctx.getChild(i); - if (statusArg instanceof Status_argContext) { - String statusArgStr = stringFromNode(statusArg); - if (statusArgStr.equals("current")) { - return Status.CURRENT; - } else if (statusArgStr.equals("deprecated")) { - return Status.DEPRECATED; - } else if (statusArgStr.equals("obsolete")) { - return Status.OBSOLETE; - } else { - logger.warn("Invalid 'status' statement: " + statusArgStr); - } - } - } - return null; - } - - /** - * Parse given tree and returns units statement as string. - * - * @param ctx - * context to parse - * @return value of units statement as string or null if there is no units - * statement - */ - public static String parseUnits(ParseTree ctx) { - String units = null; - for (int i = 0; i < ctx.getChildCount(); i++) { - ParseTree child = ctx.getChild(i); - if (child instanceof Units_stmtContext) { - units = stringFromNode(child); - break; - } - } - return units; - } - - /** - * Create SchemaPath object from given path list with namespace, revision - * and prefix based on given values. - * - * @param actualPath - * @param namespace - * @param revision - * @param prefix - * @return SchemaPath object. - */ - public static SchemaPath createActualSchemaPath(List actualPath, - URI namespace, Date revision, String prefix) { - final List path = new ArrayList(); - QName qname; - for (String pathElement : actualPath) { - qname = new QName(namespace, revision, prefix, pathElement); - path.add(qname); - } - return new SchemaPath(path, true); - } - - /** - * Create SchemaPath from given string. - * - * @param augmentPath - * string representation of path - * @return SchemaPath object - */ - public static SchemaPath parseAugmentPath(String augmentPath) { - boolean absolute = augmentPath.startsWith("/"); - String[] splittedPath = augmentPath.split("/"); - List path = new ArrayList(); - QName name; - for (String pathElement : splittedPath) { - if (pathElement.length() > 0) { - String[] splittedElement = pathElement.split(":"); - if (splittedElement.length == 1) { - name = new QName(null, null, null, splittedElement[0]); - } else { - name = new QName(null, null, splittedElement[0], - splittedElement[1]); - } - path.add(name); - } - } - return new SchemaPath(path, absolute); - } - - /** - * Create java.util.List of QName objects from given key definition as - * string. - * - * @param keyDefinition - * key definition as string - * @param namespace - * current namespace - * @param revision - * current revision - * @param prefix - * current prefix - * @return YANG list key as java.util.List of QName objects - */ - public static List createListKey(String keyDefinition, - URI namespace, Date revision, String prefix) { - List key = new ArrayList(); - String[] splittedKey = keyDefinition.split(" "); - - QName qname = null; - for (String keyElement : splittedKey) { - if (keyElement.length() != 0) { - qname = new QName(namespace, revision, prefix, keyElement); - key.add(qname); - } - } - return key; - } - - private static List getEnumConstants( - Type_body_stmtsContext ctx, List path, URI namespace, - Date revision, String prefix) { - List enumConstants = new ArrayList(); - - out: for (int j = 0; j < ctx.getChildCount(); j++) { - ParseTree enumSpecChild = ctx.getChild(j); - if (enumSpecChild instanceof Enum_specificationContext) { - for (int k = 0; k < enumSpecChild.getChildCount(); k++) { - ParseTree enumChild = enumSpecChild.getChild(k); - if (enumChild instanceof Enum_stmtContext) { - enumConstants.add(createEnumPair( - (Enum_stmtContext) enumChild, k, path, - namespace, revision, prefix)); - if (k == enumSpecChild.getChildCount() - 1) { - break out; - } - } - } - } - } - return enumConstants; - } - - private static EnumTypeDefinition.EnumPair createEnumPair( - Enum_stmtContext ctx, final int value, List path, - final URI namespace, final Date revision, final String prefix) { - final String name = stringFromNode(ctx); - final QName qname = new QName(namespace, revision, prefix, name); - String description = null; - String reference = null; - Status status = null; - List enumPairPath = new ArrayList(path); - enumPairPath.add(name); - - for (int i = 0; i < ctx.getChildCount(); i++) { - ParseTree child = ctx.getChild(i); - if (child instanceof Description_stmtContext) { - description = stringFromNode(child); - } else if (child instanceof Reference_stmtContext) { - reference = stringFromNode(child); - } else if (child instanceof Status_stmtContext) { - status = parseStatus((Status_stmtContext) child); - } - } - - EnumPairImpl result = new EnumPairImpl(); - result.qname = qname; - result.path = createActualSchemaPath(enumPairPath, namespace, revision, - prefix); - result.description = description; - result.reference = reference; - result.status = status; - // TODO: extensionSchemaNodes - result.name = name; - result.value = value; - return result; - } - - private static class EnumPairImpl implements EnumTypeDefinition.EnumPair { - - private QName qname; - private SchemaPath path; - private String description; - private String reference; - private Status status; - private List extensionSchemaNodes = Collections - .emptyList(); - private String name; - private Integer value; - - @Override - public QName getQName() { - return qname; - } - - @Override - public SchemaPath getPath() { - return path; - } - - @Override - public String getDescription() { - return description; - } - - @Override - public String getReference() { - return reference; - } - - @Override - public Status getStatus() { - return status; - } - - @Override - public List getUnknownSchemaNodes() { - return extensionSchemaNodes; - } - - @Override - public String getName() { - return name; - } - - @Override - public Integer getValue() { - return value; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((qname == null) ? 0 : qname.hashCode()); - result = prime * result + ((path == null) ? 0 : path.hashCode()); - result = prime * result - + ((description == null) ? 0 : description.hashCode()); - result = prime * result - + ((reference == null) ? 0 : reference.hashCode()); - result = prime * result - + ((status == null) ? 0 : status.hashCode()); - result = prime - * result - + ((extensionSchemaNodes == null) ? 0 - : extensionSchemaNodes.hashCode()); - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + ((value == null) ? 0 : value.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - EnumPairImpl other = (EnumPairImpl) obj; - if (qname == null) { - if (other.qname != null) { - return false; - } - } else if (!qname.equals(other.qname)) { - return false; - } - if (path == null) { - if (other.path != null) { - return false; - } - } else if (!path.equals(other.path)) { - return false; - } - if (description == null) { - if (other.description != null) { - return false; - } - } else if (!description.equals(other.description)) { - return false; - } - if (reference == null) { - if (other.reference != null) { - return false; - } - } else if (!reference.equals(other.reference)) { - return false; - } - if (status == null) { - if (other.status != null) { - return false; - } - } else if (!status.equals(other.status)) { - return false; - } - if (extensionSchemaNodes == null) { - if (other.extensionSchemaNodes != null) { - return false; - } - } else if (!extensionSchemaNodes.equals(other.extensionSchemaNodes)) { - return false; - } - if (name == null) { - if (other.name != null) { - return false; - } - } else if (!name.equals(other.name)) { - return false; - } - if (value == null) { - if (other.value != null) { - return false; - } - } else if (!value.equals(other.value)) { - return false; - } - return true; - } - - @Override - public String toString() { - return EnumTypeDefinition.EnumPair.class.getSimpleName() + "[name=" - + name + ", value=" + value + "]"; - } - }; - - private static List getRangeConstraints( - Type_body_stmtsContext ctx) { - final List rangeConstraints = new ArrayList(); - for (int j = 0; j < ctx.getChildCount(); j++) { - ParseTree numRestrChild = ctx.getChild(j); - if (numRestrChild instanceof Numerical_restrictionsContext) { - for (int k = 0; k < numRestrChild.getChildCount(); k++) { - ParseTree rangeChild = numRestrChild.getChild(k); - if (rangeChild instanceof Range_stmtContext) { - rangeConstraints - .addAll(parseRangeConstraints((Range_stmtContext) rangeChild)); - break; - } - } - } - } - return rangeConstraints; - } - - private static List parseRangeConstraints( - Range_stmtContext ctx) { - List rangeConstraints = new ArrayList(); - String description = null; - String reference = null; - - for (int i = 0; i < ctx.getChildCount(); i++) { - ParseTree child = ctx.getChild(i); - if (child instanceof Description_stmtContext) { - description = stringFromNode(child); - } else if (child instanceof Reference_stmtContext) { - reference = stringFromNode(child); - } - } - - String rangeStr = stringFromNode(ctx); - String trimmed = rangeStr.replace(" ", ""); - String[] splittedRange = trimmed.split("\\|"); - for (String rangeDef : splittedRange) { - String[] splittedRangeDef = rangeDef.split("\\.\\."); - Long min; - Long max; - if (splittedRangeDef.length == 1) { - min = max = parseRangeValue(splittedRangeDef[0]); - } else { - min = parseRangeValue(splittedRangeDef[0]); - max = parseRangeValue(splittedRangeDef[1]); - } - RangeConstraint range = BaseConstraints.rangeConstraint(min, max, - description, reference); - rangeConstraints.add(range); - } - - return rangeConstraints; - } - - private static List getLengthConstraints( - Type_body_stmtsContext ctx) { - List lengthConstraints = new ArrayList(); - for (int j = 0; j < ctx.getChildCount(); j++) { - ParseTree stringRestrChild = ctx.getChild(j); - if (stringRestrChild instanceof String_restrictionsContext) { - for (int k = 0; k < stringRestrChild.getChildCount(); k++) { - ParseTree lengthChild = stringRestrChild.getChild(k); - if (lengthChild instanceof Length_stmtContext) { - lengthConstraints - .addAll(parseLengthConstraints((Length_stmtContext) lengthChild)); - } - } - } - } - return lengthConstraints; - } - - private static List parseLengthConstraints( - Length_stmtContext ctx) { - List lengthConstraints = new ArrayList(); - String description = null; - String reference = null; - - for (int i = 0; i < ctx.getChildCount(); i++) { - ParseTree child = ctx.getChild(i); - if (child instanceof Description_stmtContext) { - description = stringFromNode(child); - } else if (child instanceof Reference_stmtContext) { - reference = stringFromNode(child); - } - } - - String lengthStr = stringFromNode(ctx); - String trimmed = lengthStr.replace(" ", ""); - String[] splittedRange = trimmed.split("\\|"); - for (String rangeDef : splittedRange) { - String[] splittedRangeDef = rangeDef.split("\\.\\."); - Long min; - Long max; - if (splittedRangeDef.length == 1) { - min = max = parseRangeValue(splittedRangeDef[0]); - } else { - min = parseRangeValue(splittedRangeDef[0]); - max = parseRangeValue(splittedRangeDef[1]); - } - LengthConstraint range = BaseConstraints.lengthConstraint(min, max, - description, reference); - lengthConstraints.add(range); - } - - return lengthConstraints; - } - - private static Long parseRangeValue(String value) { - Long result = null; - if (value.equals("min")) { - result = Long.MIN_VALUE; - } else if (value.equals("max")) { - result = Long.MAX_VALUE; - } else { - result = Long.valueOf(value); - } - return result; - } - - private static List getPatternConstraint( - Type_body_stmtsContext ctx) { - List patterns = new ArrayList(); - - out: for (int j = 0; j < ctx.getChildCount(); j++) { - ParseTree stringRestrChild = ctx.getChild(j); - if (stringRestrChild instanceof String_restrictionsContext) { - for (int k = 0; k < stringRestrChild.getChildCount(); k++) { - ParseTree lengthChild = stringRestrChild.getChild(k); - if (lengthChild instanceof Pattern_stmtContext) { - patterns.add(parsePatternConstraint((Pattern_stmtContext) lengthChild)); - if (k == lengthChild.getChildCount() - 1) { - break out; - } - } - } - } - } - return patterns; - } - - /** - * Internal helper method. - * - * @param ctx - * pattern context - * @return PatternConstraint object - */ - private static PatternConstraint parsePatternConstraint( - Pattern_stmtContext ctx) { - String description = null; - String reference = null; - for (int i = 0; i < ctx.getChildCount(); i++) { - ParseTree child = ctx.getChild(i); - if (child instanceof Description_stmtContext) { - description = stringFromNode(child); - } else if (child instanceof Reference_stmtContext) { - reference = stringFromNode(child); - } - } - String pattern = patternStringFromNode(ctx); - return BaseConstraints.patternConstraint(pattern, description, - reference); - } - - public static String patternStringFromNode(final Pattern_stmtContext treeNode) { - String result = ""; - for (int i = 0; i < treeNode.getChildCount(); ++i) { - ParseTree child = treeNode.getChild(i); - if (child instanceof StringContext) { - for(int j = 0; j < child.getChildCount(); j++) { - if(j % 2 == 0) { - String patternToken = child.getChild(j).getText(); - result += patternToken.substring(1, patternToken.length()-1); - } - } - } - } - return result; - } - - private static Integer getFractionDigits(Type_body_stmtsContext ctx) { - for (int j = 0; j < ctx.getChildCount(); j++) { - ParseTree dec64specChild = ctx.getChild(j); - if (dec64specChild instanceof Decimal64_specificationContext) { - return parseFractionDigits((Decimal64_specificationContext) dec64specChild); - } - } - return null; - } - - private static Integer parseFractionDigits( - Decimal64_specificationContext ctx) { - for (int k = 0; k < ctx.getChildCount(); k++) { - ParseTree fdChild = ctx.getChild(k); - if (fdChild instanceof Fraction_digits_stmtContext) { - return Integer.valueOf(stringFromNode(fdChild)); - } - } - return null; - } - - private static List getBits( - Type_body_stmtsContext ctx, List actualPath, URI namespace, - Date revision, String prefix) { - List bits = new ArrayList(); - for (int j = 0; j < ctx.getChildCount(); j++) { - ParseTree bitsSpecChild = ctx.getChild(j); - if (bitsSpecChild instanceof Bits_specificationContext) { - for (int k = 0; k < bitsSpecChild.getChildCount(); k++) { - ParseTree bitChild = bitsSpecChild.getChild(k); - if (bitChild instanceof Bit_stmtContext) { - bits.add(parseBit((Bit_stmtContext) bitChild, - actualPath, namespace, revision, prefix)); - } - } - } - } - return bits; - } - - private static boolean isRequireInstance(Type_body_stmtsContext ctx) { - for (int i = 0; i < ctx.getChildCount(); i++) { - ParseTree child = ctx.getChild(i); - if (child instanceof Require_instance_stmtContext) { - for (int j = 0; j < child.getChildCount(); j++) { - ParseTree reqArg = child.getChild(j); - if (reqArg instanceof Require_instance_argContext) { - return Boolean.valueOf(stringFromNode(reqArg)); - } - } - } - } - return false; - } - - private static BitsTypeDefinition.Bit parseBit(final Bit_stmtContext ctx, - List actualPath, final URI namespace, final Date revision, - final String prefix) { - String name = stringFromNode(ctx); - final QName qname = new QName(namespace, revision, prefix, name); - Long position = null; - - String description = null; - String reference = null; - Status status = Status.CURRENT; - - Stack bitPath = new Stack(); - bitPath.addAll(actualPath); - bitPath.add(name); - - SchemaPath schemaPath = createActualSchemaPath(bitPath, namespace, - revision, prefix); - - for (int i = 0; i < ctx.getChildCount(); i++) { - ParseTree child = ctx.getChild(i); - if (child instanceof Position_stmtContext) { - String positionStr = stringFromNode(child); - position = Long.valueOf(positionStr); - if (position < 0 || position > 4294967295L) { - throw new IllegalArgumentException( - "position value MUST be in the range 0 to 4294967295, but was: " - + position); - } - } else if (child instanceof Description_stmtContext) { - description = stringFromNode(child); - } else if (child instanceof Reference_stmtContext) { - reference = stringFromNode(child); - } else if (child instanceof Status_stmtContext) { - status = parseStatus((Status_stmtContext) child); - } - } - - // TODO: extensionDefinitions - return createBit(qname, schemaPath, description, reference, status, - null, position); - } - - private static BitsTypeDefinition.Bit createBit(final QName qname, - final SchemaPath schemaPath, final String description, - final String reference, final Status status, - final List extensionDefinitions, - final Long position) { - return new BitsTypeDefinition.Bit() { - - @Override - public QName getQName() { - return qname; - } - - @Override - public SchemaPath getPath() { - return schemaPath; - } - - @Override - public String getDescription() { - return description; - } - - @Override - public String getReference() { - return reference; - } - - @Override - public Status getStatus() { - return status; - } - - @Override - public List getUnknownSchemaNodes() { - return extensionDefinitions; - } - - @Override - public Long getPosition() { - return position; - } - - @Override - public String getName() { - return qname.getLocalName(); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result - + ((qname == null) ? 0 : qname.hashCode()); - result = prime * result - + ((schemaPath == null) ? 0 : schemaPath.hashCode()); - result = prime * result - + ((description == null) ? 0 : description.hashCode()); - result = prime * result - + ((reference == null) ? 0 : reference.hashCode()); - result = prime * result - + ((status == null) ? 0 : status.hashCode()); - result = prime * result - + ((position == null) ? 0 : position.hashCode()); - result = prime - * result - + ((extensionDefinitions == null) ? 0 - : extensionDefinitions.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - Bit other = (Bit) obj; - if (qname == null) { - if (other.getQName() != null) { - return false; - } - } else if (!qname.equals(other.getQName())) { - return false; - } - if (schemaPath == null) { - if (other.getPath() != null) { - return false; - } - } else if (!schemaPath.equals(other.getPath())) { - return false; - } - if (description == null) { - if (other.getDescription() != null) { - return false; - } - } else if (!description.equals(other.getDescription())) { - return false; - } - if (reference == null) { - if (other.getReference() != null) { - return false; - } - } else if (!reference.equals(other.getReference())) { - return false; - } - if (status == null) { - if (other.getStatus() != null) { - return false; - } - } else if (!status.equals(other.getStatus())) { - return false; - } - if (extensionDefinitions == null) { - if (other.getUnknownSchemaNodes() != null) { - return false; - } - } else if (!extensionDefinitions.equals(other - .getUnknownSchemaNodes())) { - return false; - } - if (position == null) { - if (other.getPosition() != null) { - return false; - } - } else if (!position.equals(other.getPosition())) { - return false; - } - return true; - } - - @Override - public String toString() { - return Bit.class.getSimpleName() + "[name=" - + qname.getLocalName() + ", position=" + position + "]"; - } - }; - } - - /** - * Parse orderedby statement. - * - * @param childNode - * Ordered_by_stmtContext - * @return true, if orderedby contains value 'user' or false otherwise - */ - public static boolean parseUserOrdered(Ordered_by_stmtContext childNode) { - boolean result = false; - for (int j = 0; j < childNode.getChildCount(); j++) { - ParseTree orderArg = childNode.getChild(j); - if (orderArg instanceof Ordered_by_argContext) { - String orderStr = stringFromNode(orderArg); - if (orderStr.equals("system")) { - result = false; - } else if (orderStr.equals("user")) { - result = true; - } else { - logger.warn("Invalid 'orderedby' statement."); - } - } - } - return result; - } - - /** - * Parse given config context and return true if it contains string 'true', - * false otherwise. - * - * @param ctx - * config context to parse. - * @return true if given context contains string 'true', false otherwise - */ - public static boolean parseConfig(final Config_stmtContext ctx) { - if (ctx != null) { - for (int i = 0; i < ctx.getChildCount(); ++i) { - final ParseTree configContext = ctx.getChild(i); - if (configContext instanceof Config_argContext) { - final String value = stringFromNode(configContext); - if (value.equals("true")) { - return true; - } - } - } - } - return false; - } - - /** - * Parse given type body and creates UnknownType definition. - * - * @param typedefQName - * qname of current type - * @param ctx - * type body - * @return UnknownType object with constraints from parsed type body - */ - public static TypeDefinition parseUnknownTypeBody(QName typedefQName, - Type_body_stmtsContext ctx) { - UnknownType.Builder ut = new UnknownType.Builder(typedefQName); - - if (ctx != null) { - List rangeStatements = getRangeConstraints(ctx); - List lengthStatements = getLengthConstraints(ctx); - List patternStatements = getPatternConstraint(ctx); - Integer fractionDigits = getFractionDigits(ctx); - - ut.rangeStatements(rangeStatements); - ut.lengthStatements(lengthStatements); - ut.patterns(patternStatements); - ut.fractionDigits(fractionDigits); - } - - return ut.build(); - } - - /** - * Create TypeDefinition object based on given type name and type body. - * - * @param typeName - * name of type - * @param typeBody - * type body - * @param actualPath - * current path in schema - * @param namespace - * current namespace - * @param revision - * current revision - * @param prefix - * current prefix - * @return TypeDefinition object based on parsed values. - */ - public static TypeDefinition parseTypeBody(String typeName, - Type_body_stmtsContext typeBody, List actualPath, - URI namespace, Date revision, String prefix) { - TypeDefinition type = null; - - List rangeStatements = getRangeConstraints(typeBody); - Integer fractionDigits = getFractionDigits(typeBody); - List lengthStatements = getLengthConstraints(typeBody); - List patternStatements = getPatternConstraint(typeBody); - List enumConstants = getEnumConstants(typeBody, actualPath, namespace, revision, prefix); - - if (typeName.equals("decimal64")) { - type = YangTypesConverter.javaTypeForBaseYangDecimal64Type( - rangeStatements, fractionDigits); - } else if (typeName.startsWith("int")) { - type = YangTypesConverter.javaTypeForBaseYangSignedIntegerType(typeName, - rangeStatements); - } else if(typeName.startsWith("uint")) { - type = YangTypesConverter.javaTypeForBaseYangUnsignedIntegerType(typeName, - rangeStatements); - } else if (typeName.equals("enumeration")) { - type = new EnumerationType(enumConstants); - } else if (typeName.equals("string")) { - type = new StringType(lengthStatements, patternStatements); - } else if (typeName.equals("bits")) { - type = new BitsType(getBits(typeBody, actualPath, namespace, - revision, prefix)); - } else if (typeName.equals("leafref")) { - final String path = parseLeafrefPath(typeBody); - final boolean absolute = path.startsWith("/"); - RevisionAwareXPath xpath = new RevisionAwareXPathImpl(path, - absolute); - type = new Leafref(actualPath, namespace, revision, xpath); - } else if (typeName.equals("binary")) { - type = new BinaryType(null, lengthStatements, null); - } else if (typeName.equals("instance-identifier")) { - boolean requireInstance = isRequireInstance(typeBody); - type = new InstanceIdentifier(null, requireInstance); - } - return type; - } - - private static String parseLeafrefPath(Type_body_stmtsContext ctx) { - for (int i = 0; i < ctx.getChildCount(); i++) { - ParseTree child = ctx.getChild(i); - if (child instanceof Leafref_specificationContext) { - for (int j = 0; j < child.getChildCount(); j++) { - ParseTree leafRefSpec = child.getChild(j); - if (leafRefSpec instanceof Path_stmtContext) { - return stringFromNode(leafRefSpec); - } - } - } - } - return null; - } - - /** - * Internal helper method for parsing Must_stmtContext. - * - * @param ctx - * Must_stmtContext - * @return an array of strings with following fields: [0] must text [1] - * description [2] reference - */ - public static String[] parseMust(YangParser.Must_stmtContext ctx) { - String[] params = new String[3]; - - String mustText = ""; - String description = null; - String reference = null; - for (int i = 0; i < ctx.getChildCount(); ++i) { - ParseTree child = ctx.getChild(i); - if (child instanceof StringContext) { - final StringContext context = (StringContext) child; - for (int j = 0; j < context.getChildCount(); j++) { - String mustPart = context.getChild(j).getText(); - if (j == 0) { - mustText += mustPart - .substring(0, mustPart.length() - 1); - continue; - } - if (j % 2 == 0) { - mustText += mustPart.substring(1); - } - } - } else if (child instanceof Description_stmtContext) { - description = stringFromNode(child); - } else if (child instanceof Reference_stmtContext) { - reference = stringFromNode(child); - } - } - params[0] = mustText; - params[1] = description; - params[2] = reference; - - return params; - } - - /** - * Parse given tree and set constraints to given builder. - * - * @param ctx - * Context to search. - * @param constraintsBuilder - * ConstraintsBuilder to fill. - */ - public static void parseConstraints(ParseTree ctx, - ConstraintsBuilder constraintsBuilder) { - for (int i = 0; i < ctx.getChildCount(); ++i) { - final ParseTree childNode = ctx.getChild(i); - if (childNode instanceof Max_elements_stmtContext) { - Integer max = Integer.valueOf(stringFromNode(childNode)); - constraintsBuilder.setMinElements(max); - } else if (childNode instanceof Min_elements_stmtContext) { - Integer min = Integer.valueOf(stringFromNode(childNode)); - constraintsBuilder.setMinElements(min); - } else if (childNode instanceof Must_stmtContext) { - String[] mustParams = parseMust((Must_stmtContext) childNode); - constraintsBuilder.addMustDefinition(mustParams[0], - mustParams[1], mustParams[2]); - } else if (childNode instanceof Mandatory_stmtContext) { - for (int j = 0; j < childNode.getChildCount(); j++) { - ParseTree mandatoryTree = ctx.getChild(j); - if (mandatoryTree instanceof Mandatory_argContext) { - Boolean mandatory = Boolean - .valueOf(stringFromNode(mandatoryTree)); - constraintsBuilder.setMandatory(mandatory); - } - } - } else if (childNode instanceof When_stmtContext) { - constraintsBuilder.addWhenCondition(stringFromNode(childNode)); - } - } - } - -} +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/eplv10.html + */ +package org.opendaylight.controller.yang.model.parser.util; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Stack; + +import org.antlr.v4.runtime.tree.ParseTree; +import org.opendaylight.controller.antlrv4.code.gen.YangParser; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Argument_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Bit_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Bits_specificationContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Config_argContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Config_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Decimal64_specificationContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Description_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Enum_specificationContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Enum_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Fraction_digits_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leafref_specificationContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Length_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_argContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Max_elements_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Min_elements_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Must_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Numerical_restrictionsContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_argContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Path_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Pattern_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Position_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Range_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Reference_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Require_instance_argContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Require_instance_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_argContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.StringContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.String_restrictionsContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_body_stmtsContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Units_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.When_stmtContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yin_element_argContext; +import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yin_element_stmtContext; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.RevisionAwareXPath; +import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.Status; +import org.opendaylight.controller.yang.model.api.TypeDefinition; +import org.opendaylight.controller.yang.model.api.UnknownSchemaNode; +import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition; +import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition.Bit; +import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition; +import org.opendaylight.controller.yang.model.api.type.LengthConstraint; +import org.opendaylight.controller.yang.model.api.type.PatternConstraint; +import org.opendaylight.controller.yang.model.api.type.RangeConstraint; +import org.opendaylight.controller.yang.model.parser.builder.api.SchemaNodeBuilder; +import org.opendaylight.controller.yang.model.parser.builder.impl.ConstraintsBuilder; +import org.opendaylight.controller.yang.model.util.BaseConstraints; +import org.opendaylight.controller.yang.model.util.BinaryType; +import org.opendaylight.controller.yang.model.util.BitsType; +import org.opendaylight.controller.yang.model.util.EnumerationType; +import org.opendaylight.controller.yang.model.util.InstanceIdentifier; +import org.opendaylight.controller.yang.model.util.Leafref; +import org.opendaylight.controller.yang.model.util.RevisionAwareXPathImpl; +import org.opendaylight.controller.yang.model.util.StringType; +import org.opendaylight.controller.yang.model.util.UnknownType; +import org.opendaylight.controller.yang.model.util.YangTypesConverter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class YangModelBuilderUtil { + + private static final Logger logger = LoggerFactory + .getLogger(YangModelBuilderUtil.class); + + /** + * Parse given tree and get first string value. + * + * @param treeNode + * tree to parse + * @return first string value from given tree + */ + public static String stringFromNode(final ParseTree treeNode) { + final String result = ""; + for (int i = 0; i < treeNode.getChildCount(); ++i) { + if (treeNode.getChild(i) instanceof StringContext) { + final StringContext context = (StringContext) treeNode + .getChild(i); + if (context != null) { + return context.getChild(0).getText().replace("\"", ""); + } + } + } + return result; + } + + /** + * Parse 'description', 'reference' and 'status' statements and fill in + * given builder. + * + * @param ctx + * context to parse + * @param builder + * builder to fill in with parsed statements + */ + public static void parseSchemaNodeArgs(ParseTree ctx, + SchemaNodeBuilder builder) { + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree child = ctx.getChild(i); + if (child instanceof Description_stmtContext) { + String desc = stringFromNode(child); + builder.setDescription(desc); + } else if (child instanceof Reference_stmtContext) { + String ref = stringFromNode(child); + builder.setReference(ref); + } else if (child instanceof Status_stmtContext) { + Status status = parseStatus((Status_stmtContext) child); + builder.setStatus(status); + } + } + } + + /** + * Parse given context and return its value; + * + * @param ctx + * status context + * @return value parsed from context + */ + public static Status parseStatus(Status_stmtContext ctx) { + Status result = null; + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree statusArg = ctx.getChild(i); + if (statusArg instanceof Status_argContext) { + String statusArgStr = stringFromNode(statusArg); + if ("current".equals(statusArgStr)) { + result = Status.CURRENT; + } else if ("deprecated".equals(statusArgStr)) { + result = Status.DEPRECATED; + } else if ("obsolete".equals(statusArgStr)) { + result = Status.OBSOLETE; + } else { + logger.warn("Invalid 'status' statement: " + statusArgStr); + } + } + } + return result; + } + + /** + * Parse given tree and returns units statement as string. + * + * @param ctx + * context to parse + * @return value of units statement as string or null if there is no units + * statement + */ + public static String parseUnits(ParseTree ctx) { + String units = null; + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree child = ctx.getChild(i); + if (child instanceof Units_stmtContext) { + units = stringFromNode(child); + break; + } + } + return units; + } + + /** + * Create SchemaPath object from given path list with namespace, revision + * and prefix based on given values. + * + * @param actualPath + * current position in model + * @param namespace + * @param revision + * @param prefix + * @return SchemaPath object. + */ + public static SchemaPath createActualSchemaPath(List actualPath, + URI namespace, Date revision, String prefix) { + final List path = new ArrayList(); + QName qname; + // start from index 1 - module name ommited + for (int i = 1; i < actualPath.size(); i++) { + qname = new QName(namespace, revision, prefix, actualPath.get(i)); + path.add(qname); + } + return new SchemaPath(path, true); + } + + /** + * Create SchemaPath from given string. + * + * @param augmentPath + * string representation of path + * @return SchemaPath object + */ + public static SchemaPath parseAugmentPath(String augmentPath) { + boolean absolute = augmentPath.startsWith("/"); + String[] splittedPath = augmentPath.split("/"); + List path = new ArrayList(); + QName name; + for (String pathElement : splittedPath) { + if (pathElement.length() > 0) { + String[] splittedElement = pathElement.split(":"); + if (splittedElement.length == 1) { + name = new QName(null, null, null, splittedElement[0]); + } else { + name = new QName(null, null, splittedElement[0], + splittedElement[1]); + } + path.add(name); + } + } + return new SchemaPath(path, absolute); + } + + /** + * Create java.util.List of QName objects from given key definition as + * string. + * + * @param keyDefinition + * key definition as string + * @param namespace + * current namespace + * @param revision + * current revision + * @param prefix + * current prefix + * @return YANG list key as java.util.List of QName objects + */ + public static List createListKey(String keyDefinition, + URI namespace, Date revision, String prefix) { + List key = new ArrayList(); + String[] splittedKey = keyDefinition.split(" "); + + QName qname = null; + for (String keyElement : splittedKey) { + if (keyElement.length() != 0) { + qname = new QName(namespace, revision, prefix, keyElement); + key.add(qname); + } + } + return key; + } + + private static List getEnumConstants( + Type_body_stmtsContext ctx, List path, URI namespace, + Date revision, String prefix) { + List enumConstants = new ArrayList(); + + out: for (int j = 0; j < ctx.getChildCount(); j++) { + ParseTree enumSpecChild = ctx.getChild(j); + if (enumSpecChild instanceof Enum_specificationContext) { + for (int k = 0; k < enumSpecChild.getChildCount(); k++) { + ParseTree enumChild = enumSpecChild.getChild(k); + if (enumChild instanceof Enum_stmtContext) { + enumConstants.add(createEnumPair( + (Enum_stmtContext) enumChild, k, path, + namespace, revision, prefix)); + if (k == enumSpecChild.getChildCount() - 1) { + break out; + } + } + } + } + } + return enumConstants; + } + + private static EnumTypeDefinition.EnumPair createEnumPair( + Enum_stmtContext ctx, final int value, List path, + final URI namespace, final Date revision, final String prefix) { + final String name = stringFromNode(ctx); + final QName qname = new QName(namespace, revision, prefix, name); + String description = null; + String reference = null; + Status status = null; + List enumPairPath = new ArrayList(path); + enumPairPath.add(name); + + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree child = ctx.getChild(i); + if (child instanceof Description_stmtContext) { + description = stringFromNode(child); + } else if (child instanceof Reference_stmtContext) { + reference = stringFromNode(child); + } else if (child instanceof Status_stmtContext) { + status = parseStatus((Status_stmtContext) child); + } + } + + EnumPairImpl result = new EnumPairImpl(); + result.qname = qname; + result.path = createActualSchemaPath(enumPairPath, namespace, revision, + prefix); + result.description = description; + result.reference = reference; + result.status = status; + result.name = name; + result.value = value; + return result; + } + + private static class EnumPairImpl implements EnumTypeDefinition.EnumPair { + private QName qname; + private SchemaPath path; + private String description; + private String reference; + private Status status; + private List extensionSchemaNodes = Collections + .emptyList(); + private String name; + private Integer value; + + @Override + public QName getQName() { + return qname; + } + + @Override + public SchemaPath getPath() { + return path; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getReference() { + return reference; + } + + @Override + public Status getStatus() { + return status; + } + + @Override + public List getUnknownSchemaNodes() { + return extensionSchemaNodes; + } + + @Override + public String getName() { + return name; + } + + @Override + public Integer getValue() { + return value; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((qname == null) ? 0 : qname.hashCode()); + result = prime * result + ((path == null) ? 0 : path.hashCode()); + result = prime + * result + + ((extensionSchemaNodes == null) ? 0 + : extensionSchemaNodes.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((value == null) ? 0 : value.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + EnumPairImpl other = (EnumPairImpl) obj; + if (qname == null) { + if (other.qname != null) { + return false; + } + } else if (!qname.equals(other.qname)) { + return false; + } + if (path == null) { + if (other.path != null) { + return false; + } + } else if (!path.equals(other.path)) { + return false; + } + if (extensionSchemaNodes == null) { + if (other.extensionSchemaNodes != null) { + return false; + } + } else if (!extensionSchemaNodes.equals(other.extensionSchemaNodes)) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + if (value == null) { + if (other.value != null) { + return false; + } + } else if (!value.equals(other.value)) { + return false; + } + return true; + } + + @Override + public String toString() { + return EnumTypeDefinition.EnumPair.class.getSimpleName() + "[name=" + + name + ", value=" + value + "]"; + } + }; + + private static List getRangeConstraints( + Type_body_stmtsContext ctx) { + final List rangeConstraints = new ArrayList(); + for (int j = 0; j < ctx.getChildCount(); j++) { + ParseTree numRestrChild = ctx.getChild(j); + if (numRestrChild instanceof Numerical_restrictionsContext) { + for (int k = 0; k < numRestrChild.getChildCount(); k++) { + ParseTree rangeChild = numRestrChild.getChild(k); + if (rangeChild instanceof Range_stmtContext) { + rangeConstraints + .addAll(parseRangeConstraints((Range_stmtContext) rangeChild)); + break; + } + } + } + } + return rangeConstraints; + } + + private static List parseRangeConstraints( + Range_stmtContext ctx) { + List rangeConstraints = new ArrayList(); + String description = null; + String reference = null; + + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree child = ctx.getChild(i); + if (child instanceof Description_stmtContext) { + description = stringFromNode(child); + } else if (child instanceof Reference_stmtContext) { + reference = stringFromNode(child); + } + } + + String rangeStr = stringFromNode(ctx); + String trimmed = rangeStr.replace(" ", ""); + String[] splittedRange = trimmed.split("\\|"); + for (String rangeDef : splittedRange) { + String[] splittedRangeDef = rangeDef.split("\\.\\."); + Number min; + Number max; + if (splittedRangeDef.length == 1) { + min = max = parseRangeValue(splittedRangeDef[0]); + } else { + min = parseRangeValue(splittedRangeDef[0]); + max = parseRangeValue(splittedRangeDef[1]); + } + RangeConstraint range = BaseConstraints.rangeConstraint(min, max, + description, reference); + rangeConstraints.add(range); + } + + return rangeConstraints; + } + + private static List getLengthConstraints( + Type_body_stmtsContext ctx) { + List lengthConstraints = new ArrayList(); + for (int j = 0; j < ctx.getChildCount(); j++) { + ParseTree stringRestrChild = ctx.getChild(j); + if (stringRestrChild instanceof String_restrictionsContext) { + for (int k = 0; k < stringRestrChild.getChildCount(); k++) { + ParseTree lengthChild = stringRestrChild.getChild(k); + if (lengthChild instanceof Length_stmtContext) { + lengthConstraints + .addAll(parseLengthConstraints((Length_stmtContext) lengthChild)); + } + } + } + } + return lengthConstraints; + } + + private static List parseLengthConstraints( + Length_stmtContext ctx) { + List lengthConstraints = new ArrayList(); + String description = null; + String reference = null; + + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree child = ctx.getChild(i); + if (child instanceof Description_stmtContext) { + description = stringFromNode(child); + } else if (child instanceof Reference_stmtContext) { + reference = stringFromNode(child); + } + } + + String lengthStr = stringFromNode(ctx); + String trimmed = lengthStr.replace(" ", ""); + String[] splittedRange = trimmed.split("\\|"); + for (String rangeDef : splittedRange) { + String[] splittedRangeDef = rangeDef.split("\\.\\."); + Number min; + Number max; + if (splittedRangeDef.length == 1) { + min = max = parseRangeValue(splittedRangeDef[0]); + } else { + min = parseRangeValue(splittedRangeDef[0]); + max = parseRangeValue(splittedRangeDef[1]); + } + LengthConstraint range = BaseConstraints.lengthConstraint(min, max, + description, reference); + lengthConstraints.add(range); + } + + return lengthConstraints; + } + + private static Number parseRangeValue(String value) { + Number result = null; + if ("min".equals(value) || "max".equals(value)) { + result = new UnknownBoundaryNumber(value); + } else { + try { + result = Long.valueOf(value); + } catch (NumberFormatException e) { + throw new YangParseException("Unable to parse range value '" + + value + "'.", e); + } + } + return result; + } + + private static List getPatternConstraint( + Type_body_stmtsContext ctx) { + List patterns = new ArrayList(); + + out: for (int j = 0; j < ctx.getChildCount(); j++) { + ParseTree stringRestrChild = ctx.getChild(j); + if (stringRestrChild instanceof String_restrictionsContext) { + for (int k = 0; k < stringRestrChild.getChildCount(); k++) { + ParseTree lengthChild = stringRestrChild.getChild(k); + if (lengthChild instanceof Pattern_stmtContext) { + patterns.add(parsePatternConstraint((Pattern_stmtContext) lengthChild)); + if (k == lengthChild.getChildCount() - 1) { + break out; + } + } + } + } + } + return patterns; + } + + /** + * Internal helper method. + * + * @param ctx + * pattern context + * @return PatternConstraint object + */ + private static PatternConstraint parsePatternConstraint( + Pattern_stmtContext ctx) { + String description = null; + String reference = null; + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree child = ctx.getChild(i); + if (child instanceof Description_stmtContext) { + description = stringFromNode(child); + } else if (child instanceof Reference_stmtContext) { + reference = stringFromNode(child); + } + } + String pattern = patternStringFromNode(ctx); + return BaseConstraints.patternConstraint(pattern, description, + reference); + } + + /** + * Parse given context and return pattern value. + * + * @param ctx + * context to parse + * @return pattern value as String + */ + public static String patternStringFromNode(final Pattern_stmtContext ctx) { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < ctx.getChildCount(); ++i) { + ParseTree child = ctx.getChild(i); + if (child instanceof StringContext) { + for (int j = 0; j < child.getChildCount(); j++) { + if (j % 2 == 0) { + String patternToken = child.getChild(j).getText(); + result.append(patternToken.substring(1, + patternToken.length() - 1)); + } + } + } + } + return result.toString(); + } + + private static Integer getFractionDigits(Type_body_stmtsContext ctx) { + Integer result = null; + for (int j = 0; j < ctx.getChildCount(); j++) { + ParseTree dec64specChild = ctx.getChild(j); + if (dec64specChild instanceof Decimal64_specificationContext) { + result = parseFractionDigits((Decimal64_specificationContext) dec64specChild); + } + } + return result; + } + + private static Integer parseFractionDigits( + Decimal64_specificationContext ctx) { + Integer result = null; + for (int k = 0; k < ctx.getChildCount(); k++) { + ParseTree fdChild = ctx.getChild(k); + if (fdChild instanceof Fraction_digits_stmtContext) { + String value = stringFromNode(fdChild); + try { + result = Integer.valueOf(value); + } catch (NumberFormatException e) { + throw new YangParseException( + "Unable to parse fraction digits value '" + value + + "'.", e); + } + } + } + return result; + } + + private static List getBits( + Type_body_stmtsContext ctx, List actualPath, URI namespace, + Date revision, String prefix) { + List bits = new ArrayList(); + for (int j = 0; j < ctx.getChildCount(); j++) { + ParseTree bitsSpecChild = ctx.getChild(j); + if (bitsSpecChild instanceof Bits_specificationContext) { + long highestPosition = -1; + for (int k = 0; k < bitsSpecChild.getChildCount(); k++) { + ParseTree bitChild = bitsSpecChild.getChild(k); + if (bitChild instanceof Bit_stmtContext) { + Bit bit = parseBit((Bit_stmtContext) bitChild, + highestPosition, actualPath, namespace, + revision, prefix); + if (bit.getPosition() > highestPosition) { + highestPosition = bit.getPosition(); + } + bits.add(bit); + } + } + } + } + return bits; + } + + private static BitsTypeDefinition.Bit parseBit(final Bit_stmtContext ctx, + long highestPosition, List actualPath, final URI namespace, + final Date revision, final String prefix) { + String name = stringFromNode(ctx); + final QName qname = new QName(namespace, revision, prefix, name); + Long position = null; + + String description = null; + String reference = null; + Status status = Status.CURRENT; + + Stack bitPath = new Stack(); + bitPath.addAll(actualPath); + bitPath.add(name); + + SchemaPath schemaPath = createActualSchemaPath(bitPath, namespace, + revision, prefix); + + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree child = ctx.getChild(i); + if (child instanceof Position_stmtContext) { + String positionStr = stringFromNode(child); + position = Long.valueOf(positionStr); + } else if (child instanceof Description_stmtContext) { + description = stringFromNode(child); + } else if (child instanceof Reference_stmtContext) { + reference = stringFromNode(child); + } else if (child instanceof Status_stmtContext) { + status = parseStatus((Status_stmtContext) child); + } + } + + if (position == null) { + position = highestPosition + 1; + } + if (position < 0 || position > 4294967295L) { + throw new YangParseException( + "Error on bit '" + + name + + "': the position value MUST be in the range 0 to 4294967295"); + } + + final List extensionNodes = Collections.emptyList(); + return createBit(qname, schemaPath, description, reference, status, + extensionNodes, position); + } + + private static BitsTypeDefinition.Bit createBit(final QName qname, + final SchemaPath schemaPath, final String description, + final String reference, final Status status, + final List unknownNodes, final Long position) { + return new BitsTypeDefinition.Bit() { + + @Override + public QName getQName() { + return qname; + } + + @Override + public SchemaPath getPath() { + return schemaPath; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getReference() { + return reference; + } + + @Override + public Status getStatus() { + return status; + } + + @Override + public List getUnknownSchemaNodes() { + return unknownNodes; + } + + @Override + public Long getPosition() { + return position; + } + + @Override + public String getName() { + return qname.getLocalName(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((qname == null) ? 0 : qname.hashCode()); + result = prime * result + + ((schemaPath == null) ? 0 : schemaPath.hashCode()); + result = prime * result + + ((position == null) ? 0 : position.hashCode()); + result = prime + * result + + ((unknownNodes == null) ? 0 : unknownNodes.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Bit other = (Bit) obj; + if (qname == null) { + if (other.getQName() != null) { + return false; + } + } else if (!qname.equals(other.getQName())) { + return false; + } + if (schemaPath == null) { + if (other.getPath() != null) { + return false; + } + } else if (!schemaPath.equals(other.getPath())) { + return false; + } + if (unknownNodes == null) { + if (other.getUnknownSchemaNodes() != null) { + return false; + } + } else if (!unknownNodes.equals(other.getUnknownSchemaNodes())) { + return false; + } + if (position == null) { + if (other.getPosition() != null) { + return false; + } + } else if (!position.equals(other.getPosition())) { + return false; + } + return true; + } + + @Override + public String toString() { + return Bit.class.getSimpleName() + "[name=" + + qname.getLocalName() + ", position=" + position + "]"; + } + }; + } + + /** + * Parse orderedby statement. + * + * @param childNode + * Ordered_by_stmtContext + * @return true, if orderedby contains value 'user' or false otherwise + */ + public static boolean parseUserOrdered(Ordered_by_stmtContext childNode) { + boolean result = false; + for (int j = 0; j < childNode.getChildCount(); j++) { + ParseTree orderArg = childNode.getChild(j); + if (orderArg instanceof Ordered_by_argContext) { + String orderStr = stringFromNode(orderArg); + if ("system".equals(orderStr)) { + result = false; + } else if ("user".equals(orderStr)) { + result = true; + } else { + logger.warn("Invalid 'orderedby' statement."); + } + } + } + return result; + } + + /** + * Parse given config context and return true if it contains string 'true', + * false otherwise. + * + * @param ctx + * config context to parse. + * @return true if given context contains string 'true', false otherwise + */ + public static boolean parseConfig(final Config_stmtContext ctx) { + boolean result = false; + if (ctx != null) { + for (int i = 0; i < ctx.getChildCount(); ++i) { + final ParseTree configContext = ctx.getChild(i); + if (configContext instanceof Config_argContext) { + final String value = stringFromNode(configContext); + if ("true".equals(value)) { + result = true; + break; + } + } + } + } + return result; + } + + /** + * Parse given type body and creates UnknownType definition. + * + * @param typedefQName + * qname of current type + * @param ctx + * type body + * @return UnknownType object with constraints from parsed type body + */ + public static TypeDefinition parseUnknownTypeBody(QName typedefQName, + Type_body_stmtsContext ctx) { + UnknownType.Builder unknownType = new UnknownType.Builder(typedefQName); + + if (ctx != null) { + List rangeStatements = getRangeConstraints(ctx); + List lengthStatements = getLengthConstraints(ctx); + List patternStatements = getPatternConstraint(ctx); + Integer fractionDigits = getFractionDigits(ctx); + + unknownType.rangeStatements(rangeStatements); + unknownType.lengthStatements(lengthStatements); + unknownType.patterns(patternStatements); + unknownType.fractionDigits(fractionDigits); + } + + return unknownType.build(); + } + + /** + * Create TypeDefinition object based on given type name and type body. + * + * @param typeName + * name of type + * @param typeBody + * type body + * @param actualPath + * current path in schema + * @param namespace + * current namespace + * @param revision + * current revision + * @param prefix + * current prefix + * @return TypeDefinition object based on parsed values. + */ + public static TypeDefinition parseTypeBody(String typeName, + Type_body_stmtsContext typeBody, List actualPath, + URI namespace, Date revision, String prefix) { + TypeDefinition type = null; + + List rangeStatements = getRangeConstraints(typeBody); + Integer fractionDigits = getFractionDigits(typeBody); + List lengthStatements = getLengthConstraints(typeBody); + List patternStatements = getPatternConstraint(typeBody); + List enumConstants = getEnumConstants( + typeBody, actualPath, namespace, revision, prefix); + + if ("decimal64".equals(typeName)) { + type = YangTypesConverter.javaTypeForBaseYangDecimal64Type( + rangeStatements, fractionDigits); + } else if (typeName.startsWith("int")) { + type = YangTypesConverter.javaTypeForBaseYangSignedIntegerType( + typeName, rangeStatements); + } else if (typeName.startsWith("uint")) { + type = YangTypesConverter.javaTypeForBaseYangUnsignedIntegerType( + typeName, rangeStatements); + } else if ("enumeration".equals(typeName)) { + type = new EnumerationType(enumConstants); + } else if ("string".equals(typeName)) { + type = new StringType(lengthStatements, patternStatements); + } else if ("bits".equals(typeName)) { + type = new BitsType(getBits(typeBody, actualPath, namespace, + revision, prefix)); + } else if ("leafref".equals(typeName)) { + final String path = parseLeafrefPath(typeBody); + final boolean absolute = path.startsWith("/"); + RevisionAwareXPath xpath = new RevisionAwareXPathImpl(path, + absolute); + type = new Leafref(xpath); + } else if ("binary".equals(typeName)) { + List bytes = Collections.emptyList(); + type = new BinaryType(bytes, lengthStatements, null); + } else if ("instance-identifier".equals(typeName)) { + boolean requireInstance = isRequireInstance(typeBody); + type = new InstanceIdentifier(null, requireInstance); + } + return type; + } + + private static boolean isRequireInstance(Type_body_stmtsContext ctx) { + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree child = ctx.getChild(i); + if (child instanceof Require_instance_stmtContext) { + for (int j = 0; j < child.getChildCount(); j++) { + ParseTree reqArg = child.getChild(j); + if (reqArg instanceof Require_instance_argContext) { + return Boolean.valueOf(stringFromNode(reqArg)); + } + } + } + } + return false; + } + + private static String parseLeafrefPath(Type_body_stmtsContext ctx) { + for (int i = 0; i < ctx.getChildCount(); i++) { + ParseTree child = ctx.getChild(i); + if (child instanceof Leafref_specificationContext) { + for (int j = 0; j < child.getChildCount(); j++) { + ParseTree leafRefSpec = child.getChild(j); + if (leafRefSpec instanceof Path_stmtContext) { + return stringFromNode(leafRefSpec); + } + } + } + } + return null; + } + + /** + * Internal helper method for parsing Must_stmtContext. + * + * @param ctx + * Must_stmtContext + * @return an array of strings with following fields: [0] must text [1] + * description [2] reference + */ + public static String[] parseMust(YangParser.Must_stmtContext ctx) { + String[] params = new String[3]; + + StringBuilder mustText = new StringBuilder(); + String description = null; + String reference = null; + for (int i = 0; i < ctx.getChildCount(); ++i) { + ParseTree child = ctx.getChild(i); + if (child instanceof StringContext) { + final StringContext context = (StringContext) child; + for (int j = 0; j < context.getChildCount(); j++) { + String mustPart = context.getChild(j).getText(); + if (j == 0) { + mustText.append(mustPart.substring(0, + mustPart.length() - 1)); + continue; + } + if (j % 2 == 0) { + mustText.append(mustPart.substring(1)); + } + } + } else if (child instanceof Description_stmtContext) { + description = stringFromNode(child); + } else if (child instanceof Reference_stmtContext) { + reference = stringFromNode(child); + } + } + params[0] = mustText.toString(); + params[1] = description; + params[2] = reference; + + return params; + } + + /** + * Parse given tree and set constraints to given builder. + * + * @param ctx + * Context to search. + * @param constraintsBuilder + * ConstraintsBuilder to fill. + */ + public static void parseConstraints(ParseTree ctx, + ConstraintsBuilder constraintsBuilder) { + for (int i = 0; i < ctx.getChildCount(); ++i) { + final ParseTree childNode = ctx.getChild(i); + if (childNode instanceof Max_elements_stmtContext) { + Integer max = Integer.valueOf(stringFromNode(childNode)); + constraintsBuilder.setMinElements(max); + } else if (childNode instanceof Min_elements_stmtContext) { + Integer min = Integer.valueOf(stringFromNode(childNode)); + constraintsBuilder.setMinElements(min); + } else if (childNode instanceof Must_stmtContext) { + String[] mustParams = parseMust((Must_stmtContext) childNode); + constraintsBuilder.addMustDefinition(mustParams[0], + mustParams[1], mustParams[2]); + } else if (childNode instanceof Mandatory_stmtContext) { + for (int j = 0; j < childNode.getChildCount(); j++) { + ParseTree mandatoryTree = ctx.getChild(j); + if (mandatoryTree instanceof Mandatory_argContext) { + Boolean mandatory = Boolean + .valueOf(stringFromNode(mandatoryTree)); + constraintsBuilder.setMandatory(mandatory); + } + } + } else if (childNode instanceof When_stmtContext) { + constraintsBuilder.addWhenCondition(stringFromNode(childNode)); + } + } + } + + /** + * Parse given context and return yin value. + * + * @param ctx + * context to parse + * @return true if value is 'true', false otherwise + */ + public static boolean parseYinValue(Argument_stmtContext ctx) { + boolean yinValue = false; + outer: for (int j = 0; j < ctx.getChildCount(); j++) { + ParseTree yin = ctx.getChild(j); + if (yin instanceof Yin_element_stmtContext) { + for (int k = 0; k < yin.getChildCount(); k++) { + ParseTree yinArg = yin.getChild(k); + if (yinArg instanceof Yin_element_argContext) { + String yinString = stringFromNode(yinArg); + if ("true".equals(yinString)) { + yinValue = true; + break outer; + } + } + } + } + } + return yinValue; + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/YangParseException.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/YangParseException.java index bc1c9d6ac2..331869a0f7 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/YangParseException.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/util/YangParseException.java @@ -15,4 +15,8 @@ public class YangParseException extends RuntimeException { super(errorMsg); } + public YangParseException(String errorMsg, Exception exception) { + super(errorMsg, exception); + } + } diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/builder/impl/ContainerSchemaNodeBuilderTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/builder/impl/ContainerSchemaNodeBuilderTest.java deleted file mode 100644 index 709d5e3750..0000000000 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/builder/impl/ContainerSchemaNodeBuilderTest.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.yang.model.parser.builder.impl; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.when; - -import java.net.URI; -import java.util.Date; -import java.util.HashSet; -import java.util.Set; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.opendaylight.controller.yang.common.QName; -import org.opendaylight.controller.yang.model.api.AugmentationSchema; -import org.opendaylight.controller.yang.model.api.ContainerSchemaNode; -import org.opendaylight.controller.yang.model.api.GroupingDefinition; -import org.opendaylight.controller.yang.model.api.SchemaPath; -import org.opendaylight.controller.yang.model.api.Status; -import org.opendaylight.controller.yang.model.api.TypeDefinition; -import org.opendaylight.controller.yang.model.api.UsesNode; -import org.opendaylight.controller.yang.model.parser.builder.api.GroupingBuilder; -import org.opendaylight.controller.yang.model.parser.builder.api.UsesNodeBuilder; - -public class ContainerSchemaNodeBuilderTest { - - private ContainerSchemaNodeBuilder tested; - - private final String NAME = "test-container"; - - private final URI namespace = URI.create("test:container.name"); - private final Date revision = new Date(); - private final String prefix = "x"; - - private SchemaPath schemaPath; - private final String description = "description of container"; - private final String reference = "reference"; - - private QName typedefQName; - private TypedefBuilder typeBuilder; - @Mock - private AugmentationSchema augment; - @Mock - private UsesNodeBuilder usesBuilder; - @Mock - private UsesNode uses; - @Mock - private GroupingBuilder groupingBuilder; - @Mock - private GroupingDefinition grouping; - - @Before - public void init() { - MockitoAnnotations.initMocks(this); - when(usesBuilder.build()).thenReturn(uses); - when(groupingBuilder.build()).thenReturn(grouping); - - schemaPath = TestUtils.createSchemaPath(true, namespace, "main", - "interface"); - typedefQName = new QName(namespace, "test-type"); - typeBuilder = new TypedefBuilder(typedefQName); - - QName qname = new QName(namespace, revision, prefix, NAME); - tested = new ContainerSchemaNodeBuilder(qname); - } - - @Test - public void test() { - tested.addTypedef(typeBuilder); - tested.setPath(schemaPath); - tested.setDescription(description); - tested.setReference(reference); - tested.setStatus(Status.OBSOLETE); - tested.setConfiguration(false); - tested.addUsesNode(usesBuilder); - tested.addAugmentation(augment); - tested.setPresenceContainer(true); - - ContainerSchemaNode result = tested.build(); - - Set> expectedTypedefs = result.getTypeDefinitions(); - assertEquals(1, expectedTypedefs.size()); - assertEquals(typedefQName, expectedTypedefs.iterator().next() - .getQName()); - - Set expectedAugments = new HashSet(); - expectedAugments.add(augment); - assertEquals(expectedAugments, result.getAvailableAugmentations()); - - assertEquals(schemaPath, result.getPath()); - assertEquals(description, result.getDescription()); - assertEquals(reference, result.getReference()); - assertEquals(Status.OBSOLETE, result.getStatus()); - assertFalse(result.isConfiguration()); - - Set expectedUses = new HashSet(); - expectedUses.add(uses); - assertEquals(expectedUses, result.getUses()); - - assertTrue(result.isPresenceContainer()); - } - -} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/builder/impl/LeafListSchemaNodeBuilderTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/builder/impl/LeafListSchemaNodeBuilderTest.java deleted file mode 100644 index 367669f8df..0000000000 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/builder/impl/LeafListSchemaNodeBuilderTest.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.yang.model.parser.builder.impl; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.when; - -import java.net.URI; -import java.util.Date; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.opendaylight.controller.yang.common.QName; -import org.opendaylight.controller.yang.model.api.GroupingDefinition; -import org.opendaylight.controller.yang.model.api.LeafListSchemaNode; -import org.opendaylight.controller.yang.model.api.SchemaPath; -import org.opendaylight.controller.yang.model.api.Status; -import org.opendaylight.controller.yang.model.api.TypeDefinition; -import org.opendaylight.controller.yang.model.api.UsesNode; -import org.opendaylight.controller.yang.model.parser.builder.api.GroupingBuilder; -import org.opendaylight.controller.yang.model.parser.builder.api.UsesNodeBuilder; - -public class LeafListSchemaNodeBuilderTest { - - private LeafListSchemaNodeBuilder tested; - - private final String NAME = "test-leaf"; - - private final URI namespace = URI.create("test:leaf.name"); - private final Date revision = new Date(); - private final String prefix = "x"; - - private SchemaPath schemaPath; - private final String description = "description of container"; - private final String reference = "reference"; - - private QName typedefQName; - private TypeDefinition type; - - @Mock - private UsesNodeBuilder usesBuilder; - @Mock - private UsesNode uses; - @Mock - private GroupingBuilder groupingBuilder; - @Mock - private GroupingDefinition grouping; - - @Before - public void init() { - MockitoAnnotations.initMocks(this); - when(usesBuilder.build()).thenReturn(uses); - when(groupingBuilder.build()).thenReturn(grouping); - - schemaPath = TestUtils.createSchemaPath(true, namespace, "main", - "interface"); - typedefQName = new QName(namespace, "test-type"); - TypedefBuilder typeBuilder = new TypedefBuilder(typedefQName); - type = typeBuilder.build(); - - QName qname = new QName(namespace, revision, prefix, NAME); - tested = new LeafListSchemaNodeBuilder(qname); - } - - @Test - public void test() { - tested.setType(type); - tested.setPath(schemaPath); - tested.setDescription(description); - tested.setReference(reference); - tested.setStatus(Status.OBSOLETE); - tested.setConfiguration(false); - - LeafListSchemaNode result = tested.build(); - - assertEquals(type, result.getType()); - assertEquals(schemaPath, result.getPath()); - assertEquals(description, result.getDescription()); - assertEquals(reference, result.getReference()); - assertEquals(Status.OBSOLETE, result.getStatus()); - assertFalse(result.isConfiguration()); - } - -} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/builder/impl/LeafSchemaNodeBuilderTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/builder/impl/LeafSchemaNodeBuilderTest.java deleted file mode 100644 index 622c82d4fc..0000000000 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/builder/impl/LeafSchemaNodeBuilderTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.yang.model.parser.builder.impl; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.when; - -import java.net.URI; -import java.util.Date; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.opendaylight.controller.yang.common.QName; -import org.opendaylight.controller.yang.model.api.GroupingDefinition; -import org.opendaylight.controller.yang.model.api.LeafSchemaNode; -import org.opendaylight.controller.yang.model.api.SchemaPath; -import org.opendaylight.controller.yang.model.api.Status; -import org.opendaylight.controller.yang.model.api.TypeDefinition; -import org.opendaylight.controller.yang.model.api.UsesNode; -import org.opendaylight.controller.yang.model.parser.builder.api.GroupingBuilder; -import org.opendaylight.controller.yang.model.parser.builder.api.UsesNodeBuilder; - -public class LeafSchemaNodeBuilderTest { - - private LeafSchemaNodeBuilder tested; - - private final String NAME = "test-leaf"; - - private final URI namespace = URI.create("test:leaf.name"); - private final Date revision = new Date(); - private final String prefix = "x"; - - private SchemaPath schemaPath; - private final String description = "description of container"; - private final String reference = "reference"; - - private QName typedefQName; - private TypeDefinition type; - @Mock - private UsesNodeBuilder usesBuilder; - @Mock - private UsesNode uses; - @Mock - private GroupingBuilder groupingBuilder; - @Mock - private GroupingDefinition grouping; - - @Before - public void init() { - MockitoAnnotations.initMocks(this); - when(usesBuilder.build()).thenReturn(uses); - when(groupingBuilder.build()).thenReturn(grouping); - - schemaPath = TestUtils.createSchemaPath(true, namespace, "main", - "interface"); - typedefQName = new QName(namespace, "test-type"); - TypedefBuilder typeBuilder = new TypedefBuilder(typedefQName); - type = typeBuilder.build(); - - QName qname = new QName(namespace, revision, prefix, NAME); - tested = new LeafSchemaNodeBuilder(qname); - } - - @Test - public void test() { - tested.setType(type); - tested.setPath(schemaPath); - tested.setDescription(description); - tested.setReference(reference); - tested.setStatus(Status.OBSOLETE); - tested.setConfiguration(false); - - LeafSchemaNode result = tested.build(); - - assertEquals(type, result.getType()); - assertEquals(schemaPath, result.getPath()); - assertEquals(description, result.getDescription()); - assertEquals(reference, result.getReference()); - assertEquals(Status.OBSOLETE, result.getStatus()); - assertFalse(result.isConfiguration()); - } - -} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/builder/impl/ListSchemaNodeBuilderTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/builder/impl/ListSchemaNodeBuilderTest.java deleted file mode 100644 index c5f336179b..0000000000 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/builder/impl/ListSchemaNodeBuilderTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.yang.model.parser.builder.impl; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.when; - -import java.net.URI; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.opendaylight.controller.yang.common.QName; -import org.opendaylight.controller.yang.model.api.AugmentationSchema; -import org.opendaylight.controller.yang.model.api.GroupingDefinition; -import org.opendaylight.controller.yang.model.api.ListSchemaNode; -import org.opendaylight.controller.yang.model.api.SchemaPath; -import org.opendaylight.controller.yang.model.api.Status; -import org.opendaylight.controller.yang.model.api.TypeDefinition; -import org.opendaylight.controller.yang.model.api.UsesNode; -import org.opendaylight.controller.yang.model.parser.builder.api.GroupingBuilder; -import org.opendaylight.controller.yang.model.parser.builder.api.UsesNodeBuilder; - -public class ListSchemaNodeBuilderTest { - - private ListSchemaNodeBuilder tested; - - private static final String NAME = "test-list"; - - private final URI namespace = URI.create("test:list.name"); - private final Date revision = new Date(); - private final String prefix = "x"; - - private SchemaPath schemaPath; - private final String description = "description of list"; - private final String reference = "reference"; - - private QName typedefQName; - private TypedefBuilder typeBuilder; - @Mock - private AugmentationSchema augment; - @Mock - private UsesNodeBuilder usesBuilder; - @Mock - private UsesNode uses; - @Mock - private GroupingBuilder groupingBuilder; - @Mock - private GroupingDefinition grouping; - private List keyDefinition; - - @Before - public void init() { - MockitoAnnotations.initMocks(this); - when(usesBuilder.build()).thenReturn(uses); - when(groupingBuilder.build()).thenReturn(grouping); - - schemaPath = TestUtils.createSchemaPath(true, namespace, "main", NAME); - typedefQName = new QName(namespace, "test-type"); - typeBuilder = new TypedefBuilder(typedefQName); - - keyDefinition = new ArrayList(); - keyDefinition.add(new QName(namespace, "name")); - - QName qname = new QName(namespace, revision, prefix, NAME); - tested = new ListSchemaNodeBuilder(qname); - } - - @Test - public void test() { - tested.addTypedef(typeBuilder); - tested.setPath(schemaPath); - tested.setDescription(description); - tested.setReference(reference); - tested.setStatus(Status.OBSOLETE); - tested.setConfiguration(false); - tested.addUsesNode(usesBuilder); - tested.addAugmentation(augment); - tested.setUserOrdered(true); - tested.setKeyDefinition(keyDefinition); - - ListSchemaNode result = tested.build(); - - Set> expectedTypedefs = result.getTypeDefinitions(); - assertEquals(1, expectedTypedefs.size()); - assertEquals(typedefQName, expectedTypedefs.iterator().next() - .getQName()); - - Set expectedAugments = new HashSet(); - expectedAugments.add(augment); - assertEquals(expectedAugments, result.getAvailableAugmentations()); - - assertEquals(schemaPath, result.getPath()); - assertEquals(description, result.getDescription()); - assertEquals(reference, result.getReference()); - assertEquals(Status.OBSOLETE, result.getStatus()); - assertFalse(result.isConfiguration()); - - Set expectedUses = new HashSet(); - expectedUses.add(uses); - assertEquals(expectedUses, result.getUses()); - - assertTrue(result.isUserOrdered()); - assertEquals(keyDefinition, result.getKeyDefinition()); - } - -} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/TypesResolutionTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/TypesResolutionTest.java index cad548110a..de9142e592 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/TypesResolutionTest.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/TypesResolutionTest.java @@ -1,177 +1,249 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.yang.model.parser.impl; - -import static org.junit.Assert.*; - -import java.io.File; -import java.util.List; -import java.util.Set; - -import org.junit.Before; -import org.junit.Test; -import org.opendaylight.controller.yang.model.api.IdentitySchemaNode; -import org.opendaylight.controller.yang.model.api.LeafSchemaNode; -import org.opendaylight.controller.yang.model.api.Module; -import org.opendaylight.controller.yang.model.api.TypeDefinition; -import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition.EnumPair; -import org.opendaylight.controller.yang.model.api.type.LengthConstraint; -import org.opendaylight.controller.yang.model.api.type.PatternConstraint; -import org.opendaylight.controller.yang.model.parser.api.YangModelParser; -import org.opendaylight.controller.yang.model.util.EnumerationType; -import org.opendaylight.controller.yang.model.util.InstanceIdentifier; -import org.opendaylight.controller.yang.model.util.StringType; -import org.opendaylight.controller.yang.model.util.UnionType; - -public class TypesResolutionTest { - - private YangModelParser parser; - private String[] testFiles; - private Set modules; - - @Before - public void init() { - parser = new YangModelParserImpl(); - File testDir = new File("src/test/resources/types"); - String[] fileList = testDir.list(); - testFiles = new String[fileList.length]; - int i = 0; - for(String fileName : fileList) { - File file = new File(testDir, fileName); - testFiles[i] = file.getAbsolutePath(); - i++; - } - modules = parser.parseYangModels(testFiles); - assertEquals(fileList.length, modules.size()); - } - - @Test - public void testIPVersion() { - Module tested = findModule(modules, "ietf-inet-types"); - Set> typedefs = tested.getTypeDefinitions(); - assertEquals(14, typedefs.size()); - - TypeDefinition type = findTypedef(typedefs, "ip-version"); - EnumerationType en = (EnumerationType)type.getBaseType(); - List values = en.getValues(); - assertEquals(3, values.size()); - - EnumPair value0 = values.get(0); - assertEquals("unknown", value0.getName()); - assertEquals(0, (int)value0.getValue()); - - EnumPair value1 = values.get(1); - assertEquals("ipv4", value1.getName()); - assertEquals(1, (int)value1.getValue()); - - EnumPair value2 = values.get(2); - assertEquals("ipv6", value2.getName()); - assertEquals(2, (int)value2.getValue()); - } - - @Test - public void testIpAddress() { - Module tested = findModule(modules, "ietf-inet-types"); - Set> typedefs = tested.getTypeDefinitions(); - TypeDefinition type = findTypedef(typedefs, "ip-address"); - UnionType baseType = (UnionType)type.getBaseType(); - List> unionTypes = baseType.getTypes(); - - StringType ipv4 = (StringType)unionTypes.get(0); - String expectedPattern = - "(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}" - + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])" - + "(%[\\p{N}\\p{L}]+)?"; - assertEquals(expectedPattern, ipv4.getPatterns().get(0).getRegularExpression()); - - StringType ipv6 = (StringType)unionTypes.get(1); - List ipv6Patterns = ipv6.getPatterns(); - expectedPattern = "((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}" - + "((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|" - + "(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}" - + "(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))" - + "(%[\\p{N}\\p{L}]+)?"; - assertEquals(expectedPattern, ipv6Patterns.get(0).getRegularExpression()); - - expectedPattern = "(([^:]+:){6}(([^:]+:[^:]+)|(.*\\..*)))|" - + "((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)" - + "(%.+)?"; - assertEquals(expectedPattern, ipv6Patterns.get(1).getRegularExpression()); - } - - @Test - public void testDomainName() { - Module tested = findModule(modules, "ietf-inet-types"); - Set> typedefs = tested.getTypeDefinitions(); - TypeDefinition type = findTypedef(typedefs, "domain-name"); - StringType baseType = (StringType)type.getBaseType(); - List patterns = baseType.getPatterns(); - assertEquals(1, patterns.size()); - String expectedPattern = "((([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.)*" - + "([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.?)" - + "|\\."; - assertEquals(expectedPattern, patterns.get(0).getRegularExpression()); - - List lengths = baseType.getLengthStatements(); - assertEquals(1, lengths.size()); - LengthConstraint length = baseType.getLengthStatements().get(0); - assertEquals(1L, length.getMin().longValue()); - assertEquals(253L, length.getMax().longValue()); - } - - @Test - public void testInstanceIdentifier1() { - Module tested = findModule(modules, "custom-types-test"); - LeafSchemaNode leaf = (LeafSchemaNode)tested.getDataChildByName("inst-id-leaf1"); - InstanceIdentifier leafType = (InstanceIdentifier)leaf.getType(); - assertFalse(leafType.requireInstance()); - } - - @Test - public void testInstanceIdentifier2() { - Module tested = findModule(modules, "custom-types-test"); - LeafSchemaNode leaf = (LeafSchemaNode)tested.getDataChildByName("inst-id-leaf2"); - InstanceIdentifier leafType = (InstanceIdentifier)leaf.getType(); - assertTrue(leafType.requireInstance()); - } - - @Test - public void testIdentity() { - Module tested = findModule(modules, "custom-types-test"); - Set identities = tested.getIdentities(); - IdentitySchemaNode testedIdentity = null; - for(IdentitySchemaNode id : identities) { - if(id.getQName().getLocalName().equals("crypto-alg")) { - testedIdentity = id; - IdentitySchemaNode baseIdentity = id.getBaseIdentity(); - assertEquals("crypto-base", baseIdentity.getQName().getLocalName()); - assertNull(baseIdentity.getBaseIdentity()); - } - } - assertNotNull(testedIdentity); - } - - private Module findModule(Set modules, String name) { - for(Module module : modules) { - if(module.getName().equals(name)) { - return module; - } - } - return null; - } - - private TypeDefinition findTypedef(Set> typedefs, String name) { - for(TypeDefinition td : typedefs) { - if(td.getQName().getLocalName().equals(name)) { - return td; - } - } - return null; - } - -} +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.yang.model.parser.impl; + +import static org.junit.Assert.*; + +import java.io.File; +import java.util.List; +import java.util.Set; + +import org.junit.Before; +import org.junit.Test; +import org.opendaylight.controller.yang.model.api.IdentitySchemaNode; +import org.opendaylight.controller.yang.model.api.LeafSchemaNode; +import org.opendaylight.controller.yang.model.api.Module; +import org.opendaylight.controller.yang.model.api.TypeDefinition; +import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition.Bit; +import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition.EnumPair; +import org.opendaylight.controller.yang.model.api.type.LengthConstraint; +import org.opendaylight.controller.yang.model.api.type.PatternConstraint; +import org.opendaylight.controller.yang.model.parser.api.YangModelParser; +import org.opendaylight.controller.yang.model.util.BitsType; +import org.opendaylight.controller.yang.model.util.EnumerationType; +import org.opendaylight.controller.yang.model.util.ExtendedType; +import org.opendaylight.controller.yang.model.util.InstanceIdentifier; +import org.opendaylight.controller.yang.model.util.StringType; +import org.opendaylight.controller.yang.model.util.UnionType; + +public class TypesResolutionTest { + + private Set testedModules; + + @Before + public void init() { + YangModelParser parser = new YangModelParserImpl(); + File testDir = new File("src/test/resources/types"); + String[] fileList = testDir.list(); + String[] testFiles = new String[fileList.length]; + for (int i = 0; i < fileList.length; i++) { + String fileName = fileList[i]; + File file = new File(testDir, fileName); + testFiles[i] = file.getAbsolutePath(); + } + testedModules = parser.parseYangModels(testFiles); + assertEquals(fileList.length, testedModules.size()); + } + + @Test + public void testIPVersion() { + Module tested = findModule(testedModules, "ietf-inet-types"); + Set> typedefs = tested.getTypeDefinitions(); + assertEquals(14, typedefs.size()); + + TypeDefinition type = findTypedef(typedefs, "ip-version"); + assertTrue(type.getDescription().contains( + "This value represents the version of the IP protocol.")); + assertTrue(type.getReference().contains( + "RFC 2460: Internet Protocol, Version 6 (IPv6) Specification")); + + EnumerationType enumType = (EnumerationType) type.getBaseType(); + List values = enumType.getValues(); + assertEquals(3, values.size()); + + EnumPair value0 = values.get(0); + assertEquals("unknown", value0.getName()); + assertEquals(0, (int) value0.getValue()); + assertEquals( + "An unknown or unspecified version of the Internet protocol.", + value0.getDescription()); + + EnumPair value1 = values.get(1); + assertEquals("ipv4", value1.getName()); + assertEquals(1, (int) value1.getValue()); + assertEquals("The IPv4 protocol as defined in RFC 791.", + value1.getDescription()); + + EnumPair value2 = values.get(2); + assertEquals("ipv6", value2.getName()); + assertEquals(2, (int) value2.getValue()); + assertEquals("The IPv6 protocol as defined in RFC 2460.", + value2.getDescription()); + } + + @Test + public void testIpAddress() { + Module tested = findModule(testedModules, "ietf-inet-types"); + Set> typedefs = tested.getTypeDefinitions(); + TypeDefinition type = findTypedef(typedefs, "ip-address"); + UnionType baseType = (UnionType) type.getBaseType(); + List> unionTypes = baseType.getTypes(); + + ExtendedType ipv4 = (ExtendedType)unionTypes.get(0); + StringType ipv4Base = (StringType) ipv4.getBaseType(); + String expectedPattern = "(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}" + + "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])" + + "(%[\\p{N}\\p{L}]+)?"; + assertEquals(expectedPattern, ipv4Base.getPatterns().get(0) + .getRegularExpression()); + + ExtendedType ipv6 = (ExtendedType)unionTypes.get(1); + StringType ipv6Base = (StringType) ipv6.getBaseType(); + List ipv6Patterns = ipv6Base.getPatterns(); + expectedPattern = "((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}" + + "((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|" + + "(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}" + + "(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))" + + "(%[\\p{N}\\p{L}]+)?"; + assertEquals(expectedPattern, ipv6Patterns.get(0) + .getRegularExpression()); + + expectedPattern = "(([^:]+:){6}(([^:]+:[^:]+)|(.*\\..*)))|" + + "((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)" + "(%.+)?"; + assertEquals(expectedPattern, ipv6Patterns.get(1) + .getRegularExpression()); + } + + @Test + public void testDomainName() { + Module tested = findModule(testedModules, "ietf-inet-types"); + Set> typedefs = tested.getTypeDefinitions(); + TypeDefinition type = findTypedef(typedefs, "domain-name"); + StringType baseType = (StringType) type.getBaseType(); + List patterns = baseType.getPatterns(); + assertEquals(1, patterns.size()); + String expectedPattern = "((([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.)*" + + "([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.?)" + + "|\\."; + assertEquals(expectedPattern, patterns.get(0).getRegularExpression()); + + List lengths = baseType.getLengthStatements(); + assertEquals(1, lengths.size()); + LengthConstraint length = baseType.getLengthStatements().get(0); + assertEquals(1L, length.getMin()); + assertEquals(253L, length.getMax()); + } + + @Test + public void testInstanceIdentifier1() { + Module tested = findModule(testedModules, "custom-types-test"); + LeafSchemaNode leaf = (LeafSchemaNode) tested + .getDataChildByName("inst-id-leaf1"); + InstanceIdentifier leafType = (InstanceIdentifier) leaf.getType(); + assertFalse(leafType.requireInstance()); + } + + @Test + public void testInstanceIdentifier2() { + Module tested = findModule(testedModules, "custom-types-test"); + LeafSchemaNode leaf = (LeafSchemaNode) tested + .getDataChildByName("inst-id-leaf2"); + InstanceIdentifier leafType = (InstanceIdentifier) leaf.getType(); + assertTrue(leafType.requireInstance()); + } + + @Test + public void testIdentity() { + Module tested = findModule(testedModules, "custom-types-test"); + Set identities = tested.getIdentities(); + IdentitySchemaNode testedIdentity = null; + for (IdentitySchemaNode id : identities) { + if (id.getQName().getLocalName().equals("crypto-alg")) { + testedIdentity = id; + IdentitySchemaNode baseIdentity = id.getBaseIdentity(); + assertEquals("crypto-base", baseIdentity.getQName() + .getLocalName()); + assertNull(baseIdentity.getBaseIdentity()); + } + } + assertNotNull(testedIdentity); + } + + @Test + public void testBitsType1() { + Module tested = findModule(testedModules, "custom-types-test"); + LeafSchemaNode leaf = (LeafSchemaNode) tested + .getDataChildByName("mybits"); + BitsType leafType = (BitsType) leaf.getType(); + List bits = leafType.getBits(); + assertEquals(3, bits.size()); + + Bit bit1 = bits.get(0); + assertEquals("disable-nagle", bit1.getName()); + assertEquals(0L, (long) bit1.getPosition()); + + Bit bit2 = bits.get(1); + assertEquals("auto-sense-speed", bit2.getName()); + assertEquals(1L, (long) bit2.getPosition()); + + Bit bit3 = bits.get(2); + assertEquals("10-Mb-only", bit3.getName()); + assertEquals(2L, (long) bit3.getPosition()); + } + + @Test + public void testBitsType2() { + Module tested = findModule(testedModules, "custom-types-test"); + Set> typedefs = tested.getTypeDefinitions(); + TypeDefinition testedType = findTypedef(typedefs, + "access-operations-type"); + + BitsType bitsType = (BitsType) testedType.getBaseType(); + List bits = bitsType.getBits(); + assertEquals(5, bits.size()); + + Bit bit0 = bits.get(0); + assertEquals(0L, (long) bit0.getPosition()); + + Bit bit1 = bits.get(1); + assertEquals(500L, (long) bit1.getPosition()); + + Bit bit2 = bits.get(2); + assertEquals(501L, (long) bit2.getPosition()); + + Bit bit3 = bits.get(3); + assertEquals(365L, (long) bit3.getPosition()); + + Bit bit4 = bits.get(4); + assertEquals(502L, (long) bit4.getPosition()); + } + + private Module findModule(Set modules, String name) { + Module result = null; + for (Module module : modules) { + if (module.getName().equals(name)) { + result = module; + break; + } + } + return result; + } + + private TypeDefinition findTypedef(Set> typedefs, + String name) { + TypeDefinition result = null; + for (TypeDefinition td : typedefs) { + if (td.getQName().getLocalName().equals(name)) { + result = td; + break; + } + } + return result; + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserListenerTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserListenerTest.java deleted file mode 100644 index 1f0cb03012..0000000000 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserListenerTest.java +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.yang.model.parser.impl; - -import static org.junit.Assert.*; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Set; - -import org.antlr.v4.runtime.ANTLRInputStream; -import org.antlr.v4.runtime.CommonTokenStream; -import org.antlr.v4.runtime.tree.ParseTree; -import org.antlr.v4.runtime.tree.ParseTreeWalker; -import org.junit.Ignore; -import org.junit.Test; -import org.opendaylight.controller.antlrv4.code.gen.YangLexer; -import org.opendaylight.controller.antlrv4.code.gen.YangParser; -import org.opendaylight.controller.yang.common.QName; -import org.opendaylight.controller.yang.model.api.ContainerSchemaNode; -import org.opendaylight.controller.yang.model.api.DataNodeContainer; -import org.opendaylight.controller.yang.model.api.DataSchemaNode; -import org.opendaylight.controller.yang.model.api.LeafSchemaNode; -import org.opendaylight.controller.yang.model.api.ListSchemaNode; -import org.opendaylight.controller.yang.model.api.Module; -import org.opendaylight.controller.yang.model.api.ModuleImport; -import org.opendaylight.controller.yang.model.api.SchemaNode; -import org.opendaylight.controller.yang.model.api.SchemaPath; -import org.opendaylight.controller.yang.model.api.Status; -import org.opendaylight.controller.yang.model.api.TypeDefinition; -import org.opendaylight.controller.yang.model.parser.builder.impl.ModuleBuilder; -import org.opendaylight.controller.yang.model.util.Leafref; -import org.opendaylight.controller.yang.model.util.UnknownType; - -public class YangModelParserListenerTest { - - @Test - public void testParseImport() throws Exception { - Module module = getModule("/abstract-topology.yang"); - - Set imports = module.getImports(); - assertEquals(1, imports.size()); - ModuleImport moduleImport = imports.iterator().next(); - - assertEquals("inet", moduleImport.getPrefix()); - - DateFormat simpleDateFormat = new SimpleDateFormat("yyyy-mm-dd"); - Date expectedDate = simpleDateFormat.parse("2010-09-24"); - assertEquals(expectedDate, moduleImport.getRevision()); - } - - @Test - public void testParseHeaders() throws Exception { - Module module = getModule("/abstract-topology.yang"); - - URI namespace = module.getNamespace(); - URI expectedNS = URI.create(""); - assertEquals(expectedNS, namespace); - - DateFormat simpleDateFormat = new SimpleDateFormat("yyyy-mm-dd"); - Date expectedDate = simpleDateFormat.parse("2013-02-08"); - assertEquals(expectedDate, module.getRevision()); - - String prefix = module.getPrefix(); - String expectedPrefix = "tp"; - assertEquals(expectedPrefix, prefix); - - String expectedDescription = "This module contains the definitions of elements that creates network"; - assertTrue(module.getDescription().contains(expectedDescription)); - - String expectedReference = "~~~ WILL BE DEFINED LATER"; - assertEquals(expectedReference, module.getReference()); - - assertEquals("1", module.getYangVersion()); - } - - @Test - public void testParseLeafref() throws Exception { - Module module = getModule("/abstract-topology.yang"); - - Set> typedefs = module.getTypeDefinitions(); - assertEquals(2, typedefs.size()); - for(TypeDefinition td : typedefs) { - Leafref baseType = (Leafref)td.getBaseType(); - if(td.getQName().getLocalName().equals("node-id-ref")) { - assertEquals("/tp:topology/tp:network-nodes/tp:network-node/tp:node-id", baseType.getPathStatement().toString()); - } else { - assertEquals("/tp:topology/tp:network-links/tp:network-link/tp:link-id", baseType.getPathStatement().toString()); - } - } - } - - @Ignore - @Test - public void testParseModule() throws IOException { - //TODO: fix test - Module module = getModule("/test-model.yang"); - - URI namespace = module.getNamespace(); - Date revision = module.getRevision(); - String prefix = module.getPrefix(); - - String expectedDescription = "module description"; - assertEquals(expectedDescription, module.getDescription()); - - String expectedReference = "module reference"; - assertEquals(expectedReference, module.getReference()); - - Set> typedefs = module.getTypeDefinitions(); - assertEquals(10, typedefs.size()); - - Set childNodes = module.getChildNodes(); - assertEquals(1, childNodes.size()); - - final String containerName = "network"; - final QName containerQName = new QName(namespace, revision, prefix, containerName); - ContainerSchemaNode tested = (ContainerSchemaNode) module.getChildNodes().iterator().next(); - DataSchemaNode container1 = module.getDataChildByName(containerName); - DataSchemaNode container2 = module.getDataChildByName(containerQName); - - assertEquals(tested, container1); - assertEquals(container1, container2); - } - - @Ignore - @Test - public void testParseContainer() throws IOException { - //TODO: fix test - Module module = getModule("/test-model.yang"); - - URI namespace = module.getNamespace(); - Date revision = module.getRevision(); - String prefix = module.getPrefix(); - final QName containerQName = new QName(namespace, revision, prefix, "network"); - - ContainerSchemaNode tested = (ContainerSchemaNode)module.getDataChildByName(containerQName); - - Set containerChildNodes = tested.getChildNodes(); - assertEquals(3, containerChildNodes.size()); - - String expectedDescription = "network-description"; - String expectedReference = "network-reference"; - Status expectedStatus = Status.OBSOLETE; - testDesc_Ref_Status(tested, expectedDescription, expectedReference, expectedStatus); - - List path = new ArrayList(); - path.add(new QName(namespace, revision, prefix, "test-model")); - path.add(containerQName); - SchemaPath expectedSchemaPath = new SchemaPath(path, true); - assertEquals(expectedSchemaPath, tested.getPath()); - - assertTrue(tested.isConfiguration()); - assertTrue(tested.isPresenceContainer()); - } - - @Ignore - @Test - public void testParseList() throws IOException { - //TODO: fix test - Module module = getModule("/test-model.yang"); - - URI namespace = module.getNamespace(); - Date revision = module.getRevision(); - String prefix = module.getPrefix(); - final QName listQName = new QName(namespace, revision, prefix, "topology"); - - DataNodeContainer networkContainer = (DataNodeContainer)module.getDataChildByName("network"); - DataNodeContainer topologiesContainer = (DataNodeContainer)networkContainer.getDataChildByName("topologies"); - ListSchemaNode tested = (ListSchemaNode)topologiesContainer.getDataChildByName(listQName); - assertEquals(listQName, tested.getQName()); - - String expectedDescription = "Test description of list 'topology'."; - String expectedReference = null; - Status expectedStatus = Status.CURRENT; - testDesc_Ref_Status(tested, expectedDescription, expectedReference, expectedStatus); - - List path = new ArrayList(); - path.add(new QName(namespace, revision, prefix, "test-model")); - path.add(new QName(namespace, revision, prefix, "network")); - path.add(new QName(namespace, revision, prefix, "topologies")); - path.add(listQName); - SchemaPath expectedSchemaPath = new SchemaPath(path, true); - assertEquals(expectedSchemaPath, tested.getPath()); - - List expectedKey = new ArrayList(); - expectedKey.add(new QName(namespace, revision, prefix, "topology-id")); - assertEquals(expectedKey, tested.getKeyDefinition()); - - assertEquals(Collections.EMPTY_SET, tested.getTypeDefinitions()); - assertEquals(Collections.EMPTY_SET, tested.getUses()); - assertEquals(Collections.EMPTY_SET, tested.getGroupings()); - - assertTrue(tested.getDataChildByName("topology-id") instanceof LeafSchemaNode); - } - - @Ignore - @Test - public void testParseLeaf() throws IOException { - //TODO: fix test - Module module = getModule("/test-model.yang"); - - URI namespace = module.getNamespace(); - Date revision = module.getRevision(); - String prefix = module.getPrefix(); - final QName leafQName = new QName(namespace, revision, prefix, "topology-id"); - - DataNodeContainer networkContainer = (DataNodeContainer)module.getDataChildByName("network"); - DataNodeContainer topologiesContainer = (DataNodeContainer)networkContainer.getDataChildByName("topologies"); - DataNodeContainer topologyList = (DataNodeContainer)topologiesContainer.getDataChildByName("topology"); - LeafSchemaNode tested = (LeafSchemaNode)topologyList.getDataChildByName(leafQName); - assertEquals(leafQName, tested.getQName()); - - String expectedDescription = "Test description of leaf 'topology-id'"; - String expectedReference = null; - Status expectedStatus = Status.CURRENT; - testDesc_Ref_Status(tested, expectedDescription, expectedReference, expectedStatus); - - List path = new ArrayList(); - path.add(new QName(namespace, revision, prefix, "test-model")); - path.add(new QName(namespace, revision, prefix, "network")); - path.add(new QName(namespace, revision, prefix, "topologies")); - path.add(new QName(namespace, revision, prefix, "topology")); - path.add(leafQName); - SchemaPath expectedSchemaPath = new SchemaPath(path, true); - assertEquals(expectedSchemaPath, tested.getPath()); - - UnknownType.Builder typeBuilder = new UnknownType.Builder(new QName(namespace, revision, prefix, "topology-id"), null, null); - TypeDefinition expectedType = typeBuilder.build(); - assertEquals(expectedType, tested.getType()); - } - - - private void testDesc_Ref_Status(SchemaNode tested, String expectedDescription, String expectedReference, Status expectedStatus) { - assertEquals(expectedDescription, tested.getDescription()); - assertEquals(expectedReference, tested.getReference()); - assertEquals(expectedStatus, tested.getStatus()); - } - - private Module getModule(String testFile) throws IOException { - ModuleBuilder builder = getBuilder(testFile); - return builder.build(); - } - - private ModuleBuilder getBuilder(String fileName) throws IOException { - final InputStream inStream = getClass().getResourceAsStream(fileName); - ANTLRInputStream input = new ANTLRInputStream(inStream); - final YangLexer lexer = new YangLexer(input); - final CommonTokenStream tokens = new CommonTokenStream(lexer); - final YangParser parser = new YangParser(tokens); - - final ParseTree tree = parser.yang(); - final ParseTreeWalker walker = new ParseTreeWalker(); - - final YangModelParserListenerImpl modelParser = new YangModelParserListenerImpl(); - walker.walk(modelParser, tree); - return modelParser.getModuleBuilder(); - } - -} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserTest.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserTest.java index a42a4fa749..650eaeab82 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserTest.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserTest.java @@ -1,235 +1,293 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.yang.model.parser.impl; - -import static org.junit.Assert.*; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.junit.Before; -import org.junit.Test; -import org.opendaylight.controller.yang.model.api.AugmentationSchema; -import org.opendaylight.controller.yang.model.api.ContainerSchemaNode; -import org.opendaylight.controller.yang.model.api.LeafSchemaNode; -import org.opendaylight.controller.yang.model.api.ListSchemaNode; -import org.opendaylight.controller.yang.model.api.Module; -import org.opendaylight.controller.yang.model.api.TypeDefinition; -import org.opendaylight.controller.yang.model.api.type.IntegerTypeDefinition; -import org.opendaylight.controller.yang.model.api.type.PatternConstraint; -import org.opendaylight.controller.yang.model.api.type.RangeConstraint; -import org.opendaylight.controller.yang.model.parser.api.YangModelParser; -import org.opendaylight.controller.yang.model.util.Decimal64; -import org.opendaylight.controller.yang.model.util.Int32; -import org.opendaylight.controller.yang.model.util.StringType; - -public class YangModelParserTest { - - private final String testFile1 = "src/test/resources/model/testfile1.yang"; - private final String testFile2 = "src/test/resources/model/testfile2.yang"; - private YangModelParser tested; - - @Before - public void init() { - tested = new YangModelParserImpl(); - } - - @Test - public void testAugment() { - Set modules = tested.parseYangModels(testFile1, testFile2); - assertEquals(2, modules.size()); - - Module m2 = null; - for(Module m : modules) { - if(m.getName().equals("types2")) { - m2 = m; - } - } - assertNotNull(m2); - - AugmentationSchema augment = m2.getAugmentations().iterator().next(); - assertNotNull(augment); - } - - @Test - public void testAugmentTarget() { - Set modules = tested.parseYangModels(testFile1, testFile2); - assertEquals(2, modules.size()); - - Module m1 = null; - for(Module m : modules) { - if(m.getName().equals("types1")) { - m1 = m; - } - } - assertNotNull(m1); - - ContainerSchemaNode container = (ContainerSchemaNode)m1.getDataChildByName("interfaces"); - assertNotNull(container); - - ListSchemaNode list = (ListSchemaNode)container.getDataChildByName("ifEntry"); - assertNotNull(list); - assertEquals(1, list.getAvailableAugmentations().size()); - - LeafSchemaNode leaf = (LeafSchemaNode)list.getDataChildByName("ds0ChannelNumber"); - assertNotNull(leaf); - } - - @Test - public void testTypedefRangesResolving() { - Set modules = tested.parseYangModels(testFile1, testFile2); - assertEquals(2, modules.size()); - - Module m1 = null; - for(Module m : modules) { - if(m.getName().equals("types1")) { - m1 = m; - } - } - assertNotNull(m1); - - LeafSchemaNode testleaf = (LeafSchemaNode)m1.getDataChildByName("testleaf"); - TypeDefinition baseType = testleaf.getType().getBaseType(); - assertTrue(testleaf.getType().getBaseType() instanceof Int32); - Int32 baseTypeCast = (Int32)baseType; - List ranges = baseTypeCast.getRangeStatements(); - assertEquals(2, ranges.size()); - RangeConstraint range = ranges.get(0); - assertEquals(2L, range.getMin()); - assertEquals(20L, range.getMax()); - } - - @Test - public void testTypedefPatternsResolving() { - Set modules = tested.parseYangModels(testFile1, testFile2); - assertEquals(2, modules.size()); - - Module m1 = null; - for(Module m : modules) { - if(m.getName().equals("types1")) { - m1 = m; - } - } - assertNotNull(m1); - - LeafSchemaNode testleaf = (LeafSchemaNode)m1.getDataChildByName("test-string-leaf"); - TypeDefinition baseType = testleaf.getType().getBaseType(); - assertTrue(testleaf.getType().getBaseType() instanceof StringType); - StringType baseTypeCast = (StringType)baseType; - - Set expectedRegularExpressions = new HashSet(); - expectedRegularExpressions.add("[a-k]*"); - expectedRegularExpressions.add("[b-u]*"); - expectedRegularExpressions.add("[e-z]*"); - - Set actualRegularExpressions = new HashSet(); - List patterns = baseTypeCast.getPatterns(); - for(PatternConstraint pc : patterns) { - actualRegularExpressions.add(pc.getRegularExpression()); - } - - assertEquals(expectedRegularExpressions, actualRegularExpressions); - } - - @Test - public void testTypedefLengthsResolving() { - Set modules = tested.parseYangModels(testFile1, testFile2); - assertEquals(2, modules.size()); - - Module m1 = null; - for(Module m : modules) { - if(m.getName().equals("types1")) { - m1 = m; - } - } - assertNotNull(m1); - - LeafSchemaNode testleaf = (LeafSchemaNode)m1.getDataChildByName("test-int-leaf"); - TypeDefinition baseType = testleaf.getType().getBaseType(); - assertTrue(testleaf.getType().getBaseType() instanceof IntegerTypeDefinition); - Int32 baseTypeCast = (Int32)baseType; - - Long[][] expectedRanges = new Long[3][2]; - expectedRanges[0] = new Long[]{10L, 20L}; - expectedRanges[1] = new Long[]{12L, 18L}; - expectedRanges[2] = new Long[]{14L, 16L}; - - List actualRanges = baseTypeCast.getRangeStatements(); - assertEquals(3, actualRanges.size()); - for(int i = 0; i < actualRanges.size(); i++) { - assertEquals(expectedRanges[i][0], actualRanges.get(i).getMin()); - assertEquals(expectedRanges[i][1], actualRanges.get(i).getMax()); - } - } - - @Test - public void testTypeDef() { - Set modules = tested.parseYangModels(testFile1, testFile2); - assertEquals(2, modules.size()); - - Module m2 = null; - for(Module m : modules) { - if(m.getName().equals("types2")) { - m2 = m; - } - } - assertNotNull(m2); - - LeafSchemaNode testleaf = (LeafSchemaNode)m2.getDataChildByName("nested-type-leaf"); - TypeDefinition baseType = testleaf.getType().getBaseType(); - assertTrue(testleaf.getType().getBaseType() instanceof Int32); - Int32 baseTypeCast = (Int32)baseType; - List ranges = baseTypeCast.getRangeStatements(); - assertEquals(2, ranges.size()); - RangeConstraint range = ranges.get(0); - assertEquals(2L, range.getMin()); - assertEquals(20L, range.getMax()); - } - - @Test - public void testTypedefDecimal1() { - Set modules = tested.parseYangModels(testFile1, testFile2); - assertEquals(2, modules.size()); - - Module m1 = null; - for(Module m : modules) { - if(m.getName().equals("types1")) { - m1 = m; - } - } - assertNotNull(m1); - - LeafSchemaNode testleaf = (LeafSchemaNode)m1.getDataChildByName("test-decimal-leaf"); - TypeDefinition baseType = testleaf.getType().getBaseType(); - assertTrue(testleaf.getType().getBaseType() instanceof Decimal64); - Decimal64 baseTypeCast = (Decimal64)baseType; - assertEquals(4, (int)baseTypeCast.getFractionDigits()); - } - - @Test - public void testTypedefDecimal2() { - Set modules = tested.parseYangModels(testFile1, testFile2); - assertEquals(2, modules.size()); - - Module m1 = null; - for(Module m : modules) { - if(m.getName().equals("types1")) { - m1 = m; - } - } - assertNotNull(m1); - - LeafSchemaNode testleaf = (LeafSchemaNode)m1.getDataChildByName("test-decimal-leaf2"); - TypeDefinition baseType = testleaf.getType().getBaseType(); - assertTrue(testleaf.getType().getBaseType() instanceof Decimal64); - Decimal64 baseTypeCast = (Decimal64)baseType; - assertEquals(5, (int)baseTypeCast.getFractionDigits()); - } - -} +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.yang.model.parser.impl; + +import static org.junit.Assert.*; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.junit.Before; +import org.junit.Test; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.model.api.AugmentationSchema; +import org.opendaylight.controller.yang.model.api.ContainerSchemaNode; +import org.opendaylight.controller.yang.model.api.LeafSchemaNode; +import org.opendaylight.controller.yang.model.api.ListSchemaNode; +import org.opendaylight.controller.yang.model.api.Module; +import org.opendaylight.controller.yang.model.api.TypeDefinition; +import org.opendaylight.controller.yang.model.api.type.LengthConstraint; +import org.opendaylight.controller.yang.model.api.type.PatternConstraint; +import org.opendaylight.controller.yang.model.api.type.RangeConstraint; +import org.opendaylight.controller.yang.model.parser.api.YangModelParser; +import org.opendaylight.controller.yang.model.util.Decimal64; +import org.opendaylight.controller.yang.model.util.ExtendedType; +import org.opendaylight.controller.yang.model.util.Int16; +import org.opendaylight.controller.yang.model.util.Int32; +import org.opendaylight.controller.yang.model.util.StringType; +import org.opendaylight.controller.yang.model.util.UnionType; + +public class YangModelParserTest { + + private static final String TEST_FILE1 = "src/test/resources/model/testfile1.yang"; + private static final String TEST_FILE2 = "src/test/resources/model/testfile2.yang"; + private YangModelParser tested; + + @Before + public void init() { + tested = new YangModelParserImpl(); + } + + @Test + public void testAugment() { + Set modules = tested.parseYangModels(TEST_FILE1, TEST_FILE2); + assertEquals(2, modules.size()); + + Module testModule = findModule(modules, "types2"); + assertNotNull(testModule); + + AugmentationSchema augment = testModule.getAugmentations().iterator().next(); + assertNotNull(augment); + } + + @Test + public void testAugmentTarget() { + Set modules = tested.parseYangModels(TEST_FILE1, TEST_FILE2); + assertEquals(2, modules.size()); + + Module testModule = findModule(modules, "types1"); + assertNotNull(testModule); + + ContainerSchemaNode container = (ContainerSchemaNode)testModule.getDataChildByName("interfaces"); + assertNotNull(container); + + ListSchemaNode list = (ListSchemaNode)container.getDataChildByName("ifEntry"); + assertNotNull(list); + assertEquals(1, list.getAvailableAugmentations().size()); + + LeafSchemaNode leaf = (LeafSchemaNode)list.getDataChildByName("ds0ChannelNumber"); + assertNotNull(leaf); + } + + @Test + public void testTypedefRangesResolving() { + Set modules = tested.parseYangModels(TEST_FILE1, TEST_FILE2); + assertEquals(2, modules.size()); + + Module testModule = findModule(modules, "types1"); + assertNotNull(testModule); + + LeafSchemaNode testleaf = (LeafSchemaNode)testModule.getDataChildByName("testleaf"); + ExtendedType leafType = (ExtendedType)testleaf.getType(); + assertEquals("my-type1", leafType.getQName().getLocalName()); + assertEquals("t2", leafType.getQName().getPrefix()); + ExtendedType baseType = (ExtendedType)leafType.getBaseType(); + assertEquals("my-base-int32-type", baseType.getQName().getLocalName()); + assertEquals("t2", baseType.getQName().getPrefix()); + + List ranges = leafType.getRanges(); + assertEquals(1, ranges.size()); + RangeConstraint range = ranges.get(0); + assertEquals(11L, range.getMin()); + assertEquals(20L, range.getMax()); + } + + @Test + public void testTypedefPatternsResolving() { + Set modules = tested.parseYangModels(TEST_FILE1, TEST_FILE2); + assertEquals(2, modules.size()); + + Module testModule = findModule(modules, "types1"); + assertNotNull(testModule); + + LeafSchemaNode testleaf = (LeafSchemaNode)testModule.getDataChildByName("test-string-leaf"); + ExtendedType testleafType = (ExtendedType)testleaf.getType(); + QName testleafTypeQName = testleafType.getQName(); + assertEquals("my-string-type-ext", testleafTypeQName.getLocalName()); + assertEquals("t2", testleafTypeQName.getPrefix()); + + Set expectedRegex = new HashSet(); + expectedRegex.add("[a-k]*"); + expectedRegex.add("[b-u]*"); + expectedRegex.add("[e-z]*"); + + Set actualRegex = new HashSet(); + List patterns = testleafType.getPatterns(); + assertEquals(3, patterns.size()); + for (PatternConstraint pc : patterns) { + actualRegex.add(pc.getRegularExpression()); + } + assertEquals(expectedRegex, actualRegex); + + TypeDefinition baseType = testleafType.getBaseType(); + assertEquals("my-string-type2", baseType.getQName().getLocalName()); + + List lengths = testleafType.getLengths(); + assertEquals(1, lengths.size()); + + LengthConstraint length = lengths.get(0); + assertEquals(5L, length.getMin()); + assertEquals(10L, length.getMax()); + } + + @Test + public void testTypedefLengthsResolving() { + Set modules = tested.parseYangModels(TEST_FILE1, TEST_FILE2); + assertEquals(2, modules.size()); + + Module testModule = findModule(modules, "types1"); + assertNotNull(testModule); + + LeafSchemaNode testleaf = (LeafSchemaNode)testModule.getDataChildByName("leaf-with-length"); + ExtendedType testleafType = (ExtendedType)testleaf.getType(); + assertEquals("my-string-type", testleafType.getQName().getLocalName()); + + List lengths = testleafType.getLengths(); + assertEquals(1, lengths.size()); + + LengthConstraint length = lengths.get(0); + assertEquals(7L, length.getMin()); + assertEquals(10L, length.getMax()); + } + + @Test + public void testTypeDef() { + Set modules = tested.parseYangModels(TEST_FILE1, TEST_FILE2); + assertEquals(2, modules.size()); + + Module testModule = findModule(modules, "types2"); + assertNotNull(testModule); + + LeafSchemaNode testleaf = (LeafSchemaNode)testModule.getDataChildByName("nested-type-leaf"); + ExtendedType testleafType = (ExtendedType)testleaf.getType(); + assertEquals("my-type1", testleafType.getQName().getLocalName()); + + ExtendedType baseType = (ExtendedType)testleafType.getBaseType(); + assertEquals("my-base-int32-type", baseType.getQName().getLocalName()); + + Int32 int32base = (Int32)baseType.getBaseType(); + List ranges = int32base.getRangeStatements(); + assertEquals(1, ranges.size()); + RangeConstraint range = ranges.get(0); + assertEquals(2L, range.getMin()); + assertEquals(20L, range.getMax()); + } + + @Test + public void testTypedefDecimal1() { + Set modules = tested.parseYangModels(TEST_FILE1, TEST_FILE2); + assertEquals(2, modules.size()); + + Module testModule = findModule(modules, "types1"); + assertNotNull(testModule); + + LeafSchemaNode testleaf = (LeafSchemaNode)testModule.getDataChildByName("test-decimal-leaf"); + ExtendedType type = (ExtendedType)testleaf.getType(); + + TypeDefinition baseType = type.getBaseType(); + assertTrue(baseType instanceof Decimal64); + Decimal64 baseTypeCast = (Decimal64)baseType; + assertEquals(6, (int)baseTypeCast.getFractionDigits()); + } + + @Test + public void testTypedefDecimal2() { + Set modules = tested.parseYangModels(TEST_FILE1, TEST_FILE2); + assertEquals(2, modules.size()); + + Module testModule = findModule(modules, "types1"); + assertNotNull(testModule); + + LeafSchemaNode testleaf = (LeafSchemaNode)testModule.getDataChildByName("test-decimal-leaf2"); + TypeDefinition baseType = testleaf.getType().getBaseType(); + assertTrue(testleaf.getType().getBaseType() instanceof Decimal64); + Decimal64 baseTypeCast = (Decimal64)baseType; + assertEquals(5, (int)baseTypeCast.getFractionDigits()); + } + + @Test + public void testTypedefUnion() { + Set modules = tested.parseYangModels(TEST_FILE1, TEST_FILE2); + assertEquals(2, modules.size()); + + Module testModule = findModule(modules, "types1"); + assertNotNull(testModule); + + LeafSchemaNode testleaf = (LeafSchemaNode)testModule.getDataChildByName("union-leaf"); + ExtendedType testleafType = (ExtendedType)testleaf.getType(); + assertEquals("my-union-ext", testleafType.getQName().getLocalName()); + + ExtendedType baseType = (ExtendedType)testleafType.getBaseType(); + assertEquals("my-union", baseType.getQName().getLocalName()); + + UnionType unionBase = (UnionType) baseType.getBaseType(); + + List> unionTypes = unionBase.getTypes(); + Int16 unionType1 = (Int16)unionTypes.get(0); + List ranges = unionType1.getRangeStatements(); + assertEquals(1, ranges.size()); + RangeConstraint range = ranges.get(0); + assertEquals(1L, range.getMin()); + assertEquals(100L, range.getMax()); + + assertTrue(unionTypes.get(0) instanceof Int16); + assertTrue(unionTypes.get(1) instanceof Int32); + } + + @Test + public void testNestedUnionResolving() { + Set modules = tested.parseYangModels(TEST_FILE1, TEST_FILE2); + assertEquals(2, modules.size()); + + Module testModule = findModule(modules, "types1"); + assertNotNull(testModule); + + LeafSchemaNode testleaf = (LeafSchemaNode)testModule.getDataChildByName("nested-union-leaf"); + + ExtendedType nestedUnion1 = (ExtendedType)testleaf.getType(); + assertEquals("nested-union1", nestedUnion1.getQName().getLocalName()); + + ExtendedType nestedUnion2 = (ExtendedType)nestedUnion1.getBaseType(); + assertEquals("nested-union2", nestedUnion2.getQName().getLocalName()); + + UnionType unionType1 = (UnionType)nestedUnion2.getBaseType(); + List> unionTypes = unionType1.getTypes(); + assertEquals(2, unionTypes.size()); + assertTrue(unionTypes.get(0) instanceof StringType); + assertTrue(unionTypes.get(1) instanceof ExtendedType); + + ExtendedType extendedUnion = (ExtendedType)unionTypes.get(1); + ExtendedType extendedUnionBase = (ExtendedType)extendedUnion.getBaseType(); + assertEquals("my-union", extendedUnionBase.getQName().getLocalName()); + + UnionType extendedTargetUnion = (UnionType)extendedUnionBase.getBaseType(); + List> extendedTargetTypes = extendedTargetUnion.getTypes(); + assertTrue(extendedTargetTypes.get(0) instanceof Int16); + assertTrue(extendedTargetTypes.get(1) instanceof Int32); + + Int16 int16 = (Int16) extendedTargetTypes.get(0); + List ranges = int16.getRangeStatements(); + assertEquals(1, ranges.size()); + RangeConstraint range = ranges.get(0); + assertEquals(1L, range.getMin()); + assertEquals(100L, range.getMax()); + } + + private Module findModule(Set modules, String moduleName) { + Module result = null; + for(Module module : modules) { + if(module.getName().equals(moduleName)) { + result = module; + break; + } + } + return result; + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile1.yang b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile1.yang index 9e779c2ce5..f38e3488cf 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile1.yang +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile1.yang @@ -1,67 +1,81 @@ -module types1 { - yang-version 1; - namespace "urn:simple.container.demo"; - prefix "t1"; - - import types2 { - prefix "data"; - revision-date 2013-02-27; - } - - organization "Cisco"; - contact "WILL-BE-DEFINED-LATER"; - - revision "2013-02-27" { - reference " WILL BE DEFINED LATER"; - } - - container interfaces { - list ifEntry { - key "ifIndex"; - - leaf ifIndex { - type uint32; - units minutes; - } - - leaf ifMtu { - type int32; - } - } - } - - leaf testleaf { - type data:my-type1 { - range "min..max"; - } - } - - leaf test-string-leaf { - type data:my-string-type-ext; - } - - leaf leaf-with-length { - type data:my-string-type { - length "7..max"; - } - } - - leaf test-int-leaf { - type data:my-int-type-ext; - } - - leaf test-decimal-leaf { - type data:my-decimal-type { - fraction-digits 4; - } - } - - leaf test-decimal-leaf2 { - type data:my-decimal-type-ext; - } - - container ext { - data:c-define "MY_INTERFACES"; - } - -} +module types1 { + yang-version 1; + namespace "urn:simple.container.demo"; + prefix "t1"; + + import types2 { + prefix "data"; + revision-date 2013-02-27; + } + + organization "opendaylight"; + contact "WILL-BE-DEFINED-LATER"; + + revision "2013-02-27" { + reference " WILL BE DEFINED LATER"; + } + + container interfaces { + list ifEntry { + key "ifIndex"; + + leaf ifIndex { + type uint32; + units minutes; + } + + leaf ifMtu { + type int32; + } + } + } + + leaf testleaf { + type data:my-type1 { + range "min..max"; + } + } + + leaf test-string-leaf { + type data:my-string-type-ext; + } + + leaf leaf-with-length { + type data:my-string-type { + length "7..max"; + } + } + + leaf test-int-leaf { + type data:my-int-type-ext; + } + + leaf test-decimal-leaf { + type data:my-decimal-type { + fraction-digits 4; + } + } + + leaf test-decimal-leaf2 { + type data:my-decimal-type-ext; + } + + container ext { + data:c-define "MY_INTERFACES"; + } + + leaf union-leaf { + type data:my-union-ext; + } + + deviation /data:system/data:user { + deviate add { + default "admin"; // new users are 'admin' by default + } + } + + leaf nested-union-leaf { + type data:nested-union1; + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile2.yang b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile2.yang index ea12a507eb..15685f75a1 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile2.yang +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/model/testfile2.yang @@ -1,130 +1,149 @@ -module types2 { - yang-version 1; - namespace "urn:simple.types.data.demo"; - prefix "t2"; - - import types1 { - prefix "if"; - revision-date 2013-02-27; - } - - organization "Cisco"; - contact "WILL-BE-DEFINED-LATER"; - description "This is types-data test description"; - - revision "2013-02-27" { - reference " WILL BE DEFINED LATER"; - } - - typedef ranges1 { - type int32 { - range "10..20"; - } - } - - typedef ranges2 { - type ranges1 { - range "12..max"; - } - } - - typedef my-base-int32-type { - type int32 { - range "2..20"; - } - } - - typedef my-type1 { - type my-base-int32-type { - range "11..max"; - } - } - - typedef my-string-type { - type my-custom-string { - pattern "[a-k]*"; - length "5..10"; - } - } - - typedef my-custom-string { - type string { - pattern "[a-k]*"; - length "5..11"; - } - } - - typedef my-string-type2 { - type my-string-type { - pattern "[b-u]*"; - } - } - - typedef my-string-type-ext { - type my-string-type2 { - pattern "[e-z]*"; - } - } - - typedef my-int-type { - type int32 { - range "10..20"; - } - } - - typedef my-int-type2 { - type my-int-type { - range "12..18"; - } - } - - typedef my-int-type-ext { - type my-int-type2 { - range "14..16"; - } - } - - typedef my-decimal-type { - type decimal64 { - fraction-digits 6; - } - } - - typedef my-decimal-type-ext { - type decimal64 { - fraction-digits 5; - } - } - - augment "/if:interfaces/if:ifEntry" { - when "if:ifType='ds0'"; - leaf ds0ChannelNumber { - type string; - } - } - - leaf if-name { - type leafref { - path "/interface/name"; - } - } - - leaf name { - type string; - } - - leaf nested-type-leaf { - type my-type1; - } - - extension c-define { - description - "Takes as argument a name string. - Makes the code generator use the given name in the - #define."; - argument "name" { - yin-element "true"; - } - } - -} +module types2 { + yang-version 1; + namespace "urn:simple.types.data.demo"; + prefix "t2"; + + import types1 { + prefix "if"; + revision-date 2013-02-27; + } + + organization "opendaylight"; + contact "WILL-BE-DEFINED-LATER"; + description "This is types-data test description"; + + revision "2013-02-27" { + reference " WILL BE DEFINED LATER"; + } + + typedef my-base-int32-type { + type int32 { + range "2..20"; + } + } + + typedef my-type1 { + type my-base-int32-type { + range "11..max"; + } + units "mile"; + default "11"; + } + + typedef my-custom-string { + type string { + pattern "[a-k]*"; + length "5..11"; + } + } + + typedef my-string-type { + type my-custom-string { + length "5..10"; + } + } + + typedef my-string-type2 { + type my-string-type { + pattern "[b-u]*"; + } + } + + typedef my-string-type-ext { + type my-string-type2 { + pattern "[e-z]*"; + } + } + + typedef my-int-type { + type int32 { + range "10..20"; + } + } + + typedef my-int-type2 { + type my-int-type { + range "12..18"; + } + } + + typedef my-int-type-ext { + type my-int-type2 { + range "14..16"; + } + } + + typedef my-decimal-type { + type decimal64 { + fraction-digits 6; + } + } + + typedef my-decimal-type-ext { + type decimal64 { + fraction-digits 5; + } + } + + typedef my-union { + type union { + type int16 { + range "1..100"; + } + type int32; + } + } + + typedef my-union-ext { + type my-union; + } + + typedef nested-union1 { + type nested-union2; + } + + typedef nested-union2 { + type union { + type my-union-ext; + type string; + } + } + + augment "/if:interfaces/if:ifEntry" { + when "if:ifType='ds0'"; + leaf ds0ChannelNumber { + type string; + } + } + + leaf if-name { + type leafref { + path "/interface/name"; + } + } + + leaf name { + type string; + } + + leaf nested-type-leaf { + type my-type1; + } + + extension c-define { + description + "Takes as argument a name string. + Makes the code generator use the given name in the + #define."; + argument "name" { + yin-element "true"; + } + } + + container system { + leaf user { + type string; + } + } + +} diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/types/custom-types-test@2012-4-4.yang b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/types/custom-types-test@2012-4-4.yang index 4231699b50..d52068a4ad 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/types/custom-types-test@2012-4-4.yang +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/test/resources/types/custom-types-test@2012-4-4.yang @@ -4,8 +4,32 @@ module custom-types-test { namespace "urn:simple.container.demo"; prefix "iit"; - organization "Cisco"; + organization "opendaylight"; contact "WILL-BE-DEFINED-LATER"; + + + typedef access-operations-type { + type bits { + bit create { + description "Any protocol operation that creates a new data node."; + } + bit read { + description "Any protocol operation or notification that returns the value of a data node."; + position 500; + } + bit update { + description "Any protocol operation that alters an existing data node."; + } + bit delete { + description "Any protocol operation that removes a data node."; + position 365; + } + bit exec { + description "Execution access to the specified protocol operation."; + } + } + description "NETCONF Access Operation."; + } leaf inst-id-leaf1 { type instance-identifier { @@ -25,5 +49,20 @@ module custom-types-test { base "crypto-base"; description "crypto-alg description"; } + + leaf mybits { + type bits { + bit disable-nagle { + position 0; + } + bit auto-sense-speed { + position 1; + } + bit 10-Mb-only { + position 2; + } + } + default "auto-sense-speed"; + } } diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/TypeDefinition.java b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/TypeDefinition.java index 0f098422eb..71b5d193df 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/TypeDefinition.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/TypeDefinition.java @@ -8,7 +8,7 @@ package org.opendaylight.controller.yang.model.api; -public interface TypeDefinition> extends SchemaNode { +public interface TypeDefinition> extends SchemaNode { T getBaseType(); diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/ExtendedType.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/ExtendedType.java index c82df2e079..03f06387f1 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/ExtendedType.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/ExtendedType.java @@ -15,6 +15,9 @@ import org.opendaylight.controller.yang.model.api.SchemaPath; import org.opendaylight.controller.yang.model.api.Status; import org.opendaylight.controller.yang.model.api.TypeDefinition; import org.opendaylight.controller.yang.model.api.UnknownSchemaNode; +import org.opendaylight.controller.yang.model.api.type.LengthConstraint; +import org.opendaylight.controller.yang.model.api.type.PatternConstraint; +import org.opendaylight.controller.yang.model.api.type.RangeConstraint; public class ExtendedType implements TypeDefinition { @@ -25,6 +28,12 @@ public class ExtendedType implements TypeDefinition { private final String reference; private final List unknownSchemaNodes; + private List ranges = Collections.emptyList(); + private List lengths = Collections.emptyList(); + private List patterns = Collections.emptyList(); + private Integer fractionDigits = null; + + private Status status; private String units; private Object defaultValue; @@ -42,6 +51,11 @@ public class ExtendedType implements TypeDefinition { private String units = ""; private Object defaultValue = null; + private List ranges = Collections.emptyList(); + private List lengths = Collections.emptyList(); + private List patterns = Collections.emptyList(); + private Integer fractionDigits = null; + public Builder(final QName typeName, TypeDefinition baseType, final String description, final String reference) { this.typeName = typeName; @@ -71,6 +85,32 @@ public class ExtendedType implements TypeDefinition { return this; } + public Builder ranges(final List ranges) { + if(ranges != null) { + this.ranges = ranges; + } + return this; + } + + public Builder lengths(final List lengths) { + if(lengths != null) { + this.lengths = lengths; + } + return this; + } + + public Builder patterns(final List patterns) { + if(patterns != null) { + this.patterns = patterns; + } + return this; + } + + public Builder fractionDigits(final Integer fractionDigits) { + this.fractionDigits = fractionDigits; + return this; + } + public ExtendedType build() { return new ExtendedType(this); } @@ -86,6 +126,11 @@ public class ExtendedType implements TypeDefinition { this.status = builder.status; this.units = builder.units; this.defaultValue = builder.defaultValue; + + this.ranges = builder.ranges; + this.lengths = builder.lengths; + this.patterns = builder.patterns; + this.fractionDigits = builder.fractionDigits; } @Override @@ -253,4 +298,20 @@ public class ExtendedType implements TypeDefinition { builder2.append("]"); return builder2.toString(); } + + public List getRanges() { + return ranges; + } + + public List getLengths() { + return lengths; + } + + public List getPatterns() { + return patterns; + } + + public Integer getFractionDigits() { + return fractionDigits; + } } diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Leafref.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Leafref.java index 3218116290..9253895e3f 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Leafref.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Leafref.java @@ -22,7 +22,7 @@ import org.opendaylight.controller.yang.model.api.type.LeafrefTypeDefinition; /** * The default implementation of Instance Leafref Type Definition * interface. - * + * * @see LeafrefTypeDefinition */ public class Leafref implements LeafrefTypeDefinition { @@ -35,12 +35,12 @@ public class Leafref implements LeafrefTypeDefinition { private final String units = ""; private final LeafrefTypeDefinition baseType; - private Leafref(final RevisionAwareXPath xpath) { + public Leafref(final RevisionAwareXPath xpath) { this.xpath = xpath; this.path = BaseTypes.schemaPath(name); this.baseType = this; } - + public Leafref(final List actualPath, final URI namespace, final Date revision, final RevisionAwareXPath xpath) { super(); @@ -48,7 +48,7 @@ public class Leafref implements LeafrefTypeDefinition { this.xpath = xpath; baseType = new Leafref(xpath); } - + public Leafref(final List actualPath, final URI namespace, final Date revision, final LeafrefTypeDefinition baseType, final RevisionAwareXPath xpath) { @@ -60,7 +60,7 @@ public class Leafref implements LeafrefTypeDefinition { /* * (non-Javadoc) - * + * * @see * org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType() */ @@ -71,7 +71,7 @@ public class Leafref implements LeafrefTypeDefinition { /* * (non-Javadoc) - * + * * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getUnits() */ @Override @@ -81,7 +81,7 @@ public class Leafref implements LeafrefTypeDefinition { /* * (non-Javadoc) - * + * * @see * org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue * () @@ -93,7 +93,7 @@ public class Leafref implements LeafrefTypeDefinition { /* * (non-Javadoc) - * + * * @see org.opendaylight.controller.yang.model.api.SchemaNode#getQName() */ @Override @@ -103,7 +103,7 @@ public class Leafref implements LeafrefTypeDefinition { /* * (non-Javadoc) - * + * * @see org.opendaylight.controller.yang.model.api.SchemaNode#getPath() */ @Override @@ -113,7 +113,7 @@ public class Leafref implements LeafrefTypeDefinition { /* * (non-Javadoc) - * + * * @see * org.opendaylight.controller.yang.model.api.SchemaNode#getDescription() */ @@ -124,7 +124,7 @@ public class Leafref implements LeafrefTypeDefinition { /* * (non-Javadoc) - * + * * @see org.opendaylight.controller.yang.model.api.SchemaNode#getReference() */ @Override @@ -134,7 +134,7 @@ public class Leafref implements LeafrefTypeDefinition { /* * (non-Javadoc) - * + * * @see org.opendaylight.controller.yang.model.api.SchemaNode#getStatus() */ @Override @@ -144,7 +144,7 @@ public class Leafref implements LeafrefTypeDefinition { /* * (non-Javadoc) - * + * * @see * org.opendaylight.controller.yang.model.api.SchemaNode#getExtensionSchemaNodes * () @@ -156,7 +156,7 @@ public class Leafref implements LeafrefTypeDefinition { /* * (non-Javadoc) - * + * * @see * org.opendaylight.controller.yang.model.api.type.LeafrefTypeDefinition * #getPathStatement() -- 2.36.6