package org.hl7.fhir.utilities.xml;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2017 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import org.hl7.fhir.utilities.TextStreamWriter;
import org.hl7.fhir.utilities.Utilities;
public class SchematronWriter extends TextStreamWriter {
public enum SchematronType {
ALL_RESOURCES,
RESOURCE,
PROFILE
}
public class Assert {
private String test;
private String message;
}
public class Rule {
private String name;
private List<Assert> asserts = new ArrayList<Assert>();
public void assrt(String test, String message) {
Assert a = new Assert();
a.test = test;
a.message = message;
asserts.add(a);
}
}
public class Section {
private String title;
private List<Rule> rules = new ArrayList<Rule>();
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Rule rule(String name) {
for (Rule r : rules) {
if (r.name.equals(name))
return r;
}
Rule r = new Rule();
r.name = name;
rules.add(r);
return r;
}
}
private SchematronType type;
private String description;
private List<Section> sections = new ArrayList<Section>();
public SchematronWriter(OutputStream out, SchematronType type, String description) throws UnsupportedEncodingException {
super(out);
this.type = type;
this.description = description;
}
public Section section(String title) {
for (Section s : sections) {
if (s.title.equals(title))
return s;
}
Section s = new Section();
s.title = title;
sections.add(s);
return s;
}
public void dump() throws IOException {
ln("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
ln_i("<sch:schema xmlns:sch=\"http://purl.oclc.org/dsdl/schematron\" queryBinding=\"xslt2\">");
ln("<sch:ns prefix=\"f\" uri=\"http://hl7.org/fhir\"/>");
ln("<sch:ns prefix=\"h\" uri=\"http://www.w3.org/1999/xhtml\"/>");
addNote();
for (Section s : sections) {
ln_i("<sch:pattern>");
ln("<sch:title>"+s.title+"</sch:title>");
for (Rule r : s.rules) {
if (!r.asserts.isEmpty()) {
ln_i("<sch:rule context=\""+r.name+"\">");
for (Assert a : r.asserts)
ln("<sch:assert test=\""+Utilities.escapeXml(a.test)+"\">"+Utilities.escapeXml(a.message)+"</sch:assert>");
ln_o("</sch:rule>");
}
}
ln_o("</sch:pattern>");
}
ln_o("</sch:schema>");
flush();
close();
}
private void addNote() throws IOException {
switch (type) {
case ALL_RESOURCES : addAllResourcesNote(); break;
case RESOURCE : addResourceNote(); break;
case PROFILE : addProfileNote(); break;
}
}
private void addAllResourcesNote() throws IOException {
ln("<!-- ");
ln(" This file contains constraints for all resources");
ln(" Because of the way containment works, this file should always )");
ln(" be used for validating resources. Alternatively you can use ");
ln(" the resource specific files to build a smaller version of");
ln(" this file (the contents are identical; only include those ");
ln(" resources relevant to your implementation).");
ln("-->");
}
private void addResourceNote() throws IOException {
ln("<!-- ");
ln(" This file contains just the constraints for the resource "+description);
ln(" It is provided for documentation purposes. When actually validating,");
ln(" always use fhir-invariants.sch (because of the way containment works)");
ln(" Alternatively you can use this file to build a smaller version of");
ln(" fhir-invariants.sch (the contents are identical; only include those ");
ln(" resources relevant to your implementation).");
ln("-->");
}
private void addProfileNote() throws IOException {
ln("<!-- ");
ln(" This file contains just the constraints for the profile "+description);
ln(" It includes the base constraints for the resource as well.");
ln(" Because of the way that schematrons and containment work, ");
ln(" you may need to use this schematron fragment to build a, ");
ln(" single schematron that validates contained resources (if you have any) ");
ln("-->");
}
}