Bug 1232 - Add snippet of yang file into comments 44/9144/15
authorLadislav Borak <lborak@cisco.com>
Thu, 31 Jul 2014 22:59:32 +0000 (00:59 +0200)
committerMartin Vitez <mvitez@cisco.com>
Mon, 4 Aug 2014 11:46:52 +0000 (11:46 +0000)
- reworked all proposals from Tom Pantelis
- tested with toaster.yang, generated javadoc files added
  as attachment into bugzilla

Change-Id: I6a6c8a6f6592b1abf9368e9b8232263a029460a8
Signed-off-by: Ladislav Borak <lborak@cisco.com>
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.java
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/YangTemplate.xtend [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BaseTemplate.xtend
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BuilderTemplate.xtend

index 59ea3c53f3ce426324d06e92e924da5a3e4484d3..60120759fabeb7227c770cc9fd540f647306dc60 100644 (file)
@@ -30,7 +30,6 @@ import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findP
 import com.google.common.base.Splitter;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -39,7 +38,6 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
 import org.opendaylight.yangtools.binding.generator.util.BindingTypes;
 import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
@@ -139,6 +137,10 @@ public class BindingGeneratorImpl implements BindingGenerator {
      */
     private final static String AUGMENT_IDENTIFIER_NAME = "augment-identifier";
 
+    private final char NEW_LINE = '\n';
+
+    private final char TAB = '\t';
+
     /**
      * Resolves generated types from <code>context</code> schema nodes of all
      * modules.
@@ -284,6 +286,10 @@ public class BindingGeneratorImpl implements BindingGenerator {
         final String packageName = packageNameForGeneratedType(basePackageName, node.getPath());
         final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, node, childOf);
         genType.addComment(node.getDescription());
+        genType.setDescription(createDescription(node, genType.getFullyQualifiedName()));
+        genType.setModuleName(module.getName());
+        genType.setReference(node.getReference());
+        genType.setSchemaPath(node.getPath().getPathFromRoot());
         if (node instanceof DataNodeContainer) {
             genCtx.get(module).addChildNodeType(node, genType);
             groupingsToGenTypes(module, ((DataNodeContainer) node).getGroupings());
@@ -413,6 +419,8 @@ public class BindingGeneratorImpl implements BindingGenerator {
         addImplementedInterfaceFromUses(module, moduleDataTypeBuilder);
         moduleDataTypeBuilder.addImplementsType(DATA_ROOT);
         moduleDataTypeBuilder.addComment(module.getDescription());
+        moduleDataTypeBuilder.setDescription(createDescription(module));
+        moduleDataTypeBuilder.setReference(module.getReference());
         return moduleDataTypeBuilder;
     }
 
@@ -444,6 +452,8 @@ public class BindingGeneratorImpl implements BindingGenerator {
         final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
         final GeneratedTypeBuilder interfaceBuilder = moduleTypeBuilder(module, "Service");
         interfaceBuilder.addImplementsType(Types.typeForClass(RpcService.class));
+        interfaceBuilder.setDescription(createDescription(rpcDefinitions, module.getName(), module.getModuleSourcePath()));
+
         for (RpcDefinition rpc : rpcDefinitions) {
             if (rpc != null) {
                 final String rpcName = BindingMapping.getClassName(rpc.getQName());
@@ -513,6 +523,8 @@ public class BindingGeneratorImpl implements BindingGenerator {
         listenerInterface.addImplementsType(BindingTypes.NOTIFICATION_LISTENER);
         final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
 
+
+
         for (NotificationDefinition notification : notifications) {
             if (notification != null) {
                 processUsesAugments(notification, module);
@@ -531,6 +543,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 .setComment(notification.getDescription()).setReturnType(Types.VOID);
             }
         }
+        listenerInterface.setDescription(createDescription(notifications, module.getName(), module.getModuleSourcePath()));
 
         genCtx.get(module).addTopLevelNodeType(listenerInterface);
     }
@@ -601,9 +614,10 @@ public class BindingGeneratorImpl implements BindingGenerator {
         }
         newType.setAbstract(true);
         newType.addComment(identity.getDescription());
-        newType.setDescription(identity.getDescription());
+        newType.setDescription(createDescription(identity, newType.getFullyQualifiedName()));
         newType.setReference(identity.getReference());
         newType.setModuleName(module.getName());
+        SchemaPath path = identity.getPath();
         newType.setSchemaPath(identity.getPath().getPathFromRoot());
 
         final QName qname = identity.getQName();
@@ -722,7 +736,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         final String moduleName = BindingMapping.getClassName(module.getName()) + postfix;
 
         final GeneratedTypeBuilderImpl moduleBuilder = new GeneratedTypeBuilderImpl(packageName, moduleName);
-        moduleBuilder.setDescription(module.getDescription());
+        moduleBuilder.setDescription(createDescription(module));
         moduleBuilder.setReference(module.getReference());
         moduleBuilder.setModuleName(moduleName);
 
@@ -1665,13 +1679,12 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
         // FIXME: Validation of name conflict
         final GeneratedTypeBuilderImpl newType = new GeneratedTypeBuilderImpl(packageName, genTypeName);
+        final Module module = findParentModule(schemaContext, schemaNode);
         qnameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, schemaNode.getQName());
         newType.addComment(schemaNode.getDescription());
-        newType.setDescription(schemaNode.getDescription());
+        newType.setDescription(createDescription(schemaNode, newType.getFullyQualifiedName()));
         newType.setReference(schemaNode.getReference());
         newType.setSchemaPath(schemaNode.getPath().getPathFromRoot());
-
-        final Module module = findParentModule(schemaContext, schemaNode);
         newType.setModuleName(module.getName());
 
         if (!genTypeBuilders.containsKey(packageName)) {
@@ -1934,13 +1947,151 @@ public class BindingGeneratorImpl implements BindingGenerator {
                     throw new IllegalStateException("Grouping " + usesNode.getGroupingPath() + "is not resolved for "
                             + builder.getName());
                 }
+
                 builder.addImplementsType(genType);
-                builder.addComment(genType.getComment());
+                /*
+                builder.addComment(genType.getDescription());
+                builder.setDescription(genType.getDescription());
+                builder.setModuleName(genType.getModuleName());
+                builder.setReference(genType.getReference());
+                builder.setSchemaPath(genType.getSchemaPath());
+                */
             }
         }
         return builder;
     }
 
