+ * 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
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * Implementations should specify how resources are combined and may use functional
+ * interfaces for flexible retrieval mechanisms.
*
- * @param
+ * 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
+ * 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
+ * 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.
+ *
+ * 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.
+ *
+ * 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
+ * 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.
+ *
+ * This implementation is intended for testing or mocking purposes and simulates a resource management system.
+ */
+public class MockResourceManagementService {
+
+ private final Map
+ * 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.
+ *
+ * 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 @@