All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.wcm.handler.mediasource.dam.impl.RenditionMetadata Maven / Gradle / Ivy

There is a newer version: 2.3.0
Show newest version
/*
 * #%L
 * wcm.io
 * %%
 * Copyright (C) 2014 wcm.io
 * %%
 * Licensed 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.
 * #L%
 */
package io.wcm.handler.mediasource.dam.impl;

import java.io.InputStream;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.sling.api.adapter.SlingAdaptable;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;

import com.day.cq.commons.jcr.JcrConstants;
import com.day.cq.dam.api.Asset;
import com.day.cq.dam.api.DamConstants;
import com.day.cq.dam.api.Rendition;
import com.day.image.Layer;

import io.wcm.handler.media.format.MediaFormat;
import io.wcm.handler.media.format.MediaFormatHandler;
import io.wcm.handler.media.impl.MediaFileServlet;
import io.wcm.wcm.commons.contenttype.FileExtension;

/**
 * Wrapper class for rendition metadata retrieved from DAM rendition filenames.
 */
class RenditionMetadata extends SlingAdaptable implements Comparable {

  private final Rendition rendition;
  private final String fileName;
  private final String fileExtension;
  private final long width;
  private final long height;
  private MediaFormat mediaFormat;

  /**
   * @param rendition DAM rendition
   */
  RenditionMetadata(Rendition rendition) {
    this.rendition = rendition;

    // check if rendition is original image
    boolean isOriginal = isOriginalRendition(rendition);
    Asset asset = rendition.getAsset();

    // get filename and extension
    String renditionName = rendition.getName();
    if (isOriginal) {
      renditionName = asset.getName();
    }
    this.fileName = renditionName;
    this.fileExtension = StringUtils.substringAfterLast(renditionName, ".");

    // get image width/height
    int imageWidth = 0;
    int imageHeight = 0;
    if (isOriginal) {
      // get width/height from metadata for original renditions
      try {
        imageWidth = Integer.parseInt(StringUtils.defaultString(asset.getMetadataValue(DamConstants.TIFF_IMAGEWIDTH), "0"));
      }
      catch (NumberFormatException ex) {
        // ignore
      }
      if (imageWidth == 0) {
        try {
          imageWidth = Integer.parseInt(StringUtils.defaultString(asset.getMetadataValue(DamConstants.EXIF_PIXELXDIMENSION), "0"));
        }
        catch (NumberFormatException ex) {
          // ignore
        }
      }
      try {
        imageHeight = Integer.parseInt(StringUtils.defaultString(asset.getMetadataValue(DamConstants.TIFF_IMAGELENGTH), "0"));
      }
      catch (NumberFormatException ex) {
        // ignore
      }
      if (imageHeight == 0) {
        try {
          imageHeight = Integer.parseInt(StringUtils.defaultString(asset.getMetadataValue(DamConstants.EXIF_PIXELYDIMENSION), "0"));
        }
        catch (NumberFormatException ex) {
          // ignore
        }
      }
    }
    else if (FileExtension.isImage(this.fileExtension)) {
      // otherwise get from rendition metadata written by {@link DamRenditionMetadataService}
      String metadataPath = JcrConstants.JCR_CONTENT + "/" + DamRenditionMetadataService.NN_RENDITIONS_METADATA + "/" + rendition.getName();
      Resource metadataResource = asset.adaptTo(Resource.class).getChild(metadataPath);
      if (metadataResource != null) {
        ValueMap props = metadataResource.getValueMap();
        imageWidth = props.get(DamRenditionMetadataService.PN_IMAGE_WIDTH, 0);
        imageHeight = props.get(DamRenditionMetadataService.PN_IMAGE_HEIGHT, 0);
      }
    }
    this.width = imageWidth;
    this.height = imageHeight;
  }

  /**
   * @param value DAM rendition
   * @return true if rendition is the original file that was uploaded initially
   */
  private boolean isOriginalRendition(Rendition value) {
    return StringUtils.equals(value.getName(), DamConstants.ORIGINAL_FILE);
  }

  /**
   * @return DAM rendition
   */
  public Rendition getRendition() {
    return this.rendition;
  }

  /**
   * @return File name
   */
  public String getFileName() {
    return this.fileName;
  }

  /**
   * @return File size
   */
  public long getFileSize() {
    return this.rendition.getSize();
  }

  /**
   * @return File extension
   */
  public String getFileExtension() {
    return this.fileExtension;
  }

  /**
   * @return Mime type
   */
  public String getMimeType() {
    return this.rendition.getMimeType();
  }

  /**
   * @return Image width
   */
  public long getWidth() {
    return this.width;
  }

  /**
   * @return Image height
   */
  public long getHeight() {
    return this.height;
  }

  /**
   * @return Media format that matches with the resolved rendition. Null if no media format was specified for resolving.
   */
  public MediaFormat getMediaFormat() {
    return this.mediaFormat;
  }

  /**
   * @param mediaFormat Media format that matches with the resolved rendition. Null if no media format was specified for
   *          resolving.
   */
  public void setMediaFormat(MediaFormat mediaFormat) {
    this.mediaFormat = mediaFormat;
  }