+    private boolean isNullOrEmpty(final Collection<?> list) {
+        return (list == null || list.isEmpty() ? true : false);
+    }
+
+    private String createDescription(final Set<? extends SchemaNode> schemaNodes, final String moduleName, final String moduleSourcePath) {
+        final StringBuilder sb = new StringBuilder();
+        final String yangSnipet = YangTemplate.generateYangSnipet(schemaNodes);
+
+        if (!isNullOrEmpty(schemaNodes)) {
+            final SchemaNode node = schemaNodes.iterator().next();
+
+            if (node instanceof RpcDefinition) {
+                sb.append("Interface for implementing the following YANG RPCs defined in module <b>" + moduleName + "</b>");
+            }
+            else if (node instanceof NotificationDefinition) {
+                sb.append("Interface for receiving the following YANG notifications defined in module <b>" + moduleName + "</b>");
+            }
+        }
+        sb.append(NEW_LINE);
+        sb.append("<br />(Source path: <i>");
+        sb.append(moduleSourcePath);
+        sb.append("</i>):");
+        sb.append(NEW_LINE);
+        sb.append("<pre>");
+        sb.append(NEW_LINE);
+        sb.append(yangSnipet);
+        sb.append("</pre>");
+        sb.append(NEW_LINE);
+
+        return sb.toString();
+    }
+
+    private String createDescription(final SchemaNode schemaNode, final String fullyQualifiedName) {
+        final StringBuilder sb = new StringBuilder();
+        final Module module = findParentModule(schemaContext, schemaNode);
+        final String yangSnipet = YangTemplate.generateYangSnipet(schemaNode);
+        final String formattedDescription = YangTemplate.formatToParagraph(schemaNode.getDescription(), 0);
+        final StringBuilder linkToBuilderClass = new StringBuilder();
+        final StringBuilder linkToKeyClass = new StringBuilder();
+        final Splitter splitter = Splitter.on("\\.");
+        final String[] namespace = Iterables.toArray(splitter.split(fullyQualifiedName), String.class);
+        String className = namespace[namespace.length - 1];
+
+        if (hasBuilderClass(schemaNode)) {
+            linkToBuilderClass.append(className);
+            linkToBuilderClass.append("Builder");
+
+            if (schemaNode instanceof ListSchemaNode) {
+                linkToKeyClass.append(className);
+                linkToKeyClass.append("Key");
+            }
+        }
+
+        if (!isNullOrEmpty(formattedDescription)) {
+            sb.append(formattedDescription);
+            sb.append(NEW_LINE);
+        }
+        sb.append("<p>");
+        sb.append("This class represents the following YANG schema fragment defined in module <b>");
+        sb.append(module.getName());
+        sb.append("</b>");
+        sb.append(NEW_LINE);
+        sb.append("<br />(Source path: <i>");
+        sb.append(module.getModuleSourcePath());
+        sb.append("</i>):");
+        sb.append(NEW_LINE);
+        sb.append("<pre>");
+        sb.append(NEW_LINE);
+        sb.append(yangSnipet);
+        sb.append("</pre>");
+        sb.append(NEW_LINE);
+        sb.append("The schema path to identify an instance is");
+        sb.append(NEW_LINE);
+        sb.append("<i>");
+        sb.append(YangTemplate.formatSchemaPath(module.getName(), schemaNode.getPath().getPathFromRoot()));
+        sb.append("</i>");
+        sb.append(NEW_LINE);
+
+        if (hasBuilderClass(schemaNode)) {
+            sb.append(NEW_LINE);
+            sb.append("<p>To create instances of this class use " + "{@link " + linkToBuilderClass + "}.");
+            sb.append(NEW_LINE);
+            sb.append("@see ");
+            sb.append(linkToBuilderClass);
+            if (schemaNode instanceof ListSchemaNode) {
+                sb.append("@see ");
+                sb.append(linkToKeyClass);
+            }
+            sb.append(NEW_LINE);
+        }
+
+        return sb.toString();
+    }
+
+    private boolean hasBuilderClass(final SchemaNode schemaNode) {
+        if (schemaNode instanceof ContainerSchemaNode || schemaNode instanceof ListSchemaNode ||
+                schemaNode instanceof RpcDefinition || schemaNode instanceof NotificationDefinition)
+            return true;
+        return false;
+    }
+
+    private boolean isNullOrEmpty(final String string) {
+        return (string == null || string.isEmpty() ? true : false);
+    }
+
+    private String createDescription(final Module module) {
+        final StringBuilder sb = new StringBuilder();
+        final String yangSnipet = YangTemplate.generateYangSnipet(module);
+        final String formattedDescription = YangTemplate.formatToParagraph(module.getDescription(), 0);
+
+        if (!isNullOrEmpty(formattedDescription)) {
+            sb.append(formattedDescription);
+            sb.append(NEW_LINE);
+        }
+        sb.append("<p>");
+        sb.append("This class represents the following YANG schema fragment defined in module <b>");
+        sb.append(module.getName());
+        sb.append("</b>");
+        sb.append(NEW_LINE);
+        sb.append("<br />Source path: <i>");
+        sb.append(module.getModuleSourcePath());
+        sb.append("</i>):");
+        sb.append(NEW_LINE);
+        sb.append("<pre>");
+        sb.append(NEW_LINE);
+        sb.append(yangSnipet);
+        sb.append("</pre>");
+
+        return sb.toString();
+    }
+
     private GeneratedTypeBuilder findChildNodeByPath(final SchemaPath path) {
         for (ModuleContext ctx : genCtx.values()) {
             GeneratedTypeBuilder result = ctx.getChildNode(path);
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/YangTemplate.xtend b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/YangTemplate.xtend
new file mode 100644 (file)
index 0000000..396001d
--- /dev/null
@@ -0,0 +1,808 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.sal.binding.generator.impl
+
+import java.text.SimpleDateFormat
+import java.util.Collection
+import java.util.Date
+import java.util.List
+import java.util.Map
+import java.util.Set
+import java.util.StringTokenizer
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema
+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.DataSchemaNode
+import org.opendaylight.yangtools.yang.model.api.Deviation
+import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition
+import org.opendaylight.yangtools.yang.model.api.FeatureDefinition
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition
+import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode
+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.ModuleImport
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition
+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.UnknownSchemaNode
+import org.opendaylight.yangtools.yang.model.api.UsesNode
+import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair
+
+class YangTemplate {
+
+    private static var Module module = null
+
+    def static String generateYangSnipet(SchemaNode schemaNode) {
+        if (schemaNode == null)
+            return ''
+
+        '''
+            «IF schemaNode instanceof DataSchemaNode»
+            «writeDataSchemaNode(schemaNode as DataSchemaNode)»
+            «ENDIF»
+            «IF schemaNode instanceof EnumTypeDefinition.EnumPair»
+            «writeEnumPair(schemaNode as EnumTypeDefinition.EnumPair)»
+            «ENDIF»
+            «IF schemaNode instanceof ExtensionDefinition»
+            «writeExtension(schemaNode as ExtensionDefinition)»
+            «ENDIF»
+            «IF schemaNode instanceof FeatureDefinition»
+            «writeFeature(schemaNode as FeatureDefinition)»
+            «ENDIF»
+            «IF schemaNode instanceof GroupingDefinition»
+            «writeGroupingDef(schemaNode as GroupingDefinition)»
+            «ENDIF»
+            «IF schemaNode instanceof IdentitySchemaNode»
+            «writeIdentity(schemaNode as IdentitySchemaNode)»
+            «ENDIF»
+            «IF schemaNode instanceof NotificationDefinition»
+            «writeNotification(schemaNode as NotificationDefinition)»
+            «ENDIF»
+            «IF schemaNode instanceof RpcDefinition»
+            «writeRPC(schemaNode as RpcDefinition)»
+            «ENDIF»
+            «IF schemaNode instanceof TypeDefinition<?>»
+            «writeTypeDefinition(schemaNode as TypeDefinition<?>)»
+            «ENDIF»
+            «IF schemaNode instanceof UnknownSchemaNode»
+            «writeUnknownSchemaNode(schemaNode as UnknownSchemaNode)»
+            «ENDIF»
+        '''
+    }
+    
+    def static String generateYangSnipet(Set<? extends SchemaNode> nodes) {
+        if (nodes.nullOrEmpty)
+            return ''
+        
+        '''
+            «FOR node : nodes»
+                «IF node instanceof NotificationDefinition»
+                «writeNotification(node as NotificationDefinition)»
+                «ELSEIF node instanceof RpcDefinition»
+                «writeRPC(node as RpcDefinition)»
+                «ENDIF»
+            «ENDFOR»
+        '''
+    }
+
+    def static writeEnumPair(EnumPair pair) {
+        var boolean hasEnumPairValue = pair.value != null
+        '''
+            enum «pair.name»«IF !hasEnumPairValue»;«ELSE»{
+                value «pair.value»;
+            }
+            «ENDIF»
+        '''
+    }
+
+    def static String writeModuleImports(Set<ModuleImport> moduleImports) {
+        if (moduleImports.nullOrEmpty)
+            return ''
+
+        '''
+            «FOR moduleImport : moduleImports SEPARATOR "\n"»
+                «IF moduleImport != null && !moduleImport.moduleName.nullOrEmpty»
+                import «moduleImport.moduleName» { prefix "«moduleImport.prefix»"; }
+                «ENDIF»
+            «ENDFOR»
+        '''
+    }
+
+    def static formatDate(Date moduleRevision) {
+        val SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-mm-dd")
+        return dateFormat.format(moduleRevision)
+    }
+
+    def static writeRevision(Date moduleRevision, String moduleDescription) {
+        val revisionIndent = 12
+
+        '''
+            revision «formatDate(moduleRevision)» {
+                description "«formatToParagraph(moduleDescription, revisionIndent)»";
+            }
+        '''
+    }
+
+    def static String generateYangSnipet(Module module) {
+
+        '''
+            module «module.name» {
+                yang-version «module.yangVersion»;
+                namespace "«module.QNameModule.namespace.toString»";
+                prefix "«module.prefix»";
+
+                «IF !module.imports.nullOrEmpty»
+                «writeModuleImports(module.imports)»
+                «ENDIF»
+                «IF module.revision != null»
+                «writeRevision(module.revision, module.description)»
+                «ENDIF»
+                «IF !module.childNodes.nullOrEmpty»
+
+                «writeDataSchemaNodes(module.childNodes)»
+                «ENDIF»
+                «IF !module.groupings.nullOrEmpty»
+
+                «writeGroupingDefs(module.groupings)»
+                «ENDIF»
+                «IF !module.augmentations.nullOrEmpty»
+
+                «writeAugments(module.augmentations)»
+                «ENDIF»
+                «IF !module.deviations.nullOrEmpty»
+
+                «writeDeviations(module.deviations)»
+                «ENDIF»
+                «IF !module.extensionSchemaNodes.nullOrEmpty»
+
+                «writeExtensions(module.extensionSchemaNodes)»
+                «ENDIF»
+                «IF !module.features.nullOrEmpty»
+
+                «writeFeatures(module.features)»
+                «ENDIF»
+                «IF !module.identities.nullOrEmpty»
+
+                «writeIdentities(module.identities)»
+                «ENDIF»
+                «IF !module.notifications.nullOrEmpty»
+
+                «writeNotifications(module.notifications)»
+                «ENDIF»
+                «IF !module.rpcs.nullOrEmpty»
+
+                «writeRPCs(module.rpcs)»
+                «ENDIF»
+                «IF !module.unknownSchemaNodes.nullOrEmpty»
+
+                «writeUnknownSchemaNodes(module.unknownSchemaNodes)»
+                «ENDIF»
+                «IF !module.uses.nullOrEmpty»
+
+                «writeUsesNodes(module.uses)»
+                «ENDIF»
+            }
+        '''
+    }
+
+    def static writeRPCs(Set<RpcDefinition> rpcDefs) {
+        '''
+            «FOR rpc : rpcDefs»
+                «IF rpc != null»
+                «writeRPC(rpc)»
+                «ENDIF»
+            «ENDFOR»
+        '''
+    }
+
+    def static writeRPC(RpcDefinition rpc) {
+        '''
+            rpc «rpc.QName.localName» {
+                «IF !rpc.description.nullOrEmpty»
+                    "«rpc.description»";
+                «ENDIF»
+                «IF !rpc.groupings.nullOrEmpty»
+                    «writeGroupingDefs(rpc.groupings)»
+                «ENDIF»
+                «IF rpc.input != null»
+                    «writeRpcInput(rpc.input)»
+                «ENDIF»
+                «IF rpc.output != null»
+                    «writeRpcOutput(rpc.output)»
+                «ENDIF»
+                «IF !rpc.reference.nullOrEmpty»
+                reference
+                    "«rpc.reference»";
+                «ENDIF»
+                «IF rpc.status != null»
+                status «rpc.status»;
+                «ENDIF»
+            }
+        '''
+    }
+
+    def static writeRpcInput(ContainerSchemaNode input) {
+        if(input == null)
+            return ''
+
+        '''
+            input {
+                «IF input instanceof DataSchemaNode && !input.childNodes.nullOrEmpty»
+                «writeDataSchemaNodes(input.childNodes)»
+                «ENDIF»
+            }
+
+        '''
+    }
+
+    def static writeRpcOutput(ContainerSchemaNode output) {
+        if(output == null)
+            return ''
+
+        '''
+            output {
+                «IF output instanceof DataSchemaNode && !output.childNodes.nullOrEmpty»
+                «writeDataSchemaNodes(output.childNodes)»
+                «ENDIF»
+            }
+        '''
+    }
+
+    def static writeNotifications(Set<NotificationDefinition> notifications) {
+        '''
+            «FOR notification : notifications»
+                «IF notification != null»
+                «writeNotification(notification)»
+                «ENDIF»
+            «ENDFOR»
+        '''
+    }
+
+    def static writeNotification(NotificationDefinition notification) {
+        '''
+            notification «notification.QName.localName» {
+                «IF !notification.description.nullOrEmpty»
+                description
+                    "«notification.description»";
+                «ENDIF»
+                «IF !notification.childNodes.nullOrEmpty»
+                    «writeDataSchemaNodes(notification.childNodes)»
+                «ENDIF»
+                «IF !notification.availableAugmentations.nullOrEmpty»
+                    «writeAugments(notification.availableAugmentations)»
+                «ENDIF»
+                «IF !notification.groupings.nullOrEmpty»
+                    «writeGroupingDefs(notification.groupings)»
+                «ENDIF»
+                «IF !notification.uses.nullOrEmpty»
+                    «writeUsesNodes(notification.uses)»
+                «ENDIF»
+                «IF !notification.reference.nullOrEmpty»
+                reference
+                    "«notification.reference»";
+                «ENDIF»
+                «IF notification.status != null»
+                status «notification.status»;
+                «ENDIF»
+            }
+        '''
+    }
+
+    def static writeUnknownSchemaNodes(List<UnknownSchemaNode> unknownSchemaNodes) {
+        if (unknownSchemaNodes.nullOrEmpty)
+            return ''
+
+        '''
+            «FOR unknownSchemaNode : unknownSchemaNodes»
+                «writeUnknownSchemaNode(unknownSchemaNode)»
+            «ENDFOR»
+        '''
+    }
+
+    def static writeUnknownSchemaNode(UnknownSchemaNode unknownSchemaNode) {
+        if (unknownSchemaNode == null)
+            return ''
+
+        '''
+            anyxml «unknownSchemaNode.QName.localName» {
+                «IF !unknownSchemaNode.description.nullOrEmpty»
+                description
+                    "«unknownSchemaNode.description»";
+                «ENDIF»
+                «IF !unknownSchemaNode.reference.nullOrEmpty»
+                reference
+                    "«unknownSchemaNode.reference»";
+                «ENDIF»
+                «IF unknownSchemaNode.status != null»
+                status «unknownSchemaNode.status»;
+                «ENDIF»
+            }
+        '''
+    }
+
+    def static writeUsesNodes(Set<UsesNode> usesNodes) {
+        if (usesNodes == null) {
+            return ''
+        }
+
+        '''
+            «FOR usesNode : usesNodes»
+                «IF usesNode != null»
+                «writeUsesNode(usesNode)»
+                «ENDIF»
+            «ENDFOR»
+        '''
+    }
+
+    def static writeUsesNode(UsesNode usesNode) {
+        val hasRefines = !usesNode.refines.empty
+
+        '''
+            uses «usesNode.groupingPath.pathFromRoot.head.localName»«IF !hasRefines»;«ELSE» {«ENDIF»
+            «IF hasRefines»
+                «writeRefines(usesNode.refines)»
+            }
+            «ENDIF»
+        '''
+    }
+
+    def static writeRefines(Map<SchemaPath, SchemaNode> refines) {
+        '''
+            «FOR path : refines.keySet»
+            «val schemaNode = refines.get(path)»
+            «writeRefine(path, schemaNode)»
+            «ENDFOR»
+        '''
+    }
+
+    def static writeRefine(SchemaPath path, SchemaNode schemaNode) {
+        '''
+            refine «path.pathFromRoot.last» {
+                «IF schemaNode instanceof DataSchemaNode»
+                «writeDataSchemaNode(schemaNode as DataSchemaNode)»
+                «ENDIF»
+            }
+        '''
+    }
+
+    def static writeTypeDefinitions(Set<TypeDefinition<?>> typeDefinitions) {
+        '''
+            «FOR typeDefinition : typeDefinitions»
+                «IF typeDefinition != null»
+                «writeTypeDefinition(typeDefinition)»
+                «ENDIF»
+            «ENDFOR»
+        '''
+    }
+
+    def static writeTypeDefinition(TypeDefinition<?> typeDefinition) {
+        '''
+            type «typeDefinition.QName.localName»;
+        '''
+    }
+
+    def static writeIdentities(Set<IdentitySchemaNode> identities) {
+        if (identities.nullOrEmpty)
+            return ''
+        '''
+            «FOR identity : identities»
+                «writeIdentity(identity)»
+            «ENDFOR»
+        '''
+    }
+
+    def static writeIdentity(IdentitySchemaNode identity) {
+        if (identity == null)
+            return ''
+        '''
+            identity «identity.QName.localName» {
+                «IF identity.baseIdentity != null»
+                base "«writeIdentityPrefix(identity.baseIdentity)»«identity.baseIdentity»";
+                «ENDIF»
+                «IF !identity.description.nullOrEmpty»
+                description
+                    "«identity.description»";
+                «ENDIF»
+                «IF !identity.reference.nullOrEmpty»
+                reference
+                    "«identity.reference»";
+                «ENDIF»
+                «IF identity.status != null»
+                status «identity.status»;
+                «ENDIF»
+            }
+        '''
+    }
+
+    def static writeIdentityPrefix(IdentitySchemaNode identity) {
+        if(module == null)
+            return ''
+
+        if(identity.QName.prefix.nullOrEmpty || module.prefix.nullOrEmpty)
+            return ''
+
+        val identityPrefix = identity.QName.prefix
+
+        if(!module.prefix.equals(identity.QName.prefix))
+            return identityPrefix + ":"
+        return ''
+    }
+
+    def static writeFeatures(Set<FeatureDefinition> features) {
+        '''
+            «FOR feature : features»
+                «IF feature != null»
+                «writeFeature(feature)»
+                «ENDIF»
+            «ENDFOR»
+        '''
+    }
+
+    def static writeFeature(FeatureDefinition featureDef) {
+        '''
+            feature «featureDef.QName.localName» {
+                «IF !featureDef.description.nullOrEmpty»
+                description
+                    "«featureDef.description»";
+                «ENDIF»
+                «IF !featureDef.reference.nullOrEmpty»
+                reference
+                    "«featureDef.reference»";
+                «ENDIF»
+                «IF featureDef.status != null»
+                status «featureDef.status»;
+                «ENDIF»
+            }
+        '''
+    }
+
+    def static writeExtensions(List<ExtensionDefinition> extensions) {
+        '''
+            «FOR anExtension : extensions»
+                «IF anExtension != null»
+                «writeExtension(anExtension)»
+                «ENDIF»
+            «ENDFOR»
+        '''
+    }
+
+    def static writeExtension(ExtensionDefinition extensionDef) {
+        '''
+            extension «extensionDef.QName.localName» {
+                «IF !extensionDef.description.nullOrEmpty»
+                description
+                    "«extensionDef.description»";
+                «ENDIF»
+                «IF !extensionDef.argument.nullOrEmpty»
+                argument "«extensionDef.argument»";
+                «ENDIF»
+                «IF !extensionDef.reference.nullOrEmpty»
+                reference
+                    "«extensionDef.reference»";
+                «ENDIF»
+                «IF extensionDef.status != null»
+                status «extensionDef.status»;
+                «ENDIF»
+            }
+        '''
+    }
+
+    def static writeDeviations(Set<Deviation> deviations) {
+        '''
+            «FOR deviation : deviations»
+                «IF deviation != null»
+                «writeDeviation(deviation)»
+                «ENDIF»
+            «ENDFOR»
+        '''
+    }
+
+    def static writeDeviation(Deviation deviation) {
+        '''
+            deviation «deviation.targetPath» {
+                «IF !deviation.reference.nullOrEmpty»
+                    reference
+                        "«deviation.reference»";
+                «ENDIF»
+                «IF deviation.deviate != null && !deviation.deviate.name.nullOrEmpty»
+                    deviation «deviation.deviate.name»;
+                «ENDIF»
+            }
+        '''
+    }
+
+    def static writeAugments(Set<AugmentationSchema> augments) {
+        '''
+            «FOR augment : augments»
+                «IF augment != null»
+                «writeAugment(augment)»
+                «ENDIF»
+            «ENDFOR»
+        '''
+    }
+
+    def static writeDataSchemaNodes(Collection<DataSchemaNode> dataSchemaNodes) {
+        '''
+            «FOR schemaNode : dataSchemaNodes»
+                «writeDataSchemaNode(schemaNode)»
+            «ENDFOR»
+        '''
+    }
+
+    def static CharSequence writeGroupingDefs(Set<GroupingDefinition> groupingDefs) {
+        '''
+            «FOR groupingDef : groupingDefs»
+                «IF groupingDef != null»
+                «writeGroupingDef(groupingDef)»
+                «ENDIF»
+            «ENDFOR»
+        '''
+    }
+
+    def static writeAugment(AugmentationSchema augment) {
+        '''
+            augment «formatToAugmentPath(augment.targetPath.pathFromRoot)» {
+                «IF augment.whenCondition != null && !augment.whenCondition.toString.nullOrEmpty»
+                when "«augment.whenCondition.toString»";
+                «ENDIF»
+                «IF !augment.description.nullOrEmpty»
+                description
+                    "«augment.description»";
+                «ENDIF»
+                «IF !augment.reference.nullOrEmpty»
+                reference
+                    "«augment.reference»";
+                «ENDIF»
+                «IF augment.status != null»
+                status «augment.status»;
+                «ENDIF»
+                «IF !augment.childNodes.nullOrEmpty»
+                «writeDataSchemaNodes(augment.childNodes)»
+                «ENDIF»
+                «IF !augment.uses.nullOrEmpty»
+                «writeUsesNodes(augment.uses)»
+                «ENDIF»
+            }
+        '''
+    }
+
+    def static writeGroupingDef(GroupingDefinition groupingDef) {
+        '''
+            grouping «groupingDef.QName.localName» {
+                «IF !groupingDef.groupings.nullOrEmpty»
+                    «writeGroupingDefs(groupingDef.groupings)»
+                «ENDIF»
+                «IF !groupingDef.childNodes.nullOrEmpty»
+                    «writeDataSchemaNodes(groupingDef.childNodes)»
+                «ENDIF»
+                «IF !groupingDef.unknownSchemaNodes.nullOrEmpty»
+                    «writeUnknownSchemaNodes(groupingDef.unknownSchemaNodes)»
+                «ENDIF»
+            }
+        '''
+    }
+
+    def static writeContSchemaNode(ContainerSchemaNode contSchemaNode) {
+        '''
+            container «contSchemaNode.getQName.localName» {
+                «IF !contSchemaNode.childNodes.nullOrEmpty»
+                «writeDataSchemaNodes(contSchemaNode.childNodes)»
+                «ENDIF»
+                «IF !contSchemaNode.availableAugmentations.nullOrEmpty»
+                «writeAugments(contSchemaNode.availableAugmentations)»
+                «ENDIF»
+                «IF !contSchemaNode.groupings.nullOrEmpty»
+                «writeGroupingDefs(contSchemaNode.groupings)»
+                «ENDIF»
+                «IF !contSchemaNode.uses.nullOrEmpty»
+                «writeUsesNodes(contSchemaNode.uses)»
+                «ENDIF»
+                «IF !contSchemaNode.unknownSchemaNodes.nullOrEmpty»
+                «writeUnknownSchemaNodes(contSchemaNode.unknownSchemaNodes)»
+                «ENDIF»
+            }
+        '''
+    }
+
+    def static writeAnyXmlSchemaNode(AnyXmlSchemaNode anyXmlSchemaNode) {
+        '''
+            anyxml «anyXmlSchemaNode.getQName.localName»;
+        '''
+    }
+
+    def static writeLeafSchemaNode(LeafSchemaNode leafSchemaNode) {
+        '''
+            leaf «leafSchemaNode.getQName.localName» {
+                type «leafSchemaNode.type.getQName.localName»;
+            }
+        '''
+    }
+
+    def static writeLeafListSchemaNode(LeafListSchemaNode leafListSchemaNode) {
+        '''
+            leaf-list «leafListSchemaNode.getQName.localName» {
+                type «leafListSchemaNode.type.getQName.localName»;
+            }
+        '''
+    }
+
+    def static writeChoiceCaseNode(ChoiceCaseNode choiceCaseNode) {
+        '''
+            case «choiceCaseNode.getQName.localName» {
+                «FOR childNode : choiceCaseNode.childNodes»
+                    «writeDataSchemaNode(childNode)»
+                «ENDFOR»
+            }
+        '''
+    }
+
+    def static writeChoiceNode(ChoiceNode choiceNode) {
+        '''
+            choice «choiceNode.getQName.localName» {
+                «FOR child : choiceNode.cases»
+                    «writeDataSchemaNode(child)»
+                «ENDFOR»
+            }
+        '''
+    }
+
+    def static writeListSchemaNode(ListSchemaNode listSchemaNode) {
+        '''
+            list «listSchemaNode.getQName.localName» {
+                key «FOR listKey : listSchemaNode.keyDefinition SEPARATOR " "»"«listKey.localName»"
+                «ENDFOR»
+                «IF !listSchemaNode.childNodes.nullOrEmpty»
+                    «writeDataSchemaNodes(listSchemaNode.childNodes)»
+                «ENDIF»
+                «IF !listSchemaNode.availableAugmentations.nullOrEmpty»
+                    «writeAugments(listSchemaNode.availableAugmentations)»
+                «ENDIF»
+                «IF !listSchemaNode.groupings.nullOrEmpty»
+                    «writeGroupingDefs(listSchemaNode.groupings)»
+                «ENDIF»
+                «IF !listSchemaNode.uses.nullOrEmpty»
+                    «writeUsesNodes(listSchemaNode.uses)»
+                «ENDIF»
+                «IF !listSchemaNode.unknownSchemaNodes.nullOrEmpty»
+                    «writeUnknownSchemaNodes(listSchemaNode.unknownSchemaNodes)»
+                «ENDIF»
+            }
+        '''
+    }
+
+    def static CharSequence writeDataSchemaNode(DataSchemaNode child) {
+        '''
+            «IF child instanceof ContainerSchemaNode»
+                «writeContSchemaNode(child as ContainerSchemaNode)»
+            «ENDIF»
+            «IF child instanceof AnyXmlSchemaNode»
+                «writeAnyXmlSchemaNode(child as AnyXmlSchemaNode)»
+            «ENDIF»
+            «IF child instanceof LeafSchemaNode»
+                «writeLeafSchemaNode(child as LeafSchemaNode)»
+            «ENDIF»
+            «IF child instanceof LeafListSchemaNode»
+                «writeLeafListSchemaNode(child as LeafListSchemaNode)»
+            «ENDIF»
+            «IF child instanceof ChoiceCaseNode»
+                «writeChoiceCaseNode(child as ChoiceCaseNode)»
+            «ENDIF»
+            «IF child instanceof ChoiceNode»
+                «writeChoiceNode(child as ChoiceNode)»
+            «ENDIF»
+            «IF child instanceof ListSchemaNode»
+                «writeListSchemaNode(child as ListSchemaNode)»
+            «ENDIF»
+        '''
+    }
+    
+    static def String formatSchemaPath(String moduleName, Iterable<QName> schemaPath) {
+        var currentElement = schemaPath.head
+        val StringBuilder sb = new StringBuilder()
+        sb.append(moduleName)
+
+        for(pathElement : schemaPath) {
+            if(!currentElement.namespace.equals(pathElement.namespace)) {
+                currentElement = pathElement
+                sb.append('/')
+                sb.append(pathElement)
+            }
+            else {
+                sb.append('/')
+                sb.append(pathElement.localName)
+            }
+        }
+        return sb.toString
+    }
+
+    static def String formatToParagraph(String text, int nextLineIndent) {
+        if (text == null || text.isEmpty())
+            return '';
+
+        var String formattedText = text;
+        val StringBuilder sb = new StringBuilder();
+        val StringBuilder lineBuilder = new StringBuilder();
+        var boolean isFirstElementOnNewLineEmptyChar = false;
+        val lineIndent = computeNextLineIndent(nextLineIndent);
+
+        formattedText = formattedText.replace("*/", "&#42;&#47;");
+        formattedText = formattedText.replace("\n", "");
+        formattedText = formattedText.replace("\t", "");
+        formattedText = formattedText.replaceAll(" +", " ");
+
+        val StringTokenizer tokenizer = new StringTokenizer(formattedText, " ", true);
+
+        while (tokenizer.hasMoreElements()) {
+            val String nextElement = tokenizer.nextElement().toString();
+
+            if (lineBuilder.length() + nextElement.length() > 80) {
+                if (lineBuilder.charAt(lineBuilder.length() - 1) == ' ') {
+                    lineBuilder.setLength(0);
+                    lineBuilder.append(lineBuilder.substring(0, lineBuilder.length() - 1));
+                }
+                if (lineBuilder.charAt(0) == ' ') {
+                    lineBuilder.setLength(0);
+                    lineBuilder.append(lineBuilder.substring(1));
+                }
+
+                sb.append(lineBuilder);
+                lineBuilder.setLength(0);
+                sb.append("\n");
+
+                if (nextLineIndent > 0) {
+                    sb.append(lineIndent)
+                }
+
+                if (nextElement.toString().equals(" "))
+                    isFirstElementOnNewLineEmptyChar = !isFirstElementOnNewLineEmptyChar;
+            }
+            if (isFirstElementOnNewLineEmptyChar) {
+                isFirstElementOnNewLineEmptyChar = !isFirstElementOnNewLineEmptyChar;
+            } else {
+                lineBuilder.append(nextElement);
+            }
+        }
+        sb.append(lineBuilder);
+        sb.append("\n");
+
+        return sb.toString();
+    }
+
+    def private static formatToAugmentPath(Iterable<QName> schemaPath) {
+        val StringBuilder sb = new StringBuilder();
+
+        for(pathElement : schemaPath) {
+            val prefix = pathElement.prefix
+            val localName = pathElement.localName
+
+            sb.append("\\")
+            sb.append(prefix)
+            sb.append(":")
+            sb.append(localName)
+        }
+        return sb.toString
+    }
+
+    private static def computeNextLineIndent(int nextLineIndent) {
+        val StringBuilder sb = new StringBuilder()
+        var i = 0
+        while (i < nextLineIndent) {
+            sb.append(' ')
+            i = i + 1
+        }
+        return sb.toString
+    }
+}
index eb7b948c545283c6e7e3d162a202574365eb0723..152d60e6de6b5f933addf4714e41f4da702dbae7 100644 (file)
@@ -190,70 +190,15 @@ abstract class BaseTemplate {
     }
 
     def protected String formatDataForJavaDoc(GeneratedType type) {
-        val typeDescription = type.description
-        val typeReference = type.reference
-        val typeModuleName = type.moduleName
-        val typeSchemaPath = type.schemaPath
+        val typeDescription = type.getDescription();
 
         return '''
-            «IF !type.isDocumentationParametersNullOrEmtpy»
-               «IF typeDescription != null && !typeDescription.empty»
-                «formatToParagraph(typeDescription)»
-               «ENDIF»
-               «IF typeReference != null && !typeReference.empty»
-                Reference:
-                    «formatReference(typeReference)»
-               «ENDIF»
-               «IF typeModuleName != null && !typeModuleName.empty»
-                Module name:
-                    «typeModuleName»
-               «ENDIF»
-               «IF typeSchemaPath != null && !typeSchemaPath.empty»
-                Schema path:
-                    «formatPath(typeSchemaPath)»
-               «ENDIF»
+            «IF !typeDescription.nullOrEmpty»
+            «typeDescription»
             «ENDIF»
         '''.toString
     }
 
-    def formatPath(Iterable<QName> schemaPath) {
-        var currentElement = schemaPath.head
-        val StringBuilder sb = new StringBuilder()
-        sb.append('[')
-        sb.append(currentElement)
-
-        for(pathElement : schemaPath) {
-            if(!currentElement.namespace.equals(pathElement.namespace)) {
-                currentElement = pathElement
-                sb.append('/')
-                sb.append(pathElement)
-            }
-            else {
-                sb.append('/')
-                sb.append(pathElement.localName)
-            }
-        }
-        sb.append(']')
-        return sb.toString
-    }
-
-    def formatReference(String reference) {
-        if(reference == null || reference.isEmpty)
-            return reference
-
-        val StringTokenizer tokenizer = new StringTokenizer(reference, " ", true)
-        val StringBuilder sb = new StringBuilder();
-
-        while(tokenizer.hasMoreTokens) {
-            var String oneElement = tokenizer.nextToken
-            if (oneElement.contains("http://")) {
-                oneElement = asLink(oneElement)
-            }
-            sb.append(oneElement)
-        }
-        return sb.toString
-    }
-
     def asLink(String text) {
         val StringBuilder sb = new StringBuilder()
         var tempText = text
@@ -329,29 +274,16 @@ abstract class BaseTemplate {
     }
 
     def isDocumentationParametersNullOrEmtpy(GeneratedType type) {
-        var boolean isNullOrEmpty = true
-        val String typeDescription = type.description
-        val String typeReference = type.reference
-        val String typeModuleName = type.moduleName
-        val Iterable<QName> typeSchemaPath = type.schemaPath
-
-        if(typeDescription != null && !typeDescription.empty) {
-            isNullOrEmpty = false
-            return isNullOrEmpty
-        }
-        if(typeReference != null && !typeReference.empty) {
-            isNullOrEmpty = false
-            return isNullOrEmpty
-        }
-        if(typeModuleName != null && !typeModuleName.empty) {
-            isNullOrEmpty = false
-            return isNullOrEmpty
-        }
-        if(typeSchemaPath != null && !typeSchemaPath.empty) {
-            isNullOrEmpty = false
-            return isNullOrEmpty
+        val boolean isTypeDescriptionNullOrEmpty = type.description.nullOrEmpty
+        val boolean isTypeReferenceNullOrEmpty = type.reference.nullOrEmpty
+        val boolean isTypeModuleNameNullOrEmpty = type.moduleName.nullOrEmpty
+        val boolean isTypeSchemaPathNullOrEmpty = type.schemaPath.nullOrEmpty
+
+        if (isTypeDescriptionNullOrEmpty && isTypeReferenceNullOrEmpty && isTypeModuleNameNullOrEmpty
+            && isTypeSchemaPathNullOrEmpty) {
+            return true
         }
-        return isNullOrEmpty
+        return false
     }
 
     def generateRestrictions(Type type, String paramName, Type returnType) '''
index d73b71e93aaf601b3f8c7e3143a806490611de82..d818c11d3d04e17cad071320888dbd7846dfdfb1 100644 (file)
@@ -736,6 +736,23 @@ class BuilderTemplate extends BaseTemplate {
         return «type.importedName».class;
     }
     '''
+    
+    private def createDescription(GeneratedType type) {
+        return '''
+        Class that builds {@link «type.importedName»} instances.
+        
+        @see «type.importedName»
+    '''
+    }
+    
+    override def protected String formatDataForJavaDoc(GeneratedType type) {
+        val typeDescription = createDescription(type)
 
+        return '''
+            «IF !typeDescription.nullOrEmpty»
+            «typeDescription»
+            «ENDIF»
+        '''.toString
+    }
 }