merge from 2_4_Release branch
[jalview.git] / src / com / stevesoft / pat / FileRegex.java
index 37729eb..342d41c 100755 (executable)
-//\r
-// This software is now distributed according to\r
-// the Lesser Gnu Public License.  Please see\r
-// http://www.gnu.org/copyleft/lesser.txt for\r
-// the details.\r
-//    -- Happy Computing!\r
-//\r
-package com.stevesoft.pat;\r
-\r
-import java.io.*;\r
-import java.util.*;\r
-\r
-/** This class is a different form of Regex designed to work more\r
- like the file matching utility of a Unix shell.  It is implemented\r
- by some simple string transformations:\r
- <center>\r
- <table border=1>\r
- <tr> <td> FileRegex </td> <td> Regex </td>\r
- <tr> <td> * </td><td> .* </td>\r
- <tr> <td> . </td><td> \. </td>\r
- <tr> <td> { </td><td> (?: </td>\r
- <tr> <td> {?! </td><td> (?! </td>\r
- <tr> <td> {?= </td><td> (?= </td>\r
- <tr> <td> {?? </td><td> (?? </td>\r
- <tr> <td> } </td><td> ) </td>\r
- <tr> <td> ? </td><td> . </td>\r
- <tr> <td> {,} </td><td> (|) </td>\r
- </table>\r
- </center>\r
- Note that a FileRegex pattern always ends with the Regex\r
- pattern element "$".  If you like to experiment, try making\r
- FileRegex's and then printing them out.  The toString() method\r
- does a decompile of the pattern to a standard Regex.  Here are\r
- some more complete examples:\r
- <center>\r
- <table border=3>\r
- <tr> <td> FileRegex </td><td> Regex </td>\r
- <tr> <td>*.java </td><td> .*\.java$ </td>\r
- <tr> <td>*.{java,html} </td><td> .*\.(java|html)$ </td>\r
- <tr> <td> foo.[chC] </td><td> foo.[chC]$ </td>\r
- </table>\r
- </center>\r
- */\r
-public class FileRegex\r
-    extends Regex\r
-{\r
-  /** Build an unitialized FileRegex. */\r
-  public FileRegex()\r
-  {\r
-    dirflag = EITHER;\r
-  }\r
-\r
-  /** Build a FileRegex form String s. */\r
-  public FileRegex(String s)\r
-  {\r
-    super(s);\r
-    dirflag = EITHER;\r
-  }\r
-\r
-  /** Compile a new pattern.\r
-      Throws @exception com.stevesoft.pat.RegSyntax for\r
-      nonsensical patterns like "[9-0]+" just as Regex does.\r
-      @see com.stevesoft.pat#compile(java.lang.String)\r
-   */\r
-  public void compile(String s)\r
-      throws RegSyntax\r
-  {\r
-    String npat = toFileRegex(s);\r
-    super.compile(npat);\r
-    if (File.separatorChar == '\\') // MS-DOS\r
-    {\r
-      ignoreCase = true;\r
-    }\r
-  }\r
-\r
-  /** This is the method required by FileNameFilter.\r
-     To get a listing of files in the current directory\r
-       ending in .java, do this:\r
-      <pre>\r
-      File dot = new File(".");\r
-      FileRegex java_files = new FileRegex("*.java");\r
-      String[] file_list = dot.list(java_files);\r
-      </pre>\r
-   */\r
-  public boolean accept(File dir, String s)\r
-  {\r
-    if (dirflag != EITHER)\r
-    {\r
-      File f = new File(s);\r
-      if (f.isDirectory() && dirflag == NONDIR)\r
-      {\r
-        return false;\r
-      }\r
-      if (!f.isDirectory() && dirflag == DIR)\r
-      {\r
-        return false;\r
-      }\r
-    }\r
-    return matchAt(s, 0);\r
-  }\r
-\r
-  int dirflag = 0;\r
-  final static int EITHER = 0, DIR = 1, NONDIR = 2;\r
-\r
-  /** Provides an alternative to File.list -- this\r
-      separates its argument according to File.pathSeparator.\r
-      To each path, it splits off a directory -- all characters\r
-      up to and including the first instance of File.separator --\r
-      and a file pattern -- the part that comes after the directory.\r
-      It then produces a list of all the pattern matches on all\r
-      the paths.  Thus "*.java:../*.java" would produce a list of\r
-       all the java files in this directory and in the ".." directory\r
-       on a Unix machine.  "*.java;..\\*.java" would do the same thing\r
-       on a Dos machine. */\r
-   public static String[] list(String f)\r
-   {\r
-     return list(f, EITHER);\r
-   }\r
-\r
-  static String[] list(String f, int df)\r
-  {\r
-    //return list_(f,new FileRegex());\r
-    StringTokenizer st = new StringTokenizer(f, File.pathSeparator);\r
-    Vector v = new Vector();\r
-    while (st.hasMoreTokens())\r
-    {\r
-      String path = st.nextToken();\r
-      list1(path, v, df, true);\r
-    }\r
-    String[] sa = new String[v.size()];\r
-    v.copyInto(sa);\r
-    return sa;\r
-  }\r
-\r
-  final static Regex root = new Regex(File.separatorChar == '/' ?\r
-                                      "/$" : "(?:.:|)\\\\$");\r
-  static void list1(String path, Vector v, int df, boolean rec)\r
-  {\r
-    // if path looks like a/b/c/ or d:\ then add .\r
-    if (root.matchAt(path, 0))\r
-    {\r
-      v.addElement(path + ".");\r
-      return;\r
-    }\r
-    File f = new File(path);\r
-    if (f.getParent() != null && rec)\r
-    {\r
-      Vector v2 = new Vector();\r
-      list1(f.getParent(), v2, DIR, true);\r
-      for (int i = 0; i < v2.size(); i++)\r
-      {\r
-        String path2 = ( (String) v2.elementAt(i)) +\r
-            File.separator + f.getName();\r
-        list1(path2, v, df, false);\r
-      }\r
-    }\r
-    else\r
-    {\r
-      File base = new File(path);\r
-\r
-      String dir_s = base.getParent();\r
-      if (dir_s == null)\r
-      {\r
-        dir_s = ".";\r
-      }\r
-      File dir = new File(dir_s);\r
-\r
-      FileRegex fr = new FileRegex(base.getName());\r
-      if (fr.isLiteral())\r
-      {\r
-        v.addElement(dir_s + File.separator + base.getName());\r
-        return;\r
-      }\r
-      fr.dirflag = df;\r
-      String[] sa = dir.list(fr);\r
-      if (sa == null)\r
-      {\r
-        return;\r
-      }\r
-      for (int i = 0; i < sa.length; i++)\r
-      {\r
-        v.addElement(dir_s + File.separator + sa[i]);\r
-      }\r
-    }\r
-  }\r
-\r
-  /** This method takes a file regular expression, and translates it\r
-          into the type of pattern used by a normal Regex. */\r
-  public static String toFileRegex(String s)\r
-  {\r
-    StrPos sp = new StrPos(s, 0);\r
-    StringBuffer sb = new StringBuffer();\r
-    if (sp.incMatch("{?e="))\r
-    {\r
-      char e = sp.thisChar();\r
-      sp.inc();\r
-      if (sp.incMatch("}"))\r
-      {\r
-        sb.append("(?e=" + e + ")^");\r
-      }\r
-      else\r
-      {\r
-        sb.append("^(?e=");\r
-      }\r
-      sp.esc = e;\r
-    }\r
-    int ParenLvl = 0;\r
-    while (!sp.eos())\r
-    {\r
-      if (File.separatorChar == '\\')\r
-      {\r
-        if (sp.escaped())\r
-        {\r
-          sb.append("\\\\");\r
-        }\r
-        sp.dontMatch = false;\r
-      }\r
-      if (sp.incMatch("?"))\r
-      {\r
-        sb.append(".");\r
-      }\r
-      else if (sp.incMatch("."))\r
-      {\r
-        sb.append(sp.esc);\r
-        sb.append('.');\r
-      }\r
-      else if (sp.incMatch("{??"))\r
-      {\r
-        sb.append("(??");\r
-        ParenLvl++;\r
-        // allow negative lookahead to work\r
-      }\r
-      else if (sp.incMatch("{?!"))\r
-      {\r
-        sb.append("(?!");\r
-        ParenLvl++;\r
-        // allow positive lookahead to work\r
-      }\r
-      else if (sp.incMatch("{?="))\r
-      {\r
-        sb.append("(?=");\r
-        ParenLvl++;\r
-      }\r
-      else if (sp.incMatch("{"))\r
-      {\r
-        sb.append("(?:");\r
-        ParenLvl++;\r
-      }\r
-      else if (sp.incMatch("}"))\r
-      {\r
-        sb.append(')');\r
-        ParenLvl--;\r
-      }\r
-      else if (ParenLvl != 0 && sp.incMatch(","))\r
-      {\r
-        sb.append('|');\r
-      }\r
-      else if (sp.incMatch("*"))\r
-      {\r
-        sb.append(".*");\r
-      }\r
-      else\r
-      {\r
-        sb.append(sp.thisChar());\r
-        sp.inc();\r
-      }\r
-    }\r
-    sb.append("$");\r
-    return sb.toString();\r
-  }\r
-\r
-  public boolean isLiteral()\r
-  {\r
-    Pattern x = thePattern;\r
-    while (x != null && ! (x instanceof End))\r
-    {\r
-      if (x instanceof oneChar)\r
-      {\r
-        ;\r
-      }\r
-      else if (x instanceof Skipped)\r
-      {\r
-        ;\r
-      }\r
-      else\r
-      {\r
-        return false;\r
-      }\r
-      x = x.next;\r
-    }\r
-    return true;\r
-  }\r
-}\r
+//
+// This software is now distributed according to
+// the Lesser Gnu Public License.  Please see
+// http://www.gnu.org/copyleft/lesser.txt for
+// the details.
+//    -- Happy Computing!
+//
+package com.stevesoft.pat;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * This class is a different form of Regex designed to work more like the file
+ * matching utility of a Unix shell. It is implemented by some simple string
+ * transformations: <center> <table border=1>
+ * <tr>
+ * <td> FileRegex </td>
+ * <td> Regex </td>
+ * <tr>
+ * <td> * </td>
+ * <td> .* </td>
+ * <tr>
+ * <td> . </td>
+ * <td> \. </td>
+ * <tr>
+ * <td> { </td>
+ * <td> (?: </td>
+ * <tr>
+ * <td> {?! </td>
+ * <td> (?! </td>
+ * <tr>
+ * <td> {?= </td>
+ * <td> (?= </td>
+ * <tr>
+ * <td> {?? </td>
+ * <td> (?? </td>
+ * <tr>
+ * <td> } </td>
+ * <td> ) </td>
+ * <tr>
+ * <td> ? </td>
+ * <td> . </td>
+ * <tr>
+ * <td> {,} </td>
+ * <td> (|) </td>
+ * </table> </center> Note that a FileRegex pattern always ends with the Regex
+ * pattern element "$". If you like to experiment, try making FileRegex's and
+ * then printing them out. The toString() method does a decompile of the pattern
+ * to a standard Regex. Here are some more complete examples: <center> <table
+ * border=3>
+ * <tr>
+ * <td> FileRegex </td>
+ * <td> Regex </td>
+ * <tr>
+ * <td>*.java </td>
+ * <td> .*\.java$ </td>
+ * <tr>
+ * <td>*.{java,html} </td>
+ * <td> .*\.(java|html)$ </td>
+ * <tr>
+ * <td> foo.[chC] </td>
+ * <td> foo.[chC]$ </td>
+ * </table> </center>
+ */
+public class FileRegex extends Regex
+{
+  /** Build an unitialized FileRegex. */
+  public FileRegex()
+  {
+    dirflag = EITHER;
+  }
+
+  /** Build a FileRegex form String s. */
+  public FileRegex(String s)
+  {
+    super(s);
+    dirflag = EITHER;
+  }
+
+  /**
+   * Compile a new pattern. Throws
+   * 
+   * @exception com.stevesoft.pat.RegSyntax
+   *                    for nonsensical patterns like "[9-0]+" just as Regex
+   *                    does.
+   * @see com.stevesoft.pat#compile(java.lang.String)
+   */
+  public void compile(String s) throws RegSyntax
+  {
+    String npat = toFileRegex(s);
+    super.compile(npat);
+    if (File.separatorChar == '\\') // MS-DOS
+    {
+      ignoreCase = true;
+    }
+  }
+
+  /**
+   * This is the method required by FileNameFilter. To get a listing of files in
+   * the current directory ending in .java, do this:
+   * 
+   * <pre>
+   * File dot = new File(&quot;.&quot;);
+   * 
+   * FileRegex java_files = new FileRegex(&quot;*.java&quot;);
+   * 
+   * String[] file_list = dot.list(java_files);
+   * </pre>
+   */
+  public boolean accept(File dir, String s)
+  {
+    if (dirflag != EITHER)
+    {
+      File f = new File(s);
+      if (f.isDirectory() && dirflag == NONDIR)
+      {
+        return false;
+      }
+      if (!f.isDirectory() && dirflag == DIR)
+      {
+        return false;
+      }
+    }
+    return matchAt(s, 0);
+  }
+
+  int dirflag = 0;
+
+  final static int EITHER = 0, DIR = 1, NONDIR = 2;
+
+  /**
+   * Provides an alternative to File.list -- this separates its argument
+   * according to File.pathSeparator. To each path, it splits off a directory --
+   * all characters up to and including the first instance of File.separator --
+   * and a file pattern -- the part that comes after the directory. It then
+   * produces a list of all the pattern matches on all the paths. Thus
+   * "*.java:../*.java" would produce a list of all the java files in this
+   * directory and in the ".." directory on a Unix machine. "*.java;..\\*.java"
+   * would do the same thing on a Dos machine.
+   */
+  public static String[] list(String f)
+  {
+    return list(f, EITHER);
+  }
+
+  static String[] list(String f, int df)
+  {
+    // return list_(f,new FileRegex());
+    StringTokenizer st = new StringTokenizer(f, File.pathSeparator);
+    Vector v = new Vector();
+    while (st.hasMoreTokens())
+    {
+      String path = st.nextToken();
+      list1(path, v, df, true);
+    }
+    String[] sa = new String[v.size()];
+    v.copyInto(sa);
+    return sa;
+  }
+
+  final static Regex root = new Regex(File.separatorChar == '/' ? "/$"
+          : "(?:.:|)\\\\$");
+
+  static void list1(String path, Vector v, int df, boolean rec)
+  {
+    // if path looks like a/b/c/ or d:\ then add .
+    if (root.matchAt(path, 0))
+    {
+      v.addElement(path + ".");
+      return;
+    }
+    File f = new File(path);
+    if (f.getParent() != null && rec)
+    {
+      Vector v2 = new Vector();
+      list1(f.getParent(), v2, DIR, true);
+      for (int i = 0; i < v2.size(); i++)
+      {
+        String path2 = ((String) v2.elementAt(i)) + File.separator
+                + f.getName();
+        list1(path2, v, df, false);
+      }
+    }
+    else
+    {
+      File base = new File(path);
+
+      String dir_s = base.getParent();
+      if (dir_s == null)
+      {
+        dir_s = ".";
+      }
+      File dir = new File(dir_s);
+
+      FileRegex fr = new FileRegex(base.getName());
+      if (fr.isLiteral())
+      {
+        v.addElement(dir_s + File.separator + base.getName());
+        return;
+      }
+      fr.dirflag = df;
+      String[] sa = dir.list(fr);
+      if (sa == null)
+      {
+        return;
+      }
+      for (int i = 0; i < sa.length; i++)
+      {
+        v.addElement(dir_s + File.separator + sa[i]);
+      }
+    }
+  }
+
+  /**
+   * This method takes a file regular expression, and translates it into the
+   * type of pattern used by a normal Regex.
+   */
+  public static String toFileRegex(String s)
+  {
+    StrPos sp = new StrPos(s, 0);
+    StringBuffer sb = new StringBuffer();
+    if (sp.incMatch("{?e="))
+    {
+      char e = sp.thisChar();
+      sp.inc();
+      if (sp.incMatch("}"))
+      {
+        sb.append("(?e=" + e + ")^");
+      }
+      else
+      {
+        sb.append("^(?e=");
+      }
+      sp.esc = e;
+    }
+    int ParenLvl = 0;
+    while (!sp.eos())
+    {
+      if (File.separatorChar == '\\')
+      {
+        if (sp.escaped())
+        {
+          sb.append("\\\\");
+        }
+        sp.dontMatch = false;
+      }
+      if (sp.incMatch("?"))
+      {
+        sb.append(".");
+      }
+      else if (sp.incMatch("."))
+      {
+        sb.append(sp.esc);
+        sb.append('.');
+      }
+      else if (sp.incMatch("{??"))
+      {
+        sb.append("(??");
+        ParenLvl++;
+        // allow negative lookahead to work
+      }
+      else if (sp.incMatch("{?!"))
+      {
+        sb.append("(?!");
+        ParenLvl++;
+        // allow positive lookahead to work
+      }
+      else if (sp.incMatch("{?="))
+      {
+        sb.append("(?=");
+        ParenLvl++;
+      }
+      else if (sp.incMatch("{"))
+      {
+        sb.append("(?:");
+        ParenLvl++;
+      }
+      else if (sp.incMatch("}"))
+      {
+        sb.append(')');
+        ParenLvl--;
+      }
+      else if (ParenLvl != 0 && sp.incMatch(","))
+      {
+        sb.append('|');
+      }
+      else if (sp.incMatch("*"))
+      {
+        sb.append(".*");
+      }
+      else
+      {
+        sb.append(sp.thisChar());
+        sp.inc();
+      }
+    }
+    sb.append("$");
+    return sb.toString();
+  }
+
+  public boolean isLiteral()
+  {
+    Pattern x = thePattern;
+    while (x != null && !(x instanceof End))
+    {
+      if (x instanceof oneChar)
+      {
+        ;
+      }
+      else if (x instanceof Skipped)
+      {
+        ;
+      }
+      else
+      {
+        return false;
+      }
+      x = x.next;
+    }
+    return true;
+  }
+}