  /**
   * @param forceDownload Force content disposition download header.
   * @return Media path (not externalized)
   */
  public String getMediaPath(boolean forceDownload) {
    if (forceDownload) {
      return RenditionMetadata.buildMediaPath(getRendition().getPath() + "." + MediaFileServlet.SELECTOR
          + "." + MediaFileServlet.SELECTOR_DOWNLOAD
          + "." + MediaFileServlet.EXTENSION, getFileName());
    }
    else {
      return RenditionMetadata.buildMediaPath(this.rendition.getPath() + ".", getFileName());
    }
  }

  /**
   * Checks if this rendition matches the given width/height.
   * @param checkWidth Width
   * @param checkHeight Height
   * @return true if matches
   */
  public boolean matches(long checkWidth, long checkHeight) {
    if (checkWidth != 0 && checkWidth != getWidth()) {
      return false;
    }
    if (checkHeight != 0 && checkHeight != getHeight()) {
      return false;
    }
    return true;
  }

  /**
   * Checks if this rendition matches the given width/height/ration restrictions.
   * @param minWidth Min. width
   * @param minHeight Min. height
   * @param maxWidth Max. width
   * @param maxHeight Max. height
   * @param ratio Ratio
   * @return true if matches
   */
  public boolean matches(long minWidth, long minHeight, long maxWidth, long maxHeight, double ratio) {
    if (minWidth > 0 && getWidth() < minWidth) {
      return false;
    }
    if (minHeight > 0 && getHeight() < minHeight) {
      return false;
    }
    if (maxWidth > 0 && getWidth() > maxWidth) {
      return false;
    }
    if (maxHeight > 0 && getHeight() > maxHeight) {
      return false;
    }
    if (ratio > 0) {
      double renditionRatio = (double)getWidth() / (double)getHeight();
      if (renditionRatio > ratio + MediaFormatHandler.RATIO_TOLERANCE
          || renditionRatio < ratio - MediaFormatHandler.RATIO_TOLERANCE) {
        return false;
      }
    }
    return true;
  }

  @Override
  public int hashCode() {
    return new HashCodeBuilder()
        .append(this.rendition.getPath())
        .hashCode();
  }

  @Override
  public boolean equals(Object obj) {
    if (obj == null || obj.getClass() != this.getClass()) {
      return false;
    }
    RenditionMetadata other = (RenditionMetadata)obj;
    return new EqualsBuilder()
        .append(this.rendition.getPath(), other.rendition.getPath())
        .build();
  }

  @Override
  public int compareTo(RenditionMetadata obj) {
    // always prefer the virtual crop rendition
    if (this instanceof VirtualCropRenditionMetadata) {
      return -1;
    }
    else if (obj instanceof VirtualCropRenditionMetadata) {
      return 1;
    }

    // order by width, height, rendition path
    Long thisWidth = getWidth();
    Long otherWidth = obj.getWidth();
    if (thisWidth.equals(otherWidth)) {
      Long thisHeight = getHeight();
      Long otherHeight = obj.getHeight();
      if (thisHeight.equals(otherHeight)) {
        String thisPath = getRendition().getPath();
        String otherPath = obj.getRendition().getPath();
        if (!StringUtils.equals(thisPath, otherPath)) {
          // same with/height - prefer original rendition
          if (isOriginalRendition(getRendition())) {
            return -1;
          }
          else if (isOriginalRendition(obj.getRendition())) {
            return 1;
          }
          else {
            return thisPath.compareTo(otherPath);
          }
        }
        else {
          return 0;
        }
      }
      else {
        return thisHeight.compareTo(otherHeight);
      }
    }
    else {
      return thisWidth.compareTo(otherWidth);
    }
  }

  protected Layer getLayer() {
    if (FileExtension.isImage(getFileExtension())) {
      return this.rendition.adaptTo(Resource.class).adaptTo(Layer.class);
    }
    else {
      return null;
    }
  }

  protected InputStream getInputStream() {
    return this.rendition.adaptTo(Resource.class).adaptTo(InputStream.class);
  }

  @Override
  public String toString() {
    return this.rendition.getPath() + " (" + this.width + "x" + this.height + ")";
  }

  /**
   * Build media path and suffix. The suffix is url-encoded.
   * @param mediaPath Media path
   * @param suffix Suffix
   * @return Media path and suffix
   */
  static String buildMediaPath(String mediaPath, String suffix) {
    return mediaPath + "/" + suffix;
  }

  @Override
  @SuppressWarnings("unchecked")
  public  AdapterType adaptTo(Class type) {
    if (type == Rendition.class) {
      return (AdapterType)this.rendition;
    }
    if (type == Resource.class) {
      return (AdapterType)this.rendition.adaptTo(Resource.class);
    }
    else if (type == Layer.class) {
      return (AdapterType)getLayer();
    }
    else if (type == InputStream.class) {
      return (AdapterType)getInputStream();
    }
    return super.adaptTo(type);
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy