Project

General

Profile

Actions

Document processors

Requality содержит api для создания собственных обработчиков документов. Для реализации некоторого специфического обработчика можно воспользоваться интерфейсом IDocumentProcessor. При этом необходимо описать три метода:
setEncoding - устанавливающий кодировку
configure - вызываемый перед обработкой метод для настройки процессора. Например, может быть использован для запроса дополнительных параметров у пользователя.
process(String docId, TreeNode rootNode) — метод непосредственной обработки документа, параметры включают в себя идентификатор документа и элемент каталога требований
При использовании указанного подхода может осуществляться любая работа с документом, но при этом требуется описывать все связанные методы, в том числе связанные с загрузкой и выгрузкой содержимого документа. Для получения потока входных данных из документа с переданным идентификатором можно использовать пример:
Document doc = (Document) db.getNode(docQId);
String htmlName = doc.getResourceName();
Reader reader = new InputStreamReader(doc.getResourceContent(htmlName),
encoding);
Имеется возможность использования реализации интерфейса скрывающего работу с файлом и предполагавшего работу с двумя потоками данных (DocumentProcessor) — на поток входных данных подается текущее содержимое документа, на поток выходных данных выводится модифицированная версия документа. Для импорта требований в таком случае будут добавлены теги соответствующие разметке требований. Стоит дополнительно отметить, что в случаях когда изменения документа не требуется, прочитанное содержимое должно быть записано в выходной поток иначе оно будет потеряно.
Для работы с классом необходимо наследовать класс и реализовать метод process(String docId, Reader reader, Writer writer, TreeNode rootNode) на вход которому подается идентификатор документа, Reader, Writer и элемент каталога требований для доступа к каталогу требований. Также при необходимости можно переопределить метод configure при необходимости дополнительных настроек перед обработкой.

На данный момент предусмотрено два наиболее часто применимых сценария работы с документами — автоматическое получение элементов каталога требований и изменение элементов каталога требований при переходе на новую версию документа. Для реализации обработчика согласно первому сценарию можно воспользоваться Simple API for XML реализацией обработчика с набором предопределенных возможностей по работе с каталогом требований. При использовании данного подхода происходит последовательная обработка всех xml элементов в форме событий одного из трех основных видов, соответствующих обработке соответственно открывающего тега, закрывающего тега и фрагмента текста.
При этом потребуется реализовать наследника класса SAXDocumentParser и реализовать метод processEvent(XMLEvent event, XMLEventFactory eventFactory, XMLEventWriter writer, TreeNode rootNode). Метод соответствует обработке одного события парсером XMLEventFactory. Параметры:
event — обрабатываемое XMLEvent событие. Может соответствовать открытию тега(event.isStartElement()), закрытию тега(event.isEndElement()) или набору символов (event.isCharacters())
eventFactory — фабрика для создания новых тегов или свойств
writer — интерфейс записи новой версии документа. При отсутствии изменений event должен быть записан во writer
rootNode — ссылка на элемент каталога требований
Для организации работы с документом также доступно несколько методов облегчающих запись в измененный вариант документа данных:
  • startTag(String tagName,[ Map<String,String> attrib]) - открытие тега с именем tagName и набором свойств attrib в форме пар имя-значение. При этом свойства могут не указываться
  • endTag(String tagName) — закрытие тега с именем tagName
  • startRequirementFragment(Requirement req) - метод используемый для обозначения начала разметки фрагмента требования. Параметр — требование для которого размечется фрагмент.
  • endRequirementFragment() - метод обозначающий окончание разметки фрагмента требования
  • createRequirement([String name], [Requirement parent]) — метод для создания нового требования с указанным именем как потомка требования parent. Если параметр parent не указан то создает требование как потомка элемента /Requirements. Если не указан параметр name то используется автоматически сгенерированный идентификатор. Чтобы изменить имя требования следует впоследствии для требования последовательно выполнить операции .setName(String name) и .saveAttributes().
  • createComment(String description, [Requirement parent]) — метод для создания нового комментария, содержащего указанное в параметре description описание. Параметр parent — элемент для которого создается комментарий, при отсутствии параметра комментарий создается для элемента /Requirements
  • getElement(String qualifiedId) — метод для получения элемента из каталога требований по пути к нему. Возвращает null если по указанному пути элемент не обнаружен
  • getLocalTagName(XMLEvent event) — метод возвращающий имя тега для события если это возможно, иначе возвращающий null
  • getTagAttribute(XMLEvent event, String attribName, [String defValue]) — метод возвращающий свойство открывающегося тега. Если свойства с указанным именем(attribName) не существует то возвращает значение defValue. Если последний не определен то возвращает null.
