X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;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=2a65150480d3a61c19c017a7a509b5d6479f2c6e;hpb=8164360cd885335e78fc1979f716777e6b8a8aa8;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 2a65150480..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 @@ -7,53 +7,54 @@ */ package org.opendaylight.yangtools.yang.unified.doc.generator -import org.opendaylight.yangtools.yang.model.api.SchemaContext +import com.google.common.collect.Iterables +import java.io.BufferedWriter import java.io.File -import java.util.Set -import org.opendaylight.yangtools.yang.model.api.Module 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.io.BufferedWriter -import java.io.OutputStreamWriter; +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.TypeDefinition +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.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.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.RangeConstraint 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.api.NotificationDefinition -import org.opendaylight.yangtools.yang.model.api.DataNodeContainer -import org.slf4j.LoggerFactory +import org.opendaylight.yangtools.yang.model.util.ExtendedType 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 -import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode +import org.slf4j.LoggerFactory +import org.sonatype.plexus.build.incremental.BuildContext +import org.sonatype.plexus.build.incremental.DefaultBuildContext class GeneratorImpl { @@ -62,7 +63,12 @@ class GeneratorImpl { 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; @@ -76,6 +82,8 @@ class GeneratorImpl { 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) @@ -104,6 +112,16 @@ class GeneratorImpl { 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)» @@ -127,6 +145,34 @@ class GeneratorImpl { ''' + 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) { @@ -137,7 +183,7 @@ class GeneratorImpl {
    «FOR typedef : typedefs»
  • - «strong("typedef " + typedef.QName.localName)» +

    «typedef.QName.localName»

      «typedef.descAndRefLi» «typedef.restrictions» @@ -157,10 +203,10 @@ class GeneratorImpl {
        «FOR identity : module.identities»
      • - «strong("identity " + identity.QName.localName)» +

        «identity.QName.localName»

          «identity.descAndRefLi» - «IF identity.baseIdentity != null» + «IF identity.baseIdentity !== null» «listItem("base", identity.baseIdentity.QName.localName)» «ENDIF»
        @@ -170,6 +216,31 @@ class GeneratorImpl { ''' } + 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 ''; @@ -179,9 +250,12 @@ class GeneratorImpl {
          «FOR grouping : module.groupings»
        • - «strong("grouping " + grouping.QName.localName)» +

          «grouping.QName.localName»

            «grouping.descAndRefLi» + «FOR childNode : grouping.childNodes» + «childNode.printSchemaNodeInfo» + «ENDFOR»
        • «ENDFOR» @@ -189,6 +263,31 @@ class GeneratorImpl { ''' } + 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 ''; @@ -205,24 +304,209 @@ class GeneratorImpl { } return '''

          Augmentations

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

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

            +

            + 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» - «augment.childNodes.printChildren(3,InstanceIdentifier.builder().toInstance())» + «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 @@ -234,10 +518,37 @@ class GeneratorImpl {

          Notifications

          «FOR notificationdef : notificationdefs» -

          «notificationdef.nodeName»

          +

          «notificationdef.nodeName»

          «notificationdef.descAndRef» - «notificationdef.childNodes.printChildren(3,InstanceIdentifier.builder().toInstance())» + «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» +
          ''' } @@ -249,13 +560,42 @@ class GeneratorImpl { return '''

          RPC Definitions

          «FOR rpc : module.rpcs» -

          «rpc.nodeName»

          - «rpc.rpcInfo(InstanceIdentifier.builder().node(rpc.QName).toInstance())» +

          «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 ''; @@ -264,13 +604,38 @@ class GeneratorImpl {

        Extensions

        «FOR ext : module.extensionSchemaNodes»
      • -

        «ext.nodeName»

        +

        «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 ''; @@ -281,7 +646,7 @@ class GeneratorImpl {
          «FOR feature : module.features»
        • - «strong("feature " + feature.QName.localName)» +

          «feature.QName.localName»

            «feature.descAndRefLi»
          @@ -291,24 +656,96 @@ class GeneratorImpl { ''' } - def header(Module module) ''' + 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

          -
          -
          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» -
          + + + + + + + + + + + + + + + + + + + + + + + «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) { @@ -316,16 +753,16 @@ class GeneratorImpl { } def CharSequence tree(Module module) ''' - «strong("module " + module.name)» - «module.childNodes.treeSet(InstanceIdentifier.builder.toInstance())» + «strong(module.name)» + «module.childNodes.treeSet(YangInstanceIdentifier.builder.build())» ''' - private def dispatch CharSequence tree(ChoiceNode node,InstanceIdentifier path) ''' + private def dispatch CharSequence tree(ChoiceNode node,YangInstanceIdentifier path) ''' «node.nodeName» (choice) «casesTree(node.cases,path)» ''' - def casesTree(Set nodes,InstanceIdentifier path) ''' + def casesTree(Set nodes,YangInstanceIdentifier path) '''
            «FOR node : nodes»
          • @@ -336,17 +773,17 @@ class GeneratorImpl {
          ''' - private def dispatch CharSequence tree(DataSchemaNode node,InstanceIdentifier path) ''' + private def dispatch CharSequence tree(DataSchemaNode node,YangInstanceIdentifier path) ''' «node.nodeName» ''' - private def dispatch CharSequence tree(ListSchemaNode node,InstanceIdentifier path) ''' + 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,InstanceIdentifier path) ''' + private def dispatch CharSequence tree(ContainerSchemaNode node,YangInstanceIdentifier path) ''' «val newPath = path.append(node)» «localLink(newPath,node.nodeName)» «node.childNodes.treeSet(newPath)» @@ -354,71 +791,218 @@ class GeneratorImpl { def CharSequence childNodes(Module module) ''' «val childNodes = module.childNodes» - «IF childNodes !== null && !childNodes.empty» + «IF !childNodes.nullOrEmpty»

          Child nodes

          - «childNodes.printChildren(3,InstanceIdentifier.builder().toInstance())» + «childNodes.printChildren(3,YangInstanceIdentifier.builder().build())» «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» + 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» +
          + ''' + } - «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 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(Set nodes, QName name,InstanceIdentifier path) ''' + def CharSequence xmlExample(Iterable nodes, QName name,YangInstanceIdentifier path) '''
               «xmlExampleTag(name,nodes.xmplExampleTags(path))»
           
      ''' - def CharSequence xmplExampleTags(Set nodes, InstanceIdentifier identifier) ''' + def CharSequence xmplExampleTags(Iterable nodes, YangInstanceIdentifier identifier) ''' «FOR node : nodes» @@ -427,29 +1011,29 @@ class GeneratorImpl { ''' - private def dispatch CharSequence asXmlExampleTag(LeafSchemaNode node, InstanceIdentifier identifier) ''' + private def dispatch CharSequence asXmlExampleTag(LeafSchemaNode node, YangInstanceIdentifier identifier) ''' «node.QName.xmlExampleTag("...")» ''' - private def dispatch CharSequence asXmlExampleTag(LeafListSchemaNode node, InstanceIdentifier identifier) ''' + 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, InstanceIdentifier identifier) ''' + 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, InstanceIdentifier identifier) ''' + 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, InstanceIdentifier identifier) ''' + private def dispatch CharSequence asXmlExampleTag(DataSchemaNode node, YangInstanceIdentifier identifier) ''' ''' @@ -461,19 +1045,19 @@ class GeneratorImpl { def header(int level,QName name) '''«name.localName»''' - def header(int level,InstanceIdentifier name) ''' - - «FOR cmp : name.path SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR» + def header(int level,YangInstanceIdentifier name) ''' + + «FOR cmp : name.pathArguments SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR» ''' - private def dispatch CharSequence printInfo(DataSchemaNode node, int level, InstanceIdentifier path) ''' + 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, InstanceIdentifier path) ''' + private def dispatch CharSequence printInfo(ContainerSchemaNode node, int level, YangInstanceIdentifier path) ''' «val newPath = path.append(node)» «header(level,newPath)»
      @@ -485,7 +1069,7 @@ class GeneratorImpl { «node.childNodes.printChildren(level,newPath)» ''' - private def dispatch CharSequence printInfo(ListSchemaNode node, int level, InstanceIdentifier path) ''' + private def dispatch CharSequence printInfo(ListSchemaNode node, int level, YangInstanceIdentifier path) ''' «val newPath = path.append(node)» «header(level,newPath)»
      @@ -497,89 +1081,114 @@ class GeneratorImpl { «node.childNodes.printChildren(level,newPath)» ''' - private def dispatch CharSequence printInfo(ChoiceNode node, int level, InstanceIdentifier path) ''' + 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, InstanceIdentifier path) ''' + private def dispatch CharSequence printInfo(ChoiceCaseNode node, int level, YangInstanceIdentifier path) ''' «node.childNodes.printChildren(level,path)» ''' - def CharSequence printShortInfo(ContainerSchemaNode node, int level, InstanceIdentifier path) { + def CharSequence printShortInfo(ContainerSchemaNode node, int level, YangInstanceIdentifier path) { val newPath = path.append(node); return ''' -
    • «strong(localLink(newPath,node.QName.localName))» (container)
    • +
    • «strong(localLink(newPath,node.QName.localName))» (container) +
        +
      • configuration data: «strong(String.valueOf(node.configuration))»
      • +
      +
    • ''' } - def CharSequence printShortInfo(ListSchemaNode node, int level, InstanceIdentifier path) { + def CharSequence printShortInfo(ListSchemaNode node, int level, YangInstanceIdentifier path) { val newPath = path.append(node); return ''' -
    • «strong(localLink(newPath,node.QName.localName))» (list)
    • +
    • «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(AnyXmlSchemaNode node, int level, InstanceIdentifier path) { + def CharSequence printShortInfo(LeafSchemaNode node, int level, YangInstanceIdentifier path) { return ''' -
    • «strong((node.QName.localName))» (anyxml)
    • +
    • «strong((node.QName.localName))» (leaf) +
        +
      • configuration data: «strong(String.valueOf(node.configuration))»
      • +
      • mandatory: «strong(String.valueOf(node.constraints.mandatory))»
      • +
      +
    • ''' } - def CharSequence printShortInfo(LeafSchemaNode node, int level, InstanceIdentifier path) { + def CharSequence printShortInfo(LeafListSchemaNode node, int level, YangInstanceIdentifier path) { return ''' -
    • «strong((node.QName.localName))» (leaf)
    • +
    • «strong((node.QName.localName))» (leaf-list) +
        +
      • configuration data: «strong(String.valueOf(node.configuration))»
      • +
      +
    • ''' } - def CharSequence printShortInfo(LeafListSchemaNode node, int level, InstanceIdentifier path) { + def CharSequence anchorLink(CharSequence anchor, CharSequence text) { return ''' -
    • «strong((node.QName.localName))» (leaf-list)
    • + «text» ''' } - def CharSequence localLink(InstanceIdentifier identifier, CharSequence text) ''' - «text» + def CharSequence localLink(YangInstanceIdentifier 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 YangInstanceIdentifier append(YangInstanceIdentifier identifier, ContainerSchemaNode node) { + return identifier.node(node.QName); } - private def dispatch InstanceIdentifier append(InstanceIdentifier identifier, ListSchemaNode node) { - val pathArguments = new ArrayList(identifier.path) + private def dispatch YangInstanceIdentifier append(YangInstanceIdentifier identifier, ListSchemaNode node) { val keyValues = new LinkedHashMap(); - if(node.keyDefinition != null) { + if(node.keyDefinition !== null) { for(definition : node.keyDefinition) { keyValues.put(definition,new Object); } } - pathArguments.add(new NodeIdentifierWithPredicates(node.QName,keyValues)); - return new InstanceIdentifier(pathArguments); + + return identifier.node(new NodeIdentifierWithPredicates(node.QName, keyValues)); } - def asXmlPath(InstanceIdentifier identifier) { + def asXmlPath(YangInstanceIdentifier identifier) { return ""; } - def asRestconfPath(InstanceIdentifier identifier) { + def asRestconfPath(YangInstanceIdentifier identifier) { val it = new StringBuilder(); append(currentModule.name) append(":") var previous = false; - for(arg : identifier.path) { + 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.keyValues.keySet) { + for(qname : nodeIdentifier.getKeyValues.keySet) { append("/{"); append(qname.localName) append("}") @@ -590,16 +1199,11 @@ class GeneratorImpl { 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 + 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("/") + pathString.append('/') } val QName qname = path.get(0) @@ -625,22 +1229,20 @@ 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) + 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); } - 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; @@ -667,7 +1269,7 @@ class GeneratorImpl { «ENDIF» ''' - private def CharSequence treeSet(Collection childNodes, InstanceIdentifier path) ''' + private def CharSequence treeSet(Collection childNodes, YangInstanceIdentifier path) ''' «IF childNodes !== null && !childNodes.empty»
        «FOR child : childNodes» @@ -683,18 +1285,6 @@ class GeneratorImpl { [«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» @@ -702,13 +1292,14 @@ class GeneratorImpl {
        ''' - private def dispatch CharSequence tree(Void obj, InstanceIdentifier path) ''' + private def dispatch CharSequence tree(Void obj, YangInstanceIdentifier path) ''' ''' /* #################### RESTRICTIONS #################### */ private def restrictions(TypeDefinition type) ''' + «type.baseType.toBaseStmt» «type.toLength» «type.toRange» ''' @@ -749,7 +1340,7 @@ class GeneratorImpl { def toLengthStmt(Collection lengths) ''' «IF lengths != null && !lengths.empty» - «listItem("Length restrictions")» + «listItem("Length restrictions:")»
          «FOR length : lengths»
        • @@ -766,7 +1357,7 @@ class GeneratorImpl { def toRangeStmt(Collection ranges) ''' «IF ranges != null && !ranges.empty» - «listItem("Range restrictions")» + «listItem("Range restrictions:")»
            «FOR range : ranges»
          • @@ -781,15 +1372,20 @@ class GeneratorImpl { «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»''' - private def pre(CharSequence str) '''
            «str»
            ''' def CharSequence descAndRefLi(SchemaNode node) ''' - «listItem(node.description)» + «listItem("Description", node.description)» «listItem("Reference", node.reference)» ''' @@ -832,7 +1428,7 @@ class GeneratorImpl { var i = 0; for (pathElement : path) { actual.add(pathElement) - val DataSchemaNode nodeByPath = childNodes.get(new SchemaPath(actual, absolute)) + 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) { @@ -887,7 +1483,7 @@ class GeneratorImpl { «node.QName.localName»«node.addedByInfo» «ENDIF» ''' - + private def dispatch nodeName(ContainerSchemaNode node) ''' «IF node.isAddedBy» «strong(italic(node.QName.localName))»«node.addedByInfo»