:::
針對查詢「dspace」依關聯性排序顯示文章。依日期排序 顯示所有文章

JAVA寄信問題「HELO requires domain address」的解決方法

布丁布丁吃布丁

JAVA寄信問題「HELO requires domain address」的解決方法

image

當我利用VirtualBox架設虛擬機器時,會發現沒辦法正常地使用註冊信的功能。這是因為虛擬機器內部的domain name並不是其他domain name server認可的名稱,只是我測試用的名字。此時可以自行在伺服器當中新增此domain name,對應到127.0.0.1,也就是本機端,就可以解決此問題。

以下詳述這個問題的發生與解決過程。

虛擬機器中DSpace的郵件設定
##### Email settings ######

# SMTP mail server
mail.server = 127.0.0.1

# SMTP mail server authentication username and password (if required)
# mail.server.username = myusername
# mail.server.password = mypassword

# SMTP mail server alternate port (defaults to 25)
mail.server.port = 25

# From address for mail
mail.from.address = dspace-noreply@dspace-dlll.nccu.edu.tw

# Currently limited to one recipient!
feedback.recipient = dspace-help@dspace-dlll.nccu.edu.tw

# General site administration (Webmaster) e-mail
mail.admin = dspace-help@dspace-dlll.nccu.edu.tw

必須說明到,上述設定當中的「dspace-dlll.nccu.edu.tw」完全沒有註冊在任何domain name server當中。因此執行時就會發生錯誤。

認不出domain name的錯誤訊息

image

在此設定當中進入DSpace的使用者註冊時,就會發生錯誤。我們來到DSpace的記錄檔當中看看,預設位置在「[dspace]/log/dspace.log」,可以用文字編輯器來開啟。

錯誤訊息如下:

2009-10-02 23:58:27,828 INFO  org.dspace.app.webui.servlet.RegisterServlet @ anonymous:session_id=29633B32BF10EEEF95FCF4DC71B5C7FD:ip_addr=10.0.2.2:sendtoken_register:email=puddingchen.35@gmail.com
2009-10-02 23:58:30,669 INFO  org.dspace.app.webui.servlet.RegisterServlet @ anonymous:session_id=29633B32BF10EEEF95FCF4DC71B5C7FD:ip_addr=10.0.2.2:error_emailing:email=puddingchen.35@gmail.com
javax.mail.MessagingException: 501 5.0.0 HELO requires domain address

        at com.sun.mail.smtp.SMTPTransport.issueCommand(SMTPTransport.java:1363)
        at com.sun.mail.smtp.SMTPTransport.helo(SMTPTransport.java:838)
        at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:375)
        at javax.mail.Service.connect(Service.java:275)
        at javax.mail.Service.connect(Service.java:156)
        at javax.mail.Service.connect(Service.java:105)
        at javax.mail.Transport.send0(Transport.java:168)
        at javax.mail.Transport.send(Transport.java:98)
        at org.dspace.core.Email.send(Email.java:362)
        at org.dspace.eperson.AccountManager.sendEmail(AccountManager.java:296)
        at org.dspace.eperson.AccountManager.sendInfo(AccountManager.java:256)
        at org.dspace.eperson.AccountManager.sendRegistrationInfo(AccountManager.java:101)
        at org.dspace.app.webui.servlet.RegisterServlet.processEnterEmail(RegisterServlet.java:287)
        at org.dspace.app.webui.servlet.RegisterServlet.doDSPost(RegisterServlet.java:202)
        at org.dspace.app.webui.servlet.DSpaceServlet.processRequest(DSpaceServlet.java:147)
        at org.dspace.app.webui.servlet.DSpaceServlet.doPost(DSpaceServlet.java:105)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
        at java.lang.Thread.run(Thread.java:619)

你可能會發現到IP很奇怪,因為這是VirtualBox配給的內部IP。

這段記錄的重點在於錯誤訊息「HELO requires domain address」,代表的意思是HELO認不出來「dspace-dlll.nccu.edu.tw」對應到哪台主機。

設定伺服器當中的domain name對照表

用指令列來修改「/etc/hosts」,增加下列設定:

127.0.0.1       dspace-dlll.nccu.edu.tw dspace-dlll

然後得重新啟動網路,指令是「/etc/init.d/network restart」

或著你也可以用圖形介面來設定。

image

先進入「網路」當中。

image 

切換到「主機」那一頁,然後按「新增」。

image

設定位址、要對應的主機名稱跟其別名。

image

最後記得要儲存才會生效。


以上,大功告成。用虛擬機器果然是比較麻煩了一些,不過也可以藉此在精進網路知識就是了。

(more...)

DSpace-DLLL教學投影片 / DSpace-DLLL Teaching Slides

DSpace-DLLL教學投影片 / DSpace-DLLL Teaching Slides

image

最近幫老師上課教了DSpace-DLLL,教導學生如何用DSpace-DLLL建檔、規劃社群與類別、設計遞交表單。在此公開教學的內容。

In recent days, I taught students how to use DSpace-DLLL to archive items, organize communities and collections, design submission input forms (metadata schema). I public my teaching materials in this article.


什麼是DSpace-DLLL? / What is DSpace-DLLL

DSpace-DLLL係以DSpace 1.5版本為基礎,結合實驗室長久使用DSpace發展數位典藏系統專案的經驗,改良並同樣以BSD條款釋出開放給讀者使用的數位典藏軟體。DSpace-DLLL系統與原本的DSpace 1.5版本有許多改良的地方,列舉如下:

  1. 以臺灣國情為主的中文化介面。
  2. 加強DSpace著錄數位典藏後設資料的功能。使用者可以用已經具備的後設資料格式,以輸入文字、上傳檔案等多種輸入型態來著錄後設資料。
  3. 在網頁使用介面裡加入許多管理工具,諸如設定檔編輯、語系檔編輯、遞交表單編輯、重新啟動Tomcat伺服器與記錄檔查閱等。即使不熟悉各個設定檔的編輯語法細節,讀者也可以在網頁使用介面上輕易地調整這些設定。
  4. 改良部份操作細節、版面配置,讓使用上能夠符合一般使用者的邏輯與習慣。

我之前已經用「談DSpace-DLLL系統」一文來介紹了一些DSpace-DLLL的事情。關於DSpace-DLLL的細節會在專書中介紹。

以下是以DSpace-DLLL的教學內容。跟專書中有點不一樣的是,我針對社群、類別、文件這三個重要但容易混淆的差異,我用目錄、Excel、表格內容來比喻:

2014-03-31_15-39-00

針對Metadata Schema概念設計的部分,我建立了一份「遞交表單規劃表」供初學者規劃。

image

遞交表單規劃表下載:Google DriveOneDriveBox.net

Part.1 資料建檔:新增遞交作業

大綱:

  • 進入並登入您的DSpace
  • 文件建檔:新增遞交作業
  • 檢視已建檔的文件

檔案下載:Google DriveOne DriveBox.net

Part.2 建構DSpace的架構

大綱:

  • 修改系統設定
    • DSpace-DLLL網站名稱
    • 編輯網站介紹(頭條新聞)
  • 介紹內容資料組織架構概念
    • 新增社群(community)
    • 新增類別(collection)

檔案下載:Google DriveOne DriveBox.net

