use of org.hl7.fhir.definitions.model.SearchParameterDefn in project kindling by HL7.
the class ResourceParser method parseSearchParameter.
private void parseSearchParameter(ResourceDefn r, SearchParameter src) {
if (!src.hasName()) {
src.setName(src.getCode());
}
src.setVersion(version);
SearchParameterDefn sp = new SearchParameterDefn(src.getCode(), src.getDescription(), type(src.getType()), src.getXpathUsage(), StandardsStatus.fromCode(BuildExtensions.readStringExtension(src, "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status")));
r.getSearchParams().put(sp.getCode(), sp);
sp.setExpression(src.getExpression());
sp.setXPath(src.getXpath());
sp.setResource(src);
String s = BuildExtensions.readStringExtension(src, BuildExtensions.EXT_PATH);
if (!Utilities.noString(s)) {
for (String p : s.split("\\,")) {
String v = p.trim();
if (!Utilities.noString(v)) {
sp.getPaths().add(v);
}
}
}
for (SearchParameterComponentComponent comp : src.getComponent()) {
sp.getComposites().add(new CompositeDefinition(comp.getDefinition(), comp.getExpression()));
}
}
use of org.hl7.fhir.definitions.model.SearchParameterDefn in project kindling by HL7.
the class ProfileGenerator method makeSearchParam.
public SearchParameter makeSearchParam(StructureDefinition p, String id, String rn, SearchParameterDefn spd, ResourceDefn rd) throws Exception {
boolean shared;
boolean created = true;
SearchParameter sp;
if (definitions.getCommonSearchParameters().containsKey(rn + "::" + spd.getCode())) {
shared = true;
CommonSearchParameter csp = definitions.getCommonSearchParameters().get(rn + "::" + spd.getCode());
if (csp.getDefinition() == null) {
sp = new SearchParameter();
csp.setDefinition(sp);
sp.setId(csp.getId());
} else {
created = false;
sp = csp.getDefinition();
}
} else {
shared = false;
sp = new SearchParameter();
sp.setId(id.replace("[", "").replace("]", ""));
}
spd.setCommonId(sp.getId());
if (created) {
sp.setUrl("http://hl7.org/fhir/SearchParameter/" + sp.getId());
sp.setVersion(version.toCode());
if (context.getSearchParameter(sp.getUrl()) != null)
throw new Exception("Duplicated Search Parameter " + sp.getUrl());
context.cacheResource(sp);
spd.setResource(sp);
definitions.addNs(sp.getUrl(), "Search Parameter: " + sp.getName(), rn.toLowerCase() + ".html#search");
sp.setStatus(spd.getStandardsStatus() == StandardsStatus.NORMATIVE ? PublicationStatus.fromCode("active") : PublicationStatus.fromCode("draft"));
StandardsStatus sst = ToolingExtensions.getStandardsStatus(sp);
if (sst == null || (spd.getStandardsStatus() == null && spd.getStandardsStatus().isLowerThan(sst)))
ToolingExtensions.setStandardsStatus(sp, spd.getStandardsStatus(), spd.getNormativeVersion());
sp.setExperimental(p.getExperimental());
sp.setName(spd.getCode());
sp.setCode(spd.getCode());
sp.setDate(genDate.getTime());
sp.setPublisher(p.getPublisher());
for (ContactDetail tc : p.getContact()) {
ContactDetail t = sp.addContact();
if (tc.hasNameElement())
t.setNameElement(tc.getNameElement().copy());
for (ContactPoint ts : tc.getTelecom()) t.getTelecom().add(ts.copy());
}
if (!definitions.hasResource(p.getType()) && !p.getType().equals("Resource") && !p.getType().equals("DomainResource"))
throw new Exception("unknown resource type " + p.getType());
sp.setType(getSearchParamType(spd.getType()));
if (sp.getType() == SearchParamType.REFERENCE && spd.isHierarchy()) {
sp.addModifier(SearchParameter.SearchModifierCode.BELOW);
sp.addModifier(SearchParameter.SearchModifierCode.ABOVE);
}
if (shared) {
sp.setDescription("Multiple Resources: \r\n\r\n* [" + rn + "](" + rn.toLowerCase() + ".html): " + spd.getDescription() + "\r\n");
} else
sp.setDescription(preProcessMarkdown(spd.getDescription(), "Search Description"));
if (!Utilities.noString(spd.getExpression()))
sp.setExpression(spd.getExpression());
// addModifiers(sp);
addComparators(sp);
String xpath = Utilities.noString(spd.getXPath()) ? new XPathQueryGenerator(this.definitions, null, null).generateXpath(spd.getPaths(), rn) : spd.getXPath();
if (xpath != null) {
if (xpath.contains("[x]"))
xpath = convertToXpath(xpath);
sp.setXpath(xpath);
sp.setXpathUsage(spd.getxPathUsage());
}
if (sp.getType() == SearchParamType.COMPOSITE) {
for (CompositeDefinition cs : spd.getComposites()) {
SearchParameterDefn cspd = findSearchParameter(rd, cs.getDefinition());
if (cspd != null)
sp.addComponent().setExpression(cs.getExpression()).setDefinition(cspd.getUrl());
else
sp.addComponent().setExpression(cs.getExpression()).setDefinition("http://hl7.org/fhir/SearchParameter/" + rn + "-" + cs.getDefinition());
}
sp.setMultipleOr(false);
}
sp.addBase(p.getType());
} else {
if (sp.getType() != getSearchParamType(spd.getType()))
throw new FHIRException("Type mismatch on common parameter: expected " + sp.getType().toCode() + " but found " + getSearchParamType(spd.getType()).toCode());
if (!sp.getDescription().contains("[" + rn + "](" + rn.toLowerCase() + ".html)"))
sp.setDescription(sp.getDescription() + "* [" + rn + "](" + rn.toLowerCase() + ".html): " + spd.getDescription() + "\r\n");
// ext.addExtension("description", new MarkdownType(spd.getDescription()));
if (!Utilities.noString(spd.getExpression()) && !sp.getExpression().contains(spd.getExpression()))
sp.setExpression(sp.getExpression() + " | " + spd.getExpression());
String xpath = new XPathQueryGenerator(this.definitions, null, null).generateXpath(spd.getPaths(), rn);
if (xpath != null) {
if (xpath.contains("[x]"))
xpath = convertToXpath(xpath);
if (sp.getXpath() != null && !sp.getXpath().contains(xpath))
sp.setXpath(sp.getXpath() + " | " + xpath);
if (sp.getXpathUsage() != spd.getxPathUsage())
throw new FHIRException("Usage mismatch on common parameter: expected " + sp.getXpathUsage().toCode() + " but found " + spd.getxPathUsage().toCode());
}
boolean found = false;
for (CodeType ct : sp.getBase()) found = found || p.getType().equals(ct.asStringValue());
if (!found)
sp.addBase(p.getType());
}
spd.setUrl(sp.getUrl());
for (String target : spd.getWorkingTargets()) {
if ("Any".equals(target) == true) {
for (String resourceName : definitions.sortedResourceNames()) {
boolean found = false;
for (CodeType st : sp.getTarget()) found = found || st.asStringValue().equals(resourceName);
if (!found)
sp.addTarget(resourceName);
}
} else {
boolean found = false;
for (CodeType st : sp.getTarget()) found = found || st.asStringValue().equals(target);
if (!found)
sp.addTarget(target);
}
}
return sp;
}
use of org.hl7.fhir.definitions.model.SearchParameterDefn in project org.hl7.fhir.core by hapifhir.
the class JavaResourceGenerator method generate.
// public void generate(ElementDefinition root, String name, JavaGenClass clss, ProfiledType cd, Date genDate, String version, boolean isAbstract, Map<String, SearchParameterDefn> nameToSearchParamDef, ElementDefinition template) throws Exception {
public void generate(Analysis analysis) throws Exception {
if (analysis.getStructure().getKind() == StructureDefinitionKind.RESOURCE) {
clss = JavaGenClass.Resource;
} else {
clss = JavaGenClass.Type;
}
write("package org.hl7.fhir." + jid + ".model;\r\n");
startMark(version, genDate);
// hasList(root);
boolean hl = true;
boolean hh = hasXhtml(analysis.getStructure().getSnapshot().getElement());
boolean hd = hasDecimal(analysis.getStructure().getSnapshot().getElement());
boolean hs = hasString(analysis.getStructure().getSnapshot().getElement());
boolean he = hasSharedEnums(analysis.getStructure().getSnapshot().getElement());
boolean hn = hasNestedTypes(analysis.getStructure().getSnapshot().getElement());
if (hl || hh || hd || he) {
if (hl) {
write("import java.util.ArrayList;\r\n");
write("import java.util.Date;\r\n");
write("import java.util.List;\r\n");
} else {
write("import java.util.Date;\r\n");
}
if (hh) {
write("import org.hl7.fhir.utilities.xhtml.NodeType;\r\n");
write("import org.hl7.fhir.utilities.xhtml.XhtmlNode;\r\n");
}
if (hd)
write("import java.math.*;\r\n");
if (hs)
write("import org.hl7.fhir.utilities.Utilities;\r\n");
if (he)
write("import org.hl7.fhir." + jid + ".model.Enumerations.*;\r\n");
}
if (hn) {
if (clss == JavaGenClass.Resource) {
write("import org.hl7.fhir.instance.model.api.IBaseBackboneElement;\r\n");
} else {
write("import org.hl7.fhir.instance.model.api.IBaseDatatypeElement;\r\n");
}
}
write("import org.hl7.fhir.exceptions.FHIRException;\r\n");
write("import org.hl7.fhir.instance.model.api.ICompositeType;\r\n");
if (clss == JavaGenClass.Resource) {
write("import ca.uhn.fhir.model.api.annotation.ResourceDef;\r\n");
write("import ca.uhn.fhir.model.api.annotation.SearchParamDefinition;\r\n");
}
if (clss == JavaGenClass.Resource || "BackboneElement".equals(analysis.getName()) || "BackboneType".equals(analysis.getName())) {
write("import org.hl7.fhir.instance.model.api.IBaseBackboneElement;\r\n");
}
write("import ca.uhn.fhir.model.api.annotation.Child;\r\n");
write("import ca.uhn.fhir.model.api.annotation.ChildOrder;\r\n");
if (clss != JavaGenClass.Resource) {
write("import ca.uhn.fhir.model.api.annotation.DatatypeDef;\r\n");
}
write("import ca.uhn.fhir.model.api.annotation.Description;\r\n");
write("import ca.uhn.fhir.model.api.annotation.Block;\r\n");
write("\r\n");
if (config.getIni().hasProperty("imports", analysis.getName())) {
for (String imp : config.getIni().getStringProperty("imports", analysis.getName()).split("\\,")) {
write("import " + imp.replace("{{jid}}", jid) + ";\r\n");
}
}
jdoc("", replaceTitle(analysis.getName(), analysis.getStructure().getDescription()));
TypeInfo ti = analysis.getRootType();
boolean hasChildren = ti.getChildren().size() > 0;
String superName = analysis.getAncestor() == null ? null : analysis.getAncestor().getName();
if (VersionUtilities.isR4BVer(version) && !Utilities.noString(config.getIni().getStringProperty("R4B.CanonicalResources", analysis.getName()))) {
superName = "CanonicalResource";
}
String hierarchy = analysis.getAncestor() != null ? "extends " + superName : "";
if (clss == JavaGenClass.Resource) {
if (!analysis.isAbstract()) {
write("@ResourceDef(name=\"" + upFirst(analysis.getName()).replace("ListResource", "List") + "\", profile=\"http://hl7.org/fhir/StructureDefinition/" + upFirst(analysis.getName()) + "\")\r\n");
}
} else {
write("@DatatypeDef(name=\"" + upFirst(analysis.getName()) + "\")\r\n");
hierarchy = hierarchy + " implements ICompositeType";
}
if (config.getIni().hasProperty("hierarchy", analysis.getName())) {
String h = config.getIni().getStringProperty("hierarchy", analysis.getName());
if (analysis.getAncestor() != null) {
h = h.replace("{{super}}", superName);
}
hierarchy = h;
}
write("public " + (analysis.isAbstract() ? "abstract " : "") + "class " + analysis.getClassName() + " " + hierarchy.trim() + " {\r\n");
write("\r\n");
for (String s : sorted(analysis.getEnums().keySet())) {
EnumInfo e = analysis.getEnums().get(s);
generateEnum(e);
}
for (TypeInfo t : analysis.getTypeList()) {
generateType(analysis, t);
}
allfields = "";
int i = 0;
for (ElementDefinition e : ti.getChildren()) {
if (!analysis.isInterface()) {
generateField(analysis, ti, e, " ", i++);
}
}
write(" private static final long serialVersionUID = " + Long.toString(allfields.hashCode()) + "L;\r\n\r\n");
hashSum = hashSum + allfields.hashCode();
List<ElementDefinition> mandatory = new ArrayList<ElementDefinition>();
generateConstructor(analysis.getClassName(), mandatory, " ");
if (hasChildren) {
for (ElementDefinition e : ti.getChildren()) {
if (e.getMin() > 0)
mandatory.add(e);
}
if (mandatory.size() > 0)
generateConstructor(analysis.getClassName(), mandatory, " ");
generateTypeSpecificConstructors(analysis.getClassName());
for (ElementDefinition e : ti.getChildren()) {
if (analysis.isInterface()) {
generateAbstractAccessors(analysis, ti, e, " ");
} else {
generateAccessors(analysis, ti, e, " ", matchingInheritedElement(ti.getInheritedChildren(), e, analysis.getName()));
}
}
if (!analysis.isInterface() && ti.getInheritedChildren() != null) {
for (ElementDefinition e : filterInherited(ti.getInheritedChildren(), ti.getChildren())) {
generateUnimplementedAccessors(analysis, ti, e, " ");
}
}
generateChildrenRegister(analysis, ti, " ");
generatePropertyGetterId(analysis, ti, " ");
generatePropertySetterId(analysis, ti, " ");
generatePropertySetterName(analysis, ti, " ");
generatePropertyMaker(analysis, ti, " ");
generatePropertyTypeGetter(analysis, ti, " ");
generateChildAdder(analysis, ti, " ");
}
generateFhirType(analysis.getName());
// // check for mappings
// for (String map : root.getMappings().keySet()) {
// if ("http://hl7.org/fhir/workflow".equals(map)) {
// String namenn = root.getMapping(map);
// if (patterns.containsKey(namenn)) {
// generateImpl(namenn, patterns.get(namenn), upFirst(name), root, version, genDate);
// }
// }
// }
generateCopy(analysis, ti, false);
if (hasChildren) {
generateEquals(analysis, ti, false);
generateIsEmpty(analysis, ti, false);
}
if (clss == JavaGenClass.Resource && !analysis.isAbstract()) {
write(" @Override\r\n");
write(" public ResourceType getResourceType() {\r\n");
write(" return ResourceType." + analysis.getName() + ";\r\n");
write(" }\r\n");
write("\r\n");
} else if (analysis.isAbstract() && analysis.getAncestor() != null && Utilities.noString(superName)) {
write("\r\n");
write(" @Override\r\n");
write(" public String getIdBase() {\r\n");
write(" return getId();\r\n");
write(" }\r\n");
write(" \r\n");
write(" @Override\r\n");
write(" public void setIdBase(String value) {\r\n");
write(" setId(value);\r\n");
write(" }\r\n");
write(" public abstract ResourceType getResourceType();\r\n");
} else if (analysis.isAbstract() && analysis.getAncestor() != null && Utilities.noString(superName)) {
write(" @Override\r\n");
write(" public String getIdBase() {\r\n");
write(" return getId();\r\n");
write(" }\r\n");
write(" \r\n");
write(" @Override\r\n");
write(" public void setIdBase(String value) {\r\n");
write(" setId(value);\r\n");
write(" }\r\n");
}
// Write resource fields which can be used as constants in client code
// to refer to standard search params
Set<String> spcodes = new HashSet<>();
for (SearchParameter sp : analysis.getSearchParams()) {
String code = sp.getCode();
if (!spcodes.contains(code)) {
spcodes.add(code);
/*
* For composite codes we want to find the two param this is a composite
* of. We generate search parameter constants which reference the
* component parts of the composite.
*/
if (sp.getType() == SearchParamType.COMPOSITE) {
if (code.endsWith("-[x]")) {
// partialCode will have "value" in this example
String partialCode = code.substring(0, code.length() - 4);
partialCode = partialCode.substring(partialCode.lastIndexOf('-') + 1);
// rootCode will have "component-code"
String rootCode = code.substring(0, code.indexOf("-" + partialCode));
/*
* If the composite has the form "foo-bar[x]" we expand this to create
* a constant for each of the possible [x] values, so that client have
* static binding to the individual possibilities. AFAIK this is only
* used right now in Observation (e.g. for code-value-[x])
*/
for (SearchParameter nextCandidate : analysis.getSearchParams()) {
if (nextCandidate.getCode().startsWith(partialCode)) {
String nextCompositeCode = rootCode + "-" + nextCandidate.getCode();
String[] compositeOf = new String[] { rootCode, nextCandidate.getCode() };
writeSearchParameterField(analysis.getName(), clss, analysis.isAbstract(), sp, nextCompositeCode, compositeOf, analysis.getSearchParams(), analysis.getName());
}
}
} else {
SearchParameter comp0 = definitions.getSearchParams().get(sp.getComponent().get(0).getDefinition());
SearchParameter comp1 = definitions.getSearchParams().get(sp.getComponent().get(1).getDefinition());
if (comp0 != null && comp1 != null) {
String[] compositeOf = new String[] { comp0.getCode(), comp1.getCode() };
writeSearchParameterField(analysis.getName(), clss, analysis.isAbstract(), sp, sp.getCode(), compositeOf, analysis.getSearchParams(), analysis.getName());
}
}
} else if (code.contains("[x]")) {
/*
* We only know how to handle search parameters with [x] in the name
* where it's a composite, and the [x] comes last. Are there other possibilities?
*/
throw new Exception("Unable to generate constant for search parameter: " + code);
} else {
writeSearchParameterField(analysis.getName(), clss, analysis.isAbstract(), sp, code, null, analysis.getSearchParams(), analysis.getName());
}
}
}
if (VersionUtilities.isR4BVer(version)) {
String extras = config.getIni().getStringProperty("R4B.NullImplementation", analysis.getName());
if (!Utilities.noString(extras)) {
for (String n : extras.split("\\,")) {
String t = n.substring(n.indexOf(":") + 1);
n = n.substring(0, n.indexOf(":"));
if (n.endsWith("[]")) {
n = Utilities.capitalize(n.substring(0, n.length() - 2));
write(" @Override\r\n");
write(" public List<" + t + "> get" + n + "() {\r\n");
write(" return new ArrayList<>();\r\n");
write(" }\r\n");
write(" \r\n");
write(" @Override\r\n");
write(" public CanonicalResource set" + n + "(List<" + t + "> the" + n + ") {\r\n");
write(" return this;\r\n");
write(" }\r\n");
write(" \r\n");
write(" @Override\r\n");
write(" public boolean has" + n + "() {\r\n");
write(" return false;\r\n");
write(" }\r\n");
write(" \r\n");
write(" @Override\r\n");
write(" public " + t + " add" + n + "() {\r\n");
write(" return null;\r\n");
write(" }\r\n");
write(" \r\n");
write(" @Override\r\n");
write(" public CanonicalResource add" + n + "(" + t + " t) {\r\n");
write(" return null;\r\n");
write(" }\r\n");
write(" \r\n");
write(" @Override\r\n");
write(" public " + t + " get" + n + "FirstRep() {\r\n");
write(" return new " + t + "();\r\n");
write(" }\r\n");
write(" \r\n");
} else if (t.contains("|")) {
n = Utilities.capitalize(n);
String t1 = t.substring(0, t.indexOf("|"));
String t2 = t.substring(t.indexOf("|") + 1);
write(" @Override\r\n");
write(" public " + t1 + " get" + n + "() {\r\n");
if ("boolean".equals(t1)) {
write(" return false;\r\n");
} else {
write(" return new " + t1 + "();\r\n");
}
write(" }\r\n");
write(" \r\n");
write(" @Override\r\n");
write(" public " + t2 + " get" + n + "Element() {\r\n");
write(" return new " + t2 + "();\r\n");
write(" }\r\n");
write(" \r\n");
write(" @Override\r\n");
write(" public CanonicalResource set" + n + "(" + t1 + " the" + n + ") {\r\n");
write(" return this;\r\n");
write(" }\r\n");
write(" \r\n");
write(" @Override\r\n");
write(" public CanonicalResource set" + n + "Element(" + t2 + " the" + n + ") {\r\n");
write(" return this;\r\n");
write(" }\r\n");
write(" \r\n");
write(" @Override\r\n");
write(" public boolean has" + n + "() {\r\n");
write(" return false;\r\n");
write(" }\r\n");
write(" \r\n");
write(" @Override\r\n");
write(" public boolean has" + n + "Element() {\r\n");
write(" return false;\r\n");
write(" }\r\n");
write(" \r\n");
write(" \r\n");
} else {
n = Utilities.capitalize(n);
write(" @Override\r\n");
write(" public " + t + " get" + n + "() {\r\n");
write(" return new " + t + "();\r\n");
write(" }\r\n");
write(" \r\n");
write(" @Override\r\n");
write(" public CanonicalResource set" + n + "(" + t + " the" + n + ") {\r\n");
write(" return this;\r\n");
write(" }\r\n");
write(" \r\n");
write(" @Override\r\n");
write(" public boolean has" + n + "() {\r\n");
write(" return false;\r\n");
write(" }\r\n");
write(" \r\n");
write(" @Override\r\n");
write(" public boolean has" + n + "Element() {\r\n");
write(" return false;\r\n");
write(" }\r\n");
write(" \r\n");
write(" \r\n");
}
}
}
}
if (config.getAdornments().containsKey(analysis.getClassName())) {
write("// Manual code (from Configuration.txt):\r\n");
write(config.getAdornments().get(analysis.getClassName()) + "\r\n");
write("// end addition\r\n");
}
write("\r\n");
write("}\r\n");
write("\r\n");
flush();
}
use of org.hl7.fhir.definitions.model.SearchParameterDefn in project kindling by HL7.
the class ResourceValidator method check.
public void check(List<ValidationMessage> errors, String name, ResourceDefn rd) throws Exception {
for (String s : rd.getHints()) hint(errors, IssueType.INFORMATIONAL, rd.getName(), false, s);
rule(errors, IssueType.STRUCTURE, rd.getName(), !name.equals("Metadata"), "The name 'Metadata' is not a legal name for a resource");
rule(errors, IssueType.STRUCTURE, rd.getName(), !name.equals("History"), "The name 'History' is not a legal name for a resource");
rule(errors, IssueType.STRUCTURE, rd.getName(), !name.equals("Tag"), "The name 'Tag' is not a legal name for a resource");
rule(errors, IssueType.STRUCTURE, rd.getName(), !name.equals("Tags"), "The name 'Tags' is not a legal name for a resource");
rule(errors, IssueType.STRUCTURE, rd.getName(), !name.equals("MailBox"), "The name 'MailBox' is not a legal name for a resource");
rule(errors, IssueType.STRUCTURE, rd.getName(), !name.equals("Validation"), "The name 'Validation' is not a legal name for a resource");
rule(errors, IssueType.REQUIRED, rd.getName(), name.equals("Parameters") || translations.hasTranslation(name), "The name '" + name + "' is not found in the file translations.xml");
rule(errors, IssueType.STRUCTURE, rd.getName(), name.length() > 1 && Character.isUpperCase(name.charAt(0)), "Resource Name must start with an uppercase alpha character");
rule(errors, IssueType.STRUCTURE, rd.getName(), !Utilities.noString(rd.getFmmLevel()), "Resource must have a maturity level");
// too many downstream issues in the parsers, and it would only happen as a transient thing when designing the resources
rule(errors, IssueType.REQUIRED, rd.getName(), rd.getRoot().getElements().size() > 0, "A resource must have at least one element in it before the build can proceed");
// too many downstream issues in the parsers, and it would only happen as a transient thing when designing the resources
rule(errors, IssueType.REQUIRED, rd.getName(), rd.getWg() != null, "A resource must have a designated owner");
rule(errors, IssueType.REQUIRED, rd.getName(), !Utilities.noString(rd.getRoot().getW5()), "A resource must have a W5 category");
rd.getRoot().setMinCardinality(0);
rd.getRoot().setMaxCardinality(Integer.MAX_VALUE);
// pattern related rules
buildW5Mappings(rd.getRoot(), true);
if ((isWorkflowPattern(rd, "Event") || isWorkflowPattern(rd, "Request")) && hasPatient(rd)) {
rule(errors, IssueType.STRUCTURE, rd.getName(), rd.getSearchParams().containsKey("patient"), "An 'event' or 'request' resource must have a search parameter 'patient'");
}
if (suppressedwarning(errors, IssueType.REQUIRED, rd.getName(), hasW5Mappings(rd) || rd.getName().equals("Binary") || rd.getName().equals("OperationOutcome") || rd.getName().equals("Parameters"), "A resource must have w5 mappings")) {
String w5Order = listW5Elements(rd);
String w5CorrectOrder = listW5Correct(rd);
if (!w5Order.equals(w5CorrectOrder)) {
warning(errors, IssueType.REQUIRED, rd.getName(), false, "Resource elements are out of order. The correct order is '" + w5CorrectOrder + "' but the actual order is '" + w5Order + "'");
// System.out.println("Resource "+parent.getName()+": elements are out of order. The correct order is '"+w5CorrectOrder+"' but the actual order is '"+w5Order+"'");
}
if (!Utilities.noString(rd.getProposedOrder())) {
w5Order = listW5Elements(rd, rd.getProposedOrder());
if (!w5Order.equals(w5CorrectOrder)) {
rule(errors, IssueType.REQUIRED, rd.getName(), false, "Proposed Resource elements are out of order. The correct order is '" + w5CorrectOrder + "' but the proposed order is '" + w5Order + "'");
} else
System.out.println("Proposed order for " + rd.getName() + ": build order ok");
}
}
if (Utilities.noString(rd.getEnteredInErrorStatus()))
if (hasStatus(rd, "entered-in-error"))
rd.setEnteredInErrorStatus(".status = entered-in-error");
else if (hasStatus(rd, "retired"))
rd.setEnteredInErrorStatus(".status = retired");
else if (hasActivFalse(rd))
rd.setEnteredInErrorStatus(".active = false");
else
// too many downstream issues in the parsers, and it would only happen as a transient thing when designing the resources
warning(errors, IssueType.REQUIRED, rd.getName(), false, "A resource must have an 'entered in error' status");
String s = rd.getRoot().getMapping(Definitions.RIM_MAPPING);
hint(errors, IssueType.REQUIRED, rd.getName(), !Utilities.noString(s), "RIM Mapping is required");
for (Operation op : rd.getOperations()) {
warning(errors, IssueType.BUSINESSRULE, rd.getName() + ".$" + op.getName(), hasOpExample(op.getExamples(), false), "Operation must have an example request");
warning(errors, IssueType.BUSINESSRULE, rd.getName() + ".$" + op.getName(), hasOpExample(op.getExamples(), true), "Operation must have an example response");
}
List<String> vsWarns = new ArrayList<String>();
int vsWarnings = checkElement(errors, rd.getName(), rd.getRoot(), rd, null, s == null || !s.equalsIgnoreCase("n/a"), false, hasSummary(rd.getRoot()), vsWarns, true, rd.getStatus());
if (!resourceIsTechnical(name)) {
// these are exempt because identification is tightly managed
ElementDefn id = rd.getRoot().getElementByName(definitions, "identifier", true, false);
if (id == null)
warning(errors, IssueType.STRUCTURE, rd.getName(), false, "All resources should have an identifier");
else
rule(errors, IssueType.STRUCTURE, rd.getName(), id.typeCode().equals("Identifier"), "If a resource has an element named identifier, it must have a type 'Identifier'");
}
rule(errors, IssueType.STRUCTURE, rd.getName(), rd.getRoot().getElementByName(definitions, "text", true, false) == null, "Element named \"text\" not allowed");
rule(errors, IssueType.STRUCTURE, rd.getName(), rd.getRoot().getElementByName(definitions, "contained", true, false) == null, "Element named \"contained\" not allowed");
if (rd.getRoot().getElementByName(definitions, "subject", true, false) != null && rd.getRoot().getElementByName(definitions, "subject", true, false).typeCode().startsWith("Reference"))
rule(errors, IssueType.STRUCTURE, rd.getName(), rd.getSearchParams().containsKey("subject"), "A resource that contains a subject reference must have a search parameter 'subject'");
ElementDefn ped = rd.getRoot().getElementByName(definitions, "patient", true, false);
if (ped != null && ped.typeCode().startsWith("Reference")) {
SearchParameterDefn spd = rd.getSearchParams().get("patient");
if (rule(errors, IssueType.STRUCTURE, rd.getName(), spd != null, "A resource that contains a patient reference must have a search parameter 'patient'"))
rule(errors, IssueType.STRUCTURE, rd.getName(), (spd.getTargets().size() == 1 && spd.getTargets().contains("Patient")) || (ped.getTypes().get(0).getParams().size() == 1 && ped.getTypes().get(0).getParams().get(0).equals("Patient")), "A Patient search parameter must only refer to patient");
}
ElementDefn sed = rd.getRoot().getElementByName(definitions, "subject", true, false);
if (sed != null && sed.typeCode().startsWith("Reference") && sed.typeCode().contains("Patient"))
warning(errors, IssueType.STRUCTURE, rd.getName(), rd.getSearchParams().containsKey("patient"), "A resource that contains a subject that can be a patient reference must have a search parameter 'patient'");
if (rd.getRoot().getElementByName(definitions, "identifier", true, false) != null) {
warning(errors, IssueType.STRUCTURE, rd.getName(), rd.getSearchParams().containsKey("identifier"), "A resource that contains an identifier must have a search parameter 'identifier'");
}
if (rd.getRoot().getElementByName(definitions, "status", true, false) != null) {
// todo: change to a warning post STU3
hint(errors, IssueType.STRUCTURE, rd.getName(), rd.getSearchParams().containsKey("status"), "A resource that contains a status element must have a search parameter 'status'");
}
if (rd.getRoot().getElementByName(definitions, "url", true, false) != null) {
warning(errors, IssueType.STRUCTURE, rd.getName(), rd.getSearchParams().containsKey("url"), "A resource that contains a url element must have a search parameter 'url'");
}
checkSearchParams(errors, rd);
for (Operation op : rd.getOperations()) {
rule(errors, IssueType.STRUCTURE, rd.getName() + "/$" + op.getName(), !parentHasOp(rd.getRoot().typeCode(), op.getName()), "Duplicate Operation Name $" + op.getName() + " on " + rd.getName());
}
for (Compartment c : definitions.getCompartments()) {
if (rule(errors, IssueType.STRUCTURE, rd.getName(), name.equals("Parameters") || c.getResources().containsKey(rd), "Resource not entered in resource map for compartment '" + c.getTitle() + "' (compartments.xml)")) {
String param = c.getResources().get(rd);
if (!Utilities.noString(param)) {
// rule(errors, IssueType.STRUCTURE, parent.getName(), param.equals("{def}") || parent.getSearchParams().containsKey(c.getName()), "Resource "+parent.getName()+" in compartment " +c.getName()+" must have a search parameter named "+c.getName().toLowerCase()+")");
for (String p : param.split("\\|")) {
String pn = p.trim();
if (pn.contains("."))
pn = pn.substring(0, pn.indexOf("."));
rule(errors, IssueType.STRUCTURE, rd.getName(), Utilities.noString(pn) || pn.equals("{def}") || rd.getSearchParams().containsKey(pn), "Resource " + rd.getName() + " in compartment " + c.getName() + ": parameter " + param + " was not found (" + pn + ")");
}
}
}
}
// Remove suppressed messages
List<ValidationMessage> suppressed = new ArrayList<ValidationMessage>();
for (ValidationMessage em : errors) {
if (isSuppressedMessage(em.getDisplay())) {
suppressed.add(em);
}
}
errors.removeAll(suppressed);
// last check: if maturity level is
int warnings = 0;
int hints = 0;
for (ValidationMessage em : errors) {
if (em.getLevel() == IssueSeverity.WARNING)
warnings++;
else if (em.getLevel() == IssueSeverity.INFORMATION)
hints++;
}
boolean ok = warnings == 0 || "0".equals(rd.getFmmLevel());
if (rule(errors, IssueType.STRUCTURE, rd.getName(), ok, "Resource " + rd.getName() + " (FMM=" + rd.getFmmLevel() + ") cannot have an FMM level >1 (" + rd.getFmmLevel() + ") if it has warnings"))
rule(errors, IssueType.STRUCTURE, rd.getName(), vsWarnings == 0 || "0".equals(rd.getFmmLevel()), "Resource " + rd.getName() + " (FMM=" + rd.getFmmLevel() + ") cannot have an FMM level >1 (" + rd.getFmmLevel() + ") if it has linked value set warnings (" + vsWarns.toString() + ")");
ok = hints == 0 || Integer.parseInt(rd.getFmmLevel()) < 3;
rule(errors, IssueType.STRUCTURE, rd.getName(), ok, "Resource " + rd.getName() + " (FMM=" + rd.getFmmLevel() + ") cannot have an FMM level >2 (" + rd.getFmmLevel() + ") if it has informational hints");
// if (isInterface(rd.getRoot().typeCode())) {
// checkInterface(errors, rd, definitions.getBaseResources().get(rd.getRoot().typeCode()));
// }
}
use of org.hl7.fhir.definitions.model.SearchParameterDefn in project kindling by HL7.
the class ProfileGenerator method generate.
public StructureDefinition generate(Profile pack, ResourceDefn r, String usage, boolean logical) throws Exception {
StructureDefinition p = new StructureDefinition();
p.setId(r.getRoot().getName());
p.setUrl("http://hl7.org/fhir/StructureDefinition/" + r.getRoot().getName());
if (logical)
p.setKind(StructureDefinitionKind.LOGICAL);
else
p.setKind(StructureDefinitionKind.RESOURCE);
if (r.isInterface()) {
ToolingExtensions.addBooleanExtension(p, ToolingExtensions.EXT_RESOURCE_INTERFACE, true);
}
IniFile cini = new IniFile(Utilities.path(rootFolder, "temp", "categories.ini"));
String cat = cini.getStringProperty("category", r.getName());
if (!Utilities.noString(cat))
ToolingExtensions.setStringExtension(p, ToolingExtensions.EXT_RESOURCE_CATEGORY, cat);
p.setAbstract(r.isAbstract());
assert !Utilities.noString(r.getRoot().typeCode());
if (!Utilities.noString(r.getRoot().typeCode())) {
p.setBaseDefinition("http://hl7.org/fhir/StructureDefinition/" + r.getRoot().typeCode());
p.setDerivation(TypeDerivationRule.SPECIALIZATION);
// if (r.getTemplate() != null)
// ToolingExtensions.addStringExtension(p.getBaseDefinitionElement(), ToolingExtensions.EXT_CODE_GENERATION_PARENT, r.getTemplate().getName());
}
p.setType(r.getRoot().getName());
p.setUserData("filename", r.getName().toLowerCase());
p.setUserData("path", r.getName().toLowerCase() + ".html");
p.setTitle(pack.metadata("display"));
p.setFhirVersion(version);
p.setVersion(version.toCode());
ToolingExtensions.setStandardsStatus(p, r.getStatus(), r.getNormativeVersion());
if (r.getFmmLevel() != null)
ToolingExtensions.addIntegerExtension(p, ToolingExtensions.EXT_FMM_LEVEL, Integer.parseInt(r.getFmmLevel()));
if (r.getSecurityCategorization() != null)
ToolingExtensions.addCodeExtension(p, ToolingExtensions.EXT_SEC_CAT, r.getSecurityCategorization().toCode());
ToolResourceUtilities.updateUsage(p, usage);
p.setName(r.getRoot().getName());
p.setPublisher("Health Level Seven International" + (r.getWg() == null ? "" : " (" + r.getWg().getName() + ")"));
p.addContact().getTelecom().add(Factory.newContactPoint(ContactPointSystem.URL, "http://hl7.org/fhir"));
if (r.getWg() != null)
p.addContact().getTelecom().add(Factory.newContactPoint(ContactPointSystem.URL, r.getWg().getUrl()));
ToolingExtensions.setCodeExtension(p, ToolingExtensions.EXT_WORKGROUP, r.getWg().getCode());
p.setDescription(r.getDefinition());
p.setPurpose(r.getRoot().getRequirements());
if (!p.hasPurpose())
p.setPurpose(r.getRoot().getRequirements());
p.setDate(genDate.getTime());
// DSTU
p.setStatus(r.getStatus() == StandardsStatus.NORMATIVE ? PublicationStatus.fromCode("active") : PublicationStatus.fromCode("draft"));
Set<String> containedSlices = new HashSet<String>();
// first, the differential
p.setDifferential(new StructureDefinitionDifferentialComponent());
defineElement(null, p, p.getDifferential().getElement(), r.getRoot(), r.getRoot().getName(), containedSlices, new ArrayList<ProfileGenerator.SliceHandle>(), SnapShotMode.None, true, "BackboneElement", r.getRoot().typeCode(), false);
reset();
// now. the snapshot'
p.setSnapshot(new StructureDefinitionSnapshotComponent());
defineElement(null, p, p.getSnapshot().getElement(), r.getRoot(), r.getRoot().getName(), containedSlices, new ArrayList<ProfileGenerator.SliceHandle>(), SnapShotMode.Resource, true, "BackboneElement", r.getRoot().typeCode(), true);
for (ElementDefinition ed : p.getSnapshot().getElement()) if (!ed.hasBase() && !logical)
generateElementDefinition(p, ed, getParent(ed, p.getSnapshot().getElement()));
if (!logical && !r.isInterface()) {
List<String> names = new ArrayList<String>();
names.addAll(r.getSearchParams().keySet());
Collections.sort(names);
// 1st, non composites
for (String pn : names) {
SearchParameterDefn sp = r.getSearchParams().get(pn);
if (sp.getType() != SearchType.composite)
pack.getSearchParameters().add(makeSearchParam(p, r.getName() + "-" + pn.replace("_", ""), r.getName(), sp, r));
}
for (String pn : names) {
SearchParameterDefn sp = r.getSearchParams().get(pn);
if (sp.getType() == SearchType.composite)
pack.getSearchParameters().add(makeSearchParam(p, r.getName() + "-" + pn.replace("_", ""), r.getName(), sp, r));
}
}
containedSlices.clear();
addElementConstraintToSnapshot(p);
p.getDifferential().getElement().get(0).getType().clear();
p.getSnapshot().getElement().get(0).getType().clear();
XhtmlNode div = new XhtmlNode(NodeType.Element, "div");
div.addText("to do");
p.setText(new Narrative());
p.getText().setStatus(NarrativeStatus.GENERATED);
p.getText().setDiv(div);
checkHasTypes(p);
return p;
}
Aggregations