Fixed codec loading for choice case nodes.
Fixed bug in parser when handling uses/augment target path.
Helper methods from BindingGeneratorImpl moved to SchemaContextUtil class.
Added test.
Change-Id: Id1b835150cdad2c278bd9c125d5369822b75639a
Signed-off-by: Martin Vitez <mvitez@cisco.com>
import org.opendaylight.yangtools.sal.binding.model.api.type.builder.AnnotationTypeBuilder
import org.opendaylight.yangtools.yang.model.api.ModuleImport
import org.opendaylight.yangtools.yang.binding.DataContainer
-import org.opendaylight.yangtools.yang.model.api.AugmentationTarget
import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
import org.opendaylight.yangtools.sal.binding.model.api.Restrictions
import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilderBase
import com.google.common.collect.Sets
-import java.net.URI
-import java.util.Date
public class BindingGeneratorImpl implements BindingGenerator {
targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);
if (targetSchemaNode instanceof DataSchemaNode && (targetSchemaNode as DataSchemaNode).isAddedByUses()) {
- targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode);
+ targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode, schemaContext);
if (targetSchemaNode == null) {
throw new NullPointerException(
"Failed to find target node from grouping in augmentation " + augSchema + " in module " +
}
}
- /**
- * Utility method which search for original node defined in grouping.
- */
- private def DataSchemaNode findOriginal(DataSchemaNode node) {
- var DataSchemaNode result = findCorrectTargetFromGrouping(node);
- if (result == null) {
- result = findCorrectTargetFromAugment(node);
- if (result != null) {
- if (result.addedByUses) {
- result = findOriginal(result);
- }
- }
- }
- return result;
- }
-
- private def DataSchemaNode findCorrectTargetFromAugment(DataSchemaNode node) {
- if (!node.augmenting) {
- return null
- }
-
- var QName currentName = node.QName
- var Object currentNode = node
- var Object parent = node;
- val tmpPath = new ArrayList<QName>()
- val tmpTree = new ArrayList<SchemaNode>()
-
- var AugmentationSchema augment = null;
- do {
- val SchemaPath sp = (parent as SchemaNode).path
- val List<QName> names = sp.path
- val List<QName> newNames = new ArrayList(names)
- newNames.remove(newNames.size - 1)
- val SchemaPath newSp = new SchemaPath(newNames, sp.absolute)
- parent = findDataSchemaNode(schemaContext, newSp)
- if (parent instanceof AugmentationTarget) {
- tmpPath.add(currentName);
- tmpTree.add(currentNode as SchemaNode)
- augment = findNodeInAugment((parent as AugmentationTarget).availableAugmentations, currentName);
- if (augment == null) {
- currentName = (parent as DataSchemaNode).QName
- currentNode = parent
- }
- }
- } while ((parent as DataSchemaNode).augmenting && augment == null);
-
- if (augment == null) {
- return null;
- } else {
- Collections.reverse(tmpPath);
- Collections.reverse(tmpTree);
- var Object actualParent = augment;
- var DataSchemaNode result = null;
- for (name : tmpPath) {
- if (actualParent instanceof DataNodeContainer) {
- result = (actualParent as DataNodeContainer).getDataChildByName(name.localName);
- actualParent = (actualParent as DataNodeContainer).getDataChildByName(name.localName);
- } else {
- if (actualParent instanceof ChoiceNode) {
- result = (actualParent as ChoiceNode).getCaseNodeByName(name.localName);
- actualParent = (actualParent as ChoiceNode).getCaseNodeByName(name.localName);
- }
- }
- }
-
- if (result.addedByUses) {
- result = findCorrectTargetFromAugmentGrouping(result, augment, tmpTree);
- }
-
- return result;
- }
- }
-
- private def AugmentationSchema findNodeInAugment(Collection<AugmentationSchema> augments, QName name) {
- for (augment : augments) {
- val DataSchemaNode node = augment.getDataChildByName(name);
- if (node != null) {
- return augment;
- }
- }
- return null;
- }
-
- private def DataSchemaNode findCorrectTargetFromGrouping(DataSchemaNode node) {
- if (node.path.path.size == 1) {
- // uses is under module statement
- val Module m = findParentModule(schemaContext, node);
- var DataSchemaNode result = null;
- for (u : m.uses) {
- var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, u.groupingPath.path);
- if (!(targetGrouping instanceof GroupingDefinition)) {
- throw new IllegalArgumentException("Failed to generate code for augment in " + u);
- }
- var gr = targetGrouping as GroupingDefinition;
- result = gr.getDataChildByName(node.QName.localName);
- }
- if (result == null) {
- throw new IllegalArgumentException("Failed to generate code for augment")
- }
- return result
- } else {
- var DataSchemaNode result = null;
- var QName currentName = node.QName
- var tmpPath = new ArrayList<QName>()
- var Object parent = null
-
- val SchemaPath sp = node.path
- val List<QName> names = sp.path
- val List<QName> newNames = new ArrayList(names)
- newNames.remove(newNames.size - 1)
- val SchemaPath newSp = new SchemaPath(newNames, sp.absolute)
- parent = findDataSchemaNode(schemaContext, newSp)
-
- do {
- tmpPath.add(currentName);
- if (parent instanceof DataNodeContainer) {
- val dataNodeParent = parent as DataNodeContainer;
- for (u : dataNodeParent.uses) {
- if (result == null) {
- result = getResultFromUses(u, currentName.localName)
- }
- }
- }
- if (result == null) {
- currentName = (parent as SchemaNode).QName
- if (parent instanceof SchemaNode) {
- val SchemaPath nodeSp = (parent as SchemaNode).path
- val List<QName> nodeNames = nodeSp.path
- val List<QName> nodeNewNames = new ArrayList(nodeNames)
- nodeNewNames.remove(nodeNewNames.size - 1)
- if (nodeNewNames.empty) {
- parent = getParentModule(parent as SchemaNode)
- } else {
- val SchemaPath nodeNewSp = new SchemaPath(nodeNewNames, nodeSp.absolute)
- parent = findDataSchemaNode(schemaContext, nodeNewSp)
- }
- } else {
- throw new IllegalArgumentException("Failed to generate code for augment")
- }
- }
- } while (result == null && !(parent instanceof Module));
-
- if (result != null) {
- result = getTargetNode(tmpPath, result)
- }
- return result;
- }
- }
-
- private def DataSchemaNode findCorrectTargetFromAugmentGrouping(DataSchemaNode node, AugmentationSchema parentNode,
- List<SchemaNode> dataTree) {
-
- var DataSchemaNode result = null;
- var QName currentName = node.QName
- var tmpPath = new ArrayList<QName>()
- tmpPath.add(currentName)
- var int i = 1;
- var Object parent = null
-
- do {
- if (dataTree.size < 2 || dataTree.size == i) {
- parent = parentNode
- } else {
- parent = dataTree.get(dataTree.size - (i+1))
- tmpPath.add((parent as SchemaNode).QName)
- }
-
- val dataNodeParent = parent as DataNodeContainer;
- for (u : dataNodeParent.uses) {
- if (result == null) {
- result = getResultFromUses(u, currentName.localName)
- }
- }
- if (result == null) {
- i = i + 1
- currentName = (parent as SchemaNode).QName
- }
- } while (result == null);
-
- if (result != null) {
- result = getTargetNode(tmpPath, result)
- }
- return result;
- }
-
- private def getResultFromUses(UsesNode u, String currentName) {
- var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, u.groupingPath.path)
- if (!(targetGrouping instanceof GroupingDefinition)) {
- throw new IllegalArgumentException("Failed to generate code for augment in " + u)
- }
- var gr = targetGrouping as GroupingDefinition
- return gr.getDataChildByName(currentName)
- }
-
- private def getTargetNode(List<QName> tmpPath, DataSchemaNode node) {
- var DataSchemaNode result = node
- if (tmpPath.size == 1) {
- if (result != null && result.addedByUses) {
- result = findOriginal(result);
- }
- return result;
- } else {
- var DataSchemaNode newParent = result;
- Collections.reverse(tmpPath);
-
- tmpPath.remove(0);
- for (name : tmpPath) {
- // searching by local name is must, because node has different namespace in its original location
- if (newParent instanceof DataNodeContainer) {
- newParent = (newParent as DataNodeContainer).getDataChildByName(name.localName);
- } else {
- newParent = (newParent as ChoiceNode).getCaseNodeByName(name.localName);
- }
- }
- if (newParent != null && newParent.addedByUses) {
- newParent = findOriginal(newParent);
- }
- return newParent;
- }
- }
-
-
/**
* Convenient method to find node added by uses statement.
*/
var targetSchemaNode = findDataSchemaNode(schemaContext, targetPath)
if (targetSchemaNode instanceof DataSchemaNode &&
(targetSchemaNode as DataSchemaNode).isAddedByUses()) {
- targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode);
+ targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode, schemaContext);
if (targetSchemaNode == null) {
throw new NullPointerException(
"Failed to find target node from grouping for augmentation " + augSchema +
return null
}
- private def Module getParentModule(SchemaNode node) {
- val QName qname = node.getPath().getPath().get(0);
- val URI namespace = qname.getNamespace();
- val Date revision = qname.getRevision();
- return schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
- }
-
public def getModuleContexts() {
genCtx;
}
}
private void tryToCreateCasesCodecs(ChoiceNode schema) {
- for (ChoiceCaseNode caseNode : schema.getCases()) {
+ for (ChoiceCaseNode choiceCase : schema.getCases()) {
+ ChoiceCaseNode caseNode = choiceCase;
+ if (caseNode.isAddedByUses()) {
+ DataSchemaNode origCaseNode = SchemaContextUtil.findOriginal(caseNode, currentSchema);
+ if (origCaseNode instanceof ChoiceCaseNode) {
+ caseNode = (ChoiceCaseNode) origCaseNode;
+ }
+ }
SchemaPath path = caseNode.getPath();
+
GeneratedTypeBuilder type;
if (path != null && (type = pathToType.get(path)) != null) {
ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName());
private static class ChoiceCaseCodecImpl<T extends DataContainer> implements ChoiceCaseCodec<T>, //
Delegator<BindingCodec> {
private boolean augmenting;
+ private boolean uses;
private BindingCodec delegate;
private Set<String> validNames;
validNames.add(qname.getLocalName());
}
augmenting = caseNode.isAugmenting();
+ uses = caseNode.isAddedByUses();
}
public ChoiceCaseCodecImpl() {
@Override
public boolean isAcceptable(Node<?> input) {
if (input instanceof CompositeNode) {
- if (augmenting) {
+ if (augmenting && !uses) {
return checkAugmenting((CompositeNode) input);
} else {
return checkLocal((CompositeNode) input);
if (typeSpecBuilder == null) {
typeSpecBuilder = pathToType.get(node.path);
}
- var schemaNode = typeToSchemaNode.get(ref);
- if (schemaNode === null) {
- schemaNode = node;
- }
+
checkState(typeSpecBuilder !== null, "Could not find TypeDefinition for %s, $s", inputType.name, node);
val typeSpec = typeSpecBuilder.toInstance();
- val newret = generateTransformerFor(inputType, typeSpec, schemaNode);
+ val newret = generateTransformerFor(inputType, typeSpec, node);
listener.onClassProcessed(inputType);
return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
]
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!-- 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 -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>model-parent</artifactId>
+ <version>0.6.2-SNAPSHOT</version>
+ <relativePath>../../model/pom.xml</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>bug527-test-model</artifactId>
+ <name>${project.artifactId}</name>
+ <description>${project.artifactId}</description>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
+
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+module bar {
+ yang-version 1;
+ namespace "urn:yang:bar";
+ prefix "bar";
+
+ revision "2014-03-21" {
+ }
+
+ container alpha {
+ container beta {
+ }
+ }
+
+ grouping group-a {
+ container xcont {
+ choice xchoice {
+ }
+ }
+ }
+
+ grouping group-b {
+ uses group-a {
+ augment "xcont/xchoice" {
+ case xcase {
+ leaf idx {
+ type string;
+ }
+ }
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+module foo {
+ yang-version 1;
+ namespace "urn:yang:foo";
+ prefix "foo";
+
+ import bar {
+ prefix bar;
+ }
+
+ revision "2014-03-21" {
+ }
+
+
+
+ augment "/bar:alpha/bar:beta" {
+ uses bar:group-b;
+ }
+
+}
+
<packaging>pom</packaging>
<modules>
+ <module>bug527-test-model</module>
<module>regression-test-model</module>
<module>yang-runtime-tests</module>
</modules>
<?xml version="1.0" encoding="UTF-8"?>
<!-- vi: set et smarttab sw=4 tabstop=4: -->
-<!--
- 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
--->
+<!-- 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 -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-generator-impl</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>bug527-test-model</artifactId>
+ <version>0.6.2-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.restconf.utils;
+
+import static junit.framework.Assert.assertNotNull;
+import static org.junit.Assert.*;
+
+import java.io.InputStream;
+
+import javassist.ClassPool;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.yang.bar.rev140321.Alpha;
+import org.opendaylight.yang.gen.v1.urn.yang.bar.rev140321.alpha.Beta;
+import org.opendaylight.yang.gen.v1.urn.yang.bar.rev140321.group.a.xcont.Xchoice;
+import org.opendaylight.yang.gen.v1.urn.yang.bar.rev140321.group.b.xcont.xchoice.Xcase;
+import org.opendaylight.yang.gen.v1.urn.yang.foo.rev140321.Beta1;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+public class Bug527Test {
+
+ private RuntimeGeneratedMappingServiceImpl mappingService;
+
+ @Before
+ public void setup() {
+ this.mappingService = new RuntimeGeneratedMappingServiceImpl();
+ this.mappingService.setPool(new ClassPool());
+ this.mappingService.init();
+
+ final ModuleInfoBackedContext moduleInfo = ModuleInfoBackedContext.create();
+ moduleInfo.addModuleInfos(BindingReflections.loadModuleInfos());
+ this.mappingService.onGlobalContextUpdated(moduleInfo.tryToCreateSchemaContext().get());
+ }
+
+ @Test
+ public void testToDataObjectMappingWithNestedAugmentations() {
+ InstanceIdentifier<Alpha> alphaId = InstanceIdentifier.builder(Alpha.class).toInstance();
+ InputStream is = this.getClass().getClassLoader().getResourceAsStream("topology-bug527.xml");
+ DataSchemaNode dataSchema = RestconfUtils.toRestconfIdentifier(alphaId, mappingService,
+ mappingService.getSchemaContext()).getValue();
+ Alpha alpha = (Alpha) RestconfUtils.dataObjectFromInputStream(alphaId, is, mappingService.getSchemaContext(),
+ mappingService, dataSchema);
+ assertNotNull(alpha);
+
+ Beta beta = alpha.getBeta();
+ Beta1 beta1 = beta.getAugmentation(Beta1.class);
+
+ Xchoice xchoice = beta1.getXcont().getXchoice();
+ assertNotNull(xchoice);
+
+ Xcase acase = (Xcase) xchoice;
+ assertEquals("idx2", acase.getIdx());
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!-- 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 -->
+<alpha xmlns="urn:yang:bar">
+ <beta>
+ <xcont xmlns="urn:yang:foo">
+ <idx>idx2</idx>
+ </xcont>
+ </beta>
+</alpha>
*/
package org.opendaylight.yangtools.yang.model.util;
+import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.ModuleImport;
-import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
-import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
-
-import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.model.api.*;
import com.google.common.base.Preconditions;
return null;
}
+ /**
+ * Utility method which search for original node defined in grouping.
+ *
+ * @param node
+ * @return
+ */
+ public static DataSchemaNode findOriginal(DataSchemaNode node, SchemaContext ctx) {
+ DataSchemaNode result = findCorrectTargetFromGrouping(node, ctx);
+ if (result == null) {
+ result = findCorrectTargetFromAugment(node, ctx);
+ if (result != null) {
+ if (result.isAddedByUses()) {
+ result = findOriginal(result, ctx);
+ }
+ }
+ }
+ return result;
+ }
+
+ private static DataSchemaNode findCorrectTargetFromGrouping(DataSchemaNode node, SchemaContext ctx) {
+ if (node.getPath().getPath().size() == 1) {
+ // uses is under module statement
+ Module m = findParentModule(ctx, node);
+ DataSchemaNode result = null;
+ for (UsesNode u : m.getUses()) {
+ SchemaNode targetGrouping = findNodeInSchemaContext(ctx, u.getGroupingPath().getPath());
+ if (!(targetGrouping instanceof GroupingDefinition)) {
+ throw new IllegalArgumentException("Failed to generate code for augment in " + u);
+ }
+ GroupingDefinition gr = (GroupingDefinition) targetGrouping;
+ result = gr.getDataChildByName(node.getQName().getLocalName());
+ }
+ if (result == null) {
+ throw new IllegalArgumentException("Failed to generate code for augment");
+ }
+ return result;
+ } else {
+ DataSchemaNode result = null;
+ QName currentName = node.getQName();
+ List<QName> tmpPath = new ArrayList<>();
+ Object parent = null;
+
+ SchemaPath sp = node.getPath();
+ List<QName> names = sp.getPath();
+ List<QName> newNames = new ArrayList<>(names);
+ newNames.remove(newNames.size() - 1);
+ SchemaPath newSp = new SchemaPath(newNames, sp.isAbsolute());
+ parent = findDataSchemaNode(ctx, newSp);
+
+ do {
+ tmpPath.add(currentName);
+ if (parent instanceof DataNodeContainer) {
+ DataNodeContainer dataNodeParent = (DataNodeContainer) parent;
+ for (UsesNode u : dataNodeParent.getUses()) {
+ if (result == null) {
+ result = getResultFromUses(u, currentName.getLocalName(), ctx);
+ }
+ }
+ }
+ if (result == null) {
+ currentName = ((SchemaNode) parent).getQName();
+ if (parent instanceof SchemaNode) {
+ SchemaPath nodeSp = ((SchemaNode) parent).getPath();
+ List<QName> nodeNames = nodeSp.getPath();
+ List<QName> nodeNewNames = new ArrayList<>(nodeNames);
+ nodeNewNames.remove(nodeNewNames.size() - 1);
+ if (nodeNewNames.isEmpty()) {
+ parent = getParentModule((SchemaNode) parent, ctx);
+ } else {
+ SchemaPath nodeNewSp = new SchemaPath(nodeNewNames, nodeSp.isAbsolute());
+ parent = findDataSchemaNode(ctx, nodeNewSp);
+ }
+ } else {
+ throw new IllegalArgumentException("Failed to generate code for augment");
+ }
+ }
+ } while (result == null && !(parent instanceof Module));
+
+ if (result != null) {
+ result = getTargetNode(tmpPath, result, ctx);
+ }
+ return result;
+ }
+ }
+
+ private static DataSchemaNode findCorrectTargetFromAugment(DataSchemaNode node, SchemaContext ctx) {
+ if (!node.isAugmenting()) {
+ return null;
+ }
+
+ QName currentName = node.getQName();
+ Object currentNode = node;
+ Object parent = node;
+ List<QName> tmpPath = new ArrayList<QName>();
+ List<SchemaNode> tmpTree = new ArrayList<SchemaNode>();
+
+ AugmentationSchema augment = null;
+ do {
+ SchemaPath sp = ((SchemaNode) parent).getPath();
+ List<QName> names = sp.getPath();
+ List<QName> newNames = new ArrayList<>(names);
+ newNames.remove(newNames.size() - 1);
+ SchemaPath newSp = new SchemaPath(newNames, sp.isAbsolute());
+ parent = findDataSchemaNode(ctx, newSp);
+ if (parent instanceof AugmentationTarget) {
+ tmpPath.add(currentName);
+ tmpTree.add((SchemaNode) currentNode);
+ augment = findNodeInAugment(((AugmentationTarget) parent).getAvailableAugmentations(), currentName);
+ if (augment == null) {
+ currentName = ((DataSchemaNode) parent).getQName();
+ currentNode = parent;
+ }
+ }
+ } while (((DataSchemaNode) parent).isAugmenting() && augment == null);
+
+ if (augment == null) {
+ return null;
+ } else {
+ Collections.reverse(tmpPath);
+ Collections.reverse(tmpTree);
+ Object actualParent = augment;
+ DataSchemaNode result = null;
+ for (QName name : tmpPath) {
+ if (actualParent instanceof DataNodeContainer) {
+ result = ((DataNodeContainer) actualParent).getDataChildByName(name.getLocalName());
+ actualParent = ((DataNodeContainer) actualParent).getDataChildByName(name.getLocalName());
+ } else {
+ if (actualParent instanceof ChoiceNode) {
+ result = ((ChoiceNode) actualParent).getCaseNodeByName(name.getLocalName());
+ actualParent = ((ChoiceNode) actualParent).getCaseNodeByName(name.getLocalName());
+ }
+ }
+ }
+
+ if (result.isAddedByUses()) {
+ result = findCorrectTargetFromAugmentGrouping(result, augment, tmpTree, ctx);
+ }
+
+ return result;
+ }
+ }
+
+ private static DataSchemaNode getResultFromUses(UsesNode u, String currentName, SchemaContext ctx) {
+ SchemaNode targetGrouping = findNodeInSchemaContext(ctx, u.getGroupingPath().getPath());
+ if (!(targetGrouping instanceof GroupingDefinition)) {
+ throw new IllegalArgumentException("Failed to generate code for augment in " + u);
+ }
+ GroupingDefinition gr = (GroupingDefinition) targetGrouping;
+ return gr.getDataChildByName(currentName);
+ }
+
+ private static Module getParentModule(SchemaNode node, SchemaContext ctx) {
+ QName qname = node.getPath().getPath().get(0);
+ URI namespace = qname.getNamespace();
+ Date revision = qname.getRevision();
+ return ctx.findModuleByNamespaceAndRevision(namespace, revision);
+ }
+
+ private static DataSchemaNode getTargetNode(List<QName> tmpPath, DataSchemaNode node, SchemaContext ctx) {
+ DataSchemaNode result = node;
+ if (tmpPath.size() == 1) {
+ if (result != null && result.isAddedByUses()) {
+ result = findOriginal(result, ctx);
+ }
+ return result;
+ } else {
+ DataSchemaNode newParent = result;
+ Collections.reverse(tmpPath);
+
+ tmpPath.remove(0);
+ for (QName name : tmpPath) {
+ // searching by local name is must, because node has different
+ // namespace in its original location
+ if (newParent == null) {
+ break;
+ }
+ if (newParent instanceof DataNodeContainer) {
+ newParent = ((DataNodeContainer) newParent).getDataChildByName(name.getLocalName());
+ } else {
+ newParent = ((ChoiceNode) newParent).getCaseNodeByName(name.getLocalName());
+ }
+ }
+ if (newParent != null && newParent.isAddedByUses()) {
+ newParent = findOriginal(newParent, ctx);
+ }
+ return newParent;
+ }
+ }
+
+ private static AugmentationSchema findNodeInAugment(Collection<AugmentationSchema> augments, QName name) {
+ for (AugmentationSchema augment : augments) {
+ DataSchemaNode node = augment.getDataChildByName(name);
+ if (node != null) {
+ return augment;
+ }
+ }
+ return null;
+ }
+
+ private static DataSchemaNode findCorrectTargetFromAugmentGrouping(DataSchemaNode node,
+ AugmentationSchema parentNode, List<SchemaNode> dataTree, SchemaContext ctx) {
+
+ DataSchemaNode result = null;
+ QName currentName = node.getQName();
+ List<QName> tmpPath = new ArrayList<>();
+ tmpPath.add(currentName);
+ int i = 1;
+ Object parent = null;
+
+ do {
+ if (dataTree.size() < 2 || dataTree.size() == i) {
+ parent = parentNode;
+ } else {
+ parent = dataTree.get(dataTree.size() - (i + 1));
+ tmpPath.add(((SchemaNode) parent).getQName());
+ }
+
+ if (parent instanceof DataNodeContainer) {
+ DataNodeContainer dataNodeParent = (DataNodeContainer) parent;
+ for (UsesNode u : dataNodeParent.getUses()) {
+ if (result == null) {
+ result = getResultFromUses(u, currentName.getLocalName(), ctx);
+ }
+ }
+ }
+
+ if (result == null) {
+ i = i + 1;
+ currentName = ((SchemaNode) parent).getQName();
+ }
+ } while (result == null);
+
+ if (result != null) {
+ result = getTargetNode(tmpPath, result, ctx);
+ }
+ return result;
+ }
+
/**
* Transforms string representation of XPath to Queue of QNames. The XPath
* is split by "/" and for each part of XPath is assigned correct module in
newPath.add(new QName(ns, rev, localPrefix, qn.getLocalName()));
}
}
- augment.setTargetNodeSchemaPath(new SchemaPath(newPath, augment.getTargetPath().isAbsolute()));
+ augment.setTargetNodeSchemaPath(new SchemaPath(newPath, true));
for (DataSchemaNodeBuilder childNode : augment.getChildNodeBuilders()) {
correctPathForAugmentNodes(childNode, augment.getTargetNodeSchemaPath());