alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software
 * License version 1.1, a copy of which has been included with this
 * distribution in the LICENSE.txt file.
 */
package org.apache.log4j.lf5.viewer;

import org.apache.log4j.lf5.LogRecord;
import org.apache.log4j.lf5.LogRecordFilter;
import org.apache.log4j.lf5.PassingLogRecordFilter;

import javax.swing.table.AbstractTableModel;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;


/**
 * A TableModel for LogRecords which includes filtering support.
 *
 * @author Richard Wan
 * @author Brent Sprecher
 */

// Contributed by ThoughtWorks Inc.

public class FilteredLogTableModel
    extends AbstractTableModel {
  //--------------------------------------------------------------------------
  //   Constants:
  //--------------------------------------------------------------------------

  //--------------------------------------------------------------------------
  //   Protected Variables:
  //--------------------------------------------------------------------------

  protected LogRecordFilter _filter = new PassingLogRecordFilter();
  protected List _allRecords = new ArrayList();
  protected List _filteredRecords;
  protected int _maxNumberOfLogRecords = 5000;
  protected String[] _colNames = {"Date",
                                  "Thread",
                                  "Message #",
                                  "Level",
                                  "NDC",
                                  "Category",
                                  "Message",
                                  "Location",
                                  "Thrown"};

  //--------------------------------------------------------------------------
  //   Private Variables:
  //--------------------------------------------------------------------------

  //--------------------------------------------------------------------------
  //   Constructors:
  //--------------------------------------------------------------------------

  public FilteredLogTableModel() {
    super();
  }

  //--------------------------------------------------------------------------
  //   Public Methods:
  //--------------------------------------------------------------------------

  public void setLogRecordFilter(LogRecordFilter filter) {
    _filter = filter;
  }

  public LogRecordFilter getLogRecordFilter() {
    return _filter;
  }

  public String getColumnName(int i) {
    return _colNames[i];
  }

  public int getColumnCount() {
    return _colNames.length;
  }

  public int getRowCount() {
    return getFilteredRecords().size();
  }

  public int getTotalRowCount() {
    return _allRecords.size();
  }

  public Object getValueAt(int row, int col) {
    LogRecord record = getFilteredRecord(row);
    return getColumn(col, record);
  }

  public void setMaxNumberOfLogRecords(int maxNumRecords) {
    if (maxNumRecords > 0) {
      _maxNumberOfLogRecords = maxNumRecords;
    }

  }

  public synchronized boolean addLogRecord(LogRecord record) {

    _allRecords.add(record);

    if (_filter.passes(record) == false) {
      return false;
    }
    getFilteredRecords().add(record);
    fireTableRowsInserted(getRowCount(), getRowCount());
    trimRecords();
    return true;
  }

  /**
   * Forces the LogTableModel to requery its filters to determine
   * which records to display.
   */
  public synchronized void refresh() {
    _filteredRecords = createFilteredRecordsList();
    fireTableDataChanged();
  }

  public synchronized void fastRefresh() {
    _filteredRecords.remove(0);
    fireTableRowsDeleted(0, 0);
  }


  /**
   * Clears all records from the LogTableModel
   */
  public synchronized void clear() {
    _allRecords.clear();
    _filteredRecords.clear();
    fireTableDataChanged();
  }

  //--------------------------------------------------------------------------
  //   Protected Methods:
  //--------------------------------------------------------------------------

  protected List getFilteredRecords() {
    if (_filteredRecords == null) {
      refresh();
    }
    return _filteredRecords;
  }

  protected List createFilteredRecordsList() {
    List result = new ArrayList();
    Iterator records = _allRecords.iterator();
    LogRecord current;
    while (records.hasNext()) {
      current = (LogRecord) records.next();
      if (_filter.passes(current)) {
        result.add(current);
      }
    }
    return result;
  }

  protected LogRecord getFilteredRecord(int row) {
    List records = getFilteredRecords();
    int size = records.size();
    if (row < size) {
      return (LogRecord) records.get(row);
    }
    // a minor problem has happened. JTable has asked for
    // a row outside the bounds, because the size of
    // _filteredRecords has changed while it was looping.
    // return the last row.
    return (LogRecord) records.get(size - 1);

  }

  protected Object getColumn(int col, LogRecord lr) {
    if (lr == null) {
      return "NULL Column";
    }
    String date = new Date(lr.getMillis()).toString();
    switch (col) {
      case 0:
        return date + " (" + lr.getMillis() + ")";
      case 1:
        return lr.getThreadDescription();
      case 2:
        return new Long(lr.getSequenceNumber());
      case 3:
        return lr.getLevel();
      case 4:
        return lr.getNDC();
      case 5:
        return lr.getCategory();
      case 6:
        return lr.getMessage();
      case 7:
        return lr.getLocation();
      case 8:
        return lr.getThrownStackTrace();
      default:
        String message = "The column number " + col + "must be between 0 and 8";
        throw new IllegalArgumentException(message);
    }
  }

  // We don't want the amount of rows to grow without bound,
  // leading to a out-of-memory-exception.  Especially not good
  // in a production environment :)

  // This method & clearLogRecords() are synchronized so we don't
  // delete rows that don't exist.
  protected void trimRecords() {
    if (needsTrimming()) {
      trimOldestRecords();
    }
  }

  protected boolean needsTrimming() {
    return (_allRecords.size() > _maxNumberOfLogRecords);
  }

  protected void trimOldestRecords() {
    synchronized (_allRecords) {
      int trim = numberOfRecordsToTrim();
      if (trim > 1) {
        List oldRecords =
            _allRecords.subList(0, trim);
        oldRecords.clear();
        refresh();
      } else {
        _allRecords.remove(0);
        fastRefresh();
      }
    }

  }

  //--------------------------------------------------------------------------
  //   Private Methods:
  //--------------------------------------------------------------------------
  private int numberOfRecordsToTrim() {
    return _allRecords.size() - _maxNumberOfLogRecords;
  }

  //--------------------------------------------------------------------------
  //   Nested Top-Level Classes or Interfaces
  //--------------------------------------------------------------------------
}

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.