merged 1.1 branch into head
[mir.git] / source / mir / changetracker / ChangeTracker.java
diff --git a/source/mir/changetracker/ChangeTracker.java b/source/mir/changetracker/ChangeTracker.java
new file mode 100644 (file)
index 0000000..3df943e
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2001-2006 The Mir-coders group
+ *
+ * This file is part of Mir.
+ *
+ * Mir is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Mir is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Mir; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * In addition, as a special exception, The Mir-coders gives permission to link
+ * the code of this program with  any library licensed under the Apache Software License,
+ * and distribute linked combinations including the two.  You must obey the
+ * GNU General Public License in all respects for all of the code used other than
+ * the above mentioned libraries.  If you modify this file, you may extend this
+ * exception to your version of the file, but you are not obligated to do so.
+ * If you do not wish to do so, delete this exception statement from your version.
+ */
+
+package mir.changetracker;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Calendar;
+
+/**
+ * Change tracker, tracks changes to a path based repository.
+ * All methods are thread-safe
+ */
+
+public class ChangeTracker {
+  private final List changes = new ArrayList();
+  private Calendar calendar = Calendar.getInstance();
+
+  // to prevent memory issues with the number of recorded changes,
+  //   we'll adhere to this maximum
+  private static final int MAX_CHANGES = 10000;
+
+  /**
+   * Add a single change. A change is represented by the full path
+   * of the file involved.
+   */
+  public void addChange(String aPath, ChangeType aChangeType) {
+    synchronized (changes) {
+      changes.add(new Change(aPath, aChangeType, calendar.getTime()));
+    }
+  }
+
+  /**
+   * Add an array of changes. Each change is represented by the full path
+   * of the file involved.
+   */
+  public void addChanges(String[] aPaths, ChangeType aChangeType) {
+    addChanges(Arrays.asList(aPaths), aChangeType);
+  }
+
+  /**
+   * Adds a <code>Collection</code> of changes. Each change is represented by the
+   * full path of the file involved.
+   */
+  public void addChanges(Collection aChanges, ChangeType aChangeType) {
+    synchronized (changes) {
+      Iterator i = aChanges.iterator();
+      while (i.hasNext()) {
+        addChange((String) i.next(), aChangeType);
+      }
+    }
+  }
+
+  public class Change {
+    private ChangeType type;
+    private String path;
+    private Date date;
+
+    Change(String anAbsolutePath, ChangeType aType, Date aDate) {
+      type = aType;
+      path = anAbsolutePath;
+      date = aDate;
+    }
+
+    public String getPath() {
+      return path;
+    }
+
+    public ChangeType getType() {
+      return type;
+    }
+
+    public Date getDate() {
+      return date;
+    }
+
+  }
+
+  /**
+   * Returns a <code>Collection</code> of {@link Change}s within a base
+   *     path, and removes them from the tracker.
+   */
+  public Collection flushChanges(String aBasePath) {
+    return flushChanges(aBasePath, Collections.EMPTY_LIST);
+  }
+
+  /**
+   * Returns a <code>Collection</code> of {@link Change}s within a base
+   *     path, exluding a list of excluded paths, and removes them from
+   *     the tracker.
+   */
+  public Collection flushChanges(String aBasePath, Collection anExcludedPaths) {
+    synchronized (changes) {
+      Collection result = getChanges(aBasePath, anExcludedPaths);
+
+      removeChanges(result);
+
+      return result;
+    }
+  }
+
+  /**
+   * Remove specific changes from the change tracker.
+   *
+   * @param someChanges a <code>Collection</code> of changes represented by
+   * their full path in the form of a <code>String</code>
+   */
+  void removeChanges(Collection someChanges) {
+    synchronized (changes) {
+      changes.removeAll(someChanges);
+    }
+  }
+
+  /**
+   * Returns all changes within a base path
+   */
+  List getChanges(String aBasePath) {
+    synchronized (changes) {
+      List result = new ArrayList();
+
+      Iterator i = changes.iterator();
+      while (i.hasNext()) {
+        Change change = (Change) i.next();
+        if (change.getPath().startsWith(aBasePath)) {
+          result.add(change);
+        }
+      }
+
+      return result;
+    }
+  }
+
+  /**
+   * Gets all changes within a base path, but excluding some other paths
+   *
+   * @param aBasePath
+   * @param anExcludedPaths a collection of paths to exclude. may be <code>null</code>
+   *       to not exclude anything
+   */
+  Collection getChanges(String aBasePath, Collection anExcludedPaths) {
+    synchronized (changes) {
+      List result = getChanges(aBasePath);
+
+      if (anExcludedPaths != null) {
+        Iterator i = anExcludedPaths.iterator();
+        while (i.hasNext()) {
+          String excludedPath = (String) i.next();
+          List remove = new ArrayList();
+          Iterator j = result.iterator();
+          while (j.hasNext()) {
+            Change change = (Change) j.next();
+            if (change.getPath().startsWith(excludedPath)) {
+              remove.add(change);
+            }
+          }
+          result.removeAll(remove);
+        }
+      }
+
+      if (changes.size()>MAX_CHANGES) {
+        changes.clear();
+      }
+
+      return result;
+    }
+  }
+}
\ No newline at end of file