Предоставление выбора пользователю: интерфейс
Цель этого руководства - дать пользователям возможность заменить один сервис другим, основываясь на информации, содержащейся в онтологии. Давайте начнем с предоставления пользователю возможности выбора.
Создание индивидных концептов
Первый шаг состоит в создании индивидных концептов, из которых пользователь будет осуществлять выбор. Вам необходимо создать экземпляры класса Bookstore. Например, текущий файл онтологии выглядит следующим образом (см. листинг 4):
Листинг 4. Создание индивидных концептов
<Bookstore rdf:ID="BarnesAndNoble.com"/>
<Bookstore rdf:ID="Amazon.com"/>
<Bookstore rdf:ID="Buy.com"/>
<Author rdf:ID="J_K_Rowling"/>
<Author rdf:ID="Joanne_Rowling">
<owl:sameAs rdf:resource="#J_K_Rowling" />
</Author>
<Author rdf:ID="Fyodor_Dostoevsky"/>
<Book rdf:ID="Harry_Potter_and_the_Sorcerers_Stone">
<writtenBy rdf:resource="#J_K_Rowling"/>
</Book>
|
Конечно же, это просто перечень Bookstores. Позже мы добавим к ним свойства.
Обратите внимание, что здесь мы определили несколько индивидных концептов различных типов. Для изучения этих объектов используем API.
Создание модели
Для того чтобы немного прояснить ситуацию, все функции онтологии мы будем обрабатывать в новом классе MashupOntologyReader.
Начнем с создания нового класса (см. листинг 5):
Листинг 5. Базовый класс
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();
}
}
|
Здесь для создания модели онтологии мы используем ModelFactory. Обратите внимание, что Jena API также является RDF API, что дает вам возможность создания нескольких различных видов моделей. Понятно, что в этом случае нам нужна модель онтологии, и используя предоставленные константы, мы указываем на то, что хотим хранить ее в памяти.
Загрузка онтологии
Интерфейс Jena API позволяет создать онтологию с нуля и содержит в себе все необходимые для этого методы; однако в данном случае у нас уже есть файл онтологии, который мы можем прочитать, поэтому следующим шагом будет его загрузка в только что созданную модель (см. листинг 6):
Листинг 6. Загрузка онтологии
...
public class MashupOntologyReader {
private OntModel bookStoreOntModel;
public MashupOntologyReader(){
String source = "http://example.com/store";
// 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();
}
}
|
Сначала создадим исходное пространство имен для загружаемых объектов. Для онтологии, созданной в четвертой части, этим пространством имен будет http://www.example.com/store. Для добавления записей мы используем DocumentManager модели. Обратите внимание, что мы указываем пространство имен и файл, из которого будут поступать записи, но фактически модель не будет считывать эти данные, пока не будет вызван метод read().
Последовательная обработка индивидных концептов
Наша цель состоит в получении списка всех индивидных концептов Bookstore, содержащихся в онтологии, поэтому мы начнем их последовательную обработку в цикле (см. листинг 7):
Листинг 7. Последовательная обработка индивидных концептов
...
// 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();
}
}
|
Для начала создадим метод getIndividuals(), который создает счетчик и использует метод listIndividuals() модели онтологии для получения стандартного Iterator Java, посредством которого мы получим доступ к каждому из найденных индивидных концептов. Пока у нас нет никаких данных о присутствующих индивидных концептах, поэтому мы просто выводим счетчик, чтобы посмотреть, что произойдет. Мы должны получить список чисел от одного до одиннадцати.
Все это интересно, но очевидно, что мы получили не просто индивидные концепты Bookstore. Давайте посмотрим, что же мы получили на самом деле.
Получение информации об индивидных концептах
Когда у вас есть ссылка на индивидный концепт, получение информации о нем - это просто вопрос вызова getter-метода, реализованного в API. Каждый индивидный концепт Individual, независимо от типа, содержит одни и те же три элемента информации: унифицированный идентификатор ресурса URI, используемый для уникального обозначения ресурса, тип и название, соответствующие атрибуту rdf:ID в файле RDF (см. листинг 8):
Листинг 8. Получение информации об индивидных концептах
...
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);
}
}
...
|
Результат выполнения должен быть похож на приведенный в листинге 9:
Листинг 9. Вывод информации индивидных концептов
0: Book Harry_Potter_and_the_Sorcerers_Stone
http://example.com/store#Harry_Potter_and_the_Sorcerers_Stone
1: Genre Memoir http://example.com/store#Memoir
2: Genre Philosophy http://example.com/store#Philosophy
3: Genre History http://example.com/store#History
4: Genre Nonfiction http://example.com/store#Nonfiction
5: Genre Fiction http://example.com/store#Fiction
6: Author Fyodor_Dostoevsky http://example.com/store#Fyodor_Dostoevsky
7: Author Joanne_Rowling http://example.com/store#Joanne_Rowling
8: Author J_K_Rowling http://example.com/store#J_K_Rowling
9: Bookstore Buy.com http://example.com/store#Buy.com
10: Bookstore Amazon.com http://example.com/store#Amazon.com
11: Bookstore BarnesAndNoble.com http://example.com/store#BarnesAndNoble.com
|
Обратите внимание, что порядок, в котором выводятся индивидные концепты, не обязательно будет совпадать с порядком их упоминания в файле онтологии. Сейчас это не имеет значения, но будет актуально при добавлении данных в шаблон! К счастью, предупрежден - значит вооружен, и эту проблему легко решить.
Однако на данный момент нам нужно беспокоиться только об извлечении индивидных концептов Bookstore.
Выбор только книжных магазинов
Тот факт, что тип ресурса представлен строкой, делает извлечение только книжных магазинов (bookstore) очень простым, а именно (см. листинг 10):
Листинг 10. Извлечение индивидных концептов только одного типа
...
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");
}
} |
В этом случае мы сравниваем указанный тип с типом каждого из индивидных концептов, и если эти концепты являются теми, которые мы ищем, мы добавляем их к массиву individuals. После проверки всех индивидных концептов мы возвращаем массив как результат работы метода.
Следующим действием будет добавление этой возможности к действующему приложению.
Создание меню выбора из списка сервисов
Теперь мы готовы использовать возможности Jena из действующего Web-приложения. Перед тем, как приступить к работе, убедитесь, что файлы *.jar интерфейса Jena доступны Web-приложению, а класс
MashupOntologyReader доступен сервлету. Добавляем к методу
doGet() следующие функциональные возможности (см. листинг 11):
Листинг 11. Создание меню выбора
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
MashupOntologyReader reader = new MashupOntologyReader();
Individual[] individuals = reader.getIndividuals("Bookstore");
response.getWriter().print("<html>");
response.getWriter().print("<head></head>");
response.getWriter().print("<body>");
response.getWriter().print("<h1>The Mashup</h1>");
response.getWriter().print("<form action='MashupClientServlet'
method='post'>");
response.getWriter().print("<p>Choose a bookstore:</p>");
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+"</option>");
}
}
response.getWriter().print("</select>");
response.getWriter().print("<p>Enter a keyword:</p>");
response.getWriter().print("<input type='text' name='query' />");
response.getWriter().print("<input type='submit' />");
response.getWriter().print("</form>");
response.getWriter().print("</body>");
response.getWriter().print("</html>");
}
|
Во-первых, создаем экземпляр класса MashupOntologyReader, который также загружает онтологию. Теперь мы можем использовать только что созданный метод getIndividuals() для получения массива Bookstore. Теперь, когда у нас есть массив Bookstore, мы можем циклически пройти по нему, как по любому массиву, используя те же методы, что использовались ранее для получения URI и названия или ID. Используем это для создания меню select
в HTML в рамках существующей формы.
Результат работы должен быть похож на представленный на рисунке 1:
Рисунок 1. Добавление поля выбора
Передача формы и вывод выбранного сервиса
Получить сервис, с которым желает работать пользователь, очень просто. На самом деле это делается так же, как при получении любой другой информации, переданной формой (см. листинг 12):
Листинг 12. Получение информации из формы
...
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("<p>Results pulled from "
+serviceURI+"</p>");
try {
DocumentBuilder builder =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
...
|
Просто получите serviceURI как параметр формы. Можно вывести его на страницу, просто чтобы убедиться в том, что все работает.
Теперь мы готовы получить реальную информацию о сервисе.
|