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類型。
未完待續……