{
+ /**
+ * Applies this function to the given arguments.
+ *
+ * @param t the first function argument
+ * @param u the second function argument
+ * @param v the third function argument
+ * @return the function result
+ */
+ R apply(T t, U u, V v);
+}
\ No newline at end of file
diff --git a/api/src/main/java/org/apache/unomi/api/services/cache/CacheableTypeConfig.java b/api/src/main/java/org/apache/unomi/api/services/cache/CacheableTypeConfig.java
new file mode 100644
index 0000000000..3194305f7b
--- /dev/null
+++ b/api/src/main/java/org/apache/unomi/api/services/cache/CacheableTypeConfig.java
@@ -0,0 +1,620 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.apache.unomi.api.services.cache;
+
+import org.apache.unomi.api.Item;
+import org.osgi.framework.BundleContext;
+import org.apache.unomi.api.services.TriFunction;
+
+import java.io.Serializable;
+import java.util.Comparator;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.net.URL;
+import java.util.Map;
+import java.io.InputStream;
+
+/**
+ * Configuration for a cacheable item type in Unomi.
+ *
+ * This class defines how a specific type of item is cached, loaded, and processed within
+ * the Unomi caching system. It supports a comprehensive callback system for processing items
+ * at different stages of their lifecycle:
+ *
+ * Callback System Overview
+ *
+ * The callback system includes two major categories of callbacks:
+ *
+ * 1. Item-Level Processing Callbacks
+ * These callbacks operate on individual items during loading and are executed in the following
+ * order of precedence (only the first applicable callback is called):
+ *
+ * - urlAwareBundleItemProcessor: Most specific, gets item, bundle context, and resource URL
+ * - bundleItemProcessor: Gets item and bundle context
+ * - postProcessor: Most general, gets only the item
+ *
+ *
+ * 2. Cache Refresh Callbacks
+ * These callbacks operate after items are loaded and cached:
+ *
+ * - tenantRefreshCallback: Called for each tenant that has changes after refresh
+ * - postRefreshCallback: Called once after all tenants are processed if any changes occurred
+ *
+ *
+ * Example Usage
+ *
+ * {@code
+ * // Define a cacheable type for PropertyType
+ * CacheableTypeConfig.builder(PropertyType.class, "propertyType", "properties")
+ * .withInheritFromSystemTenant(true)
+ * .withRequiresRefresh(true)
+ * .withRefreshInterval(10000)
+ * .withIdExtractor(PropertyType::getItemId)
+ *
+ * // Simple post-processor example
+ * .withPostProcessor(propertyType -> {
+ * // Normalize or initialize fields
+ * if (propertyType.getPriority() == 0) {
+ * propertyType.setPriority(1);
+ * }
+ * })
+ *
+ * // URL-aware processor example
+ * .withUrlAwareBundleItemProcessor((bundleContext, propertyType, url) -> {
+ * // Extract information from the URL path
+ * if (url.getPath().contains("/profiles/")) {
+ * propertyType.setTarget("profiles");
+ * }
+ * })
+ *
+ * // Tenant-specific callback example
+ * .withTenantRefreshCallback((tenantId, oldState, newState) -> {
+ * // Process tenant-specific changes efficiently
+ * boolean hasChanges = !oldState.equals(newState);
+ * if (hasChanges) {
+ * System.out.println("Tenant " + tenantId + " property types updated");
+ * // Update tenant-specific caches or indices
+ * }
+ * })
+ *
+ * // Global callback example
+ * .withPostRefreshCallback((oldState, newState) -> {
+ * // Process cross-tenant relationships or global state
+ * System.out.println("All property types refreshed, updating type registry");
+ * // Update cross-tenant registries or perform global operations
+ * })
+ * .build();
+ * }
+ *
+ * @param the type of the cacheable item
+ */
+public class CacheableTypeConfig {
+ private final Class type;
+ private final String itemType;
+ private final String metaInfPath;
+ private final boolean inheritFromSystemTenant;
+ private final boolean requiresRefresh;
+ private final long refreshInterval;
+ private final Function idExtractor;
+ private final Consumer postProcessor;
+ private final boolean hasPredefinedItems;
+ private final BiConsumer bundleItemProcessor;
+ private final TriConsumer urlAwareBundleItemProcessor;
+ private final Comparator urlComparator;
+ private final BiConsumer