Дипломная работа: Разработка серверной части системы для лингвистических исследований

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

...

</GateDocumentFeatures>

<!-- Далеерасполагаетсятекстспронумерованнымиузлами -->

<TextWithNodes>

<Nodeid="0"/>This

<Nodeid="4"/>

<Nodeid="5"/>is

...

</TextWithNodes>

<!-- Далее располагается набор аннотаций, привязанных к узлам текста -->

<AnnotationSet>

<AnnotationId="0"Type="Token"StartNode="0"EndNode="4">

<Feature>...</Feature>

...

</Annotation>

...

</AnnotationSet>

</GateDocument>

SAX-парсер не учитывает вложенность, но здесь она оказывается не нужна, так как в XML-файле, генерируемомGATE, узлы, содержащие текст и аннотации являются деревом с глубиной 1. Этот факт можно наблюдать в листинге выше (см. листинг3.2). При считывании из файла текстовые узлы создаются с сохранением поля «id», а узлы аннотаций - с полями «id», «type», «startnode», «endnode». Узел «GateDocumentFeatures»содержит информацию о документе в целом, на данный момент он целиком игнорируется.

После обработки XML-файла создается новый экземпляр класса Text, который является деревом с глубиной 1, и каждый лист представляет собой экземпляр класса TextNode. В листе хранится строка с текстом - это может быть слово, фраза, предложение или целый параграф - зависит это от специфики обрабатывающего маркера.

Помимо текста, каждый лист хранит массив аннотаций, каждая из которых представляет собой объект, хранящий название маркера GATE, который произвел данную аннотацию, и строку вида «color-n», где «n» -натуральное число, присвоенное каждому типу аннотаций парсером в порядке встречи этой аннотации в тексте.

Каждый лист дерева имеет метод для преобразования в HTML-элемент, который по сути является элементом«div» с классом, установленным в соответствие со вышеописанной строкой вида «color-n». Создание цветного текста происходит на сервере в методе класса TextNode, где «annotations» представляют собой массив строк вида «color-n» (см. листинг 3.3). На клиентской стороне такие элементы подсвечиваются различными цветами в зависимости от установок, записанных в файле «annotations.css».

Построение аннотированного текста

publicvoidappendAsHtml(StringBuildersb) {

sb.append("<div class=\"colorized-text-node");

for (var annotation : annotations) {

sb.append(" ");

sb.append(annotation.toLowerCase());

}

sb.append("\">");

sb.append(text);

sb.append("</div>");

}

Для вывода статистики по корпусам был разработан классStatistics, который содержит в себе множество StatisticsNode. Каждый такой узел содержит имя аннотации и количество встреч этой аннотации в корпусе. Данная статистика будет отсылаться на микросервис для визуализации статистики, который находится в разработке другим участником Научно-исследовательской лаборатории.

В процессе функционирования сервера непременно могут возникнуть специфические исключительные ситуации, которые, как правило, нельзя описать стандартными исключениями. Для обработки таких ситуаций были разработаны собственные классы исключений (см. таблица 3.3).

Таблица 3.3 - Описание классов пользовательских исключений

Название

Описание исключительной ситуации

CorpusNotFound

Исключение возникает в случае, если корпус не найден. Самый частый пример такого случая - когда клиентская сторона передает idкорпуса, который не существует либо был уже удален.

CredentialsNotMatch

При авторизации пользователь может ввести несуществующий на сервере логин или пароль (умышленно или неумышленно). В таком случае ему будет предложено ввести данные повторно.

DocumentNotCreated

Возникает, если по каким-то причинам документ не удалось создать. Например, в процессе работы библиотеки GATEможет возникнуть исключение. В таком случае документ не удастся создать, так как не будет предоставлена XML-разметка текста.

TextNotPresent

Это исключение выбрасывается, в случае если документ ссылается на удаленный или не созданный текст.

UserAlreadyExists

При регистрации пользователя может оказаться, что логин занят. В таком случае исключение будет перехвачено, и пользователю будет сообщено, что логин занят.

В названии всех классов опущен суффикс Exception для краткости. Этот суффикс считается хорошим тоном при именовании классов исключений в Java, как и во многих других языках.

