/**
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
*
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
* graphic logo is a trademark of OpenMRS Inc.
*/
package org.openmrs.module.radiology.report.template;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.openmrs.ConceptReferenceTerm;
import org.openmrs.ConceptSource;
import org.openmrs.api.APIException;
import org.openmrs.api.ConceptService;
import org.openmrs.api.context.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* A parser to parse MRRT report templates and and return an MrrtReportTemplate object.
*/
class DefaultMrrtReportTemplateFileParser implements MrrtReportTemplateFileParser {
private static final Logger log = LoggerFactory.getLogger(DefaultMrrtReportTemplateFileParser.class);
private static final String DCTERMS_TITLE = "dcterms.title";
private static final String DCTERMS_DESCRIPTION = "dcterms.description";
private static final String DCTERMS_IDENTIFIER = "dcterms.identifier";
private static final String DCTERMS_TYPE = "dcterms.type";
private static final String DCTERMS_LANGUAGE = "dcterms.language";
private static final String DCTERMS_PUBLISHER = "dcterms.publisher";
private static final String DCTERMS_RIGHTS = "dcterms.rights";
private static final String DCTERMS_LICENSE = "dcterms.license";
private static final String DCTERMS_DATE = "dcterms.date";
private static final String DCTERMS_CREATOR = "dcterms.creator";
private MrrtReportTemplateValidator validator;
public void setValidator(MrrtReportTemplateValidator validator) {
this.validator = validator;
}
/**
* @see MrrtReportTemplateFileParser#parse(String)
*/
@Override
public MrrtReportTemplate parse(String mrrtTemplate) throws IOException {
validator.validate(mrrtTemplate);
final Document doc = Jsoup.parse(mrrtTemplate, "");
final MrrtReportTemplate result = new MrrtReportTemplate();
initializeTemplate(result, doc);
try {
addTermsToTemplate(result, doc.getElementsByTag("script")
.get(0)
.toString());
}
catch (ParserConfigurationException | SAXException e) {
throw new APIException("radiology.report.template.parser.error", null, e);
}
return result;
}
private final void initializeTemplate(MrrtReportTemplate template, Document doc) {
final Elements metaTags = doc.getElementsByTag("meta");
template.setPath(doc.baseUri());
template.setCharset(metaTags.attr("charset"));
for (Element metaTag : metaTags) {
final String name = metaTag.attr("name");
final String content = metaTag.attr("content");
switch (name) {
case DCTERMS_TITLE:
template.setDcTermsTitle(content);
break;
case DCTERMS_DESCRIPTION:
template.setDcTermsDescription(content);
break;
case DCTERMS_IDENTIFIER:
template.setDcTermsIdentifier(content);
break;
case DCTERMS_TYPE:
template.setDcTermsType(content);
break;
case DCTERMS_LANGUAGE:
template.setDcTermsLanguage(content);
break;
case DCTERMS_PUBLISHER:
template.setDcTermsPublisher(content);
break;
case DCTERMS_RIGHTS:
template.setDcTermsRights(content);
break;
case DCTERMS_LICENSE:
template.setDcTermsLicense(content);
break;
case DCTERMS_DATE:
template.setDcTermsDate(content);
break;
case DCTERMS_CREATOR:
template.setDcTermsCreator(content);
break;
default:
log.debug("Unhandled meta tag " + name);
}
}
}
private final void addTermsToTemplate(MrrtReportTemplate template, String script)
throws ParserConfigurationException, SAXException, IOException {
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
final DocumentBuilder builder = factory.newDocumentBuilder();
try (InputStream in = new ByteArrayInputStream(script.getBytes())) {
final org.w3c.dom.Document scriptPartAsDocument = builder.parse(in);
scriptPartAsDocument.getDocumentElement()
.normalize();
final NodeList terms = scriptPartAsDocument.getElementsByTagName("term");
final ConceptService conceptService = Context.getService(ConceptService.class);
final Set<ConceptReferenceTerm> referenceTerms = new HashSet<>();
for (int i = 0; i < terms.getLength(); i++) {
final org.w3c.dom.Element termElement = (org.w3c.dom.Element) terms.item(i);
final org.w3c.dom.Element codeElement = (org.w3c.dom.Element) termElement.getElementsByTagName("code")
.item(0);
final ConceptSource conceptSource =
getConceptSourceByName(codeElement.getAttribute("scheme"), conceptService);
if (conceptSource != null) {
final ConceptReferenceTerm referenceTerm =
conceptService.getConceptReferenceTermByCode(codeElement.getAttribute("value"), conceptSource);
if (referenceTerm != null) {
referenceTerms.add(referenceTerm);
}
}
}
if (!referenceTerms.isEmpty()) {
template.setTerms(referenceTerms);
}
}
}
private final ConceptSource getConceptSourceByName(String name, ConceptService conceptService) {
final List<ConceptSource> conceptSources = conceptService.getAllConceptSources(false);
for (ConceptSource conceptSource : conceptSources) {
if (conceptSource.getName()
.equalsIgnoreCase(name)) {
return conceptSource;
}
}
return null;
}
}