Merge branch 'master' of https://source.jalview.org/git/jalviewjs.git
[jalviewjs.git] / src / javajs / util / AU.java
1 /* $RCSfile$
2  * $Author: egonw $
3  * $Date: 2005-11-10 09:52:44 -0600 (Thu, 10 Nov 2005) $
4  * $Revision: 4255 $
5  *
6  * Copyright (C) 2003-2005  The Jmol Development Team
7  *
8  * Contact: jmol-developers@lists.sf.net
9  *
10  *  This library is free software; you can redistribute it and/or
11  *  modify it under the terms of the GNU Lesser General Public
12  *  License as published by the Free Software Foundation; either
13  *  version 2.1 of the License, or (at your option) any later version.
14  *
15  *  This library is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  *  Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with this library; if not, write to the Free Software
22  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24 package javajs.util;
25
26 // 4/23/15 BH getComponentType fix
27
28 import java.lang.reflect.Array;
29
30 import java.util.Arrays;
31 import java.util.Hashtable;
32 import java.util.Map;
33
34
35 final public class AU {
36
37   /**
38    * Very important that this not be used with Int32Array or Float32Array,
39    * because it is not initialized to all zeros in MSIE 9.
40    * 
41    * @param array
42    * @param minimumLength
43    * @return array
44    */
45   public static Object ensureLength(Object array, int minimumLength) {
46     if (array != null && getLength(array) >= minimumLength)
47       return array;
48     return arrayCopyObject(array, minimumLength);
49   }
50
51   public static String[] ensureLengthS(String[] array, int minimumLength) {
52     if (array != null && array.length >= minimumLength)
53       return array;
54     return arrayCopyS(array, minimumLength);
55   }
56
57   public static float[] ensureLengthA(float[] array, int minimumLength) {
58     if (array != null && array.length >= minimumLength)
59       return array;
60     return arrayCopyF(array, minimumLength);
61   }
62
63   public static int[] ensureLengthI(int[] array, int minimumLength) {
64     if (array != null && array.length >= minimumLength)
65       return array;
66     return arrayCopyI(array, minimumLength);
67   }
68
69   public static short[] ensureLengthShort(short[] array, int minimumLength) {
70     if (array != null && array.length >= minimumLength)
71       return array;
72     return arrayCopyShort(array, minimumLength);
73   }
74
75   public static byte[] ensureLengthByte(byte[] array, int minimumLength) {
76     if (array != null && array.length >= minimumLength)
77       return array;
78     return arrayCopyByte(array, minimumLength);
79   }
80
81   /**
82    * Very important that this not be used with Int32Array or Float32Array,
83    * because it is not initialized to all zeros in MSIE 9.
84    * 
85    * @param array
86    * @return array
87    */
88   public static Object doubleLength(Object array) {
89     return arrayCopyObject(array, (array == null ? 16 : 2 * getLength(array)));
90   }
91
92   public static String[] doubleLengthS(String[] array) {
93     return arrayCopyS(array, (array == null ? 16 : 2 * array.length));
94   }
95
96   public static float[] doubleLengthF(float[] array) {
97     return arrayCopyF(array, (array == null ? 16 : 2 * array.length));
98   }
99
100   public static int[] doubleLengthI(int[] array) {
101     return arrayCopyI(array, (array == null ? 16 : 2 * array.length));
102   }
103
104   public static short[] doubleLengthShort(short[] array) {
105     return arrayCopyShort(array, (array == null ? 16 : 2 * array.length));
106   }
107
108   public static byte[] doubleLengthByte(byte[] array) {
109     return arrayCopyByte(array, (array == null ? 16 : 2 * array.length));
110   }
111
112   public static boolean[] doubleLengthBool(boolean[] array) {
113     return arrayCopyBool(array, (array == null ? 16 : 2 * array.length));
114   }
115
116   public static Object deleteElements(Object array, int firstElement,
117                                      int nElements) {
118     if (nElements == 0 || array == null)
119       return array;
120     int oldLength = getLength(array);
121     if (firstElement >= oldLength)
122       return array;
123     int n = oldLength - (firstElement + nElements);
124     if (n < 0)
125       n = 0;
126     Object t = newInstanceO(array, firstElement + n);
127     if (firstElement > 0)
128       System.arraycopy(array, 0, t, 0, firstElement);
129     if (n > 0)
130       System.arraycopy(array, firstElement + nElements, t, firstElement, n);
131     return t;
132   }
133
134   /**
135    * note -- cannot copy if array is null!
136    * 
137    * @param array
138    * @param newLength
139    * @return array
140    */
141   public static Object arrayCopyObject(Object array, int newLength) {
142     //System.out.println("ArrayUtil.copy " + newLength + " " + array + "  ");
143     if (array == null) {
144       return null; // We can't allocate since we don't know the type of array
145     }
146     int oldLength = getLength(array);
147     if (newLength == oldLength)
148       return array;
149     Object t = newInstanceO(array, newLength);
150     System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength
151         : newLength);
152     return t;
153
154   }
155
156   /**
157    * Very important that this not be used with Int32Array or Float32Array,
158    * because those need to be initialized to all zeros in MSIE 9, and
159    * MSIE 9 cannot distinguish Int32Array or Float32Array from Array.
160    * 
161    * @param array
162    * @param n
163    * @return array
164    */
165   private static Object newInstanceO(Object array, int n) {
166     /**
167      * @j2sNative
168      * 
169      * if (!array.getClass().getComponentType)
170      *   return new Array(n);
171      * 
172      */
173     {
174       return Array.newInstance(array.getClass().getComponentType(), n);
175     }
176   }
177
178   public static int getLength(Object array) {
179     /**
180      * @j2sNative
181      * 
182      *  return array.length
183      *   
184      */
185     {
186       return Array.getLength(array);
187     }
188   }
189
190   public static String[] arrayCopyS(String[] array, int newLength) {
191     if (newLength < 0)
192       newLength = array.length;
193     String[] t = new String[newLength];
194     if (array != null) {
195       int oldLength = array.length;
196       System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength
197           : newLength);
198     }
199     return t;
200   }
201
202   public static int[][] arrayCopyII(int[][] array, int newLength) {
203     int[][] t = newInt2(newLength);
204     if (array != null) {
205       int oldLength = array.length;
206       System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength
207           : newLength);
208     }
209     return t;
210   }
211
212   public static T3[] arrayCopyPt(T3[] array, int newLength) {
213     if (newLength < 0)
214       newLength = array.length;
215     T3[] t = new T3[newLength];
216     if (array != null) {
217       int oldLength = array.length;
218       System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength
219           : newLength);
220     }
221     return t;
222   }
223
224   public static float[] arrayCopyF(float[] array, int newLength) {
225     if (newLength < 0)
226       newLength = array.length;
227     float[] t = new float[newLength];
228     if (array != null) {
229       int oldLength = array.length;
230       System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength
231           : newLength);
232     }
233     return t;
234   }
235
236   public static int[] arrayCopyI(int[] array, int newLength) {
237     if (newLength < 0)
238       newLength = array.length;
239     int[] t = new int[newLength];
240     if (array != null) {
241       int oldLength = array.length;
242       System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength
243           : newLength);
244     }
245     return t;
246   }
247
248   /**
249    * a specialized method that allows copying from a starting point either
250    * to the end or to the middle (color schemes, especially)
251    * @param array
252    * @param i0
253    * @param n
254    * @return array or null
255    */
256   public static int[] arrayCopyRangeI(int[] array, int i0, int n) {
257     if (array == null)
258       return null;
259     int oldLength = array.length;
260     if (n == -1) n = oldLength;
261     if (n == -2) n = oldLength / 2;
262     n = n - i0;
263     int[] t = new int[n];
264     System.arraycopy(array, i0, t, 0, n);
265     return t;
266   }
267
268   public static int[] arrayCopyRangeRevI(int[] array, int i0, int n) {
269     if (array == null)
270       return null;
271     int[] t = arrayCopyRangeI(array, i0, n);
272     if (n < 0)
273       n = array.length;
274     for (int i = n / 2; --i >= 0;)
275       swapInt(t, i, n - 1 - i);
276     return t;
277   }
278
279   public static short[] arrayCopyShort(short[] array, int newLength) {
280     if (newLength < 0)
281       newLength = array.length;
282     short[] t = new short[newLength];
283     if (array != null) {
284       int oldLength = array.length;
285       System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength
286           : newLength);
287     }
288     return t;
289   }
290
291   public static byte[] arrayCopyByte(byte[] array, int newLength) {
292     if (newLength < 0)
293       newLength = array.length;
294     byte[] t = new byte[newLength];
295     if (array != null) {
296       int oldLength = array.length;
297       System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength
298           : newLength);
299     }
300     return t;
301   }
302
303   public static boolean[] arrayCopyBool(boolean[] array, int newLength) {
304     if (newLength < 0)
305       newLength = array.length;
306     boolean[] t = new boolean[newLength];
307     if (array != null) {
308       int oldLength = array.length;
309       System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength
310           : newLength);
311     }
312     return t;
313   }
314
315   public static void swapInt(int[] array, int indexA, int indexB) {
316     int t = array[indexA];
317     array[indexA] = array[indexB];
318     array[indexB] = t;
319   }
320
321   /*
322   public static void swap(short[] array, int indexA, int indexB) {
323     short t = array[indexA];
324     array[indexA] = array[indexB];
325     array[indexB] = t;
326   }
327
328   public static void swap(float[] array, int indexA, int indexB) {
329     float t = array[indexA];
330     array[indexA] = array[indexB];
331     array[indexB] = t;
332   }
333   */
334   
335   public static String dumpArray(String msg, float[][] A, int x1, int x2, int y1, int y2) {
336     String s = "dumpArray: " + msg + "\n";
337     for (int x = x1; x <= x2; x++)
338       s += "\t*" + x + "*";
339     for (int y = y2; y >= y1; y--) {
340       s += "\n*" + y + "*";
341       for (int x = x1; x <= x2; x++)
342         s += "\t" + (x < A.length && y < A[x].length ? A[x][y] : Float.NaN);
343     }
344     return s;
345   }
346
347   public static String dumpIntArray(int[] A, int n) {
348     String str = "";
349     for (int i = 0; i < n; i++)
350       str += " " + A[i];
351     return str;
352   }
353
354   public static String sortedItem(Lst<String> v, int n) {
355     if (v.size() == 0)
356       return null;
357     if (v.size() == 1)
358       return v.get(0);
359     String[] keys = v.toArray(new String[v.size()]);
360     Arrays.sort(keys);
361     return keys[n % keys.length];
362   }
363
364   /**
365    * Helper method for creating a List<Tx>[] without warnings.
366    * 
367    * @param <type> Type of objects in the list.
368    * @param size Array size.
369    * @return Array of List<type>
370    */
371   @SuppressWarnings("unchecked")
372   public static <type> Lst<type>[] createArrayOfArrayList(int size) {
373     return new Lst[size];
374   }
375
376   /**
377    * Helper method for creating a Map<K, V>[] without warnings.
378    * 
379    * @param <K> Type of object for the keys in the map.
380    * @param <V> Type of object for the values in the map.
381    * @param size Array size.
382    * @return Array of Map<K, V>
383    */
384   @SuppressWarnings("unchecked")
385   public static <K, V> Map<K, V>[] createArrayOfHashtable(int size) {
386     return new Hashtable[size];
387   }
388
389   public static void swap(Object[] o, int i, int j) {
390     Object oi = o[i];
391     o[i] = o[j];
392     o[j] = oi;
393   }
394
395   public static float[][] newFloat2(int n) {
396     /**
397      * @j2sNative
398      * 
399      * return Clazz.newArray(n, null);
400      * 
401      */
402     {
403     return new float[n][];
404     }
405   }
406
407   public static int[][] newInt2(int n) {
408     /**
409      * @j2sNative
410      * 
411      * return Clazz.newArray(n, null);
412      * 
413      */
414     {
415     return new int[n][];
416     }
417   }
418
419   public static int[][][] newInt3(int nx, int ny) {
420     /**
421      * @j2sNative
422      * 
423      * return Clazz.newArray(nx, null);
424      * 
425      */
426     {
427       return (ny < 0 ? new int[nx][][] : new int[nx][ny][]);
428     }
429   }
430
431   public static float[][][] newFloat3(int nx, int ny) {
432     /**
433      * @j2sNative
434      * 
435      * return Clazz.newArray(nx, null);
436      * 
437      */
438     {
439       return (ny < 0 ? new float[nx][][] : new float[nx][ny][]);
440     }
441   }
442
443   public static int[][][][] newInt4(int n) {
444     /**
445      * @j2sNative
446      * 
447      * return Clazz.newArray(n, null);
448      * 
449      */
450     {
451     return new int[n][][][];
452     }
453   }
454
455   public static short[][] newShort2(int n) {
456     /**
457      * @j2sNative
458      * 
459      * return Clazz.newArray(n, null);
460      * 
461      */
462     {
463     return new short[n][];
464     }
465   }
466
467   public static byte[][] newByte2(int n) {
468     /**
469      * @j2sNative
470      * 
471      * return Clazz.newArray(n, null);
472      * 
473      */
474     {
475     return new byte[n][];
476     }
477   }
478
479   public static double[][] newDouble2(int n) {
480     /**
481      * @j2sNative
482      * 
483      * return Clazz.newArray(n, null);
484      * 
485      */
486     {
487     return new double[n][];
488     }
489   }
490
491   /**
492    * remove all keys from a map that start with given root
493    * @param map
494    * @param root
495    * @return number removed
496    */
497   public static int removeMapKeys(Map<String, ?> map, String root) {
498     Lst<String> list = new Lst<String>();
499     for (String key: map.keySet())
500       if (key.startsWith(root))
501         list.addLast(key);
502     for (int i = list.size(); --i >= 0;)
503       map.remove(list.get(i));
504     return list.size();
505   }
506
507         public static boolean isAS(Object x) {
508           /**
509            * 
510            * look also for array with first null element
511            * so untypable -- just call it a String[]
512            * (group3Lists, created in ModelLoader)
513            * 
514            * @j2sNative
515            *  return Clazz.isAS(x);
516            */
517           {
518           return x instanceof String[];
519           }
520         }
521
522         public static boolean isASS(Object x) {
523           /**
524            * @j2sNative
525            *  return Clazz.isASS(x);
526            */
527           {
528           return x instanceof String[][];
529           }
530         }
531
532         public static boolean isAP(Object x) {
533           /**
534            * @j2sNative
535            *  return Clazz.isAP(x);
536            */
537           {
538           return x instanceof T3[];
539           }
540         }
541
542         public static boolean isAF(Object x) {
543           /**
544            * @j2sNative
545            *  return Clazz.isAF(x);
546            */
547           {
548           return x instanceof float[];
549           }
550         }
551
552         public static boolean isAFloat(Object x) {
553           /**
554            * @j2sNative
555            *  return Clazz.isAFloat(x);
556            */
557           {
558           return x instanceof Float[];
559           }
560         }
561
562         public static boolean isAD(Object x) {
563           /**
564            * @j2sNative
565            *  return Clazz.isAF(x);
566            */
567           {
568           return x instanceof double[];
569           }
570         }
571
572         public static boolean isADD(Object x) {
573           /**
574            * @j2sNative
575            *  return Clazz.isAFF(x);
576            */
577           {
578           return x instanceof double[][];
579           }
580         }
581
582         public static boolean isAB(Object x) {
583           /**
584            * @j2sNative
585            *  return Clazz.isAI(x);
586            */
587           {
588           return x instanceof byte[];
589           }
590         }
591
592         public static boolean isAI(Object x) {
593           /**
594            * @j2sNative
595            *  return Clazz.isAI(x);
596            */
597           {
598           return x instanceof int[];
599           }
600         }
601
602         public static boolean isAII(Object x) {
603           /**
604            * @j2sNative
605            *  return Clazz.isAII(x);
606            */
607           {
608           return (x instanceof int[][]);
609           }
610         }
611
612         public static boolean isAFF(Object x) {
613           /**
614            * @j2sNative
615            *  return Clazz.isAFF(x);
616            */
617           {
618           return x instanceof float[][];
619           }
620         }
621
622         public static boolean isAFFF(Object x) {
623           /**
624            * @j2sNative
625            *  return Clazz.isAFFF(x);
626            */
627           {
628           return x instanceof float[][][];
629           }
630         }
631         
632         /**
633          * Ensure that we have signed and not unsigned bytes
634          * coming out of any process, but particularly out of 
635          * file reading. 
636          * 
637          * @param b
638          */
639         public static void ensureSignedBytes(byte[] b) {
640           /**
641            * @j2sNative
642            * 
643            * for (var i = b.length; --i >= 0;) {
644            *   var j = b[i] & 0xFF;
645            *   if (j >= 0x80) j -= 0x100;
646            *   b[i] = j;
647            * }
648            * 
649            */
650           {
651           }
652         }
653
654
655 }