:::

CentOS安裝Xpdf教學

布丁布丁吃布丁

CentOS安裝Xpdf教學

image

Xpdf是Linux中可以讀取PDF檔案的開放原始碼程式,我引用一下Wikipedia的詳細介紹:

Xpdf 是一個開放原始碼PDF檔案瀏覽器,此軟體運行於X Window以及Motif上。 Xpdf 也實際運行於所有類Unix作業系統上。Xpdf 可解碼LZW壓縮格式並閱讀加密的PDF文件。官方版本的Xpdf遵循PDF檔案的智慧財產權政策,因此可能禁止拷貝、列印或轉換的功能。當然有某些破解補丁可以忽略這些智慧財產管理限制。

Xpdf包含數項不需要X windows系統的程式,包含了解析PDF的圖檔以及將PDF轉檔成文字檔或PostScript的程式。

Xpdf也被其他PDF瀏覽程式用於前端,例如KPDF(一個運行在KDE桌面的程式)。而它的文字引擎則被許多PDF瀏覽程式運用,例如BeOS上的BePDF、RISCOS上的!PDF以及Palm OS上的PalmPDF。

Poppler以xpdf 3.0的繪圖函式庫為基礎創造出來,以便增加其再用性。許多程式(包括Xpdf自己)可使用poppler為它們的後端繪圖器。

來源:Xpdf - 維基百科,自由的百科全書,http://zh.wikipedia.org/wiki/Xpdf

Xpdf很重要的功能在於「從PDF轉成文字檔」,這可以取代DSpace原本使用PDFbox的缺點:PDFbox不支援Acrobat 9的PDF檔案。

在一篇網路上到處轉載的「JAVA抽取WORD和PDF格式文件的四种武器」當中也有介紹到Xpdf,但並沒有很詳盡的安裝方法。所以這一篇主要是來教大家怎麼在Linux,特別是在CentOS當中安裝Xpdf。


Xpdf可以利用rpm來安裝,而相依套件的部份我們則是用yum來安裝。

1. 安裝Xpdf的相依套件

請以root的身份輸入以下指令:

[root@dspace ~]# yum install -y openmotif libpaper poppler-utils xdg-utils

2. 下載Xpdf的rpm檔案並安裝

Xpdf沒有提供rpm,但我們可以在RPM pbone.net找到Xpdf的rpm安裝檔。網頁位置在這裡,其中一個載點請點此下載,另外我準備了SkyDrive備份。

確定你存放的位置之後,請以root的身份輸入以下指令:.

[root@dspace ~]# rpm -ivh xpdf-3.02-5.el5.1.i386.rpm

如果沒有錯誤訊息,表示安裝成功。

3. 安裝語系檔

請先下載以下語系檔,或是下載我在SkyDrive的語系檔備份

如果你下載我備份的壓縮檔,請依照以下指令來解壓縮並安裝。

[root@dspace ~]# unzip xpdf-language-i386.zip -d lang
[root@dspace ~]# rpm –ivh lang/xpdf-*.rpm --force

4. 使用Xpdf的pdftotext來抽取PDF的文字檔

讓我們試著將一個PDF檔案中的文字抽取成txt文字檔吧。

  1. 請下載PDF檔案:「Chen, A Study on Knowledge Extraction from User Reading Annotation of Digital Library.pdf」(其實這是我的論文計畫書初稿XD)。
  2. 放到伺服器中的位置,你知道的地方即可。
  3. 執行pdftotext指令與檔名,如下:
  4. [root@dspace ~]# pdftotext Chen\,\ A\ Study\ on\ Knowledge\ Extraction\ from\ User\ Reading\ Annotation\ of\ Digital\ Library.pdf
  5. 此時應該會有同樣檔名,但是副檔名為.txt的檔案產生。結果應該跟這個檔案一樣,下圖中,左邊是PDF原稿,右邊則是抽取出來的文字檔!image

這樣就安裝完成囉。此外,上面安裝過語系檔的檔案也全都可以如法炮製地抽取出文字檔,Xpdf非常地強大!


本篇教學是為了擴增DSpace的Media-filter而鋪路,我現在正要把Xpdf跟DSpace整合,讓DSpace全文搜尋功能更為完整。

(more...)

橫跨政大景美溪對岸堤防

布丁布丁吃布丁

橫跨政大景美溪對岸堤防

image

聽說政大有列出十條必走不可的路,可是對我來說,其實最想要走的一條路,就在政大過景美溪對岸的河堤。每次傍晚經過的時候,都可以看到好多人悠閒地散步、騎腳踏車,昏黃的夕陽與路燈之下交織出一種幸福的景色。

今天晚餐難得一個人下山吃飯,也沒有特別要再上山回實驗室,剛好趁著吃飽飯要回宿舍的機會,來走走看這條路線吧!

2009-06-23-013

上道南橋的樓梯在那邊,平常只有到對面吃日本料裡的時候才會走的路呢。

2009-06-23-014

狹窄的樓梯,還碰到一對情侶剛好要下來,就先讓他們過吧。

2009-06-23-015

道南橋上一景,平常我會在右邊的道路上騎車,今天則是走旁邊的人行道。

2009-06-23-016

從道南橋上遠眺政大。

2009-06-23-019

回頭看看道南橋,車子好多喔。

2009-06-23-018

這就是待會要走的堤岸,要走上面還是下面好呢?

2009-06-23-020

從橋上是直接接到上面的河堤,那就走這邊吧。要開始囉~

2009-06-23-021

馬上就在路口出發現了一個神秘的石碑!「木柵舊址」,原來木柵以前真的有柵欄,只是不知道什麼時候拆掉了。

2009-06-23-024

因為越來越晚了,如果不找些有光源的地方照,憑手機相機拍起來還真的會什麼都看不到。我指的光源是指路燈,並不是指路邊座椅上正在親密聊天的情侶喔。

2009-06-23-023

回頭看看,那個方形的建築物是管制設施,頗神秘。

2009-06-23-025

走到一半,看到了樓梯,來下去走走吧!

2009-06-23-026

景美溪河岸有籃球場、散步道與腳踏車道路,可惜太暗了什麼都看不清楚。

2009-06-23-027 2009-06-23-028

發現了「渡船頭」!上面還有指出東西南北方位,各以一個景點作為代表:北—陽明山花季、南—林家花園、西—忘了(喂~)、東—貓空採茶。

