package org.zanata.util;

import java.io.File;
import java.util.regex.Pattern;

import org.apache.commons.io.FilenameUtils;

/**
 * From
 * http://stackoverflow.com/questions/204784/how-to-construct-a-relative-path
 * -in-java-from-two-absolute-paths-or-urls/3054692#3054692
 * 
 */

public class PathUtil
{
   private static final String pathSeparator = System.getProperty("file.separator");

   /**
    * Get the relative path from one file to another, specifying the directory
    * separator. If one of the provided resources does not exist, it is assumed
    * to be a file unless it ends with '/' or '\'.
    * 
    * @param target targetPath is calculated to this file
    * @param base basePath is calculated from this file
    * @return
    */
   public static String getRelativePath(String targetPath, String basePath)
   {
      return getRelativePath(targetPath, basePath, pathSeparator);
   }

   /**
    * Get the relative path from one file to another, specifying the directory
    * separator. If one of the provided resources does not exist, it is assumed
    * to be a file unless it ends with '/' or '\'.
    * 
    * @param target targetPath is calculated to this file
    * @param base basePath is calculated from this file
    * @param separator directory separator. The platform default is not assumed
    *           so that we can test Unix behaviour when running on Windows (for
    *           example)
    * @return
    */
   public static String getRelativePath(String targetPath, String basePath, String pathSeparator)
   {

      // Normalize the paths
      String normalizedTargetPath = FilenameUtils.normalizeNoEndSeparator(targetPath);
      String normalizedBasePath = FilenameUtils.normalizeNoEndSeparator(basePath);

      // Undo the changes to the separators made by normalization
      if (pathSeparator.equals("/"))
      {
         normalizedTargetPath = FilenameUtils.separatorsToUnix(normalizedTargetPath);
         normalizedBasePath = FilenameUtils.separatorsToUnix(normalizedBasePath);

      }
      else if (pathSeparator.equals("\\"))
      {
         normalizedTargetPath = FilenameUtils.separatorsToWindows(normalizedTargetPath);
         normalizedBasePath = FilenameUtils.separatorsToWindows(normalizedBasePath);

      }
      else
      {
         throw new IllegalArgumentException("Unrecognised dir separator '" + pathSeparator + "'");
      }

      String[] base = normalizedBasePath.split(Pattern.quote(pathSeparator));
      String[] target = normalizedTargetPath.split(Pattern.quote(pathSeparator));

      // First get all the common elements. Store them as a string,
      // and also count how many of them there are.
      StringBuffer common = new StringBuffer();

      int commonIndex = 0;
      while (commonIndex < target.length && commonIndex < base.length && target[commonIndex].equals(base[commonIndex]))
      {
         common.append(target[commonIndex] + pathSeparator);
         commonIndex++;
      }

      if (commonIndex == 0)
      {
         // No single common path element. This most
         // likely indicates differing drive letters, like C: and D:.
         // These paths cannot be relativized.
         throw new PathResolutionException("No common path element found for '" + normalizedTargetPath + "' and '" + normalizedBasePath + "'");
      }

      // The number of directories we have to backtrack depends on whether the
      // base is a file or a dir
      // For example, the relative path from
      //
      // /foo/bar/baz/gg/ff to /foo/bar/baz
      //
      // ".." if ff is a file
      // "../.." if ff is a directory
      //
      // The following is a heuristic to figure out if the base refers to a file
      // or dir. It's not perfect, because
      // the resource referred to by this path may not actually exist, but it's
      // the best I can do
      boolean baseIsFile = true;

      File baseResource = new File(normalizedBasePath);

      if (baseResource.exists())
      {
         baseIsFile = baseResource.isFile();

      }
      else if (basePath.endsWith(pathSeparator))
      {
         baseIsFile = false;
      }

      StringBuffer relative = new StringBuffer();

      if (base.length != commonIndex)
      {
         int numDirsUp = baseIsFile ? base.length - commonIndex - 1 : base.length - commonIndex;

         for (int i = 0; i < numDirsUp; i++)
         {
            relative.append(".." + pathSeparator);
         }
      }
      relative.append(normalizedTargetPath.substring(common.length()));
      return relative.toString();
   }


   static class PathResolutionException extends RuntimeException
   {
      private static final long serialVersionUID = 1L;

      PathResolutionException(String msg)
      {
         super(msg);
      }
   }
}
@@ -40,16 +40,44 @@
 o.File;%0A
+import java.io.IOException;%0A
 import j
@@ -4815,9 +4815,258 @@
  %7D%0A   %7D%0A
-%7D
+%0A   public static boolean makeParents(File f) throws IOException%0A   %7B%0A      File parent = f.getCanonicalFile().getParentFile();%0A      if (parent == null %7C%7C parent.exists())%0A      %7B%0A         return false;%0A      %7D%0A      return parent.mkdirs();%0A   %7D%0A%0A%7D%0A

check for null parent when creating output directories