+ private def void augmentationToGenTypes(String augmentPackageName, AugmentationSchema augSchema, Module module) {
+ checkArgument(augmentPackageName !== null, "Package Name cannot be NULL.");
+ checkArgument(augSchema !== null, "Augmentation Schema cannot be NULL.");
+ checkState(augSchema.targetPath !== null,
+ "Augmentation Schema does not contain Target Path (Target Path is NULL).");
+
+ processUsesAugments(augSchema, module);
+ val targetPath = augSchema.targetPath;
+ var SchemaNode targetSchemaNode = null
+
+ targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);
+ if (targetSchemaNode instanceof DataSchemaNode && (targetSchemaNode as DataSchemaNode).isAddedByUses()) {
+ targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode);
+ if (targetSchemaNode == null) {
+ throw new NullPointerException(
+ "Failed to find target node from grouping in augmentation " + augSchema + " in module " +
+ module.name);
+ }
+ }
+ if (targetSchemaNode == null) {
+ throw new IllegalArgumentException("augment target not found: " + targetPath)
+ }
+
+ var targetTypeBuilder = findChildNodeByPath(targetSchemaNode.path)
+ if (targetTypeBuilder === null) {
+ targetTypeBuilder = findCaseByPath(targetSchemaNode.path)
+ }
+ if (targetTypeBuilder === null) {
+ throw new NullPointerException("Target type not yet generated: " + targetSchemaNode);
+ }
+
+ if (!(targetSchemaNode instanceof ChoiceNode)) {
+ var packageName = augmentPackageName;
+ val augTypeBuilder = addRawAugmentGenTypeDefinition(module, packageName, augmentPackageName,
+ targetTypeBuilder.toInstance, augSchema);
+ genCtx.get(module).addAugmentType(augTypeBuilder)
+ genCtx.get(module).addTypeToAugmentation(augTypeBuilder, augSchema);
+ } else {
+ generateTypesFromAugmentedChoiceCases(module, augmentPackageName, targetTypeBuilder.toInstance,
+ targetSchemaNode as ChoiceNode, augSchema.childNodes);
+ }
+ }
+
+ private def void usesAugmentationToGenTypes(String augmentPackageName, AugmentationSchema augSchema, Module module,
+ UsesNode usesNode, DataNodeContainer usesNodeParent) {
+ checkArgument(augmentPackageName !== null, "Package Name cannot be NULL.");
+ checkArgument(augSchema !== null, "Augmentation Schema cannot be NULL.");
+ checkState(augSchema.targetPath !== null,
+ "Augmentation Schema does not contain Target Path (Target Path is NULL).");
+
+ processUsesAugments(augSchema, module);
+ val targetPath = augSchema.targetPath;
+ var SchemaNode targetSchemaNode = null
+ targetSchemaNode = findOriginalTargetFromGrouping(targetPath, usesNode);
+ if (targetSchemaNode == null) {
+ throw new IllegalArgumentException("augment target not found: " + targetPath)
+ }
+
+ var targetTypeBuilder = findChildNodeByPath(targetSchemaNode.path)
+ if (targetTypeBuilder === null) {
+ targetTypeBuilder = findCaseByPath(targetSchemaNode.path)
+ }
+ if (targetTypeBuilder === null) {
+ throw new NullPointerException("Target type not yet generated: " + targetSchemaNode);
+ }
+
+ if (!(targetSchemaNode instanceof ChoiceNode)) {
+ var packageName = augmentPackageName;
+ if (usesNodeParent instanceof SchemaNode) {
+ packageName = packageNameForGeneratedType(augmentPackageName, (usesNodeParent as SchemaNode).path, true)
+ }
+ val augTypeBuilder = addRawAugmentGenTypeDefinition(module, packageName, augmentPackageName,
+ targetTypeBuilder.toInstance, augSchema);
+ genCtx.get(module).addAugmentType(augTypeBuilder)
+ genCtx.get(module).addTypeToAugmentation(augTypeBuilder, augSchema);
+ } else {
+ generateTypesFromAugmentedChoiceCases(module, augmentPackageName, targetTypeBuilder.toInstance,
+ targetSchemaNode as ChoiceNode, augSchema.childNodes);
+ }
+ }
+
+ /**
+ * 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.
+ */
+ private def DataSchemaNode findOriginalTargetFromGrouping(SchemaPath targetPath, UsesNode parentUsesNode) {
+ var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, parentUsesNode.groupingPath.path);
+ if (!(targetGrouping instanceof GroupingDefinition)) {
+ throw new IllegalArgumentException("Failed to generate code for augment in " + parentUsesNode);
+ }
+
+ var grouping = targetGrouping as GroupingDefinition;
+ var SchemaNode result = grouping;
+ val List<QName> path = targetPath.path
+ for (node : path) {
+ // finding by local name is valid, grouping cannot contain nodes with same name and different namespace
+ if (result instanceof DataNodeContainer) {
+ result = (result as DataNodeContainer).getDataChildByName(node.localName)
+ } else if (result instanceof ChoiceNode) {
+ result = (result as ChoiceNode).getCaseNodeByName(node.localName)
+ }
+ }
+ if (result == null) {
+ return null;
+ }
+
+ val String targetSchemaNodeName = result.QName.localName;
+ var boolean fromUses = (result as DataSchemaNode).addedByUses
+ var Iterator<UsesNode> groupingUses = grouping.uses.iterator;
+ while (fromUses) {
+ if (groupingUses.hasNext()) {
+ grouping = findNodeInSchemaContext(schemaContext, groupingUses.next().groupingPath.path) as GroupingDefinition;
+ result = grouping.getDataChildByName(targetSchemaNodeName);
+ fromUses = (result as DataSchemaNode).addedByUses;
+ } else {
+ throw new NullPointerException("Failed to generate code for augment in " + parentUsesNode);
+ }
+ }
+
+ return result as DataSchemaNode
+ }
+
+ /**