2009-06-23-031

然後,我跑去景美溪踏水了!穿著涼鞋,感受溪水從腳底下不斷流過的清涼感,以及在水中舉步維艱的阻力,真的很讓人開心!

好像是有個挖土機在鏟土,留下了一條到溪邊的道路,我才能順利下去,不然其他用水泥建好的道路幾乎都被雜草擋住了。可惜景美溪又深又廣,一不小心腳滑還可能就上演溪中游泳的戲碼,只好踏踏水就上來。不過不禁感慨到,還好現在有道南橋了,不然要靠船送東西還真的很麻煩耶。

2009-06-23-032

舉頭看看政大藝文中心,還真的很大一棟。

2009-06-23-033 

2009-06-23-034

繼續往 下走吧,天已經暗到拍照只能拍到遠方的路燈了。

 2009-06-23-035

又發現了一處可以靠近溪邊道路,只是這邊的水深已經不是可以下去踏踏的程度了。

2009-06-23-037

恆光橋下小公園,許多老人、小孩在此處聊天、嬉戲。可以明顯地發現這邊沒什麼年輕人(汗

2009-06-23-038

2009-06-23-039 

恆光橋對面就是大大的「國立政治大學」六個字。

2009-06-23-040

上恆光橋吧!

2009-06-23-043

回頭來看看政大與剛剛走過的路,雖然是幾乎看不太到啦。

2009-06-23-041

終點就在橋的對岸,回宿舍囉!


這樣逛啊逛的也花去了一個多小時的時間,而我又對政大的景色有更多的認識。至於照片太過模糊、雜訊過多的問題,就不要勉強手機相機了吧,他已經盡力囉。

好啦,回到宿舍就繼續工作吧,加油!

(more...)

DSpace Input-type新增taiwanaddress

布丁布丁吃布丁

DSpace Input-type新增taiwanaddress

2009-06-15_000205

為了因應臺灣的地址,我開發了一個TaiwanAddress的input-type,可以在選擇縣市之後,由程式自動帶入郵遞區號前三碼。

這個程式我也寫成jQuery的plugin,只要引入之後以jQuery(selecotr).taiwanAddress()就可以使用。

由於最近修改程式碼的頻率頻繁,故不提供檔案,而是以指示的方式教你安裝這些功能。以下是安裝與使用教學:


檔案下載

請下載以下檔案,並擺到下述的指定位置:

修改遞交作業

本步驟有兩個檔案必需要修改。

修改edit-metadata.jsp

edit-metadata.jsp是遞交作業中填寫metadata使用的JSP檔案。

如果你修改過edit-metadata.jsp的話,你應該要在[dspace-source]/dspace/modules/jspui/src/main/webapp/submit/edit-metadata.jsp找到該檔案,否則請到[dspace-source]/dspace-jspui/dspace-jspui-webapp/src/main/webapp/submit/edit-metadata.jsp找到該檔案。

請依照以下指示修改程式碼:

插入doTaiwanAddress函式

請找到「do」開頭函式的最後一個,如果你安裝過我之前介紹的DSpace新增input-type,那麼可以找到「}    //void doXMLMetadata()」,請在後面插入以下程式碼:

    void doTaiwanAddress(javax.servlet.jsp.JspWriter out, Item item,
      String fieldName, String schema, String element, String qualifier, boolean repeatable,
      int fieldCountIncr, String label, PageContext pageContext, String vocabulary, boolean closedVocabulary) 
      throws java.io.IOException 
    {

      DCValue[] defaults = item.getMetadata(schema, element, qualifier, Item.ANY);
      int fieldCount = defaults.length + fieldCountIncr;
      StringBuffer sb = new StringBuffer();
      String val;

      if (fieldCount == 0)
         fieldCount = 1;

      for (int i = 0; i < fieldCount; i++) 
      {
	 if (i == 0) 
	    sb.append("<tr><td class=\"submitFormLabel\">")
	      .append(label)
	      .append("</td>");
	 else
	    sb.append("<tr><td>&nbsp;</td>");

         if (i < defaults.length)
           val = defaults[i].value.replaceAll("\"", "&quot;");
         else
           val = "";

         sb.append("<td colspan=\"2\"><input type=\"text\" name=\"")
           .append(fieldName);
         if (repeatable && i>0)
           sb.append("_").append(i);
         
         sb.append("\" size=\"50\" value=\"")
           .append(val +"\"")
           .append(hasVocabulary(vocabulary)&&closedVocabulary?" readonly=\"readonly\" ":"")
	   	.append("   />")
	   .append(doControlledVocabulary(fieldName + (repeatable?"_" + i:""), pageContext, vocabulary))
	   .append("<script type=\"text/javascript\">" + "\n")
		.append("jQuery(document).ready(function () {" + "\n")
		.append("jQuery(\"input[name=\'")
		.append(fieldName);
		if (repeatable && i>0)
           sb.append("_").append(i);
		sb.append("\']\").taiwanAddress();" + "\n")
		.append("});" + "\n")
	   .append("</script>")
	   .append("</td>\n");
	   

	 if (repeatable && i < defaults.length) 
	 {
	    // put a remove button next to filled in values
	    sb.append("<td><input type=\"submit\" name=\"submit_")
	      .append(fieldName)
	      .append("_remove_")
	      .append(i)
//	      .append("\" value=\"Remove This Entry\"/> </td></tr>");
	      .append("\" value=\"")
   	      .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove"))
   	      .append("\"/> </td></tr>");
	 } 
	 else if (repeatable && i == fieldCount - 1) 
	 {
	    // put a 'more' button next to the last space
	    sb.append("<td><input type=\"submit\" name=\"submit_")
	      .append(fieldName)
//	      .append("_add\" value=\"Add More\"/> </td></tr>");
	      .append("_add\" value=\"")
	      .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.add"))
	      .append("\"/> </td></tr>");
	 } 
	 else 
	 {
	    // put a blank if nothing else
	    sb.append("<td>&nbsp;</td></tr>");
	 }
      }

      out.write(sb.toString());
    }

引用jquery-plugin-taiwan-address.js

找到引用JavaScript與CSS的地方,在「<link rel="stylesheet" href="<%= request.getContextPath() %>/extension/xmlmetadata/dspace-inputtype-xml.css" type="text/css" media="screen">」之後插入以下程式碼:

