
org.hl7.fhir.validation.instance.utils.NodeStack Maven / Gradle / Ivy
The newest version!
package org.hl7.fhir.validation.instance.utils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.utilities.Utilities;
public class NodeStack {
protected IWorkerContext context;
private ElementDefinition definition;
private Element element;
private ElementDefinition extension;
private String literalPath; // xpath format
private Set logicalPaths; // dotted format, various entry points
private NodeStack parent;
private ElementDefinition type;
private String workingLang;
private Map ids;
private boolean resetPoint = false;
private boolean contained = false;
public NodeStack(IWorkerContext context) {
this.context = context;
}
public NodeStack(IWorkerContext context, String initialPath, Element element, String validationLanguage) {
this.context = context;
ids = new HashMap<>();
this.element = element;
literalPath = (initialPath == null ? "" : initialPath+".") + buildPathForElement(element, true);
workingLang = validationLanguage;
if (!element.getName().equals(element.fhirType())) {
logicalPaths = new HashSet<>();
logicalPaths.add(element.fhirType());
}
}
private String buildPathForElement(Element e, boolean first) {
if (e.getParentForValidator() != null) {
String node = e.getName().contains("/") ? e.getName().substring(e.getName().lastIndexOf("/")+1) : e.getName();
if (e.hasIndex() && e.getProperty().isList() && e.getSpecial() == null) {
node = node+"["+Integer.toString(e.getIndex())+"]";
}
if (!first && e.isResource()) {
node = node +"/*"+e.fhirType()+"/"+e.getIdBase()+"*/";
}
return buildPathForElement(e.getParentForValidator(), false)+"."+node;
} else {
return e.getPath();
}
}
public NodeStack(IWorkerContext context, Element element, String refPath, String validationLanguage) {
this.context = context;
ids = new HashMap<>();
this.element = element;
int i = element.getName().indexOf(".");
if (i == -1) {
literalPath = refPath+".resolve().ofType(" + element.getName()+")";
} else {
literalPath = refPath+".resolve().ofType(" + element.getName().substring(0, i)+")"+element.getName().substring(i);
}
workingLang = validationLanguage;
}
public String addToLiteralPath(String... path) {
StringBuilder b = new StringBuilder();
b.append(getLiteralPath());
for (String p : path) {
if (p.startsWith(":")) {
b.append("[");
b.append(p.substring(1));
b.append("]");
} else {
b.append(".");
b.append(p);
}
}
return b.toString();
}
private ElementDefinition getDefinition() {
return definition;
}
public Element getElement() {
return element;
}
public String getLiteralPath() {
return literalPath == null ? "" : literalPath;
}
public Set getLogicalPaths() {
return logicalPaths == null ? new HashSet() : logicalPaths;
}
private ElementDefinition getType() {
return type;
}
public NodeStack pushTarget(Element element, int count, ElementDefinition definition, ElementDefinition type) {
return pushInternal(element, count, definition, type, "->");
}
public NodeStack push(Element element, int count, ElementDefinition definition, ElementDefinition type) {
return pushInternal(element, count, definition, type, ".");
}
private NodeStack pushInternal(Element element, int count, ElementDefinition definition, ElementDefinition type, String sep) {
if (definition == null & element.getProperty() != null) {
definition = element.getProperty().getDefinition();
}
NodeStack res = new NodeStack(context);
res.ids = ids;
res.parent = this;
res.workingLang = this.workingLang;
res.element = element;
res.definition = definition;
res.contained = contained;
res.literalPath = getLiteralPath() + sep + element.getName();
if (count > -1)
res.literalPath = res.literalPath + "[" + Integer.toString(count) + "]";
else if (element.getSpecial() == null && element.getProperty().isList())
res.literalPath = res.literalPath + "[0]";
else if (element.getProperty().isChoice()) {
String n = res.literalPath.substring(res.literalPath.lastIndexOf(".") + 1);
String en = element.getProperty().getName();
if (en.endsWith("[x]")) {
en = en.substring(0, en.length() - 3);
String t = n.substring(en.length());
if (context.isPrimitiveType(Utilities.uncapitalize(t)))
t = Utilities.uncapitalize(t);
res.literalPath = res.literalPath.substring(0, res.literalPath.lastIndexOf(".")) + "." + en + ".ofType(" + t + ")";
} else {
res.literalPath = res.literalPath.substring(0, res.literalPath.lastIndexOf(".")) + "." + en;;
}
}
res.logicalPaths = new HashSet();
if (type != null) {
// type will be null if we on a stitching point of a contained resource, or if....
res.type = type;
String tn = res.type.getPath();
String t = tail(definition.getPath());
if ("Resource".equals(tn)) {
tn = element.fhirType();
}
for (String lp : getLogicalPaths()) {
if (isRealPath(lp, t)) {
res.logicalPaths.add(lp + "." + t);
if (t.endsWith("[x]")) {
res.logicalPaths.add(lp + "." + t.substring(0, t.length() - 3) + ".ofType("+type.getPath()+")");
res.logicalPaths.add(lp + "." + t.substring(0, t.length() - 3) + type.getPath());
}
}
}
res.logicalPaths.add(tn);
} else if (definition != null) {
for (String lp : getLogicalPaths()) {
if (isRealPath(lp, element.getName())) {
res.logicalPaths.add(lp + "." + element.getName());
}
}
if (definition.hasContentReference()) {
res.logicalPaths.add(definition.getContentReference().substring(definition.getContentReference().indexOf("#")+1));
} else {
res.logicalPaths.addAll(definition.typeList());
}
} else {
res.logicalPaths.addAll(getLogicalPaths());
}
return res;
}
private boolean isRealPath(String lp, String t) {
if (Utilities.existsInList(lp, "Element")) {
return Utilities.existsInList(t, "id", "extension");
}
if (Utilities.existsInList(lp, "BackboneElement", "BackboneType")) {
return Utilities.existsInList(t, "modifierExtension");
}
if (Utilities.existsInList(lp, "Resource")) {
return Utilities.existsInList(t, "id", "meta", "implicitRules", "language");
}
if (Utilities.existsInList(lp, "DomainResource")) {
return Utilities.existsInList(t, "text", "contained", "extension", "modifierExtension");
}
return true;
}
private void setType(ElementDefinition type) {
this.type = type;
}
public NodeStack resetIds() {
ids = new HashMap<>();
resetPoint = true;
return this;
}
public Map getIds() {
return ids;
}
private String tail(String path) {
return path.substring(path.lastIndexOf(".") + 1);
}
public String getWorkingLang() {
return workingLang;
}
public void setWorkingLang(String workingLang) {
this.workingLang = workingLang;
}
public NodeStack getParent() {
return parent;
}
public void pathComment(String comment) {
literalPath = literalPath + "/*"+comment+"*/";
}
public boolean isResetPoint() {
return resetPoint;
}
@Override
public String toString() {
return literalPath;
}
public int depth() {
if (parent == null) {
return 0;
} else {
return parent.depth()+1;
}
}
public boolean isContained() {
return contained;
}
public void setContained(boolean contained) {
this.contained = contained;
}
public int line() {
return element.line();
}
public int col() {
return element.col();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy