diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..f109e63
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction,
+and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by
+the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all
+other entities that control, are controlled by, or are under common
+control with that entity. For the purposes of this definition,
+"control" means (i) the power, direct or indirect, to cause the
+direction or management of such entity, whether by contract or
+otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity
+exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications,
+including but not limited to software source code, documentation
+source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical
+transformation or translation of a Source form, including but
+not limited to compiled object code, generated documentation,
+and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or
+Object form, made available under the License, as indicated by a
+copyright notice that is included in or attached to the work
+(an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object
+form, that is based on (or derived from) the Work and for which the
+editorial revisions, annotations, elaborations, or other modifications
+represent, as a whole, an original work of authorship. For the purposes
+of this License, Derivative Works shall not include works that remain
+separable from, or merely link (or bind by name) to the interfaces of,
+the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including
+the original version of the Work and any modifications or additions
+to that Work or Derivative Works thereof, that is intentionally
+submitted to Licensor for inclusion in the Work by the copyright owner
+or by an individual or Legal Entity authorized to submit on behalf of
+the copyright owner. For the purposes of this definition, "submitted"
+means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems,
+and issue tracking systems that are managed by, or on behalf of, the
+Licensor for the purpose of discussing and improving the Work, but
+excluding communication that is conspicuously marked or otherwise
+designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity
+on behalf of whom a Contribution has been received by Licensor and
+subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+this License, each Contributor hereby grants to You a perpetual,
+worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the
+Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+this License, each Contributor hereby grants to You a perpetual,
+worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+(except as stated in this section) patent license to make, have made,
+use, offer to sell, sell, import, and otherwise transfer the Work,
+where such license applies only to those patent claims licensable
+by such Contributor that are necessarily infringed by their
+Contribution(s) alone or by combination of their Contribution(s)
+with the Work to which such Contribution(s) was submitted. If You
+institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work
+or a Contribution incorporated within the Work constitutes direct
+or contributory patent infringement, then any patent licenses
+granted to You under this License for that Work shall terminate
+as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+Work or Derivative Works thereof in any medium, with or without
+modifications, and in Source or Object form, provided that You
+meet the following conditions:
+
+(a) You must give any other recipients of the Work or
+Derivative Works a copy of this License; and
+
+(b) You must cause any modified files to carry prominent notices
+stating that You changed the files; and
+
+(c) You must retain, in the Source form of any Derivative Works
+that You distribute, all copyright, patent, trademark, and
+attribution notices from the Source form of the Work,
+excluding those notices that do not pertain to any part of
+the Derivative Works; and
+
+(d) If the Work includes a "NOTICE" text file as part of its
+distribution, then any Derivative Works that You distribute must
+include a readable copy of the attribution notices contained
+within such NOTICE file, excluding those notices that do not
+pertain to any part of the Derivative Works, in at least one
+of the following places: within a NOTICE text file distributed
+as part of the Derivative Works; within the Source form or
+documentation, if provided along with the Derivative Works; or,
+within a display generated by the Derivative Works, if and
+wherever such third-party notices normally appear. The contents
+of the NOTICE file are for informational purposes only and
+do not modify the License. You may add Your own attribution
+notices within Derivative Works that You distribute, alongside
+or as an addendum to the NOTICE text from the Work, provided
+that such additional attribution notices cannot be construed
+as modifying the License.
+
+You may add Your own copyright statement to Your modifications and
+may provide additional or different license terms and conditions
+for use, reproduction, or distribution of Your modifications, or
+for any such Derivative Works as a whole, provided Your use,
+reproduction, and distribution of the Work otherwise complies with
+the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+any Contribution intentionally submitted for inclusion in the Work
+by You to the Licensor shall be under the terms and conditions of
+this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify
+the terms of any separate license agreement you may have executed
+with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+names, trademarks, service marks, or product names of the Licensor,
+except as required for reasonable and customary use in describing the
+origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+agreed to in writing, Licensor provides the Work (and each
+Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+implied, including, without limitation, any warranties or conditions
+of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+PARTICULAR PURPOSE. You are solely responsible for determining the
+appropriateness of using or redistributing the Work and assume any
+risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+whether in tort (including negligence), contract, or otherwise,
+unless required by applicable law (such as deliberate and grossly
+negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special,
+incidental, or consequential damages of any character arising as a
+result of this License or out of the use or inability to use the
+Work (including but not limited to damages for loss of goodwill,
+work stoppage, computer failure or malfunction, or any and all
+other commercial damages or losses), even if such Contributor
+has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+the Work or Derivative Works thereof, You may choose to offer,
+and charge a fee for, acceptance of support, warranty, indemnity,
+or other liability obligations and/or rights consistent with this
+License. However, in accepting such obligations, You may act only
+on Your own behalf and on Your sole responsibility, not on behalf
+of any other Contributor, and only if You agree to indemnify,
+defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason
+of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+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.
diff --git a/README.md b/README.md
index 2538f06..f8727d2 100755
--- a/README.md
+++ b/README.md
@@ -1,2 +1,2 @@
# hapi-fhir-opensrp-extensions
-This repository holds all the code extensions OpenSRP will build on top of the HAPI FHIR server.
+This repository holds all the code extensions OpenSRP will build on top of the HAPI FHIR server.
diff --git a/location/.gitignore b/location/.gitignore
new file mode 100755
index 0000000..128621a
--- /dev/null
+++ b/location/.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/location/README.md b/location/README.md
new file mode 100755
index 0000000..f8727d2
--- /dev/null
+++ b/location/README.md
@@ -0,0 +1,2 @@
+# hapi-fhir-opensrp-extensions
+This repository holds all the code extensions OpenSRP will build on top of the HAPI FHIR server.
diff --git a/location/pom.xml b/location/pom.xml
new file mode 100755
index 0000000..2015b63
--- /dev/null
+++ b/location/pom.xml
@@ -0,0 +1,19 @@
+
+ 4.0.0
+
+ hapi-fhir-opensrp-extensions
+ org.smartregister
+ 0.0.1-SNAPSHOT
+
+
+ The repository holds the location extensions on the HAPI server
+ org.smartregister.hapi-fhir-opensrp-extensions.location
+ hapi-fhir-opensrp-extensions.location
+ jar
+ https://github.com/opensrp/hapi-fhir-opensrp-extensions
+ 0.0.1-SNAPSHOT
+
+ location
+
+
diff --git a/location/src/license-header.txt b/location/src/license-header.txt
new file mode 100644
index 0000000..d937133
--- /dev/null
+++ b/location/src/license-header.txt
@@ -0,0 +1,15 @@
+/*
+ * Copyright $YEAR 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.
+ */
diff --git a/location/src/main/java/org/smartregister/extension/model/ChildTreeNode.java b/location/src/main/java/org/smartregister/extension/model/ChildTreeNode.java
new file mode 100755
index 0000000..c561a74
--- /dev/null
+++ b/location/src/main/java/org/smartregister/extension/model/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.extension.model;
+
+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/location/src/main/java/org/smartregister/extension/model/LocationHierarchy.java b/location/src/main/java/org/smartregister/extension/model/LocationHierarchy.java
new file mode 100755
index 0000000..6a4528c
--- /dev/null
+++ b/location/src/main/java/org/smartregister/extension/model/LocationHierarchy.java
@@ -0,0 +1,83 @@
+/*
+ * 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.extension.model;
+
+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 java.util.ArrayList;
+import java.util.List;
+import org.hl7.fhir.r4.model.*;
+
+@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/location/src/main/java/org/smartregister/extension/model/LocationHierarchyTree.java b/location/src/main/java/org/smartregister/extension/model/LocationHierarchyTree.java
new file mode 100755
index 0000000..bb7a007
--- /dev/null
+++ b/location/src/main/java/org/smartregister/extension/model/LocationHierarchyTree.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.extension.model;
+
+import ca.uhn.fhir.model.api.annotation.Child;
+import ca.uhn.fhir.model.api.annotation.DatatypeDef;
+import ca.uhn.fhir.util.ElementUtil;
+import java.util.List;
+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.thymeleaf.util.StringUtils;
+
+@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/location/src/main/java/org/smartregister/extension/model/ParentChildrenMap.java b/location/src/main/java/org/smartregister/extension/model/ParentChildrenMap.java
new file mode 100755
index 0000000..07667a1
--- /dev/null
+++ b/location/src/main/java/org/smartregister/extension/model/ParentChildrenMap.java
@@ -0,0 +1,83 @@
+/*
+ * 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.extension.model;
+
+import ca.uhn.fhir.model.api.annotation.Child;
+import ca.uhn.fhir.model.api.annotation.DatatypeDef;
+import ca.uhn.fhir.util.ElementUtil;
+import java.util.List;
+import org.hl7.fhir.instance.model.api.ICompositeType;
+import org.hl7.fhir.r4.model.StringType;
+import org.hl7.fhir.r4.model.Type;
+
+@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/location/src/main/java/org/smartregister/extension/model/SingleTreeNode.java b/location/src/main/java/org/smartregister/extension/model/SingleTreeNode.java
new file mode 100755
index 0000000..f9fd9e7
--- /dev/null
+++ b/location/src/main/java/org/smartregister/extension/model/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.extension.model;
+
+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/location/src/main/java/org/smartregister/extension/model/Tree.java b/location/src/main/java/org/smartregister/extension/model/Tree.java
new file mode 100755
index 0000000..de4896c
--- /dev/null
+++ b/location/src/main/java/org/smartregister/extension/model/Tree.java
@@ -0,0 +1,274 @@
+/*
+ * 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.extension.model;
+
+import static org.smartregister.extension.utils.Constants.SLASH_UNDERSCORE;
+
+import ca.uhn.fhir.model.api.annotation.Child;
+import ca.uhn.fhir.model.api.annotation.DatatypeDef;
+import ca.uhn.fhir.util.ElementUtil;
+import java.util.*;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+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;
+
+@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 = LogManager.getLogger(Tree.class.toString());
+
+ 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
+ && listOfNodes.getTreeNode().getChildren() != null) {
+ return recursivelyFindNode(idString, listOfNodes.getTreeNode().getChildren());
+ }
+ }
+ 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();
+ }
+
+ private TreeNode recursivelyFindNode(String idString, List childTreeNodeList) {
+ for (ChildTreeNode childTreeNode : childTreeNodeList) {
+ TreeNode treeNode = childTreeNode.getChildren();
+ if (treeNode != null
+ && treeNode.getNodeId() != null
+ && StringUtils.isNotBlank(treeNode.getNodeId().getValue())
+ && treeNode.getNodeId().getValue().equals(idString)) {
+ return treeNode;
+ } else {
+ if (treeNode != null
+ && treeNode.getChildren() != null
+ && treeNode.getChildren().size() > 0) {
+ return recursivelyFindNode(idString, treeNode.getChildren());
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/location/src/main/java/org/smartregister/extension/model/TreeNode.java b/location/src/main/java/org/smartregister/extension/model/TreeNode.java
new file mode 100755
index 0000000..2107464
--- /dev/null
+++ b/location/src/main/java/org/smartregister/extension/model/TreeNode.java
@@ -0,0 +1,213 @@
+/*
+ * 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.extension.model;
+
+import static org.smartregister.extension.utils.Constants.SLASH_UNDERSCORE;
+
+import ca.uhn.fhir.model.api.annotation.Child;
+import ca.uhn.fhir.model.api.annotation.DatatypeDef;
+import ca.uhn.fhir.util.ElementUtil;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.hl7.fhir.instance.model.api.ICompositeType;
+import org.hl7.fhir.r4.model.*;
+
+@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/location/src/main/java/org/smartregister/extension/rest/LocationHierarchyResourceProvider.java b/location/src/main/java/org/smartregister/extension/rest/LocationHierarchyResourceProvider.java
new file mode 100755
index 0000000..781f187
--- /dev/null
+++ b/location/src/main/java/org/smartregister/extension/rest/LocationHierarchyResourceProvider.java
@@ -0,0 +1,115 @@
+/*
+ * 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.extension.rest;
+
+import static org.smartregister.extension.utils.Constants.*;
+
+import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
+import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
+import ca.uhn.fhir.rest.annotation.*;
+import ca.uhn.fhir.rest.api.server.IBundleProvider;
+import ca.uhn.fhir.rest.param.*;
+import ca.uhn.fhir.rest.server.IResourceProvider;
+import java.util.*;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.r4.model.*;
+import org.smartregister.extension.model.LocationHierarchy;
+import org.smartregister.extension.model.LocationHierarchyTree;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class LocationHierarchyResourceProvider implements IResourceProvider {
+
+ @Autowired IFhirResourceDao locationIFhirResourceDao;
+
+ private static Logger logger =
+ LogManager.getLogger(LocationHierarchyResourceProvider.class.toString());
+
+ @Override
+ public Class extends IBaseResource> getResourceType() {
+ return LocationHierarchy.class;
+ }
+
+ @Search
+ public LocationHierarchy getLocationHierarchy(
+ @RequiredParam(name = IDENTIFIER) TokenParam identifier) {
+
+ SearchParameterMap paramMap = new SearchParameterMap();
+ paramMap.add(IDENTIFIER, identifier);
+
+ IBundleProvider locationBundle = locationIFhirResourceDao.search(paramMap);
+ List locations =
+ locationBundle != null
+ ? locationBundle.getResources(0, locationBundle.size())
+ : new ArrayList<>();
+ Long id = null;
+ if (locations.size() > 0) {
+ id =
+ locations.get(0) != null && locations.get(0).getIdElement() != null
+ ? locations.get(0).getIdElement().getIdPartAsLong()
+ : null;
+ }
+
+ LocationHierarchyTree locationHierarchyTree = new LocationHierarchyTree();
+ LocationHierarchy locationHierarchy = new LocationHierarchy();
+ if (id != null && locations.size() > 0) {
+ logger.info("Building Location Hierarchy of Location Id : " + id);
+ locationHierarchyTree.buildTreeFromList(getLocationHierarchy(id, locations.get(0)));
+ StringType locationIdString = new StringType().setId(id.toString()).getIdElement();
+ locationHierarchy.setLocationId(locationIdString);
+ locationHierarchy.setId(LOCATION_RESOURCE + id);
+
+ locationHierarchy.setLocationHierarchyTree(locationHierarchyTree);
+ } else {
+ locationHierarchy.setId(LOCATION_RESOURCE_NOT_FOUND);
+ }
+ return locationHierarchy;
+ }
+
+ private List getLocationHierarchy(Long id, IBaseResource parentLocation) {
+ return descendants(id, parentLocation);
+ }
+
+ public List descendants(Long id, IBaseResource parentLocation) {
+
+ SearchParameterMap paramMap = new SearchParameterMap();
+ ReferenceAndListParam thePartOf = new ReferenceAndListParam();
+ ReferenceParam partOf = new ReferenceParam();
+ partOf.setValue(LOCATION + FORWARD_SLASH + id);
+ ReferenceOrListParam referenceOrListParam = new ReferenceOrListParam();
+ referenceOrListParam.add(partOf);
+ thePartOf.addValue(referenceOrListParam);
+ paramMap.add(PART_OF, thePartOf);
+
+ IBundleProvider childLocationBundle = locationIFhirResourceDao.search(paramMap);
+ List allLocations = new ArrayList<>();
+ if (parentLocation != null) {
+ allLocations.add((Location) parentLocation);
+ }
+ for (IBaseResource childLocation :
+ childLocationBundle.getResources(0, childLocationBundle.size())) {
+ Location childLocationEntity = (Location) childLocation;
+ allLocations.add(childLocationEntity);
+ allLocations.addAll(descendants(childLocation.getIdElement().getIdPartAsLong(), null));
+ }
+ return allLocations;
+ }
+
+ public void setLocationIFhirResourceDao(IFhirResourceDao locationIFhirResourceDao) {
+ this.locationIFhirResourceDao = locationIFhirResourceDao;
+ }
+}
diff --git a/location/src/main/java/org/smartregister/extension/utils/Constants.java b/location/src/main/java/org/smartregister/extension/utils/Constants.java
new file mode 100644
index 0000000..dc8deda
--- /dev/null
+++ b/location/src/main/java/org/smartregister/extension/utils/Constants.java
@@ -0,0 +1,27 @@
+/*
+ * 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.extension.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";
+}
diff --git a/location/src/test/java/org/smartregister/extension/model/LocationHierarchyTreeTest.java b/location/src/test/java/org/smartregister/extension/model/LocationHierarchyTreeTest.java
new file mode 100644
index 0000000..4e129a1
--- /dev/null
+++ b/location/src/test/java/org/smartregister/extension/model/LocationHierarchyTreeTest.java
@@ -0,0 +1,250 @@
+/*
+ * 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.extension.model;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.hl7.fhir.r4.model.Location;
+import org.hl7.fhir.r4.model.Reference;
+import org.junit.Test;
+
+public class LocationHierarchyTreeTest {
+
+ @Test
+ public void testAddLocationWithoutChildLocations() {
+ Location location = new Location();
+ location.setId("Location/1");
+ location.setName("Test Location");
+ Reference partOfReference = new Reference();
+ partOfReference.setReference("");
+ location.setPartOf(partOfReference);
+ LocationHierarchyTree locationHierarchyTree = new LocationHierarchyTree();
+ locationHierarchyTree.addLocation(location);
+
+ Tree tree = locationHierarchyTree.getLocationsHierarchy();
+ assertNotNull(tree);
+ assertNotNull(tree.getTree());
+ assertEquals("Location/1", tree.getTree().getTreeNodeId().getValue());
+ assertEquals("Location/1", tree.getTree().getTreeNode().getNodeId().getValue());
+ assertEquals("Test Location", tree.getTree().getTreeNode().getLabel().getValue());
+ assertNull(tree.getTree().getTreeNode().getParent().getValue());
+ assertEquals(0, tree.getTree().getTreeNode().getChildren().size());
+ }
+
+ @Test
+ public void testBuildTreeFromList() {
+ Location location1 = new Location();
+ location1.setId("Location/1");
+ location1.setName("Test Location");
+ Reference partOfReference = new Reference();
+ partOfReference.setReference("");
+ location1.setPartOf(partOfReference);
+
+ Location location2 = new Location();
+ location2.setId("Location/2");
+ location2.setName("Test Location 2");
+ partOfReference = new Reference();
+ partOfReference.setReference("Location/1");
+ location2.setPartOf(partOfReference);
+
+ Location location3 = new Location();
+ location3.setId("Location/3");
+ location3.setName("Test Location 3");
+ partOfReference = new Reference();
+ partOfReference.setReference("Location/2");
+ location3.setPartOf(partOfReference);
+
+ LocationHierarchyTree locationHierarchyTree = new LocationHierarchyTree();
+
+ List locationList = new ArrayList<>();
+ locationList.add(location1);
+ locationList.add(location2);
+ locationList.add(location3);
+
+ locationHierarchyTree.buildTreeFromList(locationList);
+ Tree tree = locationHierarchyTree.getLocationsHierarchy();
+ assertNotNull(tree);
+ assertNotNull(tree.getTree());
+ assertEquals("Location/1", tree.getTree().getTreeNodeId().getValue());
+ assertEquals("Location/1", tree.getTree().getTreeNode().getNodeId().getValue());
+ assertEquals("Test Location", tree.getTree().getTreeNode().getLabel().getValue());
+ assertNull(tree.getTree().getTreeNode().getParent().getValue());
+ assertEquals(1, tree.getTree().getTreeNode().getChildren().size());
+
+ assertEquals(
+ "Location/2",
+ tree.getTree()
+ .getTreeNode()
+ .getChildren()
+ .get(0)
+ .getChildren()
+ .getNodeId()
+ .getValue());
+ assertEquals(
+ "Test Location 2",
+ tree.getTree()
+ .getTreeNode()
+ .getChildren()
+ .get(0)
+ .getChildren()
+ .getLabel()
+ .getValue());
+ assertNotNull(
+ tree.getTree()
+ .getTreeNode()
+ .getChildren()
+ .get(0)
+ .getChildren()
+ .getParent()
+ .getValue());
+ assertEquals(
+ "Location/1",
+ tree.getTree()
+ .getTreeNode()
+ .getChildren()
+ .get(0)
+ .getChildren()
+ .getParent()
+ .getValue());
+ assertEquals(
+ 1,
+ tree.getTree()
+ .getTreeNode()
+ .getChildren()
+ .get(0)
+ .getChildren()
+ .getChildren()
+ .size());
+
+ assertEquals(
+ "Location/3",
+ tree.getTree()
+ .getTreeNode()
+ .getChildren()
+ .get(0)
+ .getChildren()
+ .getChildren()
+ .get(0)
+ .getChildren()
+ .getNodeId()
+ .getValue());
+ assertEquals(
+ "Test Location 3",
+ tree.getTree()
+ .getTreeNode()
+ .getChildren()
+ .get(0)
+ .getChildren()
+ .getChildren()
+ .get(0)
+ .getChildren()
+ .getLabel()
+ .getValue());
+ assertNotNull(
+ tree.getTree()
+ .getTreeNode()
+ .getChildren()
+ .get(0)
+ .getChildren()
+ .getChildren()
+ .get(0)
+ .getChildren()
+ .getParent()
+ .getValue());
+ assertEquals(
+ "Location/2",
+ tree.getTree()
+ .getTreeNode()
+ .getChildren()
+ .get(0)
+ .getChildren()
+ .getChildren()
+ .get(0)
+ .getChildren()
+ .getParent()
+ .getValue());
+ assertEquals(
+ 0,
+ tree.getTree()
+ .getTreeNode()
+ .getChildren()
+ .get(0)
+ .getChildren()
+ .getChildren()
+ .get(0)
+ .getChildren()
+ .getChildren()
+ .size());
+
+ assertNotNull(locationHierarchyTree.getLocationsHierarchy().getParentChildren());
+ assertEquals(2, locationHierarchyTree.getLocationsHierarchy().getParentChildren().size());
+ assertEquals(
+ "Location/1",
+ locationHierarchyTree
+ .getLocationsHierarchy()
+ .getParentChildren()
+ .get(0)
+ .getIdentifier()
+ .getValue());
+ assertEquals(
+ 1,
+ locationHierarchyTree
+ .getLocationsHierarchy()
+ .getParentChildren()
+ .get(0)
+ .getChildIdentifiers()
+ .size());
+ assertEquals(
+ "Location/2",
+ locationHierarchyTree
+ .getLocationsHierarchy()
+ .getParentChildren()
+ .get(0)
+ .getChildIdentifiers()
+ .get(0)
+ .getValue());
+
+ assertEquals(
+ "Location/2",
+ locationHierarchyTree
+ .getLocationsHierarchy()
+ .getParentChildren()
+ .get(1)
+ .getIdentifier()
+ .getValue());
+ assertEquals(
+ 1,
+ locationHierarchyTree
+ .getLocationsHierarchy()
+ .getParentChildren()
+ .get(1)
+ .getChildIdentifiers()
+ .size());
+ assertEquals(
+ "Location/3",
+ locationHierarchyTree
+ .getLocationsHierarchy()
+ .getParentChildren()
+ .get(1)
+ .getChildIdentifiers()
+ .get(0)
+ .getValue());
+ }
+}
diff --git a/src/test/java/org/smartregister/extension/model/TreeNodeTest.java b/location/src/test/java/org/smartregister/extension/model/TreeNodeTest.java
similarity index 51%
rename from src/test/java/org/smartregister/extension/model/TreeNodeTest.java
rename to location/src/test/java/org/smartregister/extension/model/TreeNodeTest.java
index f4df891..06c7b37 100644
--- a/src/test/java/org/smartregister/extension/model/TreeNodeTest.java
+++ b/location/src/test/java/org/smartregister/extension/model/TreeNodeTest.java
@@ -1,19 +1,31 @@
+/*
+ * 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.extension.model;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+
import org.hl7.fhir.r4.model.Location;
import org.hl7.fhir.r4.model.StringType;
import org.junit.Test;
-import java.util.HashMap;
-import java.util.Map;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNull;
-
public class TreeNodeTest {
- @Test
- public void testAddingChild() {
+ @Test
+ public void testAddingChild() {
StringType rootNodeName = new StringType();
rootNodeName.setValue("Root Node");
@@ -36,16 +48,21 @@ public void testAddingChild() {
StringType childNodeLabel = new StringType();
childNodeLabel.setValue("Child Location Node");
- TreeNode rootNode = new TreeNode(rootNodeName, rootNodeId, rootNodeLabel, location, null);
- TreeNode childNode = new TreeNode(childNodeName, childNodeId, childNodeLabel, location, rootNodeId);
- rootNode.addChild(childNode);
-
- assertEquals(childNodeId.getValue(), rootNode.findChild(childNodeId.getValue()).getNodeId().getValue());
- assertEquals(rootNodeId.getValue(), rootNode.findChild(childNodeId.getValue()).getParent().getValue());
- }
-
- @Test
- public void findInvalidChildren() {
+ TreeNode rootNode = new TreeNode(rootNodeName, rootNodeId, rootNodeLabel, location, null);
+ TreeNode childNode =
+ new TreeNode(childNodeName, childNodeId, childNodeLabel, location, rootNodeId);
+ rootNode.addChild(childNode);
+
+ assertEquals(
+ childNodeId.getValue(),
+ rootNode.findChild(childNodeId.getValue()).getNodeId().getValue());
+ assertEquals(
+ rootNodeId.getValue(),
+ rootNode.findChild(childNodeId.getValue()).getParent().getValue());
+ }
+
+ @Test
+ public void findInvalidChildren() {
StringType rootNodeName = new StringType();
rootNodeName.setValue("Root Node");
@@ -59,7 +76,7 @@ public void findInvalidChildren() {
location.setId("Location/1");
TreeNode rootNode = new TreeNode(rootNodeName, rootNodeId, rootNodeLabel, location, null);
- assertEquals(0, rootNode.getChildren().size());
- assertNull(rootNode.findChild("Location/2"));
- }
+ assertEquals(0, rootNode.getChildren().size());
+ assertNull(rootNode.findChild("Location/2"));
+ }
}
diff --git a/location/src/test/java/org/smartregister/extension/model/TreeTest.java b/location/src/test/java/org/smartregister/extension/model/TreeTest.java
new file mode 100644
index 0000000..2f59d3d
--- /dev/null
+++ b/location/src/test/java/org/smartregister/extension/model/TreeTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.extension.model;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
+
+import org.hl7.fhir.r4.model.Location;
+import org.junit.Test;
+
+public class TreeTest {
+
+ @Test
+ public void testAddingNodeWithOutParent() {
+ Tree tree = new Tree();
+ Location location = new Location();
+ location.setId("testId");
+ tree.addNode("Location/1", "test", location, null);
+
+ TreeNode treeNode = tree.getNode("Location/1");
+
+ assertEquals("Location/1", treeNode.getNodeId().getValue());
+ assertEquals("test", treeNode.getLabel().getValue());
+ assertEquals(location, treeNode.getNode());
+ assertNull(treeNode.getParent().getValue());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCannotReAddExistingNode() {
+ Tree tree = new Tree();
+ Location location = new Location();
+ location.setId("testId");
+ tree.addNode("Location/1", "test", location, null);
+ tree.addNode("Location/1", "test", location, null);
+ }
+
+ @Test
+ public void testAddingNodeWithValidParent() {
+ Tree tree = new Tree();
+ Location location = new Location();
+ location.setId("testId");
+ tree.addNode("Location/1", "test", location, null);
+ tree.addNode("Location/2", "test2", location, "Location/1");
+
+ TreeNode childNode = tree.getNode("Location/2");
+
+ assertEquals("Location/2", childNode.getNodeId().getValue());
+ assertEquals("test2", childNode.getLabel().getValue());
+ assertEquals(location, childNode.getNode());
+ assertNotNull(childNode.getParent().getValue());
+
+ String parentNodeId = childNode.getParent().getValue();
+
+ assertEquals("Location/1", parentNodeId);
+ }
+}
diff --git a/pom.xml b/pom.xml
index d1bce25..d85aceb 100755
--- a/pom.xml
+++ b/pom.xml
@@ -1,89 +1,160 @@
-
-
- 4.0.0
+
+ 4.0.0
- org.smartregister
- hapi-fhir-opensrp-extensions
- jar
- 0.0.1-SNAPSHOT
- hapi-fhir-opensrp-extensions
- This repository holds all the code extensions on top of Hapi-FHIR
- https://github.com/opensrp/hapi-fhir-opensrp-extensions
+ org.smartregister
+ hapi-fhir-opensrp-extensions
+ pom
+ 0.0.1-SNAPSHOT
+ hapi-fhir-opensrp-extensions
+ This repository holds all the code extensions on top of Hapi-FHIR
+ https://github.com/opensrp/hapi-fhir-opensrp-extensions
-
- 8
- 8
- 5.2.4.RELEASE
-
+
+ GitHub Issues
+ https://github.com/opensrp/hapi-fhir-opensrp-extensions/issues
+
+ 2021
-
-
- nexus-snapshots
- Nexus Snapshots Repository
- https://oss.sonatype.org/content/repositories/snapshots
- false
-
-
- nexus-releases
- https://oss.sonatype.org/service/local/staging/deploy/maven2
-
-
+
+
+ nexus-releases
+ https://oss.sonatype.org/service/local/staging/deploy/maven2
+
+
+ nexus-snapshots
+ Nexus Snapshots Repository
+ false
+ https://oss.sonatype.org/content/repositories/snapshots
+
+
-
-
- org.springframework
- spring-web
- ${spring.version}
-
+
+ 8
+ 8
+ 5.2.4.RELEASE
+ 2.13.0
+ 2.5
+ 5.4.0
+ 4.13.1
+
-
- org.springframework
- spring-jdbc
- ${spring.version}
-
-
-
- javax.servlet
- servlet-api
- 2.5
- provided
-
+
+ location
+
-
-
- ca.uhn.hapi.fhir
- hapi-fhir-base
- 5.4.0
-
+
+
+ spring-web
+ org.springframework
+ ${spring.version}
+
-
-
- ca.uhn.hapi.fhir
- hapi-fhir-jpaserver-base
- 5.4.0
-
-
- org.springframework
- spring-jcl
-
-
- commons-logging
- commons-logging
-
-
-
+
+ spring-jdbc
+ org.springframework
+ ${spring.version}
+
+
+
+ servlet-api
+ javax.servlet
+ provided
+ ${servlet.version}
+
-
-
- junit
- junit
- 4.13.1
- test
-
+
+
+ hapi-fhir-base
+ ca.uhn.hapi.fhir
+ ${hapi.fhir.base.version}
+
-
+
+
+ com.diffplug.spotless
+ spotless-maven-plugin
+ ${spotless.version}
+
+
+
+ hapi-fhir-jpaserver-base
+
+
+ spring-jcl
+ org.springframework
+
+
+ commons-logging
+ commons-logging
+
+
+ ca.uhn.hapi.fhir
+ 5.4.0
+
+
+
+ junit
+ junit
+ test
+ ${junit.version}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+
+ 1.8
+ true
+ UTF-8
+
+
+
+ com.diffplug.spotless
+ spotless-maven-plugin
+ ${spotless.version}
+
+
+
+ check
+
+ compile
+
+
+
+
+
+
+ *.factories
+ *.xml
+ .gitignore
+
+
+
+
+ true
+ 4
+
+
+
+
+
+ 1.8
+
+
+
+ ${basedir}/src/license-header.txt
+
+
+
+
+
+
diff --git a/src/main/java/org/smartregister/extension/model/ChildTreeNode.java b/src/main/java/org/smartregister/extension/model/ChildTreeNode.java
deleted file mode 100755
index e6d3f4f..0000000
--- a/src/main/java/org/smartregister/extension/model/ChildTreeNode.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.smartregister.extension.model;
-
-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/extension/model/LocationHierarchy.java b/src/main/java/org/smartregister/extension/model/LocationHierarchy.java
deleted file mode 100755
index e4a5c59..0000000
--- a/src/main/java/org/smartregister/extension/model/LocationHierarchy.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.smartregister.extension.model;
-
-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/extension/model/LocationHierarchyTree.java b/src/main/java/org/smartregister/extension/model/LocationHierarchyTree.java
deleted file mode 100755
index 5a73778..0000000
--- a/src/main/java/org/smartregister/extension/model/LocationHierarchyTree.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package org.smartregister.extension.model;
-
-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.thymeleaf.util.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/extension/model/ParentChildrenMap.java b/src/main/java/org/smartregister/extension/model/ParentChildrenMap.java
deleted file mode 100755
index fc40c69..0000000
--- a/src/main/java/org/smartregister/extension/model/ParentChildrenMap.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package org.smartregister.extension.model;
-
-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/extension/model/SingleTreeNode.java b/src/main/java/org/smartregister/extension/model/SingleTreeNode.java
deleted file mode 100755
index b0f6392..0000000
--- a/src/main/java/org/smartregister/extension/model/SingleTreeNode.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.smartregister.extension.model;
-
-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/extension/model/Tree.java b/src/main/java/org/smartregister/extension/model/Tree.java
deleted file mode 100755
index 9dde450..0000000
--- a/src/main/java/org/smartregister/extension/model/Tree.java
+++ /dev/null
@@ -1,243 +0,0 @@
-package org.smartregister.extension.model;
-
-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.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-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.*;
-
-import static org.smartregister.extension.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 = LogManager.getLogger(Tree.class.toString());
-
- 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
- && listOfNodes.getTreeNode().getChildren() != null) {
- return recursivelyFindNode(idString, listOfNodes.getTreeNode().getChildren());
- }
- }
- 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();
- }
-
- private TreeNode recursivelyFindNode(String idString, List childTreeNodeList) {
- for (ChildTreeNode childTreeNode : childTreeNodeList) {
- TreeNode treeNode = childTreeNode.getChildren();
- if (treeNode != null && treeNode.getNodeId() != null && StringUtils.isNotBlank(treeNode.getNodeId().getValue()) &&
- treeNode.getNodeId().getValue().equals(idString)) {
- return treeNode;
- } else {
- if (treeNode != null && treeNode.getChildren() != null && treeNode.getChildren().size() > 0) {
- return recursivelyFindNode(idString, treeNode.getChildren());
- }
- }
- }
- return null;
- }
-
-}
diff --git a/src/main/java/org/smartregister/extension/model/TreeNode.java b/src/main/java/org/smartregister/extension/model/TreeNode.java
deleted file mode 100755
index 95fc4c3..0000000
--- a/src/main/java/org/smartregister/extension/model/TreeNode.java
+++ /dev/null
@@ -1,175 +0,0 @@
-package org.smartregister.extension.model;
-
-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.LinkedHashMap;
-import java.util.List;
-
-import static org.smartregister.extension.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/extension/rest/LocationHierarchyResourceProvider.java b/src/main/java/org/smartregister/extension/rest/LocationHierarchyResourceProvider.java
deleted file mode 100755
index 4a9ed37..0000000
--- a/src/main/java/org/smartregister/extension/rest/LocationHierarchyResourceProvider.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package org.smartregister.extension.rest;
-
-import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
-import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
-import ca.uhn.fhir.rest.annotation.*;
-import ca.uhn.fhir.rest.api.server.IBundleProvider;
-import ca.uhn.fhir.rest.param.*;
-import ca.uhn.fhir.rest.server.IResourceProvider;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.smartregister.extension.model.LocationHierarchy;
-import org.smartregister.extension.model.LocationHierarchyTree;
-import org.hl7.fhir.instance.model.api.IBaseResource;
-import org.hl7.fhir.r4.model.*;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import java.util.*;
-
-import static org.smartregister.extension.utils.Constants.*;
-
-public class LocationHierarchyResourceProvider implements IResourceProvider {
-
- @Autowired
- IFhirResourceDao locationIFhirResourceDao;
-
- private static Logger logger = LogManager.getLogger(LocationHierarchyResourceProvider.class.toString());
-
- @Override
- public Class extends IBaseResource> getResourceType() {
- return LocationHierarchy.class;
- }
-
- @Search
- public LocationHierarchy getLocationHierarchy(@RequiredParam(name = IDENTIFIER) TokenParam identifier) {
-
- SearchParameterMap paramMap = new SearchParameterMap();
- paramMap.add(IDENTIFIER, identifier);
-
- IBundleProvider locationBundle = locationIFhirResourceDao.search(paramMap);
- List locations = locationBundle != null ?
- locationBundle.getResources(0, locationBundle.size()) : new ArrayList<>();
- Long id = null;
- if (locations.size() > 0) {
- id = locations.get(0) != null && locations.get(0).getIdElement() != null ? locations.get(0).getIdElement().getIdPartAsLong() : null;
- }
-
- LocationHierarchyTree locationHierarchyTree = new LocationHierarchyTree();
- LocationHierarchy locationHierarchy = new LocationHierarchy();
- if (id != null && locations.size() > 0) {
- logger.info("Building Location Hierarchy of Location Id : " + id);
- locationHierarchyTree.buildTreeFromList(getLocationHierarchy(id, locations.get(0)));
- StringType locationIdString = new StringType().setId(id.toString()).getIdElement();
- locationHierarchy.setLocationId(locationIdString);
- locationHierarchy.setId(LOCATION_RESOURCE + id);
-
- locationHierarchy.setLocationHierarchyTree(locationHierarchyTree);
- } else {
- locationHierarchy.setId(LOCATION_RESOURCE_NOT_FOUND);
- }
- return locationHierarchy;
-
- }
-
- private List getLocationHierarchy(Long id, IBaseResource parentLocation) {
- return descendants(id, parentLocation);
- }
-
- public List descendants(Long id, IBaseResource parentLocation) {
-
- SearchParameterMap paramMap = new SearchParameterMap();
- ReferenceAndListParam thePartOf = new ReferenceAndListParam();
- ReferenceParam partOf = new ReferenceParam();
- partOf.setValue(LOCATION + FORWARD_SLASH + id);
- ReferenceOrListParam referenceOrListParam = new ReferenceOrListParam();
- referenceOrListParam.add(partOf);
- thePartOf.addValue(referenceOrListParam);
- paramMap.add(PART_OF, thePartOf);
-
- IBundleProvider childLocationBundle = locationIFhirResourceDao.search(paramMap);
- List allLocations = new ArrayList<>();
- if (parentLocation != null) {
- allLocations.add((Location) parentLocation);
- }
- for (IBaseResource childLocation : childLocationBundle.getResources(0, childLocationBundle.size())) {
- Location childLocationEntity = (Location) childLocation;
- allLocations.add(childLocationEntity);
- allLocations.addAll(descendants(childLocation.getIdElement().getIdPartAsLong(), null));
- }
- return allLocations;
- }
-
- public void setLocationIFhirResourceDao(IFhirResourceDao locationIFhirResourceDao) {
- this.locationIFhirResourceDao = locationIFhirResourceDao;
- }
-}
diff --git a/src/main/java/org/smartregister/extension/utils/Constants.java b/src/main/java/org/smartregister/extension/utils/Constants.java
deleted file mode 100644
index eaf35a6..0000000
--- a/src/main/java/org/smartregister/extension/utils/Constants.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.smartregister.extension.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";
-}
diff --git a/src/test/java/org/smartregister/extension/model/LocationHierarchyTreeTest.java b/src/test/java/org/smartregister/extension/model/LocationHierarchyTreeTest.java
deleted file mode 100644
index fdb4bee..0000000
--- a/src/test/java/org/smartregister/extension/model/LocationHierarchyTreeTest.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package org.smartregister.extension.model;
-
-import ca.uhn.fhir.rest.param.ReferenceParam;
-import org.hl7.fhir.r4.model.Location;
-import org.hl7.fhir.r4.model.Reference;
-import org.junit.Test;
-
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNull;
-import static org.junit.Assert.assertNotNull;
-
-public class LocationHierarchyTreeTest {
-
- @Test
- public void testAddLocationWithoutChildLocations() {
- Location location = new Location();
- location.setId("Location/1");
- location.setName("Test Location");
- Reference partOfReference = new Reference();
- partOfReference.setReference("");
- location.setPartOf(partOfReference);
- LocationHierarchyTree locationHierarchyTree = new LocationHierarchyTree();
- locationHierarchyTree.addLocation(location);
-
- Tree tree = locationHierarchyTree.getLocationsHierarchy();
- assertNotNull(tree);
- assertNotNull(tree.getTree());
- assertEquals("Location/1", tree.getTree().getTreeNodeId().getValue());
- assertEquals("Location/1", tree.getTree().getTreeNode().getNodeId().getValue());
- assertEquals("Test Location", tree.getTree().getTreeNode().getLabel().getValue());
- assertNull(tree.getTree().getTreeNode().getParent().getValue());
- assertEquals(0, tree.getTree().getTreeNode().getChildren().size());
- }
-
- @Test
- public void testBuildTreeFromList() {
- Location location1 = new Location();
- location1.setId("Location/1");
- location1.setName("Test Location");
- Reference partOfReference = new Reference();
- partOfReference.setReference("");
- location1.setPartOf(partOfReference);
-
- Location location2 = new Location();
- location2.setId("Location/2");
- location2.setName("Test Location 2");
- partOfReference = new Reference();
- partOfReference.setReference("Location/1");
- location2.setPartOf(partOfReference);
-
- Location location3 = new Location();
- location3.setId("Location/3");
- location3.setName("Test Location 3");
- partOfReference = new Reference();
- partOfReference.setReference("Location/2");
- location3.setPartOf(partOfReference);
-
- LocationHierarchyTree locationHierarchyTree = new LocationHierarchyTree();
-
- List locationList = new ArrayList<>();
- locationList.add(location1);
- locationList.add(location2);
- locationList.add(location3);
-
- locationHierarchyTree.buildTreeFromList(locationList);
- Tree tree = locationHierarchyTree.getLocationsHierarchy();
- assertNotNull(tree);
- assertNotNull(tree.getTree());
- assertEquals("Location/1", tree.getTree().getTreeNodeId().getValue());
- assertEquals("Location/1", tree.getTree().getTreeNode().getNodeId().getValue());
- assertEquals("Test Location", tree.getTree().getTreeNode().getLabel().getValue());
- assertNull(tree.getTree().getTreeNode().getParent().getValue());
- assertEquals(1, tree.getTree().getTreeNode().getChildren().size());
-
- assertEquals("Location/2", tree.getTree().getTreeNode().getChildren().get(0).getChildren().getNodeId().getValue());
- assertEquals("Test Location 2", tree.getTree().getTreeNode().getChildren().get(0).getChildren().getLabel().getValue());
- assertNotNull(tree.getTree().getTreeNode().getChildren().get(0).getChildren().getParent().getValue());
- assertEquals("Location/1", tree.getTree().getTreeNode().getChildren().get(0).getChildren().getParent().getValue());
- assertEquals(1, tree.getTree().getTreeNode().getChildren().get(0).getChildren().getChildren().size());
-
- assertEquals("Location/3", tree.getTree().getTreeNode().getChildren().get(0).getChildren().getChildren().get(0).getChildren().getNodeId().getValue());
- assertEquals("Test Location 3", tree.getTree().getTreeNode().getChildren().get(0).getChildren().getChildren().get(0).getChildren().getLabel().getValue());
- assertNotNull(tree.getTree().getTreeNode().getChildren().get(0).getChildren().getChildren().get(0).getChildren().getParent().getValue());
- assertEquals("Location/2", tree.getTree().getTreeNode().getChildren().get(0).getChildren().getChildren().get(0).getChildren().getParent().getValue());
- assertEquals(0, tree.getTree().getTreeNode().getChildren().get(0).getChildren().getChildren().get(0).getChildren().getChildren().size());
-
- assertNotNull(locationHierarchyTree.getLocationsHierarchy().getParentChildren());
- assertEquals(2, locationHierarchyTree.getLocationsHierarchy().getParentChildren().size());
- assertEquals("Location/1", locationHierarchyTree.getLocationsHierarchy().getParentChildren().get(0).getIdentifier().getValue());
- assertEquals(1, locationHierarchyTree.getLocationsHierarchy().getParentChildren().get(0).getChildIdentifiers().size());
- assertEquals("Location/2", locationHierarchyTree.getLocationsHierarchy().getParentChildren().get(0).getChildIdentifiers().get(0).getValue());
-
- assertEquals("Location/2", locationHierarchyTree.getLocationsHierarchy().getParentChildren().get(1).getIdentifier().getValue());
- assertEquals(1, locationHierarchyTree.getLocationsHierarchy().getParentChildren().get(1).getChildIdentifiers().size());
- assertEquals("Location/3", locationHierarchyTree.getLocationsHierarchy().getParentChildren().get(1).getChildIdentifiers().get(0).getValue());
-
-
- }
-
-}
diff --git a/src/test/java/org/smartregister/extension/model/TreeTest.java b/src/test/java/org/smartregister/extension/model/TreeTest.java
deleted file mode 100644
index 00cf9cb..0000000
--- a/src/test/java/org/smartregister/extension/model/TreeTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.smartregister.extension.model;
-
-
-import org.hl7.fhir.r4.model.Location;
-import org.junit.Test;
-
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNull;
-import static org.junit.Assert.assertNotNull;
-
-public class TreeTest {
-
- @Test
- public void testAddingNodeWithOutParent() {
- Tree tree = new Tree();
- Location location = new Location();
- location.setId("testId");
- tree.addNode("Location/1", "test", location, null);
-
- TreeNode treeNode = tree.getNode("Location/1");
-
- assertEquals("Location/1", treeNode.getNodeId().getValue());
- assertEquals("test", treeNode.getLabel().getValue());
- assertEquals(location, treeNode.getNode());
- assertNull(treeNode.getParent().getValue());
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testCannotReAddExistingNode() {
- Tree tree = new Tree();
- Location location = new Location();
- location.setId("testId");
- tree.addNode("Location/1", "test", location, null);
- tree.addNode("Location/1", "test", location, null);
- }
-
- @Test
- public void testAddingNodeWithValidParent() {
- Tree tree = new Tree();
- Location location = new Location();
- location.setId("testId");
- tree.addNode("Location/1", "test", location, null);
- tree.addNode("Location/2", "test2", location, "Location/1");
-
- TreeNode childNode = tree.getNode("Location/2");
-
- assertEquals("Location/2", childNode.getNodeId().getValue());
- assertEquals("test2", childNode.getLabel().getValue());
- assertEquals(location, childNode.getNode());
- assertNotNull(childNode.getParent().getValue());
-
- String parentNodeId = childNode.getParent().getValue();
-
- assertEquals("Location/1", parentNodeId);
- }
-}