Tóm tắt: Loạt bài viết này trình bày chi tiết việc tạo ra một ứng dụng Mashup
cho phép kiểm soát các dữ liệu được hiển thị với người sử dụng. Bây giờ bạn biết
làm thế nào để tạo một bản thể luận (ontology) để xác định khái niệm đại diện của
một dịch vụ, bạn có thể cho phép người dùng lựa chọn dịch vụ mà họ muốn sử
dụng
92 trang |
Chia sẻ: tlsuongmuoi | Lượt xem: 2011 | Lượt tải: 1
Bạn đang xem trước 20 trang tài liệu Đề tài Các dịch vụ Web và Web ngữ nghĩa - Phần 5, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
g các biểu thức XPath trong các
mảng elementValues và các giá trị thuộc tính attributeValues.
Trong trường hợp này, bạn cũng có thể thấy phần gắn thêm của một dịch vụ thứ
hai và được thể hiện bởi thành tố dịch vụ con subservice.
Các bài viết trước: các tính năng tiên tiến
Trong Phần 2, bạn phát triển phần ứng dụng hơn là tạo ra một yêu cầu Web cho tất
các các yêu cầu dịch vụ - đây là một quá trình có thể kéo dài đến vài phút nếu
phần mashup tạo ra nhiều yêu cầu - bạn bắt đầu lưu giữ các kết quả yêu cầu trong
cơ sở dữ liệu XML có sử dụng khả năng pureXML mới của DB2. Điều này cho
phép bạn kiểm tra một cơ sở dữ liệu cho một yêu cầu cụ thể trước khi chạy
Mashup và tạo một cái mới.
Nhưng mục tiêu tổng quát là tạo ra một dịch vụ thông minh – với nó người sử
dụng có thể yêu cầu một kiểu dữ liệu cụ thể - như sách, giá...- và mashup sẽ hiểu
làm thế nào để tìm được cho dù vấn đề không phải là bạn sử dụng dịch vụ nào.
Để làm được điều này, ở Phần 3 và 4, bạn sẽ học cách tạo bản thể luận hoặc phân
loại các khái niệm. Bằng cách này, bạn có thể định nghĩa các khái niệm như cuốn
sách, giá cả,… để cung cấp một hình thức chung và sắp xếp từ đó bạn có thể xử lý
từng kiểu dịch vụ chứ không phải chỉ là từng dịch vụ.
Ở phần 4, bạn đã tạo ra một bản thể luận của hiệu sách có rất nhiều các khái niệm,
định nghĩa mà bạn có thể tìm thấy trong các hiệu sách điện tử, như sách, DVD,
cho rất nhiều khái niệm có thể được tìm kiếm từ các lưu trữ điện tử như sách,
DVD, tác giả...ở phần hướng dẫn bạn có thể bắt đầu thêm vào các dữ liệu thực tế
cho bản thể luận này.
Bản thể luận cơ sở
Bản thể luận cở sở trông tương tự như sau (xem ví dụ 2).
Ví dụ 2. Bản thể luận cơ sở
<!DOCTYPE rdf:RDF [
]>
<rdf:RDF
xmlns = ""
xmlns:store = ""
xml:base = ""
xmlns:owl = ""
xmlns:rdf = ""
xmlns:rdfs= ""
xmlns:xsd = ""
>
An example OWL ontology for Online Bookstores (The
Ultimate Mashup: Part #4)
BookStore Ontology
Web Service
<owl:minCardinality
rdf:datatype="&xsd;nonNegativeInteger">1
Online Store
Bookstore
Product sold at online store
Book
<owl:minCardinality
rdf:datatype="&xsd;nonNegativeInteger">1
Movie
Person
Author
<owl:minCardinality
rdf:datatype="&xsd;nonNegativeInteger">1
Director
Bạn sẽ không sử dụng tất cả các định nghĩa này trong phần hướng dẫn, nhưng điều
quan trọng cần nhận biết là cấu trúc, một kho Store chứa StockItems có thể ví dụ
là Book, Movie và vân vân. Theo cách này bạn có thể xác định một Book một cách
khái quát, các thiết lập thuộc tính về tác giả, nhà xuất bản,…nhưng vẫn còn sự
khác biệt về giá cả và thông tin giao hàng phụ thuộc vào các kho hàng mà từ đó
khách hàng mua sách.
Nhớ là chúng chỉ là các định nghĩa. Dữ liệu thực tế bao gồm các cá thể hoặc
những ví dụ cho mỗi lớp. Ví dụ (xem ví dụ 3).
Ví dụ 3. Các cá thể của bản thể luận
...
<itemPrice rdf:datatype=""
>29.99
Harry Potter and the Sorcerers
Stone
<stockedProduct
rdf:resource="#Harry_Potter_and_the_Sorcerers_Stone" />
<bundledWith
rdf:resource="#Harry_Potter_and_the_Sorcerers_Stone"/>
...
Bạn có thể đặt những cá thể này trong tệp riêng của chúng hoặc trong cùng một
tệp của các định nghĩa; điều quan trọng là các không gian tên phải phù hợp với
nhau.
Trong bài viết này, bạn sẽ tạo các cá thể từ dữ liệu chiết xuất được từ các dịch vụ
Web cụ thể.
Cài đặt
Bài viết này giả định rằng bạn đã có một hệ thống mashup được cài đặt và đang
làm việc, đồng thời có hoặc không có bộ nhớ cơ sở dữ liệu DB2. Để biết thêm
thông tin về việc thiết lập Tomcat và các thành phần khác, xem Phần 1 và Phần 2
của loạt bài viết (xem Tài nguyên).
Bạn cũng có thể cần đến Jena API để hoàn thành các đoạn mã trong bài viết này.
Có thể tải Jena từ Để cài đặt, đơn giản chỉ cần thêm
các tệp Jena *.jar vào đường dẫn lớp (class path).
bài viết này sử dụng các dịch vụ giao diện của Amazon Web làm ví dụ. Để thực
hiện việc mã hóa, bạn cần có các biểu tượng phát triển (developers token), và thay
thế chuỗi các số 0 (000000000000000) trong mã bằng công cụ đó. Để có biểu
tượng phát triển, xem
ạo cho người sử dụng sự lựa chọn: giao diện
Mục đích của bài viết này là cung cấp một phương thức cho người dùng thay thế
một dịch vụ bằng một dịch vụ khác dựa trên thông tin trong bản thể luận. Hãy bắt
đầu bằng việc cho người dùng một lựa chọn.
Tạo ra các cá thể
Bước đầu tiên là tạo một cá thể từ đó khách hàng sẽ lựa chọn. Bạn sẽ phải tạo ra
các trường hợp cá biệt của các lớp Bookstore. Ví dụ, tệp bản thể luận hiện nay
nhìn giống như ví dụ 4.
Ví dụ 4. Tạo ra các cá thể
<Book
rdf:ID="Harry_Potter_and_the_Sorcerers_Stone">
<writtenBy
rdf:resource="#J_K_Rowling"/>
Nhưng tất nhiên chúng hiện chỉ đơn thuần là Bookstores. Sau đó, bạn phải thêm
thuộc tính cho chúng
Ghi nhớ là bạn có vài cá thể ở đây và có nhiều loại khác nhau. Bạn phải sử dụng
API để kiểm tra các đối tượng này.
Tạo ra mô hình
Để trông gọn gàng hơn một chút, bạn sẽ phải điều chỉnh tất cả các chức năng bản
thể luận ở trong một lớp mới, MashupOntologyReader. Bắt đầu bằng việc tạo ra
lớp cơ bản (xem ví dụ 5):
Ví dụ 5. Lớp cơ bản
import com.hp.hpl.jena.ontology.*;
import java.util.Iterator;
import com.hp.hpl.jena.rdf.model.ModelFactory;
public class MashupOntologyReader {
private OntModel bookStoreOntModel;
public MashupOntologyReader(){
// create an ontology model
bookStoreOntModel =
ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
}
public static void main(String[] args) {
MashupOntologyReader reader = new MashupOntologyReader();
}
}
Ở đây bạn sử dụng ModelFactory để tạo một mô hình bản thể luận. Lưu ý là Jena
API đồng thời cũng là một RDF API, cho nên nó cho phép bạn tạo ra rất nhiều
kiểu mô hình khác nhau. Bình thường, trong trường hợp này, bạn cần một mô hình
bản thể luận, và thông qua các dữ liệu cố định được cung cấp, bạn phải xác định rõ
là bạn muốn nó nằm bên trong bộ nhớ.
Tải bản thể luận
Jena API cho phép bạn tạo các bản thể luận từ đầu và bao gồm các phương thức
cần thiết để thực hiện, trong trường hợp này, bạn đã có sẵn một tệp bản thể luận để
đọc, cho nên bước tiếp theo là tải nó từ mô hình bạn vừa tạo ra (xem ví dụ 6):
Ví dụ 6. Tải bản thể luận
...
public class MashupOntologyReader {
private OntModel bookStoreOntModel;
public MashupOntologyReader(){
String source = "";
// create an ontology model
bookStoreOntModel =
ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
// you have a local copy of the bookstore ontology
bookStoreOntModel.getDocumentManager().addAltEntry( source,
"file:c:/sw/stores.owl" ); //
read the source document bookStoreOntModel.read( source );
}
public static void main(String[] args) {
MashupOntologyReader reader = new MashupOntologyReader();
}
}
Đầu tiên, hãy dành chỗ ghi tên cho đối tượng bạn vừa tải. Với bản thể luận bạn đã
xây dựng ở phần 4, không gian tên là Từ đó bạn sử
dụng của mô hình DocumentManager để thêm vào các đầu mục. Lưu ý rằng bạn
chỉ rõ không gian tên và tập tin mà từ đó cho phép thâm nhập, nhưng các mô hình
không thực sự đọc các định nghĩa trừ khi bạn gọi hàm read().
Duyệt qua các cá thể
Mục tiêu là có được danh sách các cá thể Bookstore trong bản thể luận, vì thế bắt
đầu bằng việc đi qua chuỗi tất cả các cá thể có mặt (xem ví dụ 7).
Ví dụ 7. Duyệt các cá thể
...
// read the source document
bookStoreOntModel.read( source );
}
public void getIndividuals(){
int counter = 0;
for (Iterator i = bookStoreOntModel.listIndividuals(); i.hasNext(); ) {
counter++;
Individual thisIndividual = (Individual) i.next();
System.out.println(counter);
}
}
public static void main(String[] args) {
MashupOntologyReader reader = new MashupOntologyReader();
reader.getIndividuals();
}
}
Để bắt đầu, cần tạo ra một phương thức getIndividuals() mà nó sẽ tạo ra một bộ
đếm và sử dụng mô hình của phương thức listIndividuals() của bản thể luận để lấy
bộ lặp Iterator chuẩn của JAVA qua nó bạn có thể tiếp cận các cá thể tìm được.
Bạn chưa có bất kỳ một dữ liệu nào về các cá thể do đó đơn giản cung cấp một bộ
đếm để xem điều gì xảy ra. Bạn sẽ có một danh sách từ một đến mười một.
Bây giờ mọi việc đều thú vị, rõ ràng bạn có nhiều hơn là các cá thể Bookstore.
Hãy tìm hiểu xem bạn thật sự thu được cái gì.
Có các thông tin về cá thể
Khi có thông tin tham khảo của cá thể, việc thu thập các thông tin của nó là vấn đề
đơn giản thông qua sử dụng các phương thức thu thập mà API cung cấp. Bất kỳ
một cá thể Individual nào, cho dù là loại đối tượng nào, đều có ba loại thông tin
giống nhau: URI, sử dụng duy nhất để xác định tài nguyên, kiểu, và tên, cái mà
tương ứng với thuộc tính rdf:ID trong tệp RDF (xem ví dụ 8):
Ví dụ 8. Lấy thông tin cá thể
...
public void getIndividuals(){
int counter = 0;
for (Iterator i = bookStoreOntModel.listIndividuals(); i.hasNext(); ) {
counter++;
Individual thisIndividual = (Individual) i.next();
String indType = thisIndividual.getRDFType().getLocalName();
String indName = thisIndividual.getLocalName();
String indResourceURI = thisIndividual.getURI();
System.out.println(indType + " " + indName + " " +
indResourceURI);
}
}
...
Bạn cần chú ý đầu ra trông giống với Ví dụ 9:
Ví dụ 9. Đầu ra thông tin cá thể
0: Book Harry_Potter_and_the_Sorcerers_Stone
1: Genre Memoir
2: Genre Philosophy
3: Genre History
4: Genre Nonfiction
5: Genre Fiction
6: Author Fyodor_Dostoevsky
7: Author Joanne_Rowling
8: Author J_K_Rowling
9: Bookstore Buy.com
10: Bookstore Amazon.com
11: Bookstore BarnesAndNoble.com
Chú ý rằng thứ tự các cá thể xuất hiện ở đầu ra thì không cần thiết phải giống với
thứ tự chúng xuất hiện trong tệp bản thể luận. Hiện giờ chúng không là vấn đề,
nhưng nếu nhúng dữ liệu vào mẫu (template) thì sẽ có vấn đề. May mắn là nếu
biết trước là sẽ được chuẩn bị trước và đây là vấn đề có thể xử lý dễ dàng.
Tại thời điểm này bạn chỉ lo lắng về chuyện thu thập các cá thể Bookstore.
Chỉ lấy ra các Bookstores
Sự thật là các kiểu tài nguyên được đại diện như một chuỗi (string) sẽ tạo điều
kiện dễ dàng để lấy ra Bookstores hoặc bất kỳ kiểu cụ thể nào (xem ví dụ 10):
Ví dụ 10. Chiết xuất chỉ một loại cá thể
...
public Individual[] getIndividuals(String individualType){
int counter = -1;
Individual[] individuals = new Individual[50];
for (Iterator i = bookStoreOntModel.listIndividuals(); i.hasNext(); ) {
Individual thisIndividual = (Individual) i.next();
String indType = thisIndividual.getRDFType().getLocalName();
String indName = thisIndividual.getLocalName();
String indResourceURI = thisIndividual.getURI();
if (indType.equals(individualType)){
counter++;
individuals[counter] = thisIndividual;
System.out.println(counter + ": " + indType + " " + indName +
" " + indResourceURI);
}
}
return individuals;
}
public static void main(String[] args) {
MashupOntologyReader reader = new MashupOntologyReader();
Individual[] individuals = reader.getIndividuals("Bookstore");
}
}
Trong trường hợp này, bạn kiểm tra kiểu đã gửi đến so với loại của từng cá thể, và
nếu cá thể là một trong những loại bạn đang tìm kiếm thì bạn chuyển nó vào mảng
các individuals. Sau khi bạn xem tất cả các cá thể, quay trở lại mảng như là đầu ra
của phương thức.
Bước tiếp theo là thêm tính năng này vào ứng dụng thực sự.
Tạo ra một thực đơn từ danh sách các dịch vụ
Tại thời điểm này, bạn đã sẵn sàng tiếp cận với các khả năng của Jena từ trong các
ứng dụng thật của web. Trước khi bạn bắt đầu, phải chắc chắn rằng các tệp *.jar
đều có thể truy cập vào từ ứng dụng của web và lớp MashupOntologyReader có
sẵn cho servlet. Bổ sung chức năng sau vào phương thức doGet() (xem ví dụ 11):
Ví dụ 11. Tạo ra một mẫu chọn thực đơn
protected void doGet(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
MashupOntologyReader reader = new MashupOntologyReader();
Individual[] individuals = reader.getIndividuals("Bookstore");
response.getWriter().print("");
response.getWriter().print("");
response.getWriter().print("");
response.getWriter().print("The Mashup");
response.getWriter().print("<form action='MashupClientServlet'
method='post'>");
response.getWriter().print("Choose a bookstore:");
response.getWriter().print("");
for (int i = 0; i < individuals.length; i++){
Individual thisIndividual = individuals[i];
if (thisIndividual != null){
String id = thisIndividual.getURI();
System.out.println("["+id+"]");
String label = thisIndividual.getLocalName();
System.out.println("["+label+"]");
response.getWriter().print("<option "+
"value=\""+id+"\">"+label+"");
}
}
response.getWriter().print("");
response.getWriter().print("Enter a keyword:");
response.getWriter().print("");
response.getWriter().print("");
response.getWriter().print("");
response.getWriter().print("");
response.getWriter().print("");
}
Đầu tiên, tạo một thể hiện của lớp MashupOntologyReader, cái mà cũng tải bản
thể luận thực sự. Từ đó bạn có thể sử dụng phương thức getIndividuals() bạn vừa
tạo ra để thu được một mảng Bookstore. Khi bạn đã có mảng Bookstore bạn có thể
lặp vòng chúng nếu bạn muốn các mảng khác sử dụng cùng phương thức trước khi
thu lại được URI và tên hoặc ID. Sử dụng chúng để tạo ra thực đơn HTML select
trong mẫu có sẵn.
Kết quả cuối cùng trông giống hình 1
Hình 1. Thêm vào hộp lựa chọn
Gửi biểu mẫu và dịch vụ đầu ra
Lấy dịch vụ mà người sử dụng muốn sử dụng là việc rất giản đơn. Thực tế, nó
không khác với lấy lại bất cứ thông tin nào đã gửi từ một biểu mẫu (xem ví dụ 12):
Ví dụ 12. Lấy lại thông tin từ mẫu thông tin
...
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
String query = request.getParameter("query").toString();
String serviceURI = request.getParameter("serviceURI").toString();
Service service = ont.obtainServiceInfo(serviceURI);
response.getWriter().print("Results pulled from "
+serviceURI+"");
try {
DocumentBuilder builder =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
...
Một cách đơn giản, lấy serviceURI như là một tham số từ mẫu. Bạn có thể cung
cấp nó tới trang để bảo đảm nó hoạt động được.
Bây giờ bạn có thể sẵn sàng lấy lại thông tin dịch vụ thực tế.
Lấy lại dịch vụ thông tin từ bản thể luận
Giờ bạn đã biết loại dịch vụ nào người sử dụng muốn dùng, bạn sẽ cần phải lấy
thông tin về nó từ bản thể luận. Để làm vậy, bạn cần thêm API đối với phương
thức doPost().
Bổ sung thông tin dịch vụ vào bản thể luận
Khi bạn xây dựng bản thể luận ở Phần 4, đã bao gồm thông tin dịch vụ căn bản,
nhưng bây giờ phải chi tiết hơn một chút. Đặc biệt, phải thêm vào các thông tin bổ
sung về dịch vụ, chẳng hạn như mẫu và bản ghi dữ liệu hiển thị đang tồn tại ở thời
điểm lớp Service hiện tại cũng như một cách để tập hợp các tham số bổ sung cho
một dịch vụ, chẳng hạn như các kiểu tìm kiếm hoặc một mã phát triển (developer
token).
Ví dụ 13. Làm rõ trên định nghĩa về dịch vụ
...
Web Service
<owl:minCardinality rdf:datatype=
"&xsd;nonNegativeInteger">1
<owl:minCardinality rdf:datatype=
"&xsd;nonNegativeInteger">1
<rdfs:range rdf:resource=
""/>
Web Service Parameter Map
<owl:cardinality
rdf:datatype="&xsd;nonNegativeInteger">1
<owl:cardinality
rdf:datatype="&xsd;nonNegativeInteger">1
...
Bất cứ thông tin nào như mẫu ghi các hồ sơ hiển thị (ở đây gọi là rootnode) khá là
dễ hiểu. Bạn chỉ cần thêm vào như một thuộc tính của lớp. Ở một số trường hợp,
tình trạng không đơn giản như thế. Ví dụ, nhập các thông số đầu vào cần cả tên và
giá trị, cho nên bạn phải xây dựng cấu trúc để có đủ các thông tin như vậy.
Trong trường hợp này, cấu trúc này được gọi là ServiceParameterMap.
ServiceParameterMap tham chiếu với tài nguyên paramname và paramvalue. Với
toàn bộ các thuộc tính đã được tạo ra, bây giờ bạn có thể thiết lập các cá thể thực
tế.
Dịch vụ riêng biệt trong bản thể luận
Tạo các cá thể dịch vụ thực tế khá đơn giản, chỉ cần theo cấu trúc các lớp (xem ví
dụ 14).
Ví dụ 14. Tạo ra cá thể hiệu sách
/ItemSearchResponse/Items/Item
<![CDATA[
TBD
]]>
<![CDATA[
by
]]>
ItemAttributes/Title!ItemAttributes/Author
DetailPageURL
Title
Service
AWSECommerceService
AWSAccessKeyId
000000000000000
SearchIndex
Books
ResponseGroup
Large
Operation
ItemSearch
Một số đặc tính, ví dụ mẫu và elementValue bạn cần nhận ra từ lớp Service. Các
lớp khác, ví dụ như tài nguyên inputparameter là mới và được tạo ra như là các ví
dụ riêng biệt của lớp ServiceParameterMap, sau đó được tham khảo từ trong phần
chính của cá thể dịch vụ như đặc tính inputparameter.
Ngoài ra có vẻ sẽ là tốt nếu thêm mỗi elementValue và attributeValue trong chính
đặc tính của nó, nó sẽ gây ra rắc rối vì bạn không thể dự đoán thứ tự nào chúng có
thể được lấy lại, nhưng bạn phải chắc chắn thứ tự mà chúng xuất hiện. Để xử lý
vấn đề này, bao gồm cả tất cả các giá trị, được tách ra bởi một dấu chấm than (!).
Dấu chấm than có vẻ sẽ không xuất hiện trong các biểu thức XPath, mà sau này
bạn có thể sử dụng nó như là một dấu phân cách.
Chú ý bạn có thể đơn giản cho thêm vào một tham số đối với điểm cuối cùng,
nhưng làm như vậy bạn sẽ có rất nhiều lợi ích. Một là bạn có thể chọn linh hoạt
các tham số như là nguyên tắc của nhân tố phát triển (developer key), hai là cấu
trúc của bạn được đồng nhất hơn và do đó dễ dàng trong việc áp dụng các ứng
dụng cho các dịch vụ SOAP cũng nhưng REST.
Bây giờ hãy nhìn các thông tin thu được.
Thu lại các cá thể
Bước đầu tiên là tìm các tham khảo đối với tài nguyên đại diện cho cá thể ở trong
bản thể luận. Do các giá trị quay lại bởi hộp lựa chọn là URI cho tài nguyên, việc
lựa chọn là tương đối dễ dàng (xem ví dụ 15):
Ví dụ 15. Thu lại các cá thể
...
public class MashupOntologyReader {
private OntModel bookStoreOntModel;
public MashupOntologyReader(){
...
}
public Individual[] getIndividuals(String individualType){
...
return individuals;
}
public void obtainServiceInfo(String serviceURI){ Individual bookstore =
bookStoreOntModel.getIndividual(serviceURI);
}
}
public static void main(String[] args) {
MashupOntologyReader reader = new MashupOntologyReader();
Individual[] individuals = reader.getIndividuals("Bookstore");
reader.obtainServiceInfo( "");
}
}
Tạo một phương thức mới, obtainServiceInfo() trong lớp MashupOntologyGreater
và sử dụng phương thức getIndividual() để lấy lại tài liệu tham khảo đối với tài
nguyên cụ thể.
Từ đây bạn có thể lấy ra các thông tin về chính dịch vụ đó.
Thu lại các tham số dịch vụ
Các tham biến dịch vụ được lưu như là đặc tính của tài nguyên đại diện cho dịch
vụ do đó bạn phải tiếp cận những đặc tính này để lấy thông tin (xem ví dụ 16):
Ví dụ 16. Lấy các tham biến dịch vụ
...
public class MashupOntologyReader {
private OntModel bookStoreOntModel;
public MashupOntologyReader(){
...
}
public Individual[] getIndividuals(String individualType){
...
return individuals;
}
public void obtainServiceInfo(String serviceURI){
Individual bookstore =
bookStoreOntModel.getIndividual(serviceURI);
for (StmtIterator i = bookstore.listProperties( );
i.hasNext(); ) {
Statement s = i.nextStatement();
Property p = s.getPredicate();
if (p.canAs(OntProperty.class)){
Resource r;
Literal l;
if (p.getLocalName().equals("endpoint")){
l = s.getLiteral();
System.out.println( p.getLocalName() + " ==> "
+ l.getString() );
}
else if (p.getLocalName().equals("rootoutputnode")){
l = s.getLiteral();
System.out.println( p.getLocalName() + " ==> "
+ l.getString() );
}
else if (p.getLocalName().equals("inputparameter")){
r = s.getResource();
System.out.println( getParameterName(r.getURI())
+ " ==> " + getParameterValue(r.getURI()));
}
else if (p.getLocalName()
.equals("xsltTransformationString")){
l = s.getLiteral();
System.out.println( p.getLocalName() + " ==> "
+ l.getString() );
}
else if (p.getLocalName().equals("template")){
l = s.getLiteral();
System.out.println( p.getLocalName() + " ==> "
+ l.getString() );
}
else if (p.getLocalName().equals("elementValue")){
l = s.getLiteral();
System.out.println( p.getLocalName() + " ==> "
+ l.getString() );
}
else if (p.getLocalName().equals("attributeValue")){
l = s.getLiteral();
System.out.println( p.getLocalName() + " ==> "
+ l.getString() );
}
else if (p.getLocalName().equals("queryParameter")){
l = s.getLiteral();
System.out.println( p.getLocalName() + " ==> "
+ l.getString() );
}
}
}
}
public String getParameterName(String uri){
// this assumes the uri is to a ServiceParameterMap
OntResource or = bookStoreOntModel.getOntResource(uri);
String toReturn=null;
for (StmtIterator i = or.listProperties( ); i.hasNext(); ) {
Statement s = i.nextStatement();
Property p = s.getPredicate();
if (p.canAs(OntProperty.class)){
Resource r;
Literal l;
if (p.getLocalName().equals("paramname")){
l = s.getLiteral();
toReturn=l.getString();
}
}
}
return toReturn;
}
public String getParameterValue(String uri){
// this assumes the uri is to a ServiceParameterMap
OntResource or = bookStoreOntModel.getOntResource(uri);
String toReturn=null;
for (StmtIterator i = or.listProperties( ); i.hasNext(); ) {
Statement s = i.nextStatement();
Property p = s.getPredicate();
if (p.canAs(OntProperty.class)){
Resource r;
Literal l;
if (p.getLocalName().equals("paramvalue")){
l = s.getLiteral();
toReturn=l.getString();
}
}
}
return toReturn;
}
public static void main(String[] args) {
MashupOntologyReader reader = new MashupOntologyReader();
Individual[] individuals = reader.getIndividuals("Bookstore");
reader.obtainServiceInfo(
"");
}
}
Đáng tiếc, bạn không thể chỉ đơn giản vào và nhặt lấy các đặc tính. Thay vào đó,
bạn phải lặp lại tất cả các đặc tính sử dụng phương thức listProperties() mà nó sẽ
trả lại cho một bộ lặp Iterator.
Bạn phải nhớ rằng trong RDF, các thuộc tính được trình bày dưới dạng các câu
hoặc các câu lệnh ví dụ như "The Amazon.com service has an endpoint of
" Sử dụng ngữ pháp một cách thông
minh, cụm "has an endpoint of " là phần
thuộc tính của câu. Do đó, bước đầu tiên để truy lục các thuộc tính là truy lục câu
lệnh, sau đó truy lục các thuộc tính từ đây.
Khi bạn đã có các thuộc tính, đầu tiên bạn cần chắc chắn rằng thực tế đó là thuộc
tính bản thể luận. Sau cùng, đó có thể là một thuộc tính RDF hoặc một thuộc tính
bất thường khác. Khi bạn chắc rằng đó là một thuộc tính bản thể luận, bạn có thể
truy vấn localName và so sánh nó với các tham số mà bạn mong đợi.
Khi bạn biết mình đang xử lý thuộc tính nào thì việc bạn làm gì phụ thuộc vào thể
loại thuộc tính đó. Một số đặc tính như mẫu (template), đơn giản là các chuỗi ký
tự bằng chữ, và bạn có thể trích ra như vậy. Tuy nhiên, một số thuộc tính khác như
inputparameter là các tài nguyên, do đó bạn không thể đơn giản trích các giá trị
bằng chữ từ đây. Thay vào đó, bạn cần trích các thuộc tính của chúng. Ví dụ
inputparameter bao gồm một mục tiêu cùng với một thuộc tính paramname và
paramvalue. Để tìm các thuộc tính này, bạn có thể thiết kế phương thức
getParameterName() và getParameterValue() mà lặp chính nó thông qua các thuộc
tính của tài nguyên chủ thể.
Khi ta chạy ứng dụng, bạn sẽ có kết quả tương tự như hình 2:
Hình 2. Thông tin dịch vụ
Lớp dịch vụ được cập nhật
Tất cả các thông tin này không tốt với bạn trừ khi nó được lưu đâu đó mà bạn có
thể có được. Ứng dụng hiện được cài đặt để phân tích và chạy một mảng các mục
tiêu dịch vụ, vì vậy dự đoán tốt nhất là chỉnh sửa lớp dịch vụ sao cho nó có thể lưu
trữ dữ liệu (xem ví dụ 17):
Ví dụ 17. Lớp dịch vụ được cập nhật
import java.util.Vector;
public class Service {
String name = ";
String baseURL = ";
String template = ";
Vector inputParameters = new Vector();
String queryParameter = "";
String recordExp = "";
String xsltTransformationString = "";
Vector elementValues = new Vector();
Vector attributeValues = new Vector();
String filterExp = "";
Service subSvc = null;
}
Mục đích của lớp dịch vụ nguyên bản là cung cấp một nơi lưu dữ liệu, thuyết minh
các mục tiêu bất kỳ và gửi chúng lại. Bạn sẽ không phải làm như vậy nữa - mọi dữ
liệu có từ bản thể luận. Tất cả những gì bạn cần làm là chắc chắn bạn có các tham
số thành viên cho mỗi mảng dữ liệu mà bạn muốn lưu trữ, như là inputparameters
và xsltTransformationString.
Tương tự, để làm các lớp dịch vụ linh động hơn, thay đổi elementValues và
attributeValues thành các Vector, chứ không phải các mảng kích thước cố định,
như lúc trước đây của chúng.
Bây giờ bạn có thể tạo dịch vụ .
Tạo dịch vụ
Bạn vừa hoàn thành công việc khó khăn là trích xuất dữ liệu từ bản thể luận.
Những gì bạn cần làm bây giờ là tạo một mục tiêu dịch vụ mới và sau đó thêm các
thông tin vào đó (xem ví dụ 18):
Ví dụ 18. Tạo dịch vụ
...
public Service obtainServiceInfo(String serviceURI){
Individual bookstore =
bookStoreOntModel.getIndividual(serviceURI);
Service svc = new Service();
for (StmtIterator i = bookstore.listProperties( );
i.hasNext(); ) {
Statement s = i.nextStatement();
Property p = s.getPredicate();
if (p.canAs(OntProperty.class)){
Resource r;
Literal l;
if (p.getLocalName().equals("endpoint")){
l = s.getLiteral();
svc.baseURL=l.getString();
System.out.println( p.getLocalName() + " ==> "
+ l.getString() );
}
else if (p.getLocalName().equals("rootoutputnode")){
l = s.getLiteral();
svc.recordExp=l.getString();
System.out.println( p.getLocalName() + " ==> "
+ l.getString() );
}
else if (p.getLocalName().equals("inputparameter")){
r = s.getResource();
svc.inputParameters.add(r.getURI());
System.out.println( getParameterName(r.getURI())
+ " ==> " + getParameterValue(r.getURI()));
}
else if (p.getLocalName()
.equals("xsltTransformationString")){
l = s.getLiteral();
svc.xsltTransformationString=l.getString();
System.out.println( p.getLocalName() + " ==> "
+ l.getString() );
}
else if (p.getLocalName().equals("template")){
l = s.getLiteral();
svc.template=l.getString();
System.out.println( p.getLocalName() + " ==> "
+ l.getString() );
}
else if (p.getLocalName().equals("elementValue")){
l = s.getLiteral();
String[] elementValues = l.getString().split("!");
for (int j = elementValues.length; j>0; j--){
svc.elementValues.add(elementValues[(j-1)]);
}
System.out.println( p.getLocalName() + " ==> "
+ l.getString() );
}
else if (p.getLocalName().equals("attributeValue")){
l = s.getLiteral();
String[] attributeValues = l.getString().split("!");
for (int j = attributeValues.length; j>0; j--){
svc.attributeValues.add(attributeValues[(j-1)]);
}
System.out.println( p.getLocalName() + " ==> "
+ l.getString() );
}
else if (p.getLocalName().equals("queryParameter")){
l = s.getLiteral();
svc.queryParameter = l.getString();
System.out.println( p.getLocalName() + " ==> "
+ l.getString() );
}
}
}
return svc;
}
...
Lưu ý rằng bạn nắm được sự khác nhau của các tên giữa lớp dịch vụ và bản thể
luận trong phương thức này. Ví dụ, bạn đã vạch ra endpoint đối với baseURL.
Cũng lưu ý rằng, trong khi bạn có thể thêm chuỗi các chữ ví dụ như mẫu trực tiếp
đối với lớp, bất cứ đặc tính được đại diện như là một tài nguyên, ví như
inputparameter có thêm những thứ không phải là ký tự chữ, mà như URI đối với
tài nguyên. (Bạn có thể quyết định các ứng dụng của mình sẽ có lợi từ tất cả thông
tin chứa trực tiếp giữa các lớp. Trong tình huống đó, bạn cần chế tác thêm tại điểm
này). Bạn cũng có thể phân chia các giá trị trong thuộc tính elementValue và
attributeValue thành một mảng, và sau đó sử dụng mảng để tạo dịch vụ.
Bước tiếp theo là xây dựng yêu cầu REST thực.
Xây dựng yêu cầu
Lúc này, bạn có tất cả thông tin dịch vụ, nhưng bạn không có một yêu cầu có thể
gửi trực tiếp đến dịch vụ, vì tất cả các tham số đầu vào đã bị tách thành các tài
nguyên riêng lẻ. Việc tạo ra yêu cầu này là một đặc tính đối với dịch vụ, và không
phải một phần của bản thể luận hay servlet, vì vậy bao gồm nó như một phần của
lớp dịch vụ (xem ví dụ 19):
Ví dụ 19. Xây dựng yêu cầu
import java.util.Vector;
public class Service {
String name = "";
...
public String getRESTRequest(MashupOntologyReader ont){
String restQuery = this.baseURL;
for (int i=0;i<this.inputParameters.size();i++){
String serviceParameterMapURI =
(String) this.inputParameters.elementAt(i);
if (restQuery.equals(this.baseURL))
restQuery = restQuery + "?";
else
restQuery = restQuery + "&";
restQuery = restQuery +
ont.getParameterName(serviceParameterMapURI) + "=" +
ont.getParameterValue(serviceParameterMapURI);
}
restQuery = restQuery + "&" + this.queryParameter + "=";
return restQuery;
}
}
Trong phương thức getRESTRequest(), bạn lặp qua mỗi inputParameters, thêm
chúng vào baseURL. Cuối cùng, cuối URL, bạn thêm các tham số truy vấn thực và
một tín hiệu ngang bằng (=). Theo cách này, khi bạn thêm các từ khoá để tìm đến
hết truy vấn, bạn có một truy vấn URL đầy đủ như:
AWSECommerceService&AWSAccess
KeyId=000000000000000&SearchIndex=
Books&Operation=ItemSearch&Title=Star+Wars
Lưu ý: Mã gốc là một dòng đơn thông thường. Để dễ nhìn, nó được diễn tả trên
nhiều dòng như trên.
Tạo các yêu cầu
Thực ra, việc tạo các yêu cầu được tiến hành hầu như giống hệt như trước (xem ví
dụ 20):
Ví dụ 20. Tạo yêu cầu
...
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
MashupOntologyReader ont = new MashupOntologyReader();
String query = request.getParameter("query").toString();
String serviceURI =
request.getParameter("serviceURI").toString();
Service service = ont.obtainServiceInfo(serviceURI);
try {
DocumentBuilder builder =
DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
Service[] svcs = {service};
Document hostDoc = builder.parse(
new InputSource(new StringReader("")));
Node hostRoot = hostDoc.getDocumentElement();
for (int k=0; k < svcs.length; k++){
Service svc = svcs[k];
Node renderedService =
renderService(svc.getRESTRequest(ont)+query,
hostDoc);
if (renderedService != null){
Element nameElement = hostDoc.createElement("h1");
nameElement.appendChild(
hostDoc.createTextNode(svc.name));
...
Đầu tiên, bạn cần mở bản thể luận - bạn cũng cần nó để đặt dịch vụ vào, và tạo
yêu cầu REST. Khi bạn đã đặt dịch vụ vào rồi, bạn có thể sử dụng nó để thay thế
các thành phần trong mảng dịch vụ với một thành phần đơn nhất. Từ đây, mọi thứ
tiến hành như trước, trừ khi bạn tạo truy vấn khi bạn sử dụng dịch vụ
renderService().
Bây giờ bạn có thể chạy ứng dụng và có kết quả tương tự với những gì được tạo ra
trong phiên bản ứng dụng cơ bản hơn.
Chuyển đổi kết quả
Tới đây, những gì bạn cần hoàn tất là thay đổi ứng dụng nhận thông tin như thế
nào về dịch vụ. Nó vẫn yêu cầu thông tin như vậy, và nó triển khai thông tin thô
được trả lại từ dịch vụ. Bước tiếp theo là chuyển đổi thông tin đặc tính dịch vụ
thành thông tin dạng bản thể luận tổng quát (generic ontological information).
Đầu vào
Hãy cùng bắt đầu bằng cách xem dữ liệu được trả về từ yêu cầu thực. Dịch vụ
mạng Amazon thực tế đưa cho bạn một sự lựa chọn về lượng dữ liệu bạn muốn
được gửi lại là bao nhiêu, bằng cách chọn một ResponseGroup của Small, bạn sẽ
có thông tin cơ bản nhất, cái mà ít cồng kềnh để xử lý hơn là một kết quả đầy đủ.
Không may rằng bạn sẽ cần yêu cầu một ResponseGroup của Large để có thông
tin về giá. Dữ liệu trả lại có dạng như sau (xem Ví dụ 21):
Ví dụ 21. Dữ liệu thô
<ItemSearchResponse xmlns=
"">
...
...
17717
1772
0307337332
07337332%26tag=ws%26lcode=xm2%26cID=2025%26ccmID=165953%26lo
cation=/o
/ASIN/0307337332%253FSubscriptionId=000000000000000
16
...
...
...
...
Cesar Millan
Hardcover
Asdf
Melissa Jo Peltier
636.70887
9780307337337
RAO
0307337332
Harmony
2495
USD
$24.95
Harmony
1
234
Cesar's Way: The Natural, Everyday Guide
to Understanding and Correcting Common Dog Problems
...
0060817089
...
Tất nhiên, bạn đủ khả năng để thêm các thông tin này vào bản thể luận của bạn,
nhưng vì mục đích của bài viết này, nên gắn với các vấn đề cơ bản.
Kết quả đích
Mục tiêu tổng thể là nắm được thông tin và chuyển đổi nó thành một dạng phù
hợp với bản thể luận. Trong trường hợp này, trông nó sẽ như sau (xem ví dụ 22):
Ví dụ 22. Mục tiêu đầu ra
<rdf:RDF xmlns:res=
""
xmlns:rdf="">
Cesar Millan
Cesar's Way: The Natural, Everyday Guide to
Understanding and Correcting Common Dog Problems
<itemPrice rdf:datatype=
"">24.95
07337332%26tag=ws%26lcode=xm2%26cID=2025%26ccmID=165953%26location=/o
/ASIN/0307337332%253FSubscriptionId=000000000000000
John Grogan
...
Một vài mục cần lưu ý ở đây. Đầu tiên là Book có một mã số bao gồm số xuất bản
(ISBN). Số này là duy nhất trong tất cả dịch vụ. Trong một quy trình sản xuất, bạn
muốn kiểm tra để chắc chắn rằng yếu tố này không tồn tại trước khi bạn tạo lại nó;
có thể rằng cuốn sách tương tự đã có yêu cầu từ dịch vụ khác, hoặc thậm chí một
truy vấn khác từ dịch vụ tương tự.
Tương tự, mã này tránh được sự trùng lặp các yếu tố tác giả bằng cách chưa xử lý
trước số xuất bản với tên tác giả trong mã số. Cũng như vậy, bạn sẽ phải xử lý với
thực tế rằng một giá trị mã số không thể có các khoảng cách trong đó. StockItem
tham chiếu ngược lại Book thông qua đặc tính stockProduct cái mà chứng nhận là
những tài nguyên thích hợp.
Khi bạn đã chuyển dữ liệu sang dạng này, bạn có thể lưu nó trong cơ sở dữ liệu và
phân tích nó bằng cách sử dụng công cụ dạng bản thể luận. Bạn sẽ hoàn tất sự
chuyển đổi bằng cách sử dụng bộ chuyển đổi XSLT.
Bảng định kiểu
Bảng định kiểu (Stylesheet) là một trang dùng để định dạng điển hình, nhưng sử
dụng một cặp chức năng XPath để hoàn thành một vài tác vụ khó hơn (xem ví dụ
23):
Ví dụ 23. The stylesheet
<xsl:stylesheet version="1.0"
xmlns:xsl=""
xmlns:res=
""
xmlns:rdf = "">
<xsl:apply-templates select=
"/res:ItemSearchResponse/res:Items/res:Item" />
<xsl:value-of select=
"translate(res:ItemAttributes/res:Author, ' ', '_' )"/>
<xsl:value-of
select="res:ASIN"/><xsl:value-of select=
"translate(res:ItemAttributes/res:Author, ' ', '_' )"/>
AMAZON_<xsl:value-of select=
"res:ASIN"/>
#<xsl:value-of select=
"res:ASIN"/>
<itemPrice rdf:datatype=
""><xsl:value-of
select="translate(res:ItemAttributes/res:ListPrice/res:FormattedPrice, '$', '')"/>
<xsl:value-of select=
"res:ItemAttributes/res:Title"/>
Đầu tiên bảng định kiểu tạo thành phần chính RDF, hoạt động như là khởi nguồn
của tài liệu. Từ đây, nó lặp lại thông qua từng thành phần Item và tạo ra các thành
phần Author, Book, và StockItem. Khi cần thiết nó sử dụng hàm translate() để
thay thế những khoảng trống trong tên tác giả bằng dấu gạch chân.
Lưu ý cách dùng của các chuỗi ký tự bằng chữ như là AMAZON_. Do sự chuyển
đổi này là đặc tính của dịch vụ, bạn có thể thực hiện việc chuyển đổi mà không bị
sao.
Tạo một ứng dụng thử nghiệm
Bây giờ bạn gần như sẵn sàng để bắt đầu sự chuyển đổi, nhưng do gần như không
thể xem những gì xảy ra giữa các servlet, nên tạo ra một lớp kiểm tra để chạy sự
chuyển đổi và chắc chắn nó hoạt động đúng cách (xem ví dụ 24).
Ví dụ 24. Tạo lớp thử nghiệm
import java.io.IOException;
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import java.io.PrintStream;
public class DoThis {
public static void main (String args[]){
String transString=
"<xsl:stylesheet version=\"1.0\" "+
...
try {
}
catch (Exception e){
e.printStackTrace();
}
}
}
Đây chỉ là một lớp đơn giản, nhưng do bảng định kiểu cuối cùng sẽ bị tiếp cận như
là một chuỗi (như là một đặc tính của lớp Service).
Xây dựng tài liệu gốc
Để bắt đầu sự chuyển đổi, tạo DOMSource bằng cách phân tích cú pháp các kết
quả của yêu cầu thực (xem ví dụ 25):
Ví dụ 25. Xây dựng DOMSource
...
try {
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(
"
WSAccessKeyId=000000000000000&SearchIndex=Books&Operation=ItemSe
arch&ResponseGroup=Large&Title=Dogs");
Source xmlSource = new DOMSource(document);
}
catch (Exception e){
e.printStackTrace();
}
}
URL đang được phân tích là URL được tạo ra bởi phương thức getRESTRequest()
nhưng để mọi thứ hoạt động đúng đắn, bạn cần chắc chắn rằng
DocumentBuilderFactory tạo một DocumentBuilder mà nhận ra các khoảng trống.
Nếu không, chương trình phân tích sẽ không hiểu các thành phần bảng định kiểu
nên được xử lý như là một bảng định kiểu.
Tạo bảng định kiểu
Bạn cần tạo một DOMSource cái mà đại diện cho bảng định kiểu (xem ví dụ 26):
Ví dụ 26. Tạo đối tượng bảng định kiểu
...
Source xmlSource = new DOMSource(document);
Document xslDoc = builder.parse(
new InputSource(new StringReader(transString)));
DOMSource xslSource = new DOMSource(xslDoc);
TransformerFactory transFactory =
TransformerFactory.newInstance();
Transformer transformer =
transFactory.newTransformer(xslSource);
}
catch (Exception e){
e.printStackTrace();
}
}
Tất nhiên trong ứng dụng thực, bạn sẽ thay thế transString bằng
xsltTransformationString từ Service.
Chuyển đổi tài liệu
Bây giờ bạn cần thực hiện sự chuyển đổi thực (xem ví dụ 27):
Ví dụ 27. Thực hiện chuyển đổi
...
TransformerFactory transFactory =
TransformerFactory.newInstance();
Transformer transformer =
transFactory.newTransformer(xslSource);
StreamResult result = new StreamResult(System.out);
transformer.transform(xmlSource, result);
}
catch (Exception e){
e.printStackTrace();
}
}
Bạn đang thiết lập kết quả là System.out do đó bạn sẽ thấy các cá thể của bản thể
luận xuất hiện trong dòng lệnh, hoặc cửa sổ bảng điều khiển, như bạn thấy trong
hình 3.
Hình 3. Kết quả của sự chuyển đổi
Hiển thị các kết quả
Cuối cùng bạn đã gần hoàn thành. Bạn có thể truy xuất thông tin dịch vụ từ bản
thể luận, thiết lập yêu cầu, và chuyển đổi kết quả sang thông tin dạng bản thể luận.
Bây giờ bạn chỉ phải trình bày thông tin loại dạng bản thể luận như là bộ phận của
một ứng dụng.
Quy trình hiển thị hoạt động như thế nào
Đến đây có thể là lúc để rà soát xem quy trình hiển thị thực sự hoạt động thế nào.
Mọi yêu cầu dịch vụ trả lại một khối lớn XML. Mục tiêu là để hiển thị các phần cụ
thể của khối này trên một trang HTML. Có nghĩa rằng bạn sẽ kết hợp dữ liệu với
các thẻ HTML.
Đối với mỗi dịch vụ, bạn xác định một mẫu, một chuỗi mã HTML bao gồm các
trình giữ chỗ (placeholders) trong đó mà bạn có thể thả các dữ liệu thích hợp vào.
Ví dụ, mẫu bạn đang sử dụng đối với dịch vụ Amazon là (xem ví dụ 28):
Ví dụ 28. Mẫu
by
Bạn thấy hai thành phần value và một thuộc tính value . Khi bạn xử lý dịch vụ,
bạn sẽ thay thế các nút này bằng thông tin cụ thể từ dịch vụ. Ví dụ, bạn muốn
thành phần value đầu tiên để đại diện cho tiêu đề, nên bạn sẽ thay thế nó bằng nút
tìm được trong kết quả REST tại
/ItemSearchResponse/Items/Item/ItemAttributes/Title. Bạn biết đó là dữ liệu bạn
cần vì recordExp được thiết lập tới /ItemSearchResponse/Items/Item, hoạt động
như nguồn gốc khởi đầu của trường hợp này, và là elementValue đầu tiên được
thiết lập ItemAttributes/Title.
Để mọi thứ xảy ra với dữ liệu được chuyển đổi, bạn cần phải làm như sau:
1. Thêm thông tin chuyển đổi vào bản thể luận, và cả dịch vụ.
2. Tạo yêu cầu.
3. Chuyển đổi yêu cầu thô sang thông tin dạng bản thể luận.
4. Trích dẫn thông tin phù hợp từ thông tin dạng bản thể luận.
5. Chèn các thông tin thu được vào mẫu.
6. Hiển thị mẫu
Hãy bắt đầu bằng cách chắc chắn rằng thông tin dịch vụ trong bản thể luận là mới
cập nhật.
Điều chỉnh đầu vào tổng quát
Điều đầu tiên bạn cần làm là thêm bảng định kiểu XSLT vào
xsltTransformationString một cách đúng đắn, nhưng trước khi làm như vậy hãy
cân nhắc thêm một khía cạnh.
Bản thể luận được xây dựng để phục vụ một mục đích cụ thể, và phục vụ tốt mục
đích đó, nhưng nó không đưa chính nó vào biểu thức XPath. Vì mục đích của bài
viết này - bạn không cần đưa hết tất cả các phần vào biểu thức XPath khó hiểu -
tạo một sự thay đổi đối với bảng định kiểu để đơn giản hoá đầu ra. Bạn có một đầu
ra mới trông như sau (xem ví dụ 29):
Ví dụ 29. Cấu trúc dữ liệu mới
Cesar's Way: The Natural, Everyday Guide to
Understanding and Correcting Common Dog Problems
Cesar Millan
7332%26tag=ws%26lcode=xm2%26cID=2025%26ccmID=165953%26location=/o/ASIN/030733733
2%253FSubscriptionId=000000000000000
Marley amp; Me: Life and Love with the World's Worst
Dog
John Grogan
7089%26tag=ws%26lcode=xm2%26cID=2025%26ccmID=165953%26location=/o/ASIN/006081708
9%253FSubscriptionId=000000000000000
...
To set that up, add the following stylesheet to the ontology (see Listing 30):
Listing 30. Adding the stylesheet to the ontology
...
//Book
<![CDATA[
<xsl:stylesheet version="1.0"
xmlns:xsl=""
xmlns:res=
""
xmlns:rdf =
"">
<xsl:output method="xml" version="1.0" encoding="UTF-8"
indent="yes"/>
<xsl:apply-templates select=
"/res:ItemSearchResponse/res:Items/res:Item" />
<xsl:value-of select=
"res:ItemAttributes/res:Title"/>
<xsl:value-of select=
"res:ItemAttributes/res:Author"/>
<xsl:value-of select=
"res:DetailPageURL"/>
]]>
by ]]>
ItemAttributes/Title!ItemAttributes/Author
DetailPageURL
Title
Service
AWSECommerceService
...
Để thiết lập cấu trúc đó, thêm bảng định kiểu sau vào bản thể luận (xem ví dụ 30):
Ví dụ 30. Thêm bảng định kiểu vào bản thể luận
...
//Book
<![CDATA[
<xsl:stylesheet version="1.0"
xmlns:xsl=""
xmlns:res=
""
xmlns:rdf =
"">
<xsl:output method="xml" version="1.0" encoding="UTF-8"
indent="yes"/>
<xsl:apply-templates select=
"/res:ItemSearchResponse/res:Items/res:Item" />
<xsl:value-of select=
"res:ItemAttributes/res:Title"/>
<xsl:value-of select=
"res:ItemAttributes/res:Author"/>
<xsl:value-of select=
"res:DetailPageURL"/>
]]>
by ]]>
ItemAttributes/Title!ItemAttributes/Author
DetailPageURL
Title
Service
AWSECommerceService
...
Bây giờ bạn đã sẵn sàng thực hiện chuyển đổi trên phản hồi dịch vụ.
Chuyển đổi kết quả dịch vụ cụ thể
Sự chuyển đổi dữ liệu thô sang dữ liệu có ý nghĩa nên trong suốt; nó xảy ra như
một phần của quy trình tổng thể của dịch vụ (xem ví dụ 31):
Ví dụ 31. Chuyển đổi phản hồi
...
public class MashupClientServlet extends javax.servlet.http.HttpServlet
implements
javax.servlet.Servlet {
...
public static Document getData (String query, Service svc) {
try {
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
String cached = checkCache(query);
Document document = null;
if (cached.equals("-1")){
//Using fresh data
Document inputDocument = builder.parse(query);
try {
Source xmlSource = new DOMSource(inputDocument);
Document xslDoc = builder.parse(
new InputSource(new
StringReader(svc.xsltTransformationString)));
DOMSource xslSource = new DOMSource(xslDoc);
TransformerFactory transFactory =
TransformerFactory.newInstance();
Transformer transformer =
transFactory.newTransformer(xslSource);
DOMResult result = new DOMResult();
transformer.transform(xmlSource, result);
document = (Document)result.getNode();
}
catch (Exception e){
e.printStackTrace();
}
saveData(query, document);
} else{
//Using cached data, I hope
Document cachedDocument;
...
}
public static Node renderService(String query, Service svc,
Document hostDoc){
Document document = getData(query, svc);
if (document != null){
...
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
MashupOntologyReader ont = new MashupOntologyReader();
String query = request.getParameter("query").toString();
String serviceURI =
request.getParameter("serviceURI").toString();
Service service = ont.obtainServiceInfo(serviceURI);
try {
DocumentBuilder builder =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
Service[] svcs = {service};
Document hostDoc = builder.parse(
new InputSource(new StringReader("")));
Node hostRoot = hostDoc.getDocumentElement();
for (int k=0; k < svcs.length; k++){
Service svc = svcs[k];
Node renderedService = renderService(
svc.getRESTRequest(ont)+query, svc, hostDoc);
if (renderedService != null){
Element nameElement = hostDoc.createElement("h1");
nameElement.appendChild(
hostDoc.createTextNode(svc.name));
...
Mã này chỉ ra một số thay đổi, do vậy hãy bắt đầu từ cuối và làm ngược trở lại.
Đầu tiên, do thông tin cần thiết cho việc chuyển đổi là một phần của Service, bạn
cần phải chuyển nó như là một phần của lời gọi đến hàm renderService(). Có
nghĩa bạn cần phải bổ sung nó vào chữ ký renderService(). Khi nó đã ở đấy, bạn
có thể chuyển nó tới phương thức getData() nơi mà bạn thực sự cần nó.
Trong phương thức getData(), đầu tiên bạn tạo ra DocumentBuilder (lại như trong
namespace-aware). Từ đó, bạn sử dụng nó để tạo ra nguồn DOMSource, lần này
sử dụng Document được tạo ra khi bạn phân tách các truy vấn. Từ đó, tất cả sẽ
được tiếp tục như trước đây ngoại trừ rằng bảng định kiểu đến từ Service.
Sau khi có kết quả, bạn có thể lấy lại DOM Document từ nó sử dụng phương thức
getNode(). Khi bạn có nó, bạn có thể tiếp tục như trước đây, lưu dữ liệu vào cơ sở
dữ liệu và chuyển nó quay lại ứng dụng chính như thể chưa có gì xảy ra với nó.
Điều chỉnh các tham số dịch vụ
Nếu hiện giờ bạn chạy servlet, tuy nhiên, bạn sẽ thấy có vẻ không thu được kết
quả gì. Tại sao? Do tại thời điểm hiện nay servlet đang cố gắng nhúng vào dữ liệu
từ /ItemSearchResponse/Items/Item/ItemAttributes/Title và những cái tương tự
vào mẫu, nhưng dữ liệu này không còn tồn tại bởi vì bạn đã chuyển hóa nó vào
một dạng thức mới. Vì vậy để có thể thực hiện, bạn cần điều chỉnh các biểu thức
XPath (xem ví dụ 32):
Ví dụ 32. Điều chỉnh các biểu thức XPath
...
//Book
...
<![CDATA[
...
]]>
<a
value='href'> by
]]>
itemDescription!Author
itemDetailURL
Title
...
Giờ thì bạn tìm kiếm dữ liệu kiểu như //Book/itemDescription tồn tại trong kiểu
dạng dữ liệu đã chuyển hóa, do đó mọi thứ có vẻ trông hoàn chỉnh.
Kết quả cuối cùng trông giống hình 4:
Hình 4. Kết quả cuối cùng
Tổng kết
Và từ đây bạn sẽ đi tới đâu
Mục đích của bài viết này là điều chỉnh ứng dụng để người dùng có thể lựa chọn
loại dịch vụ mà họ muốn và trong một khoảng thời gian nhất định có thể hoàn
thành được việc này. Bạn có thể tạo nên một số lượng bất kỳ các hiệu sách dựa
trên REST cho người sử dụng bằng cách đơn giản là thêm vào các thông tin của
chúng trong tệp bản thể luận. Bạn cũng có thể mở rộng dịch vụ này thành các loại
dịch vụ khác tệp. Tất cả cần làm là chỉ bổ sung chúng vào bản thể luận và thay đổi
kiểu mà bạn đang tìm kiếm khi bạn tạo nên mẫu.
Chúng ta chưa thảo luận về các dịch vụ phụ trong bài viết này, bởi vì vấn đề là
không còn đủ chỗ nữa. Các dịch vụ phụ hoạt động như trước đây. Chúng ta vẫn
chưa đề cập gì về tìm kiếm các thông tin ngôn ngữ đã được phát triển trước đây.
Bạn có thể lấy mã trong bài viết này và sử dụng chúng để tìm kiếm, như là các
quyển sách giá thấp nhất trong cơ sở dữ liệu, độc lập với dịch vụ ở chỗ là dữ liệu
được lấy lại, sử dụng cùng các công nghệ như nhau mà bạn đã học ở Phần 2
Trong bài bài viết này, bạn đã tạo cho người dùng cơ hội lựa chọn từ một số lượng
hạn chế các dịch vụ xác định của một kiểu nhất định tùy chọn, lấy lại các dữ liệu
thô và trả nó lại dữ liệu bản thể luận đánh dấu dưới hình thức ngôn ngữ. Ở Phần 6
bạn sẽ học cách làm thế nào để tạo cho người dùng lựa chọn loại dịch vụ nào được
sử dụng và loại dữ liệu nào được trình bày cũng như là làm thế nào để trình diễn
dữ liệu trên trang web.
Các file đính kèm theo tài liệu này:
- Ultimate mashup – Các dịch vụ Web và Web ngữ nghĩa, Phần 5.pdf