/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.log4j.chainsaw;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javax.swing.ProgressMonitor;
import javax.swing.event.EventListenerList;
import javax.swing.table.AbstractTableModel;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.chainsaw.color.RuleColorizer;
import org.apache.log4j.chainsaw.helper.SwingHelper;
import org.apache.log4j.helpers.Constants;
import org.apache.log4j.rule.Rule;
import org.apache.log4j.spi.LocationInfo;
import org.apache.log4j.spi.LoggingEvent;


/**
 * A CyclicBuffer implementation of the EventContainer.
 *
 * NOTE:  This implementation prevents duplicate rows from being added to the model.
 *
 * Ignoring duplicates was added to support receivers which may attempt to deliver the same
 * event more than once but can be safely ignored (for example, the database receiver
 * when set to retrieve in a loop).
 *
 * @author Paul Smith &lt;psmith@apache.org&gt;
 * @author Scott Deboy &lt;sdeboy@apache.org&gt;
 * @author Stephen Pain
 *
 */
class ChainsawCyclicBufferTableModel extends AbstractTableModel
  implements EventContainer, PropertyChangeListener {

  private static final int DEFAULT_CAPACITY = 5000;
  //cyclic field used internally in this class, but not exposed via the eventcontainer
  private boolean cyclic = true;
  private int cyclicBufferSize = DEFAULT_CAPACITY;
  //original list of LoggingEventWrapper instances
  List unfilteredList;
  //filtered list of LoggingEventWrapper instances
  List filteredList;
  private boolean currentSortAscending;
  private int currentSortColumn;
  private final EventListenerList eventListenerList = new EventListenerList();
  private final List columnNames = new ArrayList(ChainsawColumns.getColumnsNames());
  private boolean sortEnabled = false;
  private boolean reachedCapacity = false;
  private final Logger logger = LogManager.getLogger(ChainsawCyclicBufferTableModel.class);

  //  protected final Object syncLock = new Object();
  private final LoggerNameModel loggerNameModelDelegate = new LoggerNameModelSupport();
  private final Object mutex = new Object();

  //because we may be using a cyclic buffer, if an ID is not provided in the property,
  //use and increment this row counter as the ID for each received row
  int uniqueRow;
  private final Set uniquePropertyKeys = new HashSet();
  private Rule ruleMediator;
  private final PropertyChangeSupport propertySupport = new PropertyChangeSupport(this);
  private RuleColorizer colorizer;
  private final String tableModelName;

  public ChainsawCyclicBufferTableModel(int cyclicBufferSize, RuleColorizer colorizer, String tableModelName) {
    propertySupport.addPropertyChangeListener("cyclic", new ModelChanger());
    this.cyclicBufferSize = cyclicBufferSize;
    this.colorizer = colorizer;
    this.tableModelName = tableModelName;

    unfilteredList = new CyclicBufferList(cyclicBufferSize);
    filteredList = new CyclicBufferList(cyclicBufferSize);
  }

  /* (non-Javadoc)
   * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
   */
  public void propertyChange(PropertyChangeEvent evt) {
    if (evt.getSource() instanceof Rule) {
      if (evt.getSource() == ruleMediator && evt.getPropertyName().equals("findRule")) {
        if (((RuleMediator) evt.getSource()).isFindRuleRequired()) {
          //only refilter if find rule is required
          reFilter();
        }
      } else {
        reFilter();
      }
    }
  }

  public List getMatchingEvents(Rule rule) {
    List list = new ArrayList();
    List unfilteredCopy;
    synchronized (mutex) {
        unfilteredCopy = new ArrayList(unfilteredList);
    }
    Iterator iter = unfilteredCopy.iterator();

    while (iter.hasNext()) {
      LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper) iter.next();

      if (rule.evaluate(loggingEventWrapper.getLoggingEvent(), null)) {
        list.add(loggingEventWrapper);
      }
    }

    return list;
  }

  public void reFilter() {
    final int previousSize;
    final int newSize;
          synchronized (mutex) {
            //post refilter with newValue of TRUE (filtering is about to begin)
            propertySupport.firePropertyChange("refilter", Boolean.FALSE, Boolean.TRUE);
            previousSize = filteredList.size();
            filteredList.clear();
            if (ruleMediator == null) {
                LoggingEventWrapper lastEvent = null;
                for (Iterator iter = unfilteredList.iterator();iter.hasNext();) {
                    LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper)iter.next();
                    loggingEventWrapper.setDisplayed(true);
                    updateEventMillisDelta(loggingEventWrapper, lastEvent);
                    filteredList.add(loggingEventWrapper);
                    lastEvent = loggingEventWrapper;
                }
            } else {
                Iterator iter = unfilteredList.iterator();
                LoggingEventWrapper lastEvent = null;
                while (iter.hasNext()) {
                  LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper) iter.next();

                  if (ruleMediator.evaluate(loggingEventWrapper.getLoggingEvent(), null)) {
                    loggingEventWrapper.setDisplayed(true);
                    filteredList.add(loggingEventWrapper);
                    updateEventMillisDelta(loggingEventWrapper, lastEvent);
                    lastEvent = loggingEventWrapper;
                  } else {
                    loggingEventWrapper.setDisplayed(false);
                  }
                }
            }
            newSize = filteredList.size();
          }
      	SwingHelper.invokeOnEDT(new Runnable() {
      		public void run() {
      			if (newSize > 0) {
	      			if (previousSize == newSize) {
	      				//same - update all
	      				fireTableRowsUpdated(0, newSize - 1);
	      			} else if (previousSize > newSize) {
	      				//less now..update and delete difference
	      				fireTableRowsUpdated(0, newSize - 1);
                        //swing bug exposed by variable height rows when calling fireTableRowsDeleted..use tabledatacchanged
                        fireTableDataChanged();
	      			} else if (previousSize < newSize) {
	      				//more now..update and insert difference
                        if (previousSize > 0) {
	      				    fireTableRowsUpdated(0, previousSize - 1);
                        }
	      				fireTableRowsInserted(Math.max(0, previousSize), newSize - 1);
	      			}
      			} else {
      				//no rows to show
      				fireTableDataChanged();
      			}
	      	notifyCountListeners();
            //post refilter with newValue of FALSE (filtering is complete)
            SwingHelper.invokeOnEDT(new Runnable() {
                public void run() {
                    propertySupport.firePropertyChange("refilter", Boolean.TRUE, Boolean.FALSE);
                }
            });
      	}});
  }

  public int locate(Rule rule, int startLocation, boolean searchForward) {
    List filteredListCopy;
    synchronized (mutex) {
      filteredListCopy = new ArrayList(filteredList);
    }
      if (searchForward) {
        for (int i = startLocation; i < filteredListCopy.size(); i++) {
          if (rule.evaluate(((LoggingEventWrapper) filteredListCopy.get(i)).getLoggingEvent(), null)) {
            return i;
          }
        }
        //if there was no match, start at row zero and go to startLocation
        for (int i = 0; i < startLocation; i++) {
          if (rule.evaluate(((LoggingEventWrapper) filteredListCopy.get(i)).getLoggingEvent(), null)) {
            return i;
          }
        }
      } else {
        for (int i = startLocation; i > -1; i--) {
          if (rule.evaluate(((LoggingEventWrapper) filteredListCopy.get(i)).getLoggingEvent(), null)) {
            return i;
          }
        }
        //if there was no match, start at row list.size() - 1 and go to startLocation
        for (int i = filteredListCopy.size() - 1; i > startLocation; i--) {
          if (rule.evaluate(((LoggingEventWrapper) filteredListCopy.get(i)).getLoggingEvent(), null)) {
            return i;
          }
        }
      }

    return -1;
  }

  /**
   * @param l
   */
  public void removeLoggerNameListener(LoggerNameListener l) {
    loggerNameModelDelegate.removeLoggerNameListener(l);
  }

  /**
   * @param loggerName
   * @return
   */
  public boolean addLoggerName(String loggerName) {
    return loggerNameModelDelegate.addLoggerName(loggerName);
  }

  public String toString() {
    return "ChainsawCyclicBufferTableModel{" +
        "name='" + tableModelName + '\'' +
        '}';
  }

  public void reset() {
      loggerNameModelDelegate.reset();
  }

  /**
   * @param l
   */
  public void addLoggerNameListener(LoggerNameListener l) {
    loggerNameModelDelegate.addLoggerNameListener(l);
  }

  /**
   * @return
   */
  public Collection getLoggerNames() {
    return loggerNameModelDelegate.getLoggerNames();
  }

  public void addEventCountListener(EventCountListener listener) {
    eventListenerList.add(EventCountListener.class, listener);
  }

  public boolean isSortable(int col) {
    return true;
  }

  public void notifyCountListeners() {
    EventCountListener[] listeners =
      (EventCountListener[]) eventListenerList.getListeners(
        EventCountListener.class);

    int filteredListSize;
    int unfilteredListSize;
    synchronized (mutex) {
        filteredListSize = filteredList.size();
        unfilteredListSize = unfilteredList.size();
    }
    for (int i = 0; i < listeners.length; i++) {
      listeners[i].eventCountChanged(
        filteredListSize, unfilteredListSize);
    }
  }

  /**
   * Changes the underlying display rule in use.  If there was
   * a previous Rule defined, this Model removes itself as a listener
   * from the old rule, and adds itself to the new rule (if the new Rule is not Null).
   *
   * In any case, the model ensures the Filtered list is made up to date in a separate thread.
   */
  public void setRuleMediator(RuleMediator ruleMediator) {
    if (this.ruleMediator != null) {
      this.ruleMediator.removePropertyChangeListener(this);
    }

    this.ruleMediator = ruleMediator;

    if (this.ruleMediator != null) {
      this.ruleMediator.addPropertyChangeListener(this);
    }
    reFilter();
  }

  /* (non-Javadoc)
     * @see org.apache.log4j.chainsaw.EventContainer#sort()
     */
  public void sort() {
      boolean sort;
      final int filteredListSize;
      synchronized (mutex) {
          filteredListSize = filteredList.size();
          sort = (sortEnabled && filteredListSize > 0);
        if (sort) {
            //reset display (used to ensure row height is updated)
            LoggingEventWrapper lastEvent = null;
            for (Iterator iter = filteredList.iterator();iter.hasNext();) {
                LoggingEventWrapper e = (LoggingEventWrapper)iter.next();
                e.setDisplayed(true);
                updateEventMillisDelta(e, lastEvent);
                lastEvent = e;
            }
            Collections.sort(
              filteredList,
              new ColumnComparator(
                getColumnName(currentSortColumn), currentSortColumn,
                currentSortAscending));
        }
      }
      if (sort) {
        SwingHelper.invokeOnEDT(new Runnable() {
            public void run() {
                fireTableRowsUpdated(0, Math.max(filteredListSize - 1, 0));
            }
        });
      }
  }

  public boolean isSortEnabled() {
    return sortEnabled;
  }

  public void sortColumn(int col, boolean ascending) {
    logger.debug("request to sort col=" + col);
    currentSortAscending = ascending;
    currentSortColumn = col;
    sortEnabled = true;
    sort();
  }

  /* (non-Javadoc)
   * @see org.apache.log4j.chainsaw.EventContainer#clear()
   */
  public void clearModel() {
    reachedCapacity = false;

    synchronized (mutex) {
      unfilteredList.clear();
      filteredList.clear();
      uniqueRow = 0;
    }

    SwingHelper.invokeOnEDT(new Runnable() {
    	public void run() {
    	    fireTableDataChanged();
    	}
    });

    notifyCountListeners();
    loggerNameModelDelegate.reset();
  }

  public List getAllEvents() {
      synchronized (mutex) {
          return new ArrayList(unfilteredList);
      }
  }
  
  
  public List getFilteredEvents() {

  	synchronized (mutex) {
  		return new ArrayList(filteredList);
  	}
  }
  
  public int getRowIndex(LoggingEventWrapper loggingEventWrapper) {
    synchronized (mutex) {
      return filteredList.indexOf(loggingEventWrapper);
    }
  }

    public void removePropertyFromEvents(String propName) {
        //first remove the event from any displayed events, so we can fire row updated event
        List filteredListCopy;
        List unfilteredListCopy;
        synchronized(mutex) {
            filteredListCopy = new ArrayList(filteredList);
            unfilteredListCopy = new ArrayList(unfilteredList);
        }
        for (int i=0;i<filteredListCopy.size();i++) {
            LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper)filteredListCopy.get(i);
            Object result = loggingEventWrapper.removeProperty(propName);
            if (result != null) {
                fireRowUpdated(i, false);
            }
        }
        //now remove the event from all events
        for (Iterator iter = unfilteredListCopy.iterator();iter.hasNext();) {
            LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper)iter.next();
            loggingEventWrapper.removeProperty(propName);
        }
    }

    public int updateEventsWithFindRule(Rule findRule) {
        int count = 0;
        List unfilteredListCopy;
        synchronized(mutex) {
            unfilteredListCopy = new ArrayList(unfilteredList);
        }
        for (Iterator iter = unfilteredListCopy.iterator();iter.hasNext();) {
            LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper) iter.next();
            loggingEventWrapper.evaluateSearchRule(findRule);
            //return the count of visible search matches
            if (loggingEventWrapper.isSearchMatch() && loggingEventWrapper.isDisplayed()) {
                count++;
            }
        }
        return count;
    }

    public int findColoredRow(int startLocation, boolean searchForward) {
        List filteredListCopy;
        synchronized (mutex) {
            filteredListCopy = new ArrayList(filteredList);
        }
        if (searchForward) {
          for (int i = startLocation; i < filteredListCopy.size(); i++) {
            LoggingEventWrapper event = (LoggingEventWrapper)filteredListCopy.get(i);
            if (!event.getColorRuleBackground().equals(ChainsawConstants.COLOR_DEFAULT_BACKGROUND) ||
                    !event.getColorRuleForeground().equals(ChainsawConstants.COLOR_DEFAULT_FOREGROUND)) {
                return i;
            }
          }
          //searching forward, no colorized event was found - now start at row zero and go to startLocation
          for (int i = 0; i < startLocation; i++) {
            LoggingEventWrapper event = (LoggingEventWrapper)filteredListCopy.get(i);
            if (!event.getColorRuleBackground().equals(ChainsawConstants.COLOR_DEFAULT_BACKGROUND) ||
                    !event.getColorRuleForeground().equals(ChainsawConstants.COLOR_DEFAULT_FOREGROUND)) {
                return i;
            }
          }
        } else {
          for (int i = startLocation; i > -1; i--) {
              LoggingEventWrapper event = (LoggingEventWrapper)filteredListCopy.get(i);
              if (!event.getColorRuleBackground().equals(ChainsawConstants.COLOR_DEFAULT_BACKGROUND) ||
                      !event.getColorRuleForeground().equals(ChainsawConstants.COLOR_DEFAULT_FOREGROUND)) {
                  return i;
            }
          }
          //searching backward, no colorized event was found - now start at list.size() - 1 and go to startLocation
          for (int i = filteredListCopy.size() - 1; i > startLocation; i--) {
              LoggingEventWrapper event = (LoggingEventWrapper)filteredListCopy.get(i);
              if (!event.getColorRuleBackground().equals(ChainsawConstants.COLOR_DEFAULT_BACKGROUND) ||
                      !event.getColorRuleForeground().equals(ChainsawConstants.COLOR_DEFAULT_FOREGROUND)) {
                  return i;
            }
          }
        }

      return -1;
    }

  public int getSearchMatchCount() {
    int searchMatchCount = 0;
    synchronized(mutex) {
      for (Iterator iter = filteredList.iterator();iter.hasNext();) {
        LoggingEventWrapper wrapper = (LoggingEventWrapper) iter.next();
        if (wrapper.isSearchMatch() && wrapper.isDisplayed()) {
          searchMatchCount++;
        }
      }
    }
    return searchMatchCount;
  }

  public int getColumnCount() {
    return columnNames.size();
  }

  public String getColumnName(int column) {
      return (String) columnNames.get(column);
  }

  public LoggingEventWrapper getRow(int row) {
    synchronized (mutex) {
      if (row < filteredList.size() && row > -1) {
        return (LoggingEventWrapper) filteredList.get(row);
      }
    }

    return null;
  }

  public int getRowCount() {
    synchronized (mutex) {
      return filteredList.size();
    }
  }

  public Object getValueAt(int rowIndex, int columnIndex) {
    LoggingEvent event = null;

    synchronized (mutex) {
      if (rowIndex < filteredList.size() && rowIndex > -1) {
        event = ((LoggingEventWrapper) filteredList.get(rowIndex)).getLoggingEvent();
      }
    }

    if (event == null) {
      return null;
    }

    LocationInfo info = null;

    if (event.locationInformationExists()) {
      info = event.getLocationInformation();
    }

    switch (columnIndex + 1) {
    case ChainsawColumns.INDEX_ID_COL_NAME:

      Object id = event.getProperty(Constants.LOG4J_ID_KEY);

      if (id != null) {
        return id;
      }

      return new Integer(rowIndex);

    case ChainsawColumns.INDEX_LEVEL_COL_NAME:
      return event.getLevel();

    case ChainsawColumns.INDEX_LOG4J_MARKER_COL_NAME:
      return event.getProperty(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE);

    case ChainsawColumns.INDEX_MILLIS_DELTA_COL_NAME:
      return event.getProperty(ChainsawConstants.MILLIS_DELTA_COL_NAME_LOWERCASE);

    case ChainsawColumns.INDEX_LOGGER_COL_NAME:
      return event.getLoggerName();

    case ChainsawColumns.INDEX_TIMESTAMP_COL_NAME:
      return new Date(event.getTimeStamp());

    case ChainsawColumns.INDEX_MESSAGE_COL_NAME:
      return event.getRenderedMessage();

    case ChainsawColumns.INDEX_NDC_COL_NAME:
      return event.getNDC();

    case ChainsawColumns.INDEX_THREAD_COL_NAME:
      return event.getThreadName();

    case ChainsawColumns.INDEX_THROWABLE_COL_NAME:
      return event.getThrowableStrRep();

    case ChainsawColumns.INDEX_CLASS_COL_NAME:
      return ((info == null) || ("?".equals(info.getClassName()))) ? "" : info.getClassName();

        case ChainsawColumns.INDEX_FILE_COL_NAME:
      return ((info == null) || ("?".equals(info.getFileName()))) ? "" : info.getFileName();

        case ChainsawColumns.INDEX_LINE_COL_NAME:
      return ((info == null) || ("?".equals(info.getLineNumber()))) ? "" : info.getLineNumber();

        case ChainsawColumns.INDEX_METHOD_COL_NAME:
      return ((info == null) || ("?".equals(info.getMethodName()))) ? "" : info.getMethodName();

        default:

            if (columnIndex < columnNames.size()) {
        //case may not match..try case sensitive and fall back to case-insensitive
        String result = event.getProperty(columnNames.get(columnIndex).toString());
        if (result == null) {
            String lowerColName = columnNames.get(columnIndex).toString().toLowerCase(Locale.ENGLISH);
            Set entrySet = event.getProperties().entrySet();
            for (Iterator iter = entrySet.iterator();iter.hasNext();) {
                Map.Entry thisEntry = (Map.Entry) iter.next();
                if (thisEntry.getKey().toString().equalsIgnoreCase(lowerColName)) {
                    result = thisEntry.getValue().toString();
                }
            }
        }
        if (result != null) {
            return result;
        }
      }
    }
    return "";
  }

  public boolean isAddRow(LoggingEventWrapper loggingEventWrapper) {
    Object id = loggingEventWrapper.getLoggingEvent().getProperty(Constants.LOG4J_ID_KEY);

    //only set the property if it doesn't already exist
    if (id == null) {
      id = new Integer(++uniqueRow);
      loggingEventWrapper.setProperty(Constants.LOG4J_ID_KEY, id.toString());
    }

    loggingEventWrapper.updateColorRuleColors(colorizer.getBackgroundColor(loggingEventWrapper.getLoggingEvent()), colorizer.getForegroundColor(loggingEventWrapper.getLoggingEvent()));
    Rule findRule = colorizer.getFindRule();
    if (findRule != null) {
      loggingEventWrapper.evaluateSearchRule(colorizer.getFindRule());
    }

    boolean rowAdded = false;

    /**
         * If we're in cyclic mode and over budget on the size, the addition of a new event will
         * cause the oldest event to fall off the cliff. We need to remove that events ID from the
         * Set so we are not keeping track of IDs for all events ever received (we'd run out of
         * memory...)
         */
    synchronized(mutex) {
        if (cyclic) {
            CyclicBufferList bufferList = (CyclicBufferList) unfilteredList;
            if (bufferList.size() == bufferList.getMaxSize()) {
                reachedCapacity = true;
            }
        }
        int unfilteredSize = unfilteredList.size();
        LoggingEventWrapper lastLoggingEventWrapper = null;
        if (unfilteredSize > 0) {
            lastLoggingEventWrapper = (LoggingEventWrapper) unfilteredList.get(unfilteredSize - 1);
        }
        unfilteredList.add(loggingEventWrapper);
        if ((ruleMediator == null) || (ruleMediator.evaluate(loggingEventWrapper.getLoggingEvent(), null))) {
            loggingEventWrapper.setDisplayed(true);
            updateEventMillisDelta(loggingEventWrapper, lastLoggingEventWrapper);
            filteredList.add(loggingEventWrapper);
            rowAdded = true;
        } else {
            loggingEventWrapper.setDisplayed(false);
        }
    }

    checkForNewColumn(loggingEventWrapper);

    return rowAdded;
  }

    private void updateEventMillisDelta(LoggingEventWrapper loggingEventWrapper, LoggingEventWrapper lastLoggingEventWrapper) {
      if (lastLoggingEventWrapper != null) {
        loggingEventWrapper.setPreviousDisplayedEventTimestamp(lastLoggingEventWrapper.getLoggingEvent().getTimeStamp());
      } else {
        //delta to same event = 0
        loggingEventWrapper.setPreviousDisplayedEventTimestamp(loggingEventWrapper.getLoggingEvent().getTimeStamp());
      }
    }

   private void checkForNewColumn(LoggingEventWrapper loggingEventWrapper)
   {
      /**
       * Is this a new Property key we haven't seen before?  Remember that now MDC has been merged
       * into the Properties collection
       */
      boolean newColumn = uniquePropertyKeys.addAll(loggingEventWrapper.getPropertyKeySet());

      if (newColumn) {
        /**
         * If so, we should add them as columns and notify listeners.
         */
        for (Iterator iter = loggingEventWrapper.getPropertyKeySet().iterator(); iter.hasNext();) {
          String key = iter.next().toString().toUpperCase();

          //add all keys except the 'log4jid' key (columnNames is all-caps)
          if (!columnNames.contains(key) && !(Constants.LOG4J_ID_KEY.equalsIgnoreCase(key))) {
            columnNames.add(key);
            logger.debug("Adding col '" + key + "', columnNames=" + columnNames);
            fireNewKeyColumnAdded(
              new NewKeyEvent(
                this, columnNames.indexOf(key), key, loggingEventWrapper.getLoggingEvent().getProperty(key)));
          }
        }
      }
   }

  public void fireTableEvent(final int begin, final int end, final int count) {
  	SwingHelper.invokeOnEDT(new Runnable() {
  		public void run() {
    if (cyclic) {
      if (!reachedCapacity) {
        //if we didn't loop and it's the 1st time, insert
        if ((begin + count) < cyclicBufferSize) {
          fireTableRowsInserted(begin, end);
        } else {
          //we did loop - insert and then update rows
          //rows are zero-indexed, subtract 1 from cyclicbuffersize for the event notification
          fireTableRowsInserted(begin, cyclicBufferSize - 1);
          fireTableRowsUpdated(0, cyclicBufferSize - 1);
          reachedCapacity = true;
        }
      } else {
        fireTableRowsUpdated(0, cyclicBufferSize - 1);
      }
    } else {
      fireTableRowsInserted(begin, end);
    }
  }});
  }

    public void fireRowUpdated(int row, boolean checkForNewColumns) {
        LoggingEventWrapper loggingEventWrapper = getRow(row);
        if (loggingEventWrapper != null)
        {
            loggingEventWrapper.updateColorRuleColors(colorizer.getBackgroundColor(loggingEventWrapper.getLoggingEvent()), colorizer.getForegroundColor(loggingEventWrapper.getLoggingEvent()));
            Rule findRule = colorizer.getFindRule();
            if (findRule != null) {
              loggingEventWrapper.evaluateSearchRule(colorizer.getFindRule());
            }

            fireTableRowsUpdated(row, row);
            if (checkForNewColumns) {
                //row may have had a column added..if so, make sure a column is added
                checkForNewColumn(loggingEventWrapper);
            }
        }
    }

    /**
  * @param e
  */
  private void fireNewKeyColumnAdded(NewKeyEvent e) {
    NewKeyListener[] listeners =
      (NewKeyListener[]) eventListenerList.getListeners(NewKeyListener.class);

    for (int i = 0; i < listeners.length; i++) {
      NewKeyListener listener = listeners[i];
      listener.newKeyAdded(e);
    }
  }

  /**
   * @return
   */
  public int getMaxSize() {
    return cyclicBufferSize;
  }

  /* (non-Javadoc)
   * @see org.apache.log4j.chainsaw.EventContainer#addNewKeyListener(org.apache.log4j.chainsaw.NewKeyListener)
   */
  public void addNewKeyListener(NewKeyListener l) {
    eventListenerList.add(NewKeyListener.class, l);
  }

  /* (non-Javadoc)
   * @see org.apache.log4j.chainsaw.EventContainer#removeNewKeyListener(org.apache.log4j.chainsaw.NewKeyListener)
   */
  public void removeNewKeyListener(NewKeyListener l) {
    eventListenerList.remove(NewKeyListener.class, l);
  }

  /* (non-Javadoc)
   * @see javax.swing.table.TableModel#isCellEditable(int, int)
   */
  public boolean isCellEditable(int rowIndex, int columnIndex) {
    if (getColumnName(columnIndex).equalsIgnoreCase(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE)) {
      return true;
    }

    if (columnIndex >= columnNames.size()) {
        return false;
    }

    return super.isCellEditable(rowIndex, columnIndex);
  }

  /* (non-Javadoc)
   * @see org.apache.log4j.chainsaw.EventContainer#setCyclic(boolean)
   */
  public void setCyclic(final boolean cyclic) {
    if (this.cyclic == cyclic) {
      return;
    }

    final boolean old = this.cyclic;
    this.cyclic = cyclic;
    propertySupport.firePropertyChange("cyclic", old, cyclic);
  }

  /* (non-Javadoc)
   * @see org.apache.log4j.chainsaw.EventContainer#addPropertyChangeListener(java.beans.PropertyChangeListener)
   */
  public void addPropertyChangeListener(PropertyChangeListener l) {
    propertySupport.addPropertyChangeListener(l);
  }

  /* (non-Javadoc)
   * @see org.apache.log4j.chainsaw.EventContainer#addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener)
   */
  public void addPropertyChangeListener(
    String propertyName, PropertyChangeListener l) {
    propertySupport.addPropertyChangeListener(propertyName, l);
  }

  /* (non-Javadoc)
   * @see org.apache.log4j.chainsaw.EventContainer#size()
   */
  public int size() {
    synchronized(mutex) {
      return unfilteredList.size();
    }
  }

  private class ModelChanger implements PropertyChangeListener {
    /* (non-Javadoc)
     * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
     */
    public void propertyChange(PropertyChangeEvent arg0) {
      Thread thread =
        new Thread(
          new Runnable() {
            public void run() {
              ProgressMonitor monitor = null;

              int index = 0;

              try {
                synchronized (mutex) {
                  monitor =
                    new ProgressMonitor(
                      null, "Switching models...",
                      "Transferring between data structures, please wait...", 0,
                      unfilteredList.size() + 1);
                  monitor.setMillisToDecideToPopup(250);
                  monitor.setMillisToPopup(100);
                  logger.debug(
                    "Changing Model, isCyclic is now " + cyclic);

                  List newUnfilteredList = null;
                  List newFilteredList = null;

                  if (cyclic) {
                    newUnfilteredList = new CyclicBufferList(cyclicBufferSize);
                    newFilteredList = new CyclicBufferList(cyclicBufferSize);
                  } else {
                    newUnfilteredList = new ArrayList(cyclicBufferSize);
                    newFilteredList = new ArrayList(cyclicBufferSize);
                  }

                  int increment = 0;

                  for (Iterator iter = unfilteredList.iterator();
                      iter.hasNext();) {
                    LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper) iter.next();
                    newUnfilteredList.add(loggingEventWrapper);
                    monitor.setProgress(index++);
                  }

                  unfilteredList = newUnfilteredList;
                  filteredList = newFilteredList;
                }

                monitor.setNote("Refiltering...");
                reFilter();

                monitor.setProgress(index++);
              } finally {
                monitor.close();
              }

              logger.debug("Model Change completed");
            }
          });
      thread.setPriority(Thread.MIN_PRIORITY + 1);
      thread.start();
    }
  }
}