Клиентская часть разработана с применением HTML5, CSS и JS без использования фреймворков. В ходе работы был разработан свой «микро-фреймворк», с помощью которого выполняются все нужные операции на стороне клиента. Обмен данными между сервером и клиентской частью производится по протоколу HTTP, в большинстве случаев с помощью JSON, за исключением GET-запросов, которые не позволяют иметь тело запроса. В этом случае информация кодируется прямо в адресной строке.

Документы HTML, получаемые клиентской частью, обрабатываются на сервере Thymeleaf, который может добавлять данные как в HTML, так и в JSсценарии, а также могут вставляться шаблоны из других документов, что обеспечивает активное переиспользование кода. Далее будут подробно рассмотрены каждый из созданных HTML-документов.

В-первых, разметка начальной страницы хранится в файле index.html (см. рисунок 3.5). С этой страницы можно перейти на другие страницы портала, а также пройти регистрацию или авторизацию. После авторизации пользователю будут доступны его личные корпуса, а также те корпуса, которые он может просматривать по своему уровню привилегий.

Рисунок 3.5 - Загруженная с сервера начальная страница

С главной страницы можно попасть на страницу регистрации нового пользователя - registration.html. На этой странице пользователь вводит логин, придумывает пароль, далее его подтверждает. Если созданный логин еще не использован в системе, то пользователь регистрируется и перенаправляется на главную страницу.(см. рисунок 3.6).

Рисунок 3.6 - Страница регистрации пользователя

В случае, если пользователь уже зарегистрирован, или же сразу после регистрации, он может перейти с главной страницы на страницу авторизации login.html (см. рисунок 3.7). Подобно странице регистрации, пользователь здесь вводит свой логин и пароль (подтверждение в этот раз уже не требуется). Если система находит человека с таким логином и паролем в базе, то пользователь считается авторизованным, и его перенаправляют на главную страницу.

Рисунок 3.7 - страница авторизации пользователя

Следующая страница - corpora.html - содержит разметку для отображения корпусов текстов в системе (см. рисунок 3.8). Корпуса загружаются с сервера динамически, следовательно, обновление страницы не понадобится при добавлении нового корпуса. Само добавление происходит с помощью модального окна, которое изначально скрыто и может быть открыто с помощью сценариев. В этом окне нужно указать название корпуса и нажать на кнопку сохранения. Для динамического создания элементов в списке корпусов создана разметка, которая предполагает, что по нажатию на название корпуса произойдет переход на страницу документов.

Рисунок 3.8 - Загруженная с сервера страница корпусов

Для отображения документов используется область на странице корпусов, которая имеет динамический список документов, поле для аннотированного текста, которое активируется по нажатии на документ. Справа от него появляется панель, на которой отображен динамический список аннотаций, каждая из которых может быть отключена по нажатии на флажок (см. рисунок 3.9). Для загрузки документов создано модальное окно, которое, по аналогии с модальным окном на странице корпусов, является скрытым изначально. В этом модальном окне пользователь указывает/переносит документы для загрузки, и далее нажимает на кнопку сохранения.

Рисунок 3.9 - Загруженная с сервера страница документов

Так как файлы разметки были выполнены специально для их последующей обработки в Thymeleaf, они содержат нестандартные атрибуты, однако это не мешает им быть отображенными в браузере как обычный HTML-файл. Согласно спецификации HTML5, нестандартные атрибуты должны быть проигнорированы браузерами. В страницах, загруженных таким образом, не будет контента, так как большая часть его загружается динамически с помощью скриптов. Однако такое использование разработанных HTML-файлов не предполагается, так как ожидается их предварительная обработка на сервере, и лишь после этого представление пользователю.

Таблицы стилей

Разработаны таблицы стилей для основных страниц портала, а также стили, указывающие цвета при отображении текста с аннотациями. Для классов аннотаций в файле стилей выделены особые пронумерованные наименования, которые генерируются сервером при обработке входящего документа. В поле отображения текста отдельные аннотированные единицы отображаются выделенным для них цветом. Была предпринята попытка подобрать нейтральные и довольно контрастные цвета для улучшения различимости их в тексте.В отдельный файл вынесены стили для страниц авторизации и регистрации, так как дизайн страниц схож, и многое оттуда не используется на других страницах.

