diff --git a/jnc/doc/juniper-example.md b/jnc/doc/juniper-example.md new file mode 100644 index 0000000..4f42079 --- /dev/null +++ b/jnc/doc/juniper-example.md @@ -0,0 +1,45 @@ +How to use this code to create Java class for Juniper? + +Assuming +pyang is installed in ~/projects/pyang-pyang-2.1 folder. +Netconf-Async is in ~/projects/Netconf-Async + +a) Go to pyang install root ~/projects/pyang-pyang-2.1 +b) Source env + +``` +source ./env.sh +``` +c) Now you can run pyang to make sure its function. If not then fix that. + +``` +pyang -h +``` + +d) +get Juniper yang files: + +``` +mkdir ~/projects/juniper +cd ~/projects/juniper +git clone https://github.com/Juniper/yang.git +``` + +e) Now go to Netconf-Async folder + +``` +cd ~/projects/Netconf-Async +``` + +f) Execute java code genaration using a command similar to shown below: + +``` +developer@rapti:~/projects/Netconf-Async$ pyang --jnc-no-pkginfo --lax-quote-checks --plugindir jnc -f jnc --jnc-output src/org/himalay/juniper -p /home/developer/projects/juniper/yang/17.3/17.3R1/common --dsdl-no-documentation /home/developer/projects/juniper/yang/17.3/17.3R1/junos-es/configuration.yang +``` + +if you need to generate package info then remove --jnc-no-pkginfo. Generated package info and schema has one character per line which is not good. This can be fixed using following command: + +``` +find src/org/himalay/juniper -name package-info.java -exec sed -z -r -i 's/([^\n])\n/\1/g' {} \; +find src/org/himalay/juniper -name *.schema -exec sed -z -r -i 's/([^\n])\n/\1/g' {} \; +``` diff --git a/jnc/jnc.py b/jnc/jnc.py index 72b7d86..0a078fc 100644 --- a/jnc/jnc.py +++ b/jnc/jnc.py @@ -340,10 +340,10 @@ def print_help(self): 'PathCreate', 'Prefix', 'PrefixMap', 'RevisionInfo', 'RpcError', 'SchemaNode', 'SchemaParser', 'SchemaTree', 'SSHConnection', 'SSHSession', 'Tagpath', 'TCPConnection', - 'TCPSession', 'Transport', 'Utils', 'XMLParser', + 'TCPSession', 'Transport', 'TypedElementChildrenIterator', 'Utils', 'XMLParser', 'YangBaseInt', 'YangBaseString', 'YangBaseType', 'YangBinary', 'YangBits', 'YangBoolean', 'YangDecimal64', 'YangElement', - 'YangEmpty', 'YangEnumeration', 'YangException', + 'YangEmpty', 'YangInstanceIdentifier','YangEnumeration', 'YangException', 'YangIdentityref', 'YangInt16', 'YangInt32', 'YangInt64', 'YangInt8', 'YangLeafref', 'YangString', 'YangType', 'YangUInt16', 'YangUInt32', 'YangUInt64', 'YangUInt8', @@ -1005,12 +1005,12 @@ def generate_classes(self): # Namespace and prefix ns_arg = search_one(self.stmt, 'namespace').arg prefix = search_one(self.stmt, 'prefix') - + # Add root to class_hierarchy dict if self.rootpkg not in class_hierarchy: class_hierarchy[self.rootpkg] = set([]) class_hierarchy[self.rootpkg].add(self.n) - + # Add all classes that will be generated to class_hierarchy dict def record(stmt, package): for ch in search(stmt, yangelement_stmts): @@ -1949,7 +1949,7 @@ def fix_imports(self, method, child=False): imports.add('.'.join([self.pkg, import_])) else: imports.add(import_) - + for dependency in imports: if dependency.startswith(('java.math', 'java.util', @@ -2250,14 +2250,15 @@ def child_iterator(self): ' "', self.stmt.arg, '".'])) res.add_javadoc(''.join(['@return An iterator for the ', self.stmt.keyword, '.'])) - return_stmt = ['return new Element'] if self.is_leaflist: + return_stmt = ['return new Element'] res.set_return_type('ElementLeafListValueIterator') return_stmt.append('LeafListValue') + return_stmt.extend(['Iterator(children, "', self.stmt.arg, '");']) else: # List - res.set_return_type('ElementChildrenIterator') - return_stmt.append('Children') - return_stmt.extend(['Iterator(children, "', self.stmt.arg, '");']) + return_stmt = ['return new '] + res.set_return_type('TypedElementChildrenIterator<'+self.n+'>') + return_stmt.extend(['TypedElementChildrenIterator<'+self.n+'>(children, "', self.stmt.arg, '");']) res.add_line(''.join(return_stmt)) return self.fix_imports(res) @@ -2644,7 +2645,7 @@ def constructors(self): constructor.add_line(''.join(smap)) constructor.add_line(''.join(imap)) constructor.add_line(');') - + # Add call to check method if type has constraints if self.needs_check: constructor.add_line('check();') diff --git a/jnc/jnc/src/main/java/com/tailf/jnc/TypedElementChildrenIterator.java b/jnc/jnc/src/main/java/com/tailf/jnc/TypedElementChildrenIterator.java new file mode 100644 index 0000000..a87a7dd --- /dev/null +++ b/jnc/jnc/src/main/java/com/tailf/jnc/TypedElementChildrenIterator.java @@ -0,0 +1,102 @@ +package com.tailf.jnc; + + +import java.util.Iterator; + +public class TypedElementChildrenIterator implements Iterator { + + private Iterator childrenIterator; + private Element nextChild; + private boolean hasNextChild = false; + private final String name; + + /** + * Constructor to create new children iterator for all children. + */ + public TypedElementChildrenIterator(NodeSet children) { + if (children != null) { + childrenIterator = children.iterator(); + } else { + childrenIterator = null; + } + name = null; + } + + /** + * Constructor to create a new children iterator for children of a specific + * name. + */ + public TypedElementChildrenIterator(NodeSet children, String name) { + if (children != null) { + childrenIterator = children.iterator(); + } else { + childrenIterator = null; + } + this.name = name; + } + + /** + * @return true if there are more children; + * false otherwise. + */ + @Override + public boolean hasNext() { + if (hasNextChild) { + return true; + } + if (childrenIterator == null) { + return false; + } + while (childrenIterator.hasNext()) { + if (name == null) { + return true; + } + final Element child = childrenIterator.next(); + if (child.name.equals(name)) { + hasNextChild = true; + nextChild = child; + return true; + } + } + hasNextChild = false; + return false; + } + + /** + * Iterates the Node set. + * + * @return next element with this.name in set or null if none. + */ + public T nextElement() { + if (hasNextChild) { + hasNextChild = false; + return (T) nextChild; + } + while (childrenIterator.hasNext()) { + final T child = (T)childrenIterator.next(); + if (name == null) { + return child; + } else if (child.name.equals(name)) { + return child; + } + } + return null; + } + + /** + * Iterates the Node set. + * + * @return next element with this.name in set or null if none. + */ + @Override + public T next() { + return nextElement(); + } + + /** + * Remove is not supported. + */ + @Override + public void remove() { + } +} diff --git a/jnc/jnc/src/main/java/com/tailf/jnc/YangInstanceIdentifier.java b/jnc/jnc/src/main/java/com/tailf/jnc/YangInstanceIdentifier.java new file mode 100644 index 0000000..ca43689 --- /dev/null +++ b/jnc/jnc/src/main/java/com/tailf/jnc/YangInstanceIdentifier.java @@ -0,0 +1,15 @@ +package com.tailf.jnc; + +public class YangInstanceIdentifier extends YangBaseString{ + /** + * + */ + private static final long serialVersionUID = 4335565686368455056L; + String value; + + public YangInstanceIdentifier(String value) throws YangException { + super(value); + + } + +}