Part.3 設計遞交表單

大綱:

  • 遞交表單介紹
  • 遞交表單規劃表
  • 遞交表單新增與編輯

檔案下載:Google DriveOne DriveBox.net

Part.4 遞交作業與問題回報

大綱:

  • 新增遞交作業
  • 修改文件與多媒體轉檔
  • 常見錯誤與問題回報

檔案下載:Google DriveOne DriveBox.net


心得:感謝雲端平台 / Thinking: Thanks for Proxmox VE

我教DSpace已經教很久了,不管是教使用操作、還是教系統開發,但直到現在,我還是覺得那些metadata schema什麼的概念,是很難一下子就搞懂得的事情。所以這次的教學,我也比上次又更改進了一些地方。希望大家都能夠透過簡單的比喻、熟悉的討論工具,能夠更容易操作DSpace-DLLL。

另外,多虧實驗室的Proxmox VE虛擬機器IaaS架構,以及之前把DSpace-DLLL改成OpenVZ的形式。一台實體伺服器跑11台DSpace-DLLL,運作起來仍游刃有餘。這比起去年教學時的狀況還要好上許多了。

這次所上開設的雲端運算研習班(名字尚未確定)中,我會去介紹實驗室的雲端平台架構,裡面會講我們是如何用開放原始碼的軟體來整合虛擬網路與虛擬機器,來提供快速提供大量伺服器服務的功能。有興趣的話請報名。

(more...)

DSpace 1.5統計功能無法開啟的問題

布丁布丁吃布丁

DSpace 1.5統計功能無法開啟的問題

參考資料來自於這篇:DSpace statistics(统计问题) - 上善若水.class - CSDNBlog

如果你下載的DSpace 1.5版無法正常啟用統計功能(statistic),可能是因為原始碼的API寫錯了。

請修改LogAnalyser.java,可以善用locate幫忙搜尋:

#vim [dspace-source]/dspace-api/src/main/java/org/dspace/app/statistics/LogAnalyser.java

將1216行多餘的「"FROM metadatavalue " +」註解掉,結果如下:

dateQuery.append("FROM metadatavalue " +
                  //"FROM metadatavalue " +
                  "WHERE metadata_field_id = (" +
                  " SELECT metadata_field_id " +
                  " FROM metadatafieldregistry " +
                  " WHERE element = 'date' " +
                  " AND qualifier = 'accessioned') ");

然後重新打包,請參考DSpace System Documentation_ V1.5 - May 2008.pdf 84頁的rebuild the DSpace Web application:

#cd [dspace-source]/dspace
#mvn package

等待mvn打包結束之後,再執行ant佈署:

#cd [dspace-source]/dspace/target/dspace-[version].dir
#ant -Dconfig=[dspace]/config/dspace.cfg update

等待ant佈署結束之後,再複製新的war到tomcat的webapps目錄:

#\cp -rf /dspace/webapps/ /opt/apache-tomcat-6.0.16/webapps/

這樣用以下指令執行統計功能就不會出現問題了。

#[dspace]/bin/stat-initial
#[dspace]/bin/stat-general
#[dspace]/bin/stat-monthly
#[dspace]/bin/stat-report-initial
#[dspace]/bin/stat-report-general
#[dspace]/bin/stat-report-monthly
image
(more...)

DSpace的PostgreSQL資料庫架構與操作

布丁布丁吃布丁

DSpace的PostgreSQL資料庫架構與操作

前言

PostgreSQL是個專業但卻免費開放原始碼的資料,選擇他做為DSpace的資料庫是很穩定的。即使由於它過於複雜的架構讓我們沒辦法把它像MySQL這樣地簡單操作,在本文件當中我們依然要求你具備關聯式資料庫的概念,並且熟知SQL語法的操作。特別是SQL語法,這是所有資料庫的共通語言,所以一定要知道。
PostgreSQL有pdAdmin III資料庫管理介面可供使用,GUI圖形化且中文的操作介面也容易使用。但是在DSpace裡面操作資料庫的時候,除了要知道怎麼看JAVA程式來操作物件,還會使用到SQL指令。看完本文件,希望讓你對於操作PostgreSQL有個概念。

第一章 PostgreSQL簡介

PostgreSQL 是由散佈在全球的數百名開發者(包含非營利組織團體,學術研究機構及國際企業體)志願貢獻與共同開發的專案成果,歷今22年來持續發展。長久以來被用於要 求極端嚴謹的商業應用/科學研究環境及政府組織中。PostgreSQL 為 BSD 版權協議發佈,允許您在商業或非商業應用的兩種環境下均能享有自由取得且不受限制的使用權。PostgreSQL 具有高度擴展性,且完整遵從國際 ISO-SQL 規範的開發方向,是當前全球最先進的開放源始碼(OSS)的物件關聯型資料庫管理系統(ORDBMS)。更詳細的介紹可以參考PostgreSQL ::國際中文社群網誌:: http://postgresql-chinese.blogspot.com/

PostgreSQL與其他資料庫類似,使用SQL語言來執行資料的查詢。它的特色在於資料庫的可程式性,對於使用資料庫資料的實際應用,PostgreSQL 讓開發與使用的工作,變得更加容易。

我們在建構DSpace的過程中,只需要透過DSpace的API來操控資料庫,你只需要擁有操控SQL語言的能力即可,不需要深入研究PostgreSQL的功能。由於它的架構十分複雜,我們不建議用SQL或pgAdmin手動新增、刪除或修改資料庫的任何資料或架構,請盡量使用DSpace設計好的物件(object)中的方法(method)來執行。

第二章 PostgreSQL安裝

有些Linux發行版已經內建PostgreSQL,在DSpace的建立過程中,我們使用的CentOS作業系統已經內建,因此我們不需要另外安裝。

如果你想要開放所有的對外連線來查看你的資料庫(ex. pgAdmin),則你需要編輯postgresql.conf (通常會放在/var/lib/pgsql/data或者/usr/local/pgsql/data),並且在Linux之中修改為:

vim postgresql.conf
加入tcpip_socket = true
加入listen_addresses = '*' #限定任何IP皆可連線
vim pg_hba.conf
加入host dspace dspace 127.0.0.1 0.0.0.0 md5

(注意,開放所有對外連線是不安全的,你必須明確的了解你做什麼事情。)

第三章 DSpace資料庫架構說明

透過pgAdmin III可以看到DSpace整個架構。pgAdmin III詳細的操作方法在稍後章節會提到。

以下是DSpace在安裝的過程中會自動建立的表格架構,由於PostgreSQL本身架構太過複雜,與其撰寫把完整的資料庫架構細節寫上來,不如請直接參考輸出的備份檔。在此我將各表格與各欄位的用處及注意事項寫下來,未確認的表格與欄位,註釋則是空白。灰色背景表示是表格名稱與註釋,白色背景表示是該表格底下的欄位名稱與註釋。

第四章 透過pgAdmin操作資料庫

第一節 pdAdmin簡介

pgAdmin III是一個針對PostgreSQL的通用並且具有豐富特性的開放源碼管理和開發工具,可以用在Linux、FreeBSD、Solaris、Mac OSX和Windows平臺上管理運行於任何平臺的PostgreSQL 7.3以及更高級的版本,也包括商業版本例如EnterpriseDB、Mammoth PostgreSQL、Bizgres 和 Greenplum database。詳細網址是http://www.pgadmin.org/index.php?lang=zh_CN,目前最新的版本是pgAdmin III 1.8.1版本(2008年1月23日),適用於Windows平台的pgAdmin III下載位置在http://www.pgadmin.org/download/windows.php,左方可以選擇其他的平台。

第二節 新伺服器登錄

安裝完pgAdminIII並開啟之後,首先你要做的便是將DSpace的連線資料登錄,以便之後的連線。欄位的填寫資料可以參考上圖,但要確定你的PostgreSQL是否有開啟TCP/IP連線,並且允許任何IP連線管理。

第三節 pgAdminIII操作環境簡介

PostgreSQL是有嚴謹架構的資料庫,而pdAdminIII也提供了相當完整且複雜的功能。在此我僅介紹管理DSpace時可能會使用的操作部分。

查詢資料庫中的資料表

如上圖的路徑中,可以找到DSpace所有的資料表。

查詢資料表當中的欄位

資料表可繼續往下打開,即可看到該資料表的所有欄位資料。

查詢資料表當中的資料列

資料表按右鍵,選擇「檢視資料」,當中有

  • 「檢視頂部100筆資料列」:最前面100筆資料的意
  • 「檢視全部資料列」:注意,檢視的資料量過大將會導致伺服器負荷過大,不建議開啟此項
  • 「檢視已篩選資料列」:以where的條件來篩選資料。但也要注意是否篩選結果資料量會過大的問題

直接輸入SQL指令

點選主視窗的SQL查詢工具,可使用此工具快速測試你的SQL語法。如上圖所示,上方是輸入SQL的地方,下方則是輸出的結果處,但不能像「檢視資料」這樣直接修改。除了select查詢之外,你也可以使用update、delete等其他指令,而下方結果輸出處會顯示有幾筆欄位受到影響。

第五章 透過DSpace的API來操作資料庫

DSpace大部分的物件使用方式,你都可以在原始安裝檔的src目錄下找到。其中src/org/dspace/content目錄裡面皆擺放著常用的物件及方法,例如你要操作item的話,那麼可以查詢src/org/dspace/content/Item.java。當然,要記得在文件開頭import檔案。

詳細的物件使用方法我想再另外一個Dspace操作手冊裡面說明,在此就省略。

然而,Dspace提供的物件並不能滿足設計所需,有時候我們仍需要以純粹的SQL語法來進行查詢。src/org/dspace/storage/rdbms中的DatabaseManager.java、TableRow.java跟TableRowIterator.java裡面的物件可以幫助你這樣做。以下詳細說明這些物件的操作方式。

  1. 必須在開頭輸入需要的檔案路徑。在JAVA跟JSP的輸入方法不同,看你要在哪邊操作資料庫。
    JAVA:
    import org.dspace.storage.rdbms.DatabaseManager;
    import org.dspace.storage.rdbms.TableRow;
    import org.dspace.storage.rdbms.TableRowIterator;
    JSP:
    <%@ page import="org.dspace.storage.rdbms.DatabaseManager" %>
    <%@ page import="org.dspace.storage.rdbms.TableRow" %>
    <%@ page import="org.dspace.storage.rdbms.TableRowIterator" %>
  2. Context context = new Context(); //context是DSpace定義的情境,如果你之前的文件裡面沒有context的話,那麼請用此方法建立一個空的context。當然,要記得在開頭import檔案。

  3. TableRow row = DatabaseManager.querySingle(context, "select * from collection"); //querySingle第二個參數是sql語法

  4. String temp = row.getStringColumn("name"); //這樣就能取得第一列的name欄位的值。再執行一次則是取得下一列,依此類推。

DatabaseManager.java中的操作方法有很多種,除了查詢之外也有刪除(delete)、更新(update),也有搜尋或新增等方法,相當地實用,請務必好好讀過一遍。

第六章 透過JDBC連接操作資料庫

JAVA程式語言本身也有提供連接資料庫的應用介面,Java Database Connectivity,簡稱JDBC。開始之前必須再次,DSpace的API具有錯誤回報與紀錄log的功能,而且似乎較不會使系統出現問題,建議不要使用原始的JDBC進行連線。由於早期尚未熟悉DSpace的API前,我先使用了JDBC的方式,導致現在系統時常因為資料庫連線而無法回應,並不是好事。

要使用的JDBC API包裝在java.sql(之後的延伸版本則是擺在javax.sql)之中,因此在使用之前必須要import這個檔案:

JAVA:

import java.sql.*

JSP:

<%@ page import="java.sql.*" %>

接著是與資料庫進行連線。注意以下來自於ConfigurationManager的三個參數,個別代表著資料庫位置、帳號及密碼,這是使用Dspace內建的ConfigurationManger來取得與Dspace同樣設定的方法。當然,要記得import:

Class.forName("org.postgresql.Driver").newInstance();
String db_url = ConfigurationManager.getProperty("db.url");
String db_user= ConfigurationManager.getProperty("db.username");
String db_password= ConfigurationManager.getProperty("db.password");
Connection conn= DriverManager.getConnection(db_url,db_user,db_password);
Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);

接著便可以對stmt輸入sql、傳回查詢結果,並且取出。以下是範例,請注意到sql跟rs的類型宣告:

String sql="SELECT * FROM item LIMIT 10 OFFSET 0";
//修改這邊的SQL語法!
ResultSet rs=stmt.executeQuery(sql);
while(rs.next()) {
%><br />
欄位1: <%=rs.getString(1)%>/
欄位2: <%=rs.getString(2)%>/
欄位3: <%=rs.getString(3)%>/
欄位4: <%=rs.getString(4)%>/
<%
}

在while迴圈中,你可以注意到取出rs資料的方法是用getString,而且參數是從1開始而非常見的0。

(more...)

PostgreSQL連線設定與DSpace資料庫備份設定

布丁布丁吃布丁

PostgreSQL連線設定與DSpace資料庫備份設定

安裝DSpace的時候要先把PostgreSQL的連線類型改成不需要密碼的「trust」,但是安裝完之後要改回「md5」(以md5加密的密碼)或「password」(必須詢問密碼),以提高PostgreSQL的安全性。

但是本機端需要詢問密碼的情況下,會讓crontab自動排程無法自動備份(dump)PostgreSQL的資料庫。因此必須設定該帳號家目錄底下的.pgpass,讓該帳號不需要再次詢問密碼就能夠直接通過PostgreSQL的認證連線,以順利匯出資料庫。

詳細步驟說明如下:

安裝DSpace之前需要修改的PostgreSQL設定

安裝DSpace的過程中,我建議先把PostgreSQL的連線設定(/var/lib/pgsql/data/pg_hba.conf,註1)裡每一個連線類型改成trust,範例如下:

# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD

# "local" is for Unix domain socket connections only
local   all         all                               trust #ident sameuser
# IPv4 local connections:
host    all         all         127.0.0.1/32          trust #ident sameuser
# IPv6 local connections:
host    all         all         ::1/128               trust #ident sameuser
# for DSpace
host    dspace      dspace      127.0.0.1             trust #255.255.255.
  • 註1^PostgreSQL在CentOS中預設安裝位置在/var/lib/pgsql/當中,故連線的設定檔將位於/var/lib/pgsql/data/pg_hba.conf,如果是手動安裝則可能會在其他地方。