Сценарии страниц

В учебных целях не было использовано никаких JS-фреймворков; фактически, был написан свой собственный «микро-фреймворк», обеспечивающий все необходимые порталу функции.

Для каждой HTML-страницы выделен свой файл со сценарием, в каждой из которых присутствует объект представления, унаследованный от базового View. Внутри этих объектов прописаны все взаимодействия внутри страницы. Некоторые из элементов страницы генерируются на клиентской стороне, например, список документов корпуса загружается динамически с помощью собственной универсальной функции для выполнения HTTP-запросов.

Так как коммуникация с сервером происходит при помощи протокола HTTP, изначально были реализованы функции для проведения таких запросов с помощью встроенного в JSAPIXHttpRequest. Обертка над этим APIудобна, лаконична, и может использоваться в асинхронном коде, так как запрос происходит с помощью создания объекта Promise, который содержит отложенный результат. Также созданные функции позволяют регулировать формат отправки/получения, по умолчанию установленный в JSON для всего, кроме формата отправки для запросов GET - эти запросы передают параметры в адресной строке в специальном виде URL-encoded.

В задачах отображения модальных окон, а также для создания динамического списка элемента было принято решение использовать шаблоны этих элементов, встроенные в HTML-разметку (скрытые изначально). Для эффективного управления динамическими шаблонами была создана функция traverse, которая выполняет обход в глубину от указанного корня дерева DOM (например, это корневой элемент модального окна или элемента в динамическом списке). По прохождении каждого узла функция запоминает элементы, сохраняя их в словарь, в котором ключами являются: названия классов элементов, idэлементов, а также атрибут nameдля элементов формы.

Для облегчения работы и понижения количества ошибок при работе с null/undefined объектами в JavaScript был разработан класс Optional по образу и подобию такового в Java. Класс инкапсулирует возможно пустой объект и предоставляет методы для работы с ним при его наличии или же отсутствии. Основные методы данного класса приведены ниже (см. таблица 3.4).

Таблица 3.4 - Основные методы класса Optional

Название

Параметры

Возвращаемое значение

Примечания

конструктор(значение)

значение

<объект>

Создает объект Optionalиз потенциально отсутствующего объекта - значения nullи undefinedпризнаются отсутствием объекта, и Optionalсоздается пустым.

get value

Значение, если присутствует, иначе исключение

Возвращает значение, инкапсулируемое экземпляром класса Optional, если же Optional пустой - генерируется исключение MissingValueError.

get present

Содержит ли Optional значение?

Возвращает «истина», если объект Optionalбыл инициализирован со значением, отличным от nullи undefined.

toString()

other

Строковое представление Optional

Конвертирует объект Optionalв строку, в случае если значение отсутствует, то возвращается параметр other.

filter

predicate

Тот же самый Optional, если predicate возвращает «истина», иначе пустой Optional

Заданный предикат вызывается со значением внутри Optional, в случае если предикат возвращает «ложь», метод возвращает пустой Optional.

map

mapper

Обработанный mapper результат

Функция mapperпринимает один аргумент - внутреннее значение объекта Optional, а возвращает новое значение, которые потом оборачивается в Optional. Таким образом, результатом mapperдолжен быть непустой объект. В случае, если Optional пуст, возвращается пустой Optional.

flatMap

mapper

Обработанный mapper результат

Функция mapperпринимает один аргумент - внутреннее значение объекта Optional, а возвращает новый экземпляр Optional, который также может быть пустым.

ifPresent

consumer

В функции consumerвыполняется обработка значения Optional. Consumerвызывается только в случае, если Optional не пуст.

orElse

other

Если Optional не пуст - значение, иначе other

Возвращает значение Optional в случае, если он не пустой. В случае, если объект отсутствует в экземпляре Optional, то метод возвращает объектother.

orElseGet

supplier

Если Optional не пуст - значение, иначе результат вызова supplier

Возвращает значение Optional в случае, если он не пустой. Иначе возвращает результат вызова функции supplierбез параметров.