/* GPL_HEADER */ package org.greenstone.gatherer.util; /************************************************************************************** * Title: Gatherer * Description: The Gatherer: a tool for gathering and enriching a digital collection. * Company: The University of Waikato * Written: / /01 * Revised: 16/08/02 Improved **************************************************************************************/ import java.awt.*; import java.io.*; import java.util.*; import javax.swing.filechooser.*; import org.greenstone.gatherer.file.FileNode; import org.greenstone.gatherer.msm.Metadata; import org.w3c.dom.*; /** This utility class contains a series of static methods for common array type manipulations including appending, casting and changing between containers. * @author John Thompson * @version 2.3 */ public class ArrayTools { /** Append a Component onto an array of Components. */ static public Component[] add(Component[] a, Component b) { Component[] c = null; if(a != null && b != null) { c = new Component[a.length + 1]; System.arraycopy(a, 0, c, 0, a.length); c[c.length - 1] = b; } else if(a == null && b != null) { c = new Component[1]; c[0] = b; } else if(a != null && b == null) { c = a; } return c; } /** This method efficiently appends a new element onto the end of a element array. * @param a The initial Element[]. * @param b The new Element. * @return An Element[] containing a followed by b. */ static public Element[] add(Element a[], Element b) { Element[] c = null; if(a != null && b != null) { c = new Element[a.length + 1]; System.arraycopy(a, 0, c, 0, a.length); c[c.length - 1] = b; } else if(a == null && b != null) { c = new Element[1]; c[0] = b; } else if(a != null && b == null) { c = a; } return c; } /** This method efficently appends one element array onto the end of another. * @param a The initial Element[]. * @param b The Element[] to append. * @return An Element[] containing a followed by b. */ static public Element[] add(Element a[], Element b[]) { Element[] c = null; if(a != null && b != null) { c = new Element[a.length + b.length]; System.arraycopy(a, 0, c, 0, a.length); System.arraycopy(b, 0, c, a.length, b.length); } else if(a == null && b != null) { c = b; } else if(a != null && b == null) { c = a; } return c; } /** This method efficiently appends a new file onto the end of a file array. * @param a The initial File[]. * @param b The new File. * @return A File[] containing a followed by b. */ static public File[] add(File a[], File b) { File[] c = null; if(a != null && b != null) { c = new File[a.length + 1]; System.arraycopy(a, 0, c, 0, a.length); c[c.length - 1] = b; } else if(a == null && b != null) { c = new File[1]; c[0] = b; } else if(a != null && b == null) { c = a; } return c; } /** This method efficently appends one file array onto the end of another. * @param a The initial File[]. * @param b The File[] to append. * @return A File[] containing a followed by b. */ static public File[] add(File a[], File b[]) { File[] c = null; if(a != null && b != null) { c = new File[a.length + b.length]; System.arraycopy(a, 0, c, 0, a.length); System.arraycopy(b, 0, c, a.length, b.length); } else if(a == null && b != null) { c = b; } else if(a != null && b == null) { c = a; } return c; } /** This method efficiently appends a new FileNode onto the end of a FileNode array. * @param a The initial FileNode[]. * @param b The new FileNode. * @return An FileNode[] containing a followed by b. */ static public FileNode[] add(FileNode a[], FileNode b) { FileNode[] c = null; if(a != null && b != null) { c = new FileNode[a.length + 1]; System.arraycopy(a, 0, c, 0, a.length); c[c.length - 1] = b; } else if(a == null && b != null) { c = new FileNode[1]; c[0] = b; } else if(a != null && b == null) { c = a; } return c; } /** This method efficently appends one FileNode array onto the end of another FileNode array. * @param a The initial FileNode[]. * @param b The FileNode[] to append. * @return An FileNode[] containing a followed by b. */ static final public FileNode[] add(FileNode a[], FileNode b[]) { FileNode[] c = null; if(a != null && b != null) { c = new FileNode[a.length + b.length]; System.arraycopy(a, 0, c, 0, a.length); System.arraycopy(b, 0, c, a.length, b.length); } else if(a == null && b != null) { c = b; } else if(a != null && b == null) { c = a; } return c; } /** Determine if a certain FileNode is present in an array of FileNodes. * @param array The FileNode[]. * @param a The FileNode we are searching for. * @return true if the FileNode is in the array, false otherwise. */ static final public boolean contains(FileNode array[], FileNode a) { for(int i = 0; i < array.length; i++) { if(array[i].equals(a)) { return true; } } return false; } /** Remove the first element from an array, and return the remaining 'tail'. * @param a A FileNode[]. * @return The same FileNode[] sans its head element. */ static final public FileNode[] tail(FileNode a[]) { if(a.length == 1) { return null; } FileNode b[] = new FileNode[a.length - 1]; System.arraycopy(a, 1, b, 0, b.length); return b; } /** Append a Metadata object onto an array of Metadata objects. */ static public Metadata[] add(Metadata[] a, Metadata b) { Metadata[] c = null; if(a != null && b != null) { c = new Metadata[a.length + 1]; System.arraycopy(a, 0, c, 0, a.length); c[c.length - 1] = b; } else if(a == null && b != null) { c = new Metadata[1]; c[0] = b; } else if(a != null && b == null) { c = a; } return c; } /** Append a Metadata object array onto an array of Metadata objects. */ static public Metadata[] add(Metadata[] a, Metadata[] b) { Metadata[] c = null; if(a != null && b != null) { c = new Metadata[a.length + b.length]; System.arraycopy(a, 0, c, 0, a.length); System.arraycopy(b, 0, c, a.length, b.length); } else if(a == null && b != null) { c = b; } else if(a != null && b == null) { c = a; } return c; } /** Remove the Metadata object at the given index form the specified Metadata object array. */ static public Metadata[] remove(Metadata[] a, int index) { Metadata[] c = null; if(a != null) { c = new Metadata[a.length - 1]; System.arraycopy(a, 0, c, 0, index); System.arraycopy(a, index + 1, c, index, c.length - index); } return c; } /** This method efficiently appends a new node onto the end of a node array. * @param a The initial Node[]. * @param b The new Node. * @return A Node[] containing a followed by b. */ static public Node[] add(Node a[], Node b) { Node[] c = null; if(a != null && b != null) { c = new Node[a.length + 1]; System.arraycopy(a, 0, c, 0, a.length); c[c.length - 1] = b; } else if(a == null && b != null) { c = new Node[1]; c[0] = b; } else if(a != null && b == null) { c = a; } return c; } /** This method efficently appends one node array onto the end of another. * @param a The initial Node[]. * @param b The Node[] to append. * @return A Node[] containing a followed by b. */ static public Node[] add(Node a[], Node b[]) { Node[] c = null; if(a != null && b != null) { c = new Node[a.length + b.length]; System.arraycopy(a, 0, c, 0, a.length); System.arraycopy(b, 0, c, a.length, b.length); } else if(a == null && b != null) { c = b; } else if(a != null && b == null) { c = a; } return c; } /** This method efficiently appends a new string onto the end of a string array. * @param a The initial String[]. * @param b The new String. * @return A String[] containing a followed by b. */ static public String[] add(String a[], String b) { String[] c = null; if(a != null && b != null) { c = new String[a.length + 1]; System.arraycopy(a, 0, c, 0, a.length); c[c.length - 1] = b; } else if(a == null && b != null) { c = new String[1]; c[0] = b; } else if(a != null && b == null) { c = a; } return c; } /** This method efficently appends one string array onto the end of another. * @param a The initial String[]. * @param b The String[] to append. * @return A String[] containing a followed by b. */ static public String[] add(String a[], String b[]) { String[] c = null; if(a != null && b != null) { c = new String[a.length + b.length]; System.arraycopy(a, 0, c, 0, a.length); System.arraycopy(b, 0, c, a.length, b.length); } else if(a == null && b != null) { c = b; } else if(a != null && b == null) { c = a; } return c; } /** This method takes an array list and creates a string array. * @param a An ArrayList containing hopefully String or else this will fail. * @return A String[] or null if the array could not be created. */ static public String[] arrayListToStringArray(ArrayList a) { String array[] = new String[a.size()]; for(int i = 0; i < array.length; i++) { array[i] = (String)a.get(i); } return array; } static public File[] filter(File[] files, String pattern, boolean exclude) { int write_ptr = 0; ///ystem.err.println("Filtering by '" + pattern + "', Exclude? " + exclude + " :"); for(int read_ptr = 0; read_ptr < files.length; read_ptr++) { File current = files[read_ptr]; files[write_ptr] = current; ///ystem.err.print("Testing " + current.getName() + " -> "); // Determine whether we move the write pointer or not. if(current.getName().toLowerCase().matches(pattern)) { if(!exclude) { ///ystem.err.println("Match, Exclude."); write_ptr++; } else { ///ystem.err.println("Match, Include."); } } else { // You can't exclude folders with an inclusion filter! if(exclude || current.isDirectory()) { ///ystem.err.println("Nonmatch, Exclude."); write_ptr++; } else { ///ystem.err.println("Nonmatch, Include."); } } } File[] result = new File[write_ptr]; System.arraycopy(files, 0, result, 0, result.length); pattern = null; files = null; return result; } /** Method to convert a list of nodes from the DOM model into a node array. This is quite useful as using a NodeList is problematic if you wish to traverse the tree while editing. Because they are 'live' representations of the model you are editing, it is easy to drop out of for loops early or run off the ends of arrays. * @param node_list A NodeList representing the Nodes we want to iterate through. * @return A brand new Node[] with the first Node in the NodeList at the head. * @see org.w3c.dom.Node * @see org.w3c.dom.NodeList */ static public Node[] nodeListToNodeArray(NodeList node_list) { Node nodes[] = null; for(int i = 0; i < node_list.getLength(); i++) { nodes = add(nodes, node_list.item(i)); } return nodes; } /** Transforms an Object array into a single string of the form '[o1,o2,...,on]'. * @param objects An Object[]. Note that the objects in this array must support toString() reasonably. * @return A String representing the given array. */ static public String objectArrayToString(Object objects[]) { StringBuffer result = new StringBuffer("["); for(int i = 0; i < objects.length; i++) { result.append(objects[i].toString()); if(i < objects.length - 1) { result.append(","); } } result.append("]"); return result.toString(); } /** Remove the file at the given index from the array of files. */ static public File[] remove(File[] files, int index) { if(files.length == 1) { return new File[0]; } File[] temp = new File[files.length - 1]; if(index > 0) { System.arraycopy(files, 0, temp, 0, index); } if(index < files.length - 1) { System.arraycopy(files, index + 1, temp, index, files.length - 1 - index); } return temp; } /** Sorts an array of files. */ static public void sort(File[] files) { sort(files, false); } /** Sorts an array of files. Can also to instructed to list directories first. Case insensitive. * @param files The File[] to be sorted. * @param directories_first true if you want to directories to be listed first. */ static public void sort(File[] files, boolean directories_first) { if(files != null && files.length > 1) { FileComparator comparator = new FileComparator(directories_first); Arrays.sort(files, comparator); } } /** Comparator used to order files. */ static private class FileComparator implements Comparator { private boolean directories_first = false; public FileComparator(boolean directories_first) { this.directories_first = directories_first; } /** Compare two files in terms of ordering of their paths. * @param o1 The Object that represents the first file. * @param o2 The other Object, also a file. * @return An int which is <1, 0 or >1 if o1 is < o2, = o2 or > o2 respectively. */ public int compare(Object o1, Object o2) { int result = 0; File f1 = (File) o1; String n1 = f1.getName().toLowerCase(); File f2 = (File) o2; String n2 = f2.getName().toLowerCase(); // Special checks for system roots as these include removable media drives and thus we should never attempt to call isDirectory until the user explicitly attempts to map drive. boolean f1_system_root = FileSystemView.getFileSystemView().isFileSystemRoot(f1); boolean f2_system_root = FileSystemView.getFileSystemView().isFileSystemRoot(f2); if((f1_system_root && f2_system_root) || (!f2_system_root && f1_system_root && f2.isDirectory()) || (!f1_system_root && f1.isDirectory() && f2_system_root) || (f1.isDirectory() && f2.isDirectory()) || (f1.isFile() && f2.isFile())) { result = n1.compareTo(n2); } else if(f1_system_root || f1.isDirectory()) { result = -1; } else { result = 1; } return result; } /** Compare two files for equality, in terms of their file paths. * @param object The Object representing the file we are about to compare ourselves to. * @return true if we equal the given file, false otherwise. */ public boolean equals(Object obj) { return (compare(this, obj) == 0); } } }