安裝完DSpace之後的PostgreSQL連線設定

安裝完成DSpace之後,為了提高PostgreSQL的安全性,設定為本機端連線的時候也需要詢問密碼。

一樣是修改連線設定檔/var/lib/pgsql/data/pg_hba.conf,將method改成md5(以MD5編碼加密)或password(需要詢問密碼),修改範例如下:

# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD

# "local" is for Unix domain socket connections only
local   all         all                               md5 #ident sameuser
# IPv4 local connections:
host    all         all         127.0.0.1/32          md5 #ident sameuser
# IPv6 local connections:
host    all         all         ::1/128               md5 #ident sameuser
host    dspace      dspace      127.0.0.1             password #255.255.255.255

這樣修改主要是方便使用phpPgAdmin——一個用網頁介面管理PostgreSQL的工具(註2 )。

下圖是phpPgAdmin的介面:

image 

如果連線設定依舊是trust的情況下,任何使用者只要連到該系統的phpPgAdmin工具、知道該帳號名稱,則使用任何密碼都可以登入PostgreSQL資料庫中。

使用phpPgAdmin時,除了需要修改PostgreSQL的連線為「md5」或「password」之外,最好如phpMyAdmin一樣地還加上Apache利用.htaccess來實作的認證機制(註3)。

PostgreSQL自動備份策略

如果PostgreSQL的連線設定需要使用密碼,那麼在利用crontab排程自動執行備份指令時,也會遇到需要輸入密碼而無法自動執行的情況。

PostgreSQL在8版之後(好像是,至少目前我們使用的都是8版)可以使用「.pgpass」來為使用者設定自動認證

以下介紹詳細步驟

  1. 假如我們要連線的資料庫位置為「localhost」(表示本機端)、連接埠為「5432」(PostgreSQL預設連接埠)、資料庫名稱為「database」、資料庫帳號為「username」、密碼為「password」。注意,username不一定要跟你執行crontab的帳號相同。
  2. 切換到執行crontab的LINUX實體帳號,假如是「dspace」,則利用su指令切換:
  3. [root@dspace /]# su dspace 
  4. 在該帳號的家目錄新增檔案「.pgpass」
  5. [dspace@dspace /]# vim ~/.pgpass
  6. 利用vim編輯器輸入以下資料:
  7. localhost:5432:database:username:password 
    完成之後儲存離開。
  8. 修改.pgpass的權限為600
  9. [dspace@dspace /]# chmod 600 ~/.pgpass
  10. 測試看看,利用pg_dump匯出資料庫到「/var/lib/pgsql/backups/bkup.sql」
  11. [dspace@dspace /]# pg_dump -U username database > /var/lib/pgsql/backups/bkup.sql 
  12. 如果「/var/lib/pgsql/backups/bkup.sql」有檔案,並且內文為正確的sql檔,則表示認證成功。反之,如果系統要求你輸入密碼,那可能是哪個步驟做錯了,請回頭一一確認。

當確認可以自動通過認證,以指令執行PostgreSQL匯出的之後,就可以把這些指令加入crontab排程中囉。

資料庫一定要天天備份,祝大家伺服器都能運作順利


延伸閱讀

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...)

寫書初稿完成!

布丁布丁吃布丁

寫書初稿完成!

 

image 我現在是研究所三年級下學期,很多人會問我什麼時候畢業,我都這樣回答:「先寫完書,再來寫論文。」而到今天為止,總算是把寫書初稿跟附件光碟全部完成了!

寫書至今已經一年了,可是我好像沒有在這裡好好談談寫書這件事情。所以在寫書初稿完成的今晚,我就好好地來報告一下寫書的由來與經過吧!


關於本書

這本書的書名定為「DSpace開放原始碼數位典藏系統建置技術彙編」,是由陳老師訂定的,雖然我覺得有點饒舌,但也不失學術風味,似乎也不錯。這本書是由陳老師帶領的實驗室底下的助理、學生約12人共同撰寫,其中我規劃了本書內容、製作附件光碟的DSpace-DLLL'、並撰寫了部份章節。

本書是為了讓需要建置數位典藏系統或是數位典藏教學需求而撰寫,讀者可以從本書第一部份學習數位典藏的相關理論,接著第二部份是附件光碟DSpace-DLLL的操作介紹,而第三部份則介紹三個由DSpace建置而成的數位典藏。DSpace是一個開放原始碼的數位典藏系統,而我將之重整規劃之後,成為一個容易安裝、操作的附件光碟,而且一樣以BSD條款發行供大家使用。

本書從2009年4月初制定架構到2010年4月中初稿完成,目前已經交由陳老師審查、校稿,老師正在尋求出版商,並希望能在這學期結束之前出版,以便趕在下學期上課時使用。

本書全部共15章,初稿Word檔案的頁數總共380頁。最後出版時可能會採用比A4更小的紙張,因此頁數會更多。各章概要請見下表:

本書章節標題 內容摘要
第一部分 數位典藏導論
第一章 數位典藏概論 介紹數位典藏的各種定義,釐清讀者對數位典藏的概念,並引領讀者認識數位典藏的相關計畫。
第二章 數位典藏專案規劃 介紹數位典藏小組需要的成員構成,並從後設資料與系統分析一步一步地規劃數位典藏專案的步驟與細節。
第三章 網站資訊架構 介紹數位典藏資訊系統網站的組織架構原則。包括組織系統、標籤命名系統、導覽系統、搜尋系統、後設資料與控制詞彙等支援元件等。
第四章 後設資料Metadata 說明後設資料的原理以及重要性,並介紹數位典藏常用的後設資料規格與其他參考資源。
第五章 數位資源格式 介紹典藏品數位化與原生數位資源的差異,並解說圖像、聲音、視訊、文件等各種類型的數位資源格式。
第六章 電子資源授權與權限控管 介紹電子資源的授權方式、各種不同的授權條款、以及數位典藏系統的權限控管的規劃建議。
第二部分 數位典藏系統DSpace實作
第七章 DSpace介紹 介紹DSpace的背景,並帶領讀者瀏覽DSpace各種特色功能與網頁使用介面,並介紹以DSpace進行的相關數位典藏應用。
第八章 系統安裝與設定 詳細介紹DSpace安裝與設定手續,讓讀者能夠利用自己的電腦架設DSpace。
第九章 資料內容組織架構 介紹DSpcae的資料內容組織架構架構。從社群、類別、文件、檔案集到檔案各層級與管理的介紹,讓讀者能夠學習如何制訂典藏的數位內容。
第十章 使用者、群組與權限設定 介紹如何建立DSpace的使用者、群組,以及權限控管的設定。
第十一章 遞交作業與工作流程 介紹DSpace中設計與建立數位典藏獨特的遞交作業與工作流程,其中遞交作業還涉及後設資料規範的設定。
第十二章 系統架構與版面修改 剖析DSpace的系統架構,並說明如何閱讀DSpace使用的Java程式碼,然後教導讀者修改網頁使用介面。
第三部分 DSpace數位典藏建置案例
第十三章 臺灣大學數位典藏 介紹臺灣大學數位典藏計畫發展歷程,包括以DSpace修改而成的臺灣大學典藏數位化計畫入口網站以及各種加值應用。
第十四章 臺灣百年圖書館史暨數位圖書館先導計畫 介紹由政治大學圖書資訊與檔案學研究所策劃的「台灣百年圖書館史」。詳細地描述數位典藏專案的各個程序,以供讀者作為規劃的參考。
第十五章 教育部全國通識網課程資料庫 介紹由教育部全國通識網底下的子計畫「課程資料庫」的建置成果。全國通識網課程資料庫含括典藏完整數位課程資料的優質課程資料庫與集合國內各大專院校通識課程資訊的通識課程基本資料庫。