Как пример использования приведенных механизмов можно привести код добавления требований для заголовков H1:
boolean headerStarted = false;
Requirement createdReq = null;
StringBuilder stored = new StringBuilder();
void processEvent(XMLEvent event, XMLEventFactory eventFactory, XMLEventWriter writer, TreeNode rootNode){
        if(event.isStartEvent()){
            String tagName = getLocalTagName(event);
            if(tagName.toLowerCase().equals(«h1»)){
                writer.add(event);
                headerStarted = true;
                stored.setLength(0);
                createdReq = createRequirement();
                startRequirementFragment(createdReq);
            }else
                writer.add(event);
        }else if(event.isEndEvent()){
            String tagName = getLocalTagName(event);
            if(tagName.toLowerCase().equals(«h1»))
            {
                String reqName = stored.toString();
                if(reqName.length>50)
                    reqName = reqName.substring(0,50);
                createdReq.setName(reqName);
                createdReq.saveAttributes();
                endRequirementFragment(createdReq);
                createdComment(stored.toString(), createdReq);
            }
            writer.add(event);
        }else if(event.isCharacters()){
            String content = event.asCharacters().getData();
            stored.append(content);
            writer.add(event);
        }else
            writer.add(event);
}

Другой задачей является реализация обработчика для переноса требований из одной версии документа в другую. В данном случае имеется возможность использовать класс DOMDocumentUpdateProcessor предоставляющий ряд возможностей для организации подобного процесса.
DOMDocumentUpdateProcessor также включает в себя несколько предопредленных методов для работы с каталогом требований, в том числе
  • getLocation(TreeNode, String) для получения существующего Location по его UUID в строковом представлении
  • getRequirementNode(TreeNode, String) для получения существующего Requirement по его Qualified Id или User Visible id.
  • createLocation(Document, Node, int, Node, int, Document, Requirement) для создания нового фрагмента требования в документе. Содержит описание начала и конца выделения с возможностью указания точек до(POSITION_BEFORE) и после(POSITION_AFTER) выбранного элемента DOM модели. Содержит указание на целевой документ — обычно на требуемый обновления, то есть на соответствующий новой версии спецификации, и на целевое требование к которому будет добавлен создаваемый фрагмент
  • addLocation(Document, Node, int, Node, int, String) для пометки фрагмента текста как принадлежащего существующему фрагменту с соответствующим id.
  • createRequirement(TreeDB, String, Requirement) для создания требования-потомка выбранного требования. Устанавливает имя созданного элемента если оно было передано. TreeDB может быть получен у rootNode вызовом rootNode.getTreeDB()
  • createRequirement(TreeDB, String) для создания требования-потомка /Requirements
    Для наследования класса требуется определить метод process принимающего в виде параметров пути к документам, DOM модели «старого», то есть содержащего разметку в случае перехода на новую версию спецификации и «нового», в рассматриваемом случае не содержащего разметки, элемент каталога требований. Метод предполагает наличие возвращаемого значения в виде DOM модели, которая будет записана в содержимое «нового» документа.

Updated by Denis Kildishev over 9 years ago · 1 revisions