001package org.unix4j.unix.ls; 002 003import java.io.File; 004import java.util.Comparator; 005 006import org.unix4j.util.FileUtil; 007import org.unix4j.util.sort.CompositeComparator; 008 009/** 010 * Non-instantiable class with static comparator constants used to sort files. 011 */ 012class FileComparators { 013 /** 014 * Sorts files according to file type. Hidden files are listed first, then 015 * normal files, all other files and finally the directories. 016 */ 017 static Comparator<File> FILE_TYPE = new Comparator<File>() { 018 @Override 019 public int compare(File f1, File f2) { 020 if (f1.isHidden()) { 021 return f2.isHidden() ? 0 : -1; 022 } else if (f2.isHidden()) { 023 return 1; 024 } 025 if (f1.isFile()) { 026 return f2.isFile() ? 0 : -1; 027 } else if (f2.isFile()) { 028 return 1; 029 } 030 if (!f1.isDirectory()) { 031 return !f2.isDirectory() ? 0 : -1; 032 } else if (!f2.isDirectory()) { 033 return 1; 034 } 035 return 0;// both directories 036 } 037 }; 038 039 /** 040 * Sorts files alphabetically according to the file name. 041 */ 042 static Comparator<File> FILE_NAME = new Comparator<File>() { 043 @Override 044 public int compare(File f1, File f2) { 045 return f1.getName().compareTo(f2.getName()); 046 } 047 }; 048 049 /** 050 * Sorts files alphabetically according to the relative file name from the 051 * specified root to the actual file. 052 * 053 * @param relativeTo 054 * the root for the relative file name 055 * @return a comparator for alphabetical ordering of the relative file names 056 */ 057 static Comparator<File> relativeFileName(final File relativeTo) { 058 return new Comparator<File>() { 059 @Override 060 public int compare(File f1, File f2) { 061 final String relName1 = FileUtil.getRelativePath(relativeTo, f1); 062 final String relName2 = FileUtil.getRelativePath(relativeTo, f2); 063 return relName1.compareTo(relName2); 064 } 065 }; 066 } 067 068 /** 069 * Sorts . before .. and then all other files. 070 * 071 * @param relativeTo 072 * the root to evaluate the . and .. files 073 * @return a comparator sorting . before .. before everything else 074 */ 075 static Comparator<File> dotDotdotRest(final File relativeTo) { 076 return new Comparator<File>() { 077 @Override 078 public int compare(File f1, File f2) { 079 final String relName1 = FileUtil.getRelativePath(relativeTo, f1); 080 final String relName2 = FileUtil.getRelativePath(relativeTo, f2); 081 082 final boolean isCur1 = ".".equals(relName1); 083 final boolean isCur2 = ".".equals(relName2); 084 if (isCur1) { 085 return isCur2 ? 0 : -1; 086 } else if (isCur2) { 087 return 1; 088 } 089 090 final boolean isPar1 = "..".equals(relName1); 091 final boolean isPar2 = "..".equals(relName2); 092 if (isPar1) { 093 return isPar2 ? 0 : -1; 094 } else if (isPar2) { 095 return 1; 096 } 097 098 return 0; 099 } 100 }; 101 } 102 103 /** 104 * Sorts files according to the last-modified time. More recently touched 105 * files appear first in a sorted list. 106 */ 107 static Comparator<File> FILE_LAST_MODIFIED = new Comparator<File>() { 108 @Override 109 public int compare(File f1, File f2) { 110 final long lastMod1 = f1.lastModified(); 111 final long lastMod2 = f2.lastModified(); 112 return lastMod1 > lastMod2 ? -1 : lastMod1 < lastMod2 ? 1 : 0; 113 } 114 }; 115 116 /** 117 * Sorts files according to file type and then by relative file name. Hidden 118 * files are listed first, then normal files, all other files and finally 119 * the directories. 120 * 121 * @param relativeTo 122 * the root for the relative file name 123 * @return a comparator first sorting by file type and then by relative file 124 * name 125 */ 126 static Comparator<File> typeAndRelativeFileName(File relativeTo) { 127 return new CompositeComparator<File>(dotDotdotRest(relativeTo), FILE_TYPE, relativeFileName(relativeTo)); 128 } 129 130 /** 131 * Sorts files according to the last modified time (last touched files 132 * first) and then by relative file name. 133 * @param relativeTo 134 * the root for the relative file name 135 * @return a comparator first sorting by last modified time and then by relative file 136 * name 137 */ 138 static Comparator<File> timeAndRelativeFileName(File relativeTo) { 139 return new CompositeComparator<File>(FILE_LAST_MODIFIED, relativeFileName(relativeTo)); 140 } 141 142 // no instances 143 private FileComparators() { 144 super(); 145 } 146 147}