<script type="text/javascript" src="<%= request.getContextPath() %>/extension/taiwan-address/jquery-plugin-taiwain-address.js"></script>

插入選擇使用doTaiwanAddress

最後找到以下程式碼:

								else if (inputType.equals("xmlmetadata")) 
								{
									pageContent.append(doXMLMetadata(out, item, fieldName, dcSchema, dcElement, dcQualifier, 
											  repeatable, fieldCountIncr, label, pageContext, vocabulary,
											  closedVocabulary, workspaceItemID, 
											  nonInternalBistreamsID, hasMultipleFiles, defaultValue, 
											  request.getContextPath()));
								} 

在這之後插入以下程式碼:

								else if (inputType.equals("taiwanaddress")) 
								{
									pageContent.append(doTaiwanAddress(out, item, fieldName, dcSchema, dcElement, dcQualifier, 
										repeatable, fieldCountIncr, label, pageContext, vocabulary, 
										closedVocabulary));	
								}
修改DescribeStep.java

DescribeStep.java是遞交作業中儲存資料時使用的檔案。

DescribeStep.java的位置在[dspace-source]/dspace-api/src/main/java/org/dspace/submit/step/DescribeStep.java

請找到以下程式碼:(如果增加過input-type,那這邊應該也會有所改變)

            else if ((inputType.equals("onebox"))
                    || (inputType.equals("twobox"))
                    || (inputType.equals("textarea"))

請多加一個條件式如下:

					|| (inputType.equals("taiwanaddress"))

修改完畢之後,必須將DSpace重新編譯,方能生效。

2009-06-15_010334

修改edit-item-form.jsp

edit-item-form.jsp是修改文件時使用的JSP檔案。

你必須先確認你之前安裝過我寫的DSpace擴增文件編輯功能,你才能夠繼續安裝以下功能。

如果你修改過edit-item-form.jsp的話,你應該要在[dspace-source]/dspace/modules/jspui/src/main/webapp/tools/edit-item-forms.jsp找到該檔案,否則請到[dspace-source]/dspace-jspui/dspace-jspui-webapp/src/main/webapp/tools/edit-item-form.jsp找到該檔案。

請依照以下步驟一一插入程式碼。

插入doTaiwanAddress函式

請找到「String doXMLMetadata(…」函式的結束位置,我應該有加一個註解:「}//doXMLMetadata End」,再之後加入以下程式碼:

    String doTaiwanAddress(javax.servlet.jsp.JspWriter out, Item item,
      String fieldName, String schema, String element, String qualifier, boolean repeatable,
      int fieldCountIncr, String label, PageContext pageContext, String vocabulary, boolean closedVocabulary) 
      throws java.io.IOException 
	{
		StringBuffer output = new StringBuffer();
      DCValue[] defaults = item.getMetadata(schema, element, qualifier, Item.ANY);
      int fieldCount = defaults.length + fieldCountIncr;
      StringBuffer sb = new StringBuffer();
      String val;

      if (fieldCount == 0)
         fieldCount = 1;

	  int index = 0;
      for (int i = 0; i < fieldCount; i++) 
      {
	 if (i == 0) 
	    sb.append("<tr><td class=\"submitFormLabel\" width=\"35%\">")
	      .append(label)
	      .append("</td>");
	 else
	    sb.append("<tr><td>&nbsp;</td>");

         if (i < defaults.length)
           val = defaults[i].value.replaceAll("\"", "&quot;");
         else
           val = "";

         sb.append("<td colspan=\"2\"><input type=\"text\" name=\"")
           .append(fieldName);
         if (repeatable && i>0)
           sb.append("_").append(i);
         

		String editItemFormID = getMetadataID("value_", schema, element, qualifier, index);
		String editItemFormRemoveID = getMetadataID("submit_remove_", schema, element, qualifier, index);
		String editItemFormAddID = getAddID(schema, element, qualifier);
		index++;
		 
         sb.append("\" size=\"80\" value=\"")
           .append(val +"\"")
           //.append(hasVocabulary(vocabulary)&&closedVocabulary?" readonly=\"readonly\" ":"")
	   	.append("  onchange=\"editItemFormSync('"+editItemFormID+"', this.value)\" class=\"doTaiwanAddress\" />")
	   //.append(doControlledVocabulary(fieldName + (repeatable?"_" + i:""), pageContext, vocabulary))
	   .append("<textarea class=\"javascript\" style=\"display:none\">" + "\n")
		.append("jQuery(document).ready(function () {" + "\n")
		.append("jQuery(\"input[name=\'")
		.append(fieldName);
		if (repeatable && i>0)
           sb.append("_").append(i);
		sb.append("\']\").taiwanAddress();" + "\n")
		.append("});" + "\n")
	   .append("</textarea>")
	   .append("</td>\n");
	  
	 String fieldNameFull = fieldName;
	 if (repeatable && i>0)
           fieldNameFull = fieldNameFull + "_" + i;
	 
     
	 if (repeatable && i < defaults.length) 
	 {
	    // put a remove button next to filled in values
	    sb.append("<td><input type=\"button\" onclick=\"editItemRemove('"+editItemFormRemoveID+"')\" name=\"submit_")
	      .append(fieldName)
	      .append("_remove_")
	      .append(i)
//	      .append("\" value=\"Remove This Entry\"/> </td></tr>");
	      .append("\" value=\"")
   	      .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove"))
   	      .append("\"/> </td></tr>");
	 } 
	 else if (repeatable && i == fieldCount - 1) 
	 //else if (true)
	 {
	    // put a 'more' button next to the last space
	    sb.append("<td><input type=\"button\" onclick=\"editItemAdd('"+editItemFormAddID+"')\" name=\"submit_")
	      .append(fieldName)
//	      .append("_add\" value=\"Add More\"/> </td></tr>");
	      .append("_add\" value=\"")
	      .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.add"))
	      .append("\"/> </td></tr>");
	 } 
	 else 
	 {
	    // put a blank if nothing else
	    sb.append("<td>&nbsp;</td></tr>");
	 }
      }

     	//out.write(sb.toString());
		output.append(sb.toString());
		return output.toString();
    }//doTaiwanAddress End

引用jquery-plugin-taiwan-address.js

找到引用JavaScript與CSS的地方,在「<link rel="stylesheet" href="<%= request.getContextPath() %>/extension/xmlmetadata/flora.datepicker.css" type="text/css" media="screen">」之後插入以下程式碼:

<script type="text/javascript" src="<%= request.getContextPath() %>/extension/taiwan-address/jquery-plugin-taiwain-address.js"></script>

插入選擇使用doTaiwanAddress

最後找到以下程式碼:

								else if (inputType.equals("xmlmetadata")) 
								{
									pageContent.append(doXMLMetadata(out, item, fieldName, dcSchema, dcElement, dcQualifier, 
											  repeatable, fieldCountIncr, label, pageContext, vocabulary,
											  closedVocabulary, workspaceItemID, 
											  nonInternalBistreamsID, hasMultipleFiles, defaultValue, 
											  request.getContextPath()));
								} 

在這之後插入以下程式碼:

								else if (inputType.equals("taiwanaddress")) 
								{
									pageContent.append(doTaiwanAddress(out, item, fieldName, dcSchema, dcElement, dcQualifier, 
										repeatable, fieldCountIncr, label, pageContext, vocabulary, 
										closedVocabulary));	
								}

完成!

2009-06-15_000205

使用input-type:taiwanaddress

請修改[dspace]/config/input-forms.xml,把input-type設為taiwanaddress就可以囉。舉例來說如下:

       <field>
         <dc-schema>dc</dc-schema>
         <dc-element>contributor</dc-element>
         <dc-qualifier>authorAddress</dc-qualifier>
         <repeatable>true</repeatable>
         <label>Author Address</label>
         <input-type>taiwanaddress</input-type>
         <hint>Enter the address of the author of this item below.</hint>
         <required></required>
       </field>

結語

之後還會陸續加入一些東西,我想等穩定一點再來發佈edit-metadata.jsp或其他檔案吧。

<-- Post Catalog -->

(more...)

DSpace擴增文件編輯功能

布丁布丁吃布丁

DSpace擴增文件編輯功能

DSpace遞交文件與編輯文件不同的緣由

image image

每個用過DSpace的人都會有個疑惑:「DSpace的遞交文件相當地好用,但為什麼編輯文件這麼難用?」上方左圖是原本的遞交文件時的介面,我們可以把欄位分頁顯示,也可以依照input-type的設定顯示出「onebox」、「textarea」等多種樣式的欄位。反觀上圖右邊的編輯文件頁面,完全沒有遞交文件時的功能,而只有乏味的DC名稱、單調的欄位,甚至連說明都沒有。

為什麼會這樣設計呢?這就要提到DSpace的item-mapper功能。item-mapper可以允許一個item出現在多個collection,以減少重複建置item的浪費。然而遞交文件時設定的呈現格式是依照collection在跑的,因此當一份item重複在多個不同的collection出現時,多種不同的遞交文件設定會造成混亂,所以到最後乾脆簡單地以欄位統一呈現就好。

系統設計者這麼想,但是使用者可不是這麼想的啊。到頭來,還是要由程式設計師去解決這個問題。

image image

左邊圖片是改進原本顯示文件display-item.jsp所增加的「編輯」按鈕,按下去之後會直接進入右邊圖片的編輯文件edit-item-form.jsp。實際上,編輯文件已經跟遞交文件的畫面差別無幾,既能保留編輯文件原有的功能欄位,又能夠納入遞交文件時表單的好處。

這一份文件便是說明如何修改原本的DSpace,達到擴增編輯文件的功能。


安裝檔案

請將以下檔案下載,並放到指定的資料夾當中:

  • webapp.zip
    [dspace-source]/dspace/modules/jspui/src/main/webapp當中
    ※裡面有extension跟tools兩個資料夾喔!因為exntension很多功能都更新過,所以請覆蓋掉原本的檔案吧。
  • input-forms.dtd 
    [dspace]/config/input-forms.dtd
    ※幫page多加了「label」跟「hint」兩種屬性
  • SubmissionUtil.java
    ItemEditButton.java
    [dspace-source]/dspace-jspui-api/src/main/java/org/dspace/app/webui/util/SubmissionUtil.java
    [dspace-source]/dspace-jspui-api/src/main/java/org/dspace/app/webui/util/ItemEditButton.java

新增語系檔

請加入以下語系檔設定:

jsp.extension.xmlmetadata.required-tip = \u5fc5\u9808\u586b\u5beb
jsp.extension.xmlmetadata.check-required = \u60a8\u6709\u8868\u55ae\u5c1a\u672a\u586b\u5beb\u5b8c\u6210\uff0c\u662f\u5426\u8981\u7e7c\u7e8c\uff1f
jsp.extension.xmlmetadata.date-picker = \u8acb\u9ede\u6b64\u9078\u64c7\u65e5\u671f
jsp.extension.xmlmetadata.date-picker = \u8acb\u9ede\u6b64\u9078\u64c7\u65e5\u671f
jsp.extension.xmlmetadata.delete-confirm = \u78ba\u5b9a\u8981\u522a\u9664\uff1f
jsp.extension.xmlmetadata.delete-confirm = \u8868\u793a\u5fc5\u9808\u586b\u5beb
jsp.extension.xmlmetadata.not-has-multiple-files = \u5fc5\u9808\u70ba\u300c\u6587\u4ef6\u7531\u4e00\u500b\u4ee5\u4e0a\u7684 \u6a94\u6848\u6240\u7d44\u6210\u300d\uff01

jsp.tools.edit-item-form.now-editing-form-name1 = \u60a8\u73fe\u5728\u6b63\u5728\u7de8\u8f2f
jsp.tools.edit-item-form.now-editing-form-name2 = \u905e\u4ea4\u7a0b\u5e8f
jsp.tools.edit-item-form.index = \u6587\u4ef6\u8aaa\u660e
jsp.tools.edit-item-form.edit-metadata-title = \u7de8\u8f2f\u6587\u4ef6
jsp.tools.edit-item-form.edit-bitstream-title = \u7de8\u8f2f\u6a94\u6848
jsp.tools.edit-item-form.preview = \u7522\u751f\u9810\u89bd\u6a94\u6848
jsp.tools.edit-item-form.update-and-back = \u66f4\u65b0\u4e26\u56de\u5230\u6587\u4ef6
jsp.tools.edit-item-form.add-confirm = \u4e4b\u524d\u8a72\u6b04\u4f4d\u4e26\u6c92\u6709\u503c\uff0c\u8acb\u554f\u662f\u5426\u8981\u65b0\u589e\u6b64\u6b04\u4f4d\uff1f

加入「編輯」按鈕

這個動作主要是要修改ItemTag.java,這個修改的版本是繼我之前撰寫的「DSpace擴增MediaFilter格式」,如果你已經作過之前版本的動作,那麼可以下載我撰寫好的ItemTag.java

  • ItemTag.java
    [dspace-source]/dspace-jspui-api/src/main/java/org/dspace/app/webui/jsptag/ItemTag.java

如果不是的話,那麼請看以下修改步驟,一一你需要修改的地方。

因為「編輯」按鈕依附著Item物件,所以通常會加入在display-item.jsp或ItemTag.java當中。以下舉例是以ItemTag.java為例子。

第一步:引用「ItemEditButton.java」

請在開頭輸入引用語法,Java的引用語法如下:

import org.dspace.app.webui.util.ItemEditButton;

JSP的引用語法如下:

<%@ page import="org.dspace.app.webui.util.ItemEditButton" %>
第二部:使用getJavaScript()插入JavaScript

getJavaScript()已經被我寫成靜態方法(static)了,使用方式如下:

out.println(ItemEditButton.getJavaScript());

只能夠插入一次,插入第二次的話JavaScrip會出錯。因為懶得另外撰寫JavaScript檔案,所以用這種偷懶方法。

第三步:使用getString()來插入按鈕

以下是getString的說明:

getButton()
public static String getButton(PageContext pageContext, String innerTEXT, String schema, String element, String qualifier)
回傳「編輯」按鈕的HTML程式碼字串。
參數:
pageContext - 系統要從中查詢request的admin_button屬性,看是否包含了允許顯示管理標籤的資訊,如果沒有權限,則不會顯示按鈕
innerTEXT - 顯示在按鈕上的標籤,推薦使用語系檔的「jsp.general.edit.button」
schema - 該欄位的schema
element - 該欄位的element
qualifier – 該欄位的qualifier,沒有的話填入null
回傳:
按鈕的HTML程式碼字串 - 按鈕當中包含了JavaScript的事件器。如果沒有權限,則會回傳空字串。

用法舉例:

                	out.println(ItemEditButton.getButton(pageContext
                		, LocaleSupport.getLocalizedMessage(pageContext, "jsp.general.edit.button")
                		, values[i].schema
                		, values[i].element
                		, values[i].qualifier
                	));

利用getButton()方法,你可以自訂插入「編輯」按鈕的位置囉!

幫遞交程序的每一頁加上標題

image

 

請注意到上圖中的ProgressBar,原本只有「描述」的頁面名稱,現在可以自訂為任意你要的名稱了。連帶的下面也可以增加每一頁特定的敘述。

設定方法很簡單,請修改[dspace]/config/input-forms.xml。幫page加上兩種屬性:

  • label:顯示在ProgressBar上的名稱,字數建議不要超過五字。
  • hint:顯示在下面的指示,如果你要在裡面使用HTML,就要用脫逸字元「&lt;」取代「<」、用「&gt;」取代「>」、用 「&quot;」取代「'”」

舉例來說,你可以這樣設定:

<page number="1" label="第一頁標題" hint="這是我們可以自己加進去的&lt;strong style=&quot;color:red&quot;&gt;提示&lt;/strong&gt;喔!">

其他頁碼的設定,也可以如法炮製。

重新編譯DSpace

方法不再贅述。可以參考之前的DSpace相關文件


終於作完了,這功能做了一個月有吧,邊帶人一邊作,非常累。繼續趕工下一個功能。

<-- Post Catalog -->

(more...)

作研究到底是為了誰?

布丁布丁吃布丁

作研究到底是為了誰?

每次回家的時候,都會有一個固定的出門行程:去看婆婆。

我婆婆現在待在老人院,她在台北的兒子、三位在台中的女兒會輪流來看她。其中一個是我媽媽,似乎也是看得最勤的一位,每次我回來的時候,她總是會挑一天去探望婆婆。

婆婆她年事已高,應該有八十了吧?我對這種事情都記不太起來。我們去探望她的時候,她在吃點心,吃得滿嘴都是、落到地上。問她剛剛在吃些什麼,她答了幾句「聽唔」的台語,也說「哇嘸災」。「她應該是忘記她剛剛吃了什麼了。」我媽說著,一邊去廁所準備毛巾,指示我幫婆婆擦擦嘴、洗洗臉。我笨手笨腳的,最後還是媽媽來示範怎麼作。「要像照顧小孩一樣,用手指按住去擦,這樣才擦的乾淨。」媽媽說這是訣竅。

之後我們推著婆婆去外面散步,媽媽提到有篇母親寫的文章,大意像是:「兒子啊,有一天我也會老去,我會沒辦法自己吃飯、自己洗澡,甚至是自己上廁所。請你記得像我小時候照顧你一樣地照顧我,可以嗎?」

這讓我聯想到有個人說過:「小孩越養越大,充滿希望;老人越照顧越邁向死亡,充滿無奈。」每次來探望婆婆的時候,逐漸喪失身體機能的她,的確總是讓人覺得哀傷。


有一次楊老師帶我們去桃園大園跟一位公益組織管理的老師座談,那位老師請我們舉幾個所知道的非營利組織。同學們舉了「勵馨基金會」、「慈濟功德會」等等,可是尷尬的是,我腦袋只想得到「W3C」——全球資訊網協會

仔細想想,好像不只如此,我的努力似乎都是在幫助那些「有希望的人」,而沒顧慮到那些「沒有希望的人」。

我網誌中寫的一些技術文件,是給懂得這方面的人;我作一些網頁小工具,是給會操作網頁的人;我研究標註工具,做出來的也是只有給那些會使用電腦的人——那不會使用電腦的人,他們怎麼辦?

我可以設計一個介面優良、檢索快速簡便的全文資料庫,我也可以設計符合使用者需求的數位圖書館服務,這些都可以幫助進行學術研究的老師、學生們完成更上一層的研究——那又如何?

我可以靠看書懂得怎麼撰寫JAVA程式語言,但是卻不知道該怎麼拿毛巾幫婆婆擦嘴洗臉,這種深刻的違和感在心中一直揮之不去。

有時候會發現我自己口口聲聲說要幫助別人,可是就連最需要幫助的人,我都幫不上忙。我選擇的這條道路,真的是正確的嗎?

嗯……越想只是越鑽牛角尖而已。

只好把希望寄託他人,希望那些受到我幫忙過的人,他們有更多的力量去幫助那些真正需要幫忙的人吧。

 

不想擺圖,這篇就都是文字吧。

(more...)

DSpace新增編輯語系檔功能

布丁布丁吃布丁

DSpace新增編輯語系檔功能

image

實驗版本:DSpace 1.5

DSpace要修改語系檔的時候步驟繁雜,還要考慮編碼的轉換,十分的麻煩。以前我有寫過一個DSpace中文化專用utf-8轉碼程式,但其實那個轉換的功能很陽春、也有些缺陷,不建議再使用。我修改了一下轉碼程式,設計了更完整的編輯介面,並能夠直接在DSpace系統中使用。

我的作法是把原本DSpace那邊僅允許伺服器管理者必須手動修改設定檔的動作,改成用Java檔案管理的方式去建立、修改,跟原本DSpace設計理念有所差別,但是對於初學者來說卻是比較方便的。只是還是要手動重新啟動Tomcat,這個我之後再來寫一個網頁端程式好了。

以下是安裝步驟與使用方法介紹:


安裝檔案

請下載下列檔案,並擺到指定的位置:

  • messages-edit-jspui.zip
    [dspace-source]/dspace/modules/jspui/src/main/webapp/dspace-admin/messages-edit.jsp
    [dspace-source]/dspace/modules/jspui/src/main/webapp/dspace-admin/messages-main.jsp
  • MessagesEditServlet.java
    [dspace-source]/dspace-jspui/dspace-jspui-api/src/main/java/org/dspace/app/webui/servlet/admin/MessagesEditServlet.java
  • util.zip
    [dspace-source]/dspace-api/src/main/java/org/dspace/app/util/FileUtil.java
    [dspace-source]/dspace-api/src/main/java/org/dspace/app/util/EscapeUnescape.java
  • jquery.js (必需要用1.2.6以上版本)
    [dspace-source]/dspace/modules/jspui/src/main/webapp/extension/jquery.js

修改web.xml,增加「messages-edit」路徑

web.xml原本的位置在[dspace-source]/dspace-jspui/dspace-jspui-webapp/src/main/webapp/WEB-INF/web.xml,但是如果您修改過這個檔案了,那麼應該要另外儲存一份修改過得檔案在[dspace-source]/dspace/modules/jspui/src/main/webapp/WEB-INF/web.xml

請在最後一行結尾標籤</web-app>之前加入以下設定:

  <!-- Plugin Messages Editor  -->
  <servlet>
    <servlet-name>edit-messages</servlet-name>
    <servlet-class>org.dspace.app.webui.servlet.admin.MessagesEditServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>edit-messages</servlet-name>
    <url-pattern>/dspace-admin/messages-edit</url-pattern>
  </servlet-mapping>

然後請把web.xml儲存在[dspace-source]/dspace/modules/jspui/src/main/webapp/WEB-INF/web.xml之中。

修改navbar-admin.jsp,增加編輯語系檔的連結

navbar-admin.jsp預設位置在[dspace-source]/dspace-jspui/dspace-jspui-webapp/src/main/webapp/layout/navbar-admin.jsp,修改之後應該另存一份檔案在[dspace-source]/dspace/modules/jspui/src/main/webapp/layout/navbar-admin.jsp。

請找到以下程式碼:

我們增加一段程式碼在它

  <tr class="navigationBarItem">
    <td>
      <img alt="" src="<%= request.getContextPath() %>/image/<%= (currentPage.endsWith("/statistics") ? "arrow-highlight" : "arrow") %>.gif" width="16" height="16"/>
    </td>
    <td nowrap="nowrap" class="navigationBarItem">
      <a href="<%= request.getContextPath() %>/statistics"><fmt:message key="jsp.layout.navbar-admin.statistics"/></a>
    </td>
  </tr>

之後(不要動到原本的程式碼喔),如下:

  <tr class="navigationBarItem">
    <td>
      <img alt="" src="<%= request.getContextPath() %>/image/<%= (currentPage.endsWith("/dspace-admin/messages-edit") ? "arrow-highlight" : "arrow") %>.gif" width="16" height="16"/>
    </td>
    <td nowrap="nowrap" class="navigationBarItem">
      <a href="<%= request.getContextPath() %>/dspace-admin/messages-edit"><fmt:message key="jsp.layout.navbar-admin.editmessages"/></a>
    </td>
  </tr>

修改語系檔

修改您現有的語系檔之前,要先確認您所使用的語系檔為何。您可以在dspace.cfg裡面找到default.language設定。如果設定為default.lanuage = en_US,那麼您所使用的語系檔名為預設的「Messages.properties」,如果不是en_US而是「zh_TW」,那麼檔名應該是「Messages_zh_TW.properties」。由於我是用中文撰寫的,所以現在要加入的語系設定也是中文,故我們以「Messages_zh_TW.properties」作為範例。

語系檔會在[dspace-source]/dspace/modules/jspui/src/main/resources/Messages_zh_TW.properties,請在最後加入以下設定:

jsp.layout.navbar-admin.editmessages = \u7de8\u8f2f\u8a9e\u7cfb\u6a94

jsp.dspace-admin.messages-main.title = \u7de8\u8f2f\u8a9e\u7cfb\u6a94
jsp.dspace-admin.messages-main.heading = \u7de8\u8f2f\u8a9e\u7cfb\u6a94
jsp.dspace-admin.messages-main.submit_saved = \u5df2\u7d93\u5132\u5b58\uff01\u8acb\u91cd\u65b0\u555f\u52d5Tomcat\u7db2\u9801\u4f3a\u670d\u5668\u4ee5\u770b\u5230\u4fee\u6539\u7684\u6210\u679c\u3002
jsp.dspace-admin.messages-main.submit_cancel = \u53d6\u6d88\u7de8\u8f2f
jsp.dspace-admin.messages-main.default.language = \u76ee\u524d\u9810\u8a2d\u7684\u8a9e\u7cfb\u662f\uff1a
jsp.dspace-admin.messages-main.change-default-language = \u5982\u9700\u8981\u8b8a\u66f4\u7cfb\u7d71\u9810\u8a2d\u8a9e\u7cfb\uff0c\u8acb\u4fee\u6539dspace.cfg\u4e2d\u7684default.language\u8a2d\u5b9a\u3002
jsp.dspace-admin.messages-main.edit = \u7de8\u8f2f\u8a9e\u7cfb\u6a94
jsp.dspace-admin.messages-main.create = \u5efa\u7acb\u65b0\u7684\u8a9e\u7cfb\u6a94
jsp.dspace-admin.messages-main.create.source = \u5f9e\u4f86\u6e90\u6a94\u6848\u8907\u88fd
jsp.dspace-admin.messages-main.create.to-file-name = \u5230\u65b0\u7684\u8a9e\u7cfb\u6a94\u540d\u7a31
jsp.dspace-admin.messages-main.lang-collision = \u4e0d\u80fd\u8ddf\u73fe\u6709\u7684\u8a9e\u7cfb\u6a94\u540d\u7a31\u91cd\u8907\uff01
jsp.dspace-admin.messages-main.lang-empty = \u8a9e\u7cfb\u6a94\u540d\u7a31\u4e0d\u80fd\u662f\u7a7a\u503c\uff01
jsp.dspace-admin.messages-main.lang-active = \u73fe\u5728\u4f7f\u7528

jsp.dspace-admin.messages-edit.title = \u7de8\u8f2f\u8a9e\u7cfb\u6a94
jsp.dspace-admin.messages-edit.editing-position = \u60a8\u6b63\u5728\u7de8\u8f2f {0} \u8a9e\u7cfb\u6a94
jsp.dspace-admin.messages-edit.filter.key = \u7d22\u5f15\u540d\u7a31\u5305\u542b
jsp.dspace-admin.messages-edit.filter.or = \u6216
jsp.dspace-admin.messages-edit.filter.and = \u4e26
jsp.dspace-admin.messages-edit.filter.key = \u986f\u793a\u5167\u6587\u5305\u542b
jsp.dspace-admin.messages-edit.filter.do = \u641c\u5c0b
jsp.dspace-admin.messages-edit.filter.reset = \u986f\u793a\u5168\u90e8
jsp.dspace-admin.messages-edit.function.create = \u65b0\u589e\u9805\u76ee
jsp.dspace-admin.messages-edit.function.scroll-to-button = \u79fb\u81f3\u9801\u5c3e
jsp.dspace-admin.messages-edit.function.scroll-to-top = \u56de\u5230\u9801\u9996
jsp.dspace-admin.messages-edit.table.key = \u7d22\u5f15\u540d\u7a31
jsp.dspace-admin.messages-edit.table.value = \u986f\u793a\u5167\u6587
jsp.dspace-admin.messages-edit.js.nowLoading = \u8b80\u53d6\u4e2d\u2026\u2026\u8acb\u7a0d\u5019\u2026\u2026
jsp.dspace-admin.messages-edit.js.deleteButton = \u522a\u9664
jsp.dspace-admin.messages-edit.js.deleteConfirm = \u78ba\u5b9a\u662f\u5426\u8981\u522a\u9664\uff1f
jsp.dspace-admin.messages-edit.js.insertButton = \u63d2\u5165
jsp.dspace-admin.messages-edit.js.moveUpButton = \u2191
jsp.dspace-admin.messages-edit.js.moveDownButton = \u2193
jsp.dspace-admin.messages-edit.js.error.heading = \u767c\u751f\u932f\u8aa4
jsp.dspace-admin.messages-edit.js.error.name = \u932f\u8aa4\u540d\u7a31
jsp.dspace-admin.messages-edit.js.error.message = \u932f\u8aa4\u8a0a\u606f
jsp.dspace-admin.messages-edit.js.error.ValueEmpty = \u4e0d\u80fd\u662f\u7a7a\u767d\uff01
jsp.dspace-admin.messages-edit.js.error.WithSlash = \u4e0d\u80fd\u5305\u542b\uff1a
jsp.dspace-admin.messages-edit.js.error.WithNewLine = \u4e0d\u80fd\u63db\u884c\uff01
jsp.dspace-admin.messages-edit.js.error.CharsetError = \u4e0d\u80fd\u5305\u542b\u975e\u82f1\u6578\u5b57\u7684\u6587\u5b57
jsp.dspace-admin.messages-edit.js.save.KeyEmptyError = \u986f\u793a\u5167\u6587\u300c[0]\u300d\u7f3a\u5c11\u7d22\u5f15\u540d\u7a31\uff01
jsp.dspace-admin.messages-edit.js.save.ValueEncodeError = \u89e3\u78bc\u5230\u300c[0]\u300d\u6642\u767c\u751f\u932f\u8aa4\uff01
jsp.dspace-admin.messages-edit.js.filter.processing = \u641c\u5c0b\u4e2d\uff0c\u8acb\u7a0d\u5019\u3002
jsp.dspace-admin.messages-edit.js.sortConfirm = \u6392\u5e8f\u9700\u8981\u4e00\u6bb5\u6642\u9593\u904b\u7b97\uff0c\u800c\u4e14\u6392\u5e8f\u4e4b\u5f8c\u7684\u7d50\u679c\u7121\u6cd5\u5fa9\u539f\uff0c\u8acb\u554f\u662f\u5426\u8981\u7e7c\u7e8c\uff1f
jsp.dspace-admin.messages-edit.js.filter.not-found = \u641c\u5c0b\u6c92\u6709\u7d50\u679c\u3002
jsp.dspace-admin.messages-edit.encode-demo.heading = \u6e2c\u8a66\u8f49\u78bc\u5668
jsp.dspace-admin.messages-edit.encode-demo.text-to-dspace = \u2190
jsp.dspace-admin.messages-edit.encode-demo.dspace-to-text = \u2192

修改dspace.cfg檔案

dspace.cfg位於[dspace]/config/dspace.cfg

請加入以下設定:

#---------------------------------------------------------------#
#---------------Other Plugin Configuration----------------------#

tomcat.dir = /opt/apache-tomcat-6.0.16/webapps/jspui
dspace.source.dir = /opt/dspace-1.5.0-src-release

上面的tomcat.dir跟dspace.source.dir請更換成您實際上Tomcat伺服器當中擺放DSpace的位置,以及DSpace原始碼的位置。如果您之前照我寫的DSpace安裝法的話,那目錄位置就是這樣沒錯。

重新編譯DSpace

步驟如下:

  1. 移至DSpace原始檔目錄中的dspace目錄。注意底下的[dspace-source]要替換成您DSpace原始碼的目錄。
    [dspace@dspace ~]# cd [dspace-source]/dspace/
  2. 執行mvn package指令
    [dspace@dspace dspace]# mvn package

    如果最後出現BUILD SUCCESSFUL,表示編譯成功。
  3. 移至底下的target/dspace-{您DSpace的版本號}-build.dir/目錄。注意,底下的1.5.0要替換成您DSpace的版本號,或是查查看target砥下的目錄即可。
    [dspace@dspace dspace]# cd target/dspace-1.5.0-build.dir/
  4. 執行ant指令:
    [dspace@dspace dspace-1.5.0-build.dir]# ant -Dconfig=[dspace:]/config/dspace.cfg update
  5. 複製DSpace安裝目錄底下的資料夾到Tomcat的webapps目錄之中。注意,底下的[dspace]要替換成您DSpace的安裝目錄,[tomcat]則是要替換成您Tomcat的安裝目錄。
    [dspace@dspace dspace-1.5.0-build.dir]# cd [dspace]
    [dspace@dspace dspace]# \cp -rf [dspace]/webapps/* [tomcat-6.0.16]/webapps/
  6. 重新啟動Tomcat。
    [dspace@dspace dspace]# cd [tomcat]/bin
    [dspace@dspace bin]# shutdown.sh
    [dspace@dspace bin]# startup.sh

功能說明:首頁

要使用編輯語系檔的功能,使用者必須要是管理者權限(Administrator)登入才行,一般的使用者是沒辦法使用的。

image

  1. 從左邊的導覽列可以進入「編輯語系檔」
  2. 偵測目前使用的語系:系統會取得dspace.cfg裡面的default.language設定,這就是您目前DSpace所使用的語系。
  3. 編輯語系檔:下拉式選單可以選擇您要編輯的語系檔。針對目前使用的語系檔,系統會特別在語系檔名稱後標明「現在使用」。
  4. 建立新的語系檔:您可以選擇一個來源檔案,然後將他複製到新的語系檔當中,再進行編輯動作。

功能說明:編輯頁

image

語系檔通常會高達一千多筆資料,進入編輯頁面的時候需要花一段時間讀取,請耐心等候。

  1. 顯示您現在編輯的語系檔名稱。
  2. 搜尋語系檔功能,當您要修改特定語系設定的時候非常好用。讀取完成之後,就可以按下後面的按鈕。
  3. 測試轉碼器:類似原來DSpace中文化專用utf-8轉碼程式的功能,這邊測試的資料並不會寫入語系檔。
  4. 功能列,包括更新、新增項目(在最後面新增一筆語系設定)、移至頁尾、取消(然後返回首頁)。讀取完成之後,就可以按下更新、新增項目的按鈕。
  5. 讀取中的訊息。有時候因為資料量過大,會導致網頁像是當機一樣,請稍後。
  6. 語系編輯器:
    1. 第一欄是索引名稱,請依照DSpace的設計方式,只輸入英文字(盡量小寫)、用「.」分隔索引名稱的層次,用「-」連接多字元片語。
      如果語系檔開頭使用#,則表示是註解,供系統人員閱讀用。編輯器會自動偵測並改變表現形式,如下圖:
      image
    2. 第二欄是顯示內文,也就是真正顯示在網頁上的資料。雖然可以使用一些簡單的HTML,但是不建議用太過複雜的內容,不然很容易導致語系檔錯誤,無法讀取。
    3. 刪除:刪除此設定,無法復原。
    4. 插入:在此設定之後加入一行設定。
    5. 上移與下移。

終於寫完了。

這樣要編輯DSpace語系檔就簡單多了吧。

接下來來作一個Tomcat重新啟動的功能,省得還要到伺服器端重新啟動DSpace吧。<-- Post Catalog -->

(more...)

DSpace擴增MediaFilter(BitstreamDisplay使用篇)

布丁布丁吃布丁

DSpace擴增MediaFilter(BitstreamDisplay使用篇)

DSpace擴增MediaFilter的目錄:

image

BitstreamDisplay.java是我另外撰寫的Java Class物件檔,讓程式設計者可以透過他的method去建立顯示Bitstream的介面。他可以自動判斷是否有利用MediaFilter製作的索引縮圖(thumbnail)或是內部的Bitstream(像是flv、mp3或是用ZoomifyImage轉出來的圖檔),並選擇相對應的顯示介面來顯示。

接下來說明他的使用方法:

引用BitstreamDisplay

如果要使用BitstreamDisplay的話,就必須先引用。在Java裡面,引用語法如下:

import org.dspace.app.webui.util.BitstreamDisplay;

在JSP裡面,引用語法如下:

<%@ page import="org.dspace.app.webui.util.BitstreamDisplay" %>

建立BitstreamDisplay物件

建立BitstreamDisplay物件必需要輸入兩個參數:

  • Item:DSpace的Item物件
  • Bitstream的網址:可以是retrieve的「/jspui/retrieve/468」,也可以是bitstream的「/jspui/bitstream/123456789/83/72/Animal%20Park.m4a」,程式會自動從網址判斷該Bitstream的ID、類型以及相關的內部檔案。

建立物件的範例如下:

//取得DSpace該頁面的Item資訊
Item item = (Item) request.getAttribute("item");
//設定bitstream的網址
String bdLink = request.getContextPath() + "/bitstream/123456789/83/72/Animal%20Park.m4a";
//建立物件
BitstreamDisplay db = new BitstreamDisplay(item, bdLink);

建立Dialog連結

建立完BitstreamDisplay物件之後,接下來就可以用doDialog呼叫他。

method doDialog是這樣使用的:

public String db.doDialog(String innerTEXT, boolean allowDownload)

他會回傳連結語法與顯示Dialog相關的HTML程式碼。

參數說明如下:

  • String innerTEXT:要顯示在連結裡面的HTML程式碼。
  • boolean allowDownload:是否要顯示Download按鈕,請輸入true或false。預設是true。

其他的就交給BitstreamDIsplay去設定吧。必須要注意的是,這些程式碼要搭配jQuery相關的檔案才能順利運行,如果執行的時候發生JavaScript錯誤,那麼不妨回去安裝篇看一下是不是JSPUI中extension漏裝了什麼。


雖然我還寫了其他的method,不過最重要的應該就這個而已,有興趣的話可以開啟BitstreamDisplay.java看看其他method怎麼使用。

寫完之後才發現剛剛寫的安裝篇漏寫了很多東西,再回去補……orz

(more...)