diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..128621a --- /dev/null +++ b/.gitignore @@ -0,0 +1,40 @@ +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# Default ignored files +/shelf/ +/workspace.xml +target/ +.project +.classpath +.settings/ +.DS_Store +.idea/ +*.iml +*.ipr +*.iws +logfile +*.log* +.springBeans +.gradle/ diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/pom.xml b/pom.xml new file mode 100755 index 0000000..1e50222 --- /dev/null +++ b/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + + org.smartregister + fhir-common-utils + 0.0.1-SNAPSHOT + + + 11 + 11 + 5.5.0 + + + + + hapi-fhir-base + ca.uhn.hapi.fhir + ${hapi.fhir.base.version} + + + ca.uhn.hapi.fhir + org.hl7.fhir.r4 + 5.4.10 + + + \ No newline at end of file diff --git a/src/main/java/org/smartregister/model/location/ChildTreeNode.java b/src/main/java/org/smartregister/model/location/ChildTreeNode.java new file mode 100755 index 0000000..3d7f1d8 --- /dev/null +++ b/src/main/java/org/smartregister/model/location/ChildTreeNode.java @@ -0,0 +1,84 @@ +/* + * Copyright 2021 Ona Systems, Inc + * + * 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. + */ +package org.smartregister.model.location; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.DatatypeDef; +import ca.uhn.fhir.util.ElementUtil; +import org.hl7.fhir.instance.model.api.ICompositeType; +import org.hl7.fhir.r4.model.StringType; +import org.hl7.fhir.r4.model.Type; + +@DatatypeDef(name = "ChildTreeNode") +public class ChildTreeNode extends Type implements ICompositeType { + + @Child( + name = "childId", + type = {StringType.class}, + order = 0, + min = 1, + max = 1, + modifier = false, + summary = false) + private StringType childId; + + @Child( + name = "treeNode", + type = {TreeNode.class}) + private TreeNode treeNode; + + public ChildTreeNode() { + treeNode = new TreeNode(); + } + + public StringType getChildId() { + return childId; + } + + public ChildTreeNode setChildId(StringType childId) { + this.childId = childId; + return this; + } + + public TreeNode getChildren() { + if (treeNode == null) { + treeNode = new TreeNode(); + } + return treeNode; + } + + public ChildTreeNode setChildren(TreeNode children) { + this.treeNode = children; + return this; + } + + @Override + public Type copy() { + ChildTreeNode childTreeNode = new ChildTreeNode(); + copyValues(childTreeNode); + return childTreeNode; + } + + @Override + public boolean isEmpty() { + return ElementUtil.isEmpty(childId); + } + + @Override + protected Type typedCopy() { + return copy(); + } +} diff --git a/src/main/java/org/smartregister/model/location/LocationHierarchy.java b/src/main/java/org/smartregister/model/location/LocationHierarchy.java new file mode 100755 index 0000000..5316e5a --- /dev/null +++ b/src/main/java/org/smartregister/model/location/LocationHierarchy.java @@ -0,0 +1,84 @@ +/* + * Copyright 2021 Ona Systems, Inc + * + * 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. + */ +package org.smartregister.model.location; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Description; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import org.hl7.fhir.r4.model.*; + +import java.util.ArrayList; +import java.util.List; + +@ResourceDef(name = "LocationHierarchy", profile = "http://hl7.org/fhir/profiles/custom-resource") +public class LocationHierarchy extends Location { + + @Child( + name = "locationId", + type = {StringType.class}, + order = 5, + min = 0, + max = 1, + modifier = false, + summary = true) + @Description( + shortDefinition = "Unique id to the location", + formalDefinition = "Id of the location whose location hierarchy will be displayed.") + protected StringType locationId; + + @Child( + name = "LocationHierarchyTree", + type = {LocationHierarchyTree.class}) + @Description( + shortDefinition = "Complete Location Hierarchy Tree", + formalDefinition = + "Consists of Location Hierarchy Tree and Parent Child Identifiers List") + private LocationHierarchyTree locationHierarchyTree; + + @Override + public Location copy() { + Location location = new Location(); + Bundle bundle = new Bundle(); + List theEntry = new ArrayList<>(); + Bundle.BundleEntryComponent entryComponent = new Bundle.BundleEntryComponent(); + entryComponent.setResource(new Bundle()); + theEntry.add(entryComponent); + bundle.setEntry(theEntry); + this.copyValues(location); + return location; + } + + @Override + public ResourceType getResourceType() { + return ResourceType.Bundle; + } + + public StringType getLocationId() { + return locationId; + } + + public void setLocationId(StringType locationId) { + this.locationId = locationId; + } + + public LocationHierarchyTree getLocationHierarchyTree() { + return locationHierarchyTree; + } + + public void setLocationHierarchyTree(LocationHierarchyTree locationHierarchyTree) { + this.locationHierarchyTree = locationHierarchyTree; + } +} diff --git a/src/main/java/org/smartregister/model/location/LocationHierarchyTree.java b/src/main/java/org/smartregister/model/location/LocationHierarchyTree.java new file mode 100755 index 0000000..3bdc36a --- /dev/null +++ b/src/main/java/org/smartregister/model/location/LocationHierarchyTree.java @@ -0,0 +1,91 @@ +/* + * Copyright 2021 Ona Systems, Inc + * + * 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. + */ +package org.smartregister.model.location; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.DatatypeDef; +import ca.uhn.fhir.util.ElementUtil; +import org.hl7.fhir.instance.model.api.ICompositeType; +import org.hl7.fhir.r4.model.Location; +import org.hl7.fhir.r4.model.StringType; +import org.hl7.fhir.r4.model.Type; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; + +@DatatypeDef(name = "LocationHierarchyTree") +public class LocationHierarchyTree extends Type implements ICompositeType { + + @Child(name = "locationsHierarchy") + private Tree locationsHierarchy; + + public LocationHierarchyTree() { + this.locationsHierarchy = new Tree(); + } + + public void addLocation(Location l) { + StringType idString = new StringType(); + idString.setValue(l.getId()); + if (!locationsHierarchy.hasNode(idString.getValue())) { + if (l.getPartOf() == null || StringUtils.isEmpty(l.getPartOf().getReference())) { + locationsHierarchy.addNode(idString.getValue(), l.getName(), l, null); + } else { + // get Parent Location + StringType parentId = new StringType(); + parentId.setValue(l.getPartOf().getReference()); + locationsHierarchy.addNode( + idString.getValue(), l.getName(), l, parentId.getValue()); + } + } + } + + /** + * WARNING: Overrides existing locations + * + * @param locations + */ + public void buildTreeFromList(List locations) { + for (Location location : locations) { + addLocation(location); + } + } + + public Tree getLocationsHierarchy() { + return locationsHierarchy; + } + + public LocationHierarchyTree setLocationsHierarchy(Tree locationsHierarchy) { + this.locationsHierarchy = locationsHierarchy; + return this; + } + + @Override + public Type copy() { + LocationHierarchyTree locationHierarchyTree = new LocationHierarchyTree(); + copyValues(locationHierarchyTree); + return locationHierarchyTree; + } + + @Override + public boolean isEmpty() { + return ElementUtil.isEmpty(locationsHierarchy); + } + + @Override + protected Type typedCopy() { + return copy(); + } +} diff --git a/src/main/java/org/smartregister/model/location/ParentChildrenMap.java b/src/main/java/org/smartregister/model/location/ParentChildrenMap.java new file mode 100755 index 0000000..e74e608 --- /dev/null +++ b/src/main/java/org/smartregister/model/location/ParentChildrenMap.java @@ -0,0 +1,84 @@ +/* + * Copyright 2021 Ona Systems, Inc + * + * 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. + */ +package org.smartregister.model.location; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.DatatypeDef; +import ca.uhn.fhir.util.ElementUtil; +import org.hl7.fhir.instance.model.api.ICompositeType; +import org.hl7.fhir.r4.model.StringType; +import org.hl7.fhir.r4.model.Type; + +import java.util.List; + +@DatatypeDef(name = "ParentChildrenMap") +public class ParentChildrenMap extends Type implements ICompositeType { + + @Child( + name = "identifier", + type = {StringType.class}, + order = 0, + min = 1, + max = 1, + modifier = false, + summary = false) + private StringType identifier; + + @Child( + name = "childIdentifiers", + type = {StringType.class}, + order = 1, + min = 0, + max = -1, + modifier = false, + summary = false) + private List childIdentifiers; + + public StringType getIdentifier() { + return identifier; + } + + public ParentChildrenMap setIdentifier(StringType identifier) { + this.identifier = identifier; + return this; + } + + public List getChildIdentifiers() { + return childIdentifiers; + } + + public ParentChildrenMap setChildIdentifiers(List childIdentifiers) { + this.childIdentifiers = childIdentifiers; + return this; + } + + @Override + public Type copy() { + ParentChildrenMap parentChildrenMap = new ParentChildrenMap(); + copyValues(parentChildrenMap); + return parentChildrenMap; + } + + @Override + public boolean isEmpty() { + return ElementUtil.isEmpty(identifier); + } + + @Override + protected Type typedCopy() { + return copy(); + } +} diff --git a/src/main/java/org/smartregister/model/location/SingleTreeNode.java b/src/main/java/org/smartregister/model/location/SingleTreeNode.java new file mode 100755 index 0000000..eb59785 --- /dev/null +++ b/src/main/java/org/smartregister/model/location/SingleTreeNode.java @@ -0,0 +1,78 @@ +/* + * Copyright 2021 Ona Systems, Inc + * + * 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. + */ +package org.smartregister.model.location; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.DatatypeDef; +import ca.uhn.fhir.util.ElementUtil; +import org.hl7.fhir.instance.model.api.ICompositeType; +import org.hl7.fhir.r4.model.StringType; +import org.hl7.fhir.r4.model.Type; + +@DatatypeDef(name = "SingleTreeNode") +public class SingleTreeNode extends Type implements ICompositeType { + + @Child( + name = "treeNodeId", + type = {StringType.class}, + order = 0) + private StringType treeNodeId; + + @Child( + name = "treeNode", + type = {TreeNode.class}, + order = 1, + min = 0, + max = -1, + modifier = false, + summary = false) + private TreeNode treeNode; + + @Override + public Type copy() { + SingleTreeNode singleTreeNode = new SingleTreeNode(); + copyValues(singleTreeNode); + return singleTreeNode; + } + + @Override + public boolean isEmpty() { + return ElementUtil.isEmpty(treeNodeId, treeNode); + } + + @Override + protected Type typedCopy() { + return copy(); + } + + public StringType getTreeNodeId() { + return treeNodeId; + } + + public SingleTreeNode setTreeNodeId(StringType treeNodeId) { + this.treeNodeId = treeNodeId; + return this; + } + + public TreeNode getTreeNode() { + return treeNode; + } + + public SingleTreeNode setTreeNode(TreeNode treeNode) { + this.treeNode = treeNode; + return this; + } +} diff --git a/src/main/java/org/smartregister/model/location/Tree.java b/src/main/java/org/smartregister/model/location/Tree.java new file mode 100755 index 0000000..0654fd4 --- /dev/null +++ b/src/main/java/org/smartregister/model/location/Tree.java @@ -0,0 +1,254 @@ +/* + * Copyright 2021 Ona Systems, Inc + * + * 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. + */ +package org.smartregister.model.location; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.DatatypeDef; +import ca.uhn.fhir.util.ElementUtil; +import org.apache.commons.lang3.StringUtils; +import org.hl7.fhir.instance.model.api.ICompositeType; +import org.hl7.fhir.r4.model.Location; +import org.hl7.fhir.r4.model.StringType; +import org.hl7.fhir.r4.model.Type; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +import static org.smartregister.utils.Constants.SLASH_UNDERSCORE; + +@DatatypeDef(name = "Tree") +public class Tree extends Type implements ICompositeType { + + @Child( + name = "listOfNodes", + type = {SingleTreeNode.class}) + private SingleTreeNode listOfNodes; + + @Child( + name = "parentChildren", + type = {ParentChildrenMap.class}, + order = 1, + min = 0, + max = -1, + modifier = false, + summary = false) + private List parentChildren; + + private static Logger logger = Logger.getLogger(Tree.class.getSimpleName()); + + public SingleTreeNode getTree() { + return listOfNodes; + } + + public Tree() { + listOfNodes = new SingleTreeNode(); + parentChildren = new ArrayList<>(); + } + + private void addToParentChildRelation(String parent, String id) { + if (parentChildren == null) { + parentChildren = new ArrayList<>(); + } + List kids = null; + if (parentChildren != null) { + for (int i = 0; i < parentChildren.size(); i++) { + kids = + parentChildren.get(i) != null + && parentChildren.get(i).getIdentifier() != null + && StringUtils.isNotBlank( + parentChildren.get(i).getIdentifier().getValue()) + && parentChildren + .get(i) + .getIdentifier() + .getValue() + .equals(parent) + ? parentChildren.get(i).getChildIdentifiers() + : null; + logger.info("Kids are : " + kids); + if (kids != null) { + break; + } + } + } + + if (kids == null) { + kids = new ArrayList<>(); + } + StringType idStringType = new StringType(); + String idString = id; + if (idString.contains(SLASH_UNDERSCORE)) { + idString = idString.substring(0, idString.indexOf(SLASH_UNDERSCORE)); + } + idStringType.setValue(idString); + + StringType parentStringType = new StringType(); + parentStringType.setValue(parent); + kids.add(idStringType); + Boolean setParentChildMap = false; + for (int i = 0; i < parentChildren.size(); i++) { + if (parentChildren.get(i) != null + && parentChildren.get(i).getIdentifier() != null + && StringUtils.isNotBlank(parentChildren.get(i).getIdentifier().getValue()) + && parentChildren.get(i).getIdentifier().getValue().equals(parent)) { + parentChildren.get(i).setChildIdentifiers(kids); + setParentChildMap = true; + } + } + + if (!setParentChildMap) { + ParentChildrenMap parentChildrenMap = new ParentChildrenMap(); + parentChildrenMap.setIdentifier(parentStringType); + parentChildrenMap.setChildIdentifiers(kids); + parentChildren.add(parentChildrenMap); + } + } + + public void addNode(String id, String label, Location node, String parentId) { + if (listOfNodes == null) { + listOfNodes = new SingleTreeNode(); + } + + // if node exists we should break since user should write optimized code and also tree can + // not have duplicates + if (hasNode(id)) { + throw new IllegalArgumentException("Node with ID " + id + " already exists in tree"); + } + + TreeNode treeNode = makeNode(id, label, node, parentId); + + if (parentId != null) { + addToParentChildRelation(parentId, id); + + TreeNode parentNode = getNode(parentId); + + // if parent exists add to it otherwise add as root for now + if (parentNode != null) { + parentNode.addChild(treeNode); + } else { + // if no parent exists add it as root node + String idString = (String) id; + if (idString.contains(SLASH_UNDERSCORE)) { + idString = idString.substring(0, idString.indexOf(SLASH_UNDERSCORE)); + } + SingleTreeNode singleTreeNode = new SingleTreeNode(); + StringType treeNodeId = new StringType(); + treeNodeId.setValue(idString); + singleTreeNode.setTreeNodeId(treeNodeId); + singleTreeNode.setTreeNode(treeNode); + listOfNodes = singleTreeNode; + } + } else { + // if no parent add it as root node + String idString = id; + if (idString.contains(SLASH_UNDERSCORE)) { + idString = idString.substring(0, idString.indexOf(SLASH_UNDERSCORE)); + } + + SingleTreeNode singleTreeNode = new SingleTreeNode(); + StringType treeNodeId = new StringType(); + treeNodeId.setValue(idString); + singleTreeNode.setTreeNodeId(treeNodeId); + singleTreeNode.setTreeNode(treeNode); + listOfNodes = singleTreeNode; + } + } + + private TreeNode makeNode(String id, String label, Location node, String parentId) { + TreeNode treenode = getNode(id); + if (treenode == null) { + treenode = new TreeNode(); + StringType nodeId = new StringType(); + String idString = (String) id; + if (idString.contains(SLASH_UNDERSCORE)) { + idString = idString.substring(0, idString.indexOf(SLASH_UNDERSCORE)); + } + nodeId.setValue((String) idString); + treenode.setNodeId(nodeId); + StringType labelString = new StringType(); + labelString.setValue(label); + treenode.setLabel(labelString); + treenode.setNode(node); + StringType parentIdString = new StringType(); + String parentIdStringVar = parentId; + + if (parentIdStringVar != null && parentIdStringVar.contains(SLASH_UNDERSCORE)) { + parentIdStringVar = + parentIdStringVar.substring(0, parentIdStringVar.indexOf(SLASH_UNDERSCORE)); + } + parentIdString.setValue(parentIdStringVar); + treenode.setParent(parentIdString); + } + return treenode; + } + + public TreeNode getNode(String id) { + // Check if id is any root node + String idString = id; + if (idString != null && idString.contains(SLASH_UNDERSCORE)) { + idString = idString.substring(0, idString.indexOf(SLASH_UNDERSCORE)); + } + + if (listOfNodes.getTreeNodeId() != null + && StringUtils.isNotBlank(listOfNodes.getTreeNodeId().getValue()) + && listOfNodes.getTreeNodeId().getValue().equals(idString)) { + return listOfNodes.getTreeNode(); + + } else { + if (listOfNodes != null && listOfNodes.getTreeNode() != null) { + return listOfNodes.getTreeNode().findChild(idString); + } + } + return null; + } + + public boolean hasNode(String id) { + return getNode(id) != null; + } + + public SingleTreeNode getListOfNodes() { + return listOfNodes; + } + + public void setListOfNodes(SingleTreeNode listOfNodes) { + this.listOfNodes = listOfNodes; + } + + public List getParentChildren() { + return parentChildren; + } + + public void setParentChildren(List parentChildren) { + this.parentChildren = parentChildren; + } + + @Override + public Type copy() { + Tree tree = new Tree(); + copyValues(tree); + return tree; + } + + @Override + public boolean isEmpty() { + return ElementUtil.isEmpty(listOfNodes); + } + + @Override + protected Type typedCopy() { + return copy(); + } +} diff --git a/src/main/java/org/smartregister/model/location/TreeNode.java b/src/main/java/org/smartregister/model/location/TreeNode.java new file mode 100755 index 0000000..4bc3aff --- /dev/null +++ b/src/main/java/org/smartregister/model/location/TreeNode.java @@ -0,0 +1,214 @@ +/* + * Copyright 2021 Ona Systems, Inc + * + * 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. + */ +package org.smartregister.model.location; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.DatatypeDef; +import ca.uhn.fhir.util.ElementUtil; +import org.apache.commons.lang3.StringUtils; +import org.hl7.fhir.instance.model.api.ICompositeType; +import org.hl7.fhir.r4.model.*; + +import java.util.ArrayList; +import java.util.List; + +import static org.smartregister.utils.Constants.SLASH_UNDERSCORE; + +@DatatypeDef(name = "TreeNode") +public class TreeNode extends Type implements ICompositeType { + + @Child( + name = "name", + type = {StringType.class}, + order = 0, + min = 1, + max = 1, + modifier = false, + summary = false) + protected StringType name; + + @Child( + name = "nodeId", + type = {StringType.class}, + order = 2) + private StringType nodeId; + + @Child( + name = "label", + type = {StringType.class}, + order = 3) + private StringType label; + + @Child( + name = "node", + type = {Location.class}, + order = 4) + private Location node; + + @Child( + name = "parent", + type = {StringType.class}, + order = 5) + private StringType parent; + + @Child( + name = "children", + type = {ChildTreeNode.class}, + order = 6, + min = 0, + max = -1, + modifier = false, + summary = false) + private List children; + + public TreeNode() { + children = new ArrayList<>(); + } + + public TreeNode( + StringType name, + StringType nodeId, + StringType label, + Location node, + StringType parent) { + this.name = name; + this.nodeId = nodeId; + this.label = label; + this.node = node; + this.parent = parent; + } + + public StringType getName() { + if (name == null) { + name = new StringType(); + } + return name; + } + + public TreeNode setName(StringType name) { + this.name = name; + return this; + } + + public StringType getLabel() { + return label; + } + + public TreeNode setLabel(StringType label) { + this.label = label; + return this; + } + + @Override + public Type copy() { + TreeNode treeNode = new TreeNode(); + copyValues(treeNode); + return treeNode; + } + + @Override + public boolean isEmpty() { + return ElementUtil.isEmpty(node); + } + + @Override + protected Type typedCopy() { + return copy(); + } + + public StringType getNodeId() { + return nodeId; + } + + public TreeNode setNodeId(StringType nodeId) { + this.nodeId = nodeId; + return this; + } + + public Location getNode() { + return node; + } + + public TreeNode setNode(Location node) { + this.node = node; + return this; + } + + public StringType getParent() { + return parent; + } + + public TreeNode setParent(StringType parent) { + this.parent = parent; + return this; + } + + public List getChildren() { + if (children == null) { + children = new ArrayList<>(); + } + return children; + } + + public TreeNode setChildren(List children) { + this.children = children; + return this; + } + + public void addChild(TreeNode node) { + if (children == null) { + children = new ArrayList<>(); + } + ChildTreeNode childTreeNode = new ChildTreeNode(); + childTreeNode.setChildId(node.getNodeId()); + List treeNodeList = new ArrayList<>(); + TreeNode treeNode = new TreeNode(); + treeNode.setNode(node.getNode()); + treeNode.setNodeId(node.getNodeId()); + treeNode.setLabel(node.getLabel()); + treeNode.setParent(node.getParent()); + treeNodeList.add(treeNode); + childTreeNode.setChildren(treeNode); + children.add(childTreeNode); + } + + public TreeNode findChild(String id) { + String idString = (String) id; + if (idString.contains(SLASH_UNDERSCORE)) { + idString = idString.substring(0, idString.indexOf(SLASH_UNDERSCORE)); + } + if (children != null && children.size() > 0) { + for (int i = 0; i < children.size(); i++) { + if (children.get(i) != null) { + for (ChildTreeNode child : children) { + if (child != null + && child.getChildren() != null + && child.getChildren().getNodeId() != null + && StringUtils.isNotBlank( + child.getChildren().getNodeId().getValue()) + && child.getChildren().getNodeId().getValue().equals(idString)) { + return child.getChildren(); + } else if (child != null && child != null) { + TreeNode node = child.getChildren().findChild(idString); + if (node != null) return node; + } + } + } + } + } + return null; + } +} diff --git a/src/main/java/org/smartregister/model/practitioner/FhirCareTeamExtension.java b/src/main/java/org/smartregister/model/practitioner/FhirCareTeamExtension.java new file mode 100755 index 0000000..98bc4f0 --- /dev/null +++ b/src/main/java/org/smartregister/model/practitioner/FhirCareTeamExtension.java @@ -0,0 +1,90 @@ +/* + * Copyright 2021 Ona Systems, Inc + * + * 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. + */ +package org.smartregister.model.practitioner; + +import ca.uhn.fhir.model.api.annotation.DatatypeDef; +import org.hl7.fhir.r4.model.*; + +import java.util.ArrayList; +import java.util.List; + +@DatatypeDef(name = "FhirCareTeamExtension") +public class FhirCareTeamExtension extends CareTeam { + + @Override + public CareTeam copy() { + CareTeam careTeam = new CareTeam(); + Bundle bundle = new Bundle(); + List theEntry = new ArrayList<>(); + Bundle.BundleEntryComponent entryComponent = new Bundle.BundleEntryComponent(); + entryComponent.setResource(new Bundle()); + theEntry.add(entryComponent); + bundle.setEntry(theEntry); + this.copyValues(careTeam); + return careTeam; + } + + public FhirCareTeamExtension mapValues(CareTeam careTeam) { + FhirCareTeamExtension fhirCareTeamExtension = new FhirCareTeamExtension(); + if (careTeam != null) { + if (careTeam.getId() != null) { + fhirCareTeamExtension.setId(careTeam.getId()); + } + if (careTeam.getIdentifier() != null) { + fhirCareTeamExtension.setIdentifier(careTeam.getIdentifier()); + } + if (careTeam.getStatus() != null) { + fhirCareTeamExtension.setStatus(careTeam.getStatus()); + } + if (careTeam.getCategory() != null) { + fhirCareTeamExtension.setCategory(careTeam.getCategory()); + } + if (careTeam.getName() != null) { + fhirCareTeamExtension.setName(careTeam.getName()); + } + if (careTeam.getSubject() != null) { + fhirCareTeamExtension.setSubject(careTeam.getSubject()); + } + if (careTeam.getEncounter() != null) { + fhirCareTeamExtension.setEncounter(careTeam.getEncounter()); + } + if (careTeam.getPeriod() != null) { + fhirCareTeamExtension.setPeriod(careTeam.getPeriod()); + } + if (careTeam.getParticipant() != null) { + fhirCareTeamExtension.setParticipant(careTeam.getParticipant()); + } + + if (careTeam.getReasonCode() != null) { + fhirCareTeamExtension.setReasonCode(careTeam.getReasonCode()); + } + if (careTeam.getReasonReference() != null) { + fhirCareTeamExtension.setReasonReference(careTeam.getReasonReference()); + } + if (careTeam.getManagingOrganization() != null) { + fhirCareTeamExtension.setManagingOrganization(careTeam.getManagingOrganization()); + } + if (careTeam.getTelecom() != null) { + fhirCareTeamExtension.setTelecom(careTeam.getTelecom()); + } + if (careTeam.getNote() != null) { + fhirCareTeamExtension.setNote(careTeam.getNote()); + } + } + + return fhirCareTeamExtension; + } +} diff --git a/src/main/java/org/smartregister/model/practitioner/FhirOrganizationExtension.java b/src/main/java/org/smartregister/model/practitioner/FhirOrganizationExtension.java new file mode 100755 index 0000000..9abb081 --- /dev/null +++ b/src/main/java/org/smartregister/model/practitioner/FhirOrganizationExtension.java @@ -0,0 +1,80 @@ +/* + * Copyright 2021 Ona Systems, Inc + * + * 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. + */ +package org.smartregister.model.practitioner; + +import ca.uhn.fhir.model.api.annotation.DatatypeDef; +import org.hl7.fhir.r4.model.*; + +import java.util.ArrayList; +import java.util.List; + +@DatatypeDef(name = "FhirOrganizationExtension") +public class FhirOrganizationExtension extends Organization { + + @Override + public Organization copy() { + Organization organization = new Organization(); + Bundle bundle = new Bundle(); + List theEntry = new ArrayList<>(); + Bundle.BundleEntryComponent entryComponent = new Bundle.BundleEntryComponent(); + entryComponent.setResource(new Bundle()); + theEntry.add(entryComponent); + bundle.setEntry(theEntry); + this.copyValues(organization); + return organization; + } + + public FhirOrganizationExtension mapValues(Organization organization) { + FhirOrganizationExtension fhirOrganizationExtension = new FhirOrganizationExtension(); + if (organization != null) { + if (organization.getId() != null) { + fhirOrganizationExtension.setId(organization.getId()); + } + if (organization.getIdentifier() != null) { + fhirOrganizationExtension.setIdentifier(organization.getIdentifier()); + } + + fhirOrganizationExtension.setActive(organization.getActive()); + if (organization.getType() != null) { + fhirOrganizationExtension.setType(organization.getType()); + } + if (organization.getName() != null) { + fhirOrganizationExtension.setName(organization.getName()); + } + if (organization.getAlias() != null) { + fhirOrganizationExtension.setAlias(organization.getAlias()); + } + if (organization.getTelecom() != null) { + fhirOrganizationExtension.setTelecom(organization.getTelecom()); + } + if (organization.getAddress() != null) { + fhirOrganizationExtension.setAddress(organization.getAddress()); + } + if (organization.getPartOf() != null) { + fhirOrganizationExtension.setPartOf(organization.getPartOf()); + } + if (organization.getContact() != null) { + fhirOrganizationExtension.setContact(organization.getContact()); + } + + if (organization.getEndpoint() != null) { + fhirOrganizationExtension.setEndpoint(organization.getEndpoint()); + } + } + + return fhirOrganizationExtension; + } +} diff --git a/src/main/java/org/smartregister/model/practitioner/FhirPractitionerDetails.java b/src/main/java/org/smartregister/model/practitioner/FhirPractitionerDetails.java new file mode 100755 index 0000000..5da3117 --- /dev/null +++ b/src/main/java/org/smartregister/model/practitioner/FhirPractitionerDetails.java @@ -0,0 +1,121 @@ +/* + * Copyright 2021 Ona Systems, Inc + * + * 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. + */ +package org.smartregister.model.practitioner; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.DatatypeDef; +import ca.uhn.fhir.util.ElementUtil; +import org.hl7.fhir.instance.model.api.ICompositeType; +import org.hl7.fhir.r4.model.StringType; +import org.hl7.fhir.r4.model.Type; +import org.smartregister.model.location.LocationHierarchy; + +import java.util.List; + +@DatatypeDef(name = "fhir") +public class FhirPractitionerDetails extends Type implements ICompositeType { + + @Child( + name = "careteams", + type = {FhirCareTeamExtension.class}, + order = 1, + min = 0, + max = -1, + modifier = false, + summary = false) + List fhirCareTeamExtensionList; + + @Child( + name = "teams", + type = {FhirOrganizationExtension.class}, + order = 2, + min = 0, + max = -1, + modifier = false, + summary = false) + List fhirOrganizationExtensions; + + @Child( + name = "locationHierarchyList", + type = {LocationHierarchy.class}, + order = 3, + min = 0, + max = -1, + modifier = false, + summary = false) + private List locationHierarchyList; + + @Child( + name = "practitionerId", + type = {StringType.class}, + order = 4, + min = 0, + max = -1, + modifier = false, + summary = false) + private StringType practitionerId; + + public List getFhirCareTeamExtensionList() { + return fhirCareTeamExtensionList; + } + + public void setFhirCareTeamExtensionList( + List fhirCareTeamExtensionList) { + this.fhirCareTeamExtensionList = fhirCareTeamExtensionList; + } + + public List getFhirOrganizationExtensions() { + return fhirOrganizationExtensions; + } + + public void setFhirOrganizationExtensions( + List fhirOrganizationExtensions) { + this.fhirOrganizationExtensions = fhirOrganizationExtensions; + } + + public List getLocationHierarchyList() { + return locationHierarchyList; + } + + public void setLocationHierarchyList(List locationHierarchyList) { + this.locationHierarchyList = locationHierarchyList; + } + + public StringType getPractitionerId() { + return practitionerId; + } + + public void setPractitionerId(StringType practitionerId) { + this.practitionerId = practitionerId; + } + + @Override + public Type copy() { + FhirPractitionerDetails fhirPractitionerDetails = new FhirPractitionerDetails(); + copyValues(fhirPractitionerDetails); + return fhirPractitionerDetails; + } + + @Override + public boolean isEmpty() { + return ElementUtil.isEmpty(practitionerId); + } + + @Override + protected Type typedCopy() { + return copy(); + } +} diff --git a/src/main/java/org/smartregister/model/practitioner/KeycloakUserDetails.java b/src/main/java/org/smartregister/model/practitioner/KeycloakUserDetails.java new file mode 100755 index 0000000..3c4c908 --- /dev/null +++ b/src/main/java/org/smartregister/model/practitioner/KeycloakUserDetails.java @@ -0,0 +1,81 @@ +/* + * Copyright 2021 Ona Systems, Inc + * + * 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. + */ +package org.smartregister.model.practitioner; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.DatatypeDef; +import ca.uhn.fhir.util.ElementUtil; +import org.hl7.fhir.instance.model.api.ICompositeType; +import org.hl7.fhir.r4.model.StringType; +import org.hl7.fhir.r4.model.Type; + +import java.util.List; + +@DatatypeDef(name = "KeycloakUserDetails") +public class KeycloakUserDetails extends Type implements ICompositeType { + @Child( + name = "user-bio", + type = {StringType.class}, + order = 0, + min = 0, + max = -1, + modifier = false, + summary = false) + private UserBioData userBioData; + + @Child( + name = "user-roles", + type = {StringType.class}, + order = 1, + min = 0, + max = -1, + modifier = false, + summary = false) + private List roles; + + public UserBioData getUserBioData() { + return userBioData; + } + + public void setUserBioData(UserBioData userBioData) { + this.userBioData = userBioData; + } + + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } + + @Override + public Type copy() { + KeycloakUserDetails keycloakUserDetails = new KeycloakUserDetails(); + copyValues(keycloakUserDetails); + return keycloakUserDetails; + } + + @Override + public boolean isEmpty() { + return ElementUtil.isEmpty(userBioData); + } + + @Override + protected Type typedCopy() { + return copy(); + } +} diff --git a/src/main/java/org/smartregister/model/practitioner/PractitionerDetails.java b/src/main/java/org/smartregister/model/practitioner/PractitionerDetails.java new file mode 100755 index 0000000..a86971e --- /dev/null +++ b/src/main/java/org/smartregister/model/practitioner/PractitionerDetails.java @@ -0,0 +1,82 @@ +/* + * Copyright 2021 Ona Systems, Inc + * + * 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. + */ +package org.smartregister.model.practitioner; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Description; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Practitioner; +import org.hl7.fhir.r4.model.ResourceType; + +import java.util.ArrayList; +import java.util.List; + +@ResourceDef( + name = "practitioner-details", + profile = "http://hl7.org/fhir/profiles/custom-resource") +public class PractitionerDetails extends Practitioner { + + @Child( + name = "KeycloakUserDetails", + type = {KeycloakUserDetails.class}) + @Description( + shortDefinition = "Get Keycloak User details from the Keycloak server", + formalDefinition = "Get Keycloak User details from the Keycloak server") + private KeycloakUserDetails keycloakUserDetails; + + @Child( + name = "fhir", + type = {FhirPractitionerDetails.class}) + @Description( + shortDefinition = "Get resources from FHIR Server", + formalDefinition = "Get resources from FHIR Server") + private FhirPractitionerDetails fhirPractitionerDetails; + + @Override + public Practitioner copy() { + Practitioner practitioner = new Practitioner(); + Bundle bundle = new Bundle(); + List theEntry = new ArrayList<>(); + Bundle.BundleEntryComponent entryComponent = new Bundle.BundleEntryComponent(); + entryComponent.setResource(new Bundle()); + theEntry.add(entryComponent); + bundle.setEntry(theEntry); + this.copyValues(practitioner); + return practitioner; + } + + @Override + public ResourceType getResourceType() { + return ResourceType.Bundle; + } + + public KeycloakUserDetails getUserDetail() { + return keycloakUserDetails; + } + + public void setUserDetail(KeycloakUserDetails keycloakUserDetails) { + this.keycloakUserDetails = keycloakUserDetails; + } + + public FhirPractitionerDetails getFhirPractitionerDetails() { + return fhirPractitionerDetails; + } + + public void setFhirPractitionerDetails(FhirPractitionerDetails fhirPractitionerDetails) { + this.fhirPractitionerDetails = fhirPractitionerDetails; + } +} diff --git a/src/main/java/org/smartregister/model/practitioner/UserBioData.java b/src/main/java/org/smartregister/model/practitioner/UserBioData.java new file mode 100755 index 0000000..afc626d --- /dev/null +++ b/src/main/java/org/smartregister/model/practitioner/UserBioData.java @@ -0,0 +1,170 @@ +/* + * Copyright 2021 Ona Systems, Inc + * + * 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. + */ +package org.smartregister.model.practitioner; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.DatatypeDef; +import ca.uhn.fhir.util.ElementUtil; +import org.hl7.fhir.instance.model.api.ICompositeType; +import org.hl7.fhir.r4.model.StringType; +import org.hl7.fhir.r4.model.Type; + +@DatatypeDef(name = "user-bio") +public class UserBioData extends Type implements ICompositeType { + + @Child( + name = "identifier", + type = {StringType.class}, + order = 0, + min = 1, + max = 1, + modifier = false, + summary = false) + protected StringType identifier; + + @Child( + name = "userName", + type = {StringType.class}, + order = 1, + min = 1, + max = 1, + modifier = false, + summary = false) + protected StringType userName; + + @Child( + name = "preferredName", + type = {StringType.class}, + order = 2, + min = 1, + max = 1, + modifier = false, + summary = false) + protected StringType preferredName; + + @Child( + name = "familyName", + type = {StringType.class}, + order = 3, + min = 1, + max = 1, + modifier = false, + summary = false) + protected StringType familyName; + + @Child( + name = "givenName", + type = {StringType.class}, + order = 4, + min = 1, + max = 1, + modifier = false, + summary = false) + protected StringType givenName; + + @Child( + name = "email", + type = {StringType.class}, + order = 5, + min = 1, + max = 1, + modifier = false, + summary = false) + protected StringType email; + + @Child( + name = "emailVerified", + type = {StringType.class}, + order = 6, + min = 1, + max = 1, + modifier = false, + summary = false) + protected StringType emailVerified; + + public StringType getIdentifier() { + return identifier; + } + + public void setIdentifier(StringType identifier) { + this.identifier = identifier; + } + + public StringType getUserName() { + return userName; + } + + public void setUserName(StringType userName) { + this.userName = userName; + } + + public StringType getPreferredName() { + return preferredName; + } + + public void setPreferredName(StringType preferredName) { + this.preferredName = preferredName; + } + + public StringType getFamilyName() { + return familyName; + } + + public void setFamilyName(StringType familyName) { + this.familyName = familyName; + } + + public StringType getGivenName() { + return givenName; + } + + public void setGivenName(StringType givenName) { + this.givenName = givenName; + } + + public StringType getEmail() { + return email; + } + + public void setEmail(StringType email) { + this.email = email; + } + + public StringType getEmailVerified() { + return emailVerified; + } + + public void setEmailVerified(StringType emailVerified) { + this.emailVerified = emailVerified; + } + + @Override + public Type copy() { + UserBioData userBioData = new UserBioData(); + copyValues(userBioData); + return userBioData; + } + + @Override + public boolean isEmpty() { + return ElementUtil.isEmpty(identifier); + } + + @Override + protected Type typedCopy() { + return copy(); + } +} diff --git a/src/main/java/org/smartregister/utils/Constants.java b/src/main/java/org/smartregister/utils/Constants.java new file mode 100755 index 0000000..fce39df --- /dev/null +++ b/src/main/java/org/smartregister/utils/Constants.java @@ -0,0 +1,49 @@ +/* + * Copyright 2021 Ona Systems, Inc + * + * 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. + */ +package org.smartregister.utils; + +public interface Constants { + + String SLASH_UNDERSCORE = "/_"; + String LOCATION = "Location"; + String FORWARD_SLASH = "/"; + String IDENTIFIER = "identifier"; + String LOCATION_RESOURCE_NOT_FOUND = "Location Resource : Not Found"; + String LOCATION_RESOURCE = "Location Resource : "; + String PART_OF = "partof"; + String KEYCLOAK_UUID = "keycloak-uuid"; + String PRACTITIONER = "practitioner"; + String PARTICIPANT = "participant"; + String KEYCLOAK_USER_NOT_FOUND = "Keycloak User Not Found"; + String PRACTITIONER_NOT_FOUND = "Practitioner Not Found"; + String PRIMARY_ORGANIZATION = "primary-organization"; + String ID = "_id"; + String PREFFERED_USERNAME = "Preferred Username"; + String USERNAME = "Username"; + String FAMILY_NAME = "Family Name"; + String GIVEN_NAME = "Given Name"; + String EMAIL = "Email"; + String EMAIL_VERIFIED = "Email verified"; + String ROLE = "Role"; + String COLON = ":"; + String SPACE = " "; + String EMPTY_STRING = ""; + String _PRACTITIONER = "Practitioner"; + String PRACTITIONER_ROLE = "PractitionerRole"; + String CARE_TEAM = "CareTeam"; + String ORGANIZATION = "Organization"; + String ORGANIZATION_AFFILIATION = "OrganizationAffiliation"; +}