OpenDaylight中的YANG Tools,为使用YANG提供了一组支撑工具(库)。主要功能包括将YANG模型转译为JAVA代码,含将YANG模型转译为标准化节点的方式(类DOM树模型)和Java Binding方式。并提供了YANG数据模型与XML、JSON,以及Java Binding与标准节点格式间的序列化和反序列化支持。其包括的YANG Maven Plugin所实现的Maven插件,可以在Maven构建生命周期中,基于YANG数据模型为其它组件生成Java代码(框架)。
YANG与JAVA的映射规则
一般转换规则
下面我们通过一个例子来说明YANG与Java代码的一般转换规则,YANG文件如下所示:
module helloworld {
yang-version 1;
namespace "urn:2:case:module:helloworld";
prefix helloworld;
revision "2016-09-06"{}
container cont {
container cont-inner {}
list outter-list {
list list-in-list{
}
}
leaf str {type string;}
leaf boo {type boolean;}
}
container example-name_without_capitalization {}
}
上述YANG模型经过YANG Tools的转译后,生成如下的JAVA代码目录:
- org.opendaylight.yang.gen.v1.urn._2._case.module.helloworld.rev160609
- Cont.java
- ContBuilder.java
- ExampleNameWithoutCapitalization.java
- ExampleNameWithoutCapitalizationBuilder.java
- HelloworldData.java
- org.opendaylight.yang.gen.v1.urn._2._case.module.helloworld.rev160609.cont
- ContInner.java
- ContInnerBuilder.java
- OutterList.java
- OutterListBuilder.java
- org.opendaylight.yang.gen.v1.urn._2._case.module.helloworld.rev160609.cont.outter.list
- ListInList.java
- ListInListBuilder.java
Java package
首先来看下最外层的包名org.opendaylight.yang.gen.v1.urn._2._case.module.helloworld.rev160609
是怎么来的。可以将该包名分为四个部分:
1. OpenDaylight固定前缀:org.opendaylight.yang.gen.v
2. Java Binding Version:指定的YANG Java Binding版本号,当前该版本号为1
3. Namespce:由YANG文件中对应的namespace值urn:2:case:module:helloworld
转换而来,不过例子中的是urn._2._case.module.helloworld
,和YANG的namespace不一样,这个后面会说为什么不一样。
4. Revision:由前缀rev
和YANG文件中的revision
的值组成。
根据上面的4个规则拼接出包名后,还要进行一次非法词/字符的替换工作。包名不允许包含Java关键,或以数字开头。如果有会在这些词之前加下划线。会被加下划线的关键字有:
abstract, assert, boolean, break, byte, case, catch, char, class, const, continue, default, double, do, else, enum, extends, false, final, finally, float, for, goto, if, implements, import, instanceof, int, interface, long, native, new, null, package, private, protected, public, return, short, static, strictfp, super, switch, synchronized, this, throw, throws, transient, true, try, void, volatile, while
除了最外层的package外,从上例中可以看到还有两个子package:.cont
和.cont.outter.list
。这些包是由特定的YANG语句生成的,这些语句通常是一些容器,如container、list。这些容器在其父语句所生成的interface中,不仅会被映射成Java的setter方法,也会生成相应的package。该package由父语句生成的package名,加上所声明的名称衔接组成。
例子中的org.opendaylight.yang.gen.v1.urn._2._case.module.helloworld.rev160609
包括了module语句的直接子语句。org.opendaylight.yang.gen.v1.urn._2._case.module.helloworld.rev160609.cont
包括了container cont的子语句。org.opendaylight.yang.gen.v1.urn._2._case.module.helloworld.rev160609.cont.outter.list
包括了list outter-list的子语句。例子中的ContInner.java
和OutterList.java
则分别对应container cont-inner和list outter-list的interface。
类和接口名
YANG语句映射为Java class和interface时,转换规则如下:首先将YANG名字前后的空格去掉;接着删除如空格字符、”-“、“`”等字符,且将紧跟着的字符转为大写;最后将名字首字母转为大写。如例子YANG文件中的example-name_without_capitalization
生成的interface命名为ExampleNameWithoutCapitalization
Getter和Setter
一些情况下,YANG语句会被转为getter和setter方法,如例子中生成的Cont.java中的代码:
ContInner getContInner();
List<OutterList> getOutterList();
java.lang.String getStr();
java.lang.Boolean isBoo();
getter的转换过程:
1. 如上文所提的,将YANG名字转换为Java类名格式的名字;
2. 名字前加get
作为前缀,如果结果类型是Bolean,会使用is
替换get
作为前缀。
3. getter方法的返回类型被设置为子语句对应的Java类型。
setter的转换过程:
1. 如上文所提的,将YANG名字转换为Java类名格式的名字;
2. 增加前缀set
3. 将元素的名字转换为Java参数格式的名字作为入参。
4. 返回值设置为相应的builder类型。
未完待续……