001/*
002 * Version 0.70 01/04/2002
003 *
004 * Visit my url for update: http://www.geocities.com/beapetrovicova/
005 * 
006 * jFtp was developed by Bea Petrovicova <beapetrovicova@yahoo.com>.
007 * The design and implementation of jFtp are available for royalty-free 
008 * adoption and use. This software is provided 'as is' without any 
009 * guarantees. Copyright is retained by Bea Petrovicova. Redistribution 
010 * of any part of jFtp or any derivative works must include this notice.
011 * 
012 */  
013
014package cz.dhl.io;
015
016import java.util.Date;
017import java.util.Vector;
018
019/**
020 * Orders, filters and splits arrays of CoFile objects.
021 * 
022 * @Version 0.70 01/04/2002
023 * @author Bea Petrovicova <beapetrovicova@yahoo.com>  
024 * @see CoFile
025 */
026public class CoSort
027{  private int sorttype;
028   
029   /** Order Option - Order by name. */
030   public static final int ORDER_BY_NAME = 1;
031   /** Order Option - Order by extension. */
032   public static final int ORDER_BY_TYPE = 2;
033   /** Order Option - Order by size. */
034   public static final int ORDER_BY_SIZE = 3;
035   /** Order Option - Order by date. */
036   public static final int ORDER_BY_DATE = 4;
037   /** Order Option - Order by Path. */
038   public static final int ORDER_BY_PATH = 5;
039   /** Order Option - Skip ordering. */
040   public static final int ORDER_BY_NONE = 6;
041   /** Order Flag - Inverse flag. */
042   public static final int ORDER_INVERSE = 8;   
043   CoSort(int sorttype) 
044      { this.sorttype = sorttype; }
045   
046   private boolean Pause() throws Exception { return true; }
047
048   private void Swap(CoFile a[], int i, int j)
049   {
050      CoFile T;
051      T = a[i]; 
052      a[i] = a[j];
053      a[j] = T;
054   }
055
056   private boolean AgreaterB(CoFile a,CoFile b)
057   {  boolean compare = false; 
058      switch(sorttype)
059      {
060      case ORDER_BY_NAME:
061         compare = (a.compareNameToIgnoreCase(b) > 0); break;
062      case ORDER_BY_TYPE:
063         compare = (a.compareExtToIgnoreCase(b) > 0); break;
064      case ORDER_BY_SIZE:
065         compare = (a.length() > b.length()); break;
066      case ORDER_BY_DATE:
067         compare = (new Date(a.lastModified()).after(new Date(b.lastModified()))); break;
068      case ORDER_BY_PATH:
069         compare = (a.compareTo(b) > 0); break;
070      } 
071      return compare;
072   }
073   
074   private boolean AsmallerB(CoFile a,CoFile b)
075   {  boolean compare = false; 
076      switch(sorttype)
077      {
078      case ORDER_BY_NAME:
079         compare = (a.compareNameToIgnoreCase(b) < 0); break;
080      case ORDER_BY_TYPE:
081         compare = (a.compareExtToIgnoreCase(b) < 0); break;
082      case ORDER_BY_SIZE:
083         compare = (a.length() < b.length()); break;
084      case ORDER_BY_DATE:
085         compare = (new Date(a.lastModified()).before(new Date(b.lastModified()))); break;
086      case ORDER_BY_PATH:
087         compare = (a.compareTo(b) < 0); break;
088      }
089      return compare;
090   }
091   
092   /** This is a generic version of C.A.R Hoare's Quick Sort 
093    * algorithm.  This will handle arrays that are already
094    * Sorted, and arrays with duplicate keys.
095    * If you think of a one dimensional array as going from
096    * the lowest index on the left to the highest index on the right
097    * then the parameters to this function are lowest index or
098    * left and highest index or right.  The first time you call
099    * this function it will be with the parameters 0, a.length - 1.
100    *
101    * @param a       an CoFile array
102    * @param lo0     left boundary of array partition
103    * @param hi0     right boundary of array partition */
104   private void QuickSort(CoFile a[], int lo0, int hi0) throws Exception
105   {
106      int lo = lo0;
107      int hi = hi0;
108      CoFile mid;
109
110      if ( hi0 > lo0)
111      {
112
113         /* Arbitrarily establishing partition element as the midpoint of
114          * the array. */
115         mid = a[ ( lo0 + hi0 ) / 2 ];
116
117         // loop through the array until indices cross
118         while( lo <= hi )
119         {
120            /* find the first element that is greater than or equal to 
121             * the partition element starting from the left Index. */
122             while( ( lo < hi0 ) && Pause() && AsmallerB(a[lo],mid))
123                 ++lo;
124
125            /* find an element that is smaller than or equal to 
126             * the partition element starting from the right Index. */
127             while( ( hi > lo0 ) && Pause() && AgreaterB(a[hi],mid))
128                 --hi;
129
130            // if the indexes have not crossed, Swap
131            if( lo <= hi ) 
132            {
133               Swap(a, lo, hi);
134               ++lo;
135               --hi;
136            }
137         }
138
139         /* If the right index has not reached the left side of array
140          * must now Sort the left partition. */
141         if( lo0 < hi )
142            QuickSort( a, lo0, hi );
143
144         /* If the left index has not reached the right side of array
145          * must now Sort the right partition. */
146         if( lo < hi0 )
147            QuickSort( a, lo, hi0 );
148
149      }
150   }
151
152   private void Sort(CoFile a[]) throws Exception
153   {  QuickSort(a, 0, a.length - 1); 
154      if((sorttype&ORDER_INVERSE) > 0)
155         for(int n=0; n<(a.length/2); n++)
156            Swap(a, n, a.length-1-n);
157   }
158
159   /** Returns an array of abstract pathnames filtered by specified filter list. */
160   static public CoFile[] listFilter(CoFile list[], String []filter)
161   {  if(filter.length != 0)
162      {  Vector ffv = new Vector(); 
163         for(int i=0;i<list.length;i++)
164            if(list[i].isDirectory() || 
165               list[i].isLink() ||
166               list[i].equalsExtTo(filter))
167               ffv.addElement(list[i]);
168         CoFile[] ffs = new CoFile[ffv.size()];
169         ffv.copyInto(ffs);
170         return ffs;
171      } else return list;
172   }
173
174   /** Returns an array of abstract pathnames ordered by specified sorttype. */
175   static public CoFile[] listOrder(CoFile list[], int sorttype) 
176   {  if( (sorttype&(~ORDER_INVERSE)) != ORDER_BY_NONE)
177      { CoSort s = new CoSort(sorttype);
178         try
179            { s.Sort(list); }
180         catch(Exception e)
181            {}
182         return list;
183      } else return list;
184   }
185   
186   /** Returns an array of abstract pathnames splited to directory and file part. */
187   static public CoFile[] listSplit(CoFile list[])
188   {  Vector ffv = new Vector(); 
189      for(int i=0;i<list.length;i++)
190         if(list[i].isDirectory() || list[i].isLink())
191            ffv.addElement(list[i]); 
192      for(int i=0;i<list.length;i++)
193         if(!list[i].isDirectory() && !list[i].isLink())
194            ffv.addElement(list[i]); 
195      CoFile[] ffs = new CoFile[ffv.size()];
196      ffv.copyInto(ffs);
197      return ffs;
198   }   
199}