content: /**
   * Portions Copyright 2006 DFKI GmbH.
   * Portions Copyright 2001 Sun Microsystems, Inc.
   * Portions Copyright 1999-2001 Language Technologies Institute,
   * Carnegie Mellon University.
   * All Rights Reserved.  Use is subject to license terms.
   * <p/>
   * Permission is hereby granted, free of charge, to use and distribute
   * this software and its documentation without restriction, including
   * without limitation the rights to use, copy, modify, merge, publish,
   * distribute, sublicense, and/or sell copies of this work, and to
   * permit persons to whom this work is furnished to do so, subject to
   * the following conditions:
   * <p/>
   * 1. The code must retain the above copyright notice, this list of
   * conditions and the following disclaimer.
   * 2. Any modifications must be clearly marked as such.
   * 3. Original authors' names are not deleted.
   * 4. The authors' names are not used to endorse or promote products
   * derived from this software without specific prior written
   * permission.
   * <p/>
   * DFKI GMBH AND THE CONTRIBUTORS TO THIS WORK DISCLAIM ALL WARRANTIES WITH
   * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
   * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DFKI GMBH NOR THE
   * CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
   * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
   * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
   * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
   * THIS SOFTWARE.
   */
  package marytts.util.io;
  
  import java.io.BufferedReader;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileOutputStream;
  import java.io.FilenameFilter;
  import java.io.IOException;
  import java.io.InputStreamReader;
  import java.io.OutputStreamWriter;
  import java.io.PrintWriter;
  import java.util.Arrays;
  import java.util.Vector;
  
  /**
   * The BasenameList class produces and stores an alphabetically-sorted
   * array of basenames issued from the .wav files present in a given directory.
   *
   * @author sacha
   */
  public class BasenameList {
      private static final int DEFAULT_INCREMENT = 128;
      private Vector bList = null;
      private String fromDir = null;
      private String fromExt = null;
      private boolean hasChanged;
  
      /****************/
      /* CONSTRUCTORS */
      /****************/
  
      /**
       * Default constructor for an empty list.
       */
      public BasenameList() {
          fromDir = null;
          fromExt = null;
          bList = new Vector(DEFAULT_INCREMENT, DEFAULT_INCREMENT);
          hasChanged = false;
      }
  
      /**
       * Default constructor from an existing vector and fields.
       */
      public BasenameList(String setFromDir, String setFromExt, Vector setVec) {
          fromDir = setFromDir;
          fromExt = setFromExt;
          bList = setVec;
          hasChanged = false;
      }
  
      /**
       * Constructor from an array of strings.
       */
      public BasenameList(String[] str) {
          fromDir = null;
          fromExt = null;
          bList = new Vector(DEFAULT_INCREMENT, DEFAULT_INCREMENT);
          add(str);
          hasChanged = false;
      }
  
      /**
       * This constructor lists the .<extension> files from directory dir,
       * and initializes an an array with their list of alphabetically
       * sorted basenames.
       *
       * @param dir       The name of the directory to list the files from.
       * @param extension The extension of the files to list.
       */
      public BasenameList(String dirName, final String extension) {
          fromDir = dirName;
          if (extension.indexOf(".") != 0)
              fromExt = "." + extension; // If the dot was not included, add it.
          else fromExt = extension;
          /* Turn the directory name into a file, to allow for checking and listing */
          File dir = new File(dirName);
          /* Check if the directory exists */
          if (!dir.exists()) {
              throw new RuntimeException("Directory [" + dirName + "] does not exist. Can't find the [" + extension + "] files.");
          }
          /* List the .extension files */
          File[] selectedFiles = dir.listFiles(new FilenameFilter() {
              @Override
              public boolean accept(File dir, String name) {
                  return name.endsWith(extension);
              }
          });
          
          /* Sort the file names alphabetically */
          Arrays.sort(selectedFiles);
          
          /* Extract the basenames and store them in a vector of strings */
          bList = new Vector(selectedFiles.length, DEFAULT_INCREMENT);
          String str = null;
          int subtractFromFilename = extension.length();
          for (int i = 0; i < selectedFiles.length; i++) {
              str = selectedFiles[i].getName().substring(0, selectedFiles[i].getName().length() - subtractFromFilename);
              add(str);
          }
          hasChanged = false;
      }
  
      /**
       * This constructor loads the basename list from a random access file.
       *
       * @param fileName The file to read from.
       */
      public BasenameList(String fileName) throws IOException {
          load(fileName);
          hasChanged = false;
      }
  
      /*****************/
      /* I/O METHODS   */
      /*****************/
  
      /**
       * Write the basenameList to a file, identified by its name.
       */
      public void write(String fileName) throws IOException {
          write(new File(fileName));
      }
  
      /**
       * Write the basenameList to a File.
       */
      public void write(File file) throws IOException {
          PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"), true);
          if (fromDir != null) {
              pw.println("FROM: " + fromDir + "*" + fromExt);
          }
          String str = null;
          for (int i = 0; i < bList.size(); i++) {
              str = (String) (bList.elementAt(i));
              pw.println(str);
          }
      }
  
      /**
       * Read the basenameList from a file
       */
      public void load(String fileName) throws IOException {
          /* Open the file */
          BufferedReader bfr = new BufferedReader(new InputStreamReader(new FileInputStream(fileName), "UTF-8"));
          /* Make the vector */
          if (bList == null) bList = new Vector(DEFAULT_INCREMENT, DEFAULT_INCREMENT);
          /* Check if the first line contains the origin information (directory+ext) */
          String line = bfr.readLine();
          if (line.indexOf("FROM: ") != -1) {
              line = line.substring(6);
              String[] parts = new String[2];
              parts = line.split("\\*", 2);
              fromDir = parts[0];
              fromExt = parts[1];
          } else if (!(line.matches("^\\s*$"))) add(line);
          /* Add the lines to the vector, ignoring the blank ones. */
          while ((line = bfr.readLine()) != null) {
              if (!(line.matches("^\\s*$"))) add(line);
          }
      }
  
  
      /*****************/
      /* OTHER METHODS */
      /*****************/
  
      /**
       * Adds a basename to the list.
       */
      public void add(String str) {
          if (!bList.contains(str)) bList.add(str);
          hasChanged = true;
      }
  
      /**
       * Adds an array of basenames to the list.
       */
      public void add(String[] str) {
          for (int i = 0; i < str.length; i++) add(str[i]);
          hasChanged = true;
      }
  
      /**
       * Removes a basename from the list, if it was present.
       *
       * @param str The basename to remove.
       * @return true if the list was containing the basename.
       */
      public boolean remove(String str) {
          hasChanged = true;
          return (bList.remove(str));
      }
  
      /**
       * Removes a list from another list.
       *
       * @param bnl The basename list to remove.
       * @return true if the list was containing any element of the list to remove.
       */
      public boolean remove(BasenameList bnl) {
          boolean ret = true;
          for (int i = 0; i < bnl.getLength(); i++) {
              bList.remove(bnl.getName(i));
          }
          hasChanged = true;
          return (ret);
      }
  
      /**
       * Duplicates the list (i.e., emits an autonomous copy of it).
       */
      public BasenameList duplicate() {
          return (new BasenameList(this.fromDir, this.fromExt, (Vector) (this.bList.clone())));
      }
  
      /**
       * Returns an autonomous sublist between fromIndex, inclusive, and toIndex, exclusive.
       */
      public BasenameList subList(int fromIndex, int toIndex) {
          Vector subVec = new Vector(toIndex - fromIndex, DEFAULT_INCREMENT);
          for (int i = fromIndex; i < toIndex; i++) subVec.add(this.getName(i));
          return (new BasenameList(this.fromDir, this.fromExt, subVec));
      }
  
      /**
       * An accessor for the list of basenames, returned as an array of strings
       */
      public String[] getListAsArray() {
          String[] ret = new String[this.getLength()];
          ret = (String[]) bList.toArray(ret);
          return ((ret));
      }
  
      /**
       * Another accessor for the list of basenames, returned as a vector of strings
       */
      public Vector getListAsVector() {
          return (bList);
      }
  
      /**
       * An accessor for the list's length
       */
      public int getLength() {
          return (bList.size());
      }
  
      /**
       * An accessor for the original directory. Returns null if the original
       * directory is undefined.
       */
      public String getDir() {
          return (fromDir);
      }
  
      /**
       * An accessor for the original extension. Returns null if the original
       * extension is undefined.
       */
      public String getExt() {
          return (fromExt);
      }
  
      /**
       * Return a copy of the basename at index i.
       *
       * @param i The index of the basename to consider.
       * @return The corresponding basename.
       */
      public String getName(int i) {
          return (String) bList.elementAt(i);
      }
  
      /**
       * Check if the given basename is part of the list.
       *
       * @param str The basename to check for.
       * @return true if yes, false if no.
       */
      public boolean contains(String str) {
          return (bList.contains(str));
      }
  
      /**
       * Check if the list contains another given one.
       *
       * @param bnl The list of basenames to check for.
       * @return true if yes, false if no.
       */
      public boolean contains(BasenameList bnl) {
          /* The list cannot contain a bigger one: */
          if (bnl.getLength() > this.getLength()) return (false);
          for (int i = 0; i < bnl.getLength(); i++) {
              if (!this.contains(bnl.getName(i))) return (false);
          }
          return (true);
      }
  
      /**
       * Check if two lists are equal.
       *
       * @param bnl The list of basenames to check for.
       * @return true if yes, false if no.
       */
      public boolean equals(BasenameList bnl) {
          if (bnl.getLength() != this.getLength()) return (false);
          for (int i = 0; i < bnl.getLength(); i++) {
              if (!this.contains(bnl.getName(i))) return (false);
          }
          return (true);
      }
  
      /**
       * Ensure that the list is alphabetically sorted.
       */
      public void sort() {
          String[] str = getListAsArray();
          Arrays.sort(str);
          bList.removeAllElements();
          add(str);
          hasChanged = true;
      }
  
      /**
       * Clear the list.
       */
      public void clear() {
          fromDir = null;
          fromExt = null;
          bList.removeAllElements();
          hasChanged = true;
      }
  
      public boolean hasChanged() {
          return hasChanged;
      }
  
  }