Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/sonalb/Utils.java


1   /*
2    * -*- mode: java; c-basic-indent: 4; indent-tabs-mode: nil -*-
3    * :indentSize=4:noTabs=true:tabSize=4:indentOnTab=true:indentOnEnter=true:mode=java:
4    * ex: set tabstop=4 expandtab:
5    *
6    * MrPostman - webmail <-> email gateway
7    * Copyright (C) 2002-2003 MrPostman Development Group
8    * Projectpage: http://mrbook.org/mrpostman/
9    *
10   *
11   * This program is free software; you can redistribute it and/or modify
12   * it under the terms of the GNU General Public License as published by
13   * the Free Software Foundation; either version 2 of the License, or
14   * (at your option) any later version.
15   *
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   * In particular, this implies that users are responsible for
21   * using MrPostman after reading the terms and conditions given
22   * by their web-mail provider.
23   *
24   * You should have received a copy of the GNU General Public License
25   * Named LICENSE in the base directory of this distribution,
26   * if not, write to the Free Software
27   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28   */
29  
30  package com.sonalb;
31  
32  import java.text.ParsePosition;
33  import java.text.SimpleDateFormat;
34  
35  import java.util.Comparator;
36  import java.util.Date;
37  import java.util.SimpleTimeZone;
38  import java.util.StringTokenizer;
39  
40  
41  /**
42  
43   * Utility class containing several general-purpose methods for
44  
45   * system-wide consumption.
46  
47   *
48  
49   * @author    Sonal Bansal
50  
51   */
52  public abstract class Utils {
53      public static final String CVSID = "$Id: Utils.java,v 1.5 2003/02/09 23:38:09 lbruand Exp $";
54  
55      private Utils() {
56      }
57  
58      /**
59  
60       * Returns true if argument is either <code>null</code> or is full of
61  
62       * whitespace. The argument is full of whitespace if after calling <code>String.trim()</code>
63  
64       * on it, it equals(""). In other words, whitespace determination is done by
65  
66       * <code>String.trim()</code>.
67  
68       *
69  
70       * @param s    the String to be tested.
71  
72       * @see     java.lang.String#trim()
73  
74       */
75      public static boolean isNullOrWhiteSpace(String s) {
76          if ((s == null) || "".equals(s.trim())) {
77              return (true);
78          }
79  
80          return (false);
81      }
82  
83      /**
84  
85       * Returns the String obtained by removing any whitespace at both ends of the argument.
86  
87       * Whitespace is defined as stated by <code>Character.isWhitespace(char)</code>. It is
88  
89       * different from <code>String.trim()</code> which also removes any control characters.
90  
91       *
92  
93       * @param s    the String to be trimmed.
94  
95       * @return    the trimmed String.
96  
97       * @see        java.lang.Character#isWhitespace(char)
98  
99       * @see        java.lang.String#trim()
100 
101      */
102     public static String trimWhitespace(String s) {
103         if (s == null) {
104             return (s);
105         }
106 
107         return (trimRightWS(trimLeftWS(s)));
108     }
109 
110     /**
111 
112      * Returns the String obtained by removing any whitespace at the left hand side of the argument.
113 
114      * Whitespace is defined as stated by <code>Character.isWhitespace(char)</code>.
115 
116      *
117 
118      * @see        java.lang.Character#isWhitespace(char)
119 
120      * @param s    the String to be trimmed.
121 
122      * @return    the trimmed String.
123 
124      */
125     public static String trimLeftWS(String s) {
126         if (s == null) {
127             return (s);
128         }
129 
130         for (int i = 0; i < s.length(); i++) {
131             if (!Character.isWhitespace(s.charAt(i))) {
132                 return (s.substring(i));
133             }
134         }
135 
136         return (s);
137     }
138 
139     /**
140 
141      * Returns the String obtained by removing any whitespace at the right hand side of the argument.
142 
143      * Whitespace is defined as stated by <code>Character.isWhitespace(char)</code>.
144 
145      *
146 
147      * @see        java.lang.Character#isWhitespace(char)
148 
149      * @param s    the String to be trimmed.
150 
151      * @return    the trimmed String.
152 
153      */
154     public static String trimRightWS(String s) {
155         if (s == null) {
156             return (s);
157         }
158 
159         for (int i = s.length() - 1; i >= 0; i--) {
160             if (!Character.isWhitespace(s.charAt(i))) {
161                 return (s.substring(0, i + 1));
162             }
163         }
164 
165         return (s);
166     }
167 
168     /**
169 
170      * Convenience synonym for <code>trimWhitespace(String)</code>.
171 
172      *
173 
174      * @see        #trimWhitespace(String)
175 
176      * @param s    the String to be trimmed.
177 
178      * @return    the trimmed String.
179 
180      */
181     public static String trimWS(String s) {
182         return (trimWhitespace(s));
183     }
184 
185     /**
186 
187      * Tokenizes the argument String into several constituent Strings, separated by commas,
188 
189      * and returns the tokens as an array.
190 
191      *
192 
193      * @see        #delimitedStringToArray(String, String)
194 
195      * @param s    the String to be tokenized.
196 
197      * @return    the array of token Strings.
198 
199      */
200     public static String[] csvStringToArray(String s) {
201         return (delimitedStringToArray(s, ","));
202     }
203 
204     /**
205 
206      * Tokenizes the argument String into several constituent Strings, separated by specified
207 
208      * delimiters, and returns the tokens as an array. Every character of the delimiter String is
209 
210      * treated as a token-separator individually.
211 
212      *
213 
214      * @param s    the String to be tokenized.
215 
216      * @param delimiters    the String of delimiters.
217 
218      * @return    the array of token Strings.
219 
220      */
221     public static String[] delimitedStringToArray(String s, String delimiters) {
222         if (isNullOrWhiteSpace(s)) {
223             return (null);
224         }
225 
226         delimiters = (delimiters == null) ? ",;" : delimiters;
227 
228         StringTokenizer st = new StringTokenizer(s, delimiters);
229 
230         int num;
231 
232         if ((num = st.countTokens()) == 0) {
233             return (null);
234         }
235 
236         String[] array = new String[num];
237 
238         for (int i = 0; i < num; i++) {
239             array[i] = st.nextToken();
240         }
241 
242         return (array);
243     }
244 
245     /**
246 
247      * Checks whether the specified Object exists in the given array. The <code>Object.equals(Object)</code>
248 
249      * method is used to test for equality.
250 
251      *
252 
253      * @see        java.lang.Object#equals(Object)
254 
255      * @param obj    the Object to be searched for.
256 
257      * @param array    the array which has to be searched.
258 
259      * @return    <code>true</code> if the Object exists in the array; <code>false</code> if the Object
260 
261      *         does not exist in the array, or the object, or the array is <code>null</code>.
262 
263      */
264     public static boolean isInArray(Object obj, Object[] array) {
265         if ((obj == null) || (array == null)) {
266             return (false);
267         }
268 
269         for (int i = 0; i < array.length; i++) {
270             if (array[i].equals(obj)) {
271                 return (true);
272             }
273         }
274 
275         return (false);
276     }
277 
278     /**
279 
280      * Counts the number of times the specified character appears in the input String. For example,
281 
282      * <code>countInstances("abcabcdabcde",'a')</code> returns 3.
283 
284      *
285 
286      * @param s    the String to be counted in.
287 
288      * @param c     the character to be counted.
289 
290      * @return    the number of occurrences of <code>c</code> in <code>s</code> ; -1 if <code>s</code> is <code>null</code>.
291 
292      */
293     public static int countInstances(String s, char c) {
294         if (isNullOrWhiteSpace(s)) {
295             return (-1);
296         }
297 
298         int count = 0;
299 
300         for (int i = 0; i < s.length(); i++) {
301             if (s.charAt(i) == c) {
302                 count++;
303             }
304         }
305 
306         return (count);
307     }
308 
309     /**
310 
311      * Counts the number of times the specified String appears in the input String. For example,
312 
313      * <code>countInstances("abcabcdabcde","cd")</code> returns 2.
314 
315      *
316 
317      * @param s    the String to be counted in.
318 
319      * @param c     the String to be counted.
320 
321      * @return    the number of occurrences of <code>c</code> in <code>s</code> ; -1 if <code>s</code> or <code>c</code> is <code>null</code>.
322 
323      */
324     public static int countInstances(String s, String c) {
325         if (isNullOrWhiteSpace(s) || isNullOrWhiteSpace(c)) {
326             return (-1);
327         }
328 
329         int count = 0;
330 
331         int len = c.length();
332 
333         for (int i = 0; i < s.length(); i += len) {
334             if ((i = s.indexOf(c, i)) != -1) {
335                 count++;
336             } else {
337                 break;
338             }
339         }
340 
341         return (count);
342     }
343 
344     /**
345 
346      * Checks whether the input String is a valid IP address (quad).
347 
348      *
349 
350      * @param s    the String to be checked.
351 
352      * @return    <code>true</code> if the String IS an IP address ; <code>false</code> if
353 
354      *         it is not, or <code>s</code> is <code>null</code>.
355 
356      * @see java.net.InetAddress
357 
358      */
359     public static boolean isIPAddress(String s) {
360         if (isNullOrWhiteSpace(s) || (s.indexOf('.') == -1)) {
361             return (false);
362         }
363 
364         s = s.trim();
365 
366         int index;
367         int dotCount = 0;
368         int[] dotPos = new int[5];
369 
370         char ch;
371 
372         dotPos[0] = -1;
373 
374         dotPos[4] = s.length();
375 
376         for (index = 0; (index < s.length()) && (dotCount < 4); index++) {
377             ch = s.charAt(index);
378 
379             if (!Character.isDigit(ch) && (ch != '.')) {
380                 return (false);
381             } else if (ch == '.') {
382                 dotPos[++dotCount] = index;
383             }
384         }
385 
386         if (dotCount != 3) {
387             return (false);
388         }
389 
390         try {
391             String num;
392 
393             int number;
394 
395             for (dotCount = 1; dotCount < 5; dotCount++) {
396                 index = dotPos[dotCount - 1] + 1;
397 
398                 num = s.substring(index, dotPos[dotCount]);
399 
400                 number = Integer.valueOf(num).intValue();
401 
402                 if ((number < 0) || (number > 255)) {
403                     return (false);
404                 }
405             }
406         } catch (Exception e) {
407             return (false);
408         }
409 
410         return (true);
411     }
412 
413     /**
414 
415      * Converts the input Date into a String formatted as specified by RFC 1123 of the IETF.
416 
417      * The output String is in the format "Sun, 06 Nov 1994 08:49:37 GMT".
418 
419      *
420 
421      * @param d    the Date to be converted.
422 
423      * @return    the String representation of the date as specified by RFC1123 ; <code>null</code>
424 
425      *         if input is <code>null</code>.
426 
427      * @see java.util.Date
428 
429      */
430     public static String convertToHttpDate(Date d) {
431         if (d == null) {
432             return (null);
433         }
434 
435         SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
436 
437         sdf.setTimeZone(new SimpleTimeZone(0, "GMT"));
438 
439         return (sdf.format(d));
440     }
441 
442     /**
443 
444      * Parses the input date String into a Date object. The input date String is
445 
446      * expected to be in one of the following formats (note the spaces) :-<p>
447 
448      * <ul>
449 
450      * <li>"Sun, 06 Nov 1994 08:49:37 GMT"    ; RFC 822, updated by RFC 1123</li>
451 
452      * <li>"Sunday, 06-Nov-94 08:49:37 GMT"   ; RFC 850, obsoleted by RFC 1036</li>
453 
454      * <li>"Sunday, 06-Nov-1994 08:49:37 GMT" ; RFC 1036</li>
455 
456      * <li>"Sun Nov  6 08:49:37 1994"         ; ANSI C's asctime() format</li>
457 
458      * </ul>
459 
460      *
461 
462      * @param date    the HTTP date String to be converted.
463 
464      * @return    the parsed Date object ; <code>null</code> if
465 
466      *         parsing was unsuccessful or input was <code>null</code>.
467 
468      */
469     public static Date parseHttpDateStringToDate(String date) {
470         if (date == null) {
471             return (null);
472         }
473 
474         StringTokenizer st = new StringTokenizer(date.trim(), " ");
475 
476         int iNumTokens = st.countTokens();
477 
478         String format = null;
479 
480         if (iNumTokens == 5)   // Its an asctime date ... wkday SP month SP ( 2DIGIT | ( SP 1DIGIT )) SP time SP 4DIGIT
481          {   //                                           ; month day (e.g., Jun  2)
482             // Sun Nov  6 08:49:37 1994
483             format = "EEE MMM dd HH:mm:ss yyyy";
484         } else if (iNumTokens == 4)   // Its an RFC850 date ... weekday "," SP 2DIGIT "-" month "-" 2DIGIT SP time SP "GMT"
485          {   // ; day-month-year (e.g., 02-Jun-82)
486             String dtok = null;   // may have 2 or 4-digit year
487 
488             st.nextToken();
489 
490             dtok = st.nextToken().trim();
491 
492             if (dtok.length() == 9) {  // has 2-digit year
493                 // Sunday, 06-Nov-94 08:49:37 GMT
494                 format = "EEEE, dd-MMM-yy HH:mm:ss zzz";
495             } else if (dtok.length() == 11) {  // has 4-digit year
496                 // Sunday, 06-Nov-1994 08:49:37 GMT 
497                 format = "EEEE, dd-MMM-yyyy HH:mm:ss zzz";
498             } else {
499                 return (null);
500             }
501         } else if (iNumTokens == 6)   // Its an RFC1123 date ... wkday "," SP 2DIGIT SP month SP 4DIGIT SP time SP "GMT"
502          {   // ; day-month-year (e.g., 02 Jun 1982)
503             //Sun, 06 Nov 1994 08:49:37 GMT
504             format = "EEE, dd MMM yyyy HH:mm:ss zzz";
505         } else {
506             return (null);
507         }
508 
509         SimpleDateFormat sdf = new SimpleDateFormat(format);
510 
511         sdf.setTimeZone(new SimpleTimeZone(0, "GMT"));
512 
513         Date d = sdf.parse(date, new ParsePosition(0));
514 
515         return (d);
516     }
517 
518     /**
519 
520      * Returns true if argument is either <code>null</code> or it equals("").
521 
522      * It does not trim the input, unlike <code>isNullOrWhiteSpace(String)</code>.
523 
524      *
525 
526      * @param s    the String to be tested.
527 
528      * @see     #isNullOrWhiteSpace(String)
529 
530      */
531     public static boolean isEmpty(String s) {
532         return ((s == null) || s.equals(""));
533     }
534 
535     /**
536 
537      * Replaces all occurrences of a String in the input String with another String.
538 
539      *
540 
541      * @param source    the String in which the replacements are to be carried out.
542 
543      * @param find        the String which must be searched for.
544 
545      * @param replace    the String which replaces the search String.
546 
547      * @param bIgnoreCase    determines whether case-sensitive search is done.
548 
549      * @return     the processed String if any replacements were made ; the original String if
550 
551      *         search String was not found or search String is empty.
552 
553      * @throws IllegalArgumentException    Thrown if source String is empty.
554 
555      */
556     public static String replaceAll(String source, String find, String replace, boolean bIgnoreCase)
557         throws IllegalArgumentException {
558         if (isEmpty(source)) {
559             throw new IllegalArgumentException("Empty source String");
560         } else if (isEmpty(find)) {
561             return (source);
562         }
563 
564         if (replace == null) {
565             replace = "";
566         }
567 
568         StringBuffer sb = new StringBuffer(source);
569 
570         StringBuffer mod;
571 
572         boolean bDone = false;
573 
574         int prevIndex = 0;
575         int currIndex = 0;
576         int i = 0;
577 
578         if (bIgnoreCase) {
579             source = source.toLowerCase();
580 
581             find = find.toLowerCase();
582         }
583 
584         mod = new StringBuffer(source);
585 
586         while (!bDone) {
587             if ((currIndex = mod.toString().indexOf(find, prevIndex)) != -1) {
588                 sb = sb.replace(currIndex, currIndex + find.length(), replace);
589 
590                 mod = mod.replace(currIndex, currIndex + find.length(), replace);
591 
592                 prevIndex = currIndex + replace.length();
593             } else {
594                 bDone = true;
595             }
596         }
597 
598         return (sb.toString());
599     }
600 
601     /**
602 
603      * Determines whether every double-quote has its closing partner in the input String.
604 
605      *
606 
607      * @param s     the String to be tested.
608 
609      * @return    <code>true</code> if quotes match or no quotes exist ; <code>false</code> otherwise.
610 
611      */
612     public static boolean matchQuotes(String s) {
613         int numQuotes = 0;
614         int numEscapedQuotes = 0;
615 
616         numQuotes = countInstances(s, '\"');
617 
618         numEscapedQuotes = countInstances(s, "\\\"");
619 
620         if (numQuotes == -1) {
621             return (true);
622         }
623 
624         if (numEscapedQuotes == -1) {
625             numEscapedQuotes = 0;
626         }
627 
628         return (((numQuotes - numEscapedQuotes) % 2) == 0);
629     }
630 
631     /**
632 
633      * Removes the outermost double-quotes pair from the input String. Trims the input String
634 
635      * before processing.
636 
637      *
638 
639      * @param s     the String to be stripped.
640 
641      * @return    the stripped String ; the original String if it is not quoted or quotes don't match.
642 
643      */
644     public static String stripQuotes(String s) {
645         if (isNullOrWhiteSpace(s) || !matchQuotes(s)) {
646             return (s);
647         }
648 
649         String s2 = trimWhitespace(s);
650 
651         if (isQuoted(s2)) {
652             return (s2.substring(1, s2.length() - 1));
653         }
654 
655         return (s);
656     }
657 
658     /**
659 
660      * Determines whether the input String is enclosed in double-quotes. Trims the input String
661 
662      * first.
663 
664      *
665 
666      * @param s     the String to be tested.
667 
668      * @return    <code>true</code> if input String is quoted ;
669 
670      *         <code>false</code> if it isn't or it is empty.
671 
672      * @see        #trimWhitespace(String)
673 
674      */
675     public static boolean isQuoted(String s) {
676         if (isNullOrWhiteSpace(s) || !matchQuotes(s)) {
677             return (false);
678         }
679 
680         String s2 = trimWhitespace(s);
681 
682         return ((s2.charAt(0) == '\"') && (s.charAt(s2.length() - 1) == '\"'));
683     }
684 
685     /**
686 
687      * Converts the input integer into a more readable comma-separated String. A
688 
689      * comma is inserted after every three digits, starting from the unit's place. For
690 
691      * example, <p><pre>
692 
693      *     12345        is converted to     12,345
694 
695      *     987654321    is converted to     987,654,321</pre>
696 
697      *
698 
699      * @param i     the integer to be converted.
700 
701      * @return    the String representation of the formatted integer ; if the input
702 
703      *         lies between -1000 & 1000 (not inclusive) , the returned String is
704 
705      *         the same as <code>String.valueOf(int)</code>
706 
707      * @see        java.lang.String#valueOf(int)
708 
709      */
710     public static String commaFormatInteger(int i) {
711         boolean bNegative = (i < 0);
712 
713         if ((i == 0) || ((i > 0) && (i < 1000)) || ((i < 0) && (i > -1000))) {
714             return (String.valueOf(i));
715         }
716 
717         i = Math.abs(i);
718 
719         StringBuffer sb = new StringBuffer(String.valueOf(i));
720 
721         sb.reverse();
722 
723         int l = sb.length();
724 
725         int iter = l / 3;
726 
727         if ((l % 3) == 0) {
728             iter--;
729         }
730 
731         for (int c = 1; c <= iter; c++) {
732             l = 3 * c;
733 
734             sb.insert((l + c) - 1, ',');
735         }
736 
737         if (bNegative) {
738             sb.append('-');
739         }
740 
741         return (sb.reverse().toString());
742     }
743 
744     /**
745 
746      * Returns the number which would be in the n<sup>th</sup> place if the input array were sorted
747 
748      * in descending order. For arrays with distinct elements, this returns the n<sup>th</sup> largest
749 
750      * number. For example, in the array {1,2,3,4,5,6}, <code>findOrderedMax(list, 3)</code> would return 4.
751 
752      * However, the result is quite different in arrays with repeated elements.
753 
754      * For example, in the array {1,2,6,2}, both <code>findOrderedMax(list,2)</code>
755 
756      * and <code>findOrderedMax(list,3)</code> return 2.
757 
758      *
759 
760      * @see #findMax(int[],int)
761 
762      * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
763 
764      *                     the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
765 
766      *                     Or, when the order <code>n</code> is less than or equal to 0.
767 
768      * @param inputlist    the array of numbers.
769 
770      * @param n    the desired position of sorted array. For example, 1 indicates first from top of sorted array; 2 indicates second from top, and so on.
771 
772      */
773     public static int findOrderedMax(int[] inputlist, int n) {
774         if (inputlist.length < n) {
775             throw new IllegalArgumentException("Input array should have atleast input order numbers.");
776         }
777 
778         if (n <= 0) {
779             throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
780         }
781 
782         int numIters;
783         int i;
784 
785         int maxIndex;
786         int temp;
787 
788         int[] list = new int[inputlist.length];
789 
790         System.arraycopy(inputlist, 0, list, 0, list.length);
791 
792         for (numIters = 0; numIters < n; numIters++) {
793             maxIndex = 0;
794 
795             for (i = 0; i < (list.length - numIters); i++) {
796                 if (list[i] > list[maxIndex]) {
797                     maxIndex = i;
798                 }
799             }
800 
801             temp = list[i - 1];
802 
803             list[i - 1] = list[maxIndex];
804 
805             list[maxIndex] = temp;
806         }
807 
808         return (list[list.length - n]);
809     }
810 
811     /**
812 
813      * Returns the n<sup>th</sup> largest number in the input array. This method disregards
814 
815      * duplicate elements unlike the <code>findOrderedMax</code> method. For example, in the array {1,2,3,4,5,6},
816 
817      * <code>findMax(list, 3)</code> would return 4. In the array {1,2,6,2}, <code>findMax(list,2)</code> would return 2, and
818 
819      * and <code>findMax(list,3)</code> would return 1. <p> Note that in an array with repeating elements, it is possible that
820 
821      * the required order may not exist. For example, in the array {1,2,2}, <code>findMax(list,3)</code>, there is no third-largest
822 
823      * number. In such cases, this method returns the number with highest order less than or equal to <code>n</code>. In other words,
824 
825      * in the above example, this method would return 1, which is the same value as would be returned by <code>findMax(list,2)</code>.
826 
827      *
828 
829      * @see #findOrderedMax(int[],int)
830 
831      * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
832 
833      *                     the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
834 
835      *                     Or, when the order <code>n</code> is less than or equal to 0.
836 
837      * @param inputlist    the array of numbers.
838 
839      * @param n    the desired order. For example, 1 indicates largest number; 2 indicates second-largest number, and so on.
840 
841      */
842     public static int findMax(int[] inputlist, int n) {
843         if (inputlist.length < n) {
844             throw new IllegalArgumentException("Input array should have atleast input order numbers.");
845         }
846 
847         if (n <= 0) {
848             throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
849         }
850 
851         int numIters;
852         int i;
853 
854         int maxIndex;
855         int temp;
856 
857         int[] order = new int[n];
858 
859         int oindex = 0;
860 
861         int currIter = 0;
862 
863         int[] list = new int[inputlist.length];
864 
865         System.arraycopy(inputlist, 0, list, 0, list.length);
866 
867         for (numIters = 0; numIters < list.length; numIters++) {
868             maxIndex = 0;
869 
870             for (i = 0; i < (list.length - numIters); i++) {
871                 if (list[i] > list[maxIndex]) {
872                     maxIndex = i;
873                 }
874             }
875 
876             temp = list[maxIndex];
877 
878             list[maxIndex] = list[i - 1];
879 
880             list[i - 1] = temp;
881 
882             if ((oindex == 0) || (order[oindex - 1] != temp)) {
883                 order[oindex++] = temp;
884 
885                 currIter++;
886             }
887 
888             if (currIter == n) {
889                 break;
890             }
891         }
892 
893         return (order[oindex - 1]);
894     }
895 
896     /**
897 
898      * Returns the number which would be in the n<sup>th</sup> place if the input array were sorted
899 
900      * in ascending order. For arrays with distinct elements, this returns the n<sup>th</sup> smallest
901 
902      * number. For example, in the array {1,2,3,4,5,6}, <code>findOrderedMin(list, 3)</code> would return 3.
903 
904      * However, the result is quite different in arrays with repeated elements.
905 
906      * For example, in the array {1,2,6,2}, both <code>findOrderedMin(list,2)</code>
907 
908      * and <code>findOrderedMin(list,3)</code> return 2.
909 
910      *
911 
912      * @see #findMin(int[],int)
913 
914      * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
915 
916      *                     the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
917 
918      *                     Or, when the order <code>n</code> is less than or equal to 0.
919 
920      * @param inputlist    the array of numbers.
921 
922      * @param n    the desired position of sorted array. For example, 1 indicates first from top of sorted array; 2 indicates second from top, and so on.
923 
924      */
925     public static int findOrderedMin(int[] inputlist, int n) {
926         if (inputlist.length < n) {
927             throw new IllegalArgumentException("Input array should have atleast input order numbers.");
928         }
929 
930         if (n <= 0) {
931             throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
932         }
933 
934         int numIters;
935         int i;
936 
937         int minIndex;
938         int temp;
939 
940         int[] list = new int[inputlist.length];
941 
942         System.arraycopy(inputlist, 0, list, 0, list.length);
943 
944         for (numIters = 0; numIters < n; numIters++) {
945             minIndex = 0;
946 
947             for (i = 0; i < (list.length - numIters); i++) {
948                 if (list[i] < list[minIndex]) {
949                     minIndex = i;
950                 }
951             }
952 
953             temp = list[i - 1];
954 
955             list[i - 1] = list[minIndex];
956 
957             list[minIndex] = temp;
958         }
959 
960         return (list[list.length - n]);
961     }
962 
963     /**
964 
965      * Returns the n<sup>th</sup> smallest number in the input array. This method disregards
966 
967      * duplicate elements unlike the <code>findOrderedMin</code> method. For example, in the array {1,2,3,4,5,6},
968 
969      * <code>findMin(list, 3)</code> would return 3. In the array {1,2,6,2}, <code>findMin(list,2)</code> would return 2, and
970 
971      * and <code>findMin(list,3)</code> would return 6. <p> Note that in an array with repeating elements, it is possible that
972 
973      * the required order may not exist. For example, in the array {1,2,2}, <code>findMin(list,3)</code>, there is no third-smallest
974 
975      * number. In such cases, this method returns the number with highest order less than or equal to <code>n</code>. In other words,
976 
977      * in the above example, this method would return 2, which is the same value as would be returned by <code>findMax(list,2)</code>.
978 
979      *
980 
981      * @see #findOrderedMin(int[],int)
982 
983      * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
984 
985      *                     the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
986 
987      *                     Or, when the order <code>n</code> is less than or equal to 0.
988 
989      * @param inputlist    the array of numbers.
990 
991      * @param n    the desired order. For example, 1 indicates smallest number; 2 indicates second-smallest number, and so on.
992 
993      */
994     public static int findMin(int[] inputlist, int n) {
995         if (inputlist.length < n) {
996             throw new IllegalArgumentException("Input array should have atleast input order numbers.");
997         }
998 
999         if (n <= 0) {
1000            throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
1001        }
1002
1003        int numIters;
1004        int i;
1005
1006        int minIndex;
1007        int temp;
1008
1009        int[] order = new int[n];
1010
1011        int oindex = 0;
1012
1013        int currIter = 0;
1014
1015        int[] list = new int[inputlist.length];
1016
1017        System.arraycopy(inputlist, 0, list, 0, list.length);
1018
1019        for (numIters = 0; numIters < list.length; numIters++) {
1020            minIndex = 0;
1021
1022            for (i = 0; i < (list.length - numIters); i++) {
1023                if (list[i] < list[minIndex]) {
1024                    minIndex = i;
1025                }
1026            }
1027
1028            temp = list[minIndex];
1029
1030            list[minIndex] = list[i - 1];
1031
1032            list[i - 1] = temp;
1033
1034            if ((oindex == 0) || (order[oindex - 1] != temp)) {
1035                order[oindex++] = temp;
1036
1037                currIter++;
1038            }
1039
1040            if (currIter == n) {
1041                break;
1042            }
1043        }
1044
1045        return (order[oindex - 1]);
1046    }
1047
1048    /**
1049
1050     * Returns the object which would be in the n<sup>th</sup> place if the input array were sorted
1051
1052     * in descending order. This method allows comparison of <code>Object</code>s. It follows similar
1053
1054     * semantics as the <code>findOrderedMax(int[], int)</code> method.
1055
1056     *
1057
1058     * @see #findMax(Comparable[],int)
1059
1060     * @see #findOrderedMax(int[],int)
1061
1062     * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
1063
1064     *                     the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
1065
1066     *                     Or, when the order <code>n</code> is less than or equal to 0.
1067
1068     * @param inputlist    the array of <code>Comparable</code> objects. All elements must be <i>mutually Comparable</i> (that is, e1.compareTo(e2) must not throw a ClassCastException for any elements e1 and e2 in the array).
1069
1070     * @param n    the desired position of sorted array. For example, 1 indicates first from top of sorted array; 2 indicates second from top, and so on.
1071
1072     */
1073    public static Object findOrderedMax(Comparable[] inputlist, int n) {
1074        if (inputlist.length < n) {
1075            throw new IllegalArgumentException("Input array should have atleast input order numbers.");
1076        }
1077
1078        if (n <= 0) {
1079            throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
1080        }
1081
1082        int numIters;
1083        int i;
1084
1085        int maxIndex;
1086
1087        Comparable temp;
1088
1089        Comparable[] list = new Comparable[inputlist.length];
1090
1091        System.arraycopy(inputlist, 0, list, 0, list.length);
1092
1093        for (numIters = 0; numIters < n; numIters++) {
1094            maxIndex = 0;
1095
1096            for (i = 0; i < (list.length - numIters); i++) {
1097                if (list[i].compareTo(list[maxIndex]) > 0) {
1098                    maxIndex = i;
1099                }
1100            }
1101
1102            temp = list[i - 1];
1103
1104            list[i - 1] = list[maxIndex];
1105
1106            list[maxIndex] = temp;
1107        }
1108
1109        return (list[list.length - n]);
1110    }
1111
1112    /**
1113
1114     * Returns the n<sup>th</sup> largest object in the input array. This method allows comparison of <code>Object</code>s. It follows similar
1115
1116     * semantics as the <code>findMax(int[], int)</code> method.
1117
1118     *
1119
1120     * @see #findOrderedMax(Comparable[],int)
1121
1122     * @see #findMax(int[],int)
1123
1124     * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
1125
1126     *                     the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
1127
1128     *                     Or, when the order <code>n</code> is less than or equal to 0.
1129
1130     * @param inputlist    the array of <code>Comparable</code> objects. All elements must be <i>mutually Comparable</i> (that is, e1.compareTo(e2) must not throw a ClassCastException for any elements e1 and e2 in the array).
1131
1132     * @param n    the desired order. For example, 1 indicates largest object; 2 indicates second-largest object, and so on.
1133
1134     */
1135    public static Object findMax(Comparable[] inputlist, int n) {
1136        if (inputlist.length < n) {
1137            throw new IllegalArgumentException("Input array should have atleast input order numbers.");
1138        }
1139
1140        if (n <= 0) {
1141            throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
1142        }
1143
1144        int numIters;
1145        int i;
1146
1147        int maxIndex;
1148
1149        Comparable temp;
1150
1151        Comparable[] order = new Comparable[n];
1152
1153        int oindex = 0;
1154
1155        int currIter = 0;
1156
1157        Comparable[] list = new Comparable[inputlist.length];
1158
1159        System.arraycopy(inputlist, 0, list, 0, list.length);
1160
1161        for (numIters = 0; numIters < list.length; numIters++) {
1162            maxIndex = 0;
1163
1164            for (i = 0; i < (list.length - numIters); i++) {
1165                if (list[i].compareTo(list[maxIndex]) > 0) {
1166                    maxIndex = i;
1167                }
1168            }
1169
1170            temp = list[maxIndex];
1171
1172            list[maxIndex] = list[i - 1];
1173
1174            list[i - 1] = temp;
1175
1176            if ((oindex == 0) || !order[oindex - 1].equals(temp)) {
1177                order[oindex++] = temp;
1178
1179                currIter++;
1180            }
1181
1182            if (currIter == n) {
1183                break;
1184            }
1185        }
1186
1187        return (order[oindex - 1]);
1188    }
1189
1190    /**
1191
1192     * Returns the object which would be in the n<sup>th</sup> place if the input array were sorted
1193
1194     * in ascending order. This method allows comparison of <code>Object</code>s. It follows similar
1195
1196     * semantics as the <code>findOrderedMin(int[], int)</code> method.
1197
1198     *
1199
1200     * @see #findMin(Comparable[],int)
1201
1202     * @see #findOrderedMin(int[],int)
1203
1204     * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
1205
1206     *                     the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
1207
1208     *                     Or, when the order <code>n</code> is less than or equal to 0.
1209
1210     * @param inputlist    the array of <code>Comparable</code> objects. All elements must be <i>mutually Comparable</i> (that is, e1.compareTo(e2) must not throw a ClassCastException for any elements e1 and e2 in the array).
1211
1212     * @param n    the desired position of sorted array. For example, 1 indicates first from top of sorted array; 2 indicates second from top, and so on.
1213
1214     */
1215    public static Object findOrderedMin(Comparable[] inputlist, int n) {
1216        if (inputlist.length < n) {
1217            throw new IllegalArgumentException("Input array should have atleast input order numbers.");
1218        }
1219
1220        if (n <= 0) {
1221            throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
1222        }
1223
1224        int numIters;
1225        int i;
1226
1227        int minIndex;
1228
1229        Comparable temp;
1230
1231        Comparable[] list = new Comparable[inputlist.length];
1232
1233        System.arraycopy(inputlist, 0, list, 0, list.length);
1234
1235        for (numIters = 0; numIters < n; numIters++) {
1236            minIndex = 0;
1237
1238            for (i = 0; i < (list.length - numIters); i++) {
1239                if (list[i].compareTo(list[minIndex]) < 0) {
1240                    minIndex = i;
1241                }
1242            }
1243
1244            temp = list[i - 1];
1245
1246            list[i - 1] = list[minIndex];
1247
1248            list[minIndex] = temp;
1249        }
1250
1251        return (list[list.length - n]);
1252    }
1253
1254    /**
1255
1256     * Returns the n<sup>th</sup> smallest object in the input array. This method allows comparison of <code>Object</code>s. It follows similar
1257
1258     * semantics as the <code>findMin(int[], int)</code> method.
1259
1260     *
1261
1262     * @see #findOrderedMin(Comparable[],int)
1263
1264     * @see #findMin(int[],int)
1265
1266     * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
1267
1268     *                     the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
1269
1270     *                     Or, when the order <code>n</code> is less than or equal to 0.
1271
1272     * @param inputlist    the array of <code>Comparable</code> objects. All elements must be <i>mutually Comparable</i> (that is, e1.compareTo(e2) must not throw a ClassCastException for any elements e1 and e2 in the array).
1273
1274     * @param n    the desired order. For example, 1 indicates smallest object; 2 indicates second-smallest object, and so on.
1275
1276     */
1277    public static Object findMin(Comparable[] inputlist, int n) {
1278        if (inputlist.length < n) {
1279            throw new IllegalArgumentException("Input array should have atleast input order numbers.");
1280        }
1281
1282        if (n <= 0) {
1283            throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
1284        }
1285
1286        int numIters;
1287        int i;
1288
1289        int minIndex;
1290
1291        Comparable temp;
1292
1293        Comparable[] order = new Comparable[n];
1294
1295        int oindex = 0;
1296
1297        int currIter = 0;
1298
1299        Comparable[] list = new Comparable[inputlist.length];
1300
1301        System.arraycopy(inputlist, 0, list, 0, list.length);
1302
1303        for (numIters = 0; numIters < list.length; numIters++) {
1304            minIndex = 0;
1305
1306            for (i = 0; i < (list.length - numIters); i++) {
1307                if (list[i].compareTo(list[minIndex]) < 0) {
1308                    minIndex = i;
1309                }
1310            }
1311
1312            temp = list[minIndex];
1313
1314            list[minIndex] = list[i - 1];
1315
1316            list[i - 1] = temp;
1317
1318            if ((oindex == 0) || !order[oindex - 1].equals(temp)) {
1319                order[oindex++] = temp;
1320
1321                currIter++;
1322            }
1323
1324            if (currIter == n) {
1325                break;
1326            }
1327        }
1328
1329        return (order[oindex - 1]);
1330    }
1331
1332    /**
1333
1334     * Returns the object which would be in the n<sup>th</sup> place if the input array were sorted
1335
1336     * in descending order. This method allows comparison of <code>Object</code>s. The comparison logic
1337
1338     * is provided by the <code>Comparator</code> argument. It follows similar
1339
1340     * semantics as the <code>findOrderedMax(int[], int)</code> method.
1341
1342     *
1343
1344     * @see #findMax(Object[],int,Comparator)
1345
1346     * @see #findOrderedMax(int[],int)
1347
1348     * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
1349
1350     *                     the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
1351
1352     *                     Or, when the order <code>n</code> is less than or equal to 0.
1353
1354     * @param c the <code>Comparator</code> that provides the ordering logic.
1355
1356     * @param inputlist    the array of <code>Object</code>s.
1357
1358     * @param n    the desired position of sorted array. For example, 1 indicates first from top of sorted array; 2 indicates second from top, and so on.
1359
1360     */
1361    public static Object findOrderedMax(Object[] inputlist, int n, Comparator c) {
1362        if (inputlist.length < n) {
1363            throw new IllegalArgumentException("Input array should have atleast input order numbers.");
1364        }
1365
1366        if (n <= 0) {
1367            throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
1368        }
1369
1370        int numIters;
1371        int i;
1372
1373        int maxIndex;
1374
1375        Object temp;
1376
1377        Object[] list = new Object[inputlist.length];
1378
1379        System.arraycopy(inputlist, 0, list, 0, list.length);
1380
1381        for (numIters = 0; numIters < n; numIters++) {
1382            maxIndex = 0;
1383
1384            for (i = 0; i < (list.length - numIters); i++) {
1385                if (c.compare(list[i], list[maxIndex]) > 0) {
1386                    maxIndex = i;
1387                }
1388            }
1389
1390            temp = list[i - 1];
1391
1392            list[i - 1] = list[maxIndex];
1393
1394            list[maxIndex] = temp;
1395        }
1396
1397        return (list[list.length - n]);
1398    }
1399
1400    /**
1401
1402     * Returns the n<sup>th</sup> largest object in the input array. This method allows comparison of <code>Object</code>s.
1403
1404     * The comparison logic is provided by the <code>Comparator</code> argument. It follows similar
1405
1406     * semantics as the <code>findMax(int[], int)</code> method.
1407
1408     *
1409
1410     * @see #findOrderedMax(Object[],int,Comparator)
1411
1412     * @see #findMax(int[],int)
1413
1414     * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
1415
1416     *                     the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
1417
1418     *                     Or, when the order <code>n</code> is less than or equal to 0.
1419
1420     * @param c the <code>Comparator</code> that provides the ordering logic.
1421
1422     * @param inputlist    the array of <code>Object</code>s.
1423
1424     * @param n    the desired order. For example, 1 indicates largest object; 2 indicates second-largest object, and so on.
1425
1426     */
1427    public static Object findMax(Object[] inputlist, int n, Comparator c) {
1428        if (inputlist.length < n) {
1429            throw new IllegalArgumentException("Input array should have atleast input order numbers.");
1430        }
1431
1432        if (n <= 0) {
1433            throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
1434        }
1435
1436        int numIters;
1437        int i;
1438
1439        int maxIndex;
1440
1441        Object temp;
1442
1443        Object[] order = new Object[n];
1444
1445        int oindex = 0;
1446
1447        int currIter = 0;
1448
1449        Object[] list = new Object[inputlist.length];
1450
1451        System.arraycopy(inputlist, 0, list, 0, list.length);
1452
1453        for (numIters = 0; numIters < list.length; numIters++) {
1454            maxIndex = 0;
1455
1456            for (i = 0; i < (list.length - numIters); i++) {
1457                if (c.compare(list[i], list[maxIndex]) > 0) {
1458                    maxIndex = i;
1459                }
1460            }
1461
1462            temp = list[maxIndex];
1463
1464            list[maxIndex] = list[i - 1];
1465
1466            list[i - 1] = temp;
1467
1468            if ((oindex == 0) || !(c.compare(order[oindex - 1], temp) == 0)) {
1469                order[oindex++] = temp;
1470
1471                currIter++;
1472            }
1473
1474            if (currIter == n) {
1475                break;
1476            }
1477        }
1478
1479        return (order[oindex - 1]);
1480    }
1481
1482    /**
1483
1484     * Returns the object which would be in the n<sup>th</sup> place if the input array were sorted
1485
1486     * in ascending order. This method allows comparison of <code>Object</code>s. The comparison logic
1487
1488     * is provided by the <code>Comparator</code> argument. It follows similar
1489
1490     * semantics as the <code>findOrderedMin(int[], int)</code> method.
1491
1492     *
1493
1494     * @see #findMin(Object[],int,Comparator)
1495
1496     * @see #findOrderedMin(int[],int)
1497
1498     * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
1499
1500     *                     the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
1501
1502     *                     Or, when the order <code>n</code> is less than or equal to 0.
1503
1504     * @param c the <code>Comparator</code> that provides the ordering logic.
1505
1506     * @param inputlist    the array of <code>Object</code>s.
1507
1508     * @param n    the desired position of sorted array. For example, 1 indicates first from top of sorted array; 2 indicates second from top, and so on.
1509
1510     */
1511    public static Object findOrderedMin(Object[] inputlist, int n, Comparator c) {
1512        if (inputlist.length < n) {
1513            throw new IllegalArgumentException("Input array should have atleast input order numbers.");
1514        }
1515
1516        if (n <= 0) {
1517            throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
1518        }
1519
1520        int numIters;
1521        int i;
1522
1523        int minIndex;
1524
1525        Object temp;
1526
1527        Object[] list = new Object[inputlist.length];
1528
1529        System.arraycopy(inputlist, 0, list, 0, list.length);
1530
1531        for (numIters = 0; numIters < n; numIters++) {
1532            minIndex = 0;
1533
1534            for (i = 0; i < (list.length - numIters); i++) {
1535                if (c.compare(list[i], list[minIndex]) < 0) {
1536                    minIndex = i;
1537                }
1538            }
1539
1540            temp = list[i - 1];
1541
1542            list[i - 1] = list[minIndex];
1543
1544            list[minIndex] = temp;
1545        }
1546
1547        return (list[list.length - n]);
1548    }
1549
1550    /**
1551
1552     * Returns the n<sup>th</sup> smallest object in the input array. This method allows comparison of <code>Object</code>s.
1553
1554     * The comparison logic is provided by the <code>Comparator</code> argument. It follows similar
1555
1556     * semantics as the <code>findMin(int[], int)</code> method.
1557
1558     *
1559
1560     * @see #findOrderedMin(Object[],int,Comparator)
1561
1562     * @see #findMin(int[],int)
1563
1564     * @throws IllegalArgumentException Thrown when the number of elements in the input array is less than
1565
1566     *                     the desired order, that is, when <code>n</code> exceeds <code>inputlist.length</code>.
1567
1568     *                     Or, when the order <code>n</code> is less than or equal to 0.
1569
1570     * @param c the <code>Comparator</code> that provides the ordering logic.
1571
1572     * @param inputlist    the array of <code>Objects</code>.
1573
1574     * @param n    the desired order. For example, 1 indicates smallest object; 2 indicates second-smallest object, and so on.
1575
1576     */
1577    public static Object findMin(Object[] inputlist, int n, Comparator c) {
1578        if (inputlist.length < n) {
1579            throw new IllegalArgumentException("Input array should have atleast input order numbers.");
1580        }
1581
1582        if (n <= 0) {
1583            throw new IllegalArgumentException("Order cannot be less than or equal to zero.");
1584        }
1585
1586        int numIters;
1587        int i;
1588
1589        int minIndex;
1590
1591        Object temp;
1592
1593        Object[] order = new Object[n];
1594
1595        int oindex = 0;
1596
1597        int currIter = 0;
1598
1599        Object[] list = new Object[inputlist.length];
1600
1601        System.arraycopy(inputlist, 0, list, 0, list.length);
1602
1603        for (numIters = 0; numIters < list.length; numIters++) {
1604            minIndex = 0;
1605
1606            for (i = 0; i < (list.length - numIters); i++) {
1607                if (c.compare(list[i], list[minIndex]) < 0) {
1608                    minIndex = i;
1609                }
1610            }
1611
1612            temp = list[minIndex];
1613
1614            list[minIndex] = list[i - 1];
1615
1616            list[i - 1] = temp;
1617
1618            if ((oindex == 0) || !(c.compare(order[oindex - 1], temp) == 0)) {
1619                order[oindex++] = temp;
1620
1621                currIter++;
1622            }
1623
1624            if (currIter == n) {
1625                break;
1626            }
1627        }
1628
1629        return (order[oindex - 1]);
1630    }
1631}