Chapter 4 PGML / PUML
4.2 PGML – Pervasive loGic Markup Language
4.2.4 PGML 標準函式庫
在制定PGML 的標準函式庫(PGML Standard Library)上,目前是針對三個資 料型態(boolean、int、String)來制定,主要是提供型別轉換以及各型別專屬 的函式(functions)。在標準函式庫中,我們將所有的函式分成三大類:(1) Integer (2) String (3) Boolean。
在以後,若有需要的話,可以新增標準函式庫裡的分類或是函式。每個人也 可以制定屬於自己的函式庫(library)。因為,只要能將函式庫相對應的 XSLT style sheet 撰寫好,經過轉換機制轉換之後,就能夠轉換為各種可以在行動 執行環境上執行的程式語言了。
表4-2 為 PGML 的標準函式庫(PGML Standard Library)的整理:
[表 4-2 PGML 標準函式庫說明]
Function Description Interger
toString 將整數值轉換成相對應的字串。例如:
1234 Æ “1234”。
Abs 取得整數的絕對值。
Max 取得兩個整數中的最大值。
Min 取得兩個整數中的最小值。
maxInt 取得系統所支援的整數最大值。
minInt 取得系統所支援的整數最小值。
String
parseInt 將 字 串 轉 換 成 相 對 應 的 整 數 值 。 例
如:”1234” Æ 1234。
charAt 取得字串中某個位置的單一字元。(在
PGML 中,把單一字元當長度為 1 的字串 處理)。
compare 按照一般程式語言比較字串的方式比較
兩個字串。
Length 取得字串的長度。
substring 取得字串中的子字串。
Trim 刪除字串頭尾的空白字元。
concat 將兩個字串連接成一個字串。
Booelan
toString 將布林值轉換成相對應的字串。例如:true Æ “true”。false Æ”false”。
4.2.5 PGML 範例 A. PGML
文件結構基本上,如果使用過其他任何一種程式語言的話,要撰寫 PGML 文件並不 難,也可以說是很容易上手。因為在描述邏輯運算的概念上,PGML 和其他 的程式語言並沒有什麼不同。唯一不同的是,因為PGML 是以 XML 為基礎 (XML-based)的描述方法,所以使用 PGML 來描述邏輯運算時,同時也是在 撰寫 XML 文件,所以必須遵守 XML 的規範,必須使用標籤(tag)的方式來 做邏輯運算的描述,除此之外,並沒有什麼不同了。
在觀念上,只需將一份 PGML 文件視為一個物件(object),而這個物件可以 提供 methods 出來使用,而所有的邏輯運算都在 method 裡頭做描述即可。
也就是說,對於PUML(Pervasive User-interface Markup Language,用來描述 行動應用程式中,使用者介面的描述語言)文件來說,只需要知道這個物件 (即 PGML 文件)所提供出來的 methods(或是稱為介面,interface)即可。
再來,簡單介紹一下PGML 文件結構的骨架。
PGML 的 root element (document element)為<object>,<object>包含兩種 child element,分別為<declaration>和<method>。在<object>的 element content 中 最多只能有一個<declaration>,最少一個<method>。而其他之前提到的 elements 則是放在<declaration>和<method>的 element content 中,做邏輯運 算描述用的。每種elements 的詳細用法及說明,請參考表 4-1 和本論文中的 範例。
以下為PGML 文件結構的示意圖(圖 4-1):
<?xml version="1.0"?>
<object name="..." version="1.0"
xmlns="http://dcsw3.cis.nctu.edu.tw/Project/Pervasive/PGML/">
<declaration>
...
<declaration>
<method name="..." return-type="...">
...
</method>
<method name="...">
...
</method>
...
</object>
[圖 4-1 PGML 文件結構示意圖]
B.
簡單的範例用PGML 寫個簡單的邏輯運算描述,如下(圖 4-2):
<?xml version="1.0"?>
<object name=“Increase5" version="1.0"
xmlns="http://dcsw3.cis.nctu.edu.tw/Project/Pervasive/PGML/">
<declaration>
<variable type=“int” name=“result” value=“0”/>
<declaration>
<method name=“incFive" visibility=“public” return-type=“int">
<in>
<variable type=“int” name=“num”/>
</in>
<action>
<add result=“result”>
<operand type=“int” value=“5”/>
<operand select=“num”/>
</add>
<return select=“result”/>
</action>
</method>
</object>
[圖 4-2 PGML 簡單範例]
這個例子是描述一個名為Increase5 的物件,提供了一個 method – incFive。
呼叫這個 method 之後,便會將傳入值加五之後回傳。相對應的 J2ME 程式 碼如下(圖 4-3):
public class Increase5{
int result = 0;
public int IncFive(int num){
result = 5 + num;
return this.result;
} }
[圖 4-3 PGML 簡單範例的相對應 J2ME 程式碼]
C.
複雜的範例使用 PGML 做一個比較複雜的邏輯運算的描述。在這個例子(圖 4-4)中,
PGML 的 描 述 採 取 類 似 Java Bean 的 做 法 : 在 一 開 始 , 宣 告 了 兩 個 properties(兩個全域變數) – userName 和 userPassword。隨後描述了兩個 set methods 和兩個 get methods,分別是 setUserName( )、setUserPassword( )、
getUserName( )以及 getUserPassword( )四個 methods。
<?xml version="1.0"?>
<object name="UserInfo" version="1.0"
xmlns="http://dcsw3.cis.nctu.edu.tw/Project/Pervasive/PGML/">
<declaration>
<variable type="String" name="userName" value=""/>
<variable type="String" name="userPassword" value=""/>
</declaration>
<method name="setUserName" visibility="public" return-type="void">
<in>
<variable type="String" name="user_name"/>
</in>
<action>
<assign arg1="userName" arg2="user_name"/>
</action>
</method>
<method name="setUserPassword" visibility="public" return-type="void">
<in>
<variable type="String" name="passwd"/>
</in>
<action>
<assign arg1="userPassword" arg2="passwd"/>
</action>
</method>
<method name="getUserName" visibility="public" return-type="String">
<action>
<return select="userName"/>
</action>
</method>
<method name="getUserPassword" visibility="public" return-type="String">
<action>
<return select="userPassword"/>
</action>
</method>
</object>
[圖 4-4 PGML 複雜的範例]
這個PGML 範例經過 XSLT 的轉換機制轉換之後,所產生的 J2ME 程式碼 (圖 4-5)以及 WMLScript 程式碼(圖 4-6)分別如下:
/*J2ME "import" declarations*/
public class UserInfo {
/*global varibales' declaration*/
private String userName="";
private String userPassword="";
/*constructor*/
public UserInfo(){}
/*all methods are here...*/
public void setUserName( String user_name ){
/*local variables' declaration*/
this.userName=user_name;
}
public void setUserPassword( String passwd ){
/*local variables' declaration*/
this.userPassword=passwd;
}
public String getUserName( ){
/*local variables' declaration*/
return this.userName;
}
public String getUserPassword( ){
/*local variables' declaration*/
return this.userPassword;
} }
[圖 4-5 轉換之後所產生的 J2ME 程式碼(經過排版)]
/*some pragma are declared here...*/
/*WMLScript interface to set declared global variables*/
extern function globalVarDeclaration() {
/*setting all global varibales in this logic object*/
WMLBrowser.setVar("UserInfo_userName", "");
WMLBrowser.setVar("UserInfo_userPassword", "");
}
/*all methods are here...*/
extern function setUserName (user_name){
WMLBrowser.setVar("UserInfo_userName", user_name ); } extern function setUserPassword (passwd){
WMLBrowser.setVar("UserInfo_userPassword", passwd ); } extern function getUserName (){
return WMLBrowser.getVar("UserInfo_userName"); } extern function getUserPassword (){
return WMLBrowser.getVar("UserInfo_userPassword"); } /*WMLScript interface to change value of UI component on some WML card*/
extern function change(component, newValue, callMethod){
if(callMethod == ""){
WMLBrowser.setVar(component, newValue); } else{
if(callMethod == "getUserName"){
WMLBrowser.setVar(component, getUserName()); }
if(callMethod == "getUserPassword"){
WMLBrowser.setVar(component, getUserPassword()); } }
}
[圖 4-6 轉換之後所產生的 WMLScript 程式碼(經過排版)]