Fixed bug in code generator imports.
Signed-off-by: Martin Vitez <mvitez@cisco.com>
import java.util.Collections\rimport java.util.Arrays
import org.opendaylight.yangtools.sal.binding.model.api.Restrictions
import com.google.common.collect.Range
+import java.util.regex.Pattern
/**\r
* Template for generating JAVA class. \r
«val cValue = c.value»\r
«IF cValue instanceof List<?>»\r
«val cValues = cValue as List<?>»\r
- private static final List<Pattern> «Constants.MEMBER_PATTERN_LIST» = new ArrayList<Pattern>();\r
- public static final List<String> «TypeConstants.PATTERN_CONSTANT_NAME» = «Arrays.importedName».asList(«\r
+ private static final «List.importedName»<«Pattern.importedName»> «Constants.MEMBER_PATTERN_LIST» = new «ArrayList.importedName»<«Pattern.importedName»>();\r
+ public static final «List.importedName»<String> «TypeConstants.PATTERN_CONSTANT_NAME» = «Arrays.importedName».asList(«\r
FOR v : cValues SEPARATOR ", "»«\r
IF v instanceof String»"«\r
v as String»"«\r
}
}
- final List<Constant> constants = genType.getConstantDefinitions();
- final List<MethodSignature> methods = genType.getMethodDefinitions();
-
- // CONSTANTS
- if (constants != null) {
- for (final Constant constant : constants) {
- final Type constantType = constant.getType();
- putTypeIntoImports(genType, constantType, imports);
- }
- }
-
// REGULAR EXPRESSION
if (genType instanceof GeneratedTransferObject
&& isConstantInTO(TypeConstants.PATTERN_CONSTANT_NAME, (GeneratedTransferObject) genType)) {
putTypeIntoImports(genType, Types.typeForClass(java.util.ArrayList.class), imports);
}
+ final List<MethodSignature> methods = genType.getMethodDefinitions();
// METHODS
if (methods != null) {
for (final MethodSignature method : methods) {
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-java-api-generator</artifactId>
</dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
</instructions>
</configuration>
</plugin>
+ <plugin>
+ <groupId>org.eclipse.xtend</groupId>
+ <artifactId>xtend-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ </plugin>
</plugins>
</build>
--- /dev/null
+package org.opendaylight.yangtools.yang.unified.doc.generator
+
+import org.opendaylight.yangtools.yang.model.api.SchemaContext
+import java.io.File
+import java.util.Set
+import org.opendaylight.yangtools.yang.model.api.Module
+import java.io.IOException
+import java.util.HashSet
+import java.io.FileWriter
+import java.io.BufferedWriter
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition
+import org.opendaylight.yangtools.yang.model.api.SchemaNode
+import org.opendaylight.yangtools.yang.model.util.ExtendedType
+import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition
+import java.text.SimpleDateFormat
+import java.util.Collection
+import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint
+import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint
+import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
+import org.slf4j.LoggerFactory
+import org.slf4j.Logger
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema
+import java.util.List
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition
+import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition
+
+class GeneratorImpl {
+
+ File path
+ static val REVISION_FORMAT = new SimpleDateFormat("yyyy-MM-dd")
+ static val Logger LOG = LoggerFactory.getLogger(GeneratorImpl)
+
+
+ def generate(SchemaContext context, File targetPath, Set<Module> modulesToGen) throws IOException {
+ path = targetPath;
+ path.mkdirs();
+ val it = new HashSet;
+ for (module : modulesToGen) {
+ add(module.generateDocumentation());
+ }
+ return it;
+ }
+
+ def generateDocumentation(Module module) {
+ val destination = new File(path, '''«module.name».html''')
+ try {
+ val fw = new FileWriter(destination)
+ destination.createNewFile();
+ val bw = new BufferedWriter(fw)
+
+ bw.append(module.generate);
+ bw.close();
+ fw.close();
+ } catch (IOException e) {
+ LOG.error(e.getMessage());
+ }
+ return destination;
+ }
+
+ def generate(Module module) '''
+ <!DOCTYPE html>
+ <html lang="en">
+ <head>
+ <title>«module.name»</title>
+ </head>
+ <body>
+ «module.body»
+ </body>
+ </html>
+ '''
+
+ def body(Module module) '''
+ «header(module)»
+
+ «typeDefinitions(module)»
+
+ «groupings(module)»
+
+ «dataStore(module)»
+
+ «notifications(module)»
+
+ «augmentations(module)»
+
+ «rpcs(module)»
+
+ «extensions(module)»
+
+ '''
+
+
+ def typeDefinitions(Module module) {
+ val Set<TypeDefinition<?>> typedefs = module.typeDefinitions
+ if (typedefs.empty) {
+ return '';
+ }
+ return '''
+ <h2>Type Definitions</h2>
+ «list(typedefs)»
+
+ «FOR typedef : typedefs»
+ «typeDefinition(typedef)»
+ «ENDFOR»
+ '''
+ }
+
+ private def CharSequence typeDefinition(TypeDefinition<?> type) '''
+ «header(type)»
+ «body(type)»
+ «restrictions(type)»
+ '''
+
+ def groupings(Module module) {
+ if (module.groupings.empty) {
+ return '';
+ }
+ return '''
+ <h2>Groupings</h2>
+ «list(module.groupings)»
+
+ «FOR grouping : module.groupings»
+ «headerAndBody(grouping)»
+ «ENDFOR»
+ '''
+ }
+
+ def dataStore(Module module) {
+ if (module.childNodes.empty) {
+ return '';
+ }
+ return '''
+ <h2>Datastore Structure</h2>
+ «tree(module)»
+ '''
+ }
+
+ def augmentations(Module module) {
+ if (module.augmentations.empty) {
+ return '';
+ }
+ return '''
+ <h2>Augmentations</h2>
+
+ <ul>
+ «FOR augment : module.augmentations»
+ <li>
+ augment
+ «augment.tree»
+ </li>
+ «ENDFOR»
+ </ul>
+ '''
+ }
+
+ def notifications(Module module) {
+ val Set<NotificationDefinition> notificationdefs = module.notifications
+ if (notificationdefs.empty) {
+ return '';
+ }
+ return '''
+ <h2>Notifications</h2>
+
+ <ul>
+ «FOR notificationdef : notificationdefs»
+ <li>
+ «notificationdef.nodeName»
+ «notificationdef.tree»
+ </li>
+ «ENDFOR»
+ </ul>
+ '''
+ }
+
+ def rpcs(Module module) {
+ if (module.rpcs.empty) {
+ return '';
+ }
+ return '''
+ <h2>RPC Definitions</h2>
+
+ <ul>
+ «FOR rpc : module.rpcs»
+ <li>
+ «rpc.nodeName»
+ «rpc.tree»
+ </li>
+ «ENDFOR»
+ </ul>
+ '''
+ }
+
+ def extensions(Module module) {
+ if (module.extensionSchemaNodes.empty) {
+ return '';
+ }
+ return '''
+ <h2>Extensions</h2>
+
+ <ul>
+ «FOR ext : module.extensionSchemaNodes»
+ <li>
+ «ext.nodeName»
+ «ext.tree»
+ </li>
+ «ENDFOR»
+ </ul>
+ '''
+ }
+
+ def CharSequence headerAndBody(SchemaNode node) '''
+ «header(node)»
+ «body(node)»
+ '''
+
+ def header(SchemaNode type) '''
+ <h3>«type.QName.localName»</h3>
+ '''
+
+ def body(SchemaNode definition) '''
+
+ «paragraphs(definition.description)»
+
+ «definition.reference»
+ '''
+
+
+ def list(Set<? extends SchemaNode> definitions) '''
+ <ul>
+ «FOR nodeDef : definitions»
+ <li>«nodeDef.QName.localName»</li>
+ «ENDFOR»
+ </ul>
+ '''
+
+ def header(Module module) '''
+ <h1>«module.name»</h1>
+
+ <h2>Base Information</h2>
+ <dl>
+ <dt>Prefix</dt>
+ <dd><pre>«module.prefix»</pre></dd>
+ <dt>Namespace</dt>
+ <dd><pre>«module.namespace»</pre></dd>
+ <dt>Revision</dt>
+ <dd>«REVISION_FORMAT.format(module.revision)»</dd>
+
+ «FOR imp : module.imports BEFORE "<dt>Imports</dt>" »
+ <dd>«pre(imp.prefix)» = «pre(imp.moduleName)»</dd>
+ «ENDFOR»
+ </dl>
+ '''
+
+
+ def process(Module module) {
+ throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ }
+
+
+
+ /* #################### TREE STRUCTURE #################### */
+ def dispatch CharSequence tree(Module module) '''
+ «strong("module " + module.name)»
+ «module.childNodes.childrenToTree»
+ '''
+
+ def dispatch CharSequence tree(DataNodeContainer node) '''
+ «IF node instanceof SchemaNode»
+ «(node as SchemaNode).nodeName»
+ «ENDIF»
+ «node.childNodes.childrenToTree»
+ '''
+
+ def dispatch CharSequence tree(DataSchemaNode node) '''
+ «node.nodeName»
+ '''
+
+ def dispatch CharSequence tree(ListSchemaNode node) '''
+ «node.nodeName»
+ «node.childNodes.childrenToTree»
+ '''
+
+ private def CharSequence childrenToTree(Collection<DataSchemaNode> childNodes) '''
+ «IF childNodes !== null && !childNodes.empty»
+ <ul>
+ «FOR child : childNodes»
+ <li>
+ «child.tree»
+ </li>
+ «ENDFOR»
+ </ul>
+ «ENDIF»
+ '''
+
+ def listKeys(ListSchemaNode node) '''
+ [«FOR key : node.keyDefinition SEPARATOR " "»«key.localName»«ENDFOR»]
+ '''
+
+ def dispatch CharSequence tree(AugmentationSchema augment) '''
+ <ul>
+ «listItem("Description", augment.description)»
+ «listItem("Reference", augment.reference)»
+ «IF augment.whenCondition !== null»
+ «listItem("When", augment.whenCondition.toString)»
+ «ENDIF»
+ <li>
+ Path «augment.targetPath.path.pathToTree»
+ </li>
+ <li>
+ Child nodes
+ «augment.childNodes.childrenToTree»
+ </li>
+ </ul>
+ '''
+
+ private def CharSequence pathToTree(List<QName> path) '''
+ «IF path !== null && !path.empty»
+ <ul>
+ «FOR pathElement : path»
+ <li>
+ «pathElement.namespace» «pathElement.localName»
+ </li>
+ «ENDFOR»
+ </ul>
+ «ENDIF»
+ '''
+
+ def dispatch CharSequence tree(NotificationDefinition notification) '''
+ <ul>
+ «listItem("Description", notification.description)»
+ «listItem("Reference", notification.reference)»
+ <li>
+ Child nodes
+ «notification.childNodes.childrenToTree»
+ </li>
+ </ul>
+ '''
+
+ def dispatch CharSequence tree(RpcDefinition rpc) '''
+ <ul>
+ «listItem("Description", rpc.description)»
+ «listItem("Reference", rpc.reference)»
+ <li>
+ «rpc.input.tree»
+ </li>
+ <li>
+ «rpc.output.tree»
+ </li>
+ </ul>
+ '''
+
+ def dispatch CharSequence tree(ExtensionDefinition ext) '''
+ <ul>
+ «listItem("Description", ext.description)»
+ «listItem("Reference", ext.reference)»
+ «listItem("Argument", ext.argument)»
+ </ul>
+ '''
+
+
+ /* #################### RESTRICTIONS #################### */
+ private def restrictions(TypeDefinition<?> type) '''
+ «type.toLength»
+ «type.toRange»
+ '''
+
+ def dispatch toLength(TypeDefinition<?> type) {
+ }
+
+ def dispatch toLength(BinaryTypeDefinition type) '''
+ «type.lengthConstraints.toLengthStmt»
+ '''
+
+ def dispatch toLength(StringTypeDefinition type) '''
+ «type.lengthConstraints.toLengthStmt»
+ '''
+
+ def dispatch toLength(ExtendedType type) '''
+ «type.lengthConstraints.toLengthStmt»
+ '''
+
+ def dispatch toRange(TypeDefinition<?> type) {
+ }
+
+ def dispatch toRange(DecimalTypeDefinition type) '''
+ «type.rangeConstraints.toRangeStmt»
+ '''
+
+ def dispatch toRange(IntegerTypeDefinition type) '''
+ «type.rangeConstraints.toRangeStmt»
+ '''
+
+ def dispatch toRange(UnsignedIntegerTypeDefinition type) '''
+ «type.rangeConstraints.toRangeStmt»
+ '''
+
+ def dispatch toRange(ExtendedType type) '''
+ «type.rangeConstraints.toRangeStmt»
+ '''
+
+ def toLengthStmt(Collection<LengthConstraint> lengths) '''
+ «IF lengths != null && !lengths.empty»
+ «strong("Length restrictions")»
+ <ul>
+ «FOR length : lengths»
+ <li>
+ «IF length.min == length.max»
+ «length.min»
+ «ELSE»
+ <«length.min», «length.max»>
+ «ENDIF»
+ </li>
+ «ENDFOR»
+ </ul>
+ «ENDIF»
+ '''
+
+ def toRangeStmt(Collection<RangeConstraint> ranges) '''
+ «IF ranges != null && !ranges.empty»
+ «strong("Range restrictions")»
+ <ul>
+ «FOR range : ranges»
+ <li>
+ «IF range.min == range.max»
+ «range.min»
+ «ELSE»
+ <«range.min», «range.max»>
+ «ENDIF»
+ </li>
+ «ENDFOR»
+ </ul>
+ «ENDIF»
+ '''
+
+
+
+ /* #################### UTILITY #################### */
+ def strong(String str) '''
+ <strong>«str»</strong>
+ '''
+
+ def italic(String str) '''
+ <i>«str»</i>
+ '''
+
+ def pre(String string) '''<pre>«string»</pre>'''
+
+ def paragraphs(String body) '''
+ <p>«body»</p>
+ '''
+
+ def listItem(String name, String value) '''
+ «IF value !== null && !value.empty»
+ <li>
+ «name»
+ <ul>
+ <li>
+ «value»
+ </li>
+ </ul>
+ </li>
+ «ENDIF»
+ '''
+
+ def dispatch addedByInfo(SchemaNode node) '''
+ '''
+
+ def dispatch addedByInfo(DataSchemaNode node) '''
+ «IF node.augmenting»(A)«ENDIF»«IF node.addedByUses»(U)«ENDIF»
+ '''
+
+ def dispatch isAddedBy(SchemaNode node) {
+ return false;
+ }
+
+ def dispatch isAddedBy(DataSchemaNode node) {
+ if (node.augmenting || node.addedByUses) {
+ return true
+ } else {
+ return false;
+ }
+ }
+
+ def nodeName(SchemaNode node) '''
+ «IF node.isAddedBy»
+ «italic(node.QName.localName)»«node.addedByInfo»
+ «ELSE»
+ «strong(node.QName.localName)»«node.addedByInfo»
+ «ENDIF»
+ '''
+
+ def nodeName(ListSchemaNode node) '''
+ «IF node.isAddedBy»
+ «italic(node.QName.localName)» «IF node.keyDefinition !== null && !node.keyDefinition.empty»«node.listKeys»«ENDIF»«node.addedByInfo»
+ «ELSE»
+ «strong(node.QName.localName)» «IF node.keyDefinition !== null && !node.keyDefinition.empty»«node.listKeys»«ENDIF»
+ «ENDIF»
+ '''
+
+}
--- /dev/null
+package org.opendaylight.yangtools.yang.unified.doc.generator.maven;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.project.MavenProject;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.unified.doc.generator.GeneratorImpl;
+import org.opendaylight.yangtools.yang2sources.spi.CodeGenerator;
+
+public class DocumentationGeneratorImpl extends GeneratorImpl implements CodeGenerator {
+
+ @Override
+ public Collection<File> generateSources(SchemaContext arg0, File arg1, Set<Module> arg2) throws IOException {
+ // TODO Auto-generated method stub
+ generate(arg0, arg1, arg2);
+ return Collections.emptySet();
+ }
+
+ @Override
+ public void setLog(Log log) {
+ // use maven logging if necessary
+
+ }
+
+ @Override
+ public void setAdditionalConfig(Map<String, String> additionalConfiguration) {
+ // no additional config utilized
+ }
+
+ @Override
+ public void setResourceBaseDir(File resourceBaseDir) {
+ // no resource processing necessary
+ }
+
+ @Override
+ public void setMavenProject(MavenProject project) {
+ // no additional information needed
+ }
+}
--- /dev/null
+package org.opendaylight.yangtools.yang.unified.doc.generator.maven;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.opendaylight.yangtools.yang2sources.spi.CodeGenerator;
+
+public class DocGenTest {
+
+ public static final String FS = File.separator;
+ static final String BASE_PKG = "org.opendaylight.yang.gen.v1";
+
+ static final String TEST_PATH = "target" + FS + "test";
+ static final File TEST_DIR = new File(TEST_PATH);
+
+ static final File GENERATOR_OUTPUT_DIR = new File(TEST_PATH);
+ static final String COMPILER_OUTPUT_PATH = TEST_PATH + FS + "bin";
+ static final File COMPILER_OUTPUT_DIR = new File(COMPILER_OUTPUT_PATH);
+
+
+ protected YangParserImpl parser;
+ protected BindingGenerator bindingGenerator;
+
+ @BeforeClass
+ public static void createTestDirs() {
+ if (TEST_DIR.exists()) {
+ deleteTestDir(TEST_DIR);
+ }
+ assertTrue(GENERATOR_OUTPUT_DIR.mkdirs());
+ assertTrue(COMPILER_OUTPUT_DIR.mkdirs());
+ }
+
+ @Before
+ public void init() {
+ parser = new YangParserImpl();
+ bindingGenerator = new BindingGeneratorImpl();
+ }
+
+ @Test
+ public void testListGeneration() throws Exception {
+ final List<File> sourceFiles = getSourceFiles("/doc-gen");
+ final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
+ final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
+ final CodeGenerator generator = new DocumentationGeneratorImpl();
+ generator.generateSources(context, GENERATOR_OUTPUT_DIR, modulesToBuild);
+
+
+ }
+
+ static List<File> getSourceFiles(String path) throws FileNotFoundException {
+ final String resPath = DocGenTest.class.getResource(path).getPath();
+ final File sourcesDir = new File(resPath);
+ if (sourcesDir.exists()) {
+ final List<File> sourceFiles = new ArrayList<>();
+ final File[] fileArray = sourcesDir.listFiles();
+ if (fileArray == null) {
+ throw new IllegalArgumentException("Unable to locate files in " + sourcesDir);
+ }
+ sourceFiles.addAll(Arrays.asList(fileArray));
+ return sourceFiles;
+ } else {
+ throw new FileNotFoundException("Testing files were not found(" + sourcesDir.getName() + ")");
+ }
+ }
+
+
+ static void deleteTestDir(File file) {
+ if (file.isDirectory()) {
+ File[] filesToDelete = file.listFiles();
+ if (filesToDelete != null) {
+ for (File f : filesToDelete) {
+ deleteTestDir(f);
+ }
+ }
+ }
+ if (!file.delete()) {
+ throw new RuntimeException("Failed to clean up after test");
+ }
+ }
+}
--- /dev/null
+module network-topology {
+ yang-version 1;
+ namespace "urn:TBD:params:xml:ns:yang:network-topology";
+ // replace with IANA namespace when assigned
+ prefix "nt";
+
+ organization "TBD";
+
+ contact "WILL-BE-DEFINED-LATER";
+/*
+ description
+ "This module defines a model for the topology of a network.
+ Key design decisions are as follows:
+ A topology consists of a set of nodes and links.
+ Links are point-to-point and unidirectional.
+ Bidirectional connections need to be represented through
+ two separate links.
+ Multipoint connections, broadcast domains etc can be represented
+ through a hierarchy of nodes, then connecting nodes at
+ upper layers of the hierarchy.";
+*/
+ revision 2013-07-12 {
+ description
+ "Initial revision.";
+ }
+
+ typedef topology-id {
+ type string;
+ description
+ "An identifier for a topology.";
+ }
+
+ typedef node-id {
+ type string;
+ description
+ "An identifier for a node in a topology.
+ The identifier may be opaque.
+ The identifier SHOULD be chosen such that the same node in a
+ real network topology will always be identified through the
+ same identifier, even if the model is instantiated in separate
+ datastores. An implementation MAY choose to capture semantics
+ in the identifier, for example to indicate the type of node
+ and/or the type of topology that the node is a part of.";
+ }
+
+ typedef link-id {
+ type string;
+ description
+ "An identifier for a link in a topology.
+ The identifier may be opaque.
+ The identifier SHOULD be chosen such that the same link in a
+ real network topology will always be identified through the
+ same identifier, even if the model is instantiated in separate
+ datastores. An implementation MAY choose to capture semantics
+ in the identifier, for example to indicate the type of link
+ and/or the type of topology that the link is a part of.";
+ }
+
+ typedef tp-id {
+ type string;
+ description
+ "An identifier for termination points on a node.
+ The identifier may be opaque.
+ The identifier SHOULD be chosen such that the same TP in a
+ real network topology will always be identified through the
+ same identifier, even if the model is instantiated in separate
+ datastores. An implementation MAY choose to capture semantics
+ in the identifier, for example to indicate the type of TP
+ and/or the type of node and topology that the TP is a part of.";
+ }
+
+ typedef tp-ref {
+ type leafref {
+ path "/network-topology/topology/node/termination-point/tp-id";
+ }
+ description
+ "A type for an absolute reference to a termination point.
+ (This type should not be used for relative references.
+ In such a case, a relative path should be used instead.)";
+ }
+ typedef topology-ref {
+ type leafref {
+ path "/network-topology/topology/topology-id";
+ }
+ description
+ "A type for an absolute reference a topology instance.";
+ }
+
+ typedef node-ref {
+ type leafref {
+ path "/network-topology/topology/node/node-id";
+ }
+ description
+ "A type for an absolute reference to a node instance.
+ (This type should not be used for relative references.
+ In such a case, a relative path should be used instead.)";
+ }
+
+ typedef link-ref {
+ type leafref {
+ path "/network-topology/topology/link/link-id";
+ }
+ description
+ "A type for an absolute reference a link instance.
+ (This type should not be used for relative references.
+ In such a case, a relative path should be used instead.)";
+ }
+
+ typedef x {
+ type binary {
+ length 5..10;
+ }
+ }
+
+ typedef y {
+ type int32 {
+ range 5..555;
+ }
+ }
+
+ grouping tp-attributes {
+ description
+ "The data objects needed to define a termination point.
+ (This only includes a single leaf at this point, used
+ to identify the termination point.)
+ Provided in a grouping so that in addition to the datastore,
+ the data can also be included in notifications.";
+ leaf tp-id {
+ type tp-id;
+ }
+ leaf-list tp-ref {
+ type tp-ref;
+ config false;
+ description
+ "The leaf list identifies any termination points that the
+ termination point is dependent on, or maps onto.
+ Those termination points will themselves be contained
+ in a supporting node.
+ This dependency information can be inferred from
+ the dependencies between links. For this reason,
+ this item is not separately configurable. Hence no
+ corresponding constraint needs to be articulated.
+ The corresponding information is simply provided by the
+ implementing system.";
+ }
+ }
+
+ grouping node-attributes {
+ description
+ "The data objects needed to define a node.
+ The objects are provided in a grouping so that in addition to
+ the datastore, the data can also be included in notifications
+ as needed.";
+ leaf node-id {
+ type node-id;
+ description
+ "The identifier of a node in the topology.
+ A node is specific to a topology to which it belongs.";
+ }
+ list supporting-node {
+ description
+ "This list defines vertical layering information for nodes.
+ It allows to capture for any given node, which node (or nodes)
+ in the corresponding underlay topology it maps onto.
+ A node can map to zero, one, or more nodes below it;
+ accordingly there can be zero, one, or more elements in the list.
+ If there are specific layering requirements, for example
+ specific to a particular type of topology that only allows
+ for certain layering relationships, the choice
+ below can be augmented with additional cases.
+ A list has been chosen rather than a leaf-list in order
+ to provide room for augmentations, e.g. for
+ statistics or priorization information associated with
+ supporting nodes.";
+ key "node-ref";
+ leaf node-ref {
+ type node-ref;
+ }
+ }
+ }
+
+ grouping link-attributes {
+ // This is a grouping, not defined inline with the link definition itself,
+ // so it can be included in a notification, if needed
+ leaf link-id {
+ type link-id;
+ description
+ "The identifier of a link in the topology.
+ A link is specific to a topology to which it belongs.";
+ }
+ container source {
+ description "XYZ";
+ leaf source-node {
+ mandatory true;
+ type node-ref;
+ description
+ "Source node identifier, must be in same topology.";
+ }
+ leaf source-tp {
+ type tp-ref;
+ description
+ "Termination point within source node that terminates the link.";
+ }
+ }
+ container destination {
+ leaf dest-node {
+ mandatory true;
+ type node-ref;
+ description
+ "Destination node identifier, must be in same topology.";
+ }
+ leaf dest-tp {
+ type tp-ref;
+ description
+ "Termination point within destination node that terminates the link.";
+ }
+ }
+ list supporting-link {
+ key "link-ref";
+ leaf link-ref {
+ type link-ref;
+ }
+ }
+ }
+
+
+ container network-topology {
+ list topology {
+ description "
+ This is the model of an abstract topology.
+ A topology contins nodes and links.
+ Each topology MUST be identified by
+ unique topology-id for reason that a network could contain many
+ topologies.
+ ";
+ key "topology-id";
+ leaf topology-id {
+ type topology-id;
+ description "
+ It is presumed that a datastore will contain many topologies. To
+ distinguish between topologies it is vital to have UNIQUE
+ topology identifiers.
+ ";
+ }
+ container topology-types {
+ description
+ "This container is used to identify the type, or types
+ (as a topology can support several types simultaneously),
+ of the topology.
+ Topology types are the subject of several integrity constraints
+ that an implementing server can validate in order to
+ maintain integrity of the datastore.
+ Topology types are indicated through separate data nodes;
+ the set of topology types is expected to increase over time.
+ To add support for a new topology, an augmenting module
+ needs to augment this container with a new empty optional
+ container to indicate the new topology type.
+ The use of a container allows to indicate a subcategorization
+ of topology types.
+ The container SHALL NOT be augmented with any data nodes
+ that serve a purpose other than identifying a particular
+ topology type.
+ ";
+ }
+ list underlay-topology {
+ key "topology-ref";
+ leaf topology-ref {
+ type topology-ref;
+ }
+ // a list, not a leaf-list, to allow for potential augmentation
+ // with properties specific to the underlay topology,
+ // such as statistics, preferences, or cost.
+ description
+ "Identifies the topology, or topologies, that this topology
+ is dependent on.";
+ }
+
+ list node {
+ description "The list of network nodes defined for the topology.";
+ key "node-id";
+ uses node-attributes;
+ must "boolean(../underlay-topology[*]/node[./supporting-nodes/node-ref])";
+ // This constraint is meant to ensure that a referenced node is in fact
+ // a node in an underlay topology.
+ list termination-point {
+ description
+ "A termination point can terminate a link.
+ Depending on the type of topology, a termination point could,
+ for example, refer to a port or an interface.";
+ key "tp-id";
+ uses tp-attributes;
+ }
+ }
+
+ list link {
+ description "
+ A Network Link connects a by Local (Source) node and
+ a Remote (Destination) Network Nodes via a set of the
+ nodes' termination points.
+ As it is possible to have several links between the same
+ source and destination nodes, and as a link could potentially
+ be re-homed between termination points, to ensure that we
+ would always know to distinguish between links, every link
+ is identified by a dedicated link identifier.
+ Note that a link models a point-to-point link, not a multipoint
+ link.
+ Layering dependencies on links in underlay topologies are
+ not represented as the layering information of nodes and of
+ termination points is sufficient.
+ ";
+ key "link-id";
+ uses link-attributes;
+ must "boolean(../underlay-topology/link[./supporting-link]";
+ // Constraint: any supporting link must be part of an underlay topology
+ must "boolean(../node[./source/source-node])";
+ // Constraint: A link must have as source a node of the same topology
+ must "boolean(../node[./destination/dest-node])";
+ // Constraint: A link must have as source a destination of the same topology
+ must "boolean(../node/termination-point[./source/source-tp])";
+ // Constraint: The source termination point must be contained in the source node
+ must "boolean(../node/termination-point[./destination/dest-tp])";
+ // Constraint: The destination termination point must be contained
+ // in the destination node
+ }
+ }
+ }
+
+ notification n1 {
+ description "This example defines a notification 1.";
+ leaf event-class {
+ type string;
+ }
+ anyxml reporting-entity;
+ container severity {
+ leaf id {
+ type string;
+ }
+ }
+ }
+
+ notification n2 {
+ description "This example defines a notification 2.";
+ leaf event-class {
+ type string;
+ }
+ anyxml reporting-entity;
+ leaf severity {
+ type string;
+ }
+ }
+
+ augment "/network-topology" {
+ anyxml any-a;
+ anyxml any-b;
+ }
+
+ augment "/network-topology/topology" {
+ description "description of augment 2";
+ reference "reference of augment 2";
+ list list-a {}
+ list list-b {
+ leaf leaf-c {
+ type string;
+ }
+ }
+ }
+
+ augment "/network-topology/topology/topology-types" {
+ container container-c {
+ leaf id {
+ type binary;
+ }
+ }
+ }
+
+ rpc rock-the-house {
+ input {
+ leaf zip-code {
+ type string;
+ }
+ }
+ output {
+ leaf number {
+ type int32;
+ }
+ }
+ }
+
+ extension c-define {
+ description
+ "Takes as argument a name string.
+ Makes the code generator use the given name in the
+ #define.";
+ argument "name";
+ }
+
+}
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>model-ietf</artifactId>
<build>
<plugins>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>0.5.9-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <yangFilesRootDir>src/main/yang</yangFilesRootDir>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+ <outputBaseDir>target/generated-sources/sal</outputBaseDir>
+ </generator>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl</codeGeneratorClass>
+ <outputBaseDir>target/generated-sources/site</outputBaseDir>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>true</inspectDependencies>
+ </configuration>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>maven-sal-api-gen-plugin</artifactId>
+ <version>0.6.0-SNAPSHOT</version>
+ <type>jar</type>
+ </dependency>
+ </dependencies>
+ </plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
</plugin>