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 при необходимости дополнительных настроек перед обработкой.
При этом потребуется реализовать наследника класса 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.
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 about 10 years ago · 1 revisions