
// POIUtils.java
// Andrew Davison, ad@coe.psu.ac.th, Nov. 2022

/* Utilities related to detecting a file's type (which uses
   Apache Tika core; https://tika.apache.org/), file name 
   string manipulation, and functions for loading and saving images.

  Usage:
    > compile POIUtils.java
    > run POIUtils <fnm>
    e.g.
    > run POIUtils Thailand.xlsx
    > run POIUtils readings.xlsx
    > run POIUtils sample.docx
    > run POIUtils prelims.pptx
    > run POIUtils bench.jpg
                :
*/

import java.io.*;
import java.nio.file.*;
import java.net.*;

import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;

import org.apache.tika.Tika;


public class POIUtils
{

  // -------------- POI file type ------------------------------


  public static void reportType(String fnm)
  /* focus on the big three POI formats: Excel, Word,
     and PowerPoint, but report the mime types for 
     all types of files.
  */
  {
    if (isOldExcel(fnm))
      System.out.println(fnm + ": old-style Excel file");
    else if (isNewExcel(fnm))
      System.out.println(fnm + ": new-style Excel file");

    else if (isOldWord(fnm))
      System.out.println(fnm + ": old-style Word file");
    else if (isNewWord(fnm))
      System.out.println(fnm + ": new-style Word file");

    else if (isOldPowerPoint(fnm))
      System.out.println(fnm + ": old-style PowerPoint file");
    else if (isNewPowerPoint(fnm))
      System.out.println(fnm + ": new-style PowerPoint file");

    else
      System.out.println(fnm + ": probably not POI");

    System.out.println("  Mime Type: \n    " + getMimeType(fnm) + "\n");
  }  // end of reportType()



  public static boolean isExcel(String fnm)
  {  return (isNewExcel(fnm) || isOldExcel(fnm));  }  


  public static boolean isOldExcel(String fnm)
  // HSSF for Excel 97 (-2003)
  {
    String mt = getMimeType(fnm);
    return mt.contains("excel");
     /* application/excel
        application/vnd.ms-excel
        application/x-excel
        application/x-msexcel
     */
  }  // end of isOldExcel()


  public static boolean isNewExcel(String fnm)
  // XSSF for Excel XML (2007+)
  {
    String mt = getMimeType(fnm);
    return mt.contains("spreadsheetml");
     // application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
  }  // end of isNewExcel()



  public static boolean isWord(String fnm)
  {  return (isNewWord(fnm) || isOldWord(fnm));  }  


  public static boolean isOldWord(String fnm)
  // HWPF Word
  {
    String mt = getMimeType(fnm);
    return (mt.contains("application/doc") || 
            mt.contains("ms-doc") ||
            mt.contains("msword"));
     /* application/doc
        application/ms-doc
        application/msword
     */
  }  // end of isOldWord()


  public static boolean isNewWord(String fnm)
  // XWPF Word
  {
    String mt = getMimeType(fnm);
    return mt.contains("wordprocessingml");
   // application/vnd.openxmlformats-officedocument.wordprocessingml.document
  }  // end of isNewWord()



  public static boolean isPowerPoint(String fnm)
  {  return (isNewPowerPoint(fnm) || isOldPowerPoint(fnm));  }  


  public static boolean isOldPowerPoint(String fnm)
  // HSLF PowerPoint
  {
    String mt = getMimeType(fnm);
    return mt.contains("powerpoint");
     /* application/mspowerpoint
        application/powerpoint
        application/vnd.ms-powerpoint
        application/x-mspowerpoint
     */
  }  // end of isOldPowerPoint()


  public static boolean isNewPowerPoint(String fnm)
  // XSLF PowerPoint
  {
    String mt = getMimeType(fnm);
    return mt.contains("presentationml");
 // application/vnd.openxmlformats-officedocument.presentationml.presentation
  }  // end of isNewPowerPoint()



  public static String getMimeType(String fnm)
  // https://www.baeldung.com/java-file-mime-type
  // https://www.rgagnon.com/javadetails/java-0487.html
  {
    String mimeType = null;  
    try {
      File file = new File(fnm);

      if (mimeType == null)
        mimeType = (new Tika()).detect(file);  // Apache Tika core

      if (mimeType == null)
        mimeType = Files.probeContentType(file.toPath());

      if (mimeType == null) {
        URLConnection conn = file.toURI().toURL().openConnection();
        mimeType = conn.getContentType();
      }

      if (mimeType == null) {
        URLConnection conn = file.toURI().toURL().openConnection();  // slow
        mimeType = conn.getContentType();
      }

      if (mimeType == null) {
        InputStream is = new FileInputStream(file);
        mimeType = URLConnection.guessContentTypeFromStream(is);
        is.close();
      }

      if (mimeType == null)
        mimeType = URLConnection.guessContentTypeFromName(file.getName());

      if (mimeType == null)
        System.out.println("Unable to determine mime type for " + fnm);
    } 
    catch(IOException e)   
    {  System.out.println(e); }

    return mimeType;
  } // end of getMimeType()


  // ---------------- file name manipulation ---------------

  public static String stripExt(String fnm)
  {
    int dotPos = fnm.lastIndexOf('.');
    if (dotPos == -1)
      return fnm;
    else
      return fnm.substring(0, dotPos);
  }


  public static String getExt(String fnm)
  {
    int dotPos = fnm.lastIndexOf('.');
    if (dotPos == -1)
      return fnm;
    else
      return fnm.substring(dotPos+1);
  }


  // ----------------- image manipulation ----------------------


  public static Dimension getImageSize(String fnm)
  {
    BufferedImage im = loadImage(fnm);
    if (im != null)
      return new Dimension(im.getWidth(), im.getHeight());
    else
      return new Dimension(100,100);    // dummy size
  } // end of getImageSize()



  public static BufferedImage loadImage(String fnm)
  {
    try {
      return ImageIO.read(new File(fnm));
    }
    catch(IOException e) {
      System.out.println("Could not load image in " + fnm);
    }
    return null;
  } // end of loadImage()



  public static void saveImage(BufferedImage im, String fnm)
  {
    try {
      ImageIO.write(im, "png", new File(fnm));
      System.out.println("Saved image to " + fnm);
    }
    catch (Exception e) {
      System.out.println("Could not save image to " + fnm + ": " + e);
    }
  }  // end of saveImage()


  // ------------------- test rig ---------------------------

  public static void main(String[] args)
  {
    if (args.length != 1)
      System.out.println("Usage: run POIUtils <fnm>");
    else
      reportType(args[0]);
  }  // end of main()


} // end of POIUtils class
