NextGenDynamicMediaReference.java

  1. /*
  2.  * #%L
  3.  * wcm.io
  4.  * %%
  5.  * Copyright (C) 2024 wcm.io
  6.  * %%
  7.  * Licensed under the Apache License, Version 2.0 (the "License");
  8.  * you may not use this file except in compliance with the License.
  9.  * You may obtain a copy of the License at
  10.  *
  11.  *      http://www.apache.org/licenses/LICENSE-2.0
  12.  *
  13.  * Unless required by applicable law or agreed to in writing, software
  14.  * distributed under the License is distributed on an "AS IS" BASIS,
  15.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16.  * See the License for the specific language governing permissions and
  17.  * limitations under the License.
  18.  * #L%
  19.  */
  20. package io.wcm.handler.mediasource.ngdm.impl;

  21. import java.util.regex.Matcher;
  22. import java.util.regex.Pattern;

  23. import org.apache.commons.lang3.StringUtils;
  24. import org.apache.sling.api.resource.Resource;
  25. import org.apache.sling.api.resource.ResourceResolver;
  26. import org.jetbrains.annotations.NotNull;
  27. import org.jetbrains.annotations.Nullable;
  28. import org.slf4j.Logger;
  29. import org.slf4j.LoggerFactory;

  30. import com.day.cq.dam.api.Asset;

  31. /**
  32.  * Parses and validates Dynamic Media with OpenAPI asset references.
  33.  *
  34.  * <p>
  35.  * Example: <code>/urn:aaid:aem:12345678-abcd-abcd-abcd-abcd12345678/my-image.jpg</code>
  36.  * </p>
  37.  */
  38. public final class NextGenDynamicMediaReference {

  39.   private static final Pattern REFERENCE_PATTERN = Pattern.compile("^/(urn:[^/]+)/([^/]+)$");
  40.   private static final String ASSET_ID_PREFIX = "urn:";

  41.   private final String assetId;
  42.   private final String fileName;
  43.   private final Asset asset;

  44.   private static final Logger log = LoggerFactory.getLogger(NextGenDynamicMediaReference.class);

  45.   /**
  46.    * @param assetId Asset ID (has to start with "urn:")
  47.    * @param fileName File name
  48.    */
  49.   public NextGenDynamicMediaReference(@NotNull String assetId, @NotNull String fileName) {
  50.     this(assetId, fileName, null);
  51.   }

  52.   /**
  53.    * @param assetId Asset ID (has to start with "urn:")
  54.    * @param fileName File name
  55.    */
  56.   public NextGenDynamicMediaReference(@NotNull String assetId, @NotNull String fileName, @Nullable Asset asset) {
  57.     if (!StringUtils.startsWith(assetId, ASSET_ID_PREFIX)) {
  58.       throw new IllegalArgumentException("Asset ID must start with '" + ASSET_ID_PREFIX + "'");
  59.     }
  60.     this.assetId = assetId;
  61.     this.fileName = fileName;
  62.     this.asset = asset;
  63.   }

  64.   /**
  65.    * @return Asset ID
  66.    */
  67.   public @NotNull String getAssetId() {
  68.     return assetId;
  69.   }

  70.   /**
  71.    * @return File name
  72.    */
  73.   public @NotNull String getFileName() {
  74.     return fileName;
  75.   }

  76.   /**
  77.    * @return Asset (if reference points to local asset)
  78.    */
  79.   public @Nullable Asset getAsset() {
  80.     return asset;
  81.   }

  82.   /**
  83.    * @return True if reference points to local asset.
  84.    */
  85.   public boolean isLocal() {
  86.     return asset != null;
  87.   }

  88.   /**
  89.    * @return Reference
  90.    */
  91.   public @NotNull String toReference() {
  92.     return "/" + assetId + "/" + fileName;
  93.   }

  94.   /**
  95.    * Parses a next generation dynamic media reference.
  96.    * @param reference Reference
  97.    * @return Parsed reference or null if reference is invalid
  98.    */
  99.   public static @Nullable NextGenDynamicMediaReference fromReference(@Nullable String reference) {
  100.     if (reference == null) {
  101.       return null;
  102.     }
  103.     Matcher matcher = REFERENCE_PATTERN.matcher(reference);
  104.     if (!matcher.matches()) {
  105.       return null;
  106.     }
  107.     String assetId = matcher.group(1);
  108.     String fileName = matcher.group(2);
  109.     return new NextGenDynamicMediaReference(assetId, fileName);
  110.   }

  111.   /**
  112.    * Parses a next generation dynamic media reference.
  113.    * @param reference Reference
  114.    * @return Parsed reference or null if reference is invalid
  115.    */
  116.   public static @Nullable NextGenDynamicMediaReference fromDamAssetReference(@Nullable String reference, @NotNull ResourceResolver resourceResolver) {
  117.     if (reference == null) {
  118.       return null;
  119.     }
  120.     Resource resource = resourceResolver.getResource(reference);
  121.     if (resource == null) {
  122.       return null;
  123.     }
  124.     Asset asset = resource.adaptTo(Asset.class);
  125.     if (asset == null) {
  126.       return null;
  127.     }
  128.     String uuid = asset.getID();
  129.     if (StringUtils.isBlank(uuid)) {
  130.       log.trace("Ignoring DAM asset without UUID: {}", asset.getPath());
  131.       return null;
  132.     }
  133.     String assetId = "urn:aaid:aem:" + uuid;
  134.     String fileName = asset.getName();
  135.     return new NextGenDynamicMediaReference(assetId, fileName, asset);
  136.   }

  137.   /**
  138.    * Checks if given string is a valid next generation dynamic media reference.
  139.    * @param reference Reference
  140.    * @return true if reference is valid
  141.    */
  142.   public static boolean isReference(@Nullable String reference) {
  143.     return reference != null && REFERENCE_PATTERN.matcher(reference).matches();
  144.   }

  145.   @Override
  146.   public String toString() {
  147.     return toReference();
  148.   }

  149. }