Created
April 1, 2025 08:41
-
-
Save cpilsworth/e220b6ae81eef835f43551c5a3aaf65b to your computer and use it in GitHub Desktop.
Describe AEM assets and their relationships
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.chrisp.core.servlets; | |
import java.io.IOException; | |
import java.util.Iterator; | |
import javax.jcr.Node; | |
import javax.jcr.RepositoryException; | |
import javax.jcr.Session; | |
import javax.servlet.Servlet; | |
import org.apache.sling.api.SlingHttpServletRequest; | |
import org.apache.sling.api.SlingHttpServletResponse; | |
import org.apache.sling.api.resource.Resource; | |
import org.apache.sling.api.resource.ResourceResolver; | |
import org.apache.sling.api.servlets.HttpConstants; | |
import org.apache.sling.api.servlets.SlingSafeMethodsServlet; | |
import org.osgi.framework.Constants; | |
import org.osgi.service.component.annotations.Component; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import com.day.cq.dam.api.Asset; | |
import com.google.gson.Gson; | |
import com.google.gson.GsonBuilder; | |
import com.google.gson.JsonArray; | |
import com.google.gson.JsonObject; | |
/** | |
* Servlet that lists assets and their relationships under a specific path | |
* Usage: /bin/assets/relationships?path=/content/dam/path | |
*/ | |
@Component( | |
service = Servlet.class, | |
property = { | |
Constants.SERVICE_DESCRIPTION + "=Asset Relationship Servlet", | |
"sling.servlet.methods=" + HttpConstants.METHOD_GET, | |
"sling.servlet.paths=" + "/bin/assets/relationships", | |
"sling.servlet.extensions=" + "json" | |
} | |
) | |
public class AssetRelationshipServlet extends SlingSafeMethodsServlet { | |
private static final long serialVersionUID = 1L; | |
private static final Logger log = LoggerFactory.getLogger(AssetRelationshipServlet.class); | |
@Override | |
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) | |
throws IOException { | |
response.setContentType("application/json"); | |
ResourceResolver resolver = request.getResourceResolver(); | |
String path = request.getParameter("path"); | |
if (path == null || path.isEmpty()) { | |
response.getWriter().write("{\"error\": \"Please provide a path parameter\"}"); | |
return; | |
} | |
Resource resource = resolver.getResource(path); | |
if (resource == null) { | |
response.getWriter().write("{\"error\": \"Path not found: " + path + "\"}"); | |
return; | |
} | |
try { | |
JsonArray resultArray = findAssetsWithRelationships(resource, resolver); | |
Gson gson = new GsonBuilder().setPrettyPrinting().create(); | |
String jsonOutput = gson.toJson(resultArray); | |
response.getWriter().write(jsonOutput); | |
} catch (Exception e) { | |
log.error("Error processing assets", e); | |
response.getWriter().write("{\"error\": \"" + e.getMessage() + "\"}"); | |
} | |
} | |
/** | |
* Recursively find all assets under the given resource | |
*/ | |
private JsonArray findAssetsWithRelationships(Resource resource, ResourceResolver resolver) | |
throws RepositoryException { | |
JsonArray results = new JsonArray(); | |
// Process current resource if it's an asset | |
Asset asset = resource.adaptTo(Asset.class); | |
if (asset != null) { | |
JsonObject assetJson = processAsset(asset, resolver); | |
results.add(assetJson); | |
} | |
// Process children recursively | |
Iterator<Resource> children = resource.listChildren(); | |
while (children.hasNext()) { | |
Resource child = children.next(); | |
JsonArray childResults = findAssetsWithRelationships(child, resolver); | |
for (int i = 0; i < childResults.size(); i++) { | |
results.add(childResults.get(i)); | |
} | |
} | |
return results; | |
} | |
/** | |
* Process a single asset and find its relationships | |
*/ | |
private JsonObject processAsset(Asset asset, ResourceResolver resolver) throws RepositoryException { | |
JsonObject assetJson = new JsonObject(); | |
Resource assetResource = asset.adaptTo(Resource.class); | |
// Get the JCR node | |
Node assetNode = assetResource.adaptTo(Node.class); | |
String uuid = ""; | |
if (assetNode != null && assetNode.hasProperty("jcr:uuid")) { | |
uuid = assetNode.getProperty("jcr:uuid").getString(); | |
} | |
assetJson.addProperty("path", asset.getPath()); | |
assetJson.addProperty("name", asset.getName()); | |
assetJson.addProperty("uuid", uuid); | |
// Find all types of related assets based on the specified structure | |
JsonArray derivedAssets = findRelatedAssets(asset, "derived", resolver); | |
assetJson.add("derivedAssets", derivedAssets); | |
JsonArray sourceAssets = findRelatedAssets(asset, "sources", resolver); | |
assetJson.add("sourceAssets", sourceAssets); | |
JsonArray otherAssets = findRelatedAssets(asset, "others", resolver); | |
assetJson.add("otherAssets", otherAssets); | |
return assetJson; | |
} | |
/** | |
* Find related assets of a specific type using the structure: | |
* ./jcr:content/related/{relation-type}/sling:members/{asset-name} | |
* | |
* @param asset The asset to find relationships for | |
* @param relationType The type of relation ("derived", "source", or "other") | |
* @param resolver The resource resolver | |
* @return JsonArray containing related assets | |
*/ | |
private JsonArray findRelatedAssets(Asset asset, String relationType, ResourceResolver resolver) { | |
JsonArray relatedAssets = new JsonArray(); | |
Resource assetResource = asset.adaptTo(Resource.class); | |
try { | |
if (assetResource != null) { | |
// Path to the related assets based on the specified structure | |
String relatedPath = assetResource.getPath() + "/jcr:content/related/" + relationType + "/sling:members"; | |
Resource relatedResource = resolver.getResource(relatedPath); | |
if (relatedResource != null) { | |
// Iterate through all children (asset-name nodes) | |
Iterator<Resource> relatedMembers = relatedResource.listChildren(); | |
while (relatedMembers.hasNext()) { | |
Resource memberResource = relatedMembers.next(); | |
Node memberNode = memberResource.adaptTo(Node.class); | |
if (memberNode != null && memberNode.hasProperty("sling:resource")) { | |
// Get the path of the related asset | |
String linkedAssetPath = memberNode.getProperty("sling:resource").getString(); | |
Resource linkedResource = resolver.getResource(linkedAssetPath); | |
if (linkedResource != null) { | |
Asset linkedAsset = linkedResource.adaptTo(Asset.class); | |
if (linkedAsset != null) { | |
JsonObject relatedJson = new JsonObject(); | |
relatedJson.addProperty("path", linkedAsset.getPath()); | |
relatedJson.addProperty("name", linkedAsset.getName()); | |
// Get the UUID of the linked asset | |
Node linkedNode = linkedResource.adaptTo(Node.class); | |
if (linkedNode != null && linkedNode.hasProperty("jcr:uuid")) { | |
relatedJson.addProperty("uuid", linkedNode.getProperty("jcr:uuid").getString()); | |
} | |
relatedAssets.add(relatedJson); | |
} | |
} | |
} | |
} | |
} | |
} | |
} catch (RepositoryException e) { | |
log.error("Error finding " + relationType + " related assets", e); | |
} | |
return relatedAssets; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment