import java.util.Set;
import java.util.function.Function;
import org.apache.maven.project.MavenProject;
-import org.opendaylight.mdsal.binding.generator.api.BindingGenerator;
import org.opendaylight.mdsal.binding.generator.impl.BindingGeneratorImpl;
import org.opendaylight.mdsal.binding.java.api.generator.GeneratorJavaFile;
import org.opendaylight.mdsal.binding.java.api.generator.YangModuleInfoTemplate;
-import org.opendaylight.mdsal.binding.java.api.generator.YangTemplate;
import org.opendaylight.mdsal.binding.model.api.Type;
import org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil;
import org.opendaylight.yangtools.yang.binding.BindingMapping;
outputBaseDir = outputDir == null ? getDefaultOutputBaseDir() : outputDir;
- final BindingGenerator bindingGenerator = new BindingGeneratorImpl(YangTemplate.getInstance());
- final List<Type> types = bindingGenerator.generateTypes(context, yangModules);
+ final List<Type> types = new BindingGeneratorImpl().generateTypes(context, yangModules);
final GeneratorJavaFile generator = new GeneratorJavaFile(buildContext, types);
File persistentSourcesDir = null;
+++ /dev/null
-/*
- * Copyright (c) 2018 Pantheon Technologies, s.r.o. 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.mdsal.binding.generator.spi;
-
-import com.google.common.annotations.Beta;
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-
-/**
- * SPI interface for plugging YANG snippet generation into a BindingGenerator.
- */
-@Beta
-@NonNullByDefault
-public interface YangTextSnippetProvider {
- /**
- * Generate a YANG snippet for specified SchemaNode.
- *
- * @param schemaNode SchemaNode for which to generate a snippet
- * @return YANG snippet
- */
- String generateYangSnippet(SchemaNode schemaNode);
-
- /**
- * Generate a YANG snippet for specified Module.
- *
- * @param module Module for which to generate a snippet
- * @return YANG snippet
- */
- String generateYangSnippet(Module module);
-}
String getValue();
/**
- * Returns <code>true</code> if the property si declared as read-only. <br>
+ * Returns <code>true</code> if the property is declared as read-only. <br>
* If the property has flag <code>isReadOnly == true</code> the property
* SHOULD be generated as getter only.
*
- * @return <code>true</code> if the property si declared as read-only.
+ * @return <code>true</code> if the property is declared as read-only.
*/
boolean isReadOnly();
}
package org.opendaylight.mdsal.binding.model.api;
import java.util.List;
+import java.util.Optional;
/**
* Every Java interface has to be specified with:
*
* @return comment string associated with Generated Type.
*/
- String getComment();
+ TypeComment getComment();
/**
* Returns List of annotation definitions associated with generated type.
*/
List<GeneratedProperty> getProperties();
+ /**
+ * Returns the YANG definition of this type, if available.
+ *
+ * @return YANG source definition, or empty when unavailable.
+ */
+ Optional<YangSourceDefinition> getYangSourceDefinition();
}
--- /dev/null
+/*
+ * Copyright (c) 2018 Pantheon Technologies, s.r.o. 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.mdsal.binding.model.api;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * Dedicated type for holding a class comment. It exposes a javadoc-encoded string.
+ *
+ * @author Robert Varga
+ */
+@Beta
+@FunctionalInterface
+@NonNullByDefault
+public interface TypeComment {
+
+ /**
+ * Return a javadoc snippet. This snippet is guaranteed to be safe for direct inclusion in a Java block comment.
+ *
+ * @return Javadoc snippet.
+ */
+ String getJavadoc();
+}
--- /dev/null
+/*
+ * Copyright (c) 2018 Pantheon Technologies, s.r.o. 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.mdsal.binding.model.api;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
+import java.util.Collection;
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yangtools.yang.model.api.DocumentedNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+
+/**
+ * DTO capturing the YANG source definition which lead to a {@link GeneratedType} being emitted.
+ *
+ * @author Robert Varga
+ */
+@Beta
+@NonNullByDefault
+public abstract class YangSourceDefinition {
+ public static final class Multiple extends YangSourceDefinition {
+ private final List<? extends SchemaNode> nodes;
+
+ Multiple(final Module module, final Collection<? extends SchemaNode> nodes) {
+ super(module);
+ this.nodes = ImmutableList.copyOf(nodes);
+ }
+
+ /**
+ * Return the defining SchemaNodes.
+ *
+ * @return defining SchemaNodes, guaranteed to be non-empty
+ */
+ public List<? extends SchemaNode> getNodes() {
+ return nodes;
+ }
+ }
+
+ public static final class Single extends YangSourceDefinition {
+ private final DocumentedNode node;
+
+ Single(final Module module, final DocumentedNode node) {
+ super(module);
+ this.node = requireNonNull(node);
+ }
+
+ public DocumentedNode getNode() {
+ return node;
+ }
+ }
+
+ private final Module module;
+
+ private YangSourceDefinition(final Module module) {
+ this.module = requireNonNull(module);
+ }
+
+ public static YangSourceDefinition of(final Module module) {
+ return new Single(module, module);
+ }
+
+ public static YangSourceDefinition of(final Module module, final SchemaNode node) {
+ return new Single(module, node);
+ }
+
+ public static YangSourceDefinition of(final Module module, final Collection<? extends SchemaNode> nodes) {
+ checkArgument(!nodes.isEmpty());
+ return new Multiple(module, nodes);
+ }
+
+ /**
+ * Return the defining YANG module.
+ *
+ * @return Defining YANG module.
+ */
+ public final Module getModule() {
+ return module;
+ }
+}
package org.opendaylight.mdsal.binding.model.api.type.builder;
import java.util.List;
+import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.binding.model.api.Constant;
import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.model.api.TypeComment;
+import org.opendaylight.mdsal.binding.model.api.YangSourceDefinition;
import org.opendaylight.yangtools.yang.common.QName;
public interface GeneratedTypeBuilderBase<T extends GeneratedTypeBuilderBase<T>> extends Type {
/**
* Adds String definition of comment into Method Signature definition. <br>
- * The comment String MUST NOT contain anny comment specific chars (i.e.
+ * The comment String MUST NOT contain any comment specific chars (i.e.
* "/**" or "//") just plain String text description.
*
* @param comment
* Comment String.
*/
- T addComment(String comment);
+ T addComment(TypeComment comment);
/**
* The method creates new AnnotationTypeBuilder containing specified package
List<GeneratedPropertyBuilder> getProperties();
+ /**
+ * Returns the YANG definition of this type, if available.
+ *
+ * @return YANG source definition, or empty when unavailable.
+ */
+ Optional<YangSourceDefinition> getYangSourceDefinition();
+
/**
* Add new Generated Property definition for Generated Transfer Object
* Builder and returns Generated Property Builder for specifying Property. <br>
*/
void setReference(String reference);
+ /**
+ * Set the YANG source definition.
+ *
+ * @param definition YANG source definition, must not be null
+ */
+ void setYangSourceDefinition(@NonNull YangSourceDefinition definition);
}
/**
* Adds String definition of comment into Method Signature definition. <br>
- * The comment String MUST NOT contain anny comment specific chars (i.e.
+ * The comment String MUST NOT contain any comment specific chars (i.e.
* "/**" or "//") just plain String text description.
*
* @param comment
import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findNodeInSchemaContext;
import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
-import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
-import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
-import java.util.regex.Pattern;
import org.opendaylight.mdsal.binding.generator.api.BindingGenerator;
import org.opendaylight.mdsal.binding.generator.spi.TypeProvider;
-import org.opendaylight.mdsal.binding.generator.spi.YangTextSnippetProvider;
import org.opendaylight.mdsal.binding.model.api.AccessModifier;
import org.opendaylight.mdsal.binding.model.api.Constant;
import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
import org.opendaylight.mdsal.binding.model.api.ParameterizedType;
import org.opendaylight.mdsal.binding.model.api.Restrictions;
import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.model.api.YangSourceDefinition;
import org.opendaylight.mdsal.binding.model.api.type.builder.AnnotationTypeBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.EnumBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedPropertyBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.MethodSignatureBuilder;
import org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil;
import org.opendaylight.mdsal.binding.model.util.BindingTypes;
-import org.opendaylight.mdsal.binding.model.util.FormattingUtils;
import org.opendaylight.mdsal.binding.model.util.ReferencedTypeImpl;
+import org.opendaylight.mdsal.binding.model.util.TypeComments;
import org.opendaylight.mdsal.binding.model.util.Types;
import org.opendaylight.mdsal.binding.model.util.generated.type.builder.GeneratedPropertyBuilderImpl;
import org.opendaylight.mdsal.binding.model.util.generated.type.builder.GeneratedTOBuilderImpl;
public class BindingGeneratorImpl implements BindingGenerator {
private static final Logger LOG = LoggerFactory.getLogger(BindingGeneratorImpl.class);
private static final Splitter COLON_SPLITTER = Splitter.on(':');
- private static final Splitter BSDOT_SPLITTER = Splitter.on("\\.");
- private static final char NEW_LINE = '\n';
/**
* Comparator based on augment target path.
*/
private static final String YANG_EXT_NAMESPACE = "urn:opendaylight:yang:extension:yang-ext";
- private static final Pattern UNICODE_CHAR_PATTERN = Pattern.compile("\\\\+u");
-
private final Map<Module, ModuleContext> genCtx = new HashMap<>();
-
- /**
- * When set to non-null, generated classes will include javadoc comments which are useful for users, generated
- * using specified generator.
- */
- private final VerboseCommentGenerator verboseCommentGenerator;
+ private final boolean fullTypes;
/**
* Outer key represents the package name. Outer value represents map of all
*/
private SchemaContext schemaContext;
- /**
- * Create a new binding generator, which does not generate verbose class comments.
- */
public BindingGeneratorImpl() {
- verboseCommentGenerator = null;
+ this(false);
}
- /**
- * Create a new binding generator.
- *
- * @param snippetProvider generate verbose comments using this generator
- */
- public BindingGeneratorImpl(final YangTextSnippetProvider snippetProvider) {
- this.verboseCommentGenerator = new VerboseCommentGenerator(snippetProvider);
+ public BindingGeneratorImpl(final boolean skinnyTypes) {
+ this.fullTypes = !skinnyTypes;
}
/**
}
final String packageName = packageNameForGeneratedType(basePackageName, node.getPath());
final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, node, childOf, module);
- genType.addComment(node.getDescription().orElse(null));
annotateDeprecatedIfNecessary(node.getStatus(), genType);
- genType.setDescription(createDescription(node, genType.getFullyQualifiedName()));
+
genType.setModuleName(module.getName());
- genType.setReference(node.getReference().orElse(null));
+
+ if (fullTypes) {
+ genType.setYangSourceDefinition(YangSourceDefinition.of(module, node));
+ TypeComments.description(node).ifPresent(genType::addComment);
+ node.getDescription().ifPresent(genType::setDescription);
+ node.getReference().ifPresent(genType::setReference);
+ }
genType.setSchemaPath(node.getPath().getPathFromRoot());
if (node instanceof DataNodeContainer) {
genCtx.get(module).addChildNodeType(node, genType);
final GeneratedTypeBuilder moduleDataTypeBuilder = moduleTypeBuilder(module, "Data");
addImplementedInterfaceFromUses(module, moduleDataTypeBuilder);
moduleDataTypeBuilder.addImplementsType(DATA_ROOT);
- moduleDataTypeBuilder.addComment(module.getDescription().orElse(null));
- moduleDataTypeBuilder.setDescription(createDescription(module));
- moduleDataTypeBuilder.setReference(module.getReference().orElse(null));
+
+ if (fullTypes) {
+ moduleDataTypeBuilder.setYangSourceDefinition(YangSourceDefinition.of(module));
+ TypeComments.description(module).ifPresent(moduleDataTypeBuilder::addComment);
+ module.getDescription().ifPresent(moduleDataTypeBuilder::setDescription);
+ module.getReference().ifPresent(moduleDataTypeBuilder::setReference);
+ }
return moduleDataTypeBuilder;
}
/**
- * Converts all <b>rpcs</b> inputs and outputs substatements of the module
+ * Converts all <b>RPCs</b> input and output substatements of the module
* to the list of <code>Type</code> objects. In addition are to containers
* and lists which belong to input or output also part of returning list.
*
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()));
+
+ if (fullTypes) {
+ interfaceBuilder.addComment(TypeComments.javadoc(
+ "Interface for implementing the following YANG RPCs defined in module <b>" + module.getName() + "</b>")
+ .get());
+ interfaceBuilder.setYangSourceDefinition(YangSourceDefinition.of(module, rpcDefinitions));
+ }
for (final RpcDefinition rpc : rpcDefinitions) {
if (rpc != null) {
listenerInterface.addImplementsType(BindingTypes.NOTIFICATION_LISTENER);
final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
-
-
for (final NotificationDefinition notification : notifications) {
if (notification != null) {
processUsesAugments(notification, module);
.setComment(encodeAngleBrackets(notification.getDescription().orElse(null))).setReturnType(Types.VOID);
}
}
- listenerInterface.setDescription(createDescription(notifications, module.getName()));
+
+ if (fullTypes) {
+ listenerInterface.setYangSourceDefinition(YangSourceDefinition.of(module, notifications));
+ listenerInterface.addComment(TypeComments.javadoc(
+ "Interface for receiving the following YANG notifications defined in module <b>" + module.getName()
+ + "</b>").get());
+ }
genCtx.get(module).addTopLevelNodeType(listenerInterface);
}
newType.setExtendsType(gto);
}
newType.setAbstract(true);
- newType.addComment(identity.getDescription().orElse(null));
- newType.setDescription(createDescription(identity, newType.getFullyQualifiedName()));
- newType.setReference(identity.getReference().orElse(null));
+
+ if (fullTypes) {
+ newType.setYangSourceDefinition(YangSourceDefinition.of(module, identity));
+ TypeComments.description(identity).ifPresent(newType::addComment);
+ identity.getDescription().ifPresent(newType::setDescription);
+ identity.getReference().ifPresent(newType::setReference);
+ }
newType.setModuleName(module.getName());
newType.setSchemaPath(identity.getPath().getPathFromRoot());
final String moduleName = BindingMapping.getClassName(module.getName()) + postfix;
final GeneratedTypeBuilderImpl moduleBuilder = new GeneratedTypeBuilderImpl(packageName, moduleName);
- moduleBuilder.setDescription(createDescription(module));
- moduleBuilder.setReference(module.getReference().orElse(null));
+
moduleBuilder.setModuleName(moduleName);
+ if (fullTypes) {
+ moduleBuilder.setYangSourceDefinition(YangSourceDefinition.of(module));
+ TypeComments.description(module).ifPresent(moduleBuilder::addComment);
+ module.getDescription().ifPresent(moduleBuilder::setDescription);
+ module.getReference().ifPresent(moduleBuilder::setReference);
+ }
return moduleBuilder;
}
final GeneratedTypeBuilder typeBuilder, final Module parentModule) {
final GeneratedTOBuilderImpl returnType = new GeneratedTOBuilderImpl(genTOBuilder.getPackageName(),
genTOBuilder.getName());
- final String typedefDescription = encodeAngleBrackets(typeDef.getDescription().orElse(null));
- returnType.setDescription(typedefDescription);
- returnType.setReference(typeDef.getReference().orElse(null));
+ if (fullTypes) {
+ returnType.setYangSourceDefinition(YangSourceDefinition.of(parentModule, typeDef));
+ TypeComments.description(typeDef).ifPresent(returnType::addComment);
+ typeDef.getDescription().ifPresent(returnType::setDescription);
+ typeDef.getReference().ifPresent(returnType::setReference);
+ }
returnType.setSchemaPath(typeDef.getPath().getPathFromRoot());
returnType.setModuleName(parentModule.getName());
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().orElse(null));
- newType.setDescription(createDescription(schemaNode, newType.getFullyQualifiedName()));
- newType.setReference(schemaNode.getReference().orElse(null));
+
+ if (fullTypes) {
+ newType.setYangSourceDefinition(YangSourceDefinition.of(module, schemaNode));
+ TypeComments.description(schemaNode).ifPresent(newType::addComment);
+ schemaNode.getDescription().ifPresent(newType::setDescription);
+ schemaNode.getReference().ifPresent(newType::setReference);
+ }
newType.setSchemaPath(schemaNode.getPath().getPathFromRoot());
newType.setModuleName(module.getName());
return builder;
}
- private static boolean isNullOrEmpty(final Collection<?> list) {
- return list == null || list.isEmpty();
- }
-
- private String createDescription(final Set<? extends SchemaNode> schemaNodes, final String moduleName) {
- final StringBuilder sb = new StringBuilder();
-
- 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);
-
- if (verboseCommentGenerator != null) {
- verboseCommentGenerator.appendYangSnippet(sb, schemaNodes);
- }
-
- return replaceAllIllegalChars(sb);
- }
-
- private String createDescription(final SchemaNode schemaNode, final String fullyQualifiedName) {
- final StringBuilder sb = new StringBuilder();
- final String nodeDescription = encodeAngleBrackets(schemaNode.getDescription().orElse(null));
- final String formattedDescription = FormattingUtils.formatToParagraph(nodeDescription, 0);
-
- if (!Strings.isNullOrEmpty(formattedDescription)) {
- sb.append(formattedDescription);
- sb.append(NEW_LINE);
- }
-
- if (verboseCommentGenerator != null) {
- final Module module = findParentModule(schemaContext, schemaNode);
- final String[] namespace = Iterables.toArray(BSDOT_SPLITTER.split(fullyQualifiedName), String.class);
-
- verboseCommentGenerator.appendYangSnippet(sb, module, schemaNode, namespace[namespace.length - 1]);
- }
-
- return replaceAllIllegalChars(sb);
- }
-
- private String createDescription(final Module module) {
- final StringBuilder sb = new StringBuilder();
- final String moduleDescription = encodeAngleBrackets(module.getDescription().orElse(null));
- final String formattedDescription = FormattingUtils.formatToParagraph(moduleDescription, 0);
-
- if (!Strings.isNullOrEmpty(formattedDescription)) {
- sb.append(formattedDescription);
- sb.append(NEW_LINE);
- }
-
- if (verboseCommentGenerator != null) {
- verboseCommentGenerator.appendModuleDescription(sb, module);
- }
-
- return replaceAllIllegalChars(sb);
- }
-
private GeneratedTypeBuilder findChildNodeByPath(final SchemaPath path) {
for (final ModuleContext ctx : genCtx.values()) {
final GeneratedTypeBuilder result = ctx.getChildNode(path);
return genCtx;
}
- @VisibleForTesting
- static String replaceAllIllegalChars(final StringBuilder stringBuilder){
- final String ret = UNICODE_CHAR_PATTERN.matcher(stringBuilder).replaceAll("\\\\\\\\u");
- return ret.isEmpty() ? "" : ret;
- }
-
private static void annotateDeprecatedIfNecessary(final Status status, final GeneratedTypeBuilder builder) {
if (status == Status.DEPRECATED) {
builder.addAnnotation("", "Deprecated");
+++ /dev/null
-/*
- * Copyright (c) 2018 Pantheon Technologies, s.r.o. 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.mdsal.binding.generator.impl;
-
-import static java.util.Objects.requireNonNull;
-import static org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil.encodeAngleBrackets;
-
-import com.google.common.collect.Iterables;
-import java.util.List;
-import java.util.Set;
-import org.opendaylight.mdsal.binding.generator.spi.YangTextSnippetProvider;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-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.RpcDefinition;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-
-final class VerboseCommentGenerator {
- private final YangTextSnippetProvider provider;
-
- VerboseCommentGenerator(final YangTextSnippetProvider provider) {
- this.provider = requireNonNull(provider);
- }
-
- void appendModuleDescription(final StringBuilder sb, final Module module) {
- sb.append("<p>")
- .append("This class represents the following YANG schema fragment defined in module <b>")
- .append(module.getName())
- .append("</b>\n")
- .append("<pre>\n")
- .append(encodeAngleBrackets(provider.generateYangSnippet(module)))
- .append("</pre>");
- }
-
- void appendYangSnippet(final StringBuilder sb, final Set<? extends SchemaNode> schemaNodes) {
- if (!schemaNodes.isEmpty()) {
- sb.append("<pre>\n");
- for (SchemaNode schemaNode : schemaNodes) {
- sb.append(encodeAngleBrackets(provider.generateYangSnippet(requireNonNull(schemaNode))));
- }
- sb.append("</pre>\n");
- }
- }
-
- void appendYangSnippet(final StringBuilder sb, final Module module, final SchemaNode schemaNode,
- final String className) {
-
- sb.append("<p>\n")
- .append("This class represents the following YANG schema fragment defined in module <b>")
- .append(module.getName())
- .append("</b>\n")
- .append("<pre>\n")
- .append(encodeAngleBrackets(provider.generateYangSnippet(schemaNode)))
- .append("</pre>\n")
- .append("The schema path to identify an instance is\n")
- .append("<i>")
- .append(formatSchemaPath(module.getName(), schemaNode.getPath().getPathFromRoot()))
- .append("</i>\n");
-
- if (hasBuilderClass(schemaNode)) {
- final String builderClassName = className + "Builder";
-
- sb.append("\n<p>To create instances of this class use {@link ").append(builderClassName).append("}.\n")
- .append("@see ").append(builderClassName).append('\n');
- if (schemaNode instanceof ListSchemaNode) {
- final List<QName> keyDef = ((ListSchemaNode)schemaNode).getKeyDefinition();
- if (keyDef != null && !keyDef.isEmpty()) {
- sb.append("@see ").append(className).append("Key");
- }
- sb.append('\n');
- }
- }
- }
-
- private static boolean hasBuilderClass(final SchemaNode schemaNode) {
- return schemaNode instanceof ContainerSchemaNode || schemaNode instanceof ListSchemaNode
- || schemaNode instanceof RpcDefinition || schemaNode instanceof NotificationDefinition;
- }
-
- private static String formatSchemaPath(final String moduleName, final Iterable<QName> schemaPath) {
- final StringBuilder sb = new StringBuilder();
- sb.append(moduleName);
-
- QName currentElement = Iterables.getFirst(schemaPath, null);
- for (QName pathElement : schemaPath) {
- sb.append('/');
- if (!currentElement.getNamespace().equals(pathElement.getNamespace())) {
- currentElement = pathElement;
- sb.append(pathElement);
- } else {
- sb.append(pathElement.getLocalName());
- }
- }
- return sb.toString();
- }
-}
this.strategy = strategy;
this.schemaContext = schema;
- final BindingGeneratorImpl generator = new BindingGeneratorImpl();
+ final BindingGeneratorImpl generator = new BindingGeneratorImpl(true);
generator.generateTypes(schema);
final Map<Module, ModuleContext> modules = generator.getModuleContexts();
unionGenTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeName);
final String typedefDescription = encodeAngleBrackets(typedef.getDescription().orElse(null));
unionGenTOBuilder.setDescription(typedefDescription);
- unionGenTOBuilder.setReference(typedef.getReference().orElse(null));
+ typedef.getReference().ifPresent(unionGenTOBuilder::setReference);
unionGenTOBuilder.setSchemaPath(typedef.getPath().getPathFromRoot());
unionGenTOBuilder.setModuleName(module.getName());
} else {
final String typedefDescription = encodeAngleBrackets(typedef.getDescription().orElse(null));
newType.setDescription(typedefDescription);
- newType.setReference(typedef.getReference().orElse(null));
+ typedef.getReference().ifPresent(newType::setReference);
newType.setSchemaPath(typedef.getPath().getPathFromRoot());
newType.setModuleName(moduleName);
final String typedefDescription = encodeAngleBrackets(typeDef.getDescription().orElse(null));
genTOBuilder.setDescription(typedefDescription);
- genTOBuilder.setReference(typeDef.getReference().orElse(null));
+ typeDef.getReference().ifPresent(genTOBuilder::setReference);
genTOBuilder.setSchemaPath(typeDef.getPath().getPathFromRoot());
genTOBuilder.setModuleName(moduleName);
genTOBuilder.setBaseType(typeDef);
final String typedefDescription = encodeAngleBrackets(typedef.getDescription().orElse(null));
genTOBuilder.setDescription(typedefDescription);
- genTOBuilder.setReference(typedef.getReference().orElse(null));
+ typedef.getReference().ifPresent(genTOBuilder::setReference);
genTOBuilder.setSchemaPath(typedef.getPath().getPathFromRoot());
genTOBuilder.setModuleName(moduleName);
genTOBuilder.setTypedef(true);
+++ /dev/null
-/**
- * Copyright (c) 2015 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.mdsal.binding.generator.impl;
-
-import static org.junit.Assert.assertEquals;
-
-import org.junit.Test;
-import org.opendaylight.mdsal.binding.generator.impl.BindingGeneratorImpl;
-
-public class ReplaceAllIllegalCharsTest {
-
- @Test
- public void unicodeCharReplaceTest() {
- String inputString = "abcu\\uuuuu\\uuua\\u\\\\uabc\\\\uuuu\\\\\\uuuu\\\\\\\\uuuu///uu/u/u/u/u/u/u";
-
- StringBuilder sb = new StringBuilder(inputString);
- String resultString = BindingGeneratorImpl.replaceAllIllegalChars(sb);
-
- String expectedString = "abcu\\\\uuuuu\\\\uuua\\\\u\\\\uabc\\\\uuuu\\\\uuuu\\\\uuuu///uu/u/u/u/u/u/u";
- assertEquals(expectedString, resultString);
- }
-
-}
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
+import java.util.regex.Pattern;
import org.opendaylight.mdsal.binding.model.api.AccessModifier;
import org.opendaylight.mdsal.binding.model.api.Restrictions;
import org.opendaylight.mdsal.binding.model.api.Type;
private static final CharMatcher DASH_COLON_MATCHER = CharMatcher.anyOf("-:");
private static final CharMatcher GT_MATCHER = CharMatcher.is('>');
private static final CharMatcher LT_MATCHER = CharMatcher.is('<');
+ private static final Pattern UNICODE_CHAR_PATTERN = Pattern.compile("\\\\+u");
private static final Restrictions EMPTY_RESTRICTIONS = new Restrictions() {
@Override
}
return description;
}
+
+ public static String replaceAllIllegalChars(final CharSequence stringBuilder){
+ final String ret = UNICODE_CHAR_PATTERN.matcher(stringBuilder).replaceAll("\\\\\\\\u");
+ return ret.isEmpty() ? "" : ret;
+ }
}
--- /dev/null
+/*
+ * Copyright (c) 2018 Pantheon Technologies, s.r.o. 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.mdsal.binding.model.util;
+
+import static org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil.replaceAllIllegalChars;
+import static org.opendaylight.mdsal.binding.model.util.FormattingUtils.formatToParagraph;
+
+import com.google.common.annotations.Beta;
+import com.google.common.escape.Escaper;
+import com.google.common.escape.Escapers;
+import java.util.Optional;
+import java.util.regex.Pattern;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.mdsal.binding.model.api.TypeComment;
+import org.opendaylight.yangtools.yang.model.api.DocumentedNode;
+
+/**
+ * Utility methods for creating {@link TypeComment}s.
+ */
+@Beta
+@NonNullByDefault
+public final class TypeComments {
+ private static final Escaper ENTITY_ESCAPER = Escapers.builder()
+ .addEscape('<', "<")
+ .addEscape('>', ">")
+ .addEscape('&', "&")
+ .addEscape('@', "@").build();
+ private static final Pattern TAIL_COMMENT_PATTERN = Pattern.compile("*/", Pattern.LITERAL);
+
+ /**
+ * Create a {@link TypeComment} for a javadoc-compliant text snippet. This snippet must be eligible for direct
+ * inclusion in a Java comment without further escaping.
+ *
+ * @param javadoc Pre-formatted javadoc snippet
+ * @return {@link TypeComment}, or empty if the snippet was empty
+ */
+ public static Optional<TypeComment> javadoc(final String javadoc) {
+ return javadoc.isEmpty() ? Optional.empty() : Optional.of(() -> javadoc);
+ }
+
+ /**
+ * Create a {@link TypeComment} for a {@link DocumentedNode}'s description string.
+ *
+ * @param node Documented node containing the description to be processed
+ * @return {@link TypeComment}, or empty if the node's description was empty or non-present.
+ */
+ public static Optional<TypeComment> description(final DocumentedNode node) {
+ final String description = node.getDescription().orElse("");
+ return description.isEmpty() ? Optional.empty() : Optional.of(() -> replaceAllIllegalChars(
+ formatToParagraph(
+ TAIL_COMMENT_PATTERN.matcher(ENTITY_ESCAPER.escape(description)).replaceAll("*/"), 0)));
+ }
+}
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Optional;
import org.opendaylight.mdsal.binding.model.api.AnnotationType;
import org.opendaylight.mdsal.binding.model.api.Constant;
import org.opendaylight.mdsal.binding.model.api.Enumeration;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
import org.opendaylight.mdsal.binding.model.api.MethodSignature;
import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.model.api.TypeComment;
+import org.opendaylight.mdsal.binding.model.api.YangSourceDefinition;
import org.opendaylight.mdsal.binding.model.api.type.builder.AnnotationTypeBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.EnumBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedPropertyBuilder;
abstract class AbstractGeneratedType extends AbstractBaseType implements GeneratedType {
private final Type parent;
- private final String comment;
+ private final TypeComment comment;
private final List<AnnotationType> annotations;
private final List<Type> implementsTypes;
private final List<Enumeration> enumerations;
private final List<GeneratedType> enclosedTypes;
private final List<GeneratedProperty> properties;
private final boolean isAbstract;
+ private final YangSourceDefinition definition;
public AbstractGeneratedType(final AbstractGeneratedTypeBuilder<?> builder) {
super(builder.getPackageName(), builder.getName());
builder.getEnclosedTransferObjects());
this.properties = toUnmodifiableProperties(builder.getProperties());
this.isAbstract = builder.isAbstract();
+ this.definition = builder.getYangSourceDefinition().orElse(null);
}
- public AbstractGeneratedType(final Type parent, final String packageName, final String name, final String comment,
- final List<AnnotationTypeBuilder> annotationBuilders, final boolean isAbstract,
+ public AbstractGeneratedType(final Type parent, final String packageName, final String name,
+ final TypeComment comment, final List<AnnotationTypeBuilder> annotationBuilders, final boolean isAbstract,
final List<Type> implementsTypes, final List<GeneratedTypeBuilder> enclosedGenTypeBuilders,
final List<GeneratedTOBuilder> enclosedGenTOBuilders, final List<EnumBuilder> enumBuilders,
final List<Constant> constants, final List<MethodSignatureBuilder> methodBuilders,
this.enclosedTypes = toUnmodifiableEnclosedTypes(enclosedGenTypeBuilders, enclosedGenTOBuilders);
this.properties = toUnmodifiableProperties(propertyBuilders);
this.isAbstract = isAbstract;
+ this.definition = null;
}
protected static final <T> List<T> makeUnmodifiable(final List<T> list) {
}
@Override
- public final String getComment() {
+ public final TypeComment getComment() {
return this.comment;
}
return this.properties;
}
+ @Override
+ public final Optional<YangSourceDefinition> getYangSourceDefinition() {
+ return Optional.ofNullable(definition);
+ }
+
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
import java.util.Collections;
import java.util.List;
import java.util.Objects;
+import java.util.Optional;
import org.opendaylight.mdsal.binding.model.api.AccessModifier;
import org.opendaylight.mdsal.binding.model.api.Constant;
import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.model.api.TypeComment;
+import org.opendaylight.mdsal.binding.model.api.YangSourceDefinition;
import org.opendaylight.mdsal.binding.model.api.type.builder.AnnotationTypeBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.EnumBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedPropertyBuilder;
import org.opendaylight.mdsal.binding.model.util.AbstractBaseType;
import org.opendaylight.yangtools.util.LazyCollections;
-abstract class AbstractGeneratedTypeBuilder<T extends GeneratedTypeBuilderBase<T>> extends AbstractBaseType implements GeneratedTypeBuilderBase<T> {
+abstract class AbstractGeneratedTypeBuilder<T extends GeneratedTypeBuilderBase<T>> extends AbstractBaseType
+ implements GeneratedTypeBuilderBase<T> {
private List<AnnotationTypeBuilder> annotationBuilders = Collections.emptyList();
private List<Type> implementsTypes = Collections.emptyList();
private final List<GeneratedTypeBuilder> enclosedTypes = Collections.emptyList();
private List<GeneratedTOBuilder> enclosedTransferObjects = Collections.emptyList();
private List<GeneratedPropertyBuilder> properties = Collections.emptyList();
- private String comment = "";
+ private TypeComment comment;
private boolean isAbstract;
+ private YangSourceDefinition yangSourceDefinition;
protected AbstractGeneratedTypeBuilder(final String packageName, final String name) {
super(packageName, name);
}
- protected String getComment() {
+ protected TypeComment getComment() {
return this.comment;
}
Preconditions.checkArgument(name != null, "Name for Enclosing Generated Transfer Object cannot be null!");
final GeneratedTOBuilder builder = new GeneratedTOBuilderImpl(getFullyQualifiedName(), name);
- Preconditions.checkArgument(!this.enclosedTransferObjects.contains(builder), "This generated type already contains equal enclosing transfer object.");
+ Preconditions.checkArgument(!this.enclosedTransferObjects.contains(builder),
+ "This generated type already contains equal enclosing transfer object.");
this.enclosedTransferObjects = LazyCollections.lazyAdd(this.enclosedTransferObjects, builder);
return builder;
}
@Override
public T addEnclosingTransferObject(final GeneratedTOBuilder genTOBuilder) {
Preconditions.checkArgument(genTOBuilder != null, "Parameter genTOBuilder cannot be null!");
- Preconditions.checkArgument(!this.enclosedTransferObjects.contains(genTOBuilder), "This generated type already contains equal enclosing transfer object.");
+ Preconditions.checkArgument(!this.enclosedTransferObjects.contains(genTOBuilder),
+ "This generated type already contains equal enclosing transfer object.");
this.enclosedTransferObjects = LazyCollections.lazyAdd(this.enclosedTransferObjects, genTOBuilder);
return thisInstance();
}
@Override
- public T addComment(final String comment) {
- this.comment = comment;
+ public T addComment(final TypeComment comment) {
+ this.comment = Preconditions.checkNotNull(comment);
return thisInstance();
}
final AnnotationTypeBuilder builder = new AnnotationTypeBuilderImpl(packageName, name);
- Preconditions.checkArgument(!this.annotationBuilders.contains(builder), "This generated type already contains equal annotation.");
+ Preconditions.checkArgument(!this.annotationBuilders.contains(builder),
+ "This generated type already contains equal annotation.");
this.annotationBuilders = LazyCollections.lazyAdd(this.annotationBuilders, builder);
return builder;
}
@Override
public T addImplementsType(final Type genType) {
Preconditions.checkArgument(genType != null, "Type cannot be null");
- Preconditions.checkArgument(!this.implementsTypes.contains(genType), "This generated type already contains equal implements type.");
+ Preconditions.checkArgument(!this.implementsTypes.contains(genType),
+ "This generated type already contains equal implements type.");
this.implementsTypes = LazyCollections.lazyAdd(this.implementsTypes, genType);
return thisInstance();
}
public Constant addConstant(final Type type, final String name, final Object value) {
Preconditions.checkArgument(type != null, "Returning Type for Constant cannot be null!");
Preconditions.checkArgument(name != null, "Name of constant cannot be null!");
- Preconditions.checkArgument(!containsConstant(name), "This generated type already contains constant with the same name.");
+ Preconditions.checkArgument(!containsConstant(name),
+ "This generated type already contains constant with the same name.");
final Constant constant = new ConstantImpl(this, type, name, value);
this.constants = LazyCollections.lazyAdd(this.constants, constant);
Preconditions.checkArgument(name != null, "Name of enumeration cannot be null!");
final EnumBuilder builder = new EnumerationBuilderImpl(getFullyQualifiedName(), name);
- Preconditions.checkArgument(!this.enumDefinitions.contains(builder), "This generated type already contains equal enumeration.");
+ Preconditions.checkArgument(!this.enumDefinitions.contains(builder),
+ "This generated type already contains equal enumeration.");
this.enumDefinitions = LazyCollections.lazyAdd(this.enumDefinitions, builder);
return builder;
}
@Override
public GeneratedPropertyBuilder addProperty(final String name) {
Preconditions.checkArgument(name != null, "Parameter name can't be null");
- Preconditions.checkArgument(!containsProperty(name), "This generated type already contains property with the same name.");
+ Preconditions.checkArgument(!containsProperty(name),
+ "This generated type already contains property with the same name.");
final GeneratedPropertyBuilder builder = new GeneratedPropertyBuilderImpl(name);
builder.setAccessModifier(AccessModifier.PUBLIC);
return false;
}
+ public Type getParent() {
+ return null;
+ }
+
+ @Override
+ public List<GeneratedPropertyBuilder> getProperties() {
+ return this.properties;
+ }
+
+ @Override
+ public Optional<YangSourceDefinition> getYangSourceDefinition() {
+ return Optional.ofNullable(yangSourceDefinition);
+ }
+
+
+ @Override
+ public void setYangSourceDefinition(final YangSourceDefinition definition) {
+ yangSourceDefinition = Preconditions.checkNotNull(definition);
+ }
+
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
- result = (prime * result) + Objects.hashCode(getName());
- result = (prime * result) + Objects.hashCode(getPackageName());
+ result = prime * result + Objects.hashCode(getName());
+ result = prime * result + Objects.hashCode(getPackageName());
return result;
}
final AbstractGeneratedTypeBuilder<?> other = (AbstractGeneratedTypeBuilder<?>) obj;
return Objects.equals(getName(), other.getName()) && Objects.equals(getPackageName(), other.getPackageName());
}
-
- public Type getParent() {
- return null;
- }
-
- @Override
- public List<GeneratedPropertyBuilder> getProperties() {
- return this.properties;
- }
}
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
import org.opendaylight.mdsal.binding.model.api.MethodSignature;
import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.model.api.TypeComment;
+import org.opendaylight.mdsal.binding.model.api.YangSourceDefinition;
import org.opendaylight.mdsal.binding.model.api.type.builder.AnnotationTypeBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.EnumBuilder;
import org.opendaylight.mdsal.binding.model.util.AbstractBaseType;
}
@Override
- public String getComment() {
+ public TypeComment getComment() {
return null;
}
public String getModuleName() {
return this.moduleName;
}
+
+ @Override
+ public Optional<YangSourceDefinition> getYangSourceDefinition() {
+ // TODO Auto-generated method stub
+ return Optional.empty();
+ }
}
}
package org.opendaylight.mdsal.binding.model.util.generated.type.builder;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.model.api.TypeComment;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
import org.opendaylight.yangtools.yang.common.QName;
builder.append(getPackageName());
builder.append(", name=");
builder.append(getName());
- builder.append(", comment=");
- builder.append(getComment());
+
+ final TypeComment comment = getComment();
+ if (comment != null) {
+ builder.append(", comment=");
+ builder.append(comment.getJavadoc());
+ }
builder.append(", annotations=");
builder.append(getAnnotations());
builder.append(", implements=");
assertFalse(restrictions.getLengthConstraint().isPresent());
assertTrue(restrictions.getPatternConstraints().isEmpty());
}
+
+ @Test
+ public void unicodeCharReplaceTest() {
+ String inputString = "abcu\\uuuuu\\uuua\\u\\\\uabc\\\\uuuu\\\\\\uuuu\\\\\\\\uuuu///uu/u/u/u/u/u/u";
+
+ assertEquals("abcu\\\\uuuuu\\\\uuua\\\\u\\\\uabc\\\\uuuu\\\\uuuu\\\\uuuu///uu/u/u/u/u/u/u",
+ BindingGeneratorUtil.replaceAllIllegalChars(inputString));
+ }
}
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.MethodSignatureBuilder;
import org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil;
+import org.opendaylight.mdsal.binding.model.util.TypeComments;
import org.opendaylight.mdsal.binding.model.util.Types;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
generatedTypeBuilder.setModuleName("myModuleName");
generatedTypeBuilder.setReference("myReference");
generatedTypeBuilder.setSchemaPath(SchemaPath.create(true, QName.create("test", "/path")).getPathFromRoot());
- assertNotNull(generatedTypeBuilder.addComment("My comment.."));
+ assertNotNull(generatedTypeBuilder.addComment(TypeComments.javadoc("My comment..").get()));
assertEquals(
"GeneratedTransferObject [packageName=my.package, name=MyName, comment=My comment.., annotations=[], implements=[], enclosedTypes=[], constants=[], enumerations=[], properties=, methods=[]]",
assertEquals("myModuleName", instance.getModuleName());
assertEquals("myReference", instance.getReference());
assertEquals(SchemaPath.create(true, QName.create("test", "/path")).getPathFromRoot(), instance.getSchemaPath());
- assertEquals("My comment..", instance.getComment());
+ assertEquals("My comment..", instance.getComment().getJavadoc());
}
}
*/
package org.opendaylight.mdsal.binding.java.api.generator
+import static org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil.encodeAngleBrackets
+
import com.google.common.base.CharMatcher
import com.google.common.base.Splitter
+import com.google.common.collect.Iterables
import java.util.Arrays
import java.util.Collection
import java.util.HashMap
import java.util.Map
import java.util.StringTokenizer
import java.util.regex.Pattern
-import org.opendaylight.yangtools.yang.common.QName
import org.opendaylight.mdsal.binding.model.api.ConcreteType
import org.opendaylight.mdsal.binding.model.api.Constant
import org.opendaylight.mdsal.binding.model.api.GeneratedProperty
import org.opendaylight.mdsal.binding.model.api.Restrictions
import org.opendaylight.mdsal.binding.model.api.Type
import org.opendaylight.mdsal.binding.model.api.TypeMember
+import org.opendaylight.mdsal.binding.model.api.YangSourceDefinition.Single
+import org.opendaylight.mdsal.binding.model.api.YangSourceDefinition.Multiple
import org.opendaylight.mdsal.binding.model.util.Types
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
+import org.opendaylight.yangtools.yang.model.api.DocumentedNode
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition
+import org.opendaylight.yangtools.yang.model.api.SchemaNode
abstract class BaseTemplate {
protected val GeneratedType type;
}
def protected String formatDataForJavaDoc(GeneratedType type) {
- val typeDescription = type.getDescription().encodeJavadocSymbols;
+ val sb = new StringBuilder()
+ val comment = type.comment
+ if (comment !== null) {
+ sb.append(comment.javadoc)
+ }
+
+ appendSnippet(sb, type)
return '''
- «IF !typeDescription.nullOrEmpty»
- «typeDescription»
+ «IF sb.length != 0»
+ «sb.toString»
«ENDIF»
'''.toString
}
- private static final CharMatcher AMP_MATCHER = CharMatcher.is('&');
+ private static val AMP_MATCHER = CharMatcher.is('&')
- def encodeJavadocSymbols(String description) {
+ def static encodeJavadocSymbols(String description) {
if (description.nullOrEmpty) {
return description;
}
- return AMP_MATCHER.replaceFrom(TAIL_COMMENT_PATTERN.matcher(description).replaceAll("*/"), "&");
+ return TAIL_COMMENT_PATTERN.matcher(AMP_MATCHER.replaceFrom(description, "&")).replaceAll("*/")
}
def protected String formatDataForJavaDoc(GeneratedType type, String additionalComment) {
- val StringBuilder typeDescription = new StringBuilder();
- if (!type.description.nullOrEmpty) {
- typeDescription.append(type.description)
- typeDescription.append(NEW_LINE)
- typeDescription.append(NEW_LINE)
- typeDescription.append(NEW_LINE)
- typeDescription.append(additionalComment)
- } else {
- typeDescription.append(additionalComment)
+ val comment = type.comment
+ if (comment === null) {
+ return '''
+ «additionalComment»
+ '''
}
+ val sb = new StringBuilder().append(comment.javadoc)
+ appendSnippet(sb, type)
+
+ sb.append(NEW_LINE)
+ .append(NEW_LINE)
+ .append(NEW_LINE)
+ .append(additionalComment)
+
return '''
- «typeDescription.toString»
- '''.toString
+ «sb.toString»
+ '''
+ }
+
+ def private static void appendSnippet(StringBuilder sb, GeneratedType type) {
+ val optDef = type.yangSourceDefinition
+ if (optDef.present) {
+ val def = optDef.get
+ sb.append(NEW_LINE)
+
+ if (def instanceof Single) {
+ val node = def.node
+ sb.append("<p>\n")
+ .append("This class represents the following YANG schema fragment defined in module <b>")
+ .append(def.module.name).append("</b>\n")
+ .append("<pre>\n")
+ .append(encodeAngleBrackets(encodeJavadocSymbols(YangTemplate.generateYangSnippet(node))))
+ .append("</pre>")
+
+ if (node instanceof SchemaNode) {
+ sb.append("The schema path to identify an instance is\n")
+ .append("<i>")
+ .append(formatSchemaPath(def.module.name, node.path.pathFromRoot))
+ .append("</i>\n")
+
+ if (hasBuilderClass(node)) {
+ val builderName = type.name + "Builder";
+
+ sb.append("\n<p>To create instances of this class use {@link ").append(builderName)
+ .append("}.\n")
+ .append("@see ").append(builderName).append('\n')
+ if (node instanceof ListSchemaNode) {
+ val keyDef = node.keyDefinition
+ if (keyDef !== null && !keyDef.empty) {
+ sb.append("@see ").append(type.name).append("Key")
+ }
+ sb.append('\n');
+ }
+ }
+ }
+ } else if (def instanceof Multiple) {
+ sb.append("<pre>\n")
+ for (DocumentedNode schemaNode : def.nodes) {
+ sb.append(encodeAngleBrackets(encodeJavadocSymbols(YangTemplate.generateYangSnippet(schemaNode))))
+ }
+ sb.append("</pre>\n")
+ }
+ }
+ }
+
+ def private static boolean hasBuilderClass(SchemaNode schemaNode) {
+ return schemaNode instanceof ContainerSchemaNode || schemaNode instanceof ListSchemaNode
+ || schemaNode instanceof RpcDefinition || schemaNode instanceof NotificationDefinition;
+ }
+
+ def private static String formatSchemaPath(String moduleName, Iterable<QName> schemaPath) {
+ val sb = new StringBuilder().append(moduleName);
+
+ var currentElement = Iterables.getFirst(schemaPath, null);
+ for (QName pathElement : schemaPath) {
+ sb.append('/')
+ if (!currentElement.namespace.equals(pathElement.namespace)) {
+ currentElement = pathElement
+ sb.append(pathElement)
+ } else {
+ sb.append(pathElement.getLocalName())
+ }
+ }
+ return sb.toString();
}
def protected String formatDataForJavaDoc(TypeMember type, String additionalComment) {
import java.util.List
import java.util.Map
import java.util.Set
-import org.opendaylight.mdsal.binding.generator.spi.YangTextSnippetProvider
import org.opendaylight.mdsal.binding.model.util.FormattingUtils
import org.opendaylight.yangtools.yang.common.Revision
import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode
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.DocumentedNode
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.type.EnumTypeDefinition
import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair
-final class YangTemplate implements YangTextSnippetProvider {
+final class YangTemplate {
private static val String SKIP_PROPERTY_NAME = "mdsal.skip.verbose"
private static val SKIPPED_EMPTY = '''(Empty due to «SKIP_PROPERTY_NAME» property = true)'''
- private static val INSTANCE = new YangTemplate();
-
- def static YangTemplate getInstance() {
- return INSTANCE;
- }
-
- override String generateYangSnippet(Module module) {
+ def static String generateYangSnippet(Module module) {
if (SKIP)
return SKIPPED_EMPTY
'''
'''
}
- override String generateYangSnippet(SchemaNode schemaNode) {
+ def static String generateYangSnippet(DocumentedNode schemaNode) {
if (schemaNode === null)
return ''
+ if (schemaNode instanceof Module)
+ return generateYangSnippet(schemaNode)
if (SKIP)
return SKIPPED_EMPTY
'''
import org.junit.BeforeClass;
import org.opendaylight.mdsal.binding.generator.api.BindingGenerator;
import org.opendaylight.mdsal.binding.generator.impl.BindingGeneratorImpl;
-import org.opendaylight.mdsal.binding.java.api.generator.YangTemplate;
public abstract class BaseCompilationTest {
@Before
public void init() {
- bindingGenerator = new BindingGeneratorImpl(YangTemplate.getInstance());
+ bindingGenerator = new BindingGeneratorImpl();
}
}
import org.opendaylight.mdsal.binding.generator.api.BindingGenerator;
import org.opendaylight.mdsal.binding.generator.impl.BindingGeneratorImpl;
import org.opendaylight.mdsal.binding.java.api.generator.TOGenerator;
-import org.opendaylight.mdsal.binding.java.api.generator.YangTemplate;
import org.opendaylight.mdsal.binding.model.api.GeneratedProperty;
import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
final SchemaContext context = YangParserTestUtils.parseYangResource("/list-composite-key.yang");
assertNotNull(context);
- final BindingGenerator bindingGen = new BindingGeneratorImpl(YangTemplate.getInstance());
+ final BindingGenerator bindingGen = new BindingGeneratorImpl();
final List<Type> genTypes = bindingGen.generateTypes(context);
assertTrue(genTypes != null);