Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package org.hl7.fhir.dstu3.elementmodel;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.dstu3.elementmodel.Element.ElementSortComparator;
import org.hl7.fhir.dstu3.model.Base;
import org.hl7.fhir.dstu3.model.ElementDefinition;
import org.hl7.fhir.dstu3.model.ElementDefinition.TypeRefComponent;
import org.hl7.fhir.dstu3.model.StringType;
import org.hl7.fhir.dstu3.model.StructureDefinition;
import org.hl7.fhir.dstu3.model.Type;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
/**
* This class represents the underlying reference model of FHIR
*
* A resource is nothing but a set of elements, where every element has a
* name, maybe a stated type, maybe an id, and either a value or child elements
* (one or the other, but not both or neither)
*
* @author Grahame Grieve
*
*/
public class Element extends Base {
public enum SpecialElement {
CONTAINED, BUNDLE_ENTRY, BUNDLE_OUTCOME, PARAMETER;
public static SpecialElement fromProperty(Property property) {
if (property.getStructure().getIdElement().getIdPart().equals("Parameters"))
return PARAMETER;
if (property.getStructure().getIdElement().getIdPart().equals("Bundle") && property.getName().equals("resource"))
return BUNDLE_ENTRY;
if (property.getStructure().getIdElement().getIdPart().equals("Bundle") && property.getName().equals("outcome"))
return BUNDLE_OUTCOME;
if (property.getName().equals("contained"))
return CONTAINED;
throw new Error("Unknown resource containing a native resource: "+property.getDefinition().getId());
}
}
private List comments;// not relevant for production, but useful in documentation
private String name;
private String type;
private String value;
private int index = -1;
private List children;
private Property property;
private Property elementProperty; // this is used when special is set to true - it tracks the underlying element property which is used in a few places
private int line;
private int col;
private SpecialElement special;
private XhtmlNode xhtml; // if this is populated, then value will also hold the string representation
public Element(String name) {
super();
this.name = name;
}
public Element(Element other) {
super();
name = other.name;
type = other.type;
property = other.property;
elementProperty = other.elementProperty;
special = other.special;
}
public Element(String name, Property property) {
super();
this.name = name;
this.property = property;
}
public Element(String name, Property property, String type, String value) {
super();
this.name = name;
this.property = property;
this.type = type;
this.value = value;
}
public void updateProperty(Property property, SpecialElement special, Property elementProperty) {
this.property = property;
this.elementProperty = elementProperty;
this.special = special;
}
public SpecialElement getSpecial() {
return special;
}
public String getName() {
return name;
}
public String getType() {
if (type == null)
return property.getType(name);
else
return type;
}
public String getValue() {
return value;
}
public boolean hasChildren() {
return !(children == null || children.isEmpty());
}
public List getChildren() {
if (children == null)
children = new ArrayList();
return children;
}
public boolean hasComments() {
return !(comments == null || comments.isEmpty());
}
public List getComments() {
if (comments == null)
comments = new ArrayList();
return comments;
}
public Property getProperty() {
return property;
}
public void setValue(String value) {
this.value = value;
}
public void setType(String type) {
this.type = type;
}
public boolean hasValue() {
return value != null;
}
public List getChildrenByName(String name) {
List res = new ArrayList();
if (hasChildren()) {
for (Element child : children)
if (name.equals(child.getName()))
res.add(child);
}
return res;
}
public void numberChildren() {
if (children == null)
return;
String last = "";
int index = 0;
for (Element child : children) {
if (child.getProperty().isList()) {
if (last.equals(child.getName())) {
index++;
} else {
last = child.getName();
index = 0;
}
child.index = index;
} else {
child.index = -1;
}
child.numberChildren();
}
}
public int getIndex() {
return index;
}
public boolean hasIndex() {
return index > -1;
}
public void setIndex(int index) {
this.index = index;
}
public String getChildValue(String name) {
if (children == null)
return null;
for (Element child : children) {
if (name.equals(child.getName()))
return child.getValue();
}
return null;
}
public void setChildValue(String name, String value) {
if (children == null)
children = new ArrayList();
for (Element child : children) {
if (name.equals(child.getName())) {
if (!child.isPrimitive())
throw new Error("Cannot set a value of a non-primitive type ("+name+" on "+this.getName()+")");
child.setValue(value);
}
}
try {
setProperty(name.hashCode(), name, new StringType(value));
} catch (FHIRException e) {
throw new Error(e);
}
}
public List getChildren(String name) {
List res = new ArrayList();
if (children != null)
for (Element child : children) {
if (name.equals(child.getName()))
res.add(child);
}
return res;
}
public boolean hasType() {
if (type == null)
return property.hasType(name);
else
return true;
}
@Override
public String fhirType() {
return getType();
}
@Override
public Base[] getProperty(int hash, String name, boolean checkValid) throws FHIRException {
if (isPrimitive() && (hash == "value".hashCode()) && !Utilities.noString(value)) {
// String tn = getType();
// throw new Error(tn+" not done yet");
Base[] b = new Base[1];
b[0] = new StringType(value);
return b;
}
List result = new ArrayList();
if (children != null) {
for (Element child : children) {
if (child.getName().equals(name))
result.add(child);
if (child.getName().startsWith(name) && child.getProperty().isChoice() && child.getProperty().getName().equals(name+"[x]"))
result.add(child);
}
}
if (result.isEmpty() && checkValid) {
// throw new FHIRException("not determined yet");
}
return result.toArray(new Base[result.size()]);
}
@Override
protected void listChildren(List childProps) {
if (children != null) {
for (Element c : children) {
childProps.add(new org.hl7.fhir.dstu3.model.Property(c.getName(), c.fhirType(), c.getProperty().getDefinition().getDefinition(), c.getProperty().getDefinition().getMin(), maxToInt(c.getProperty().getDefinition().getMax()), c));
}
}
}
@Override
public Base setProperty(int hash, String name, Base value) throws FHIRException {
if (isPrimitive() && (hash == "value".hashCode())) {
this.value = castToString(value).asStringValue();
return this;
}
if ("xhtml".equals(getType()) && (hash == "value".hashCode())) {
this.xhtml = castToXhtml(value);
this.value = castToXhtmlString(value);
return this;
}
if (!value.isPrimitive() && !(value instanceof Element)) {
if (isDataType(value))
value = convertToElement(property.getChild(name), value);
else
throw new FHIRException("Cannot set property "+name+" on "+this.name+" - value is not a primitive type ("+value.fhirType()+") or an ElementModel type");
}
if (children == null)
children = new ArrayList();
Element childForValue = null;
// look through existing children
for (Element child : children) {
if (child.getName().equals(name)) {
if (!child.isList()) {
childForValue = child;
break;
} else {
Element ne = new Element(child);
children.add(ne);
numberChildren();
childForValue = ne;
break;
}
}
}
if (childForValue == null)
for (Property p : property.getChildProperties(this.name, type)) {
if (p.getName().equals(name) || p.getName().equals(name+"[x]")) {
Element ne = new Element(name, p);
children.add(ne);
childForValue = ne;
break;
}
}
if (childForValue == null)
throw new Error("Cannot set property "+name+" on "+this.name);
else if (value.isPrimitive()) {
if (childForValue.property.getName().endsWith("[x]"))
childForValue.name = name+Utilities.capitalize(value.fhirType());
childForValue.setValue(value.primitiveValue());
} else {
Element ve = (Element) value;
childForValue.type = ve.getType();
if (childForValue.property.getName().endsWith("[x]"))
childForValue.name = name+Utilities.capitalize(childForValue.type);
else if (value.isResource()) {
if (childForValue.elementProperty == null)
childForValue.elementProperty = childForValue.property;
childForValue.property = ve.property;
childForValue.special = SpecialElement.BUNDLE_ENTRY;
}
if (ve.children != null) {
if (childForValue.children == null)
childForValue.children = new ArrayList();
else
childForValue.children.clear();
childForValue.children.addAll(ve.children);
}
}
return childForValue;
}
private Base convertToElement(Property prop, Base v) throws FHIRException {
return new ObjectConverter(property.getContext()).convert(prop, (Type) v);
}
private boolean isDataType(Base v) {
return v instanceof Type && property.getContext().getTypeNames().contains(v.fhirType());
}
@Override
public Base makeProperty(int hash, String name) throws FHIRException {
if (isPrimitive() && (hash == "value".hashCode())) {
return new StringType(value);
}
if (children == null)
children = new ArrayList();
// look through existing children
for (Element child : children) {
if (child.getName().equals(name)) {
if (!child.isList()) {
return child;
} else {
Element ne = new Element(child);
children.add(ne);
numberChildren();
return ne;
}
}
}
for (Property p : property.getChildProperties(this.name, type)) {
if (p.getName().equals(name)) {
Element ne = new Element(name, p);
children.add(ne);
return ne;
}
}
throw new Error("Unrecognised name "+name+" on "+this.name);
}
private int maxToInt(String max) {
if (max.equals("*"))
return Integer.MAX_VALUE;
else
return Integer.parseInt(max);
}
@Override
public boolean isPrimitive() {
return type != null ? property.isPrimitive(type) : property.isPrimitive(property.getType(name));
}
@Override
public boolean isResource() {
return property.isResource();
}
@Override
public boolean hasPrimitiveValue() {
return property.isPrimitiveName(name) || property.IsLogicalAndHasPrimitiveValue(name);
}
@Override
public String primitiveValue() {
if (isPrimitive())
return value;
else {
if (hasPrimitiveValue() && children != null) {
for (Element c : children) {
if (c.getName().equals("value"))
return c.primitiveValue();
}
}
return null;
}
}
// for the validator
public int line() {
return line;
}
public int col() {
return col;
}
public Element markLocation(int line, int col) {
this.line = line;
this.col = col;
return this;
}
public void markValidation(StructureDefinition profile, ElementDefinition definition) {
}
public Element getNamedChild(String name) {
if (children == null)
return null;
Element result = null;
for (Element child : children) {
if (child.getName().equals(name)) {
if (result == null)
result = child;
else
throw new Error("Attempt to read a single element when there is more than one present ("+name+")");
}
}
return result;
}
public void getNamedChildren(String name, List list) {
if (children != null)
for (Element child : children)
if (child.getName().equals(name))
list.add(child);
}
public String getNamedChildValue(String name) {
Element child = getNamedChild(name);
return child == null ? null : child.value;
}
public void getNamedChildrenWithWildcard(String string, List values) {
Validate.isTrue(string.endsWith("[x]"));
String start = string.substring(0, string.length() - 3);
if (children != null) {
for (Element child : children) {
if (child.getName().startsWith(start)) {
values.add(child);
}
}
}
}
public XhtmlNode getXhtml() {
return xhtml;
}
public Element setXhtml(XhtmlNode xhtml) {
this.xhtml = xhtml;
return this;
}
@Override
public boolean isEmpty() {
if (isNotBlank(value)) {
return false;
}
for (Element next : getChildren()) {
if (!next.isEmpty()) {
return false;
}
}
return true;
}
public Property getElementProperty() {
return elementProperty;
}
public boolean hasElementProperty() {
return elementProperty != null;
}
public boolean hasChild(String name) {
return getNamedChild(name) != null;
}
@Override
public String toString() {
return name+"="+fhirType() + "["+(children == null || hasValue() ? value : Integer.toString(children.size())+" children")+"]";
}
@Override
public String getIdBase() {
return getChildValue("id");
}
@Override
public void setIdBase(String value) {
setChildValue("id", value);
}
// @Override
// public boolean equalsDeep(Base other) {
// if (!super.equalsDeep(other))
// return false;
//
// }
//
// @Override
// public boolean equalsShallow(Base other) {
// if (!super.equalsShallow(other))
// return false;
// }
public Type asType() throws FHIRException {
return new ObjectConverter(property.getContext()).convertToType(this);
}
@Override
public boolean isMetadataBased() {
return true;
}
public boolean isList() {
if (elementProperty != null)
return elementProperty.isList();
else
return property.isList();
}
@Override
public String[] getTypesForProperty(int hash, String name) throws FHIRException {
Property p = property.getChildSimpleName(this.name, name);
if (p != null) {
Set types = new HashSet();
for (TypeRefComponent tr : p.getDefinition().getType()) {
types.add(tr.getCode());
}
return types.toArray(new String[]{});
}
return super.getTypesForProperty(hash, name);
}
public void sort() {
if (children != null) {
List remove = new ArrayList();
for (Element child : children) {
child.sort();
if (child.isEmpty())
remove.add(child);
}
children.removeAll(remove);
Collections.sort(children, new ElementSortComparator(this, this.property));
}
}
public class ElementSortComparator implements Comparator {
private List children;
public ElementSortComparator(Element e, Property property) {
String tn = e.getType();
StructureDefinition sd = property.getContext().fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/"+tn);
if (sd != null && !sd.getAbstract())
children = sd.getSnapshot().getElement();
else
children = property.getStructure().getSnapshot().getElement();
}
@Override
public int compare(Element e0, Element e1) {
int i0 = find(e0);
int i1 = find(e1);
return (i0 < i1) ? -1 : ((i0 == i1) ? 0 : 1);
}
private int find(Element e0) {
int i = e0.elementProperty != null ? children.indexOf(e0.elementProperty.getDefinition()) : children.indexOf(e0.property.getDefinition());
return i;
}
}
}