From a18f28ca129146c654ee9f2bc02d63ce00da9543 Mon Sep 17 00:00:00 2001
From: dhaura <dhaurapathirana@gmail.com>
Date: Thu, 21 Nov 2024 13:59:29 +0530
Subject: [PATCH 01/18] Introduce organization resource hierarchy traverse
 service with the resource resolver.

---
 .../pom.xml                                   | 207 ++++++++++++++++++
 .../service/OrgResourceResolverService.java   |  63 ++++++
 .../OrgResourceResolverServiceImpl.java       | 102 +++++++++
 ...OrgResourceHierarchyTraverseConstants.java |  75 +++++++
 .../exception/NotImplementedException.java    |  48 ++++
 ...ourceHierarchyTraverseClientException.java | 127 +++++++++++
 ...OrgResourceHierarchyTraverseException.java | 132 +++++++++++
 ...ourceHierarchyTraverseServerException.java |  95 ++++++++
 ...urceHierarchyTraverseServiceComponent.java | 104 +++++++++
 ...rceHierarchyTraverseServiceDataHolder.java |  90 ++++++++
 .../service/strategy/AggregationStrategy.java |  66 ++++++
 .../FirstFoundAggregationStrategy.java        |  81 +++++++
 .../strategy/MergeAllAggregationStrategy.java | 103 +++++++++
 .../OrgResourceHierarchyTraverseUtil.java     | 105 +++++++++
 .../src/test/resources/testng.xml             |  26 +++
 .../pom.xml                                   |   5 +
 pom.xml                                       |   9 +-
 17 files changed, 1437 insertions(+), 1 deletion(-)
 create mode 100644 components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml
 create mode 100644 components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverService.java
 create mode 100644 components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceImpl.java
 create mode 100644 components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/constant/OrgResourceHierarchyTraverseConstants.java
 create mode 100644 components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/NotImplementedException.java
 create mode 100644 components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseClientException.java
 create mode 100644 components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseException.java
 create mode 100644 components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseServerException.java
 create mode 100644 components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceComponent.java
 create mode 100644 components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceDataHolder.java
 create mode 100644 components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/AggregationStrategy.java
 create mode 100644 components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/FirstFoundAggregationStrategy.java
 create mode 100644 components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/MergeAllAggregationStrategy.java
 create mode 100644 components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/util/OrgResourceHierarchyTraverseUtil.java
 create mode 100644 components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/resources/testng.xml

diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml
new file mode 100644
index 000000000..cbc3867f8
--- /dev/null
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml
@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+  ~
+  ~ WSO2 LLC. licenses this file to you 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <parent>
+        <groupId>org.wso2.carbon.identity.organization.management</groupId>
+        <artifactId>identity-organization-management</artifactId>
+        <version>1.4.53</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service</artifactId>
+    <name>WSO2 - Organization Resource Hierarchy Traverse Service</name>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.wso2.carbon</groupId>
+            <artifactId>org.wso2.carbon.utils</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-collections.wso2</groupId>
+            <artifactId>commons-collections</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.logging</groupId>
+            <artifactId>pax-logging-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.wso2.carbon.identity.framework</groupId>
+            <artifactId>org.wso2.carbon.identity.application.mgt</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.wso2.carbon.identity.organization.management.core</groupId>
+            <artifactId>org.wso2.carbon.identity.organization.management.service</artifactId>
+        </dependency>
+
+        <!-- Test dependencies -->
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jacoco</groupId>
+            <artifactId>org.jacoco.agent</artifactId>
+            <classifier>runtime</classifier>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-inline</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+                        <Bundle-Name>${project.artifactId}</Bundle-Name>
+                        <Private-Package>
+                            org.wso2.carbon.identity.organization.resource.hierarchy.traverse.internal
+                        </Private-Package>
+                        <Import-Package>
+                            org.apache.commons.lang; version="${org.apache.commons.lang.imp.pkg.version.range}",
+                            org.apache.commons.logging; version="${org.apache.commons.logging.imp.pkg.version.range}",
+                            org.apache.commons.collections; version="${org.apache.commons.collections.imp.pkg.version.range}",
+
+                            org.osgi.framework; version="${osgi.framework.imp.pkg.version.range}",
+                            org.osgi.service.component; version="${osgi.service.component.imp.pkg.version.range}",
+
+                            org.wso2.carbon.identity.application.mgt;
+                            version="${carbon.identity.package.import.version.range}",
+                            org.wso2.carbon.identity.application.common;
+                            version="${carbon.identity.package.import.version.range}",
+
+                            org.wso2.carbon.identity.organization.management.service;
+                            version="${org.wso2.identity.organization.mgt.core.imp.pkg.version.range}",
+                            org.wso2.carbon.identity.organization.management.service.exception;
+                            version="${org.wso2.identity.organization.mgt.core.imp.pkg.version.range}",
+                            org.wso2.carbon.identity.organization.management.service.util;
+                            version="${org.wso2.identity.organization.mgt.core.imp.pkg.version.range}"
+                        </Import-Package>
+                        <Export-Package>
+                            !org.wso2.carbon.identity.organization.resource.hierarchy.traverse.internal,
+                            org.wso2.carbon.identity.organization.resource.hierarchy.traverse.*;
+                            version="${project.version}"
+                        </Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-checkstyle-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>${maven.surefire.plugin.version}</version>
+                <configuration>
+                    <!--suppress UnresolvedMavenProperty -->
+                    <argLine>
+                        ${argLine}
+                        --add-opens java.xml/jdk.xml.internal=ALL-UNNAMED
+                        --add-opens=java.base/jdk.internal.loader=ALL-UNNAMED
+                    </argLine>
+                    <suiteXmlFiles>
+                        <suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
+                    </suiteXmlFiles>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.jacoco</groupId>
+                <artifactId>jacoco-maven-plugin</artifactId>
+                <version>${jacoco.version}</version>
+                <executions>
+                    <execution>
+                        <id>default-prepare-agent</id>
+                        <goals>
+                            <goal>prepare-agent</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>default-prepare-agent-integration</id>
+                        <goals>
+                            <goal>prepare-agent-integration</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>default-report</id>
+                        <goals>
+                            <goal>report</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>default-report-integration</id>
+                        <goals>
+                            <goal>report-integration</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>default-check</id>
+                        <goals>
+                            <goal>check</goal>
+                        </goals>
+                        <configuration>
+                            <rules>
+                                <rule implementation="org.jacoco.maven.RuleConfiguration">
+                                    <element>BUNDLE</element>
+                                    <limits>
+                                        <limit implementation="org.jacoco.report.check.Limit">
+                                            <counter>COMPLEXITY</counter>
+                                            <value>COVEREDRATIO</value>
+                                            <!--<minimum>0.60</minimum>-->
+                                        </limit>
+                                    </limits>
+                                </rule>
+                            </rules>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>com.github.spotbugs</groupId>
+                <artifactId>spotbugs-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>8</source>
+                    <target>8</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverService.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverService.java
new file mode 100644
index 000000000..604c83199
--- /dev/null
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverService.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. licenses this file to you 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.wso2.carbon.identity.organization.resource.hierarchy.traverse.service;
+
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception.OrgResourceHierarchyTraverseException;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.strategy.AggregationStrategy;
+
+import java.util.Optional;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ * Service interface for organization resource resolver.
+ */
+public interface OrgResourceResolverService {
+
+    /**
+     * Get resources from the organization hierarchy.
+     *
+     * @param organizationId      Organization ID.
+     * @param resourceRetriever   Function to retrieve the resource.
+     * @param aggregationStrategy Aggregation strategy.
+     * @param <T>                 Type of the resource.
+     * @return Resolved resources.
+     * @throws OrgResourceHierarchyTraverseException If an error occurs while retrieving the resources.
+     */
+    <T> T getResourcesFromOrgHierarchy(String organizationId,
+                                       Function<String, Optional<T>> resourceRetriever,
+                                       AggregationStrategy<T> aggregationStrategy)
+            throws OrgResourceHierarchyTraverseException;
+
+    /**
+     * Get resources from the organization and application hierarchy.
+     *
+     * @param organizationId      Organization ID.
+     * @param applicationId       Application ID.
+     * @param resourceRetriever   Function to retrieve the resource.
+     * @param aggregationStrategy Aggregation strategy.
+     * @param <T>                 Type of the resource.
+     * @return Resolved resources.
+     * @throws OrgResourceHierarchyTraverseException If an error occurs while retrieving the resources.
+     */
+    <T> T getResourcesFromOrgHierarchy(String organizationId, String applicationId,
+                                       BiFunction<String, String, Optional<T>> resourceRetriever,
+                                       AggregationStrategy<T> aggregationStrategy)
+            throws OrgResourceHierarchyTraverseException;
+}
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceImpl.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceImpl.java
new file mode 100644
index 000000000..c7a9a894b
--- /dev/null
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceImpl.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. licenses this file to you 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.wso2.carbon.identity.organization.resource.hierarchy.traverse.service;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException;
+import org.wso2.carbon.identity.application.mgt.ApplicationManagementService;
+import org.wso2.carbon.identity.organization.management.service.OrganizationManager;
+import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.constant.OrgResourceHierarchyTraverseConstants;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception.OrgResourceHierarchyTraverseException;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.internal.OrgResourceHierarchyTraverseServiceDataHolder;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.strategy.AggregationStrategy;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.util.OrgResourceHierarchyTraverseUtil;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ * Implementation of the OrgResourceResolverService.
+ */
+public class OrgResourceResolverServiceImpl implements OrgResourceResolverService {
+
+    @Override
+    public <T> T getResourcesFromOrgHierarchy(String organizationId, Function<String, Optional<T>> resourceRetriever,
+                                              AggregationStrategy<T> aggregationStrategy)
+            throws OrgResourceHierarchyTraverseException {
+
+        try {
+            OrganizationManager organizationManager = OrgResourceHierarchyTraverseUtil.getOrganizationManager();
+            List<String> organizationIds = organizationManager.getAncestorOrganizationIds(organizationId);
+
+            if (CollectionUtils.isEmpty(organizationIds) || organizationIds.isEmpty()) {
+                return null;
+            }
+
+            return aggregationStrategy.aggregate(organizationIds, resourceRetriever);
+        } catch (OrganizationManagementException e) {
+            throw OrgResourceHierarchyTraverseUtil.handleServerException(
+                    OrgResourceHierarchyTraverseConstants.ErrorMessages
+                            .ERROR_CODE_SERVER_ERROR_WHILE_RESOLVING_ANCESTOR_ORGANIZATIONS, e, organizationId);
+        }
+    }
+
+    @Override
+    public <T> T getResourcesFromOrgHierarchy(String organizationId, String applicationId,
+                                              BiFunction<String, String, Optional<T>> resourceRetriever,
+                                              AggregationStrategy<T> aggregationStrategy)
+            throws OrgResourceHierarchyTraverseException {
+
+        try {
+            OrganizationManager organizationManager = OrgResourceHierarchyTraverseUtil.getOrganizationManager();
+            List<String> organizationIds = organizationManager.getAncestorOrganizationIds(organizationId);
+
+            if (CollectionUtils.isEmpty(organizationIds) || organizationIds.isEmpty()) {
+                return null;
+            }
+
+            ApplicationManagementService applicationManagementService = getApplicationManagementService();
+            Map<String, String> ancestorAppIds = Collections.emptyMap();
+            if (applicationId != null) {
+                ancestorAppIds = applicationManagementService.getAncestorAppIds(applicationId, organizationId);
+            }
+
+            return aggregationStrategy.aggregate(organizationIds, ancestorAppIds, resourceRetriever);
+        } catch (OrganizationManagementException e) {
+            throw OrgResourceHierarchyTraverseUtil.handleServerException(
+                    OrgResourceHierarchyTraverseConstants.ErrorMessages
+                            .ERROR_CODE_SERVER_ERROR_WHILE_RESOLVING_ANCESTOR_ORGANIZATIONS, e, organizationId);
+        } catch (IdentityApplicationManagementException e) {
+            throw OrgResourceHierarchyTraverseUtil.handleServerException(
+                    OrgResourceHierarchyTraverseConstants.ErrorMessages
+                            .ERROR_CODE_SERVER_ERROR_WHILE_RESOLVING_ANCESTOR_APPLICATIONS,
+                    e, organizationId, applicationId);
+        }
+    }
+
+    private ApplicationManagementService getApplicationManagementService() {
+
+        return OrgResourceHierarchyTraverseServiceDataHolder.getInstance().getApplicationManagementService();
+    }
+}
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/constant/OrgResourceHierarchyTraverseConstants.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/constant/OrgResourceHierarchyTraverseConstants.java
new file mode 100644
index 000000000..ba4b09ddf
--- /dev/null
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/constant/OrgResourceHierarchyTraverseConstants.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. licenses this file to you 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.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.constant;
+
+/**
+ * Constants for organization resource hierarchy traverse service.
+ */
+public class OrgResourceHierarchyTraverseConstants {
+
+    private static final String ORGANIZATION_RESOURCE_HIERARCHY_TRAVERSE_ERROR_CODE_PREFIX = "ORHT-";
+
+    private OrgResourceHierarchyTraverseConstants() {
+
+    }
+
+    /**
+     * Enum for error messages related to organization resource hierarchy traverse service.
+     */
+    public enum ErrorMessages {
+
+        // Server errors.
+        ERROR_CODE_SERVER_ERROR_WHILE_RESOLVING_ANCESTOR_ORGANIZATIONS(
+                "65001",
+                "Unable to resolve ancestor organizations.",
+                "Unexpected server error occurred " +
+                        "while resolving ancestor organizations for organization with id: %s."),
+        ERROR_CODE_SERVER_ERROR_WHILE_RESOLVING_ANCESTOR_APPLICATIONS(
+                "65002",
+                "Unable to resolve ancestor applications.",
+                "Unexpected server error occurred while resolving ancestor applications for organization " +
+                        "with id: %s for application with id: %s.");
+
+        private final String code;
+        private final String message;
+        private final String description;
+
+        ErrorMessages(String code, String message, String description) {
+
+            this.code = code;
+            this.message = message;
+            this.description = description;
+        }
+
+        public String getCode() {
+
+            return ORGANIZATION_RESOURCE_HIERARCHY_TRAVERSE_ERROR_CODE_PREFIX + code;
+        }
+
+        public String getMessage() {
+
+            return message;
+        }
+
+        public String getDescription() {
+
+            return description;
+        }
+    }
+}
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/NotImplementedException.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/NotImplementedException.java
new file mode 100644
index 000000000..bc937175b
--- /dev/null
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/NotImplementedException.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. licenses this file to you 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.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception;
+
+/**
+ * The exception to throw when the code is not implemented.
+ */
+public class NotImplementedException extends RuntimeException {
+
+    private static final long serialVersionUID = 5117918786934510964L;
+
+    public NotImplementedException() {
+
+        super();
+    }
+
+    public NotImplementedException(String message, Throwable cause) {
+
+        super(message, cause);
+    }
+
+    public NotImplementedException(String message) {
+
+        super(message);
+    }
+
+    public NotImplementedException(Throwable cause) {
+
+        super(cause);
+    }
+
+}
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseClientException.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseClientException.java
new file mode 100644
index 000000000..00d675930
--- /dev/null
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseClientException.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. licenses this file to you 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.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Exception class for client side errors in organization resource hierarchy traverse.
+ */
+public class OrgResourceHierarchyTraverseClientException extends OrgResourceHierarchyTraverseException {
+
+    private static final long serialVersionUID = 559143944402014381L;
+
+    private String[] messages;
+
+    public OrgResourceHierarchyTraverseClientException(String[] messages) {
+
+        super(Arrays.toString(messages));
+        if (messages == null) {
+            return;
+        }
+        List<String> msgList = new ArrayList<>();
+        for (String msg : messages) {
+            if (!msg.trim().isEmpty()) {
+                msgList.add(msg);
+            }
+        }
+        this.messages = msgList.toArray(new String[0]);
+    }
+
+    /**
+     * Constructs a new exception with the specified message.
+     *
+     * @param message Detailed message
+     */
+    public OrgResourceHierarchyTraverseClientException(String message) {
+
+        super(message);
+    }
+
+    /**
+     * Constructs a new exception with the specified message and cause.
+     *
+     * @param message Detailed message
+     * @param e       Cause as {@link Throwable}
+     */
+    public OrgResourceHierarchyTraverseClientException(String message, Throwable e) {
+
+        super(message, e);
+    }
+
+    /**
+     * Constructs a new exception with the specified error code and cause.
+     *
+     * @param errorCode Error code
+     * @param message   Detailed message
+     */
+    public OrgResourceHierarchyTraverseClientException(String errorCode, String message) {
+
+        super(errorCode, message);
+    }
+
+    /**
+     * Constructs a new exception with the specified error code, message and cause.
+     *
+     * @param errorCode Error code
+     * @param message   Detailed message
+     * @param cause     Cause as {@link Throwable}
+     */
+    public OrgResourceHierarchyTraverseClientException(String errorCode, String message, Throwable cause) {
+
+        super(errorCode, message, cause);
+    }
+
+    /**
+     * Constructs a new exception with the specified error code, message and description.
+     *
+     * @param errorCode   Error code.
+     * @param message     Error message.
+     * @param description Error description.
+     */
+    public OrgResourceHierarchyTraverseClientException(String errorCode, String message, String description) {
+
+        super(errorCode, message, description);
+    }
+
+    /**
+     * Constructs a new exception with the specified error code, message, description and cause.
+     *
+     * @param errorCode   Error code
+     * @param message     Detailed message
+     * @param cause       Cause as {@link Throwable}
+     * @param description Error description.
+     */
+    public OrgResourceHierarchyTraverseClientException(String errorCode, String message, String description,
+                                                       Throwable cause) {
+
+        super(errorCode, message, description, cause);
+    }
+
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP",
+            justification = "Client exception error messages are internally generated from the server side.")
+    public String[] getMessages() {
+
+        return messages;
+    }
+}
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseException.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseException.java
new file mode 100644
index 000000000..2cc442a70
--- /dev/null
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseException.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. licenses this file to you 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.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception;
+
+/**
+ * Exception class that represents exceptions thrown upon organization resource hierarchy traverse.
+ */
+public class OrgResourceHierarchyTraverseException extends Exception {
+
+    private String errorCode;
+    private String description;
+
+    private static final long serialVersionUID = -1982152066401023165L;
+
+    /**
+     * Constructs a new exception with the specified message.
+     *
+     * @param message Detailed message
+     */
+    public OrgResourceHierarchyTraverseException(String message) {
+
+        super(message);
+    }
+
+    /**
+     * Constructs a new exception with the specified message and cause.
+     *
+     * @param message Detailed message
+     * @param e       Cause as {@link Throwable}
+     */
+    public OrgResourceHierarchyTraverseException(String message, Throwable e) {
+
+        super(message, e);
+    }
+
+    /**
+     * Constructs a new exception with the specified error code and cause.
+     *
+     * @param errorCode Error code
+     * @param message   Detailed message
+     */
+    public OrgResourceHierarchyTraverseException(String errorCode, String message) {
+
+        super(message);
+        this.errorCode = errorCode;
+    }
+
+    /**
+     * Constructs a new exception with the specified error code, message and description.
+     *
+     * @param errorCode   Error code.
+     * @param message     Error message.
+     * @param description Error description.
+     */
+    public OrgResourceHierarchyTraverseException(String errorCode, String message, String description) {
+
+        super(message);
+        this.errorCode = errorCode;
+        this.description = description;
+    }
+
+    /**
+     * Constructs a new exception with the specified error code, message and cause.
+     *
+     * @param errorCode Error code
+     * @param message   Detailed message
+     * @param cause     Cause as {@link Throwable}
+     */
+    public OrgResourceHierarchyTraverseException(String errorCode, String message, Throwable cause) {
+
+        super(message, cause);
+        this.errorCode = errorCode;
+    }
+
+    /**
+     * Constructs a new exception with the specified error code, message, description and cause.
+     *
+     * @param errorCode   Error code.
+     * @param message     Detailed message.
+     * @param cause       Cause as {@link Throwable}.
+     * @param description Error description.
+     */
+    public OrgResourceHierarchyTraverseException(String errorCode, String message, String description,
+                                                 Throwable cause) {
+
+        super(message, cause);
+        this.errorCode = errorCode;
+        this.description = description;
+    }
+
+    /**
+     * Returns the error code.
+     *
+     * @return Error code
+     */
+    public String getErrorCode() {
+
+        return errorCode;
+    }
+
+    /**
+     * This public method is required by the stub.
+     *
+     * @return Error message.
+     */
+    @Override
+    public String getMessage() {
+
+        return super.getMessage();
+    }
+
+    public String getDescription() {
+
+        return description;
+    }
+}
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseServerException.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseServerException.java
new file mode 100644
index 000000000..28f2c30b9
--- /dev/null
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseServerException.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. licenses this file to you 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.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception;
+
+/**
+ * Exception class that represents server side errors in organization resource hierarchy traverse.
+ */
+public class OrgResourceHierarchyTraverseServerException extends OrgResourceHierarchyTraverseException {
+
+    /**
+     * Constructs a new exception with the specified message.
+     *
+     * @param message Detailed message
+     */
+    public OrgResourceHierarchyTraverseServerException(String message) {
+
+        super(message);
+    }
+
+    /**
+     * Constructs a new exception with the specified message and cause.
+     *
+     * @param message Detailed message
+     * @param e       Cause as {@link Throwable}
+     */
+    public OrgResourceHierarchyTraverseServerException(String message, Throwable e) {
+
+        super(message, e);
+    }
+
+    /**
+     * Constructs a new exception with the specified error code and message.
+     *
+     * @param errorCode Error code
+     * @param message   Detailed message
+     */
+    public OrgResourceHierarchyTraverseServerException(String errorCode, String message) {
+
+        super(errorCode, message);
+    }
+
+    /**
+     * Constructs a new exception with the specified error code, message and cause.
+     *
+     * @param errorCode Error code
+     * @param message   Detailed message
+     * @param cause     Cause as {@link Throwable}
+     */
+    public OrgResourceHierarchyTraverseServerException(String errorCode, String message, Throwable cause) {
+
+        super(errorCode, message, cause);
+    }
+
+    /**
+     * Constructs a new exception with the specified error code, message and description.
+     *
+     * @param errorCode   Error code.
+     * @param message     Error message.
+     * @param description Error description.
+     */
+    public OrgResourceHierarchyTraverseServerException(String errorCode, String message, String description) {
+
+        super(errorCode, message, description);
+    }
+
+    /**
+     * Constructs a new exception with the specified error code, message, description and cause.
+     *
+     * @param errorCode   Error code.
+     * @param message     Detailed message.
+     * @param cause       Cause as {@link Throwable}.
+     * @param description Error description.
+     */
+    public OrgResourceHierarchyTraverseServerException(String errorCode, String message, String description,
+                                                       Throwable cause) {
+
+        super(errorCode, message, description, cause);
+    }
+}
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceComponent.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceComponent.java
new file mode 100644
index 000000000..109c26397
--- /dev/null
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceComponent.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. licenses this file to you 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.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.internal;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.wso2.carbon.identity.application.mgt.ApplicationManagementService;
+import org.wso2.carbon.identity.organization.management.service.OrganizationManager;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.OrgResourceResolverService;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.OrgResourceResolverServiceImpl;
+
+/**
+ * OSGi declarative services component of the organization resource hierarchy traverse service.
+ */
+@Component(
+        name = "org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service",
+        immediate = true)
+public class OrgResourceHierarchyTraverseServiceComponent {
+
+    private static final Log log = LogFactory.getLog(OrgResourceHierarchyTraverseServiceComponent.class);
+
+    @Activate
+    protected void activate(ComponentContext context) {
+
+        try {
+            BundleContext bundleContext = context.getBundleContext();
+            bundleContext.registerService(OrgResourceResolverService.class.getName(),
+                    new OrgResourceResolverServiceImpl(), null);
+            if (log.isDebugEnabled()) {
+                log.debug("OrgResourceResolverService bundle is activated successfully.");
+            }
+        } catch (Exception e) {
+            log.error("Error while activating OrgResourceResolverService bundle.", e);
+        }
+    }
+
+    @Deactivate
+    protected void deactivate(ComponentContext context) {
+
+        if (log.isDebugEnabled()) {
+            log.debug("OrgResourceResolverService bundle is deactivated");
+        }
+    }
+
+    @Reference(name = "org.wso2.carbon.identity.organization.management.service",
+            service = OrganizationManager.class,
+            cardinality = ReferenceCardinality.OPTIONAL,
+            policy = ReferencePolicy.DYNAMIC,
+            unbind = "unsetOrganizationManager")
+    protected void setOrganizationManager(OrganizationManager organizationManager) {
+
+        OrgResourceHierarchyTraverseServiceDataHolder.getInstance().setOrganizationManager(organizationManager);
+        log.debug("OrganizationManager set in OrgResourceManagementServiceComponent bundle.");
+    }
+
+    protected void unsetOrganizationManager(OrganizationManager organizationManager) {
+
+        OrgResourceHierarchyTraverseServiceDataHolder.getInstance().setOrganizationManager(null);
+        log.debug("OrganizationManager unset in OrgResourceManagementServiceComponent bundle.");
+    }
+
+    @Reference(
+            name = "org.wso2.carbon.identity.application.mgt",
+            service = ApplicationManagementService.class,
+            cardinality = ReferenceCardinality.MANDATORY,
+            policy = ReferencePolicy.DYNAMIC,
+            unbind = "unsetApplicationManagementService")
+    protected void setApplicationManagementService(ApplicationManagementService applicationManagementService) {
+
+        OrgResourceHierarchyTraverseServiceDataHolder.getInstance()
+                .setApplicationManagementService(applicationManagementService);
+        log.debug("ApplicationManagementService set in OrgResourceManagementServiceComponent bundle.");
+    }
+
+    protected void unsetApplicationManagementService(ApplicationManagementService applicationManagementService) {
+
+        OrgResourceHierarchyTraverseServiceDataHolder.getInstance().setApplicationManagementService(null);
+        log.debug("ApplicationManagementService unset in OrgResourceManagementServiceComponent bundle.");
+    }
+}
+
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceDataHolder.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceDataHolder.java
new file mode 100644
index 000000000..b4f1f58e3
--- /dev/null
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceDataHolder.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. licenses this file to you 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.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.internal;
+
+import org.wso2.carbon.identity.application.mgt.ApplicationManagementService;
+import org.wso2.carbon.identity.organization.management.service.OrganizationManager;
+
+/**
+ * This class holds the data required for the organization resource hierarchy traverse service.
+ */
+public class OrgResourceHierarchyTraverseServiceDataHolder {
+
+    private static final OrgResourceHierarchyTraverseServiceDataHolder instance =
+            new OrgResourceHierarchyTraverseServiceDataHolder();
+
+    private OrganizationManager organizationManager;
+    private ApplicationManagementService applicationManagementService;
+
+    private OrgResourceHierarchyTraverseServiceDataHolder() {
+
+    }
+
+    /**
+     * Get the instance of OrgResourceManagementServiceDataHolder.
+     *
+     * @return OrgResourceManagementServiceDataHolder instance.
+     */
+    public static OrgResourceHierarchyTraverseServiceDataHolder getInstance() {
+
+        return instance;
+    }
+
+    /**
+     * Get the organization manager.
+     *
+     * @return Organization manager.
+     */
+    public OrganizationManager getOrganizationManager() {
+
+        return organizationManager;
+    }
+
+    /**
+     * Set the organization manager.
+     *
+     * @param organizationManager Organization manager instance.
+     */
+    public void setOrganizationManager(
+            OrganizationManager organizationManager) {
+
+        this.organizationManager = organizationManager;
+    }
+
+    /**
+     * Get the application management service.
+     *
+     * @return Application management service.
+     */
+    public ApplicationManagementService getApplicationManagementService() {
+
+        return applicationManagementService;
+    }
+
+    /**
+     * Set the application management service.
+     *
+     * @param applicationManagementService Application management service instance.
+     */
+    public void setApplicationManagementService(
+            ApplicationManagementService applicationManagementService) {
+
+        this.applicationManagementService = applicationManagementService;
+    }
+}
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/AggregationStrategy.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/AggregationStrategy.java
new file mode 100644
index 000000000..ef23bddde
--- /dev/null
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/AggregationStrategy.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. licenses this file to you 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.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.strategy;
+
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception.NotImplementedException;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception.OrgResourceHierarchyTraverseException;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ * Interface for aggregation strategies.
+ *
+ * @param <T> Type of the resource to be aggregated.
+ */
+public interface AggregationStrategy<T> {
+
+    /**
+     * Aggregate resolved resources of the given organization hierarchy.
+     *
+     * @param organizationHierarchy Organization hierarchy.
+     * @param resourceRetriever     Function to retrieve the resource.
+     * @return Aggregated resource.
+     * @throws OrgResourceHierarchyTraverseException If an error occurs while aggregating the resources.
+     */
+    default T aggregate(List<String> organizationHierarchy, Function<String, Optional<T>> resourceRetriever)
+            throws OrgResourceHierarchyTraverseException {
+
+        throw new NotImplementedException("aggregate method is not implemented in " + this.getClass());
+    }
+
+    /**
+     * Aggregate resolved resources of the given organization and application hierarchy.
+     *
+     * @param organizationHierarchy Organization hierarchy.
+     * @param applicationHierarchy  Application hierarchy.
+     * @param resourceRetriever     Function to retrieve the resource.
+     * @return Aggregated resource.
+     * @throws OrgResourceHierarchyTraverseException If an error occurs while aggregating the resources.
+     */
+    default T aggregate(List<String> organizationHierarchy, Map<String, String> applicationHierarchy,
+                        BiFunction<String, String, Optional<T>> resourceRetriever)
+            throws OrgResourceHierarchyTraverseException {
+
+        throw new NotImplementedException("aggregate method is not implemented in " + this.getClass());
+    }
+}
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/FirstFoundAggregationStrategy.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/FirstFoundAggregationStrategy.java
new file mode 100644
index 000000000..3ee3120f1
--- /dev/null
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/FirstFoundAggregationStrategy.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. licenses this file to you 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.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.strategy;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception.OrgResourceHierarchyTraverseException;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.util.OrgResourceHierarchyTraverseUtil;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ * Aggregation strategy to retrieve the first found resource in the organization hierarchy.
+ *
+ * @param <T> Type of the resource.
+ */
+public class FirstFoundAggregationStrategy<T> implements AggregationStrategy<T> {
+
+    @Override
+    public T aggregate(List<String> organizationHierarchy, Function<String, Optional<T>> resourceRetriever)
+            throws OrgResourceHierarchyTraverseException {
+
+        if (CollectionUtils.isEmpty(organizationHierarchy) || organizationHierarchy.isEmpty()) {
+            return null;
+        }
+
+        for (String orgId : organizationHierarchy) {
+            if (OrgResourceHierarchyTraverseUtil.isMinOrgHierarchyDepthReached(orgId)) {
+                break;
+            }
+
+            Optional<T> resource = resourceRetriever.apply(orgId);
+            if (resource.isPresent()) {
+                return resource.get();
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public T aggregate(List<String> organizationHierarchy, Map<String, String> applicationHierarchy,
+                       BiFunction<String, String, Optional<T>> resourceRetriever)
+            throws OrgResourceHierarchyTraverseException {
+
+        if (CollectionUtils.isEmpty(organizationHierarchy) || organizationHierarchy.isEmpty()) {
+            return null;
+        }
+
+        for (String orgId : organizationHierarchy) {
+            if (OrgResourceHierarchyTraverseUtil.isMinOrgHierarchyDepthReached(orgId)) {
+                break;
+            }
+
+            String appId = applicationHierarchy.get(orgId);
+            Optional<T> resource = resourceRetriever.apply(orgId, appId);
+            if (resource.isPresent()) {
+                return resource.get();
+            }
+        }
+        return null;
+    }
+}
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/MergeAllAggregationStrategy.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/MergeAllAggregationStrategy.java
new file mode 100644
index 000000000..648acb898
--- /dev/null
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/MergeAllAggregationStrategy.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. licenses this file to you 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.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.strategy;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception.OrgResourceHierarchyTraverseException;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.util.OrgResourceHierarchyTraverseUtil;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ * Aggregation strategy to merge all resources in the organization hierarchy with the given resource merger function.
+ *
+ * @param <T> Type of the resource.
+ */
+public class MergeAllAggregationStrategy<T> implements AggregationStrategy<T> {
+
+    private final BiFunction<T, T, T> resourceMerger;
+
+    /**
+     * Constructor to initialize the aggregation strategy with the resource merger function.
+     *
+     * @param resourceMerger Resource merger function.
+     */
+    public MergeAllAggregationStrategy(BiFunction<T, T, T> resourceMerger) {
+
+        this.resourceMerger = resourceMerger;
+    }
+
+    @Override
+    public T aggregate(List<String> organizationHierarchy, Function<String, Optional<T>> resourceRetriever)
+            throws OrgResourceHierarchyTraverseException {
+
+        T aggregatedResource = null;
+        if (CollectionUtils.isEmpty(organizationHierarchy) || organizationHierarchy.isEmpty()) {
+            return aggregatedResource;
+        }
+
+        for (String orgId : organizationHierarchy) {
+            if (OrgResourceHierarchyTraverseUtil.isMinOrgHierarchyDepthReached(orgId)) {
+                break;
+            }
+
+            Optional<T> resource = resourceRetriever.apply(orgId);
+            if (resource.isPresent()) {
+                if (aggregatedResource == null) {
+                    aggregatedResource = resource.get();
+                } else {
+                    aggregatedResource = resourceMerger.apply(aggregatedResource, resource.get());
+                }
+            }
+        }
+        return aggregatedResource;
+    }
+
+    @Override
+    public T aggregate(List<String> organizationHierarchy, Map<String, String> applicationHierarchy,
+                       BiFunction<String, String, Optional<T>> resourceRetriever)
+            throws OrgResourceHierarchyTraverseException {
+
+        T aggregatedResource = null;
+        if (CollectionUtils.isEmpty(organizationHierarchy) || organizationHierarchy.isEmpty()) {
+            return aggregatedResource;
+        }
+
+        for (String orgId : organizationHierarchy) {
+            if (OrgResourceHierarchyTraverseUtil.isMinOrgHierarchyDepthReached(orgId)) {
+                break;
+            }
+
+            String appId = applicationHierarchy.get(orgId);
+            Optional<T> resource = resourceRetriever.apply(orgId, appId);
+            if (resource.isPresent()) {
+                if (aggregatedResource == null) {
+                    aggregatedResource = resource.get();
+                } else {
+                    aggregatedResource = resourceMerger.apply(aggregatedResource, resource.get());
+                }
+            }
+        }
+        return aggregatedResource;
+    }
+}
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/util/OrgResourceHierarchyTraverseUtil.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/util/OrgResourceHierarchyTraverseUtil.java
new file mode 100644
index 000000000..68adcc9d3
--- /dev/null
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/util/OrgResourceHierarchyTraverseUtil.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. licenses this file to you 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.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.util;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.wso2.carbon.identity.organization.management.service.OrganizationManager;
+import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException;
+import org.wso2.carbon.identity.organization.management.service.util.Utils;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.constant.OrgResourceHierarchyTraverseConstants;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception.OrgResourceHierarchyTraverseClientException;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception.OrgResourceHierarchyTraverseServerException;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.internal.OrgResourceHierarchyTraverseServiceDataHolder;
+
+/**
+ * Utility class for organization resource hierarchy traverse service.
+ */
+public class OrgResourceHierarchyTraverseUtil {
+
+    private OrgResourceHierarchyTraverseUtil() {
+
+    }
+
+    /**
+     * Get the organization manager.
+     *
+     * @return Organization manager.
+     */
+    public static OrganizationManager getOrganizationManager() {
+
+        return OrgResourceHierarchyTraverseServiceDataHolder.getInstance().getOrganizationManager();
+    }
+
+    /**
+     * Check whether the minimum organization hierarchy depth is reached.
+     *
+     * @param orgId Organization ID.
+     * @return True if the minimum hierarchy depth is reached.
+     * @throws OrgResourceHierarchyTraverseServerException If an error occurs while checking the hierarchy depth.
+     */
+    public static boolean isMinOrgHierarchyDepthReached(String orgId) throws
+            OrgResourceHierarchyTraverseServerException {
+
+        int minHierarchyDepth = Utils.getSubOrgStartLevel() - 1;
+        try {
+            int depthInHierarchy = getOrganizationManager().getOrganizationDepthInHierarchy(orgId);
+            return depthInHierarchy < minHierarchyDepth;
+        } catch (OrganizationManagementException e) {
+            throw new OrgResourceHierarchyTraverseServerException(
+                    "Error occurred while getting the hierarchy depth of the organization: " + orgId, e);
+        }
+    }
+
+    /**
+     * Throw an OrgResourceHierarchyTraverseClientException upon client side error while traversing organization
+     * resource hierarchy traverse.
+     *
+     * @param error The error enum.
+     * @param data  The error message data.
+     * @return OrgResourceHierarchyTraverseClientException
+     */
+    public static OrgResourceHierarchyTraverseClientException handleClientException(
+            OrgResourceHierarchyTraverseConstants.ErrorMessages error, String... data) {
+
+        String description = error.getDescription();
+        if (ArrayUtils.isNotEmpty(data)) {
+            description = String.format(description, data);
+        }
+        return new OrgResourceHierarchyTraverseClientException(error.getMessage(), description, error.getCode());
+    }
+
+    /**
+     * Throw an OrgResourceHierarchyTraverseServerException upon server side error while traversing organization
+     * resource hierarchy traverse.
+     *
+     * @param error The error enum.
+     * @param e     The error.
+     * @param data  The error message data.
+     * @return OrgResourceHierarchyTraverseServerException
+     */
+    public static OrgResourceHierarchyTraverseServerException handleServerException(
+            OrgResourceHierarchyTraverseConstants.ErrorMessages error, Throwable e, String... data) {
+
+        String description = error.getDescription();
+        if (ArrayUtils.isNotEmpty(data)) {
+            description = String.format(description, data);
+        }
+        return new OrgResourceHierarchyTraverseServerException(error.getMessage(), description, error.getCode(), e);
+    }
+}
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/resources/testng.xml b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/resources/testng.xml
new file mode 100644
index 000000000..5f83a467d
--- /dev/null
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/resources/testng.xml
@@ -0,0 +1,26 @@
+<!--
+  ~ Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+  ~
+  ~ WSO2 LLC. licenses this file to you 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.
+  -->
+
+<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
+
+<suite name="org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.suite">
+    <test name="org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.tests" preserve-order="true" parallel="false">
+        <classes>
+        </classes>
+    </test>
+</suite>
diff --git a/features/org.wso2.carbon.identity.organization.management.server.feature/pom.xml b/features/org.wso2.carbon.identity.organization.management.server.feature/pom.xml
index 0ba6c8910..4ea7efb1b 100644
--- a/features/org.wso2.carbon.identity.organization.management.server.feature/pom.xml
+++ b/features/org.wso2.carbon.identity.organization.management.server.feature/pom.xml
@@ -83,6 +83,10 @@
             <groupId>org.wso2.carbon.identity.organization.management</groupId>
             <artifactId>org.wso2.carbon.identity.organization.discovery.service</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.wso2.carbon.identity.organization.management</groupId>
+            <artifactId>org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
@@ -120,6 +124,7 @@
                                 <bundleDef>org.wso2.carbon.identity.organization.management:org.wso2.carbon.identity.organization.user.invitation.management</bundleDef>
                                 <bundleDef>org.wso2.carbon.identity.organization.management:org.wso2.carbon.identity.organization.config.service</bundleDef>
                                 <bundleDef>org.wso2.carbon.identity.organization.management:org.wso2.carbon.identity.organization.discovery.service</bundleDef>
+                                <bundleDef>org.wso2.carbon.identity.organization.management:org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service</bundleDef>
                             </bundles>
                             <importFeatures>
                                 <importFeatureDef>org.wso2.carbon.core:compatible:${carbon.kernel.feature.version}</importFeatureDef>
diff --git a/pom.xml b/pom.xml
index 0ab32ade4..3d5e203b1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -54,6 +54,7 @@
         <module>components/org.wso2.carbon.identity.organization.config.service</module>
         <module>components/org.wso2.carbon.identity.organization.discovery.service</module>
         <module>components/org.wso2.carbon.identity.organization.management.organization.user.sharing</module>
+        <module>components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service</module>
     </modules>
 
     <dependencyManagement>
@@ -186,6 +187,12 @@
                 <version>${project.version}</version>
                 <scope>provided</scope>
             </dependency>
+            <dependency>
+                <groupId>org.wso2.carbon.identity.organization.management</groupId>
+                <artifactId>org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service</artifactId>
+                <version>${project.version}</version>
+                <scope>provided</scope>
+            </dependency>
 
             <dependency>
                 <groupId>org.wso2.carbon.identity.framework</groupId>
@@ -545,7 +552,7 @@
         <carbon.multitenancy.package.import.version.range>[4.7.0,5.0.0)
         </carbon.multitenancy.package.import.version.range>
 
-        <carbon.identity.framework.version>7.3.3</carbon.identity.framework.version>
+        <carbon.identity.framework.version>7.6.15</carbon.identity.framework.version>
         <carbon.identity.package.import.version.range>[5.20.0, 8.0.0)
         </carbon.identity.package.import.version.range>
 

From 6cbaa3dc7943ad232e8b993a6a7992385f2eb974 Mon Sep 17 00:00:00 2001
From: dhaura <dhaurapathirana@gmail.com>
Date: Thu, 21 Nov 2024 14:05:53 +0530
Subject: [PATCH 02/18] Fix traverse service pom version.

---
 .../pom.xml                                                     | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml
index cbc3867f8..cd44a8942 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.wso2.carbon.identity.organization.management</groupId>
         <artifactId>identity-organization-management</artifactId>
-        <version>1.4.53</version>
+        <version>1.4.56-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
 

From 28341aac52dda7e533936bd48113be269347983f Mon Sep 17 00:00:00 2001
From: dhaura <dhaurapathirana@gmail.com>
Date: Thu, 21 Nov 2024 19:32:36 +0530
Subject: [PATCH 03/18] Improve bundle packaging and extract ancestor org
 retrieval to a private method.

---
 .../pom.xml                                       | 12 +++++++++---
 .../service/OrgResourceResolverServiceImpl.java   | 15 +++++++++------
 2 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml
index cd44a8942..582ed4bf8 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml
@@ -89,7 +89,9 @@
                         <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
                         <Bundle-Name>${project.artifactId}</Bundle-Name>
                         <Private-Package>
-                            org.wso2.carbon.identity.organization.resource.hierarchy.traverse.internal
+                            org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.constant,
+                            org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.internal,
+                            org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.util
                         </Private-Package>
                         <Import-Package>
                             org.apache.commons.lang; version="${org.apache.commons.lang.imp.pkg.version.range}",
@@ -112,8 +114,12 @@
                             version="${org.wso2.identity.organization.mgt.core.imp.pkg.version.range}"
                         </Import-Package>
                         <Export-Package>
-                            !org.wso2.carbon.identity.organization.resource.hierarchy.traverse.internal,
-                            org.wso2.carbon.identity.organization.resource.hierarchy.traverse.*;
+                            !org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.constant,
+                            !org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.internal,
+                            !org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.util,
+                            org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service,
+                            org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception,
+                            org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.strategy;
                             version="${project.version}"
                         </Export-Package>
                     </instructions>
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceImpl.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceImpl.java
index c7a9a894b..c41fd5997 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceImpl.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceImpl.java
@@ -47,9 +47,7 @@ public <T> T getResourcesFromOrgHierarchy(String organizationId, Function<String
             throws OrgResourceHierarchyTraverseException {
 
         try {
-            OrganizationManager organizationManager = OrgResourceHierarchyTraverseUtil.getOrganizationManager();
-            List<String> organizationIds = organizationManager.getAncestorOrganizationIds(organizationId);
-
+            List<String> organizationIds = getAncestorOrganizationsIds(organizationId);
             if (CollectionUtils.isEmpty(organizationIds) || organizationIds.isEmpty()) {
                 return null;
             }
@@ -69,9 +67,7 @@ public <T> T getResourcesFromOrgHierarchy(String organizationId, String applicat
             throws OrgResourceHierarchyTraverseException {
 
         try {
-            OrganizationManager organizationManager = OrgResourceHierarchyTraverseUtil.getOrganizationManager();
-            List<String> organizationIds = organizationManager.getAncestorOrganizationIds(organizationId);
-
+            List<String> organizationIds = getAncestorOrganizationsIds(organizationId);
             if (CollectionUtils.isEmpty(organizationIds) || organizationIds.isEmpty()) {
                 return null;
             }
@@ -95,6 +91,13 @@ public <T> T getResourcesFromOrgHierarchy(String organizationId, String applicat
         }
     }
 
+    private List<String> getAncestorOrganizationsIds(String organizationId)
+            throws OrganizationManagementException {
+
+        OrganizationManager organizationManager = OrgResourceHierarchyTraverseUtil.getOrganizationManager();
+        return organizationManager.getAncestorOrganizationIds(organizationId);
+    }
+
     private ApplicationManagementService getApplicationManagementService() {
 
         return OrgResourceHierarchyTraverseServiceDataHolder.getInstance().getApplicationManagementService();

From e9667be3476a03621ecfb9c391630a6dca8558d0 Mon Sep 17 00:00:00 2001
From: dhaura <dhaurapathirana@gmail.com>
Date: Fri, 22 Nov 2024 12:15:27 +0530
Subject: [PATCH 04/18] Add unit tests and improve javadoc comments.

---
 .../pom.xml                                   |  11 +-
 .../service/OrgResourceResolverService.java   |  46 +-
 .../OrgResourceResolverServiceImpl.java       |  11 +-
 ...OrgResourceHierarchyTraverseConstants.java |  42 +-
 ...ourceHierarchyTraverseClientException.java |  12 +-
 ...OrgResourceHierarchyTraverseException.java |   7 +-
 ...ourceHierarchyTraverseServerException.java |   5 +-
 ...urceHierarchyTraverseServiceComponent.java |  37 +-
 ...rceHierarchyTraverseServiceDataHolder.java |  23 +-
 .../service/strategy/AggregationStrategy.java |  51 +-
 .../FirstFoundAggregationStrategy.java        |   6 +-
 .../strategy/MergeAllAggregationStrategy.java |  10 +-
 .../OrgResourceHierarchyTraverseUtil.java     |  60 +-
 ...gResourceResolverHierarchyServiceTest.java | 575 ++++++++++++++++++
 .../impl/MockResourceManagementService.java   | 105 ++++
 .../resource/impl/model/MockResource.java     | 143 +++++
 .../src/test/resources/testng.xml             |   1 +
 17 files changed, 1052 insertions(+), 93 deletions(-)
 create mode 100644 components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverHierarchyServiceTest.java
 create mode 100644 components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/mock/resource/impl/MockResourceManagementService.java
 create mode 100644 components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/mock/resource/impl/model/MockResource.java

diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml
index 582ed4bf8..233f0df56 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml
@@ -149,6 +149,15 @@
                 <groupId>org.jacoco</groupId>
                 <artifactId>jacoco-maven-plugin</artifactId>
                 <version>${jacoco.version}</version>
+                <configuration>
+                    <excludes>
+                        <exclude>org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/constant/*.class</exclude>
+                        <exclude>org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/*.class</exclude>
+                        <exclude>org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/*.class</exclude>
+                        <exclude>org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/AggregationStrategy.class</exclude>
+                        <exclude>org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverService.class</exclude>
+                    </excludes>
+                </configuration>
                 <executions>
                     <execution>
                         <id>default-prepare-agent</id>
@@ -187,7 +196,7 @@
                                         <limit implementation="org.jacoco.report.check.Limit">
                                             <counter>COMPLEXITY</counter>
                                             <value>COVEREDRATIO</value>
-                                            <!--<minimum>0.60</minimum>-->
+                                            <minimum>0.60</minimum>
                                         </limit>
                                     </limits>
                                 </rule>
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverService.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverService.java
index 604c83199..cb6646d5f 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverService.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverService.java
@@ -26,19 +26,28 @@
 import java.util.function.Function;
 
 /**
- * Service interface for organization resource resolver.
+ * Provides a service interface to retrieve resources from an organization's hierarchy.
+ * Supports traversal of both organization and application hierarchies using customizable
+ * resource retrieval and aggregation strategies.
+ * <p>
+ * The service is designed for extensibility, allowing clients to define their own retrieval logic
+ * and aggregation mechanisms via functional interfaces and strategy patterns.
  */
 public interface OrgResourceResolverService {
 
     /**
-     * Get resources from the organization hierarchy.
+     * Retrieves resources by traversing the hierarchy of a given organization.
      *
-     * @param organizationId      Organization ID.
-     * @param resourceRetriever   Function to retrieve the resource.
-     * @param aggregationStrategy Aggregation strategy.
-     * @param <T>                 Type of the resource.
-     * @return Resolved resources.
-     * @throws OrgResourceHierarchyTraverseException If an error occurs while retrieving the resources.
+     * @param organizationId      The unique identifier of the organization.
+     * @param resourceRetriever   A function that defines how to fetch a resource for a given organization ID.
+     *                            The function must return an {@link Optional<T>} containing the resource if found,
+     *                            or an empty {@link Optional<T>} if not.
+     * @param aggregationStrategy A strategy defining how to aggregate resources retrieved from
+     *                            different levels of the hierarchy.
+     * @param <T>                 The type of the resource being retrieved and aggregated.
+     * @return An aggregated resource of type <T> obtained from the organization hierarchy.
+     * @throws OrgResourceHierarchyTraverseException If any errors occur during resource retrieval
+     *                                               or aggregation.
      */
     <T> T getResourcesFromOrgHierarchy(String organizationId,
                                        Function<String, Optional<T>> resourceRetriever,
@@ -46,15 +55,20 @@ <T> T getResourcesFromOrgHierarchy(String organizationId,
             throws OrgResourceHierarchyTraverseException;
 
     /**
-     * Get resources from the organization and application hierarchy.
+     * Retrieves resources by traversing the hierarchy of a given organization and application.
      *
-     * @param organizationId      Organization ID.
-     * @param applicationId       Application ID.
-     * @param resourceRetriever   Function to retrieve the resource.
-     * @param aggregationStrategy Aggregation strategy.
-     * @param <T>                 Type of the resource.
-     * @return Resolved resources.
-     * @throws OrgResourceHierarchyTraverseException If an error occurs while retrieving the resources.
+     * @param organizationId      The unique identifier of the organization. Must not be null.
+     * @param applicationId       The unique identifier of the application within the organization. Must not be null.
+     * @param resourceRetriever   A bi-function that defines how to fetch a resource based on the
+     *                            organization and application IDs. The function must return an
+     *                            {@link Optional<T>} containing the resource if found,
+     *                            or an empty {@link Optional<T>} if not.
+     * @param aggregationStrategy A strategy defining how to aggregate resources retrieved from
+     *                            different levels of the hierarchy.
+     * @param <T>                 The type of the resource being retrieved and aggregated.
+     * @return An aggregated resource of type <T> obtained from the organization and application hierarchy.
+     * @throws OrgResourceHierarchyTraverseException If any errors occur during resource retrieval
+     *                                               or aggregation.
      */
     <T> T getResourcesFromOrgHierarchy(String organizationId, String applicationId,
                                        BiFunction<String, String, Optional<T>> resourceRetriever,
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceImpl.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceImpl.java
index c41fd5997..b4974135a 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceImpl.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceImpl.java
@@ -22,7 +22,7 @@
 import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException;
 import org.wso2.carbon.identity.application.mgt.ApplicationManagementService;
 import org.wso2.carbon.identity.organization.management.service.OrganizationManager;
-import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException;
+import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementServerException;
 import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.constant.OrgResourceHierarchyTraverseConstants;
 import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception.OrgResourceHierarchyTraverseException;
 import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.internal.OrgResourceHierarchyTraverseServiceDataHolder;
@@ -37,7 +37,8 @@
 import java.util.function.Function;
 
 /**
- * Implementation of the OrgResourceResolverService.
+ * Implementation of the OrgResourceResolverService interface, responsible for resolving resources within the
+ * given organization/ application hierarchy.
  */
 public class OrgResourceResolverServiceImpl implements OrgResourceResolverService {
 
@@ -53,7 +54,7 @@ public <T> T getResourcesFromOrgHierarchy(String organizationId, Function<String
             }
 
             return aggregationStrategy.aggregate(organizationIds, resourceRetriever);
-        } catch (OrganizationManagementException e) {
+        } catch (OrganizationManagementServerException e) {
             throw OrgResourceHierarchyTraverseUtil.handleServerException(
                     OrgResourceHierarchyTraverseConstants.ErrorMessages
                             .ERROR_CODE_SERVER_ERROR_WHILE_RESOLVING_ANCESTOR_ORGANIZATIONS, e, organizationId);
@@ -79,7 +80,7 @@ public <T> T getResourcesFromOrgHierarchy(String organizationId, String applicat
             }
 
             return aggregationStrategy.aggregate(organizationIds, ancestorAppIds, resourceRetriever);
-        } catch (OrganizationManagementException e) {
+        } catch (OrganizationManagementServerException e) {
             throw OrgResourceHierarchyTraverseUtil.handleServerException(
                     OrgResourceHierarchyTraverseConstants.ErrorMessages
                             .ERROR_CODE_SERVER_ERROR_WHILE_RESOLVING_ANCESTOR_ORGANIZATIONS, e, organizationId);
@@ -92,7 +93,7 @@ public <T> T getResourcesFromOrgHierarchy(String organizationId, String applicat
     }
 
     private List<String> getAncestorOrganizationsIds(String organizationId)
-            throws OrganizationManagementException {
+            throws OrganizationManagementServerException {
 
         OrganizationManager organizationManager = OrgResourceHierarchyTraverseUtil.getOrganizationManager();
         return organizationManager.getAncestorOrganizationIds(organizationId);
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/constant/OrgResourceHierarchyTraverseConstants.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/constant/OrgResourceHierarchyTraverseConstants.java
index ba4b09ddf..ef91a2fd0 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/constant/OrgResourceHierarchyTraverseConstants.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/constant/OrgResourceHierarchyTraverseConstants.java
@@ -19,18 +19,23 @@
 package org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.constant;
 
 /**
- * Constants for organization resource hierarchy traverse service.
+ * Constants defined for the organization resource hierarchy traverse service.
  */
 public class OrgResourceHierarchyTraverseConstants {
 
     private static final String ORGANIZATION_RESOURCE_HIERARCHY_TRAVERSE_ERROR_CODE_PREFIX = "ORHT-";
 
+    /**
+     * Private constructor to prevent instantiation of this constant class.
+     */
     private OrgResourceHierarchyTraverseConstants() {
 
     }
 
     /**
-     * Enum for error messages related to organization resource hierarchy traverse service.
+     * Enum which provides error codes and predefined error messages related to the traversal of
+     * the organization resource hierarchy. It ensures that error handling within the service is consistent
+     * and that detailed error descriptions are available for debugging and troubleshooting.
      */
     public enum ErrorMessages {
 
@@ -50,6 +55,16 @@ public enum ErrorMessages {
         private final String message;
         private final String description;
 
+        /**
+         * Constructor for the ErrorMessages enum.
+         * <p>
+         * This constructor is used to define each error message with a unique error code, a brief message, and
+         * a detailed description.
+         *
+         * @param code        The unique error code for the message (prefixed with "ORHT-").
+         * @param message     A brief message describing the error.
+         * @param description A detailed description of the error, often including placeholders for dynamic data.
+         */
         ErrorMessages(String code, String message, String description) {
 
             this.code = code;
@@ -57,16 +72,39 @@ public enum ErrorMessages {
             this.description = description;
         }
 
+        /**
+         * Gets the unique error code for the error message.
+         * <p>
+         * The error code is prefixed with "ORHT-" to ensure consistency in the error code system.
+         *
+         * @return The error code prefixed with "ORHT-".
+         */
         public String getCode() {
 
             return ORGANIZATION_RESOURCE_HIERARCHY_TRAVERSE_ERROR_CODE_PREFIX + code;
         }
 
+        /**
+         * Gets the brief message for the error.
+         * <p>
+         * This message provides a short description of the error, usually without context-specific details.
+         * It is used for logging or displaying to the user as part of the error response.
+         *
+         * @return A brief message describing the error.
+         */
         public String getMessage() {
 
             return message;
         }
 
+        /**
+         * Gets the detailed description for the error message.
+         * <p>
+         * This description provides a more detailed explanation of the error and often contains placeholders
+         * for dynamic data (e.g., organization or application IDs). It is typically used for logging or debugging.
+         *
+         * @return A detailed description of the error, including placeholders for dynamic data.
+         */
         public String getDescription() {
 
             return description;
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseClientException.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseClientException.java
index 00d675930..26ac0cd0d 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseClientException.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseClientException.java
@@ -25,14 +25,20 @@
 import java.util.List;
 
 /**
- * Exception class for client side errors in organization resource hierarchy traverse.
+ * Exception class for client-side errors during organization resource hierarchy traversal.
+ * <p>
+ * This class handles exceptions where client-side errors occur, capturing error codes, messages, and descriptions
+ * to provide detailed context for troubleshooting.
  */
 public class OrgResourceHierarchyTraverseClientException extends OrgResourceHierarchyTraverseException {
 
-    private static final long serialVersionUID = 559143944402014381L;
-
     private String[] messages;
 
+    /**
+     * Constructs a new exception with an array of specified error messages.
+     *
+     * @param messages Detailed error messages
+     */
     public OrgResourceHierarchyTraverseClientException(String[] messages) {
 
         super(Arrays.toString(messages));
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseException.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseException.java
index 2cc442a70..128557dc4 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseException.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseException.java
@@ -19,14 +19,17 @@
 package org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception;
 
 /**
- * Exception class that represents exceptions thrown upon organization resource hierarchy traverse.
+ * Custom exception for errors encountered during organization resource hierarchy traversal.
+ * <p>
+ * This exception captures detailed error information, including error codes, messages, descriptions,
+ * and causes, to assist in troubleshooting issues related to resolving ancestor organizations or applications.
  */
 public class OrgResourceHierarchyTraverseException extends Exception {
 
     private String errorCode;
     private String description;
 
-    private static final long serialVersionUID = -1982152066401023165L;
+    private static final long serialVersionUID = 5967152066669023668L;
 
     /**
      * Constructs a new exception with the specified message.
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseServerException.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseServerException.java
index 28f2c30b9..531b834e0 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseServerException.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseServerException.java
@@ -19,7 +19,10 @@
 package org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception;
 
 /**
- * Exception class that represents server side errors in organization resource hierarchy traverse.
+ * Exception class for server-side errors during organization resource hierarchy traversal.
+ * <p>
+ * This class handles exceptions related to server-side failures, including error codes, messages,
+ * descriptions, and causes, to provide detailed information for debugging.
  */
 public class OrgResourceHierarchyTraverseServerException extends OrgResourceHierarchyTraverseException {
 
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceComponent.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceComponent.java
index 109c26397..deec43f48 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceComponent.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceComponent.java
@@ -33,7 +33,10 @@
 import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.OrgResourceResolverServiceImpl;
 
 /**
- * OSGi declarative services component of the organization resource hierarchy traverse service.
+ * OSGi component responsible for managing the activation and deactivation of the organization resource hierarchy
+ * traverse service.
+ * <p>
+ * It manages dynamic references to necessary services required by {@link OrgResourceResolverService} as well.
  */
 @Component(
         name = "org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service",
@@ -42,6 +45,12 @@ public class OrgResourceHierarchyTraverseServiceComponent {
 
     private static final Log log = LogFactory.getLog(OrgResourceHierarchyTraverseServiceComponent.class);
 
+    /**
+     * Activates the OSGi component by registering the {@link OrgResourceResolverService} service.
+     * This method is called when the component is activated in the OSGi environment.
+     *
+     * @param context The ComponentContext instance that provides the OSGi environment context.
+     */
     @Activate
     protected void activate(ComponentContext context) {
 
@@ -57,6 +66,12 @@ protected void activate(ComponentContext context) {
         }
     }
 
+    /**
+     * Deactivates the OSGi component by cleaning up resources and logging the deactivation.
+     * This method is called when the component is deactivated in the OSGi environment.
+     *
+     * @param context The ComponentContext instance that provides the OSGi environment context.
+     */
     @Deactivate
     protected void deactivate(ComponentContext context) {
 
@@ -65,6 +80,11 @@ protected void deactivate(ComponentContext context) {
         }
     }
 
+    /**
+     * Sets the OrganizationManager instance in the OrgResourceHierarchyTraverseServiceDataHolder.
+     *
+     * @param organizationManager The OrganizationManager instance to be assigned.
+     */
     @Reference(name = "org.wso2.carbon.identity.organization.management.service",
             service = OrganizationManager.class,
             cardinality = ReferenceCardinality.OPTIONAL,
@@ -76,12 +96,22 @@ protected void setOrganizationManager(OrganizationManager organizationManager) {
         log.debug("OrganizationManager set in OrgResourceManagementServiceComponent bundle.");
     }
 
+    /**
+     * Unsets the OrganizationManager instance in the OrgResourceHierarchyTraverseServiceDataHolder.
+     *
+     * @param organizationManager The OrganizationManager instance to be removed.
+     */
     protected void unsetOrganizationManager(OrganizationManager organizationManager) {
 
         OrgResourceHierarchyTraverseServiceDataHolder.getInstance().setOrganizationManager(null);
         log.debug("OrganizationManager unset in OrgResourceManagementServiceComponent bundle.");
     }
 
+    /**
+     * Sets the ApplicationManagementService instance in the OrgResourceHierarchyTraverseServiceDataHolder.
+     *
+     * @param applicationManagementService The ApplicationManagementService instance to be assigned.
+     */
     @Reference(
             name = "org.wso2.carbon.identity.application.mgt",
             service = ApplicationManagementService.class,
@@ -95,6 +125,11 @@ protected void setApplicationManagementService(ApplicationManagementService appl
         log.debug("ApplicationManagementService set in OrgResourceManagementServiceComponent bundle.");
     }
 
+    /**
+     * Unsets the ApplicationManagementService instance in the OrgResourceHierarchyTraverseServiceDataHolder.
+     *
+     * @param applicationManagementService The ApplicationManagementService instance to be removed.
+     */
     protected void unsetApplicationManagementService(ApplicationManagementService applicationManagementService) {
 
         OrgResourceHierarchyTraverseServiceDataHolder.getInstance().setApplicationManagementService(null);
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceDataHolder.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceDataHolder.java
index b4f1f58e3..5a5c6ba02 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceDataHolder.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceDataHolder.java
@@ -22,7 +22,8 @@
 import org.wso2.carbon.identity.organization.management.service.OrganizationManager;
 
 /**
- * This class holds the data required for the organization resource hierarchy traverse service.
+ * Singleton class that serves as a centralized data holder for key service instances used in the organization
+ * resource hierarchy traversal process.
  */
 public class OrgResourceHierarchyTraverseServiceDataHolder {
 
@@ -37,9 +38,9 @@ private OrgResourceHierarchyTraverseServiceDataHolder() {
     }
 
     /**
-     * Get the instance of OrgResourceManagementServiceDataHolder.
+     * Retires the Singleton instance of the OrgResourceHierarchyTraverseServiceDataHolder class.
      *
-     * @return OrgResourceManagementServiceDataHolder instance.
+     * @return The singleton instance of OrgResourceHierarchyTraverseServiceDataHolder.
      */
     public static OrgResourceHierarchyTraverseServiceDataHolder getInstance() {
 
@@ -47,9 +48,9 @@ public static OrgResourceHierarchyTraverseServiceDataHolder getInstance() {
     }
 
     /**
-     * Get the organization manager.
+     * Retrieves the current instance of the OrganizationManager.
      *
-     * @return Organization manager.
+     * @return The current OrganizationManager instance that manages organizational data.
      */
     public OrganizationManager getOrganizationManager() {
 
@@ -57,9 +58,9 @@ public OrganizationManager getOrganizationManager() {
     }
 
     /**
-     * Set the organization manager.
+     * Sets the OrganizationManager instance.
      *
-     * @param organizationManager Organization manager instance.
+     * @param organizationManager The OrganizationManager instance to be assigned.
      */
     public void setOrganizationManager(
             OrganizationManager organizationManager) {
@@ -68,9 +69,9 @@ public void setOrganizationManager(
     }
 
     /**
-     * Get the application management service.
+     * Retrieves the current instance of the ApplicationManagementService.
      *
-     * @return Application management service.
+     * @return The current ApplicationManagementService instance responsible for managing applications.
      */
     public ApplicationManagementService getApplicationManagementService() {
 
@@ -78,9 +79,9 @@ public ApplicationManagementService getApplicationManagementService() {
     }
 
     /**
-     * Set the application management service.
+     * Sets the ApplicationManagementService instance.
      *
-     * @param applicationManagementService Application management service instance.
+     * @param applicationManagementService The ApplicationManagementService instance to be set.
      */
     public void setApplicationManagementService(
             ApplicationManagementService applicationManagementService) {
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/AggregationStrategy.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/AggregationStrategy.java
index ef23bddde..ef0798a84 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/AggregationStrategy.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/AggregationStrategy.java
@@ -28,19 +28,33 @@
 import java.util.function.Function;
 
 /**
- * Interface for aggregation strategies.
+ * Defines an interface for a strategy used for aggregating resources retrieved from hierarchical structures,
+ * such as organization and application hierarchies. This interface provides default
+ * methods that can be overridden to implement specific aggregation logic.
+ * <p>
+ * Implementations should specify how resources are combined and may use functional
+ * interfaces for flexible retrieval mechanisms.
  *
- * @param <T> Type of the resource to be aggregated.
+ * @param <T> The type of the resource to be aggregated.
  */
 public interface AggregationStrategy<T> {
 
     /**
-     * Aggregate resolved resources of the given organization hierarchy.
+     * Aggregates resources resolved from an organization's hierarchical structure.
+     * <p>
+     * This method provides a default implementation that throws a
+     * {@link NotImplementedException}. Subclasses must override this method to define
+     * specific aggregation logic for organization hierarchies.
      *
-     * @param organizationHierarchy Organization hierarchy.
-     * @param resourceRetriever     Function to retrieve the resource.
-     * @return Aggregated resource.
-     * @throws OrgResourceHierarchyTraverseException If an error occurs while aggregating the resources.
+     * @param organizationHierarchy A list representing the organization hierarchy,
+     *                              where the first element is the root organization
+     *                              and subsequent elements represent child organizations.
+     * @param resourceRetriever     A function that retrieves a resource given an organization ID.
+     *                              Returns an {@link Optional<T>} containing the resource, or empty
+     *                              if no resource is found for the given ID.
+     * @return The aggregated resource of type <T>.
+     * @throws OrgResourceHierarchyTraverseException If any error occurs during resource
+     *                                               retrieval or aggregation.
      */
     default T aggregate(List<String> organizationHierarchy, Function<String, Optional<T>> resourceRetriever)
             throws OrgResourceHierarchyTraverseException {
@@ -49,13 +63,24 @@ default T aggregate(List<String> organizationHierarchy, Function<String, Optiona
     }
 
     /**
-     * Aggregate resolved resources of the given organization and application hierarchy.
+     * Aggregates resources resolved from an organization's and application's hierarchical structure.
+     * <p>
+     * This method provides a default implementation that throws a
+     * {@link NotImplementedException}. Subclasses must override this method to define
+     * specific aggregation logic for combined organization and application hierarchies.
      *
-     * @param organizationHierarchy Organization hierarchy.
-     * @param applicationHierarchy  Application hierarchy.
-     * @param resourceRetriever     Function to retrieve the resource.
-     * @return Aggregated resource.
-     * @throws OrgResourceHierarchyTraverseException If an error occurs while aggregating the resources.
+     * @param organizationHierarchy A list representing the organization hierarchy,
+     *                              where the first element is the root organization
+     *                              and subsequent elements represent child organizations.
+     * @param applicationHierarchy  A map representing the application hierarchy, where keys
+     *                              are organization IDs, and values are application-specific
+     *                              details or IDs for each organization.
+     * @param resourceRetriever     A bi-function that retrieves a resource based on both an
+     *                              organization ID and an application ID. Returns an {@link Optional<T>}
+     *                              containing the resource, or empty if no resource is found.
+     * @return The aggregated resource of type <T>.
+     * @throws OrgResourceHierarchyTraverseException If any error occurs during resource
+     *                                               retrieval or aggregation.
      */
     default T aggregate(List<String> organizationHierarchy, Map<String, String> applicationHierarchy,
                         BiFunction<String, String, Optional<T>> resourceRetriever)
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/FirstFoundAggregationStrategy.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/FirstFoundAggregationStrategy.java
index 3ee3120f1..cfd473cc2 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/FirstFoundAggregationStrategy.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/FirstFoundAggregationStrategy.java
@@ -29,9 +29,11 @@
 import java.util.function.Function;
 
 /**
- * Aggregation strategy to retrieve the first found resource in the organization hierarchy.
+ * Aggregation strategy that can be used to traverse the organization hierarchy and retrieve the first resource found.
+ * This strategy is commonly applied when multiple resources might exist at different levels of the hierarchy,
+ * and only the first one encountered at the bottom of the hierarchy needs to be returned.
  *
- * @param <T> Type of the resource.
+ * @param <T> The type of the resource being retrieved from the organization/ application hierarchy.
  */
 public class FirstFoundAggregationStrategy<T> implements AggregationStrategy<T> {
 
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/MergeAllAggregationStrategy.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/MergeAllAggregationStrategy.java
index 648acb898..f911b2700 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/MergeAllAggregationStrategy.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/MergeAllAggregationStrategy.java
@@ -29,9 +29,15 @@
 import java.util.function.Function;
 
 /**
- * Aggregation strategy to merge all resources in the organization hierarchy with the given resource merger function.
+ * Aggregation strategy to merge all resources in the organization hierarchy using the specified
+ * resource merger function.
+ * <p>
+ * This strategy traverses the hierarchy and applies the provided function
+ * to combine the resources at each level. It ensures that the resources are merged according to the
+ * logic defined by the merger function, which could involve combining attributes, performing calculations, or
+ * resolving conflicts between resources.
  *
- * @param <T> Type of the resource.
+ * @param <T> The type of the resources being merged in the organization/ application hierarchy.
  */
 public class MergeAllAggregationStrategy<T> implements AggregationStrategy<T> {
 
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/util/OrgResourceHierarchyTraverseUtil.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/util/OrgResourceHierarchyTraverseUtil.java
index 68adcc9d3..b48159dc8 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/util/OrgResourceHierarchyTraverseUtil.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/util/OrgResourceHierarchyTraverseUtil.java
@@ -20,26 +20,31 @@
 
 import org.apache.commons.lang.ArrayUtils;
 import org.wso2.carbon.identity.organization.management.service.OrganizationManager;
-import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException;
+import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementServerException;
 import org.wso2.carbon.identity.organization.management.service.util.Utils;
 import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.constant.OrgResourceHierarchyTraverseConstants;
-import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception.OrgResourceHierarchyTraverseClientException;
 import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception.OrgResourceHierarchyTraverseServerException;
 import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.internal.OrgResourceHierarchyTraverseServiceDataHolder;
 
 /**
- * Utility class for organization resource hierarchy traverse service.
+ * Utility class for the Organization Resource Hierarchy Traverse Service.
+ * <p>
+ * This class provides helper methods to interact with the organization hierarchy and manage traversal logic,
+ * such as verifying the hierarchy depth and handling server-side exceptions.
  */
 public class OrgResourceHierarchyTraverseUtil {
 
+    /**
+     * Private constructor to prevent instantiation of the utility class.
+     */
     private OrgResourceHierarchyTraverseUtil() {
 
     }
 
     /**
-     * Get the organization manager.
+     * Retrieve the organization manager instance.
      *
-     * @return Organization manager.
+     * @return The {@link OrganizationManager} instance used to manage organizations.
      */
     public static OrganizationManager getOrganizationManager() {
 
@@ -47,11 +52,14 @@ public static OrganizationManager getOrganizationManager() {
     }
 
     /**
-     * Check whether the minimum organization hierarchy depth is reached.
+     * Verify if the organization hierarchy depth has reached the minimum required level.
+     * <p>
+     * This method obtains the depth of the specified organization in the hierarchy and compares it
+     * with the configured minimum depth. An exception is thrown if an error occurs during the depth calculation.
      *
-     * @param orgId Organization ID.
-     * @return True if the minimum hierarchy depth is reached.
-     * @throws OrgResourceHierarchyTraverseServerException If an error occurs while checking the hierarchy depth.
+     * @param orgId The ID of the organization to check.
+     * @return {@code true} if the hierarchy depth is less than the minimum required depth, {@code false} otherwise.
+     * @throws OrgResourceHierarchyTraverseServerException If an error occurs while retrieving the organization's depth.
      */
     public static boolean isMinOrgHierarchyDepthReached(String orgId) throws
             OrgResourceHierarchyTraverseServerException {
@@ -60,38 +68,22 @@ public static boolean isMinOrgHierarchyDepthReached(String orgId) throws
         try {
             int depthInHierarchy = getOrganizationManager().getOrganizationDepthInHierarchy(orgId);
             return depthInHierarchy < minHierarchyDepth;
-        } catch (OrganizationManagementException e) {
+        } catch (OrganizationManagementServerException e) {
             throw new OrgResourceHierarchyTraverseServerException(
                     "Error occurred while getting the hierarchy depth of the organization: " + orgId, e);
         }
     }
 
     /**
-     * Throw an OrgResourceHierarchyTraverseClientException upon client side error while traversing organization
-     * resource hierarchy traverse.
-     *
-     * @param error The error enum.
-     * @param data  The error message data.
-     * @return OrgResourceHierarchyTraverseClientException
-     */
-    public static OrgResourceHierarchyTraverseClientException handleClientException(
-            OrgResourceHierarchyTraverseConstants.ErrorMessages error, String... data) {
-
-        String description = error.getDescription();
-        if (ArrayUtils.isNotEmpty(data)) {
-            description = String.format(description, data);
-        }
-        return new OrgResourceHierarchyTraverseClientException(error.getMessage(), description, error.getCode());
-    }
-
-    /**
-     * Throw an OrgResourceHierarchyTraverseServerException upon server side error while traversing organization
-     * resource hierarchy traverse.
+     * Create an {@link OrgResourceHierarchyTraverseServerException} to handle server-side errors.
+     * <p>
+     * This method formats the error description using the provided data, if applicable, and constructs
+     * a custom exception for consistent error handling in the service.
      *
-     * @param error The error enum.
-     * @param e     The error.
-     * @param data  The error message data.
-     * @return OrgResourceHierarchyTraverseServerException
+     * @param error The error enumeration containing predefined error messages and codes.
+     * @param e     The underlying cause of the error.
+     * @param data  Optional data to format the error message description.
+     * @return An {@link OrgResourceHierarchyTraverseServerException} with the formatted error details.
      */
     public static OrgResourceHierarchyTraverseServerException handleServerException(
             OrgResourceHierarchyTraverseConstants.ErrorMessages error, Throwable e, String... data) {
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverHierarchyServiceTest.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverHierarchyServiceTest.java
new file mode 100644
index 000000000..1d4f38039
--- /dev/null
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverHierarchyServiceTest.java
@@ -0,0 +1,575 @@
+/*
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. licenses this file to you 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.wso2.carbon.identity.organization.resource.hierarchy.traverse.service;
+
+import org.mockito.Mock;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException;
+import org.wso2.carbon.identity.application.mgt.ApplicationManagementService;
+import org.wso2.carbon.identity.organization.management.service.OrganizationManager;
+import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException;
+import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementServerException;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception.OrgResourceHierarchyTraverseException;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception.OrgResourceHierarchyTraverseServerException;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.internal.OrgResourceHierarchyTraverseServiceDataHolder;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.mock.resource.impl.MockResourceManagementService;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.mock.resource.impl.model.MockResource;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.strategy.AggregationStrategy;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.strategy.FirstFoundAggregationStrategy;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.strategy.MergeAllAggregationStrategy;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.openMocks;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertThrows;
+
+/**
+ * Unit tests for the OrgResourceResolverHierarchyService.
+ */
+public class OrgResourceResolverHierarchyServiceTest {
+
+    private static final String ROOT_ORG_ID = "10084a8d-113f-4211-a0d5-efe36b082211";
+    private static final String ROOT_APP_ID = "1ee981ab-64e7-435c-ab91-e8d1e0a13b2c";
+    private static final String L1_ORG_ID = "93d996f9-a5ba-4275-a52b-adaad9eba869";
+    private static final String L1_APP_ID = "619d2cb1-174d-4d38-af3b-99c532dddb00";
+    private static final String L2_ORG_ID = "30b701c6-e309-4241-b047-0c299c45d1a0";
+    private static final String L2_APP_ID = "d04d48db-8c5a-437a-9458-4352b84db621";
+    private static final String INVALID_ORG_ID = "invalid-org-id";
+    private static final String INVALID_APP_ID = "invalid-app-id";
+
+    private OrgResourceResolverService orgResourceResolverService;
+    private MockResourceManagementService mockResourceManagementService;
+    private AggregationStrategy<MockResource> firstFoundAggregationStrategy;
+    private AggregationStrategy<MockResource> mergeAllAggregationStrategy;
+
+    @Mock
+    OrganizationManager organizationManager;
+
+    @Mock
+    ApplicationManagementService applicationManagementService;
+
+    /**
+     * Initializes test data and mock services before the test class is run.
+     * This method sets up necessary services and aggregation strategies required for the tests.
+     */
+    @BeforeClass
+    public void init() {
+
+        // Open mock objects for the current test instance
+        openMocks(this);
+
+        // Set the OrganizationManager and ApplicationManagementService to the data holder for use in tests
+        OrgResourceHierarchyTraverseServiceDataHolder.getInstance().setOrganizationManager(organizationManager);
+        OrgResourceHierarchyTraverseServiceDataHolder.getInstance()
+                .setApplicationManagementService(applicationManagementService);
+
+        // Initialize the aggregation strategies with the appropriate strategy types
+        firstFoundAggregationStrategy = new FirstFoundAggregationStrategy<>();
+        mergeAllAggregationStrategy = new MergeAllAggregationStrategy<>(this::resourceMerger);
+    }
+
+    /**
+     * Sets up mocks for individual test cases by initializing mock services and resource management.
+     * This method runs before each test method to ensure the environment is ready for testing specific scenarios.
+     */
+    @BeforeMethod
+    public void setUp() throws Exception {
+
+        // Mock responses for the organization manager with different ancestor organization chains
+        mockAncestorOrganizationRetrieval(Arrays.asList(L2_ORG_ID, L1_ORG_ID, ROOT_ORG_ID));
+        mockAncestorOrganizationRetrieval(Arrays.asList(L1_ORG_ID, ROOT_ORG_ID));
+        mockAncestorOrganizationRetrieval(Collections.singletonList(ROOT_ORG_ID));
+
+        // Mock responses for the application management service with corresponding application ancestor data
+        mockAncestorApplicationRetrieval(Arrays.asList(L2_ORG_ID, L1_ORG_ID, ROOT_ORG_ID),
+                Arrays.asList(L2_APP_ID, L1_APP_ID, ROOT_APP_ID));
+        mockAncestorApplicationRetrieval(Arrays.asList(L1_ORG_ID, ROOT_ORG_ID),
+                Arrays.asList(L1_APP_ID, ROOT_APP_ID));
+        mockAncestorApplicationRetrieval(Collections.singletonList(ROOT_ORG_ID),
+                Collections.singletonList(ROOT_APP_ID));
+
+        // Initialize the mock resource management service used in tests
+        mockResourceManagementService = new MockResourceManagementService();
+
+        // Instantiate the OrgResourceResolverService for testing
+        orgResourceResolverService = new OrgResourceResolverServiceImpl();
+    }
+
+    /**
+     * Resets mock services after each test method to ensure a clean state for subsequent tests.
+     */
+    @AfterMethod
+    public void tearDown() {
+
+        // Reset the mock services to their default state after each test
+        reset(organizationManager);
+        reset(applicationManagementService);
+    }
+
+    @DataProvider(name = "AggregationStrategyDataProvider")
+    public Object[][] provideAggregationStrategies() {
+
+        return new Object[][]{
+                {firstFoundAggregationStrategy},
+                {mergeAllAggregationStrategy}
+        };
+    }
+
+    @Test(dataProvider = "AggregationStrategyDataProvider")
+    public void testGetOrgLevelResourcesFromOrgHierarchyWhenNoResourceAvailable(
+            AggregationStrategy<MockResource> aggregationStrategy) throws Exception {
+
+        // No resources available in the mock resource management service.
+
+        MockResource resolvedRootResource = invokeOrgLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID);
+        assertNull(resolvedRootResource);
+
+        MockResource resolvedL1Resource = invokeOrgLevelResourceResolver(aggregationStrategy, L1_ORG_ID);
+        assertNull(resolvedL1Resource);
+
+        MockResource resolvedL2Resource = invokeOrgLevelResourceResolver(aggregationStrategy, L2_ORG_ID);
+        assertNull(resolvedL2Resource);
+    }
+
+    @Test(dataProvider = "AggregationStrategyDataProvider")
+    public void testGetOrgLevelResourcesFromOrgHierarchyWhenRootResourceAvailable(
+            AggregationStrategy<MockResource> aggregationStrategy) throws Exception {
+
+        // Add org-level resource for root organization into the mock resource management service.
+        List<MockResource> createdOrgResource = addOrgResources(Collections.singletonList(ROOT_ORG_ID));
+
+        MockResource resolvedRootResource = invokeOrgLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID);
+        assertResolvedResponse(resolvedRootResource, createdOrgResource.get(0));
+
+        MockResource resolvedL1Resource = invokeOrgLevelResourceResolver(aggregationStrategy, L1_ORG_ID);
+        assertResolvedResponse(resolvedL1Resource, createdOrgResource.get(0));
+
+        MockResource resolvedL2Resource = invokeOrgLevelResourceResolver(aggregationStrategy, L2_ORG_ID);
+        assertResolvedResponse(resolvedL2Resource, createdOrgResource.get(0));
+    }
+
+    @Test(dataProvider = "AggregationStrategyDataProvider")
+    public void testGetOrgLevelResourcesFromOrgHierarchyWhenL1OrgResourceAvailable(
+            AggregationStrategy<MockResource> aggregationStrategy) throws Exception {
+
+        // Add org-level resources for L1 and root organizations into the mock resource management service.
+        List<MockResource> createdOrgResources = addOrgResources(Arrays.asList(ROOT_ORG_ID, L1_ORG_ID));
+
+        MockResource resolvedRootResource = invokeOrgLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID);
+        assertResolvedResponse(resolvedRootResource, createdOrgResources.get(0));
+
+        MockResource resolvedL1Resource = invokeOrgLevelResourceResolver(aggregationStrategy, L1_ORG_ID);
+        assertResolvedResponse(resolvedL1Resource, createdOrgResources.get(1));
+
+        MockResource resolvedL2Resource = invokeOrgLevelResourceResolver(aggregationStrategy, L2_ORG_ID);
+        assertResolvedResponse(resolvedL2Resource, createdOrgResources.get(1));
+    }
+
+    @Test(dataProvider = "AggregationStrategyDataProvider")
+    public void testGetOrgLevelResourcesFromOrgHierarchyWhenL2OrgResourceAvailable(
+            AggregationStrategy<MockResource> aggregationStrategy) throws Exception {
+
+        // Add org-level resources for L2, L1 and root organizations into the mock resource management service.
+        List<MockResource> createdOrgResources = addOrgResources(Arrays.asList(ROOT_ORG_ID, L1_ORG_ID, L2_ORG_ID));
+
+        MockResource resolvedRootResource = invokeOrgLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID);
+        assertResolvedResponse(resolvedRootResource, createdOrgResources.get(0));
+
+        MockResource resolvedL1Resource = invokeOrgLevelResourceResolver(aggregationStrategy, L1_ORG_ID);
+        assertResolvedResponse(resolvedL1Resource, createdOrgResources.get(1));
+
+        MockResource resolvedL2Resource = invokeOrgLevelResourceResolver(aggregationStrategy, L2_ORG_ID);
+        assertResolvedResponse(resolvedL2Resource, createdOrgResources.get(2));
+    }
+
+    @Test(dataProvider = "AggregationStrategyDataProvider")
+    public void testGetAppLevelResourcesFromOrgHierarchyWhenNoResourceAvailable(
+            AggregationStrategy<MockResource> aggregationStrategy) throws Exception {
+
+        MockResource resolvedRootAppResource =
+                invokeAppLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID, ROOT_APP_ID);
+        assertNull(resolvedRootAppResource);
+
+        MockResource resolvedL1AppResource = invokeAppLevelResourceResolver(aggregationStrategy, L1_ORG_ID, L1_APP_ID);
+        assertNull(resolvedL1AppResource);
+
+        MockResource resolvedL2AppResource = invokeAppLevelResourceResolver(aggregationStrategy, L2_ORG_ID, L2_APP_ID);
+        assertNull(resolvedL2AppResource);
+    }
+
+    @Test(dataProvider = "AggregationStrategyDataProvider")
+    public void testGetAppLevelResourcesFromOrgHierarchyWhenRootResourcesAvailable(
+            AggregationStrategy<MockResource> aggregationStrategy) throws Exception {
+
+        // Add org-level resource for root organization into the mock resource management service.
+        List<MockResource> createdOrgResource = addOrgResources(Collections.singletonList(ROOT_ORG_ID));
+
+        MockResource resolvedRootAppResource =
+                invokeAppLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID, ROOT_APP_ID);
+        assertResolvedResponse(resolvedRootAppResource, createdOrgResource.get(0));
+
+        MockResource resolvedL1AppResource = invokeAppLevelResourceResolver(aggregationStrategy, L1_ORG_ID, L1_APP_ID);
+        assertResolvedResponse(resolvedL1AppResource, createdOrgResource.get(0));
+
+        MockResource resolvedL2AppResource = invokeAppLevelResourceResolver(aggregationStrategy, L2_ORG_ID, L2_APP_ID);
+        assertResolvedResponse(resolvedL2AppResource, createdOrgResource.get(0));
+
+        // Add app-level resource for root organization into the mock resource management service.
+        List<MockResource> createdAppResource = addAppResources(Collections.singletonList(ROOT_ORG_ID),
+                Collections.singletonList(ROOT_APP_ID));
+
+        resolvedRootAppResource =
+                invokeAppLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID, ROOT_APP_ID);
+        assertResolvedResponse(resolvedRootAppResource, createdAppResource.get(0));
+
+        resolvedL1AppResource = invokeAppLevelResourceResolver(aggregationStrategy, L1_ORG_ID, L1_APP_ID);
+        assertResolvedResponse(resolvedL1AppResource, createdAppResource.get(0));
+
+        resolvedL2AppResource = invokeAppLevelResourceResolver(aggregationStrategy, L2_ORG_ID, L2_APP_ID);
+        assertResolvedResponse(resolvedL2AppResource, createdAppResource.get(0));
+    }
+
+    @Test(dataProvider = "AggregationStrategyDataProvider")
+    public void testGetAppLevelResourcesFromOrgHierarchyWhenL1ResourcesAvailable(
+            AggregationStrategy<MockResource> aggregationStrategy) throws Exception {
+
+        // Add org-level resources for L1 and root organizations into the mock resource management service.
+        List<MockResource> createdOrgResources = addOrgResources(Arrays.asList(ROOT_ORG_ID, L1_ORG_ID));
+        // Add app-level resources for root organization into the mock resource management service.
+        List<MockResource> createdAppResources = addAppResources(Collections.singletonList(ROOT_ORG_ID),
+                Collections.singletonList(ROOT_APP_ID));
+
+        MockResource resolvedRootAppResource =
+                invokeAppLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID, ROOT_APP_ID);
+        assertResolvedResponse(resolvedRootAppResource, createdAppResources.get(0));
+
+        MockResource resolvedL1AppResource = invokeAppLevelResourceResolver(aggregationStrategy, L1_ORG_ID, L1_APP_ID);
+        assertResolvedResponse(resolvedL1AppResource, createdOrgResources.get(1));
+
+        MockResource resolvedL2AppResource = invokeAppLevelResourceResolver(aggregationStrategy, L2_ORG_ID, L2_APP_ID);
+        assertResolvedResponse(resolvedL2AppResource, createdOrgResources.get(1));
+
+        // Add app-level resources for L1 organization into the mock resource management service.
+        createdAppResources.addAll(addAppResources(Collections.singletonList(L1_ORG_ID),
+                Collections.singletonList(L1_APP_ID)));
+
+        resolvedRootAppResource =
+                invokeAppLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID, ROOT_APP_ID);
+        assertResolvedResponse(resolvedRootAppResource, createdAppResources.get(0));
+
+        resolvedL1AppResource = invokeAppLevelResourceResolver(aggregationStrategy, L1_ORG_ID, L1_APP_ID);
+        assertResolvedResponse(resolvedL1AppResource, createdAppResources.get(1));
+
+        resolvedL2AppResource = invokeAppLevelResourceResolver(aggregationStrategy, L2_ORG_ID, L2_APP_ID);
+        assertResolvedResponse(resolvedL2AppResource, createdAppResources.get(1));
+    }
+
+    @Test(dataProvider = "AggregationStrategyDataProvider")
+    public void testGetAppLevelResourcesFromOrgHierarchyWhenL2ResourcesAvailable(
+            AggregationStrategy<MockResource> aggregationStrategy) throws Exception {
+
+        // Add org-level resources for L2, L1 and root organizations into the mock resource management service.
+        List<MockResource> createdOrgResources = addOrgResources(Arrays.asList(ROOT_ORG_ID, L1_ORG_ID, L2_ORG_ID));
+        // Add app-level resources for L1 and root organizations into the mock resource management service.
+        List<MockResource> createdAppResources = addAppResources(Arrays.asList(ROOT_ORG_ID, L1_ORG_ID),
+                Arrays.asList(ROOT_APP_ID, L1_APP_ID));
+
+        MockResource resolvedRootAppResource =
+                invokeAppLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID, ROOT_APP_ID);
+        assertResolvedResponse(resolvedRootAppResource, createdAppResources.get(0));
+
+        MockResource resolvedL1AppResource = invokeAppLevelResourceResolver(aggregationStrategy, L1_ORG_ID, L1_APP_ID);
+        assertResolvedResponse(resolvedL1AppResource, createdAppResources.get(1));
+
+        MockResource resolvedL2AppResource = invokeAppLevelResourceResolver(aggregationStrategy, L2_ORG_ID, L2_APP_ID);
+        assertResolvedResponse(resolvedL2AppResource, createdOrgResources.get(2));
+
+        // Add app-level resources for L2 organization into the mock resource management service.
+        createdAppResources.addAll(addAppResources(Collections.singletonList(L2_ORG_ID),
+                Collections.singletonList(L2_APP_ID)));
+
+        resolvedRootAppResource =
+                invokeAppLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID, ROOT_APP_ID);
+        assertResolvedResponse(resolvedRootAppResource, createdAppResources.get(0));
+
+        resolvedL1AppResource = invokeAppLevelResourceResolver(aggregationStrategy, L1_ORG_ID, L1_APP_ID);
+        assertResolvedResponse(resolvedL1AppResource, createdAppResources.get(1));
+
+        resolvedL2AppResource = invokeAppLevelResourceResolver(aggregationStrategy, L2_ORG_ID, L2_APP_ID);
+        assertResolvedResponse(resolvedL2AppResource, createdAppResources.get(2));
+    }
+
+    @DataProvider(name = "provideAggregationStrategiesForOrgLevelResolverWithInvalidInput")
+    public Object[][] provideAggregationStrategiesForOrgLevelResolverWithInvalidInput() {
+
+        List<String> invalidOrgIds = Arrays.asList(null, "", INVALID_ORG_ID);
+
+        return new Object[][]{
+                {firstFoundAggregationStrategy, invalidOrgIds},
+                {mergeAllAggregationStrategy, invalidOrgIds},
+        };
+    }
+
+    @Test(dataProvider = "provideAggregationStrategiesForOrgLevelResolverWithInvalidInput")
+    public void testGetOrgLevelResourcesFromOrgHierarchyForInvalidInput(
+            AggregationStrategy<MockResource> aggregationStrategy, List<String> invalidOrgIds) throws Exception {
+
+        for (String orgId : invalidOrgIds) {
+            MockResource resolvedResource = invokeOrgLevelResourceResolver(aggregationStrategy, orgId);
+            assertNull(resolvedResource);
+        }
+    }
+
+    @DataProvider(name = "provideAggregationStrategiesForAppLevelResolverWithInvalidInput")
+    public Object[][] provideAggregationStrategiesForAppLevelResolverWithInvalidInput() {
+
+        List<String> invalidOrgIds = Arrays.asList(null, "", INVALID_ORG_ID);
+        List<String> invalidAppIds = Arrays.asList(null, "", INVALID_APP_ID);
+
+        return new Object[][]{
+                {firstFoundAggregationStrategy, invalidOrgIds, invalidAppIds},
+                {mergeAllAggregationStrategy, invalidOrgIds, invalidAppIds},
+        };
+    }
+
+    @Test(dataProvider = "provideAggregationStrategiesForAppLevelResolverWithInvalidInput")
+    public void testGetAppLevelResourcesFromOrgHierarchyForInvalidInput(
+            AggregationStrategy<MockResource> aggregationStrategy, List<String> invalidOrgIds,
+            List<String> invalidAppIds) throws Exception {
+
+        for (String invalidOrgId : invalidOrgIds) {
+            for (String invalidAppId : invalidAppIds) {
+                MockResource resolvedResource =
+                        invokeAppLevelResourceResolver(aggregationStrategy, invalidOrgId, invalidAppId);
+                assertNull(resolvedResource);
+            }
+        }
+    }
+
+    @Test(dataProvider = "AggregationStrategyDataProvider")
+    public void testGetOrgLevelResourcesFromOrgHierarchyWhenServerErrorOccurs(
+            AggregationStrategy<MockResource> aggregationStrategy) throws Exception {
+
+        when(organizationManager.getOrganizationDepthInHierarchy(anyString()))
+                .thenThrow(OrganizationManagementServerException.class);
+        assertThrows(OrgResourceHierarchyTraverseServerException.class,
+                () -> invokeOrgLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID));
+        assertThrows(OrgResourceHierarchyTraverseServerException.class,
+                () -> invokeOrgLevelResourceResolver(aggregationStrategy, L1_ORG_ID));
+        assertThrows(OrgResourceHierarchyTraverseServerException.class,
+                () -> invokeOrgLevelResourceResolver(aggregationStrategy, L2_ORG_ID));
+
+        when(organizationManager.getAncestorOrganizationIds(anyString()))
+                .thenThrow(OrganizationManagementServerException.class);
+        assertThrows(OrgResourceHierarchyTraverseServerException.class,
+                () -> invokeOrgLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID));
+        assertThrows(OrgResourceHierarchyTraverseServerException.class,
+                () -> invokeOrgLevelResourceResolver(aggregationStrategy, L1_ORG_ID));
+        assertThrows(OrgResourceHierarchyTraverseServerException.class,
+                () -> invokeOrgLevelResourceResolver(aggregationStrategy, L2_ORG_ID));
+    }
+
+    @Test(dataProvider = "AggregationStrategyDataProvider")
+    public void testGetAppLevelResourcesFromOrgHierarchyWhenServerErrorOccurs(
+            AggregationStrategy<MockResource> aggregationStrategy) throws Exception {
+
+        when(applicationManagementService.getAncestorAppIds(anyString(), anyString()))
+                .thenThrow(IdentityApplicationManagementException.class);
+
+        assertThrows(OrgResourceHierarchyTraverseServerException.class,
+                () -> invokeAppLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID, ROOT_APP_ID));
+        assertThrows(OrgResourceHierarchyTraverseServerException.class,
+                () -> invokeAppLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID, ROOT_APP_ID));
+        assertThrows(OrgResourceHierarchyTraverseServerException.class,
+                () -> invokeAppLevelResourceResolver(aggregationStrategy, L2_ORG_ID, L2_APP_ID));
+
+        when(organizationManager.getAncestorOrganizationIds(anyString()))
+                .thenThrow(OrganizationManagementServerException.class);
+
+        assertThrows(OrgResourceHierarchyTraverseServerException.class,
+                () -> invokeAppLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID, ROOT_APP_ID));
+        assertThrows(OrgResourceHierarchyTraverseServerException.class,
+                () -> invokeAppLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID, ROOT_APP_ID));
+        assertThrows(OrgResourceHierarchyTraverseServerException.class,
+                () -> invokeAppLevelResourceResolver(aggregationStrategy, L2_ORG_ID, L2_APP_ID));
+    }
+
+    /**
+     * Mock the retrieval of ancestor organization IDs.
+     *
+     * @param orgIds Organization IDs
+     * @throws OrganizationManagementException If an error occurs while retrieving ancestor organization IDs.
+     */
+    private void mockAncestorOrganizationRetrieval(List<String> orgIds)
+            throws OrganizationManagementException {
+
+        List<String> ancestorOrganizationIds = new ArrayList<>(orgIds);
+        when(organizationManager.getAncestorOrganizationIds(orgIds.get(0))).thenReturn(ancestorOrganizationIds);
+    }
+
+    /**
+     * Mock the retrieval of ancestor application IDs.
+     *
+     * @param orgIds Organization IDs
+     * @param appIds Application IDs
+     * @throws IdentityApplicationManagementException If an error occurs while retrieving ancestor application IDs.
+     */
+    private void mockAncestorApplicationRetrieval(List<String> orgIds, List<String> appIds)
+            throws IdentityApplicationManagementException {
+
+        Map<String, String> ancestorAppIds = new HashMap<>();
+        for (String orgId : orgIds) {
+            ancestorAppIds.put(orgId, appIds.get(orgIds.indexOf(orgId)));
+        }
+
+        when(applicationManagementService.getAncestorAppIds(appIds.get(0), orgIds.get(0))).thenReturn(ancestorAppIds);
+    }
+
+    /**
+     * Add organization resources to the mock resource management service.
+     *
+     * @param orgIds Organization IDs
+     * @return List of created organization resources.
+     */
+    private List<MockResource> addOrgResources(List<String> orgIds) {
+
+        List<MockResource> createdOrgResources = new ArrayList<>();
+        int resourceId = 1;
+        for (String orgId : orgIds) {
+            MockResource orgResource = new MockResource(resourceId++, orgId + "Org Resource", orgId);
+            mockResourceManagementService.addOrgResource(orgResource);
+            createdOrgResources.add(orgResource);
+        }
+        return createdOrgResources;
+    }
+
+    /**
+     * Add application resources to the mock resource management service.
+     *
+     * @param orgIds Organization IDs
+     * @param appIds Application IDs
+     * @return List of created application resources.
+     */
+    private List<MockResource> addAppResources(List<String> orgIds, List<String> appIds) {
+
+        List<MockResource> createdAppResources = new ArrayList<>();
+        int resourceId = 1;
+        for (String orgId : orgIds) {
+            MockResource appResource =
+                    new MockResource(resourceId++, orgId + "App Resource", orgId, appIds.get(orgIds.indexOf(orgId)));
+            mockResourceManagementService.addAppResource(appResource);
+            createdAppResources.add(appResource);
+        }
+        return createdAppResources;
+    }
+
+    /**
+     * Resource resolver function used for testing MergeAllAggregationStrategy.
+     *
+     * @param aggregatedResource Aggregated resource
+     * @param newResource        New resource
+     * @return Merged resource.
+     */
+    private MockResource resourceMerger(MockResource aggregatedResource, MockResource newResource) {
+
+        if (aggregatedResource == null) {
+            return newResource;
+        }
+        return aggregatedResource;
+    }
+
+    /**
+     * Invoke the organization level resource resolver.
+     *
+     * @param aggregationStrategy Aggregation strategy
+     * @param organizationId      Organization ID
+     * @return Resolved resource
+     * @throws OrgResourceHierarchyTraverseException If an error occurs while resolving the resource.
+     */
+    private MockResource invokeOrgLevelResourceResolver(AggregationStrategy<MockResource> aggregationStrategy,
+                                                        String organizationId)
+            throws OrgResourceHierarchyTraverseException {
+
+        return orgResourceResolverService.getResourcesFromOrgHierarchy(
+                organizationId,
+                (orgId) -> {
+                    MockResource resource = mockResourceManagementService.getOrgResource(orgId);
+                    return Optional.ofNullable(resource);
+                },
+                aggregationStrategy);
+    }
+
+    /**
+     * Invoke the application level resource resolver.
+     *
+     * @param aggregationStrategy Aggregation strategy
+     * @param organizationId      Organization ID
+     * @param applicationId       Application ID
+     * @return Resolved resource
+     * @throws OrgResourceHierarchyTraverseException If an error occurs while resolving the resource.
+     */
+    private MockResource invokeAppLevelResourceResolver(AggregationStrategy<MockResource> aggregationStrategy,
+                                                        String organizationId, String applicationId)
+            throws OrgResourceHierarchyTraverseException {
+
+        return orgResourceResolverService.getResourcesFromOrgHierarchy(
+                organizationId,
+                applicationId,
+                (orgId, appId) -> {
+                    MockResource resource = mockResourceManagementService.getAppResource(orgId, appId);
+                    return Optional.ofNullable(resource);
+                },
+                aggregationStrategy);
+    }
+
+    /**
+     * Assert the resolved resource with the actual resource.
+     *
+     * @param resolvedResource Resolved resource
+     * @param actualResource   Actual resource
+     */
+    private void assertResolvedResponse(MockResource resolvedResource, MockResource actualResource) {
+
+        if (actualResource == null) {
+            assertNull(resolvedResource);
+            return;
+        }
+
+        assertNotNull(resolvedResource);
+        assertEquals(resolvedResource.getId(), actualResource.getId());
+        assertEquals(resolvedResource.getResourceName(), actualResource.getResourceName());
+        assertEquals(resolvedResource.getOrgId(), actualResource.getOrgId());
+    }
+}
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/mock/resource/impl/MockResourceManagementService.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/mock/resource/impl/MockResourceManagementService.java
new file mode 100644
index 000000000..814b010f5
--- /dev/null
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/mock/resource/impl/MockResourceManagementService.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. licenses this file to you 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.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.mock.resource.impl;
+
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.mock.resource.impl.model.MockResource;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Service for managing mocked resources at both organization and application levels.
+ * <p>
+ * This class maintains separate mappings for organization-level and application-level
+ * resources, providing methods to add and retrieve resources. These mappings simulate a database,
+ * offering a simple in-memory representation for resource storage and retrieval operations.
+ * <p>
+ * This implementation is intended for testing or mocking purposes and simulates a resource management system.
+ */
+public class MockResourceManagementService {
+
+    private final Map<String, MockResource> orgResources;
+    private final Map<String, MockResource> appResources;
+
+    /**
+     * Initializes the mock resource management service with empty resource mappings
+     * for both organization-level and application-level resources.
+     */
+    public MockResourceManagementService() {
+
+        this.orgResources = new HashMap<>();
+        this.appResources = new HashMap<>();
+    }
+
+    /**
+     * Adds an organization-level resource to the management service.
+     *
+     * @param orgResource The resource to be added. The resource's organization ID
+     *                    ({@link MockResource#getOrgId}) is used as the key for storage.
+     */
+    public void addOrgResource(MockResource orgResource) {
+
+        orgResources.put(orgResource.getOrgId(), orgResource);
+    }
+
+    /**
+     * Retrieves an organization-level resource by its organization ID.
+     *
+     * @param orgId The unique identifier of the organization.
+     * @return The resource associated with the given organization ID, or {@code null}
+     * if no resource exists for the provided ID.
+     */
+    public MockResource getOrgResource(String orgId) {
+
+        return orgResources.get(orgId);
+    }
+
+    /**
+     * Adds an application-level resource to the management service.
+     *
+     * @param appResource The resource to be added. The key for storage is derived
+     *                    by concatenating the resource's organization ID and
+     *                    application ID ({@link MockResource#getAppId}), separated by a colon.
+     */
+    public void addAppResource(MockResource appResource) {
+
+        appResources.put(appResource.getOrgId() + ":" + appResource.getAppId(), appResource);
+    }
+
+    /**
+     * Retrieves an application-level resource by organization ID and application ID.
+     * <p>
+     * If no application-level resource is found for the given organization and application IDs,
+     * the method falls back to returning the corresponding organization-level resource, if available.
+     *
+     * @param orgId The unique identifier of the organization.
+     * @param appId The unique identifier of the application within the organization.
+     * @return The application-level resource if found; otherwise, the organization-level
+     * resource associated with the organization ID. Returns {@code null} if no matching
+     * resource is available at either level.
+     */
+    public MockResource getAppResource(String orgId, String appId) {
+
+        MockResource appResource = appResources.get(orgId + ":" + appId);
+        if (appResource == null) {
+            return orgResources.get(orgId);
+        }
+        return appResource;
+    }
+}
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/mock/resource/impl/model/MockResource.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/mock/resource/impl/model/MockResource.java
new file mode 100644
index 000000000..9b4cbb86e
--- /dev/null
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/mock/resource/impl/model/MockResource.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
+ *
+ * WSO2 LLC. licenses this file to you 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.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.mock.resource.impl.model;
+
+/**
+ * Represents a mocked resource in an organization or application hierarchy.
+ * <p>
+ * This class models resources that are associated either at the organization level
+ * or at the application level within an organization. It includes identifiers and
+ * metadata such as resource ID, resource name, organization ID, and optionally,
+ * an application ID for application-specific resources.
+ */
+public class MockResource {
+
+    private int id;
+    private String resourceName;
+    private String orgId;
+    private String appId;
+
+    /**
+     * Constructs a mocked resource associated with an organization.
+     *
+     * @param id           Unique identifier of the resource.
+     * @param resourceName Descriptive name of the resource.
+     * @param orgId        Identifier of the organization the resource belongs to.
+     */
+    public MockResource(int id, String resourceName, String orgId) {
+
+        this.id = id;
+        this.resourceName = resourceName;
+        this.orgId = orgId;
+    }
+
+    /**
+     * Constructs a mocked resource associated with a specific application within an organization.
+     *
+     * @param id           Unique identifier of the resource.
+     * @param resourceName Descriptive name of the resource.
+     * @param orgId        Identifier of the organization the resource belongs to.
+     * @param appId        Identifier of the application the resource is associated with.
+     */
+    public MockResource(int id, String resourceName, String orgId, String appId) {
+
+        this(id, resourceName, orgId);
+        this.appId = appId;
+    }
+
+    /**
+     * Retrieves the unique identifier of the resource.
+     *
+     * @return The resource ID.
+     */
+    public int getId() {
+
+        return id;
+    }
+
+    /**
+     * Sets the unique identifier of the resource.
+     *
+     * @param id The resource ID to set.
+     */
+    public void setId(int id) {
+
+        this.id = id;
+    }
+
+    /**
+     * Retrieves the name of the resource.
+     *
+     * @return The resource name.
+     */
+    public String getResourceName() {
+
+        return resourceName;
+    }
+
+    /**
+     * Sets the name of the resource.
+     *
+     * @param resourceName The name to assign to the resource.
+     */
+    public void setResourceName(String resourceName) {
+
+        this.resourceName = resourceName;
+    }
+
+    /**
+     * Retrieves the organization ID associated with the resource.
+     *
+     * @return The organization ID.
+     */
+    public String getOrgId() {
+
+        return orgId;
+    }
+
+    /**
+     * Sets the organization ID associated with the resource.
+     *
+     * @param orgId The organization ID to set.
+     */
+    public void setOrgId(String orgId) {
+
+        this.orgId = orgId;
+    }
+
+    /**
+     * Retrieves the application ID associated with the resource.
+     *
+     * @return The application ID, or {@code null} if the resource is not associated with a specific application.
+     */
+    public String getAppId() {
+
+        return appId;
+    }
+
+    /**
+     * Sets the application ID associated with the resource.
+     *
+     * @param appId The application ID to set.
+     */
+    public void setAppId(String appId) {
+
+        this.appId = appId;
+    }
+}
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/resources/testng.xml b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/resources/testng.xml
index 5f83a467d..7ef88e30e 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/resources/testng.xml
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/resources/testng.xml
@@ -21,6 +21,7 @@
 <suite name="org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.suite">
     <test name="org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.tests" preserve-order="true" parallel="false">
         <classes>
+            <class name="org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.OrgResourceResolverHierarchyServiceTest"/>
         </classes>
     </test>
 </suite>

From fc14805753bb82ff53a2bbd6fba2a5592c5de2ef Mon Sep 17 00:00:00 2001
From: dhaura <dhaurapathirana@gmail.com>
Date: Fri, 22 Nov 2024 13:27:56 +0530
Subject: [PATCH 05/18] Add unit test comments.

---
 ...gResourceResolverHierarchyServiceTest.java | 121 +++++++++++++++++-
 1 file changed, 119 insertions(+), 2 deletions(-)

diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverHierarchyServiceTest.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverHierarchyServiceTest.java
index 1d4f38039..1f0aff680 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverHierarchyServiceTest.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverHierarchyServiceTest.java
@@ -147,12 +147,17 @@ public Object[][] provideAggregationStrategies() {
         };
     }
 
+    /**
+     * Tests the behavior of the OrgResourceResolver when no resources are available in the organization hierarchy.
+     * <p>
+     * This test ensures that the resolver correctly returns null when no resources are found at any organization level.
+     *
+     * @param aggregationStrategy The aggregation strategy used to resolve resources.
+     */
     @Test(dataProvider = "AggregationStrategyDataProvider")
     public void testGetOrgLevelResourcesFromOrgHierarchyWhenNoResourceAvailable(
             AggregationStrategy<MockResource> aggregationStrategy) throws Exception {
 
-        // No resources available in the mock resource management service.
-
         MockResource resolvedRootResource = invokeOrgLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID);
         assertNull(resolvedRootResource);
 
@@ -163,6 +168,14 @@ public void testGetOrgLevelResourcesFromOrgHierarchyWhenNoResourceAvailable(
         assertNull(resolvedL2Resource);
     }
 
+    /**
+     * Tests the behavior of the OrgResourceResolver when an organization-level resource is available at the root organization level.
+     * <p>
+     * This test ensures that the resolver correctly returns the resource for the root organization and propagates
+     * the resolution to its child organizations (L1 and L2) using the given aggregation strategy.
+     *
+     * @param aggregationStrategy The aggregation strategy used to resolve resources.
+     */
     @Test(dataProvider = "AggregationStrategyDataProvider")
     public void testGetOrgLevelResourcesFromOrgHierarchyWhenRootResourceAvailable(
             AggregationStrategy<MockResource> aggregationStrategy) throws Exception {
@@ -180,6 +193,16 @@ public void testGetOrgLevelResourcesFromOrgHierarchyWhenRootResourceAvailable(
         assertResolvedResponse(resolvedL2Resource, createdOrgResource.get(0));
     }
 
+    /**
+     * Tests the behavior of the OrgResourceResolver when an organization-level resource is available at the
+     * L1 organization.
+     * <p>
+     * This test ensures that when a resource is available at the L1 level, it is correctly resolved for
+     * L1, and L2 organizations according to the provided aggregation strategy. At the root level,
+     * its own resource should be returned.
+     *
+     * @param aggregationStrategy The aggregation strategy used to resolve resources.
+     */
     @Test(dataProvider = "AggregationStrategyDataProvider")
     public void testGetOrgLevelResourcesFromOrgHierarchyWhenL1OrgResourceAvailable(
             AggregationStrategy<MockResource> aggregationStrategy) throws Exception {
@@ -197,6 +220,16 @@ public void testGetOrgLevelResourcesFromOrgHierarchyWhenL1OrgResourceAvailable(
         assertResolvedResponse(resolvedL2Resource, createdOrgResources.get(1));
     }
 
+    /**
+     * Tests the behavior of the OrgResourceResolver when an organization-level resource is available at the
+     * L2 organization.
+     * <p>
+     * This test ensures that when a resource is available at the L2 level, it is correctly resolved for the
+     * L2 organization based on the provided aggregation strategy.
+     * At the root and L1 level, their own resource should be returned.
+     *
+     * @param aggregationStrategy The aggregation strategy used to resolve resources.
+     */
     @Test(dataProvider = "AggregationStrategyDataProvider")
     public void testGetOrgLevelResourcesFromOrgHierarchyWhenL2OrgResourceAvailable(
             AggregationStrategy<MockResource> aggregationStrategy) throws Exception {
@@ -214,6 +247,15 @@ public void testGetOrgLevelResourcesFromOrgHierarchyWhenL2OrgResourceAvailable(
         assertResolvedResponse(resolvedL2Resource, createdOrgResources.get(2));
     }
 
+    /**
+     * Tests the behavior of the OrgResourceResolver when no application-level or organization-level resources
+     * are available in the hierarchy.
+     * <p>
+     * This test ensures that when no resources are available at the organization or application levels,
+     * the resolver correctly returns null.
+     *
+     * @param aggregationStrategy The aggregation strategy used to resolve resources.
+     */
     @Test(dataProvider = "AggregationStrategyDataProvider")
     public void testGetAppLevelResourcesFromOrgHierarchyWhenNoResourceAvailable(
             AggregationStrategy<MockResource> aggregationStrategy) throws Exception {
@@ -229,6 +271,15 @@ public void testGetAppLevelResourcesFromOrgHierarchyWhenNoResourceAvailable(
         assertNull(resolvedL2AppResource);
     }
 
+    /**
+     * Tests the behavior of the OrgResourceResolver when resources are available at both root organization and/ or
+     * root application levels in the organization hierarchy.
+     * <p>
+     * This test verifies that when resources are available for the root level, they are correctly resolved at the
+     * organization and application levels across all organization levels (root, L1, and L2).
+     *
+     * @param aggregationStrategy The aggregation strategy used to resolve resources at different levels.
+     */
     @Test(dataProvider = "AggregationStrategyDataProvider")
     public void testGetAppLevelResourcesFromOrgHierarchyWhenRootResourcesAvailable(
             AggregationStrategy<MockResource> aggregationStrategy) throws Exception {
@@ -261,6 +312,16 @@ public void testGetAppLevelResourcesFromOrgHierarchyWhenRootResourcesAvailable(
         assertResolvedResponse(resolvedL2AppResource, createdAppResource.get(0));
     }
 
+    /**
+     * Tests the behavior of the OrgResourceResolver when organization-level and/ or application-level resources
+     * are available for both root and L1 organizations in the hierarchy.
+     * <p>
+     * This test ensures when resources are available for the L1 level, they are correctly resolved at the
+     * organization and application levels across both organization levels, L1, and L2. At the root level,
+     * its own resource should be returned.
+     *
+     * @param aggregationStrategy The aggregation strategy used to resolve resources at different levels.
+     */
     @Test(dataProvider = "AggregationStrategyDataProvider")
     public void testGetAppLevelResourcesFromOrgHierarchyWhenL1ResourcesAvailable(
             AggregationStrategy<MockResource> aggregationStrategy) throws Exception {
@@ -296,6 +357,16 @@ public void testGetAppLevelResourcesFromOrgHierarchyWhenL1ResourcesAvailable(
         assertResolvedResponse(resolvedL2AppResource, createdAppResources.get(1));
     }
 
+    /**
+     * Tests the behavior of the OrgResourceResolver when organization-level and/ or application-level resources
+     * are available for all organization levels in the hierarchy.
+     * <p>
+     * This test ensures that when a resource is available at the L2 level, it is correctly resolved for the
+     * L2 organization based on the provided aggregation strategy. At the root and L1 level, their own resources
+     * should be returned.
+     *
+     * @param aggregationStrategy The aggregation strategy used to resolve resources at different levels.
+     */
     @Test(dataProvider = "AggregationStrategyDataProvider")
     public void testGetAppLevelResourcesFromOrgHierarchyWhenL2ResourcesAvailable(
             AggregationStrategy<MockResource> aggregationStrategy) throws Exception {
@@ -342,6 +413,16 @@ public Object[][] provideAggregationStrategiesForOrgLevelResolverWithInvalidInpu
         };
     }
 
+    /**
+     * Tests the behavior of the OrgResourceResolver when provided with invalid organization IDs.
+     * <p>
+     * This test ensures that when invalid organization IDs are passed to the resolver, it correctly returns null,
+     * indicating that no resources are found for the invalid input.
+     *
+     * @param aggregationStrategy The aggregation strategy used to resolve resources at different levels.
+     * @param invalidOrgIds       A list of invalid organization IDs to test the resolver's behavior.
+     * @throws Exception If an error occurs during resolution.
+     */
     @Test(dataProvider = "provideAggregationStrategiesForOrgLevelResolverWithInvalidInput")
     public void testGetOrgLevelResourcesFromOrgHierarchyForInvalidInput(
             AggregationStrategy<MockResource> aggregationStrategy, List<String> invalidOrgIds) throws Exception {
@@ -364,6 +445,20 @@ public Object[][] provideAggregationStrategiesForAppLevelResolverWithInvalidInpu
         };
     }
 
+    /**
+     * Tests the behavior of the OrgResourceResolver when provided with invalid organization and application IDs.
+     * <p>
+     * This test verifies that the resolver correctly handles invalid input combinations by returning null,
+     * ensuring robustness and appropriate error handling in edge cases. The test covers scenarios where:
+     * - The organization ID is invalid.
+     * - The application ID is invalid.
+     * - Both the organization and application IDs are invalid.
+     *
+     * @param aggregationStrategy The aggregation strategy used to resolve resources across the hierarchy.
+     * @param invalidOrgIds       A list of invalid organization IDs to test the resolver's behavior.
+     * @param invalidAppIds       A list of invalid application IDs to test the resolver's behavior.
+     * @throws Exception If an error occurs during resolution.
+     */
     @Test(dataProvider = "provideAggregationStrategiesForAppLevelResolverWithInvalidInput")
     public void testGetAppLevelResourcesFromOrgHierarchyForInvalidInput(
             AggregationStrategy<MockResource> aggregationStrategy, List<String> invalidOrgIds,
@@ -378,6 +473,17 @@ public void testGetAppLevelResourcesFromOrgHierarchyForInvalidInput(
         }
     }
 
+    /**
+     * Tests the behavior of the OrgResourceResolver when server-side errors occur during
+     * organizational hierarchy traversal.
+     * <p>
+     * This test simulates server-side exceptions thrown by the `organizationManager` during the following scenarios:
+     * - Fetching the depth of an organization within the hierarchy.
+     * - Retrieving ancestor organization IDs.
+     *
+     * @param aggregationStrategy The aggregation strategy used for resolving resources.
+     * @throws Exception If an unexpected error occurs.
+     */
     @Test(dataProvider = "AggregationStrategyDataProvider")
     public void testGetOrgLevelResourcesFromOrgHierarchyWhenServerErrorOccurs(
             AggregationStrategy<MockResource> aggregationStrategy) throws Exception {
@@ -401,6 +507,17 @@ public void testGetOrgLevelResourcesFromOrgHierarchyWhenServerErrorOccurs(
                 () -> invokeOrgLevelResourceResolver(aggregationStrategy, L2_ORG_ID));
     }
 
+    /**
+     * Tests the behavior of the OrgResourceResolver when server-side errors occur during
+     * application hierarchy traversal within an organization.
+     * <p>
+     * This test simulates server-side exceptions thrown by the following:
+     * - The `applicationManagementService` while retrieving ancestor application IDs.
+     * - The `organizationManager` while retrieving ancestor organization IDs.
+     *
+     * @param aggregationStrategy The aggregation strategy used for resolving resources.
+     * @throws Exception If an unexpected error occurs.
+     */
     @Test(dataProvider = "AggregationStrategyDataProvider")
     public void testGetAppLevelResourcesFromOrgHierarchyWhenServerErrorOccurs(
             AggregationStrategy<MockResource> aggregationStrategy) throws Exception {

From 15770641687e0e8f48392efbf3555944d31d7fec Mon Sep 17 00:00:00 2001
From: dhaura <dhaurapathirana@gmail.com>
Date: Fri, 22 Nov 2024 13:31:24 +0530
Subject: [PATCH 06/18] Improve OrgResourceResolverService comments.

---
 .../traverse/service/OrgResourceResolverService.java          | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverService.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverService.java
index cb6646d5f..873276d05 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverService.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverService.java
@@ -57,8 +57,8 @@ <T> T getResourcesFromOrgHierarchy(String organizationId,
     /**
      * Retrieves resources by traversing the hierarchy of a given organization and application.
      *
-     * @param organizationId      The unique identifier of the organization. Must not be null.
-     * @param applicationId       The unique identifier of the application within the organization. Must not be null.
+     * @param organizationId      The unique identifier of the organization.
+     * @param applicationId       The unique identifier of the application within the organization.
      * @param resourceRetriever   A bi-function that defines how to fetch a resource based on the
      *                            organization and application IDs. The function must return an
      *                            {@link Optional<T>} containing the resource if found,

From 1d653e05344a00da51c6b0d83f4d71f363474e6d Mon Sep 17 00:00:00 2001
From: dhaura <dhaurapathirana@gmail.com>
Date: Fri, 22 Nov 2024 14:11:26 +0530
Subject: [PATCH 07/18] Fix checkstyle issues and rename test class to
 OrgResourceResolverServiceTest.

---
 ...va => OrgResourceResolverServiceTest.java} | 32 ++++++++++---------
 1 file changed, 17 insertions(+), 15 deletions(-)
 rename components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/{OrgResourceResolverHierarchyServiceTest.java => OrgResourceResolverServiceTest.java} (95%)

diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverHierarchyServiceTest.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java
similarity index 95%
rename from components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverHierarchyServiceTest.java
rename to components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java
index 1f0aff680..b65416c78 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverHierarchyServiceTest.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java
@@ -56,9 +56,9 @@
 import static org.testng.Assert.assertThrows;
 
 /**
- * Unit tests for the OrgResourceResolverHierarchyService.
+ * Unit tests for the OrgResourceResolverServiceTest.
  */
-public class OrgResourceResolverHierarchyServiceTest {
+public class OrgResourceResolverServiceTest {
 
     private static final String ROOT_ORG_ID = "10084a8d-113f-4211-a0d5-efe36b082211";
     private static final String ROOT_APP_ID = "1ee981ab-64e7-435c-ab91-e8d1e0a13b2c";
@@ -148,7 +148,8 @@ public Object[][] provideAggregationStrategies() {
     }
 
     /**
-     * Tests the behavior of the OrgResourceResolver when no resources are available in the organization hierarchy.
+     * Tests the behavior of the OrgResourceResolverService when no resources are available in the
+     * organization hierarchy.
      * <p>
      * This test ensures that the resolver correctly returns null when no resources are found at any organization level.
      *
@@ -169,7 +170,8 @@ public void testGetOrgLevelResourcesFromOrgHierarchyWhenNoResourceAvailable(
     }
 
     /**
-     * Tests the behavior of the OrgResourceResolver when an organization-level resource is available at the root organization level.
+     * Tests the behavior of the OrgResourceResolverService when an organization-level resource is available at the
+     * root organization level.
      * <p>
      * This test ensures that the resolver correctly returns the resource for the root organization and propagates
      * the resolution to its child organizations (L1 and L2) using the given aggregation strategy.
@@ -194,7 +196,7 @@ public void testGetOrgLevelResourcesFromOrgHierarchyWhenRootResourceAvailable(
     }
 
     /**
-     * Tests the behavior of the OrgResourceResolver when an organization-level resource is available at the
+     * Tests the behavior of the OrgResourceResolverService when an organization-level resource is available at the
      * L1 organization.
      * <p>
      * This test ensures that when a resource is available at the L1 level, it is correctly resolved for
@@ -221,7 +223,7 @@ public void testGetOrgLevelResourcesFromOrgHierarchyWhenL1OrgResourceAvailable(
     }
 
     /**
-     * Tests the behavior of the OrgResourceResolver when an organization-level resource is available at the
+     * Tests the behavior of the OrgResourceResolverService when an organization-level resource is available at the
      * L2 organization.
      * <p>
      * This test ensures that when a resource is available at the L2 level, it is correctly resolved for the
@@ -248,7 +250,7 @@ public void testGetOrgLevelResourcesFromOrgHierarchyWhenL2OrgResourceAvailable(
     }
 
     /**
-     * Tests the behavior of the OrgResourceResolver when no application-level or organization-level resources
+     * Tests the behavior of the OrgResourceResolverService when no application-level or organization-level resources
      * are available in the hierarchy.
      * <p>
      * This test ensures that when no resources are available at the organization or application levels,
@@ -272,8 +274,8 @@ public void testGetAppLevelResourcesFromOrgHierarchyWhenNoResourceAvailable(
     }
 
     /**
-     * Tests the behavior of the OrgResourceResolver when resources are available at both root organization and/ or
-     * root application levels in the organization hierarchy.
+     * Tests the behavior of the OrgResourceResolverService when resources are available at both root organization
+     * and/ or root application levels in the organization hierarchy.
      * <p>
      * This test verifies that when resources are available for the root level, they are correctly resolved at the
      * organization and application levels across all organization levels (root, L1, and L2).
@@ -313,7 +315,7 @@ public void testGetAppLevelResourcesFromOrgHierarchyWhenRootResourcesAvailable(
     }
 
     /**
-     * Tests the behavior of the OrgResourceResolver when organization-level and/ or application-level resources
+     * Tests the behavior of the OrgResourceResolverService when organization-level and/ or application-level resources
      * are available for both root and L1 organizations in the hierarchy.
      * <p>
      * This test ensures when resources are available for the L1 level, they are correctly resolved at the
@@ -358,7 +360,7 @@ public void testGetAppLevelResourcesFromOrgHierarchyWhenL1ResourcesAvailable(
     }
 
     /**
-     * Tests the behavior of the OrgResourceResolver when organization-level and/ or application-level resources
+     * Tests the behavior of the OrgResourceResolverService when organization-level and/ or application-level resources
      * are available for all organization levels in the hierarchy.
      * <p>
      * This test ensures that when a resource is available at the L2 level, it is correctly resolved for the
@@ -414,7 +416,7 @@ public Object[][] provideAggregationStrategiesForOrgLevelResolverWithInvalidInpu
     }
 
     /**
-     * Tests the behavior of the OrgResourceResolver when provided with invalid organization IDs.
+     * Tests the behavior of the OrgResourceResolverService when provided with invalid organization IDs.
      * <p>
      * This test ensures that when invalid organization IDs are passed to the resolver, it correctly returns null,
      * indicating that no resources are found for the invalid input.
@@ -446,7 +448,7 @@ public Object[][] provideAggregationStrategiesForAppLevelResolverWithInvalidInpu
     }
 
     /**
-     * Tests the behavior of the OrgResourceResolver when provided with invalid organization and application IDs.
+     * Tests the behavior of the OrgResourceResolverService when provided with invalid organization and application IDs.
      * <p>
      * This test verifies that the resolver correctly handles invalid input combinations by returning null,
      * ensuring robustness and appropriate error handling in edge cases. The test covers scenarios where:
@@ -474,7 +476,7 @@ public void testGetAppLevelResourcesFromOrgHierarchyForInvalidInput(
     }
 
     /**
-     * Tests the behavior of the OrgResourceResolver when server-side errors occur during
+     * Tests the behavior of the OrgResourceResolverService when server-side errors occur during
      * organizational hierarchy traversal.
      * <p>
      * This test simulates server-side exceptions thrown by the `organizationManager` during the following scenarios:
@@ -508,7 +510,7 @@ public void testGetOrgLevelResourcesFromOrgHierarchyWhenServerErrorOccurs(
     }
 
     /**
-     * Tests the behavior of the OrgResourceResolver when server-side errors occur during
+     * Tests the behavior of the OrgResourceResolverService when server-side errors occur during
      * application hierarchy traversal within an organization.
      * <p>
      * This test simulates server-side exceptions thrown by the following:

From 22415d3011be8fb2e87c9962304baaa44ff5b3ac Mon Sep 17 00:00:00 2001
From: dhaura <dhaurapathirana@gmail.com>
Date: Fri, 22 Nov 2024 14:14:20 +0530
Subject: [PATCH 08/18] Apply test name change in testng.xml.

---
 .../src/test/resources/testng.xml                               | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/resources/testng.xml b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/resources/testng.xml
index 7ef88e30e..539837328 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/resources/testng.xml
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/resources/testng.xml
@@ -21,7 +21,7 @@
 <suite name="org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.suite">
     <test name="org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.tests" preserve-order="true" parallel="false">
         <classes>
-            <class name="org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.OrgResourceResolverHierarchyServiceTest"/>
+            <class name="org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.OrgResourceResolverServiceTest"/>
         </classes>
     </test>
 </suite>

From b71a3cc569970deebeabd78654a501fc1579a9b6 Mon Sep 17 00:00:00 2001
From: dhaura <dhaurapathirana@gmail.com>
Date: Fri, 22 Nov 2024 15:05:00 +0530
Subject: [PATCH 09/18] Add missing fullstops in comments.

---
 .../service/OrgResourceResolverServiceTest.java    | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java
index b65416c78..b75f366d5 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java
@@ -87,7 +87,7 @@ public class OrgResourceResolverServiceTest {
     @BeforeClass
     public void init() {
 
-        // Open mock objects for the current test instance
+        // Open mock objects for the current test instance.
         openMocks(this);
 
         // Set the OrganizationManager and ApplicationManagementService to the data holder for use in tests
@@ -95,7 +95,7 @@ public void init() {
         OrgResourceHierarchyTraverseServiceDataHolder.getInstance()
                 .setApplicationManagementService(applicationManagementService);
 
-        // Initialize the aggregation strategies with the appropriate strategy types
+        // Initialize the aggregation strategies with the appropriate strategy types.
         firstFoundAggregationStrategy = new FirstFoundAggregationStrategy<>();
         mergeAllAggregationStrategy = new MergeAllAggregationStrategy<>(this::resourceMerger);
     }
@@ -107,12 +107,12 @@ public void init() {
     @BeforeMethod
     public void setUp() throws Exception {
 
-        // Mock responses for the organization manager with different ancestor organization chains
+        // Mock responses for the organization manager with different ancestor organization chains.
         mockAncestorOrganizationRetrieval(Arrays.asList(L2_ORG_ID, L1_ORG_ID, ROOT_ORG_ID));
         mockAncestorOrganizationRetrieval(Arrays.asList(L1_ORG_ID, ROOT_ORG_ID));
         mockAncestorOrganizationRetrieval(Collections.singletonList(ROOT_ORG_ID));
 
-        // Mock responses for the application management service with corresponding application ancestor data
+        // Mock responses for the application management service with corresponding application ancestor data.
         mockAncestorApplicationRetrieval(Arrays.asList(L2_ORG_ID, L1_ORG_ID, ROOT_ORG_ID),
                 Arrays.asList(L2_APP_ID, L1_APP_ID, ROOT_APP_ID));
         mockAncestorApplicationRetrieval(Arrays.asList(L1_ORG_ID, ROOT_ORG_ID),
@@ -120,10 +120,10 @@ public void setUp() throws Exception {
         mockAncestorApplicationRetrieval(Collections.singletonList(ROOT_ORG_ID),
                 Collections.singletonList(ROOT_APP_ID));
 
-        // Initialize the mock resource management service used in tests
+        // Initialize the mock resource management service used in tests.
         mockResourceManagementService = new MockResourceManagementService();
 
-        // Instantiate the OrgResourceResolverService for testing
+        // Instantiate the OrgResourceResolverService for testing.
         orgResourceResolverService = new OrgResourceResolverServiceImpl();
     }
 
@@ -133,7 +133,7 @@ public void setUp() throws Exception {
     @AfterMethod
     public void tearDown() {
 
-        // Reset the mock services to their default state after each test
+        // Reset the mock services to their default state after each test.
         reset(organizationManager);
         reset(applicationManagementService);
     }

From 4c9316748b5baaf015d84999bc707b60a5766155 Mon Sep 17 00:00:00 2001
From: dhaura <dhaurapathirana@gmail.com>
Date: Fri, 22 Nov 2024 15:18:18 +0530
Subject: [PATCH 10/18] Improve assertResolvedResponse method.

---
 .../traverse/service/OrgResourceResolverServiceTest.java     | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java
index b75f366d5..e9014c020 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java
@@ -681,11 +681,6 @@ private MockResource invokeAppLevelResourceResolver(AggregationStrategy<MockReso
      */
     private void assertResolvedResponse(MockResource resolvedResource, MockResource actualResource) {
 
-        if (actualResource == null) {
-            assertNull(resolvedResource);
-            return;
-        }
-
         assertNotNull(resolvedResource);
         assertEquals(resolvedResource.getId(), actualResource.getId());
         assertEquals(resolvedResource.getResourceName(), actualResource.getResourceName());

From 7f071c12cfb1addd1c4ac523e7d26ed9581affb8 Mon Sep 17 00:00:00 2001
From: dhaura <dhaurapathirana@gmail.com>
Date: Mon, 25 Nov 2024 12:30:41 +0530
Subject: [PATCH 11/18] Improve NotImplementedException comments.

---
 .../exception/NotImplementedException.java    | 27 ++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/NotImplementedException.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/NotImplementedException.java
index bc937175b..d72bf48b5 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/NotImplementedException.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/NotImplementedException.java
@@ -19,30 +19,51 @@
 package org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception;
 
 /**
- * The exception to throw when the code is not implemented.
+ * A custom runtime exception to indicate that a method or functionality is not yet implemented.
  */
 public class NotImplementedException extends RuntimeException {
 
-    private static final long serialVersionUID = 5117918786934510964L;
+    private static final long serialVersionUID = 5117918786934518376L;
 
+    /**
+     * Constructs a new NotImplementedException with no detail message or cause.
+     *
+     * <p>This constructor is typically used when no additional information is required
+     * to explain why the exception is thrown.
+     */
     public NotImplementedException() {
 
         super();
     }
 
+    /**
+     * Constructs a new NotImplementedException with a detailed message and the root cause.
+     *
+     * @param message A descriptive message explaining why this exception is thrown.
+     * @param cause   The underlying cause of this exception.
+     */
     public NotImplementedException(String message, Throwable cause) {
 
         super(message, cause);
     }
 
+    /**
+     * Constructs a new NotImplementedException with a detailed message.
+     *
+     * @param message A descriptive message explaining why this exception is thrown.
+     */
     public NotImplementedException(String message) {
 
         super(message);
     }
 
+    /**
+     * Constructs a new NotImplementedException with the root cause.
+     *
+     * @param cause The underlying cause of this exception.
+     */
     public NotImplementedException(Throwable cause) {
 
         super(cause);
     }
-
 }

From c145e9fd21a798f3ece22337ae8a8fc372fc2db5 Mon Sep 17 00:00:00 2001
From: dhaura <dhaurapathirana@gmail.com>
Date: Tue, 26 Nov 2024 17:13:51 +0530
Subject: [PATCH 12/18] Handle invalid organization ids as error scenarios.

---
 .../OrgResourceResolverServiceImpl.java       | 46 ++++++++++---------
 ...OrgResourceHierarchyTraverseConstants.java | 13 +++++-
 .../OrgResourceHierarchyTraverseUtil.java     | 20 ++++++++
 .../OrgResourceResolverServiceTest.java       | 13 +++---
 4 files changed, 61 insertions(+), 31 deletions(-)

diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceImpl.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceImpl.java
index b4974135a..689ddbec3 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceImpl.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceImpl.java
@@ -19,12 +19,14 @@
 package org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service;
 
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
 import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException;
 import org.wso2.carbon.identity.application.mgt.ApplicationManagementService;
 import org.wso2.carbon.identity.organization.management.service.OrganizationManager;
 import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementServerException;
 import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.constant.OrgResourceHierarchyTraverseConstants;
 import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception.OrgResourceHierarchyTraverseException;
+import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception.OrgResourceHierarchyTraverseServerException;
 import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.internal.OrgResourceHierarchyTraverseServiceDataHolder;
 import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.strategy.AggregationStrategy;
 import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.util.OrgResourceHierarchyTraverseUtil;
@@ -47,18 +49,8 @@ public <T> T getResourcesFromOrgHierarchy(String organizationId, Function<String
                                               AggregationStrategy<T> aggregationStrategy)
             throws OrgResourceHierarchyTraverseException {
 
-        try {
-            List<String> organizationIds = getAncestorOrganizationsIds(organizationId);
-            if (CollectionUtils.isEmpty(organizationIds) || organizationIds.isEmpty()) {
-                return null;
-            }
-
-            return aggregationStrategy.aggregate(organizationIds, resourceRetriever);
-        } catch (OrganizationManagementServerException e) {
-            throw OrgResourceHierarchyTraverseUtil.handleServerException(
-                    OrgResourceHierarchyTraverseConstants.ErrorMessages
-                            .ERROR_CODE_SERVER_ERROR_WHILE_RESOLVING_ANCESTOR_ORGANIZATIONS, e, organizationId);
-        }
+        List<String> organizationIds = getAncestorOrganizationsIds(organizationId);
+        return aggregationStrategy.aggregate(organizationIds, resourceRetriever);
     }
 
     @Override
@@ -69,9 +61,6 @@ public <T> T getResourcesFromOrgHierarchy(String organizationId, String applicat
 
         try {
             List<String> organizationIds = getAncestorOrganizationsIds(organizationId);
-            if (CollectionUtils.isEmpty(organizationIds) || organizationIds.isEmpty()) {
-                return null;
-            }
 
             ApplicationManagementService applicationManagementService = getApplicationManagementService();
             Map<String, String> ancestorAppIds = Collections.emptyMap();
@@ -80,10 +69,6 @@ public <T> T getResourcesFromOrgHierarchy(String organizationId, String applicat
             }
 
             return aggregationStrategy.aggregate(organizationIds, ancestorAppIds, resourceRetriever);
-        } catch (OrganizationManagementServerException e) {
-            throw OrgResourceHierarchyTraverseUtil.handleServerException(
-                    OrgResourceHierarchyTraverseConstants.ErrorMessages
-                            .ERROR_CODE_SERVER_ERROR_WHILE_RESOLVING_ANCESTOR_ORGANIZATIONS, e, organizationId);
         } catch (IdentityApplicationManagementException e) {
             throw OrgResourceHierarchyTraverseUtil.handleServerException(
                     OrgResourceHierarchyTraverseConstants.ErrorMessages
@@ -93,10 +78,27 @@ public <T> T getResourcesFromOrgHierarchy(String organizationId, String applicat
     }
 
     private List<String> getAncestorOrganizationsIds(String organizationId)
-            throws OrganizationManagementServerException {
+            throws OrgResourceHierarchyTraverseServerException {
 
-        OrganizationManager organizationManager = OrgResourceHierarchyTraverseUtil.getOrganizationManager();
-        return organizationManager.getAncestorOrganizationIds(organizationId);
+        if (StringUtils.isBlank(organizationId)) {
+            throw OrgResourceHierarchyTraverseUtil.handleServerException(
+                    OrgResourceHierarchyTraverseConstants.ErrorMessages.ERROR_CODE_EMPTY_ORGANIZATION_ID);
+        }
+
+        try {
+            OrganizationManager organizationManager = OrgResourceHierarchyTraverseUtil.getOrganizationManager();
+            List<String> organizationIds = organizationManager.getAncestorOrganizationIds(organizationId);
+            if (CollectionUtils.isEmpty(organizationIds) || organizationIds.isEmpty()) {
+                throw OrgResourceHierarchyTraverseUtil.handleServerException(OrgResourceHierarchyTraverseConstants
+                                .ErrorMessages.ERROR_CODE_INVALID_ANCESTOR_ORGANIZATION_ID_LIST,
+                        organizationId);
+            }
+            return organizationIds;
+        } catch (OrganizationManagementServerException e) {
+            throw OrgResourceHierarchyTraverseUtil.handleServerException(
+                    OrgResourceHierarchyTraverseConstants.ErrorMessages
+                            .ERROR_CODE_SERVER_ERROR_WHILE_RESOLVING_ANCESTOR_ORGANIZATIONS, e, organizationId);
+        }
     }
 
     private ApplicationManagementService getApplicationManagementService() {
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/constant/OrgResourceHierarchyTraverseConstants.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/constant/OrgResourceHierarchyTraverseConstants.java
index ef91a2fd0..3c96c658c 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/constant/OrgResourceHierarchyTraverseConstants.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/constant/OrgResourceHierarchyTraverseConstants.java
@@ -40,13 +40,22 @@ private OrgResourceHierarchyTraverseConstants() {
     public enum ErrorMessages {
 
         // Server errors.
-        ERROR_CODE_SERVER_ERROR_WHILE_RESOLVING_ANCESTOR_ORGANIZATIONS(
+        ERROR_CODE_EMPTY_ORGANIZATION_ID(
                 "65001",
+                "Empty organization id.",
+                "Organization id cannot be null or empty."),
+        ERROR_CODE_INVALID_ANCESTOR_ORGANIZATION_ID_LIST(
+                "65002",
+                "Invalid ancestor organization id list.",
+                "The ancestor organization id list cannot be empty for the organization with id: %s. " +
+                        "At least the organization itself should be included in the list."),
+        ERROR_CODE_SERVER_ERROR_WHILE_RESOLVING_ANCESTOR_ORGANIZATIONS(
+                "65003",
                 "Unable to resolve ancestor organizations.",
                 "Unexpected server error occurred " +
                         "while resolving ancestor organizations for organization with id: %s."),
         ERROR_CODE_SERVER_ERROR_WHILE_RESOLVING_ANCESTOR_APPLICATIONS(
-                "65002",
+                "65004",
                 "Unable to resolve ancestor applications.",
                 "Unexpected server error occurred while resolving ancestor applications for organization " +
                         "with id: %s for application with id: %s.");
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/util/OrgResourceHierarchyTraverseUtil.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/util/OrgResourceHierarchyTraverseUtil.java
index b48159dc8..7324900a5 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/util/OrgResourceHierarchyTraverseUtil.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/util/OrgResourceHierarchyTraverseUtil.java
@@ -81,6 +81,26 @@ public static boolean isMinOrgHierarchyDepthReached(String orgId) throws
      * a custom exception for consistent error handling in the service.
      *
      * @param error The error enumeration containing predefined error messages and codes.
+     * @param data  Optional data to format the error message description.
+     * @return An {@link OrgResourceHierarchyTraverseServerException} with the formatted error details.
+     */
+    public static OrgResourceHierarchyTraverseServerException handleServerException(
+            OrgResourceHierarchyTraverseConstants.ErrorMessages error, String... data) {
+
+        String description = error.getDescription();
+        if (ArrayUtils.isNotEmpty(data)) {
+            description = String.format(description, data);
+        }
+        return new OrgResourceHierarchyTraverseServerException(error.getMessage(), description, error.getCode());
+    }
+
+    /**
+     * Create an {@link OrgResourceHierarchyTraverseServerException} to handle server-side errors.
+     * <p>
+     * This method formats the error description using the provided data, if applicable, and constructs
+     * a custom exception including the underlying cause of the error, for consistent error handling in the service.
+     *
+     * @param error The error enumeration containing predefined error messages and codes.
      * @param e     The underlying cause of the error.
      * @param data  Optional data to format the error message description.
      * @return An {@link OrgResourceHierarchyTraverseServerException} with the formatted error details.
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java
index e9014c020..825e81b03 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java
@@ -56,7 +56,7 @@
 import static org.testng.Assert.assertThrows;
 
 /**
- * Unit tests for the OrgResourceResolverServiceTest.
+ * Unit tests for the OrgResourceResolverService.
  */
 public class OrgResourceResolverServiceTest {
 
@@ -430,8 +430,8 @@ public void testGetOrgLevelResourcesFromOrgHierarchyForInvalidInput(
             AggregationStrategy<MockResource> aggregationStrategy, List<String> invalidOrgIds) throws Exception {
 
         for (String orgId : invalidOrgIds) {
-            MockResource resolvedResource = invokeOrgLevelResourceResolver(aggregationStrategy, orgId);
-            assertNull(resolvedResource);
+            assertThrows(OrgResourceHierarchyTraverseServerException.class,
+                    () -> invokeOrgLevelResourceResolver(aggregationStrategy, orgId));
         }
     }
 
@@ -468,9 +468,8 @@ public void testGetAppLevelResourcesFromOrgHierarchyForInvalidInput(
 
         for (String invalidOrgId : invalidOrgIds) {
             for (String invalidAppId : invalidAppIds) {
-                MockResource resolvedResource =
-                        invokeAppLevelResourceResolver(aggregationStrategy, invalidOrgId, invalidAppId);
-                assertNull(resolvedResource);
+                assertThrows(OrgResourceHierarchyTraverseServerException.class,
+                        () -> invokeAppLevelResourceResolver(aggregationStrategy, invalidOrgId, invalidAppId));
             }
         }
     }
@@ -643,7 +642,7 @@ private MockResource invokeOrgLevelResourceResolver(AggregationStrategy<MockReso
 
         return orgResourceResolverService.getResourcesFromOrgHierarchy(
                 organizationId,
-                (orgId) -> {
+                orgId -> {
                     MockResource resource = mockResourceManagementService.getOrgResource(orgId);
                     return Optional.ofNullable(resource);
                 },

From b4aa7f9c143600f5ce181d2535c03f7548476aa2 Mon Sep 17 00:00:00 2001
From: dhaura <dhaurapathirana@gmail.com>
Date: Fri, 29 Nov 2024 17:41:37 +0530
Subject: [PATCH 13/18] Remove redundant org id list empty check.

---
 .../traverse/service/OrgResourceResolverServiceImpl.java      | 2 +-
 .../service/strategy/FirstFoundAggregationStrategy.java       | 4 ++--
 .../service/strategy/MergeAllAggregationStrategy.java         | 4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceImpl.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceImpl.java
index 689ddbec3..c1fb7c19f 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceImpl.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceImpl.java
@@ -88,7 +88,7 @@ private List<String> getAncestorOrganizationsIds(String organizationId)
         try {
             OrganizationManager organizationManager = OrgResourceHierarchyTraverseUtil.getOrganizationManager();
             List<String> organizationIds = organizationManager.getAncestorOrganizationIds(organizationId);
-            if (CollectionUtils.isEmpty(organizationIds) || organizationIds.isEmpty()) {
+            if (CollectionUtils.isEmpty(organizationIds)) {
                 throw OrgResourceHierarchyTraverseUtil.handleServerException(OrgResourceHierarchyTraverseConstants
                                 .ErrorMessages.ERROR_CODE_INVALID_ANCESTOR_ORGANIZATION_ID_LIST,
                         organizationId);
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/FirstFoundAggregationStrategy.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/FirstFoundAggregationStrategy.java
index cfd473cc2..efede0cb7 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/FirstFoundAggregationStrategy.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/FirstFoundAggregationStrategy.java
@@ -41,7 +41,7 @@ public class FirstFoundAggregationStrategy<T> implements AggregationStrategy<T>
     public T aggregate(List<String> organizationHierarchy, Function<String, Optional<T>> resourceRetriever)
             throws OrgResourceHierarchyTraverseException {
 
-        if (CollectionUtils.isEmpty(organizationHierarchy) || organizationHierarchy.isEmpty()) {
+        if (CollectionUtils.isEmpty(organizationHierarchy)) {
             return null;
         }
 
@@ -63,7 +63,7 @@ public T aggregate(List<String> organizationHierarchy, Map<String, String> appli
                        BiFunction<String, String, Optional<T>> resourceRetriever)
             throws OrgResourceHierarchyTraverseException {
 
-        if (CollectionUtils.isEmpty(organizationHierarchy) || organizationHierarchy.isEmpty()) {
+        if (CollectionUtils.isEmpty(organizationHierarchy)) {
             return null;
         }
 
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/MergeAllAggregationStrategy.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/MergeAllAggregationStrategy.java
index f911b2700..2d1ad9372 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/MergeAllAggregationStrategy.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/strategy/MergeAllAggregationStrategy.java
@@ -58,7 +58,7 @@ public T aggregate(List<String> organizationHierarchy, Function<String, Optional
             throws OrgResourceHierarchyTraverseException {
 
         T aggregatedResource = null;
-        if (CollectionUtils.isEmpty(organizationHierarchy) || organizationHierarchy.isEmpty()) {
+        if (CollectionUtils.isEmpty(organizationHierarchy)) {
             return aggregatedResource;
         }
 
@@ -85,7 +85,7 @@ public T aggregate(List<String> organizationHierarchy, Map<String, String> appli
             throws OrgResourceHierarchyTraverseException {
 
         T aggregatedResource = null;
-        if (CollectionUtils.isEmpty(organizationHierarchy) || organizationHierarchy.isEmpty()) {
+        if (CollectionUtils.isEmpty(organizationHierarchy)) {
             return aggregatedResource;
         }
 

From 3349bbdddf5aecf36ca2bc88732b07a374288385 Mon Sep 17 00:00:00 2001
From: dhaura <dhaurapathirana@gmail.com>
Date: Fri, 29 Nov 2024 17:54:01 +0530
Subject: [PATCH 14/18] Update pom version in traverse service.

---
 .../pom.xml                                                     | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml
index 233f0df56..3efbc72e6 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.wso2.carbon.identity.organization.management</groupId>
         <artifactId>identity-organization-management</artifactId>
-        <version>1.4.56-SNAPSHOT</version>
+        <version>1.4.57-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
 

From 938dc308459c20feb1fa02b2116a22ba884a80be Mon Sep 17 00:00:00 2001
From: dhaura <dhaurapathirana@gmail.com>
Date: Fri, 29 Nov 2024 18:08:18 +0530
Subject: [PATCH 15/18] Improve javadoc comments and variable naming.

---
 .../exception/NotImplementedException.java    |  4 +--
 ...ourceHierarchyTraverseClientException.java | 24 ++++++-------
 ...OrgResourceHierarchyTraverseException.java | 30 +++++++---------
 ...ourceHierarchyTraverseServerException.java | 18 +++++-----
 ...urceHierarchyTraverseServiceComponent.java | 22 ++++++------
 ...rceHierarchyTraverseServiceDataHolder.java | 10 +++---
 .../OrgResourceResolverServiceTest.java       | 34 +++++++++----------
 7 files changed, 67 insertions(+), 75 deletions(-)

diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/NotImplementedException.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/NotImplementedException.java
index d72bf48b5..c08cb203d 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/NotImplementedException.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/NotImplementedException.java
@@ -27,8 +27,8 @@ public class NotImplementedException extends RuntimeException {
 
     /**
      * Constructs a new NotImplementedException with no detail message or cause.
-     *
-     * <p>This constructor is typically used when no additional information is required
+     * <p>
+     * This constructor is typically used when no additional information is required
      * to explain why the exception is thrown.
      */
     public NotImplementedException() {
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseClientException.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseClientException.java
index 26ac0cd0d..30e459991 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseClientException.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseClientException.java
@@ -37,7 +37,7 @@ public class OrgResourceHierarchyTraverseClientException extends OrgResourceHier
     /**
      * Constructs a new exception with an array of specified error messages.
      *
-     * @param messages Detailed error messages
+     * @param messages Detailed error messages.
      */
     public OrgResourceHierarchyTraverseClientException(String[] messages) {
 
@@ -57,7 +57,7 @@ public OrgResourceHierarchyTraverseClientException(String[] messages) {
     /**
      * Constructs a new exception with the specified message.
      *
-     * @param message Detailed message
+     * @param message Detailed message.
      */
     public OrgResourceHierarchyTraverseClientException(String message) {
 
@@ -67,8 +67,8 @@ public OrgResourceHierarchyTraverseClientException(String message) {
     /**
      * Constructs a new exception with the specified message and cause.
      *
-     * @param message Detailed message
-     * @param e       Cause as {@link Throwable}
+     * @param message Detailed message.
+     * @param e       Cause as {@link Throwable}.
      */
     public OrgResourceHierarchyTraverseClientException(String message, Throwable e) {
 
@@ -78,8 +78,8 @@ public OrgResourceHierarchyTraverseClientException(String message, Throwable e)
     /**
      * Constructs a new exception with the specified error code and cause.
      *
-     * @param errorCode Error code
-     * @param message   Detailed message
+     * @param errorCode Error code.
+     * @param message   Detailed message.
      */
     public OrgResourceHierarchyTraverseClientException(String errorCode, String message) {
 
@@ -89,9 +89,9 @@ public OrgResourceHierarchyTraverseClientException(String errorCode, String mess
     /**
      * Constructs a new exception with the specified error code, message and cause.
      *
-     * @param errorCode Error code
-     * @param message   Detailed message
-     * @param cause     Cause as {@link Throwable}
+     * @param errorCode Error code.
+     * @param message   Detailed message.
+     * @param cause     Cause as {@link Throwable}.
      */
     public OrgResourceHierarchyTraverseClientException(String errorCode, String message, Throwable cause) {
 
@@ -113,10 +113,10 @@ public OrgResourceHierarchyTraverseClientException(String errorCode, String mess
     /**
      * Constructs a new exception with the specified error code, message, description and cause.
      *
-     * @param errorCode   Error code
-     * @param message     Detailed message
-     * @param cause       Cause as {@link Throwable}
+     * @param errorCode   Error code.
+     * @param message     Detailed message.
      * @param description Error description.
+     * @param cause       Cause as {@link Throwable}.
      */
     public OrgResourceHierarchyTraverseClientException(String errorCode, String message, String description,
                                                        Throwable cause) {
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseException.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseException.java
index 128557dc4..749498bec 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseException.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseException.java
@@ -34,7 +34,7 @@ public class OrgResourceHierarchyTraverseException extends Exception {
     /**
      * Constructs a new exception with the specified message.
      *
-     * @param message Detailed message
+     * @param message Detailed message.
      */
     public OrgResourceHierarchyTraverseException(String message) {
 
@@ -44,8 +44,8 @@ public OrgResourceHierarchyTraverseException(String message) {
     /**
      * Constructs a new exception with the specified message and cause.
      *
-     * @param message Detailed message
-     * @param e       Cause as {@link Throwable}
+     * @param message Detailed message.
+     * @param e       Cause as {@link Throwable}.
      */
     public OrgResourceHierarchyTraverseException(String message, Throwable e) {
 
@@ -55,8 +55,8 @@ public OrgResourceHierarchyTraverseException(String message, Throwable e) {
     /**
      * Constructs a new exception with the specified error code and cause.
      *
-     * @param errorCode Error code
-     * @param message   Detailed message
+     * @param errorCode Error code.
+     * @param message   Detailed message.
      */
     public OrgResourceHierarchyTraverseException(String errorCode, String message) {
 
@@ -81,9 +81,9 @@ public OrgResourceHierarchyTraverseException(String errorCode, String message, S
     /**
      * Constructs a new exception with the specified error code, message and cause.
      *
-     * @param errorCode Error code
-     * @param message   Detailed message
-     * @param cause     Cause as {@link Throwable}
+     * @param errorCode Error code.
+     * @param message   Detailed message.
+     * @param cause     Cause as {@link Throwable}.
      */
     public OrgResourceHierarchyTraverseException(String errorCode, String message, Throwable cause) {
 
@@ -96,8 +96,8 @@ public OrgResourceHierarchyTraverseException(String errorCode, String message, T
      *
      * @param errorCode   Error code.
      * @param message     Detailed message.
-     * @param cause       Cause as {@link Throwable}.
      * @param description Error description.
+     * @param cause       Cause as {@link Throwable}.
      */
     public OrgResourceHierarchyTraverseException(String errorCode, String message, String description,
                                                  Throwable cause) {
@@ -110,7 +110,7 @@ public OrgResourceHierarchyTraverseException(String errorCode, String message, S
     /**
      * Returns the error code.
      *
-     * @return Error code
+     * @return Error code.
      */
     public String getErrorCode() {
 
@@ -118,16 +118,10 @@ public String getErrorCode() {
     }
 
     /**
-     * This public method is required by the stub.
+     * Returns the error description.
      *
-     * @return Error message.
+     * @return Error description.
      */
-    @Override
-    public String getMessage() {
-
-        return super.getMessage();
-    }
-
     public String getDescription() {
 
         return description;
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseServerException.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseServerException.java
index 531b834e0..2b2f7ecef 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseServerException.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/exception/OrgResourceHierarchyTraverseServerException.java
@@ -29,7 +29,7 @@ public class OrgResourceHierarchyTraverseServerException extends OrgResourceHier
     /**
      * Constructs a new exception with the specified message.
      *
-     * @param message Detailed message
+     * @param message Detailed message.
      */
     public OrgResourceHierarchyTraverseServerException(String message) {
 
@@ -39,8 +39,8 @@ public OrgResourceHierarchyTraverseServerException(String message) {
     /**
      * Constructs a new exception with the specified message and cause.
      *
-     * @param message Detailed message
-     * @param e       Cause as {@link Throwable}
+     * @param message Detailed message.
+     * @param e       Cause as {@link Throwable}.
      */
     public OrgResourceHierarchyTraverseServerException(String message, Throwable e) {
 
@@ -50,8 +50,8 @@ public OrgResourceHierarchyTraverseServerException(String message, Throwable e)
     /**
      * Constructs a new exception with the specified error code and message.
      *
-     * @param errorCode Error code
-     * @param message   Detailed message
+     * @param errorCode Error code.
+     * @param message   Detailed message.
      */
     public OrgResourceHierarchyTraverseServerException(String errorCode, String message) {
 
@@ -61,9 +61,9 @@ public OrgResourceHierarchyTraverseServerException(String errorCode, String mess
     /**
      * Constructs a new exception with the specified error code, message and cause.
      *
-     * @param errorCode Error code
-     * @param message   Detailed message
-     * @param cause     Cause as {@link Throwable}
+     * @param errorCode Error code.
+     * @param message   Detailed message.
+     * @param cause     Cause as {@link Throwable}.
      */
     public OrgResourceHierarchyTraverseServerException(String errorCode, String message, Throwable cause) {
 
@@ -87,8 +87,8 @@ public OrgResourceHierarchyTraverseServerException(String errorCode, String mess
      *
      * @param errorCode   Error code.
      * @param message     Detailed message.
-     * @param cause       Cause as {@link Throwable}.
      * @param description Error description.
+     * @param cause       Cause as {@link Throwable}.
      */
     public OrgResourceHierarchyTraverseServerException(String errorCode, String message, String description,
                                                        Throwable cause) {
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceComponent.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceComponent.java
index deec43f48..022cc1831 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceComponent.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceComponent.java
@@ -43,7 +43,7 @@
         immediate = true)
 public class OrgResourceHierarchyTraverseServiceComponent {
 
-    private static final Log log = LogFactory.getLog(OrgResourceHierarchyTraverseServiceComponent.class);
+    private static final Log LOG = LogFactory.getLog(OrgResourceHierarchyTraverseServiceComponent.class);
 
     /**
      * Activates the OSGi component by registering the {@link OrgResourceResolverService} service.
@@ -58,11 +58,11 @@ protected void activate(ComponentContext context) {
             BundleContext bundleContext = context.getBundleContext();
             bundleContext.registerService(OrgResourceResolverService.class.getName(),
                     new OrgResourceResolverServiceImpl(), null);
-            if (log.isDebugEnabled()) {
-                log.debug("OrgResourceResolverService bundle is activated successfully.");
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("OrgResourceResolverService bundle is activated successfully.");
             }
         } catch (Exception e) {
-            log.error("Error while activating OrgResourceResolverService bundle.", e);
+            LOG.error("Error while activating OrgResourceResolverService bundle.", e);
         }
     }
 
@@ -75,8 +75,8 @@ protected void activate(ComponentContext context) {
     @Deactivate
     protected void deactivate(ComponentContext context) {
 
-        if (log.isDebugEnabled()) {
-            log.debug("OrgResourceResolverService bundle is deactivated");
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("OrgResourceResolverService bundle is deactivated");
         }
     }
 
@@ -87,13 +87,13 @@ protected void deactivate(ComponentContext context) {
      */
     @Reference(name = "org.wso2.carbon.identity.organization.management.service",
             service = OrganizationManager.class,
-            cardinality = ReferenceCardinality.OPTIONAL,
+            cardinality = ReferenceCardinality.MANDATORY,
             policy = ReferencePolicy.DYNAMIC,
             unbind = "unsetOrganizationManager")
     protected void setOrganizationManager(OrganizationManager organizationManager) {
 
         OrgResourceHierarchyTraverseServiceDataHolder.getInstance().setOrganizationManager(organizationManager);
-        log.debug("OrganizationManager set in OrgResourceManagementServiceComponent bundle.");
+        LOG.debug("OrganizationManager set in OrgResourceManagementServiceComponent bundle.");
     }
 
     /**
@@ -104,7 +104,7 @@ protected void setOrganizationManager(OrganizationManager organizationManager) {
     protected void unsetOrganizationManager(OrganizationManager organizationManager) {
 
         OrgResourceHierarchyTraverseServiceDataHolder.getInstance().setOrganizationManager(null);
-        log.debug("OrganizationManager unset in OrgResourceManagementServiceComponent bundle.");
+        LOG.debug("OrganizationManager unset in OrgResourceManagementServiceComponent bundle.");
     }
 
     /**
@@ -122,7 +122,7 @@ protected void setApplicationManagementService(ApplicationManagementService appl
 
         OrgResourceHierarchyTraverseServiceDataHolder.getInstance()
                 .setApplicationManagementService(applicationManagementService);
-        log.debug("ApplicationManagementService set in OrgResourceManagementServiceComponent bundle.");
+        LOG.debug("ApplicationManagementService set in OrgResourceManagementServiceComponent bundle.");
     }
 
     /**
@@ -133,7 +133,7 @@ protected void setApplicationManagementService(ApplicationManagementService appl
     protected void unsetApplicationManagementService(ApplicationManagementService applicationManagementService) {
 
         OrgResourceHierarchyTraverseServiceDataHolder.getInstance().setApplicationManagementService(null);
-        log.debug("ApplicationManagementService unset in OrgResourceManagementServiceComponent bundle.");
+        LOG.debug("ApplicationManagementService unset in OrgResourceManagementServiceComponent bundle.");
     }
 }
 
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceDataHolder.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceDataHolder.java
index 5a5c6ba02..42d7729ab 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceDataHolder.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceDataHolder.java
@@ -27,7 +27,7 @@
  */
 public class OrgResourceHierarchyTraverseServiceDataHolder {
 
-    private static final OrgResourceHierarchyTraverseServiceDataHolder instance =
+    private static final OrgResourceHierarchyTraverseServiceDataHolder INSTANCE =
             new OrgResourceHierarchyTraverseServiceDataHolder();
 
     private OrganizationManager organizationManager;
@@ -44,7 +44,7 @@ private OrgResourceHierarchyTraverseServiceDataHolder() {
      */
     public static OrgResourceHierarchyTraverseServiceDataHolder getInstance() {
 
-        return instance;
+        return INSTANCE;
     }
 
     /**
@@ -62,8 +62,7 @@ public OrganizationManager getOrganizationManager() {
      *
      * @param organizationManager The OrganizationManager instance to be assigned.
      */
-    public void setOrganizationManager(
-            OrganizationManager organizationManager) {
+    public void setOrganizationManager(OrganizationManager organizationManager) {
 
         this.organizationManager = organizationManager;
     }
@@ -83,8 +82,7 @@ public ApplicationManagementService getApplicationManagementService() {
      *
      * @param applicationManagementService The ApplicationManagementService instance to be set.
      */
-    public void setApplicationManagementService(
-            ApplicationManagementService applicationManagementService) {
+    public void setApplicationManagementService(ApplicationManagementService applicationManagementService) {
 
         this.applicationManagementService = applicationManagementService;
     }
diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java
index 825e81b03..6c732197c 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java
@@ -547,7 +547,7 @@ public void testGetAppLevelResourcesFromOrgHierarchyWhenServerErrorOccurs(
     /**
      * Mock the retrieval of ancestor organization IDs.
      *
-     * @param orgIds Organization IDs
+     * @param orgIds Organization IDs.
      * @throws OrganizationManagementException If an error occurs while retrieving ancestor organization IDs.
      */
     private void mockAncestorOrganizationRetrieval(List<String> orgIds)
@@ -560,8 +560,8 @@ private void mockAncestorOrganizationRetrieval(List<String> orgIds)
     /**
      * Mock the retrieval of ancestor application IDs.
      *
-     * @param orgIds Organization IDs
-     * @param appIds Application IDs
+     * @param orgIds Organization IDs.
+     * @param appIds Application IDs.
      * @throws IdentityApplicationManagementException If an error occurs while retrieving ancestor application IDs.
      */
     private void mockAncestorApplicationRetrieval(List<String> orgIds, List<String> appIds)
@@ -578,7 +578,7 @@ private void mockAncestorApplicationRetrieval(List<String> orgIds, List<String>
     /**
      * Add organization resources to the mock resource management service.
      *
-     * @param orgIds Organization IDs
+     * @param orgIds Organization IDs.
      * @return List of created organization resources.
      */
     private List<MockResource> addOrgResources(List<String> orgIds) {
@@ -596,8 +596,8 @@ private List<MockResource> addOrgResources(List<String> orgIds) {
     /**
      * Add application resources to the mock resource management service.
      *
-     * @param orgIds Organization IDs
-     * @param appIds Application IDs
+     * @param orgIds Organization IDs.
+     * @param appIds Application IDs.
      * @return List of created application resources.
      */
     private List<MockResource> addAppResources(List<String> orgIds, List<String> appIds) {
@@ -616,8 +616,8 @@ private List<MockResource> addAppResources(List<String> orgIds, List<String> app
     /**
      * Resource resolver function used for testing MergeAllAggregationStrategy.
      *
-     * @param aggregatedResource Aggregated resource
-     * @param newResource        New resource
+     * @param aggregatedResource Aggregated resource.
+     * @param newResource        New resource.
      * @return Merged resource.
      */
     private MockResource resourceMerger(MockResource aggregatedResource, MockResource newResource) {
@@ -631,9 +631,9 @@ private MockResource resourceMerger(MockResource aggregatedResource, MockResourc
     /**
      * Invoke the organization level resource resolver.
      *
-     * @param aggregationStrategy Aggregation strategy
-     * @param organizationId      Organization ID
-     * @return Resolved resource
+     * @param aggregationStrategy Aggregation strategy.
+     * @param organizationId      Organization ID.
+     * @return Resolved resource.
      * @throws OrgResourceHierarchyTraverseException If an error occurs while resolving the resource.
      */
     private MockResource invokeOrgLevelResourceResolver(AggregationStrategy<MockResource> aggregationStrategy,
@@ -652,10 +652,10 @@ private MockResource invokeOrgLevelResourceResolver(AggregationStrategy<MockReso
     /**
      * Invoke the application level resource resolver.
      *
-     * @param aggregationStrategy Aggregation strategy
-     * @param organizationId      Organization ID
-     * @param applicationId       Application ID
-     * @return Resolved resource
+     * @param aggregationStrategy Aggregation strategy.
+     * @param organizationId      Organization ID.
+     * @param applicationId       Application ID.
+     * @return Resolved resource.
      * @throws OrgResourceHierarchyTraverseException If an error occurs while resolving the resource.
      */
     private MockResource invokeAppLevelResourceResolver(AggregationStrategy<MockResource> aggregationStrategy,
@@ -675,8 +675,8 @@ private MockResource invokeAppLevelResourceResolver(AggregationStrategy<MockReso
     /**
      * Assert the resolved resource with the actual resource.
      *
-     * @param resolvedResource Resolved resource
-     * @param actualResource   Actual resource
+     * @param resolvedResource Resolved resource.
+     * @param actualResource   Actual resource.
      */
     private void assertResolvedResponse(MockResource resolvedResource, MockResource actualResource) {
 

From beca6346b76e757e9a337f58a2eb62949260f8ad Mon Sep 17 00:00:00 2001
From: dhaura <dhaurapathirana@gmail.com>
Date: Fri, 29 Nov 2024 18:13:54 +0530
Subject: [PATCH 16/18] Fix data holder method comment.

---
 .../internal/OrgResourceHierarchyTraverseServiceDataHolder.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceDataHolder.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceDataHolder.java
index 42d7729ab..0b4fd6686 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceDataHolder.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/main/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/internal/OrgResourceHierarchyTraverseServiceDataHolder.java
@@ -38,7 +38,7 @@ private OrgResourceHierarchyTraverseServiceDataHolder() {
     }
 
     /**
-     * Retires the Singleton instance of the OrgResourceHierarchyTraverseServiceDataHolder class.
+     * Retrieves the Singleton instance of the OrgResourceHierarchyTraverseServiceDataHolder class.
      *
      * @return The singleton instance of OrgResourceHierarchyTraverseServiceDataHolder.
      */

From e742138557d64d5cc325ab150827d457ff4ccc86 Mon Sep 17 00:00:00 2001
From: dhaura <dhaurapathirana@gmail.com>
Date: Wed, 4 Dec 2024 10:48:34 +0530
Subject: [PATCH 17/18] Fix server error unit tests.

---
 .../traverse/service/OrgResourceResolverServiceTest.java      | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java
index 6c732197c..311ed269c 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/src/test/java/org/wso2/carbon/identity/organization/resource/hierarchy/traverse/service/OrgResourceResolverServiceTest.java
@@ -529,7 +529,7 @@ public void testGetAppLevelResourcesFromOrgHierarchyWhenServerErrorOccurs(
         assertThrows(OrgResourceHierarchyTraverseServerException.class,
                 () -> invokeAppLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID, ROOT_APP_ID));
         assertThrows(OrgResourceHierarchyTraverseServerException.class,
-                () -> invokeAppLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID, ROOT_APP_ID));
+                () -> invokeAppLevelResourceResolver(aggregationStrategy, L1_ORG_ID, L1_APP_ID));
         assertThrows(OrgResourceHierarchyTraverseServerException.class,
                 () -> invokeAppLevelResourceResolver(aggregationStrategy, L2_ORG_ID, L2_APP_ID));
 
@@ -539,7 +539,7 @@ public void testGetAppLevelResourcesFromOrgHierarchyWhenServerErrorOccurs(
         assertThrows(OrgResourceHierarchyTraverseServerException.class,
                 () -> invokeAppLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID, ROOT_APP_ID));
         assertThrows(OrgResourceHierarchyTraverseServerException.class,
-                () -> invokeAppLevelResourceResolver(aggregationStrategy, ROOT_ORG_ID, ROOT_APP_ID));
+                () -> invokeAppLevelResourceResolver(aggregationStrategy, L1_ORG_ID, L1_APP_ID));
         assertThrows(OrgResourceHierarchyTraverseServerException.class,
                 () -> invokeAppLevelResourceResolver(aggregationStrategy, L2_ORG_ID, L2_APP_ID));
     }

From 0507e267d48563d7336f0be3d3cabdaaa432824c Mon Sep 17 00:00:00 2001
From: dhaura <dhaurapathirana@gmail.com>
Date: Wed, 4 Dec 2024 10:51:06 +0530
Subject: [PATCH 18/18] Bump resource traverse version.

---
 .../pom.xml                                                     | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml
index 3efbc72e6..d01874f66 100644
--- a/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml
+++ b/components/org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service/pom.xml
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.wso2.carbon.identity.organization.management</groupId>
         <artifactId>identity-organization-management</artifactId>
-        <version>1.4.57-SNAPSHOT</version>
+        <version>1.4.58-SNAPSHOT</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>