X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=code-generator%2Fmaven-sal-api-gen-plugin%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Funified%2Fdoc%2Fgenerator%2FGeneratorImpl.xtend;h=62f628c50f5f23593d3672d948de69ad94d5a9f6;hb=1e2025a2dd82f44c31e268870ab20babfbc9a75f;hp=a0b3554aa604e87db7051359dc19d72eac67e650;hpb=5686bfb61393443275eff37fb07e1c8b87a6e198;p=yangtools.git diff --git a/code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/yang/unified/doc/generator/GeneratorImpl.xtend b/code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/yang/unified/doc/generator/GeneratorImpl.xtend index a0b3554aa6..62f628c50f 100644 --- a/code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/yang/unified/doc/generator/GeneratorImpl.xtend +++ b/code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/yang/unified/doc/generator/GeneratorImpl.xtend @@ -5,617 +5,1221 @@ * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.yangtools.yang.unified.doc.generator - -import org.opendaylight.yangtools.yang.model.api.SchemaContext -import java.io.File -import java.util.Set -import org.opendaylight.yangtools.yang.model.api.Module -import java.io.IOException -import java.util.HashSet -import java.io.BufferedWriter -import java.io.OutputStreamWriter; -import org.opendaylight.yangtools.yang.model.api.DataSchemaNode -import org.opendaylight.yangtools.yang.model.api.ListSchemaNode -import org.opendaylight.yangtools.yang.model.api.TypeDefinition -import org.opendaylight.yangtools.yang.model.api.SchemaNode -import org.opendaylight.yangtools.yang.model.util.ExtendedType -import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition -import java.text.SimpleDateFormat -import java.util.Collection -import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint -import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition -import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition -import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint -import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition -import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition -import org.opendaylight.yangtools.yang.model.api.NotificationDefinition -import org.opendaylight.yangtools.yang.model.api.DataNodeContainer -import org.slf4j.LoggerFactory -import org.slf4j.Logger -import java.util.List -import org.opendaylight.yangtools.yang.common.QName -import org.opendaylight.yangtools.yang.model.api.RpcDefinition -import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition -import java.util.ArrayList -import java.util.Map -import org.opendaylight.yangtools.yang.model.api.SchemaPath - -import org.sonatype.plexus.build.incremental.BuildContext; -import org.sonatype.plexus.build.incremental.DefaultBuildContext; - -import org.opendaylight.yangtools.yang.model.api.ChoiceNode -import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode -import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates -import java.util.LinkedHashMap -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier -import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode -import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode import java.util.HashMap +package org.opendaylight.yangtools.yang.unified.doc.generator + +import com.google.common.collect.Iterables +import java.io.BufferedWriter +import java.io.File +import java.io.IOException +import java.io.OutputStreamWriter +import java.text.SimpleDateFormat +import java.util.ArrayList +import java.util.Collection +import java.util.HashMap +import java.util.HashSet +import java.util.LinkedHashMap +import java.util.List +import java.util.Map +import java.util.Set +import org.opendaylight.yangtools.yang.common.QName +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode +import org.opendaylight.yangtools.yang.model.api.AugmentationTarget +import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode +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.ExtensionDefinition +import org.opendaylight.yangtools.yang.model.api.GroupingDefinition +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode +import org.opendaylight.yangtools.yang.model.api.Module +import org.opendaylight.yangtools.yang.model.api.NotificationDefinition +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.TypeDefinition +import org.opendaylight.yangtools.yang.model.api.UsesNode +import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition +import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition +import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition +import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint +import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint +import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition +import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition +import org.opendaylight.yangtools.yang.model.util.ExtendedType +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.sonatype.plexus.build.incremental.BuildContext +import org.sonatype.plexus.build.incremental.DefaultBuildContext + +class GeneratorImpl { + + File path + static val REVISION_FORMAT = new SimpleDateFormat("yyyy-MM-dd") + static val Logger LOG = LoggerFactory.getLogger(GeneratorImpl) + static val BuildContext CTX = new DefaultBuildContext(); + var Module currentModule; + val Map imports = new HashMap(); + var SchemaContext ctx; + + StringBuilder augmentChildNodesAsString + + DataSchemaNode lastNodeInTargetPath = null + + def generate(SchemaContext context, File targetPath, Set modulesToGen) throws IOException { + path = targetPath; + path.mkdirs(); + val it = new HashSet; + for (module : modulesToGen) { + add(generateDocumentation(module, context)); + } + return it; + } + + def generateDocumentation(Module module, SchemaContext ctx) { + val destination = new File(path, '''«module.name».html''') + this.ctx = ctx; + module.imports.forEach[importModule | this.imports.put(importModule.prefix, importModule.moduleName)] + try { + val fw = new OutputStreamWriter(CTX.newFileOutputStream(destination)) + val bw = new BufferedWriter(fw) + currentModule = module; + bw.append(generate(module, ctx)); + bw.close(); + fw.close(); + } catch (IOException e) { + LOG.error(e.getMessage()); + } + return destination; + } + + def generate(Module module, SchemaContext ctx) ''' + + + + «module.name» + + + «body(module, ctx)» + + + ''' + + def body(Module module, SchemaContext ctx) ''' + «header(module)» + + «typeDefinitionsSummary(module)» + «identitiesSummary(module)» + «groupingsSummary(module)» + «augmentationsSummary(module, ctx)» + «objectsSummary(module)» + «notificationsSummary(module)» + «rpcsSummary(module)» + «extensionsSummary(module)» + «featuresSummary(module)» + + «typeDefinitions(module)» + + «identities(module)» + + «groupings(module)» + + «dataStore(module)» + + «childNodes(module)» + + «notifications(module)» + + «augmentations(module, ctx)» + + «rpcs(module)» + + «extensions(module)» + + «features(module)» + + ''' + + + private def typeDefinitionsSummary(Module module) { + val Set> typedefs = module.typeDefinitions + if (typedefs.empty) { + return ''; + } + return ''' +
+

Type Definitions Summary

+ + + + + + «FOR typedef : typedefs» + + + + + «ENDFOR» +
NameDescription
+ «anchorLink(typedef.QName.localName, strong(typedef.QName.localName))» + + «typedef.description» +
+
+ ''' + } + + def typeDefinitions(Module module) { + val Set> typedefs = module.typeDefinitions + if (typedefs.empty) { + return ''; + } + return ''' +

Type Definitions

+
    + «FOR typedef : typedefs» +
  • +

    «typedef.QName.localName»

    +
      + «typedef.descAndRefLi» + «typedef.restrictions» +
    +
  • + «ENDFOR» +
+ ''' + } + + private def identities(Module module) { + if (module.identities.empty) { + return ''; + } + return ''' +

Identities

+
    + «FOR identity : module.identities» +
  • +

    «identity.QName.localName»

    +
      + «identity.descAndRefLi» + «IF identity.baseIdentity !== null» + «listItem("base", identity.baseIdentity.QName.localName)» + «ENDIF» +
    +
  • + «ENDFOR» +
+ ''' + } + + private def identitiesSummary(Module module) { + if (module.identities.empty) { + return ''; + } + return ''' +

Identities Summary

+ + + + + + «FOR identity : module.identities» + + + + + «ENDFOR» +
NameDescription
+ «anchorLink(identity.QName.localName, strong(identity.QName.localName))» + + «identity.description» +
+ ''' + } + + private def groupings(Module module) { + if (module.groupings.empty) { + return ''; + } + return ''' +

Groupings

+
    + «FOR grouping : module.groupings» +
  • +

    «grouping.QName.localName»

    +
      + «grouping.descAndRefLi» + «FOR childNode : grouping.childNodes» + «childNode.printSchemaNodeInfo» + «ENDFOR» +
    +
  • + «ENDFOR» +
+ ''' + } + + private def groupingsSummary(Module module) { + if (module.groupings.empty) { + return ''; + } + return ''' +

Groupings Summary

+ + + + + + «FOR grouping : module.groupings» + + + + + «ENDFOR» +
NameDescription
+ «anchorLink(grouping.QName.localName, strong(grouping.QName.localName))» + + «grouping.description» +
+ ''' + } + + def dataStore(Module module) { + if (module.childNodes.empty) { + return ''; + } + return ''' +

Datastore Structure

+ «tree(module)» + ''' + } + + def augmentations(Module module, SchemaContext context) { + if (module.augmentations.empty) { + return ''; + } + return ''' +

Augmentations

+ +
    + «FOR augment : module.augmentations» +
  • +

    + Target [«typeAnchorLink(augment.targetPath,schemaPathToString(module, augment.targetPath, context, augment))»]

    + «augment.description» + Status: «strong(String.valueOf(augment.status))» + «IF augment.reference !== null» + Reference «augment.reference» + «ENDIF» + «IF augment.whenCondition !== null» + When «augment.whenCondition.toString» + «ENDIF» + «FOR childNode : augment.childNodes» + «childNode.printSchemaNodeInfo» + «ENDFOR» + +

    Example

    + «createAugmentChildNodesAsString(new ArrayList(augment.childNodes))» + «printNodeChildren(parseTargetPath(augment.targetPath))» +
  • + «ENDFOR» +
+ ''' + } + + private def createAugmentChildNodesAsString(List childNodes) { + augmentChildNodesAsString = new StringBuilder(); + augmentChildNodesAsString.append(printNodeChildren(childNodes)) + return '' + } + + private def parseTargetPath(SchemaPath path) { + val List nodes = new ArrayList(); + for (QName pathElement : path.pathFromRoot) { + val module = ctx.findModuleByNamespaceAndRevision(pathElement.namespace, pathElement.revision); + if (module !== null) { + var foundNode = module.getDataChildByName(pathElement) + if(foundNode == null) { + val child = nodes.last + if (child instanceof DataNodeContainer) { + val dataContNode = child as DataNodeContainer + foundNode = findNodeInChildNodes(pathElement, dataContNode.childNodes) + } + } + if(foundNode != null) { + nodes.add(foundNode); + } + } + } + if(! nodes.empty) { + lastNodeInTargetPath = nodes.get(nodes.size() - 1) + } + + val List targetPathNodes = new ArrayList(); + targetPathNodes.add(lastNodeInTargetPath) + + return targetPathNodes + } + + private def DataSchemaNode findNodeInChildNodes(QName findingNode, Iterable childNodes) { + for(child : childNodes) { + if (child.QName.equals(findingNode)) + return child; + } + // find recursively + for(child : childNodes) { + if(child instanceof ContainerSchemaNode) { + val contChild = child as ContainerSchemaNode + val foundChild = findNodeInChildNodes(findingNode, contChild.childNodes) + if (foundChild != null) + return foundChild; + } + else if(child instanceof ListSchemaNode) { + val listChild = child as ListSchemaNode + val foundChild = findNodeInChildNodes(findingNode, listChild.childNodes) + if (foundChild != null) + return foundChild; + } + } + } + + private def printNodeChildren(List childNodes) { + if (childNodes.empty) { + return '' + } + + return + ''' +
+        «printAugmentedNode(childNodes.get(0))»
+        
+ ''' + } + + private def CharSequence printAugmentedNode(DataSchemaNode child) { + + if(child instanceof ChoiceCaseNode) + return '' + + return + ''' + «IF child instanceof ContainerSchemaNode» + «printContainerNode(child as ContainerSchemaNode)» + «ENDIF» + «IF child instanceof AnyXmlSchemaNode» + «printAnyXmlNode(child as AnyXmlSchemaNode)» + «ENDIF» + «IF child instanceof LeafSchemaNode» + «printLeafNode(child as LeafSchemaNode)» + «ENDIF» + «IF child instanceof LeafListSchemaNode» + «printLeafListNode(child as LeafListSchemaNode)» + «ENDIF» + «IF child instanceof ListSchemaNode» + «printListNode(child as ListSchemaNode)» + «ENDIF» + «IF child instanceof ChoiceNode» + «printChoiceNode(child as ChoiceNode)» + «ENDIF» + ''' + } + + private def printChoiceNode(ChoiceNode child) { + val List cases = new ArrayList(child.cases); + if(!cases.empty) { + val ChoiceCaseNode aCase = cases.get(0) + for(caseChildNode : aCase.childNodes) + printAugmentedNode(caseChildNode) + } + } + + private def printListNode(ListSchemaNode listNode) { + return + ''' + <«listNode.QName.localName»«IF !listNode.QName.namespace.equals(currentModule.namespace)» xmlns="«listNode.QName.namespace»"«ENDIF»> + «FOR child : listNode.childNodes» + «printAugmentedNode(child)» + «ENDFOR» + </«listNode.QName.localName»> + ''' + } + + private def printContainerNode(ContainerSchemaNode containerNode) { + return + ''' + <«containerNode.QName.localName»«IF !containerNode.QName.namespace.equals(currentModule.namespace)» xmlns="«containerNode.QName.namespace»"«ENDIF»> + «FOR child : containerNode.childNodes» + «printAugmentedNode(child)» + «ENDFOR» + </«containerNode.QName.localName»> + ''' + } + + private def printLeafListNode(LeafListSchemaNode leafListNode) { + return + ''' + <«leafListNode.QName.localName»>. . .</«leafListNode.QName.localName»> + <«leafListNode.QName.localName»>. . .</«leafListNode.QName.localName»> + <«leafListNode.QName.localName»>. . .</«leafListNode.QName.localName»> + ''' + } + + private def printAnyXmlNode(AnyXmlSchemaNode anyXmlNode) { + return + ''' + <«anyXmlNode.QName.localName»>. . .</«anyXmlNode.QName.localName»> + ''' + } + + private def printLeafNode(LeafSchemaNode leafNode) { + return + ''' + <«leafNode.QName.localName»>. . .</«leafNode.QName.localName»> + ''' + } + + private def augmentationsSummary(Module module, SchemaContext context) { + if (module.augmentations.empty) { + return ''; + } + return ''' +

Augmentations Summary

+ + + + + + «FOR augment : module.augmentations» + + + + + «ENDFOR» +
TargetDescription
+ «anchorLink(schemaPathToString(module, augment.targetPath, context, augment), + strong(schemaPathToString(module, augment.targetPath, context, augment)))» + + «augment.description» +
+ ''' + } + + def notifications(Module module) { + val Set notificationdefs = module.notifications + if (notificationdefs.empty) { + return ''; + } + + return ''' +

Notifications

+ «FOR notificationdef : notificationdefs» + +

«notificationdef.nodeName»

+ «notificationdef.descAndRef» + «FOR childNode : notificationdef.childNodes» + «childNode.printSchemaNodeInfo» + «ENDFOR» + «ENDFOR» + ''' + } + + private def notificationsSummary(Module module) { + if (module.notifications.empty) { + return ''; + } + return ''' +

Notifications Summary

+ + + + + + «FOR notification : module.notifications» + + + + + «ENDFOR» +
NameDescription
+ «anchorLink(notification.path.schemaPathToId, strong(notification.QName.localName))» + + «notification.description» +
+ ''' + } + + def rpcs(Module module) { + if (module.rpcs.empty) { + return ''; + } + + return ''' +

RPC Definitions

+ «FOR rpc : module.rpcs» +

«rpc.nodeName»

+
    + «rpc.descAndRefLi» + «rpc.input.printSchemaNodeInfo» + «rpc.output.printSchemaNodeInfo» +
+ «ENDFOR» + + ''' + } + + private def rpcsSummary(Module module) { + if (module.rpcs.empty) { + return ''; + } + return ''' +

RPCs Summary

+ + + + + + «FOR rpc : module.rpcs» + + + + + «ENDFOR» +
NameDescription
+ «anchorLink(rpc.QName.localName, strong(rpc.QName.localName))» + + «rpc.description» +
+ ''' + } + + def extensions(Module module) { + if (module.extensionSchemaNodes.empty) { + return ''; + } + return ''' +

Extensions

+ «FOR ext : module.extensionSchemaNodes» +
  • +

    «ext.nodeName»

    +
  • + «extensionInfo(ext)» + «ENDFOR» + ''' + } + + private def extensionsSummary(Module module) { + if (module.extensionSchemaNodes.empty) { + return ''; + } + return ''' +

    Extensions Summary

    + + + + + + «FOR ext : module.extensionSchemaNodes» + + + + + «ENDFOR» +
    NameDescription
    + «anchorLink(ext.QName.localName, strong(ext.QName.localName))» + + «ext.description» +
    + ''' + } + + def features(Module module) { + if (module.features.empty) { + return ''; + } + return ''' +

    Features

    + +
      + «FOR feature : module.features» +
    • +

      «feature.QName.localName»

      +
        + «feature.descAndRefLi» +
      +
    • + «ENDFOR» +
    + ''' + } + + private def featuresSummary(Module module) { + if (module.features.empty) { + return ''; + } + return ''' +

    Features Summary

    + + + + + + «FOR feature : module.features» + + + + + «ENDFOR» +
    NameDescription
    + «anchorLink(feature.QName.localName, strong(feature.QName.localName))» + + «feature.description» +
    + ''' + } + + private def objectsSummary(Module module) { + if (module.childNodes.empty) { + return ''; + } + return ''' +

    Child Nodes Summary

    + + + + + + «FOR childNode : module.childNodes» + + + + + «ENDFOR» +
    NameDescription
    + «anchorLink(childNode.QName.localName, strong(childNode.QName.localName))» + + «childNode.description» +
    + ''' + } + + def header(Module module) + ''' +

    «module.name»

    + +

    Base Information

    + + + + + + + + + + + + + + + + + + + + + + + «FOR imp : module.imports BEFORE ''''''» + «imp.prefix»:«imp.moduleName»«IF imp.revision !== null» «REVISION_FORMAT.format(imp.revision)»«ENDIF»; + «ENDFOR» + +
    «strong("prefix")»«module.prefix»
    «strong("namespace")»«module.namespace»
    «strong("revision")»«REVISION_FORMAT.format(module.revision)»
    «strong("description")»«module.description»
    «strong("yang-version")»«module.yangVersion»
    «strong("imports")»''' AFTER '''
    + ''' + + def CharSequence schemaPathToId(SchemaPath path) { + if(path !== null) { + return '''«FOR qName : path.path SEPARATOR "/"»«qName.localName»«ENDFOR»''' + } + } + + def code(String string) '''«string»''' + + def process(Module module) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + def CharSequence tree(Module module) ''' + «strong(module.name)» + «module.childNodes.treeSet(YangInstanceIdentifier.builder.build())» + ''' + + private def dispatch CharSequence tree(ChoiceNode node,YangInstanceIdentifier path) ''' + «node.nodeName» (choice) + «casesTree(node.cases,path)» + ''' + + def casesTree(Set nodes,YangInstanceIdentifier path) ''' +
      + «FOR node : nodes» +
    • + «node.nodeName» + «node.childNodes.treeSet(path)» +
    • + «ENDFOR» +
    + ''' + + private def dispatch CharSequence tree(DataSchemaNode node,YangInstanceIdentifier path) ''' + «node.nodeName» + ''' + + private def dispatch CharSequence tree(ListSchemaNode node,YangInstanceIdentifier path) ''' + «val newPath = path.append(node)» + «localLink(newPath,node.nodeName)» + «node.childNodes.treeSet(newPath)» + ''' + + private def dispatch CharSequence tree(ContainerSchemaNode node,YangInstanceIdentifier path) ''' + «val newPath = path.append(node)» + «localLink(newPath,node.nodeName)» + «node.childNodes.treeSet(newPath)» + ''' + + def CharSequence childNodes(Module module) ''' + «val childNodes = module.childNodes» + «IF !childNodes.nullOrEmpty» +

    Child nodes

    + + «childNodes.printChildren(3,YangInstanceIdentifier.builder().build())» + «ENDIF» + ''' + + def CharSequence printSchemaNodeInfo(DataSchemaNode node) { + return ''' +
      + «node.printBaseInfo» + «IF node instanceof DataNodeContainer» + «val dataNode = node as DataNodeContainer» +
        + «FOR usesNode : dataNode.uses» + «usesNode.printUses» + «ENDFOR» +
      +
        + «val Set> typeDefinitions = dataNode.typeDefinitions» + «FOR typeDef : typeDefinitions» + «typeDef.restrictions» + «ENDFOR» +
      +
        + «FOR grouping : dataNode.groupings» + «grouping.printGrouping» + «ENDFOR» +
      +
        + «FOR child : dataNode.childNodes» + «child.printSchemaNodeInfo» + «ENDFOR» +
      + «ENDIF» +
    + ''' + } + + def String typeAnchorLink(SchemaPath path, CharSequence text) { + if(path !== null) { + val lastElement = Iterables.getLast(path.pathFromRoot) + val ns = lastElement.namespace + if (ns == this.currentModule.namespace) { + return '''«text»''' + } else { + return '''(«ns»)«text»''' + //to enable external (import) links + //return '''«prefix»:«text»''' + } + } + } + + def CharSequence printBaseInfo(SchemaNode node) { + if(node instanceof LeafSchemaNode) { + val LeafSchemaNode leafNode = (node as LeafSchemaNode) + return ''' + «printInfo(node, "leaf")» + «listItem("type", typeAnchorLink(leafNode.type?.path, leafNode.type.QName.localName))» + «listItem("units", leafNode.units)» + «listItem("default", leafNode.^default)» + + ''' + } else if(node instanceof LeafListSchemaNode) { + val LeafListSchemaNode leafListNode = (node as LeafListSchemaNode) + return ''' + «printInfo(node, "leaf-list")» + «listItem("type", leafListNode.type?.QName.localName)» + + ''' + } else if(node instanceof ListSchemaNode) { + val ListSchemaNode listNode = (node as ListSchemaNode) + return ''' + «printInfo(node, "list")» + «FOR keyDef : listNode.keyDefinition» + «listItem("key definition", keyDef.localName)» + «ENDFOR» + + ''' + } else if(node instanceof ChoiceNode) { + val ChoiceNode choiceNode = (node as ChoiceNode) + return ''' + «printInfo(node, "choice")» + «listItem("default case", choiceNode.defaultCase)» + «FOR caseNode : choiceNode.cases» + «caseNode.printSchemaNodeInfo» + «ENDFOR» + + ''' + } else if(node instanceof ChoiceCaseNode) { + return ''' + «printInfo(node, "case")» + + ''' + } else if(node instanceof ContainerSchemaNode) { + return ''' + «printInfo(node, "container")» + + ''' + } else if(node instanceof AnyXmlSchemaNode) { + return ''' + «printInfo(node, "anyxml")» + + ''' + } + } + + def CharSequence printInfo(SchemaNode node, String nodeType) { + return ''' + «IF node instanceof AugmentationTarget» + «IF node !== null» + +
  • + «nodeType»: «node.QName.localName» +
  • +
    + «ENDIF» + «ELSE» + «strong(listItem(nodeType, node.QName.localName))» + «ENDIF» +
      + «listItem("description", node.description)» + «listItem("reference", node.reference)» + «IF node instanceof DataSchemaNode» + «listItem("when condition", (node as DataSchemaNode).constraints.whenCondition?.toString)» + «listItem("min elements", (node as DataSchemaNode).constraints.minElements?.toString)» + «listItem("max elements", (node as DataSchemaNode).constraints.maxElements?.toString)» + «ENDIF» + ''' + } + + def CharSequence printUses(UsesNode usesNode) { + return ''' + «strong(listItem("uses", typeAnchorLink(usesNode.groupingPath, usesNode.groupingPath.pathTowardsRoot.iterator.next.localName)))» +
        +
      • refines: +
          + «FOR sp : usesNode.refines.keySet» + «listItem("node name", usesNode.refines.get(sp).QName.localName)» + «ENDFOR» +
        +
      • + «FOR augment : usesNode.augmentations» + «typeAnchorLink(augment.targetPath,schemaPathToString(currentModule, augment.targetPath, ctx, augment))» + «ENDFOR» +
      + ''' + } + + def CharSequence printGrouping(GroupingDefinition grouping) { + return ''' + «strong(listItem("grouping", grouping.QName.localName))» + ''' + } + + def CharSequence printChildren(Iterable nodes, int level, YangInstanceIdentifier path) { + val anyxmlNodes = nodes.filter(AnyXmlSchemaNode) + val leafNodes = nodes.filter(LeafSchemaNode) + val leafListNodes = nodes.filter(LeafListSchemaNode) + val choices = nodes.filter(ChoiceNode) + val cases = nodes.filter(ChoiceCaseNode) + val containers = nodes.filter(ContainerSchemaNode) + val lists = nodes.filter(ListSchemaNode) + return ''' + «IF ((anyxmlNodes.size + leafNodes.size + leafListNodes.size + containers.size + lists.size) > 0)» +

      Direct children

      +
        + «FOR childNode : anyxmlNodes» + «childNode.printShortInfo(level,path)» + «ENDFOR» + «FOR childNode : leafNodes» + «childNode.printShortInfo(level,path)» + «ENDFOR» + «FOR childNode : leafListNodes» + «childNode.printShortInfo(level,path)» + «ENDFOR» + «FOR childNode : containers» + «childNode.printShortInfo(level,path)» + «ENDFOR» + «FOR childNode : lists» + «childNode.printShortInfo(level,path)» + «ENDFOR» +
      + «ENDIF» + + «IF path.pathArguments.iterator.hasNext» +

      XML example

      + «nodes.xmlExample(path.pathArguments.last.nodeType,path)» + + «ENDIF» + «FOR childNode : containers» + «childNode.printInfo(level,path)» + «ENDFOR» + «FOR childNode : lists» + «childNode.printInfo(level,path)» + «ENDFOR» + «FOR childNode : choices» + «childNode.printInfo(level,path)» + «ENDFOR» + «FOR childNode : cases» + «childNode.printInfo(level,path)» + «ENDFOR» + ''' + } + + def CharSequence xmlExample(Iterable nodes, QName name,YangInstanceIdentifier path) ''' +
      +        «xmlExampleTag(name,nodes.xmplExampleTags(path))»
      +    
      + ''' + + def CharSequence xmplExampleTags(Iterable nodes, YangInstanceIdentifier identifier) ''' + + «FOR node : nodes» + + «node.asXmlExampleTag(identifier)» + «ENDFOR» + + ''' + + private def dispatch CharSequence asXmlExampleTag(LeafSchemaNode node, YangInstanceIdentifier identifier) ''' + «node.QName.xmlExampleTag("...")» + ''' + + private def dispatch CharSequence asXmlExampleTag(LeafListSchemaNode node, YangInstanceIdentifier identifier) ''' + <!-- This node could appear multiple times --> + «node.QName.xmlExampleTag("...")» + ''' + + private def dispatch CharSequence asXmlExampleTag(ContainerSchemaNode node, YangInstanceIdentifier identifier) ''' + <!-- See «localLink(identifier.append(node),"definition")» for child nodes. --> + «node.QName.xmlExampleTag("...")» + ''' + + + private def dispatch CharSequence asXmlExampleTag(ListSchemaNode node, YangInstanceIdentifier identifier) ''' + <!-- See «localLink(identifier.append(node),"definition")» for child nodes. --> + <!-- This node could appear multiple times --> + «node.QName.xmlExampleTag("...")» + ''' + + + private def dispatch CharSequence asXmlExampleTag(DataSchemaNode node, YangInstanceIdentifier identifier) ''' + + ''' + + + def xmlExampleTag(QName name, CharSequence data) { + return '''<«name.localName» xmlns="«name.namespace»">«data»</«name.localName»>''' + } + + def header(int level,QName name) '''«name.localName»''' -class GeneratorImpl { - - File path - static val REVISION_FORMAT = new SimpleDateFormat("yyyy-MM-dd") - static val Logger LOG = LoggerFactory.getLogger(GeneratorImpl) - static val BuildContext CTX = new DefaultBuildContext(); - var Module currentModule; - - - def generate(SchemaContext context, File targetPath, Set modulesToGen) throws IOException { - path = targetPath; - path.mkdirs(); - val it = new HashSet; - for (module : modulesToGen) { - add(generateDocumentation(module, context)); - } - return it; - } - - def generateDocumentation(Module module, SchemaContext ctx) { - val destination = new File(path, '''«module.name».html''') - try { - val fw = new OutputStreamWriter(CTX.newFileOutputStream(destination)) - val bw = new BufferedWriter(fw) - currentModule = module; - bw.append(generate(module, ctx)); - bw.close(); - fw.close(); - } catch (IOException e) { - LOG.error(e.getMessage()); - } - return destination; - } - - def generate(Module module, SchemaContext ctx) ''' - - - - «module.name» - - - «body(module, ctx)» - - - ''' - - def body(Module module, SchemaContext ctx) ''' - «header(module)» - - «typeDefinitions(module)» - - «identities(module)» - - «groupings(module)» - - «dataStore(module)» - - «childNodes(module)» - - «notifications(module)» - - «augmentations(module, ctx)» - - «rpcs(module)» - - «extensions(module)» - - «features(module)» - - ''' - - - def typeDefinitions(Module module) { - val Set> typedefs = module.typeDefinitions - if (typedefs.empty) { - return ''; - } - return ''' -

      Type Definitions

      -
        - «FOR typedef : typedefs» -
      • - «strong("typedef " + typedef.QName.localName)» -
          - «typedef.descAndRefLi» - «typedef.restrictions» -
        -
      • - «ENDFOR» -
      - ''' - } - - private def identities(Module module) { - if (module.identities.empty) { - return ''; - } - return ''' -

      Identities

      -
        - «FOR identity : module.identities» -
      • - «strong("identity " + identity.QName.localName)» -
          - «identity.descAndRefLi» - «IF identity.baseIdentity != null» - «listItem("base", identity.baseIdentity.QName.localName)» - «ENDIF» -
        -
      • - «ENDFOR» -
      - ''' - } - - private def groupings(Module module) { - if (module.groupings.empty) { - return ''; - } - return ''' -

      Groupings

      -
        - «FOR grouping : module.groupings» -
      • - «strong("grouping " + grouping.QName.localName)» -
          - «grouping.descAndRefLi» -
        -
      • - «ENDFOR» -
      - ''' - } - - def dataStore(Module module) { - if (module.childNodes.empty) { - return ''; - } - return ''' -

      Datastore Structure

      - «tree(module)» - ''' - } - - def augmentations(Module module, SchemaContext context) { - if (module.augmentations.empty) { - return ''; - } - return ''' -

      Augmentations

      - -
        - «FOR augment : module.augmentations» -
      • -

        Target [«schemaPathAsRestconfPath(module, augment.targetPath, context)»]

        - «augment.description» - «IF augment.reference !== null» - Reference «augment.reference» - «ENDIF» - «IF augment.whenCondition !== null» - When «augment.whenCondition.toString» - «ENDIF» - «augment.childNodes.printChildren(3,InstanceIdentifier.builder().toInstance())» -
      • - «ENDFOR» -
      - ''' - } - - def notifications(Module module) { - val Set notificationdefs = module.notifications - if (notificationdefs.empty) { - return ''; - } - - return ''' -

      Notifications

      - «FOR notificationdef : notificationdefs» - -

      «notificationdef.nodeName»

      - «notificationdef.descAndRef» - «notificationdef.childNodes.printChildren(3,InstanceIdentifier.builder().toInstance())» - «ENDFOR» - ''' - } - - def rpcs(Module module) { - if (module.rpcs.empty) { - return ''; - } - - return ''' -

      RPC Definitions

      - «FOR rpc : module.rpcs» -

      «rpc.nodeName»

      - «rpc.rpcInfo(InstanceIdentifier.builder().node(rpc.QName).toInstance())» - «ENDFOR» -
    - ''' - } - - def extensions(Module module) { - if (module.extensionSchemaNodes.empty) { - return ''; - } - return ''' -

    Extensions

    - «FOR ext : module.extensionSchemaNodes» -
  • -

    «ext.nodeName»

    -
  • - «extensionInfo(ext)» - «ENDFOR» - ''' - } - - def features(Module module) { - if (module.features.empty) { - return ''; - } - return ''' -

    Features

    - -
      - «FOR feature : module.features» -
    • - «strong("feature " + feature.QName.localName)» -
        - «feature.descAndRefLi» -
      -
    • - «ENDFOR» -
    - ''' - } - - def header(Module module) ''' -

    «module.name»

    - -

    Base Information

    -
    -
    Prefix
    -
    «pre(module.prefix)»
    -
    Namespace
    -
    «pre(module.namespace.toString)»
    -
    Revision
    -
    «pre(REVISION_FORMAT.format(module.revision))»
    - - «FOR imp : module.imports BEFORE "
    Imports
    " » -
    «code(imp.prefix)» = «code(imp.moduleName)»
    - «ENDFOR» -
    - ''' - - def code(String string) '''«string»''' - - def process(Module module) { - throw new UnsupportedOperationException("TODO: auto-generated method stub") - } - - def CharSequence tree(Module module) ''' - «strong("module " + module.name)» - «module.childNodes.treeSet(InstanceIdentifier.builder.toInstance())» - ''' - - private def dispatch CharSequence tree(ChoiceNode node,InstanceIdentifier path) ''' - «node.nodeName» (choice) - «casesTree(node.cases,path)» - ''' - - def casesTree(Set nodes,InstanceIdentifier path) ''' -
      - «FOR node : nodes» -
    • - «node.nodeName» - «node.childNodes.treeSet(path)» -
    • - «ENDFOR» -
    - ''' - - private def dispatch CharSequence tree(DataSchemaNode node,InstanceIdentifier path) ''' - «node.nodeName» - ''' - - private def dispatch CharSequence tree(ListSchemaNode node,InstanceIdentifier path) ''' - «val newPath = path.append(node)» - «localLink(newPath,node.nodeName)» - «node.childNodes.treeSet(newPath)» - ''' - - private def dispatch CharSequence tree(ContainerSchemaNode node,InstanceIdentifier path) ''' - «val newPath = path.append(node)» - «localLink(newPath,node.nodeName)» - «node.childNodes.treeSet(newPath)» - ''' - - def CharSequence childNodes(Module module) ''' - «val childNodes = module.childNodes» - «IF childNodes !== null && !childNodes.empty» -

    Child nodes

    - - «childNodes.printChildren(3,InstanceIdentifier.builder().toInstance())» - «ENDIF» - ''' - - def CharSequence printChildren(Set nodes, int level, InstanceIdentifier path) { - val anyxmlNodes = nodes.filter(AnyXmlSchemaNode) - val leafNodes = nodes.filter(LeafSchemaNode) - val leafListNodes = nodes.filter(LeafListSchemaNode) - val choices = nodes.filter(ChoiceNode) - val cases = nodes.filter(ChoiceCaseNode) - val containers = nodes.filter(ContainerSchemaNode) - val lists = nodes.filter(ListSchemaNode) - return ''' - «IF ((anyxmlNodes.size + leafNodes.size + leafListNodes.size + containers.size + lists.size) > 0)» -

    Direct children

    -
      - «FOR childNode : anyxmlNodes» - «childNode.printShortInfo(level,path)» - «ENDFOR» - «FOR childNode : leafNodes» - «childNode.printShortInfo(level,path)» - «ENDFOR» - «FOR childNode : leafListNodes» - «childNode.printShortInfo(level,path)» - «ENDFOR» - «FOR childNode : containers» - «childNode.printShortInfo(level,path)» - «ENDFOR» - «FOR childNode : lists» - «childNode.printShortInfo(level,path)» - «ENDFOR» -
    - «ENDIF» - - «IF !path.path.empty» -

    XML example

    - «nodes.xmlExample(path.path.last.nodeType,path)» - - «ENDIF» - «FOR childNode : containers» - «childNode.printInfo(level,path)» - «ENDFOR» - «FOR childNode : lists» - «childNode.printInfo(level,path)» - «ENDFOR» - «FOR childNode : choices» - «childNode.printInfo(level,path)» - «ENDFOR» - «FOR childNode : cases» - «childNode.printInfo(level,path)» - «ENDFOR» - - ''' - } - - def CharSequence xmlExample(Set nodes, QName name,InstanceIdentifier path) ''' -
    -        «xmlExampleTag(name,nodes.xmplExampleTags(path))»
    -    
    - ''' - - def CharSequence xmplExampleTags(Set nodes, InstanceIdentifier identifier) ''' - - «FOR node : nodes» - - «node.asXmlExampleTag(identifier)» - «ENDFOR» - - ''' - - private def dispatch CharSequence asXmlExampleTag(LeafSchemaNode node, InstanceIdentifier identifier) ''' - «node.QName.xmlExampleTag("...")» - ''' - - private def dispatch CharSequence asXmlExampleTag(LeafListSchemaNode node, InstanceIdentifier identifier) ''' - <!-- This node could appear multiple times --> - «node.QName.xmlExampleTag("...")» - ''' - - private def dispatch CharSequence asXmlExampleTag(ContainerSchemaNode node, InstanceIdentifier identifier) ''' - <!-- See «localLink(identifier.append(node),"definition")» for child nodes. --> - «node.QName.xmlExampleTag("...")» - ''' - - - private def dispatch CharSequence asXmlExampleTag(ListSchemaNode node, InstanceIdentifier identifier) ''' - <!-- See «localLink(identifier.append(node),"definition")» for child nodes. --> - <!-- This node could appear multiple times --> - «node.QName.xmlExampleTag("...")» - ''' - - - private def dispatch CharSequence asXmlExampleTag(DataSchemaNode node, InstanceIdentifier identifier) ''' - - ''' - - - def xmlExampleTag(QName name, CharSequence data) { - return '''<«name.localName» xmlns="«name.namespace»">«data»</«name.localName»>''' - } - - def header(int level,QName name) '''«name.localName»''' - - - def header(int level,InstanceIdentifier name) ''' - - «FOR cmp : name.path SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR» - - ''' - - - - private def dispatch CharSequence printInfo(DataSchemaNode node, int level, InstanceIdentifier path) ''' - «header(level+1,node.QName)» - ''' - - private def dispatch CharSequence printInfo(ContainerSchemaNode node, int level, InstanceIdentifier path) ''' - «val newPath = path.append(node)» - «header(level,newPath)» -
    -
    XML Path
    -
    «newPath.asXmlPath»
    -
    Restconf path
    -
    «code(newPath.asRestconfPath)»
    -
    - «node.childNodes.printChildren(level,newPath)» - ''' - - private def dispatch CharSequence printInfo(ListSchemaNode node, int level, InstanceIdentifier path) ''' - «val newPath = path.append(node)» - «header(level,newPath)» -
    -
    XML Path
    -
    «newPath.asXmlPath»
    -
    Restconf path
    -
    «code(newPath.asRestconfPath)»
    -
    - «node.childNodes.printChildren(level,newPath)» - ''' - - private def dispatch CharSequence printInfo(ChoiceNode node, int level, InstanceIdentifier path) ''' - «val Set choiceCases = new HashSet(node.cases)» - «choiceCases.printChildren(level,path)» - ''' - - private def dispatch CharSequence printInfo(ChoiceCaseNode node, int level, InstanceIdentifier path) ''' - «node.childNodes.printChildren(level,path)» - ''' - - - - def CharSequence printShortInfo(ContainerSchemaNode node, int level, InstanceIdentifier path) { - val newPath = path.append(node); - return ''' -
  • «strong(localLink(newPath,node.QName.localName))» (container)
  • - ''' - } - - def CharSequence printShortInfo(ListSchemaNode node, int level, InstanceIdentifier path) { - val newPath = path.append(node); - return ''' -
  • «strong(localLink(newPath,node.QName.localName))» (list)
  • - ''' - } - - def CharSequence printShortInfo(AnyXmlSchemaNode node, int level, InstanceIdentifier path) { - return ''' -
  • «strong((node.QName.localName))» (anyxml)
  • - ''' - } - - def CharSequence printShortInfo(LeafSchemaNode node, int level, InstanceIdentifier path) { - return ''' -
  • «strong((node.QName.localName))» (leaf)
  • - ''' - } - - def CharSequence printShortInfo(LeafListSchemaNode node, int level, InstanceIdentifier path) { - return ''' -
  • «strong((node.QName.localName))» (leaf-list)
  • - ''' - } - - def CharSequence localLink(InstanceIdentifier identifier, CharSequence text) ''' - «text» - ''' - - - private def dispatch InstanceIdentifier append(InstanceIdentifier identifier, ContainerSchemaNode node) { - val pathArguments = new ArrayList(identifier.path) - pathArguments.add(new NodeIdentifier(node.QName)); - return new InstanceIdentifier(pathArguments); - } - - private def dispatch InstanceIdentifier append(InstanceIdentifier identifier, ListSchemaNode node) { - val pathArguments = new ArrayList(identifier.path) - val keyValues = new LinkedHashMap(); - if(node.keyDefinition != null) { - for(definition : node.keyDefinition) { - keyValues.put(definition,new Object); - } - } - pathArguments.add(new NodeIdentifierWithPredicates(node.QName,keyValues)); - return new InstanceIdentifier(pathArguments); - } - - - def asXmlPath(InstanceIdentifier identifier) { - return ""; - } - - def asRestconfPath(InstanceIdentifier identifier) { - val it = new StringBuilder(); - append(currentModule.name) - append(":") - var previous = false; - for(arg : identifier.path) { - if(previous) append("/") - append(arg.nodeType.localName); - previous = true; - if(arg instanceof NodeIdentifierWithPredicates) { - val nodeIdentifier = arg as NodeIdentifierWithPredicates; - for(qname : nodeIdentifier.keyValues.keySet) { - append("/{"); - append(qname.localName) - append("}") - } - } - } - - return it.toString; - } - - private def String schemaPathAsRestconfPath(Module module, SchemaPath schemaPath, SchemaContext ctx) { - val Map imports = new HashMap(); - for (mImport : module.imports) { - imports.put(mImport.prefix, mImport.moduleName) - } - - val List path = schemaPath.path - val StringBuilder pathString = new StringBuilder() - if (schemaPath.absolute) { - pathString.append("/") - } - - val QName qname = path.get(0) - var Object parent = ctx.findModuleByNamespaceAndRevision(qname.namespace, qname.revision) - - for (name : path) { - if (parent instanceof DataNodeContainer) { - var SchemaNode node = (parent as DataNodeContainer).getDataChildByName(name) - if (node == null && (parent instanceof Module)) { - val notifications = (parent as Module).notifications; - for (notification : notifications) { - if (notification.QName.equals(name)) { - node = notification - } - } - } + + def header(int level,YangInstanceIdentifier name) ''' + + «FOR cmp : name.pathArguments SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR» + + ''' + + + + private def dispatch CharSequence printInfo(DataSchemaNode node, int level, YangInstanceIdentifier path) ''' + «header(level+1,node.QName)» + ''' + + private def dispatch CharSequence printInfo(ContainerSchemaNode node, int level, YangInstanceIdentifier path) ''' + «val newPath = path.append(node)» + «header(level,newPath)» +
    +
    XML Path
    +
    «newPath.asXmlPath»
    +
    Restconf path
    +
    «code(newPath.asRestconfPath)»
    +
    + «node.childNodes.printChildren(level,newPath)» + ''' + + private def dispatch CharSequence printInfo(ListSchemaNode node, int level, YangInstanceIdentifier path) ''' + «val newPath = path.append(node)» + «header(level,newPath)» +
    +
    XML Path
    +
    «newPath.asXmlPath»
    +
    Restconf path
    +
    «code(newPath.asRestconfPath)»
    +
    + «node.childNodes.printChildren(level,newPath)» + ''' + + private def dispatch CharSequence printInfo(ChoiceNode node, int level, YangInstanceIdentifier path) ''' + «val Set choiceCases = new HashSet(node.cases)» + «choiceCases.printChildren(level,path)» + ''' + + private def dispatch CharSequence printInfo(ChoiceCaseNode node, int level, YangInstanceIdentifier path) ''' + «node.childNodes.printChildren(level,path)» + ''' + + + + def CharSequence printShortInfo(ContainerSchemaNode node, int level, YangInstanceIdentifier path) { + val newPath = path.append(node); + return ''' +
  • «strong(localLink(newPath,node.QName.localName))» (container) +
      +
    • configuration data: «strong(String.valueOf(node.configuration))»
    • +
    +
  • + ''' + } + + def CharSequence printShortInfo(ListSchemaNode node, int level, YangInstanceIdentifier path) { + val newPath = path.append(node); + return ''' +
  • «strong(localLink(newPath,node.QName.localName))» (list) +
      +
    • configuration data: «strong(String.valueOf(node.configuration))»
    • +
    +
  • + ''' + } + + def CharSequence printShortInfo(AnyXmlSchemaNode node, int level, YangInstanceIdentifier path) { + return ''' +
  • «strong((node.QName.localName))» (anyxml) +
      +
    • configuration data: «strong(String.valueOf(node.configuration))»
    • +
    • mandatory: «strong(String.valueOf(node.constraints.mandatory))»
    • +
    +
  • + ''' + } + + def CharSequence printShortInfo(LeafSchemaNode node, int level, YangInstanceIdentifier path) { + return ''' +
  • «strong((node.QName.localName))» (leaf) +
      +
    • configuration data: «strong(String.valueOf(node.configuration))»
    • +
    • mandatory: «strong(String.valueOf(node.constraints.mandatory))»
    • +
    +
  • + ''' + } + + def CharSequence printShortInfo(LeafListSchemaNode node, int level, YangInstanceIdentifier path) { + return ''' +
  • «strong((node.QName.localName))» (leaf-list) +
      +
    • configuration data: «strong(String.valueOf(node.configuration))»
    • +
    +
  • + ''' + } + + def CharSequence anchorLink(CharSequence anchor, CharSequence text) { + return ''' + «text» + ''' + } + + def CharSequence localLink(YangInstanceIdentifier identifier, CharSequence text) ''' + «text» + ''' + + + private def dispatch YangInstanceIdentifier append(YangInstanceIdentifier identifier, ContainerSchemaNode node) { + return identifier.node(node.QName); + } + + private def dispatch YangInstanceIdentifier append(YangInstanceIdentifier identifier, ListSchemaNode node) { + val keyValues = new LinkedHashMap(); + if(node.keyDefinition !== null) { + for(definition : node.keyDefinition) { + keyValues.put(definition,new Object); + } + } + + return identifier.node(new NodeIdentifierWithPredicates(node.QName, keyValues)); + } + + + def asXmlPath(YangInstanceIdentifier identifier) { + return ""; + } + + def asRestconfPath(YangInstanceIdentifier identifier) { + val it = new StringBuilder(); + append(currentModule.name) + append(":") + var previous = false; + for(arg : identifier.pathArguments) { + if(previous) append("/") + append(arg.nodeType.localName); + previous = true; + if(arg instanceof NodeIdentifierWithPredicates) { + val nodeIdentifier = arg as NodeIdentifierWithPredicates; + for(qname : nodeIdentifier.getKeyValues.keySet) { + append("/{"); + append(qname.localName) + append("}") + } + } + } + + return it.toString; + } + + private def String schemaPathToString(Module module, SchemaPath schemaPath, SchemaContext ctx, DataNodeContainer dataNode) { + val List path = schemaPath.path + val StringBuilder pathString = new StringBuilder() + if (schemaPath.absolute) { + pathString.append('/') + } + + val QName qname = path.get(0) + var Object parent = ctx.findModuleByNamespaceAndRevision(qname.namespace, qname.revision) + + for (name : path) { + if (parent instanceof DataNodeContainer) { + var SchemaNode node = (parent as DataNodeContainer).getDataChildByName(name) + if (node == null && (parent instanceof Module)) { + val notifications = (parent as Module).notifications; + for (notification : notifications) { + if (notification.QName.equals(name)) { + node = notification + } + } + } if (node == null && (parent instanceof Module)) { val rpcs = (parent as Module).rpcs; for (rpc : rpcs) { @@ -624,284 +1228,276 @@ class GeneratorImpl { } } } - - if (!(node instanceof ChoiceNode) && !(node instanceof ChoiceCaseNode)) { - var String prefix = name.prefix - var String moduleName - if (prefix == null || "".equals(prefix) || prefix.equals(module.prefix)) { - moduleName = module.name - } else { - moduleName = imports.get(prefix) - } - pathString.append(moduleName) - pathString.append(":") - pathString.append(name.localName) - pathString.append("/") - } - parent = node - } else if (parent instanceof ChoiceNode) { - parent = (parent as ChoiceNode).getCaseNodeByName(qname.localName) - } - } - return pathString.toString; - } - - - def CharSequence childNodesInfoTree(Map childNodes) ''' - «IF childNodes !== null && !childNodes.empty» - «FOR child : childNodes.values» - «childInfo(child, childNodes)» - «ENDFOR» - «ENDIF» - ''' - - def CharSequence childInfo(DataSchemaNode node, Map childNodes) ''' - «val String path = nodeSchemaPathToPath(node, childNodes)» - «IF path != null» - «code(path)» - «IF node !== null» -
      - «node.descAndRefLi» -
    - «ENDIF» - «ENDIF» - ''' - - private def CharSequence treeSet(Collection childNodes, InstanceIdentifier path) ''' - «IF childNodes !== null && !childNodes.empty» -
      - «FOR child : childNodes» -
    • - «child.tree(path)» -
    • - «ENDFOR» -
    - «ENDIF» - ''' - - def listKeys(ListSchemaNode node) ''' - [«FOR key : node.keyDefinition SEPARATOR " "»«key.localName»«ENDFOR»] - ''' - - private def CharSequence rpcInfo(RpcDefinition rpc,InstanceIdentifier path) ''' -
      - «rpc.descAndRefLi» -
    • - «rpc.input.tree(path)» -
    • -
    • - «rpc.output.tree(path)» -
    • -
    - ''' - - private def CharSequence extensionInfo(ExtensionDefinition ext) ''' -
      - «ext.descAndRefLi» - «listItem("Argument", ext.argument)» -
    - ''' - - private def dispatch CharSequence tree(Void obj, InstanceIdentifier path) ''' - ''' - - - - /* #################### RESTRICTIONS #################### */ - private def restrictions(TypeDefinition type) ''' - «type.toLength» - «type.toRange» - ''' - - private def dispatch toLength(TypeDefinition type) { - } - - private def dispatch toLength(BinaryTypeDefinition type) ''' - «type.lengthConstraints.toLengthStmt» - ''' - - private def dispatch toLength(StringTypeDefinition type) ''' - «type.lengthConstraints.toLengthStmt» - ''' - - private def dispatch toLength(ExtendedType type) ''' - «type.lengthConstraints.toLengthStmt» - ''' - - private def dispatch toRange(TypeDefinition type) { - } - - private def dispatch toRange(DecimalTypeDefinition type) ''' - «type.rangeConstraints.toRangeStmt» - ''' - - private def dispatch toRange(IntegerTypeDefinition type) ''' - «type.rangeConstraints.toRangeStmt» - ''' - - private def dispatch toRange(UnsignedIntegerTypeDefinition type) ''' - «type.rangeConstraints.toRangeStmt» - ''' - - private def dispatch toRange(ExtendedType type) ''' - «type.rangeConstraints.toRangeStmt» - ''' - - def toLengthStmt(Collection lengths) ''' - «IF lengths != null && !lengths.empty» - «listItem("Length restrictions")» -
      - «FOR length : lengths» -
    • - «IF length.min == length.max» - «length.min» - «ELSE» - <«length.min», «length.max»> - «ENDIF» -
    • - «ENDFOR» -
    - «ENDIF» - ''' - - def toRangeStmt(Collection ranges) ''' - «IF ranges != null && !ranges.empty» - «listItem("Range restrictions")» -
      - «FOR range : ranges» -
    • - «IF range.min == range.max» - «range.min» - «ELSE» - <«range.min», «range.max»> - «ENDIF» -
    • - «ENDFOR» -
    - «ENDIF» - ''' - - - - /* #################### UTILITY #################### */ - private def String strong(CharSequence str) '''«str»''' - private def italic(CharSequence str) '''«str»''' - private def pre(CharSequence str) '''
    «str»
    ''' - - def CharSequence descAndRefLi(SchemaNode node) ''' - «listItem(node.description)» - «listItem("Reference", node.reference)» - ''' - - def CharSequence descAndRef(SchemaNode node) ''' - «node.description» - «IF node.reference !== null» - Reference «node.reference» - «ENDIF» - ''' - - private def listItem(String value) ''' - «IF value !== null && !value.empty» -
  • - «value» -
  • - «ENDIF» - ''' - - private def listItem(String name, String value) ''' - «IF value !== null && !value.empty» -
  • - «name»: «value» -
  • - «ENDIF» - ''' - - private def String nodeSchemaPathToPath(DataSchemaNode node, Map childNodes) { - if (node instanceof ChoiceNode || node instanceof ChoiceCaseNode) { - return null - } - - val path = node.path.path - val absolute = node.path.absolute; - var StringBuilder result = new StringBuilder - if (absolute) { - result.append("/") - } - if (path !== null && !path.empty) { - val List actual = new ArrayList() - var i = 0; - for (pathElement : path) { - actual.add(pathElement) - val DataSchemaNode nodeByPath = childNodes.get(new SchemaPath(actual, absolute)) - if (!(nodeByPath instanceof ChoiceNode) && !(nodeByPath instanceof ChoiceCaseNode)) { - result.append(pathElement.localName) - if (i != path.size - 1) { - result.append("/") - } - } - i = i + 1 - } - } - return result.toString - } - - private def void collectChildNodes(Collection source, Map destination) { - for (node : source) { - destination.put(node.path, node) - if (node instanceof DataNodeContainer) { - collectChildNodes((node as DataNodeContainer).childNodes, destination) - } - if (node instanceof ChoiceNode) { - val List choiceCases = new ArrayList() - for (caseNode : (node as ChoiceNode).cases) { - choiceCases.add(caseNode) - } - collectChildNodes(choiceCases, destination) - } - } - } - - private def dispatch addedByInfo(SchemaNode node) ''' - ''' - - private def dispatch addedByInfo(DataSchemaNode node) ''' - «IF node.augmenting»(A)«ENDIF»«IF node.addedByUses»(U)«ENDIF» - ''' - - private def dispatch isAddedBy(SchemaNode node) { - return false; - } - - private def dispatch isAddedBy(DataSchemaNode node) { - if (node.augmenting || node.addedByUses) { - return true - } else { - return false; - } - } - - private def dispatch nodeName(SchemaNode node) ''' - «IF node.isAddedBy» - «italic(node.QName.localName)»«node.addedByInfo» - «ELSE» - «node.QName.localName»«node.addedByInfo» - «ENDIF» - ''' - - private def dispatch nodeName(ContainerSchemaNode node) ''' - «IF node.isAddedBy» - «strong(italic(node.QName.localName))»«node.addedByInfo» - «ELSE» - «strong(node.QName.localName)»«node.addedByInfo» - «ENDIF» - ''' - - private def dispatch nodeName(ListSchemaNode node) ''' - «IF node.isAddedBy» - «strong(italic(node.QName.localName))» «IF node.keyDefinition !== null && !node.keyDefinition.empty»«node.listKeys»«ENDIF»«node.addedByInfo» - «ELSE» - «strong(node.QName.localName)» «IF node.keyDefinition !== null && !node.keyDefinition.empty»«node.listKeys»«ENDIF» - «ENDIF» - ''' - -} + + val pathElementModule = ctx.findModuleByNamespaceAndRevision(name.namespace, name.revision) + val String moduleName = pathElementModule.name + pathString.append(moduleName) + pathString.append(':') + pathString.append(name.localName) + pathString.append('/') + if(node instanceof ChoiceNode && dataNode !== null) { + val DataSchemaNode caseNode = dataNode.childNodes.findFirst[DataSchemaNode e | e instanceof ChoiceCaseNode]; + if(caseNode !== null) { + pathString.append("(case)"); + pathString.append(caseNode.QName.localName); + } + } + parent = node + } + } + return pathString.toString; + } + + + def CharSequence childNodesInfoTree(Map childNodes) ''' + «IF childNodes !== null && !childNodes.empty» + «FOR child : childNodes.values» + «childInfo(child, childNodes)» + «ENDFOR» + «ENDIF» + ''' + + def CharSequence childInfo(DataSchemaNode node, Map childNodes) ''' + «val String path = nodeSchemaPathToPath(node, childNodes)» + «IF path != null» + «code(path)» + «IF node !== null» +
      + «node.descAndRefLi» +
    + «ENDIF» + «ENDIF» + ''' + + private def CharSequence treeSet(Collection childNodes, YangInstanceIdentifier path) ''' + «IF childNodes !== null && !childNodes.empty» +
      + «FOR child : childNodes» +
    • + «child.tree(path)» +
    • + «ENDFOR» +
    + «ENDIF» + ''' + + def listKeys(ListSchemaNode node) ''' + [«FOR key : node.keyDefinition SEPARATOR " "»«key.localName»«ENDFOR»] + ''' + + private def CharSequence extensionInfo(ExtensionDefinition ext) ''' +
      + «ext.descAndRefLi» + «listItem("Argument", ext.argument)» +
    + ''' + + private def dispatch CharSequence tree(Void obj, YangInstanceIdentifier path) ''' + ''' + + + + /* #################### RESTRICTIONS #################### */ + private def restrictions(TypeDefinition type) ''' + «type.baseType.toBaseStmt» + «type.toLength» + «type.toRange» + ''' + + private def dispatch toLength(TypeDefinition type) { + } + + private def dispatch toLength(BinaryTypeDefinition type) ''' + «type.lengthConstraints.toLengthStmt» + ''' + + private def dispatch toLength(StringTypeDefinition type) ''' + «type.lengthConstraints.toLengthStmt» + ''' + + private def dispatch toLength(ExtendedType type) ''' + «type.lengthConstraints.toLengthStmt» + ''' + + private def dispatch toRange(TypeDefinition type) { + } + + private def dispatch toRange(DecimalTypeDefinition type) ''' + «type.rangeConstraints.toRangeStmt» + ''' + + private def dispatch toRange(IntegerTypeDefinition type) ''' + «type.rangeConstraints.toRangeStmt» + ''' + + private def dispatch toRange(UnsignedIntegerTypeDefinition type) ''' + «type.rangeConstraints.toRangeStmt» + ''' + + private def dispatch toRange(ExtendedType type) ''' + «type.rangeConstraints.toRangeStmt» + ''' + + def toLengthStmt(Collection lengths) ''' + «IF lengths != null && !lengths.empty» + «listItem("Length restrictions:")» +
      + «FOR length : lengths» +
    • + «IF length.min == length.max» + «length.min» + «ELSE» + <«length.min», «length.max»> + «ENDIF» +
    • + «ENDFOR» +
    + «ENDIF» + ''' + + def toRangeStmt(Collection ranges) ''' + «IF ranges != null && !ranges.empty» + «listItem("Range restrictions:")» +
      + «FOR range : ranges» +
    • + «IF range.min == range.max» + «range.min» + «ELSE» + <«range.min», «range.max»> + «ENDIF» +
    • + «ENDFOR» +
    + «ENDIF» + ''' + + def toBaseStmt(TypeDefinition baseType) ''' + «IF baseType != null» + «listItem("Base type", typeAnchorLink(baseType?.path, baseType.QName.localName))» + «ENDIF» + ''' + + + + /* #################### UTILITY #################### */ + private def String strong(CharSequence str) '''«str»''' + private def italic(CharSequence str) '''«str»''' + + def CharSequence descAndRefLi(SchemaNode node) ''' + «listItem("Description", node.description)» + «listItem("Reference", node.reference)» + ''' + + def CharSequence descAndRef(SchemaNode node) ''' + «node.description» + «IF node.reference !== null» + Reference «node.reference» + «ENDIF» + ''' + + private def listItem(String value) ''' + «IF value !== null && !value.empty» +
  • + «value» +
  • + «ENDIF» + ''' + + private def listItem(String name, String value) ''' + «IF value !== null && !value.empty» +
  • + «name»: «value» +
  • + «ENDIF» + ''' + + private def String nodeSchemaPathToPath(DataSchemaNode node, Map childNodes) { + if (node instanceof ChoiceNode || node instanceof ChoiceCaseNode) { + return null + } + + val path = node.path.path + val absolute = node.path.absolute; + var StringBuilder result = new StringBuilder + if (absolute) { + result.append("/") + } + if (path !== null && !path.empty) { + val List actual = new ArrayList() + var i = 0; + for (pathElement : path) { + actual.add(pathElement) + val DataSchemaNode nodeByPath = childNodes.get(SchemaPath.create(actual, absolute)) + if (!(nodeByPath instanceof ChoiceNode) && !(nodeByPath instanceof ChoiceCaseNode)) { + result.append(pathElement.localName) + if (i != path.size - 1) { + result.append("/") + } + } + i = i + 1 + } + } + return result.toString + } + + private def void collectChildNodes(Collection source, Map destination) { + for (node : source) { + destination.put(node.path, node) + if (node instanceof DataNodeContainer) { + collectChildNodes((node as DataNodeContainer).childNodes, destination) + } + if (node instanceof ChoiceNode) { + val List choiceCases = new ArrayList() + for (caseNode : (node as ChoiceNode).cases) { + choiceCases.add(caseNode) + } + collectChildNodes(choiceCases, destination) + } + } + } + + private def dispatch addedByInfo(SchemaNode node) ''' + ''' + + private def dispatch addedByInfo(DataSchemaNode node) ''' + «IF node.augmenting»(A)«ENDIF»«IF node.addedByUses»(U)«ENDIF» + ''' + + private def dispatch isAddedBy(SchemaNode node) { + return false; + } + + private def dispatch isAddedBy(DataSchemaNode node) { + if (node.augmenting || node.addedByUses) { + return true + } else { + return false; + } + } + + private def dispatch nodeName(SchemaNode node) ''' + «IF node.isAddedBy» + «italic(node.QName.localName)»«node.addedByInfo» + «ELSE» + «node.QName.localName»«node.addedByInfo» + «ENDIF» + ''' + + private def dispatch nodeName(ContainerSchemaNode node) ''' + «IF node.isAddedBy» + «strong(italic(node.QName.localName))»«node.addedByInfo» + «ELSE» + «strong(node.QName.localName)»«node.addedByInfo» + «ENDIF» + ''' + + private def dispatch nodeName(ListSchemaNode node) ''' + «IF node.isAddedBy» + «strong(italic(node.QName.localName))» «IF node.keyDefinition !== null && !node.keyDefinition.empty»«node.listKeys»«ENDIF»«node.addedByInfo» + «ELSE» + «strong(node.QName.localName)» «IF node.keyDefinition !== null && !node.keyDefinition.empty»«node.listKeys»«ENDIF» + «ENDIF» + ''' + +}