寫書的由來

認識我的朋友們都知道,我這個學生最不像學生,老是接了一堆很奇怪又不賺錢的工作在在身上。從進研究所之前我就接了「臺灣百年圖書館史暨數位圖書館先導計畫」,作到碩一下告一段落,這就是我開始碰DSpace的起源。當時對DSpace不懂,嚴格來說,我對撰寫DSpace的Java語言也不熟。而且DSpace用了很多進階程式技巧的設計模式、將物件導向的優點發揮得淋漓盡致,也很靈活地運用MVC架構、讓程式各司其職,但這些對於當時完全不懂的我來說,要控制DSpace著實讓我花了不少時間與精力。在自我摸索、讀書、不斷地嘗試錯誤之後,我也逐漸能夠掌握DSpace系統。

然後政大圖檔所在2008年暑假舉辦了數位典藏實務與加值服務研習班,這個研習班中也用了DSpace作為教材。當時不僅先幫各個學員預先用虛擬機器安裝好DSpace就已經讓我在實驗室待了好幾個晚上,到教DSpace內容資料架構與metadata遞交表單的設計時,太過複雜的操作方式幾乎讓所有學員都舉了白旗投降。

除了研習班的學員之外,王梅玲老師與陳老師也會在上課時使用DSpace來授課,尤其是王老師會要求學生利用臺灣百年圖書館史暨數位圖書館網站來上傳資料。由於DSpace原始的操作介面實在是很難讓人使用,學生們用起來也是不少怨言。

碩二時陳老師接了教育部「教育部通識教育資源平臺建構與永續發展計畫」,這也是用DSpace來架設課程資料庫與教師資料庫這兩個系統。當時我撰寫了許多教學用投影片教導專任助理們DSpace,並配合計畫需求大幅度地開始改造DSpace的功能。這段期間我在Blog中寫了很多DSpace相關的文章,主要都是給助理們用於計畫中。而作到最後乾脆我自己下海操刀,多媒體轉檔、瀏覽搜尋、管理介面的操作工具等許多功能陸續開發出來。

大概是在碩二下學期時,陳老師提議撰寫本書,而我也覺得這是一個不錯的構想。在歷經各個計畫、授課等經驗之後,我看到了許多需要數位典藏系統的人們。有人需要一個可以用來架設用於機構、計畫使用的數位典藏,有人需要一個可以用來教課、讓學生邊玩邊操作的系統,而我則是有能力將這些需求匯整成一個實際可以用的系統、而且我也希望能將這些年來的成果以一個詳細且實用的方式發佈供人使用,於是就開始了整個寫書的工作。


寫書的經過(前期)

從2009年4月初老師提起這個想法之後,就由我來負責實現。以下聊聊一些令我印象比較深刻的經過:

一開始是制訂整本書的規劃與架構時,還有考慮文學院機構典藏的介紹。但由於文學院機構典藏本身到最後不了了之,最後則刪去不做。

寫書初期時,理論部份有找老師的一位研究助理幫忙。但是該助理對於此主題不甚熟悉,工作效率低落也讓老師看不下去,最後放棄了。

寫書前期規劃好大綱之後,其實實際上並沒有什麼進度,大家都在忙著教育部計畫與課業。直到暑假時(約2009年8月後)學弟妹較為空閒,也有新的學弟陸續加入實驗室,於是正式地分配寫書章節給學弟妹與各個助理。

最先交稿的是第二章數位典藏專案規劃。但由於這個主題其實是相當模糊的概念,與學弟來來往往修改多次之後,在寫書後期才定稿。

原本第三章是談主題分析與檢索系統,負責學妹很快地整理好之後交給我。但是後來我才知道應該擺資訊架構較為合適,最後一整個改頭換面。

第四章後設資料匯整的速度很快,而且架構很清楚,即使寫書完檢查時也覺得很漂亮。負責此章的學妹非常厲害。

第十三章臺灣大學數位典藏也是很快就整理好了。負責此章的研究助理功力一流,資料豐富到讓我覺得擺在這本書裡面似乎有點小廟容不下大佛(?)。

第一章數位典藏概論也是很快就完成了。

至此本書進度仍十分緩慢,特別是第二部份幾乎沒有令人滿意的成果。在2009年末時我大學室友進來擔任計畫助理,這時我也逐漸推掉計畫的工作而專心在寫書上,寫書的進度開始推進。


寫書的經過(中期)

首先是第九章資料內容組織架構,儘管章節內容規劃得很好,但是我卻大幅度地修改了作者的撰寫內容。能熬過我整章全紅且註解一堆(而且寫得很直接orz)的專任助理,實在是非常辛苦,真是抱歉。最後第九章由其他人接手之後,修改多次才完成,算是第二部份最早完成的章節。

第十五章的撰寫也被我改了相當多,但由於負責的專任助理本身就有很不錯的文筆,熟悉我的敘述方式之後,一整章寫下來也非常易讀、好懂。

第十四章原本是由某位專任助理負責,但她整理的方式與效率較低,第一次交稿之後就沒有多大進度。後來交給另一位專任助理完成。至此第三部份大致上完工。

接著該助理著手撰寫學弟無法完成的第五章電子資源授權與權限控管,也很快地把零散地材料重新組織成具有可讀性的章節,組織資料的能力也相當地厲害。

再來是我自己負責的第八章系統安裝與設定。本章內容很好撰寫,但這是我大幅改善DSpace操作工具所帶來的成果。這期間強化了語系檔編輯器、遞交表單編輯、重新啟動Tomcat、電子郵件編輯。還經過陳老師學程上課的實驗,讓整個系統趨於完善。而同時附件光碟的內容也漸趨成型。

接著我進行第十一章遞交作業與工作流程的撰寫,一樣是基於發展了遞交表單編輯器的功能,才能簡單又清楚地把操作方式介紹給讀者。

至此為止,寫書的進度表中,完成的章節甚至不到一半而已。而此時卻面臨另一個難關:2009年年底兩位專任助理即將離職。不過這兩位離職之後仍被我纏著寫稿,真是夠辛苦的了XD


寫書的經過(後期)

第十二章系統架構與版面修改一開始由專任助理負責,但進度十分緩慢。直到2009年底新任教育部助理進來後,我重新制訂了該章大綱,並安排兩人完成。最後再由我統一修整之後完成。

第十章使用者、群組與權限設定在專任助理離職之後努力完成。這次不像第九章那樣修改很多次,而很快地進入完稿階段。

第七章DSpace也是在轉成助教的專任助理努力翻譯之後,交由我修整過後才完成。

這段期間另一位離職的專任助理被我纏著校稿校了好幾章,真是辛苦了。

在這個時間我毅然地決定將第三章改成資訊架構學,而捨棄原本完成的主題分析。原本請離職的專任助理撰寫,但因為他事務繁忙而放棄,最後我將之完成。

第二章數位典藏專案規劃中間隔一段時間沒有進度,然後也是在這段期間完成。

第五章數位資源格式,負責學弟由於事務繁忙,到最後才完稿。

而在初稿完成之後我就著手將附件光碟完工。在撰寫第八章時我就已經把附件光碟的大部分完成,最後則是修正許多安裝上的Bug、重新清理系統,然後燒錄成光碟。

這段期間我的工作就是寫書寫書再寫書,我的噗浪三不五時就是[寫書]文,然後每週或隔週就跟老師通信報告寫書進度。而到今天總算完成整本書的初稿與附件光碟了!

整理與老師寫書進度報告中,從2009年9月14日正式進度報告開始到今天2010年4月17日為止,總共報告了19次。每一次報告由於都會有大量附件,所以得分成多封寄出,Gmail的信件對話串已經長到讓人難以點閱的程度。不過還好有這個進度報告,讓我整理上述的經過時方便許多,也算是一個寶貴的日記吧。


為什麼要寫書?

很多人會問我,其他的研究生都在寫論文,為什麼我在寫書?就算都已經碩三下學期了,都已經延畢一年了,為什麼我還是在寫書?為什麼不要先畢業再來寫?

又有人會問,寫書出版可以賺很多錢吧?版費多少錢啊?做出來的系統可以賣啊,賺大錢。

一開始我會回答說,因為要趁著專任助理還沒離職之前趕快把書寫完。不過在他們離職之後,他們還是被我纏著繼續寫,可見這個理由不太合理(XD)。

我也不會贊成畢業之後再來寫,因為畢業之後要當兵,不碰觸這些東西之後,我一定再也無法把他完成。

書或系統能賣多少錢?這也不是我在乎的問題。事實上,只要這些初稿完成,再怎樣也能找到出版商將之出版成書,所以我不太去煩惱這種問題。

此外,這本書會以多作者的方式出版。老師的名字應該掛第一個,而我的名字也會掛在上面,但其實第幾順位我也不太在意。畢竟如果這本書能夠幫助老師升等,那對實驗室的學弟妹也會有莫大的幫助。

 

我只要能夠出書就好了。

 

以一個還是學生的身份,能夠出一本能在書店裡買得到的書,甚至還能提供給其他學生當教材,或是讓相關領域的專業人員作為參考工具的書,我覺得這是一種自我滿足的成就。

有些人抱有「用機車、腳踏車或甚至走路環島」之類的目標,他們不太在意這到底能不能賺錢、能不能對自己未來有所幫助,只是單純地想要完成這項成就,而我也是如此。他們在畢業後、就業前的空檔進行這個計畫,而我則是在畢業之前、手上握有大量資源與人力的時候進行。

 

當然,我很清楚這個選擇是基於夢想的任性,而不是一種對於現實的理智。

在寫書這段期間,我不計利益得失、也不在乎花費的時間長短,只是努力地讓這本書更豐富、更好閱讀、更容易使用。也許在旁人的眼中這是很笨的行為,而我也很清楚這是事實。這段期間我沒有像其他畢業的同學一樣去工作賺錢,父母還要支付學費給學校。而實驗室內被我佔據的這個角落也一直沒有讓給新進來的學弟妹(雖然我覺得應該也沒人想要坐這邊XD)。老師等著我的標註系統,好多人都在等著我畢業,而我一直辜負著他們的期望。

換個角度來看,這可說是身為學生的一種任性的特權吧。能夠任性地單純作一件自己想做的事情,我想除了現在之外,往後就不會有這種機會了。


寫完書之後

所以寫書告一段落之後,接下來就不會耍任性,好好地努力畢業了嗎?

這個答案可說是,也可說不是。

接下來的確會開始著手規劃論文的標註系統,進度也會在這邊報告。雖然最近可能還會用幾天的時間把寫書的資料整理收拾一下就是。但是由於我論文要寫的也是一個讓人使用的系統,而且這次是重頭開始做起,而在我對於系統相當要求的標準之下,也是需要花很長一段時間來讓論文趨於完善。

與其他趕著畢業而草草完成論文的學生不同,我將會繼續耍任性,任性地寫好論文再畢業。

就如這個Blog的副標題一樣:是的,我正在繞遠路。反正人生繞的路已經夠遠了,似乎也沒差這段距離。就讓我繼續耍任性吧。


很久沒有寫這種日記文了,本篇寫完耗時三個多小時,寫到手有點痠。

在待辦事項裡面還有好多篇Blog要寫,我可能在整理寫書資料的同時,一併把他們寫一寫。

這篇就這樣告一段落啦。呼~~有點累XD

(more...)

開放原始碼數位典藏整合平台發展與建置 / Introduce to DSpace-DLLL: an Open Source Digital Archive System

布丁布丁吃布丁

開放原始碼數位典藏整合平台發展與建置 / Introduce to DSpace-DLLL: an Open Source Digital Archive System

image

這是我在2016年到兩個地方介紹DSpace-DLLL的投影片。一個是在政治大學圖書館舉辦的「數位典藏、數位策展暨數位人文學研習班」,內含實作的3小時課程,另一個是在國立師範大學舉辦的「台北市教師研習中心校史研習班」單純講課的課程。這兩個課程都可以搭配我另外製作的VirtualBox版本DSpace-DLLL虛擬機器來使用,以下提供連結讓有需要的人自由下載。

(more...)

DSpace加強Browse功能的BrowseUtil

布丁布丁吃布丁

DSpace加強Browse功能的BrowseUtil

image

DSpace具備強大的Browse功能,可是唯獨換頁的功能卻只有薄弱的「next」(下一頁)跟「prev」(上一頁)。因此我寫了一支BrowseUtil來提供這方面的功能,也把[dspace-jspui-webapp]/browse/中full.jsp、single.jsp能作到的功能也加了進去,提供程式設計師在修改Browse功能時能夠有靈活的彈性。


安裝BrowseUtil

請下載以下檔案,並放置指定的位置:

  • BrowseUtil.java (SkyDriveMiroko)
    [dspace-source]/dspace-jspui/src/main/java/org/dspace/app/webui/util/BrowseUtil.java
  • BrowseInfo.java (SkyDriveMiroko)
    [dspace-source]/dspace-jspui/src/main/java/org/dspace/browse/BrowseInfo.java
  • full.jsp (SkyDriveMiroko)
    single.jsp (SkyDriveMiroko)
    [dspace-source]/dspace/modules/jspui/src/main/webapp/browse/full.jsp
    [dspace-source]/dspace/modules/jspui/src/main/webapp/browse/single.jsp

然後請重新編譯DSpace,作mvn package跟ant update的動作。

使用BrowseUtil

引用與建立BrowseUtil物件

在JSP檔案裡面,請輸入以下語法以引用BrowseUtil:

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

BrowseUtil物件建立需要輸入兩個參數,個別是HttpServletRequest跟BrowseInfo(這是DSpace的Browse物件),建立範例如下;

<%
BrowseInfo bi = (BrowseInfo) request.getAttribute("browse.info"); //先取得BrowseInfo物件
BrowseUtil bu = new BrowseUtil(request, bi); //建立BrowseUtil
%>

然後我們就可以以這個bu物件來取得連結了。

取得換頁連結
<%
String next = bu.getNextLink(); //下一頁
String last = bu.getLastLink(); //最後一頁
String prev = bu.getPrevLink(); //前一頁
String first = bu.getFirstLink(); //第一頁
%>

取得頁碼

以下語法會取得每一頁頁碼與連結,但是會排除自己的頁碼:

<%= bu.getPagesList() %>

結果如下:

<<first < previous 1 2 3 4 5 6 next > last >>

以下語法會取得該頁前後2頁之內的頁碼:

<%= bu.getPagesLink(2) %>

結果如下:

<<first < previous ... 2 3 4 5 6 ... next > last >>


其他BrowseInfo其實還有小功能,如果有需要的話就請自行看看程式碼囉。寫小功能還是非常讓人愉快的,大家加油!

(more...)

DSpace使用XMLMetadata的方法

布丁布丁吃布丁

DSpace使用XMLMetadata的方法

之前我為DSpace 1.5.1寫過一種新型態的input-type: XMLMetadata,那裡只有處理到遞交(submit)處理,這一篇則是教大家如何利用儲存在資料庫的XMLMetadata API。

我假設你已經懂得如何從DSpace裡面取出你指定的Metadata Value,如果不懂,請參考DSpace系統文件裡面的內容管理API的章節,或是參考我之前寫過如何從DSpace的API裡面取得Item的Metadata Value教學


安裝XMLMetadata API

請把該檔案上傳到[dspace-source]/dspace-api/src/main/java/org/dspace/app/util/當中。

