Đề tài Các dịch vụ Web và Web ngữ nghĩa (semantic Web) - Phần 6

Tóm tắt: Đây là bài viết cuối cùng trong một loạt các bài viết để chỉ cho bạn cách tạo một ứng dụng mashup. Ở đây, bạn cần có một ứng dụng đang chạy và một khung làm việc thay thế nhờ đó hệ thống có thể sử dụng các lập luận ngữ nghĩa để hiểu các dịch vụ tại điểm sử dụng của nó. Trong bài viết này, bạn sẽ để cho người dùng kiểm soát việc chọn lựa loại hình dịch vụ, dữ liệu lấy về từ dịch vụ Web, và cách trình bày dữ liệu đó.

pdf92 trang | Chia sẻ: tlsuongmuoi | Lượt xem: 1828 | Lượt tải: 0download
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 (semantic Web) - Phần 6, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
><xsl:value-of select="translate(res:ItemAttributes/res:Author, ' ', '_' )"/> AMAZON_<xsl:value-of select="res:ASIN"/> #_<xsl:value-of select="res:ASIN"/> <xsl:attribute name="rdf:datatype"></xsl:att ribute ><xsl:value-of select="translate(res:ItemAttributes/res:ListPrice/res:FormattedPrice, '$', '')"/> ]]> <a value='href'> by ]]> Author!itemDescription itemDetailURL Title ... Ở đây trong ví dụ 2 này một lần nữa bạn cần tạo ra các đối tượng trong nhưng bạn sẽ thấy nó hiện ra cụ thể. Một số chú ý về chuyển đổi dữ liệu Trong loạt bài này, bạn lấy dữ liệu thô và chuyển đổi nó sang dạng XML sao cho hòa hợp với một bản thể luận cụ thể. Có thể bạn sẽ tự hỏi “Tại sao không đơn giản là để cho reasoner tự làm ra mà không cần phải chuyển đổi dữ liệu?”. (reasoner là một dịch vụ lấy các phát biểu có trong một bản thể luận và từ đó suy luận ra các phát biểu mới.) Ví như bạn có thể báo cho bản thể luận biết rằng phần tử FormattedPrice ở trong trang không gian tên là một equivalentProperty đối với itemPrice. Bạn có thể dùng một reasoner để lấy dữ liệu từ kết quả thô hơn là trình bày một quá trình chuyển đổi. Câu trả lời là không có lý do gì mà bạn không thực hiện được điều này. Nhưng sự thật là ngày nay reasoner Web ngữ nghĩa hơi giậm giật, và cách thức này sẽ thay đổi trọng tâm của bài viết này sang cách xây dựng bản thể luận chứ không phải xây dựng các ứng dụng Web. Vì thế, chúng ta cần nhớ là chúng ta có quyền lựa chọn, trong tương lai đó có thể sẽ là lựa chọn tốt cho bạn. Nhưng bây giờ, bạn sẽ làm mọi thứ đơn giản hơn bằng trình bày việc chuyển đổi dữ liệu. Cải tiến cấu trúc Trước khi bạn đi sâu hơn, bạn cần phải thay đổi cấu trúc để phù hợp với hàm mới. Thêm kiểu đầu ra Trước khi bắt đầu, xem lại một số điều liên quan tới bản thể luận. Từ vị trí của bản thể luận bây giờ, các lớp tương ứng sẽ như dưới đây. Trong trường hợp dịch vụ Bookstore là một lớp con của lớp Service trả lại một hoặc nhiều StockItems thì lớp StockItem có nhiều đặc tính như là itemPrice và stockedProduct. Nhưng một loại dịch vụ khác NewsService chẳng hạn có thể cho ra một loại mục khác (ví dụ, StockItem) thay vì cho ra một StockItems thì có thể cho ra một hoặc nhiều mục NewsStory. Vì thế, để hệ thống làm việc hợp lý, bản thể luận cần phải biết rõ từng lớp đại diện cho các mục riêng rẽ khi hiển thị câu trả lời cho dịch vụ. Để làm được điều này, bạn cần định nghĩa đặc tính outputType cho dịch vụ (Xem ví dụ 3). Ví dụ 3. Thêm outputType ... <rdfs:range rdf:resource=""/> ... Lưu ý rằng đặc tính này chứa giá trị của nó ở bất kỳ Class nào. Ví dụ ở Bookstore giá trị của đặc tính này nằm ở StockItem. Dạng này là một dạng phức (các lớp là các giá trị và các biểu mẫu) gây khó khăn cho việc soạn thảo một reasoner OWL. Tạo đặc tính sẵn có Để sử dụng được đặc tính outputType bạn cần phải truy cập được nó. Vị trí hợp lý nhất nằm ở phương thức obtainServiceInfo() phương thức của MashupOntologyReader để đọc thông tin đưa vào lớp Service (xem ví dụ 4). Ví dụ 4. Tạo đặc tính sẵn có ... public Service obtainServiceInfo(String serviceURI){ ... 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("outputType")){ l = s.getLiteral(); svc.recordExp=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() ); } ... public static void main(String[] args) { MashupOntologyReader reader = new MashupOntologyReader(); reader.obtainServiceInfo( ""); } } Trong trường hợp này (xem ví dụ 4) đơn giản là bạn cần xử lý đặc tính outputType tương tự cách bạn xử lý các đặc tính theo chuỗi khác, bạn truy cập vào Literal qua từng câu lệnh có chứa nó. Bạn có thể nhìn thấy kết quả của việc thực thi phương thức obtainServiceInfo() (xem ví dụ 5). Ví dụ 5. Thực thi phương thức obtainServiceInfo() rootoutputnode ==> //Book xsltTransformationString ==> <xsl:stylesheet version="1.0" xmlns="" ...> ... Service ==> AWSECommerceService AWSAccessKeyId ==> 000000000000000 template ==> <a value='href'> by endpoint ==> outputType ==> elementValue ==> Author!itemDescription attributeValue ==> itemDetailURL SearchIndex ==> Books queryParameter ==> Title Operation ==> ItemSearch Liệt kê tất cả các đặc tính Bạn sẽ phải thực hiện các hàm khác cùng MashupOntologyReader. Ví dụ, bạn sẽ cần một danh sách tất cả các đặc tính của một lớp, đặc biệt là lớp outputType trình bày. Để làm điều này bạn cần tạo ra một phương thức mới (Xem ví dụ 6). Ví dụ 6. Phương thức showAllProperties() ... import com.hp.hpl.jena.util.iterator.*; import com.hp.hpl.jena.ontology.*; public class MashupOntologyReader { private OntModel serviceOntModel; public OntModel getOnt(){ return serviceOntModel; } public MashupOntologyReader(){ ... } public void showAllProperties(OntClass theClass){ String thisClassURI = theClass.getURI(); for (ExtendedIterator i = theClass.listDeclaredProperties(); i.hasNext(); ) { OntProperty thisProp = (OntProperty)i.next(); System.out.println("Property (raw): " +thisProp.getLocalName()); } } public static void main(String[] args) { MashupOntologyReader reader = new MashupOntologyReader(); reader.showAllProperties(reader.getOnt().getOntClass( "")); } } Bắt đầu từ phần cuối cùng của ví dụ 6, trong hàm main() bạn gọi một hàm mới nhưng lưu ý là để có được các đặc tính cho một lớp bạn cần phải có tham chiếu cho một lớp hiện thời. Để làm điều này, bạn cần một tham chiếu cho chính bản thân bản thể luận chứ không chỉ là đối tượng MashupOntologyReader. Vì thế bạn cần có một phương thức mới để lấy được tham chiếu cho mẫu bản thể luận đó. Khi mà bạn đã thực hiện được điều này, bạn có thể lấy được tham chiếu cho lớp dựa trên URI của nó. Trong trường hợp này bạn đang tìm các đặc tính cho lớp StockItem Rõ ràng là việc lấy các đặc tính có liên quan tới sử dụng phương thức listProperties(), phương thức này sẽ trả về ExtendedIterator. Bạn có thể lặp lại qua các đặc tính. Trong trường hợp này bạn nhớ xem localName. Bạn sẽ thấy kết quả tương tự (xem ví dụ 7). Ví dụ 7. Các đặc tính của lớp StockItem Property (raw): writerOf Property (raw): itemDescription Property (raw): itemDetailURL Property (raw): authorOf Property (raw): stockedProduct Property (raw): itemPrice Tất nhiên cách này không dễ sử dụng. Bạn có thể làm cho nó trông dễ coi hơn một chút. Tân trang lại Mặc dù là các thông tin trên có ích nhưng chưa chắc là thứ bạn muốn hiển thị cho người dùng thấy. Và may mắn là RDF cho phép bạn dán nhãn cho từng lớp hay từng đặc tính. Những gì bạn cần làm là hiển thị đặc tính chứ không phải localName (xem ví dụ 8). Ví dụ 8. Sử dụng nhãn thay cho localName ... public void showAllProperties(OntClass theClass){ String thisClassURI = theClass.getURI(); for (ExtendedIterator i = theClass.listDeclaredProperties(); i.hasNext(); ) { OntProperty thisProp = (OntProperty)i.next(); Property labelProp = (Property)serviceOntModel.getProperty( " schema#label"); if (thisProp.hasProperty(labelProp)){ System.out.println("Property: " +thisProp.getProperty(labelProp).getLiteral() //+thisProp.getLabel(null) ); } else { System.out.println("Property (raw): " +thisProp.getLocalName()); } } } ... Ở ví dụ 8 bạn sẽ thấy có một kỹ thuật mới. Bạn dùng phương thức getProperty() để gọi một đối tượng đặc tính cụ thể và sau đó kiểm tra xem mỗi đặc tính có đặc tính đó không (tất nhiên là đặc tính có thể có đặc tính). Nếu nó có chứa đặc tính thì bạn cho OutputLabel nếu nó không chứa đặc tính thì ở đầu ra sẽ xuất hiện localName. Lưu ý là phương thức getLabel() cho phép bạn chọn nhãn dựa theo ngôn ngữ. Kết quả bây giờ trông sẽ như (xem ví dụ 9). Ví dụ 9. Sử dụng nhãn. Property (raw): writerOf Property: Item Description Property: Item Detail Page URL Property (raw): authorOf Property: Stocked Product Property: Item Price Một số các đặc tính này không có nhãn bởi vì người dùng không cần thiết phải nhìn thấy chúng. Giới hạn đầu ra để phân loại dữ liệu các đặc tính. Giới hạn đầu ra đối với đặc tính dataType. Ở một ứng dụng hoàn chỉnh, bạn sẽ muốn hiển thị các đặc tính và bất kỳ các đặc tính của đối tượng chứ không chỉ các đối tượng. Ví dụ, trong trường hợp này bạn tạo ra một StockItem có chứa đặc tính của sản phẩm mà nó đại diện. Trong một ứng dụng hoàn chỉnh, bạn sẽ muốn hiển thị tác giả của quyển sách mà sản phẩm đại diện. Tuy nhiên, để làm điều này bạn cần gọi lại phương thức showAllProperties() Bản thân đây không là một sai sót, tuy nhiên bạn cần nhận ra rằng có một số khó khăn xuất hiện. Lý do là StockItem của bạn có chứa một đặc tính mang giá trị của Product trong trường hợp này là Book. Book có một đặc tính là writtenBy đó là một đối tượng Author. Đối tượng Author này có một đặc tính chung đối với tất cả các quyển sách do tác giả này viết, điều này dẫn bạn quay trở lại với đối tượng Author, đối tượng tác giả dẫn bạn quay trở lại với các đối tượng Books, và cứ tiếp tục như thế. Bạn có thể làm việc này nhưng để mọi thứ đơn giản hơn bạn cần giới hạn bản thân bằng các giá trị DatatypeProperty. May mắn là không khó để phân biệt sự khác nhau giữa DatatypeProperty và một ObjectProperty (xem ví dụ 10). Ví dụ 10. Giới hạn DatatypeProperties ... public void showAllProperties(OntClass theClass){ String thisClassURI = theClass.getURI(); for (ExtendedIterator i = theClass.listDeclaredProperties(); i.hasNext(); ) { OntProperty thisProp = (OntProperty)i.next(); if (thisProp.isObjectProperty()){ //System.out.println("This is an object property."); } else { Property labelProp = (Property)serviceOntModel.getProperty( " schema#label"); if (thisProp.hasProperty(labelProp)){ System.out.println("Property: " +thisProp.getProperty(labelProp).getLiteral() //+thisProp.getLabel(null) ); } else { System.out.println("Property (raw): " +thisProp.getLocalName()); } } } } ... Với thay đổi này, đầu ra sẽ như (xem ví dụ 11). Ví dụ 11. Đặc tính xuất: Property: Property: Item Description Property: Item Detail Page URL Property: Item Price Biểu mẫu dữ liệu đầu vào mới Bạn đã biết về truy lục đặc tính, đã đến lúc xem xét việc xây dựng biểu mẫu thực. Biểu mẫu sẽ hoạt động như thế nào Trước khi bạn bắt đầu, bạn nên hiểu rõ chính xác bạn đang xây dựng cái gì. Để cho người dùng quyền kiểm soát, bạn cần một biểu mẫu chấp nhận dữ liệu vào của người dùng. Biểu mẫu dữ liệu đầu vào mới sẽ có thể là vài dạng thu thập thông tin. (Bạn có thể thực hiện việc này như một dạng sử dụng Ajax nhưng đây sẽ là một bài tập dành cho người đọc bài viết). biểu mẫu này sẽ thực hiện các bước sau: 1. Người dùng chọn một loại dịch vụ. Dạng này sẽ hiển thị cố định bằng việc kiểm tra các lớp con của lớp Service 2. Người dùng chọn một dịch vụ hiện thời. Dạng này sẽ hiển thị cố định bằng việc kiểm tra các Instances của lớp được chọn trong bước một 3. Người dùng nhập một khuôn mẫu và chọn các đặc tính hiển thị. Dạng này là sự kết hợp các đặc tính của outputType của dịch vụ đã chọn với trường nhập văn bản . Chúng ta cùng bắt đầu. Liệt kê các loại dịch vụ Bước đầu tiên là cung cấp một dạng liệt kê các loại dịch vụ thích hợp. Thêm mã cho lớp MashupClientServlet (xem ví dụ 12). Ví dụ 12. Liệt kê các loại dịch vụ. ... public class MashupClientServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet { public MashupClientServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { MashupOntologyReader reader = new MashupOntologyReader(); response.getWriter().print(""); response.getWriter().print(""); response.getWriter().print(""); response.getWriter().print("The Mashup"); response.getWriter().println( "<form action='MashupClientServlet' method='get'>"); response.getWriter().print("Choose a sevice type"); response.getWriter().print("<select name='serviceType'>"); OntClass serviceClass = reader.getOnt() .getOntClass(""); for (ExtendedIterator i = serviceClass.listSubClasses(); i.hasNext(); ) { OntClass thisClass = (OntClass)i.next(); response.getWriter().print("<option value='" +thisClass.getURI()+"'>"+ thisClass.getLocalName()+""); } response.getWriter().print(""); response.getWriter().println("<input type='submit' />"); response.getWriter().print(""); response.getWriter().print(""); response.getWriter().print(""); } ... Phương thức doGet() giúp bạn tạo ra các dạng nhập hiện thời. Trong trường hợp này bạn tạo khung cho biểu mẫu và sau đó đưa tham chiếu tới lớp Service. Từ đây bạn có thể sử dụng phương thức listSubClasses() để lấy ExtendedIterator của các lớp con. Sau đó bạn có thể hiển thị thông tin của các lớp con, bao gồm một URI (được dùng như một giá trị cần được xem xét) và localName. (Để mọi việc trôi chảy hơn bạn nên dãn nhãn cho từng loại lớp và hiển thị chúng). Kết quả là một biểu mẫu tương tự như hình 1. Hình 1. Dạng lựa chọn cơ bản. Dạng này có duy nhất một rắc rối. Bạn sẽ nhận thấy biểu mẫu liệt kê dịch vụ Store, là một lớp con của Service và MappingService và NewsService cũng là các lớp con của Service nhưng biểu mẫu này không liệt kê bất kỳ lớp con nào của lớp Store mặc dù các lớp con này, theo định nghĩa, là các lớp con của Service. Thêm lập luận Vấn đề gặp phải ở đây là chẳng liên quan gì tới mã hay bản thể luận của bạn. Điều rắc rối là khi bạn tạo một mẫu, bạn tạo nó với một sự bổ sung rất dễ đọc bản thể luận mà không trình bày bất cứ lập luận nào khác ngoài việc thuyết minh cấu trúc RDF. Nói cách khác, mô hình hiểu được rằng Bookstore là một lớp con của Store nhưng điều này không có tính chất bắc cầu là vì Store là một lớp con của Service nên suy ra Bookstore là một lớp con của Service. Để tạo ra thông tin này hoặc thông tin tương tự có thể chỉ gắn với các đặc tính của bạn và ngược lại với chuẩn các đặc tính OWL sẵn có bạn cần có một reasoner để tạo ra mô hình. Bạn bổ sung lớp MashupOntologyReader (xem ví dụ 13). Ví dụ 13. Bổ sung reasoner. ... public class MashupOntologyReader { private OntModel serviceOntModel; public MashupOntologyReader(){ String source = ""; serviceOntModel = ModelFactory.createOntologyModel( OntModelSpec.OWL_MEM_MICRO_RULE_INF, null); serviceOntModel.getDocumentManager() .addAltEntry(source, "file:c:/sw/stores.owl" ); serviceOntModel.read( source ); } ... Trong trường hợp này bạn đang dùng một reasoner siêu nhỏ không cung cấp tất cả các khả năng của trọn bộ bản thể luận OWL mà lại cung cấp một sự cân bằng giữa hàm và trình bày. (Tư liệu Jena liệt kê danh sách các reasoner khác nhau). Nếu bây giờ bạn tải lại biểu mẫu bạn sẽ tìm thấy tất cả các lớp con tại chỗ như bạn nhìn thấy trong hình 2. Hình 2. Tất cả các lớp con. Nhưng bây giờ bạn lại có một vấn đề khác. Lựa chọn “Nothing” là gì và nó có nguồn gốc từ đâu? Khử “nothing” Vấn đề ở đây là reasoner đang chạy tốt. Mỗi lớp là một lớp con của owl:Thing mỗi lớp là một liên lớp của owl:Nothing một loạt ví dụ rỗng. Vì thế khi bạn yêu cầu reasoner lấy tất cả các lớp con và nó thực hiện lệnh. Để tránh làm người dùng nhầm lẫn, bạn cần yêu cầu reasoner không hiển thị các lựa chọn riêng biệt (xem ví dụ 14): Ví dụ 14. Loại trừ lựa chọn “Nothing”. .... OntClass serviceClass = reader.getOnt() .getOntClass(""); for (ExtendedIterator i = serviceClass.listSubClasses(); i.hasNext(); ) { OntClass thisClass = (OntClass)i.next(); if (!thisClass.getURI() .equals("")){ response.getWriter().print("<option value='" +thisClass.getURI()+"'>"+ thisClass.getLocalName()+""); } } response.getWriter().print(""); ... Và bây giờ thì kết quả sẽ là những gì bạn mong đợi, xem hình 3. Hình 3. Tập các dịch vụ cuối cùng. Liệt kê các dịch vụ Khi người dùng gửi biểu mẫu thì nó sẽ tự quay trở lại phương thức doGet() bởi vì hoạt động này đã được quy định trên phần tử form. Khi máy chủ nhận được yêu cầu này nó sẽ kiểm tra xem liệu tham số serviceType đã được chấp nhận chưa. Nếu tham số serviceType chưa được chấp nhận thì máy chủ sẽ hiển thị dạng gốc. Ngược lại, nếu nó đã được chấp nhận thì bạn phải sẵn sàng cho giai đoạn hai của biểu mẫu (xem ví dụ 15). Ví dụ 15. Liệt kê các dịch vụ ... protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { MashupOntologyReader reader = new MashupOntologyReader(); response.getWriter().print(""); response.getWriter().print(""); response.getWriter().print(""); response.getWriter().print("The Mashup"); String serviceType = request.getParameter("serviceType"); if (serviceType == null) { response.getWriter().println( "<form action='MashupClientServlet' method='get'>"); ... response.getWriter().print(""); } else { response.getWriter().println( "<form action='MashupClientServlet' method='get'>"); Individual serviceTypeClass = reader.getOnt().getIndividual(serviceType); String serviceTypeName = serviceTypeClass.getLocalName(); Individual[] individuals = reader.getIndividuals(serviceTypeName); response.getWriter().println( "<input type='hidden' value='"+serviceType+ "' name='serviceType' />"); response.getWriter().print("Choose a service:"); response.getWriter().print("<select name=\"serviceURI\">"); 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().println("<input type='submit' />"); response.getWriter().print(""); response.getWriter().print(""); response.getWriter().print(""); } ... Ở giai đoạn hai của biểu mẫu bạn lấy một tham chiếu tới một lớp serviceType do URI trình bày và sau đó sử dụng localName của nó để lấy tất cả Individuals của lớp đó bằng cách sử dụng phương thức getIndividuals() mà bạn đã xây dựng được ở phần 5 (xem Tài nguyên). Sau đó bạn có thể xây dựng biểu mẫu hiện thời. Bắt đầu bằng việc tạo ra một trường ẩn dọc theo serviceType. Tạo một phần tử select, hiển thị phần tử option bằng cách sử dụng URI như một giá trị và localName hoặc label (nếu muốn) như một văn bản người dùng có thể thấy được. Kết quả sẽ là một trang tương tự như hình 4. Hình 4. Danh sách các dịch vụ Định nghĩa kết quả xuất Bây giờ thì bạn đã biết người dùng muốn dịch vụ nào. Bạn cần xem người dùng muốn loại thông tin nào người dùng muốn tìm kiếm. Để làm điều này, bạn cần tạo ra một biểu mẫu chấp nhận tất cả lựa chọn của người dùng (xem ví dụ 16). Ví dụ 16. Định nghĩa kết quả xuất. ... ... protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { MashupOntologyReader reader = new MashupOntologyReader(); ... String serviceURI = request.getParameter("serviceURI"); if (serviceType == null) { ... } else if (serviceURI == null){ response.getWriter().println( "<form action='MashupClientServlet' method='get'>"); ... response.getWriter().print(""); } else { response.getWriter().println( "<form action='MashupClientServlet' method='get'>"); response.getWriter().println("<input type='hidden' value='" +serviceType+"' name='serviceType' />"); response.getWriter().println("<input type='hidden' value='" +serviceURI+"' name='serviceURI' />"); response.getWriter().println("Define your output"); response.getWriter().println( "Define a template and choose the data to go into it."+ "For example, to create a link, you might create a "+ "template of <value "+ "/>. From there, designate the order in "+ "which you want properties to appear."); response.getWriter().println("<textarea name='template' "+ "rows='5' cols='80'>"); System.out.println("serviceuri="+serviceURI); OntClass serviceClass = reader.getOnt().getOntClass(serviceType); Property outputProp = (Property)reader.getOnt() .getProperty(""); RDFNode outputPropVal = serviceClass.getPropertyValue(outputProp); System.out.println("The service outputs items of type " +outputPropVal.toString()); } response.getWriter().println("<input type='submit' />"); response.getWriter().print(""); response.getWriter().print(""); response.getWriter().print(""); } ... Phần đầu của biểu mẫu này rất đơn giản. Nó chỉ là một textarea mà người dùng có thể nhập vào đó một khuôn mẫu giống các khuôn mẫu mà bạn đã và đang sử dụng trong suốt đề tài này. Sau đó, mọi việc hơi phức tạp hơn. Trước khi bạn nhập các đặc tính bạn cần biết loại lớp nào mà bạn đang thấy. Để biết điều này bạn truy lục một tham chiếu vào lớp serviceType và dùng nó để truy lục đặc tính outputType. Chính Property đại diện cho một lớp và lớp đó có các đặc tính riêng của nó. Truy vấn các đặc tính Đến đây bạn đã sẵn sàng cho việc truy lục các đặc tính nhưng điều này không có nghĩa là bạn nhúng tất cả các hàm vào servlet bởi vì hàm này tương tự những thao tác bạn đã thực hiện ở lớp MashupOntologyReader. Đặc biệt là tạo ra một phương thức mới ở trong lớp đó được gọi là getAllProperties() như mô tả ở ví dụ 17. ví dụ 17. Phương thức getAllProperties() ... public class MashupOntologyReader { ... public Vector getAllProperties(OntClass theClass){ Vector properties = new Vector(); String thisClassURI = theClass.getURI(); for (ExtendedIterator i = theClass.listDeclaredProperties(); i.hasNext(); ) { OntProperty thisProp = (OntProperty)i.next(); Property labelProp = (Property)serviceOntModel.getProperty( " schema#label"); if (thisProp.hasProperty(labelProp)){ System.out.println("Property: "+ thisProp.getProperty(labelProp).getLiteral()); } if (thisProp.isObjectProperty()){ System.out.println( "this bears further investigation: "); } else { properties.add(thisProp); } } return properties; } ... Phương thức này mang tính đồng nhất ảo đối với phương thức showAllProperties() mà bạn đã tạo ra trước đây ngoại trừ việc nó gửi lại một Vector có chứa tất cả các đối tượng Property. Bạn có thể dùng phương thức này trong servlet. Hiển thị các đặc tính Biểu mẫu hiện thời cần trình bày vài nhiệm vụ. Ngoài việc truy lục template của người dùng, nó không chỉ liệt kê các đặc tính mà còn cho người dùng cơ hội yêu cầu sử dụng các đặc tính như các thuộc tính và các phần tử (xem ví dụ 18). Ví dụ 18. Hiển thị đặc tính. ... public class MashupClientServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet { public MashupClientServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ... OntClass serviceClass = reader.getOnt().getOntClass(serviceType); Property outputProp = (Property)reader.getOnt() .getProperty(""); RDFNode outputPropVal = serviceClass.getPropertyValue(outputProp); System.out.println("The service outputs items of type " +outputPropVal.toString()); OntClass returnObjectClass = reader.getOnt() .getOntClass(outputPropVal.toString()); Vector properties = reader.getAllProperties(returnObjectClass); response.getWriter().println("Attribute"+ "positionElement<br />position"+ "Property name"); for (int i = 0; i < properties.size(); i++) { String cleanPropName = ((Property)properties.elementAt(i)).getURI() .replaceAll("#", "_").toString() .replaceAll("http://", "_"); response.getWriter().println("<input "+ "type='text' size='2' name='attribute"+ cleanPropName+"' />"); response.getWriter().println("<input "+ "type='text' size='2' name='element"+ cleanPropName+"' />"); response.getWriter().print(""+ ((OntProperty)properties.elementAt(i)) .getLabel(null)+""); } response.getWriter().println(""); } response.getWriter().println(""); response.getWriter().print(""); response.getWriter().print(""); response.getWriter().print(""); } ... Đầu tiên biểu mẫu truy lục một tham chiếu tới lớp đầu ra và sau đó gọi phương thức getAllProperties() để lấy một Vector các đặc tính cho lớp đó. Từ đây tạo một khung của bảng HTML để sắp xếp những đặc tính này cho người dùng nhìn thấy. Bây giờ bạn đã sẵn sàng lặp đi lặp lại qua mỗi đặc tính. Biểu mẫu cuối cùng là như hình 5 gồm hai hộp văn bản cho mỗi đặc tính. Bạn cần phải tạo một cái tên để kết nối dữ liệu của các hộp văn bản tới đặc tính. Bạn không thể dùng URI gốc cho các đặc tính tuy nhiên thay vì dùng URI gốc bạn có thể tạo ra một phiên bản URI mới để loại bỏ các ký tự lỗi và thay thế chúng bằng các ký tự gạch dưới. Khi việc này hoàn thành, bạn có thể tự do tạo một phiên bản thuộc tính và phần tử cho từng hộp văn bản cho từng đặc tính. (Trong một ứng dụng sản xuất bạn cần đảm bảo rằng tất cả các đặc tính này đều có nhãn hoặc bắt được lỗi ở đây. Bạn cũng có thể muốn có khả năng lựa chọn các ngôn ngữ khác nhau hơn là lờ việc này đi). Biểu mẫu cuối cùng sẽ trông giống như ở hình 5. Hình 5. Biểu mẫu đặc tính. Tạo biểu mẫu cuối cùng Bây giờ bạn đã thu thập đủ tất cả các thông tin từ người dùng, bạn đã sẵn sàng cho việc tái tạo biểu mẫu truy vấn gốc. Biểu mẫu này không chỉ bao gồm hộp đầu nhập cho thuật ngữ truy vấn mà còn chứa tất cả các thông tin người dùng đã chấp nhận, mã hóa như các trường ẩn (xem ví dụ 19). Ví dụ 19. Biểu mẫu cuối cùng. ... ... protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ... String serviceType = request.getParameter("serviceType"); String serviceURI = request.getParameter("serviceURI"); String template = request.getParameter("template"); if (serviceType == null) { ... } else if (template == null){ ... } else { response.getWriter().println( "<form action='MashupClientServlet' method='post'>"); response.getWriter().println( "<input type='hidden' value='"+serviceType+ "' name='serviceType' />"); response.getWriter().println( "<input type='hidden' value='"+serviceURI+ "' name='serviceURI' />"); response.getWriter().println( "<input type='hidden' value='"+ template.replaceAll("<", "<") .replaceAll("'", "'") .replaceAll("\"", """)+ "' name='template' />"); OntClass serviceClass = reader.getOnt().getOntClass(serviceType); Property outputProp = (Property)reader.getOnt() .getProperty(""); RDFNode outputPropVal = serviceClass.getPropertyValue(outputProp); OntClass returnObjectClass = reader.getOnt() .getOntClass(outputPropVal.toString()); Vector properties = reader.getAllProperties(returnObjectClass); for (int i = 0; i < properties.size(); i++) { String cleanPropName = ((Property)properties.elementAt(i)).getURI() .replaceAll("#", "_").toString() .replaceAll("http://", "_"); response.getWriter().println( "<input type='hidden' name='attribute"+cleanPropName+ "' value ='"+ request.getParameter("attribute"+cleanPropName)+"'/>"); response.getWriter().println( "<input type='hidden' name='element"+cleanPropName+ "' value = '"+ request.getParameter("element"+cleanPropName)+"'/>"); } response.getWriter().print("Enter a keyword:"); response.getWriter().print( ""); } response.getWriter().println(""); response.getWriter().print(""); response.getWriter().print(""); response.getWriter().print(""); } ... Các biểu mẫu serviceType và serviceURI rất đơn giản nhưng do khuôn mẫu được làm từ HTML nên bạn không thể thả nó vào giá trị thuộc tính của một phần tử đầu nhập mà không duyệt qua việc giải mã nó. Vì vậy, để giải quyết vấn đề này bạn cần thay thế các ký tự lỗi bằng các thực thể có thể diễn giải ngược trở lại các ký tự tương đương khi người dùng chấp nhận biểu mẫu. Tiếp đó bạn cần tạo các trường ẩn cho các đặc tính. Để thực hiện điều này bạn cần lặp đi lặp lại qua các đặc tính để đạt được các giá trị thuộc tính và phần tử tiềm năng sau đó mã hóa chúng lại thành các trường ẩn. Cuối cùng, tạo biểu mẫu truy vấn Có rất nhiều mã nhưng về cơ bản nó tạo ra HTML (như trong ví dụ 20). Ví dụ 20. Biểu mẫu kết quả. The Mashup<form action='MashupClientServlet' method='post'> <input type='hidden' value=' name='serviceType' /> <input type='hidden' value=' name='serviceURI' /> <a value='href'>, $ ' name='template' /> <input type='hidden' name='attribute_example.com/store_itemPrice' value =''/> <input type='hidden' name='element_example.com/store_itemPrice' value = '2'/> <input type='hidden' name='attribute_example.com/store_itemDescription' value =''/> <input type='hidden' name='element_example.com/store_itemDescription' value = '1'/> <input type='hidden' name='attribute_example.com/store_itemDetailURL' value ='1'/> <input type='hidden' name='element_example.com/store_itemDetailURL' value = ''/> Enter a keyword:<input type='text' name='query' /><input type='submit' /> Ở trình duyệt, tất cả những gì bạn thấy là trường truy vấn (như trong hình 6). Hình 6. Biểu mẫu truy vấn cuối cùng Bây giờ bạn đang thu thập tất cả các dữ liệu đó và bạn sẽ chấp nhận nó ở chương trình phụ trợ. Chấp nhận dữ liệu Để riêng trong tất cả các mã cho biểu mẫu cuối cùng là cố định dùng phương thức POST mà không dùng phương thức GET sẽ đưa bạn quay trở lại phương thức doPost() nơi tất cả các xử lý thực sự diễn ra. Lấy các tham số cơ bản Bước đầu tiên là lấy các tham số cơ bản, các tham số đó là các văn bản dễ dàng truy lục (xem ví dụ 21). Ví dụ 21. Lấy các tham số cơ bản. ... public class MashupClientServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet { ... 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); String template = request.getParameter("template") .replaceAll("<", "<") .replaceAll("'", "'") .replaceAll(""", "\""); System.out.println("Template = "+template); String serviceType = request.getParameter("serviceType").toString(); System.out.println("serviceType = "+serviceType); try { DocumentBuilder builder = DocumentBuilderFactory .newInstance().newDocumentBuilder(); ... Tất cả các bước này đơn giản chỉ là việc truy lục giá trị của các tham số. Mặc dù trong trường hợp khuôn mẫu thì bạn cần đảo ngược các thay đổi mà bạn tạo ra để gửi các dữ liệu thông qua biểu mẫu. Nếu bạn chấp nhận biểu mẫu, bạn nên xem thiết bị đầu cuối sau đây (xem ví dụ 22). Ví dụ 22. Các tham số cơ bản Template = <a value='href'>, $ serviceType = Lấy các dữ liệu đầu vào đặc tính Lấy các dữ liệu đầu vào đặc tính hơi phức tạp một chút nhưng bạn nên tuân theo mẫu bạn đã sử dụng ở bước cuối cùng (xem ví dụ 23). Ví dụ 23. Lấy dữ liệu đầu vào đặc tính. ... String serviceType = request.getParameter("serviceType").toString(); System.out.println("serviceType = "+serviceType); OntClass serviceClass = ont.getOnt().getOntClass(serviceType); Property outputProp = (Property)ont.getOnt() .getProperty(""); RDFNode outputPropVal = serviceClass.getPropertyValue(outputProp); OntClass returnObjectClass = ont.getOnt() .getOntClass(outputPropVal.toString()); System.out.println("returnObjectClass = "+returnObjectClass); Vector properties = ont.getAllProperties(returnObjectClass); String[] attributes = new String[20] ; String[] elements = new String[20] ; for (int i = 0; i < properties.size(); i++) { String cleanPropName = ((Property)properties.elementAt(i)) .getURI().replaceAll("#", "_").toString() .replaceAll("http://", "_"); try { int index = new Integer(request.getParameter( "attribute"+cleanPropName).toString()) .intValue() - 1; attributes[index] = ((Property)properties.elementAt(i)) .getURI(); System.out.println("Attribute = "+attributes[index]); } catch (Exception e){ //Don't do anything, just weed out entries that //aren't integers. } try { int index = new Integer(request.getParameter( "element"+cleanPropName).toString()).intValue() - 1; elements[index] = ((Property)properties.elementAt(i)).getURI(); System.out.println("Element = "+elements[index]); } catch (Exception e){ //Don't do anything, just weed out entries that //aren't integers. } } try { DocumentBuilder builder = DocumentBuilderFactory .newInstance().newDocumentBuilder(); Service[] svcs = {service}; ... Phần đầu trông rất quen thuộc, bạn đã thực hiện nó hai lần để lặp đi lặp lại thông qua các đặc tính. Nhưng việc lấy được các đặc tính lại là chuyện khác. Về cơ bản, bạn sẽ cần hiểu URIs đối với từng đặc tính như là các mục của attributeValues hoặc là elementValues Vectors ở trong lớp Service. Hơn nữa, bạn cần bổ sung chúng theo trình tự lựa chọn của người dùng. Để điều này xảy ra bạn sẽ lặp đi lặp lại thông qua từng đặc tính và nếu người dùng đã nhập một giá trị nguyên, bạn sẽ dùng giá trị nguyên đó như một chỉ mục (mục lục chỉ thị) cho một mảng. Theo cách này bạn sẽ kết thúc bằng một mảng của đặc tính URI theo trình tự người dùng yêu cầu. Nếu bạn tải lại biểu mẫu, bạn sẽ thấy tương tự như trong thiết bị đầu cuối sau đây (xem ví dụ 24). Ví dụ 24. Đầu ra Template = <value />, $ serviceType = returnObjectClass = Property: Item Price Property: Item Description Property: Item Detail Page URL Property: Stocked Product this bears further investigation: Element = Element = Attribute = Lưu ý rằng URI cho các đặc tính bây giờ đã trở lại dạng bình thường. Bổ sung dữ liệu cho dịch vụ Bây giờ bạn cần lưu giữ tất cả các thông tin trong lớp Service hiện thời (xem ví dụ 25). Ví dụ 25. Bổ sung dữ liệu cho dịch vụ ... String template = request.getParameter("template") .replaceAll("<", "<") .replaceAll("'", "'") .replaceAll(""", "\""); service.template = template; String serviceType = request.getParameter("serviceType").toString(); OntClass serviceClass = ont.getOnt().getOntClass(serviceType); Property outputProp = (Property)ont.getOnt() .getProperty(""); RDFNode outputPropVal = serviceClass.getPropertyValue(outputProp); service.recordExp = outputPropVal.toString(); OntClass returnObjectClass = ont.getOnt() .getOntClass(outputPropVal.toString()); ... elements[index] = ((Property)properties.elementAt(i)).getURI(); } catch (Exception e){ //Don't do anything, just weed out entries that //aren't integers. } } service.attributeValues.clear(); service.elementValues.clear(); for (int i = 0; i < 20; i++){ if (attributes[i] != null && !attributes[i].equals("")){ service.attributeValues.add(attributes[i]); } if (elements[i] != null && !elements[i].equals("")){ service.elementValues.add(elements[i]); } } try { DocumentBuilder builder = DocumentBuilderFactory .newInstance().newDocumentBuilder(); Service[] svcs = {service}; ... Bắt đầu từ các lệnh đầu tiên, thuộc tính khuôn mẫu là rất rõ ràng, và recordExp đại diện cho biểu thức xác định các kết quả riêng lẻ. Vì thế, theo cách làm mới này, URI sẽ đại diện cho outputType. Cuối cùng, bạn đã sẵn sàng để bổ sung các thuộc tính đặc tính và các thuộc tính phần tử. Để thực hiện nó bạn đã có các vector của tất cả các giá trị trong dịch vụ vì bạn đã tải nó về từ bản thể luận, sau đó bạn lặp đi lặp lại thông qua các mảng, kết thúc bất kỳ giá trị tồn tại nào tới Vectors. Bởi vì các servlet được cố định để lấy thông tin từ Service nên bạn không cần làm gì thêm để dữ liệu sẵn dùng cho servlet. Biểu hiện dữ liệu dịch vụ Bạn đã có các tham số do người dùng chọn ra, bây giờ là lúc để chúng chuyển từ dạng dữ liệu phác thảo sang dạng đầy đủ. Bạn cần phải thay thể các thao tác có gốc XPath hiện hành sang các thao tác dựa trên bản thể luận. Truyền bản thể luận đi Bước đầu tiên là đảm bảo rằng bản thân bản thể luận có sẵn bất kỳ chỗ nào người dùng cần tới. Trong trường hợp này có nghĩa là để cho nó sẵn sàng với phương thức renderService() của servlet (xem ví dụ 26). Ví dụ 26. Truyền bản thể luận đi ... public static Node renderService(String query, Service svc, Document hostDoc, MashupOntologyReader ont ) { Document document = getData(query, svc); ... } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ... for (int k=0; k < svcs.length; k++){ Service svc = svcs[k]; Node renderedService = renderService( svc.getRESTRequest(ont)+query, svc, hostDoc, ont); if (renderedService != null){ ... Khi bạn gộp bản thể luận như một phần chữ ký cho phương thức renderService() bạn cần phải bổ sung bản thể luận vào lệnh gọi tới phương thức đó. Tải dữ liệu mới Khi bạn thông qua bản thể luận tới phương thức renderService(), nó sẽ chứa tất cả các định nghĩa nhưng không chứa bất kỳ dữ liệu nào. May thay, bạn có thể bổ sung các dữ liệu một cách rất đơn giản (xem ví dụ 27). Ví dụ 27. Tải dữ liệu mới ... ... Document document = getData(query, svc); String source = ""; Model model = ont.getOnt().getDocumentManager() .getModel(""); DOM2Model.createD2M(source, model).load(document); OntModel ontModel = (OntModel)model; Node serviceElement = hostDoc.createElement("span"); DocumentBuilder builder = DocumentBuilderFactory .newInstance().newDocumentBuilder(); ... Lớp DOM2 bao gồm một phương thức tĩnh, createD2M() cho phép bạn tham chiếu mô hình đối với không gian tên (namepspace) bằng cách đặt câu hỏi. Từ đây bạn có thể dễ dàng tải tài liệu DOM làm đại diện cho các dữ liệu do dịch vụ trả về, sau đó chuyển đổi nó sang dạng bản thể luận chung của nó. Bạn có thể nhận thấy sự khác biệt giữa mô hình trước và sau thao tác này bằng việc sử dụng phương thức model.write() nhưng vì không có thời gian nên bạn sẽ tự kiểm tra. Truy lục các đặc điểm riêng biệt dựa trên kiểu dữ liệu đầu ra. Bước tiếp theo là truy lục các kết quả riêng biệt. Đầu tiên, bạn thực hiện việc này bằng việc dùng giá trị của thuộc tính recordExp như một biểu thức XPath. Bây giờ bạn sẽ cần phải dùng outputType (xem ví dụ 28). Ví dụ 28. Truy lục các đặc điểm riêng biệt dự trên kiểu dữ liệu outputType ... DOM2Model.createD2M(source, model).load(document); OntModel ontModel = (OntModel)model; Node serviceElement = hostDoc.createElement("span"); DocumentBuilder builder = DocumentBuilderFactory .newInstance().newDocumentBuilder(); Node toImport = null; // Get individuals based on output type ExtendedIterator recordNodes = ontModel.listIndividuals( ontModel.getOntClass(svc.recordExp)); for (ExtendedIterator i = recordNodes; i.hasNext(); ) { Individual thisRecord = (Individual)i.next(); Document templateDoc = builder.parse(new InputSource( new StringReader(svc.template))); String expression = "//value"; XPath xpath = XPathFactory.newInstance().newXPath(); NodeList templateNodes = (NodeList) xpath.evaluate( expression, templateDoc, XPathConstants.NODESET); for (int j=0; j < templateNodes.getLength(); j++){ Node thisNode = templateNodes.item(j); Node parentNode = thisNode.getParentNode(); // Get the appropriate property value and replace //it in the template if ( (Boolean)xpath.evaluate( svc.elementValues.elementAt(j).toString(), thisRecord, XPathConstants.BOOLEAN)) { Node valueNode = (Node)xpath.evaluate( svc.elementValues.elementAt(j).toString(), thisRecord, XPathConstants.NODE); String valueText = valueNode.getTextContent(); Node replacementNode = templateDoc.createTextNode(valueText); parentNode.replaceChild(replacementNode, thisNode); } } expression = "//@value"; templateNodes = (NodeList) xpath.evaluate(expression, templateDoc, XPathConstants.NODESET); for (int j=0; j < templateNodes.getLength(); j++){ Attr thisNode = (Attr) templateNodes.item(j); Element parentElement = (Element)thisNode.getOwnerElement(); parentElement.removeAttribute("value"); if ( (Boolean)xpath.evaluate( svc.attributeValues.elementAt(j).toString(), thisRecord, XPathConstants.BOOLEAN)) { Node valueNode = (Node)xpath.evaluate( svc.attributeValues.elementAt(j).toString(), thisRecord, XPathConstants.NODE); parentElement.setAttribute( thisNode.getNodeValue(), valueNode.getTextContent()); } } ... Trước tiên bạn lấy điểm lặp của các đặc điểm riêng biệt của lớp outputType, trình bày cho dịch vụ được lưu trong thuộc tính recordExp. Sau đó bạn có thể lặp đi lặp lại thông qua những đặc điểm riêng biệt này như trước. Nhưng lần này bạn dùng đặc điểm thisRecord chứ không dùng một mục trong NodeList. Vào lúc này, đây là tất cả những thay đổi. Tất cả các thao tác XPath khác vẫn ở tại chỗ nhưng bạn thay thế các tham chiếu tới một recordNode bằng thisRecord với đối tượng thisRecord nên servlet sẽ biên dịch ra. Nếu nó không biên dịch thì nó sẽ gửi tới bạn bất cứ kết quả nào bởi vì nó đang tìm kiếm biểu thức XPath cho những dữ liệu không tồn tại. Truy lục thuộc tính phần tử Bạn đang thao tác lặp đi lặp lại thông qua bản ghi riêng biệt, bạn cần tiến lên để thay đổi trình giữ chỗ khuôn mẫu với các dữ liệu người dùng yêu cầu. Khuôn mẫu do người dùng cung cấp nhưng khi phương thức renderService() được đề cập đến thì chưa có điều gì thay đổi, nó vẫn được lưu ở thuộc tính template của lớp Service. Điều thay đổi chính là cách bạn đối phó với các mục trong elementValues và attributeValues Vectors. Ngược lại, trước đây chúng là biểu thức XPath và bạn thường lấy các dữ liệu cụ thể do dịch vụ trả về ra khỏi XML, bây giờ chúng là PropertyURI mà bạn sẽ dùng để lấy dữ liệu bằng cách sử dụng reasoner bản thể luận. Bắt đầu thực hiện việc truy lục đặc tính riêng biệt (xem ví dụ 29). Ví dụ 29. Truy lục đặc tính phần tử. ... String expression = "//value"; XPath xpath = XPathFactory.newInstance().newXPath(); NodeList templateNodes = (NodeList) xpath.evaluate( expression, templateDoc, XPathConstants.NODESET); for (int j=0; j < templateNodes.getLength(); j++){ Node thisNode = templateNodes.item(j); Node parentNode = thisNode.getParentNode(); // Get the appropriate property value and replace //it in the template Property prop2 = ont.getOnt().getProperty( svc.elementValues.elementAt(j).toString()); ... } } ... Tiến trình này thường không phức tạp bởi vì thông tin lưu giữ trên elementValues Vector là chuỗi trình bày URI cho đặc tính đó. Lấy giá trị tương ứng Khi bạn có Property, bạn có thể dùng nó để lấy giá trị từ bản thể luận ra. (Nhớ là bản thể luận bây giờ còn bao gồm các dữ liệu do dịch vụ trả về (xem ví dụ 30)). Ví dụ 30. Truy lục giá trị ... for (int j=0; j < templateNodes.getLength(); j++){ Node thisNode = templateNodes.item(j); Node parentNode = thisNode.getParentNode(); // Get the appropriate property value and replace //it in the template Property prop2 = ont.getOnt().getProperty( svc.elementValues.elementAt(j).toString()); RDFNode propVal2 = thisRecord.getPropertyValue(prop2); if ( propVal2 != null ) { String valueText; if (propVal2.isLiteral()){ valueText = ((Literal)propVal2).getString(); } else { valueText = propVal2.toString(); } Node replacementNode = templateDoc.createTextNode(valueText); parentNode.replaceChild(replacementNode, thisNode); } else { System.out.println("propval2 is null"); } } ... Khi bạn sử dụng phương thức getPropertyValue() trên đối tượng thisRecord để truy lục giá trị bạn cần nhớ là phương thức này không có giá trị rỗng (Null). Nếu nó có giá trị rỗng (Null) thì bạn cần truy lục giá trị nguyên bản (nếu nó là giá trị nguyên bản) hoặc truy lục phiên bản String của giá trị đặc tính. Bằng một trong hai cách thì valueText chứa dữ liệu thích hợp do dịch vụ gửi về và bạn có thể cho phép servlet tiến hành như trước đây, sử dụng dữ liệu này để thay thế value thích hợp của trình giữ chỗ phân tử trong khuôn mẫu. Truy lục các đặc tính thuộc tính Tiến trình mang tính đồng nhất ảo đối với các bộ phận trong một vécto attributeValues. (xem ví dụ 31). Ví dụ 31. Truy lục các đặc tính thuộc tính. ... expression = "//@value"; templateNodes = (NodeList) xpath.evaluate(expression, templateDoc, XPathConstants.NODESET); for (int j=0; j < templateNodes.getLength(); j++){ Attr thisNode = (Attr) templateNodes.item(j); Element parentElement = (Element)thisNode.getOwnerElement(); // Get the appropriate property value and replace //it in the template parentElement.removeAttribute("value"); Property prop3 = ont.getOnt().getProperty( svc.attributeValues.elementAt(j).toString()); RDFNode propVal3 = thisRecord.getPropertyValue(prop3); if ( propVal3 != null ) { String valueText; if (propVal3.isLiteral()){ valueText = ((Literal)propVal3).getString(); } else { valueText = propVal3.toString(); } parentElement.setAttribute( thisNode.getNodeValue(), valueText); } else { System.out.print("prop3 is null"); } } ... Bạn lại tiếp tục thay đổi bằng cách bạn cố định biến số valueText, đoạn mã đã có để thay thế các thuộc tính trình giữ chỗ trong khuôn mẫu vẫn giữ nguyên không đổi. Kết quả cuối cùng Cuối cùng, bạn đã sẵn sàng để xem dữ liệu xuất. Cho khuôn mẫu được nhập trở lại trong hiển thị các đặc tính. Bạn sẽ thấy một kết quả tương tự như ở hình 7. Hình 7. Kết quả cuối cùng Dĩ nhiên nếu bạn nhập một khuôn mẫu khác thì bạn sẽ nhìn thấy một kết quả khác, và đây chính là toàn bộ vấn đề. Bây giờ người dùng có thể trộn và lấy thông tin nào họ cần và cách thông tin được hiển thị theo cách họ muốn trên trang đó. Tóm tắt và nguồn tài nguyên Ngoài lề về mashup đầu tiên này Bạn đã đi một quãng đường dài để đạt tới đích này. Bạn đã bắt đầu với tay không và làm theo cách của mình thông qua việc xây dựng lên một ứng dụng mashup đơn giản được gọi một cách tùy tiện là các dịch vụ Web và hiển thị các dịch vụ này lên một trang Web dựa trên một khuôn mẫu. Bạn đã lưu giữ thông tin như một cạc và sau đó ngắt nó ra thành từng phần để xây dựng một cây thư mục chung nhất. Bây giờ bạn đã sẵn sàng mở ứng dụng để thu dữ liệu nhập từ người dùng. Người dùng có thể chọn bất kỳ dịch vụ sẵn có nào và chọn các thông tin mà dịch vụ nên cung cấp hay chọn cả cách thông tin được hiển thị. Từ đây, mọi thứ dường như trong tầm tay. Chức năng của ứng dụng chỉ bị giới hạn bởi mục đích của bạn khi định nghĩa các dịch vụ thêm (phụ) và các cấu trúc trong bản thể luận. Cuối cùng, không phải tất cả các hàm từ phần một (xem Tài nguyên được chuyển sang quyền kiểm soát của người dùng, khả năng gọi nhiều dịch vụ cũng như khả năng sử dụng các dịch vụ phụ sẽ không còn hiện diện nữa. Tuy nhiên bổ sung lại các khả năng này cũng tương đối đơn giản. Bạn có thể bổ sung nhiều loại dịch vụ bằng việc thay đổi dạng dữ liệu đầu vào để điều chỉnh cho thích hợp với từng loại hình Service Bất cứ đối tượng dịch vụ nào được bổ sung vào services cũng sẽ tuân theo quy trình như thông thường Thậm chí hàm dịch vụ bổ trợ cũng không nằm ngoài tầm tay. Tất cả những gì bạn phải làm là sửa đổi dạng dữ liệu nhập sao cho nếu người dùng chọn cả một phần tử subservice trong khuôn mẫu thì người dùng cũng có thể có cơ hội chỉ rõ đặc điểm tính chất của dịch vụ bổ trợ như đối với các dịch vụ chính. Thêm một mục cho thuộc tính filterExp và bạn có tất cả các thông tin cần thiết để bắt đầu tiến hành các bước. Đây quả là một hành trình dài nhưng kiến thức kỹ thuật ngữ nghĩa không còn là một ý nghĩa viển vông của thì tương lai mà nó có khả năng sử dụng ngay bây giờ và cuộc hành trình này của bạn cũng có ý nghĩa đấy chứ./.

Các file đính kèm theo tài liệu này:

  • pdfUltimate mashup – Các dịch vụ Web và Web ngữ nghĩa (semantic Web), Phần 6.pdf
Tài liệu liên quan