content: /*
   * 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.chemistry.opencmis.inmemory.storedobj.impl;
  
  import java.io.ByteArrayInputStream;
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.math.BigInteger;
  import java.util.ArrayList;
  import java.util.List;
  
  import org.apache.chemistry.opencmis.commons.data.ContentStream;
  import org.apache.chemistry.opencmis.commons.data.RenditionData;
  import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
  import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
  import org.apache.chemistry.opencmis.commons.impl.IOUtils;
  import org.apache.chemistry.opencmis.commons.impl.dataobjects.RenditionDataImpl;
  import org.apache.chemistry.opencmis.inmemory.storedobj.api.Content;
  import org.apache.chemistry.opencmis.inmemory.storedobj.api.Folder;
  import org.apache.chemistry.opencmis.inmemory.storedobj.api.StoredObject;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  public class RenditionUtil {
      
      private static final Logger LOG = LoggerFactory.getLogger(RenditionUtil.class.getName());
      private static final int BUFFER_SIZE = 65536;
      public static final String RENDITION_MIME_TYPE_JPEG = "image/jpeg";
      public static final String RENDITION_MIME_TYPE_PNG = "image/png";
      public static final String RENDITION_SUFFIX = "-rendition";
      public static final int THUMBNAIL_SIZE = 100;
      public static final int ICON_SIZE = 32;
  
      public static boolean hasRendition(StoredObject so, String user) {
          if (so instanceof Folder) {
              return true;
          } else if (so instanceof Content) {
              ContentStream contentStream = ((Content)so).getContent();
              if (null == contentStream) {
                  return false;
              }
  
              String mimeType = contentStream.getMimeType();
  
              return isImage(mimeType) || isAudio(mimeType) || isVideo(mimeType) || isPDF(mimeType) || isPowerpoint(mimeType)
                      || isExcel(mimeType) || isWord(mimeType) || isHtml(mimeType) || isPlainText(mimeType);
          } else {
              return false;
          }
      }
      
      private static boolean isImage(String mimeType) {
          return mimeType.startsWith("image/");
      }
  
      private static boolean isWord(String mimeType) {
          return mimeType.equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document")
                  || mimeType.equals("application/ms-word");
      }
  
      private static boolean isExcel(String mimeType) {
          return mimeType.equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
                  || mimeType.equals("application/vnd.ms-excel");
      }
  
      private static boolean isPowerpoint(String mimeType) {
          return mimeType.equals("application/vnd.openxmlformats-officedocument.presentationml.slideshow")
                  || mimeType.equals("application/vnd.openxmlformats-officedocument.presentationml.presentation")
                  || mimeType.equals("application/vnd.ms-powerpoint");
      }
  
      private static boolean isPDF(String mimeType) {
          return mimeType.equals("application/pdf");
      }
  
      private static boolean isHtml(String mimeType) {
          return mimeType.equals("text/html");
      }
  
      private static boolean isAudio(String mimeType) {
          return mimeType.startsWith("audio/");
      }
  
      private static boolean isVideo(String mimeType) {
          return mimeType.startsWith("video/");
      }
  
      private static boolean isPlainText(String mimeType) {
          return mimeType.equals("text/plain");
      }
  
      public static ContentStream getIconFromResourceDir(String name) throws IOException {
  
          InputStream imageStream = StoredObjectImpl.class.getResourceAsStream(name);
          ByteArrayOutputStream ba = new ByteArrayOutputStream();
          byte[] buffer = new byte[BUFFER_SIZE];
          int noBytesRead = 0;
  
          try {
              while ((noBytesRead = imageStream.read(buffer)) >= 0) {
                  ba.write(buffer, 0, noBytesRead);
              }
          } finally {
              IOUtils.closeQuietly(ba);
              IOUtils.closeQuietly(imageStream);
          }
  
          ContentStreamDataImpl content = new ContentStreamDataImpl(0);
          content.setFileName(name);
          content.setMimeType("image/png");
          content.setContent(new ByteArrayInputStream(ba.toByteArray()));
          return content;
      }
  
      public static boolean testRenditionFilterForImage(String[] formats) {
          if (formats.length == 1 && null != formats[0] && formats[0].equals("cmis:none")) {
              return false;
          } else {
              return arrayContainsString(formats, "*") || arrayContainsString(formats, "image/*")
                      || arrayContainsString(formats, "image/jpeg");
          }
      }
  
      private static boolean arrayContainsString(String[] formats, String val) {
          for (String s : formats) {
              if (val.equals(s)) {
                  return true;
              }
          }
          return false;
      }
  
      public static ContentStream getRenditionContent(StoredObject so, String streamId, long offset, long length) {
          if (so instanceof Folder) {
              return RenditionUtil.getFolderRenditionContent(streamId, offset, length);
          }
          if (!(so instanceof Content)) {
              throw new CmisInvalidArgumentException("Only objects with content can have a rendition");
          }
          ContentStream contentStream = ((Content)so).getContent();
  
          if (null == contentStream) {
              return null;
          }
  
          String mimeType = contentStream.getMimeType();
  
          try {
              if (isImage(mimeType)) {
                  ImageThumbnailGenerator generator = new ImageThumbnailGenerator(contentStream.getStream());
                  return generator.getRendition(THUMBNAIL_SIZE, 0);
              } else if (isAudio(mimeType)) {
                  return getIconFromResourceDir("/audio-x-generic.png");
              } else if (isVideo(mimeType)) {
                  return getIconFromResourceDir("/video-x-generic.png");
              } else if (isPDF(mimeType)) {
                  return getIconFromResourceDir("/application-pdf.png");
              } else if (isWord(mimeType)) {
                  return getIconFromResourceDir("/application-msword.png");
              } else if (isPowerpoint(mimeType)) {
                  return getIconFromResourceDir("/application-vnd.ms-powerpoint.png");
              } else if (isExcel(mimeType)) {
                  return getIconFromResourceDir("/application-vnd.ms-excel.png");
              } else if (isHtml(mimeType)) {
                  return getIconFromResourceDir("/text-html.png");
              } else if (isPlainText(mimeType)) {
                  return getIconFromResourceDir("/text-x-generic.png");
              } else {
                  return null;
              }
          } catch (IOException e) {
              LOG.error("Failed to generate rendition: ", e);
              throw new CmisRuntimeException("Failed to generate rendition: " + e);
          }
      }
      
      private static ContentStream getFolderRenditionContent(String streamId, long offset, long length) {
          try {
              return getIconFromResourceDir("/folder.png");
          } catch (IOException e) {
              LOG.error("Failed to generate rendition: ", e);
              throw new CmisRuntimeException("Failed to generate rendition: " + e);
          }
      }
      
      public static List<RenditionData> getRenditions(StoredObject so, String renditionFilter, long maxItems, long skipCount) {
  
          String tokenizer = "[\\s;]";
          if (null == renditionFilter) {
              return null;
          }
          String[] formats = renditionFilter.split(tokenizer);
          boolean isImageRendition = RenditionUtil.testRenditionFilterForImage(formats);
          if (!(so instanceof Content) && !(so instanceof Folder)) {
              return null;
          }
          
          if (isImageRendition && hasRendition(so, null)) {
              String mimeType;
              if (so  instanceof Folder) {
                  mimeType = "image/png";
              } else {
                  ContentStream contentStream = ((Content)so).getContent();
                  mimeType = contentStream.getMimeType();
              }
  
              List<RenditionData> renditions = new ArrayList<RenditionData>(1);
              RenditionDataImpl rendition = new RenditionDataImpl();
              if (mimeType.equals("image/jpeg")) {
                  rendition.setBigHeight(BigInteger.valueOf(THUMBNAIL_SIZE));
                  rendition.setBigWidth(BigInteger.valueOf(THUMBNAIL_SIZE));
                  rendition.setMimeType(RENDITION_MIME_TYPE_JPEG);
              } else {
                  rendition.setBigHeight(BigInteger.valueOf(ICON_SIZE));
                  rendition.setBigWidth(BigInteger.valueOf(ICON_SIZE));
                  rendition.setMimeType(RENDITION_MIME_TYPE_PNG);
              }
              rendition.setKind("cmis:thumbnail");
              rendition.setRenditionDocumentId(so.getId());
              rendition.setStreamId(so.getId() + RENDITION_SUFFIX);
              rendition.setBigLength(BigInteger.valueOf(-1L));
              rendition.setTitle(so.getName());
              renditions.add(rendition);
              return renditions;
          } else {
              return null;
          }
      }
  
  }
  