然後進行DSpace的重新編譯,方法如下:

  1. 進入指令模式
  2. 移動到你的[dspace-source]/dspace/目錄
    > cd [dspace-source]/dspace/
  3. 執行ant編譯
    > mvn package
  4. 移動到你的[dspace-source]/dspace/target/dspace-[version].dir目錄
    > [dspace-source]/dspace/target/dspace-[version].dir
  5. 執行ant打包
    > ant -Dconfig=[dspace]/config/dspace.cfg update
  6. 停止你的Tomcat伺服器
    > cd [tomcat]/bin/
    > ./shutdown.sh
  7. 複製新的.war檔案到Tomcat的webpapps目錄:
    > \cp -rf [dspace]/webapps/* [tomcat]/webapps/
  8. 重新啟動Tomcat伺服器
    > cd [tomcat]/bin/
    > ./startup.sh

測試是否安裝成功

請把該檔案放到你的DSpace在Tomcat的執行位置,然後用網址開啟該檔案看看。

例如[tomcat]/webapps/jspui/裡面。你用http://localhost:8080/jspui/XMLMetadataExample.jsp開啟,如果出現錯誤訊息表示安裝失敗。


使用XMLMetadata API

示範檔案:XMLMetadataExample.jsp

  1. 先引用org.dspace.app.util.XMLMetadata。
    <%@ page import="org.dspace.app.util.XMLMetadata" %>
  2. 從資料庫或是利用DSpace的API取得XMLMetadata的值,存入字串型態的變數當中,假如是設為xmlText。(其中rs.getString()是從資料庫查詢結果取出資料的語法,實際使用的時候,請自行設計)。
    ※以下是JSP端的程式,請寫在<% %>之間。
    String xmlText = rs.getString();
    假設取得的XMLMetadata值如下:
    <div class=\"xml-root\"><DIV class=node>
    <DIV class=node-type>node</DIV>
    <DIV class=node-title>教師</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-node</DIV>
    <DIV class=node-content-temp>
    <DIV class=node>
    <DIV class=node-type>node</DIV>
    <DIV class=node-title>人名</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-node</DIV>
    <DIV class=node-content-temp>
    <DIV class=node>
    <DIV class=node-type>input</DIV>
    <DIV class=node-title>姓</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-input</DIV>
    <DIV class=input-default-value>aaaaa2 </DIV>
    <DIV class=input-required>true</DIV>
    <DIV class=input-type>onebox</DIV>
    <DIV class=input-values>aaaaa2 </DIV></DIV>
    <DIV class=node>
    <DIV class=node-type>input</DIV>
    <DIV class=node-title>名</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-input</DIV>
    <DIV class=input-default-value>1 </DIV>
    <DIV class=input-required>false</DIV>
    <DIV class=input-type>onebox</DIV>
    <DIV class=input-values>1 </DIV></DIV></DIV>
    <DIV class=node-contents>
    <DIV class=node>
    <DIV class=node-type>input</DIV>
    <DIV class=node-title>姓</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-input</DIV>
    <DIV class=input-default-value>aaaaasdsdsdf </DIV>
    <DIV class=input-required>false</DIV>
    <DIV class=input-type>onebox</DIV>
    <DIV class=input-values>aaaaasdsdsdf </DIV></DIV>
    <DIV class=node>
    <DIV class=node-type>input</DIV>
    <DIV class=node-title>名</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-input</DIV>
    <DIV class=input-default-value>2 </DIV>
    <DIV class=input-required>false</DIV>
    <DIV class=input-type>onebox</DIV>
    <DIV class=input-values>2 </DIV></DIV></DIV>
    <DIV class=node-contents>
    <DIV class=node>
    <DIV class=node-type>input</DIV>
    <DIV class=node-title>姓</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-input</DIV>
    <DIV class=input-default-value>aaaaa2 </DIV>
    <DIV class=input-required>false</DIV>
    <DIV class=input-type>onebox</DIV>
    <DIV class=input-values>aaaaa2 </DIV></DIV>
    <DIV class=node>
    <DIV class=node-type>input</DIV>
    <DIV class=node-title>名</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-input</DIV>
    <DIV class=input-default-value>1 </DIV>
    <DIV class=input-required>false</DIV>
    <DIV class=input-type>onebox</DIV>
    <DIV class=input-values>1 </DIV></DIV></DIV></DIV></DIV>
    <DIV class=node-contents>
    <DIV class=node>
    <DIV class=node-type>node</DIV>
    <DIV class=node-title>人名</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-node</DIV>
    <DIV class=node-content-temp>
    <DIV class=node>
    <DIV class=node-type>input</DIV>
    <DIV class=node-title>姓</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-input</DIV>
    <DIV class=input-default-value>aaaaa2 </DIV>
    <DIV class=input-required>false</DIV>
    <DIV class=input-type>onebox</DIV>
    <DIV class=input-values>aaaaa2 </DIV></DIV>
    <DIV class=node>
    <DIV class=node-type>input</DIV>
    <DIV class=node-title>名</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-input</DIV>
    <DIV class=input-default-value>1 </DIV>
    <DIV class=input-required>false</DIV>
    <DIV class=input-type>onebox</DIV>
    <DIV class=input-values>1 </DIV></DIV></DIV>
    <DIV class=node-contents>
    <DIV class=node>
    <DIV class=node-type>input</DIV>
    <DIV class=node-title>姓ewrwere</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-input</DIV>
    <DIV class=input-default-value>aaaaa </DIV>
    <DIV class=input-required>true</DIV>
    <DIV class=input-type>onebox</DIV>
    <DIV class=input-values>aaaaa </DIV></DIV>
    <DIV class=node>
    <DIV class=node-type>input</DIV>
    <DIV class=node-title>名</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-input</DIV>
    <DIV class=input-default-value>2 </DIV>
    <DIV class=input-required>false</DIV>
    <DIV class=input-type>onebox</DIV>
    <DIV class=input-values>2 </DIV></DIV></DIV>
    <DIV class=node-contents>
    <DIV class=node>
    <DIV class=node-type>input</DIV>
    <DIV class=node-title>姓</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-input</DIV>
    <DIV class=input-default-value>aaaaa2 </DIV>
    <DIV class=input-required>false</DIV>
    <DIV class=input-type>onebox</DIV>
    <DIV class=input-values>aaaaa2 </DIV></DIV>
    <DIV class=node>
    <DIV class=node-type>input</DIV>
    <DIV class=node-title>名</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-input</DIV>
    <DIV class=input-default-value>1 </DIV>
    <DIV class=input-required>false</DIV>
    <DIV class=input-type>onebox</DIV>
    <DIV class=input-values>1 </DIV></DIV></DIV></DIV></DIV>
    <DIV class=node-contents>
    <DIV class=node>
    <DIV class=node-type>node</DIV>
    <DIV class=node-title>人名</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-node</DIV>
    <DIV class=node-content-temp>
    <DIV class=node>
    <DIV class=node-type>input</DIV>
    <DIV class=node-title>姓</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-input</DIV>
    <DIV class=input-default-value>aaaaa2 </DIV>
    <DIV class=input-required>false</DIV>
    <DIV class=input-type>onebox</DIV>
    <DIV class=input-values>aaaaa2 </DIV></DIV>
    <DIV class=node>
    <DIV class=node-type>input</DIV>
    <DIV class=node-title>名</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-input</DIV>
    <DIV class=input-default-value>1 </DIV>
    <DIV class=input-required>false</DIV>
    <DIV class=input-type>onebox</DIV>
    <DIV class=input-values>1 </DIV></DIV></DIV>
    <DIV class=node-contents>
    <DIV class=node>
    <DIV class=node-type>input</DIV>
    <DIV class=node-title>姓</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-input</DIV>
    <DIV class=input-default-value>aaaaasdsdsdf </DIV>
    <DIV class=input-required>false</DIV>
    <DIV class=input-type>onebox</DIV>
    <DIV class=input-values>黃</DIV></DIV>
    <DIV class=node>
    <DIV class=node-type>input</DIV>
    <DIV class=node-title>名</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-input</DIV>
    <DIV class=input-default-value>2 </DIV>
    <DIV class=input-required>false</DIV>
    <DIV class=input-type>onebox</DIV>
    <DIV class=input-values>2 </DIV>
    <DIV class=input-values>2 </DIV>
    <DIV class=input-values>2 </DIV>
    <DIV class=input-values>2 </DIV></DIV></DIV>
    <DIV class=node-contents>
    <DIV class=node>
    <DIV class=node-type>input</DIV>
    <DIV class=node-title>姓</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-input</DIV>
    <DIV class=input-default-value>aaaaa2 </DIV>
    <DIV class=input-required>false</DIV>
    <DIV class=input-type>onebox</DIV>
    <DIV class=input-values>aaaaa2 </DIV></DIV>
    <DIV class=node>
    <DIV class=node-type>input</DIV>
    <DIV class=node-title>名</DIV>
    <DIV class=node-repeatable>true</DIV>
    <DIV class=node-class>table-input</DIV>
    <DIV class=input-default-value>1 </DIV>
    <DIV class=input-required>false</DIV>
    <DIV class=input-type>onebox</DIV>
    <DIV class=input-values>1 </DIV>
    <DIV class=input-values>1 </DIV>
    <DIV class=input-values>1 </DIV></DIV></DIV></DIV></DIV></DIV>
    </div>
    ※你可能注意到了上面的XMLMetadata並不是正規的XML:他缺少了開頭的宣告,而屬性class的值也沒有正確的雙引號。這是使用IE瀏覽器在控制input-type的XMLMetadata時最後必然的結果。所以本XMLMetadata API在設計時已經考慮到這點,這些不正規的Metadata資料會被重新整理成正規的XML格式,最後再進行分析。
  3. 建立XMLMetadata物件,並且給予XMLMetadata的值。
    XMLMetadata xmlObj = new XMLMetadata();
    xmlObj.setXMLdoc(xmlText);
  4. 設定你要在XMLMetadata當中找尋的路徑。請以每個節點的node-title為路徑名稱,中間用「/」來隔開。例如你要找的是在「教師」、「人名」、「姓」當中的資料,那麼請如下設定你的路徑變數:
    String path = "教師/人名/姓";
    注意你的根節點他也需要一個node-title!可是偶爾還是會有忘記設定node-title的時候,當該層沒有node-title之時,可以考慮直接空下來,繼續寫下一層。例如你根節點的node-title原本應該寫「教師」但是卻忘記寫了,那麼你的路徑就要這樣設:
    String path = "/人名/姓";
  5. 接著你就可以用API的方法來取得你的資料了。以下一一介紹各種方法:
    1. 你可以取得查詢的資料,以陣列的字串或是陣列的整數來回傳:
      String[] valueAry = xmlObj.locate(path);
      int[] valueIntAry = xmlObj.locateInt(path);
    2. 你可以取得資料的數量,假如有很多位教師,可以查詢到底有幾筆教師的:
      int count = xmlObj.locateCountNode("教師");
    3. 如果你明確知道要哪一筆,那麼也可以設定偏移值,第一筆則設定0,第二筆則設定1。如果偏移直超過查詢結果的數量,則會回傳「null」:
      int offset = 1;	
      String valueSingle = xmlObj.locateSingle(path, offset);
      int valueIntSingle = xmlObj.locateIntSingle(path, offset);
    4. 你也可以用XPath上來找尋資料:
      String[] valueAry = xmlObj.locateXPath(XPath);

      善用XPath來作更進一步的查詢

      聰明的你也許發現到前面locate所用的路徑查詢語法並不是正確的XPath查詢語法,而是我為簡化查詢XMLMetadata而設計的方法。

      舉例來說,剛剛查詢「教師/人名/姓」的語法,利用XPath查詢XMLMetadata則會非常地複雜。你可以利用public String titlePathToXPath(String titlePath)來看一下XMLMetadata的路徑是怎麼轉換成完整的XPath:

      String path = "教師/人名/姓";
      String XPath = "/div[@class='xml-root']/DIV[@class='node'][DIV[@class='node-title']/text() ='教師']/DIV[@class='node-contents']/DIV[@class='node'][DIV[@class='node- title']/text()='人名']/DIV[@class='node-contents']/DIV[@class='node'][DIV [@class='node-title']/text()='名']/DIV[@class='input-values']/text()";
      out.print(xmlObj.titlePathToXPath(path));  //Show full XPath

      因為時間不多,XMLMetadata的查詢語法並不是很完整。如果你需要更完整的查詢功能,那麼你得需要自行撰寫XPath才行。

      詳細的XPath教學,可以參考w3schools.com的XPath教學


      光是為了寫這份文件就花了我一整天,好累……

      (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...)