Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

org.greenstone.gatherer.gui.metaaudit
Class MetaAuditFrame  view MetaAuditFrame download MetaAuditFrame.java

java.lang.Object
  extended byjava.awt.Component
      extended byjava.awt.Container
          extended byjava.awt.Window
              extended byjava.awt.Dialog
                  extended byjavax.swing.JDialog
                      extended byorg.greenstone.gatherer.gui.ModalDialog
                          extended byorg.greenstone.gatherer.gui.metaaudit.MetaAuditFrame
All Implemented Interfaces:
javax.accessibility.Accessible, java.util.EventListener, java.awt.image.ImageObserver, java.awt.MenuContainer, javax.swing.RootPaneContainer, java.io.Serializable, javax.swing.event.TreeSelectionListener, javax.swing.WindowConstants

public class MetaAuditFrame
extends org.greenstone.gatherer.gui.ModalDialog
implements javax.swing.event.TreeSelectionListener

The MetaAuditFrame provides a table view of all of the metadata assigned to a selection of FileNodes. All values for a certain file and a certain metadata element appear in the same cell. This table can be sorted by any column, and also has a MS Excel-like AutoFilter allowing you to restrict the rows visible to only those that match a certain set of criteria (applied to each column, and then 'ANDED', or cojoined, to determine the filter). Finally this dialog does not block the Gatherer tool, so the file selection can be changed and the dialog will just generate a new table dynamically.
Much effort has gone into optimizing this table, as it quickly becomes slow and unresponsive to build/filter/sort when the number of records selected is high. However its performance is still nowhere as good as the Excel spreadsheet, and selections of 1000+ records can cause some serious waiting problems. Performance progression, shown in terms of time taken to perform action, are shown below. Note that building includes both the creation of the data model, and/or the time taken to lay out row and column sizes (due to this using multiple entry cells). Also all tables, by default, must be sorted by one column, which is initially the first column in ascending order:

Time Taken with 1000 records (ms)
ActionOriginalRevision 1Revision 2Revision 3
Build11301315001280665
Sort34228353341338
Filter57110485485485


Time Taken with 10,000 records (ms) [hdlsub]
ActionOriginalRevision 1Revision 2Revision 3
BuildDNF866767843081
SortDNF236241228
FilterDNF592725976759614


Time Taken with 30,000 records (ms) [hdl]
ActionOriginalRevision 1Revision 2Revision 3
BuildDNF19037164788111
SortDNF314301385
FilterDNF[300000][300000][300000]


It is easy to see that while building and sorting have become quite fast and reasonable, sorting is still unacceptable in terms of performance. The difficulty is this, that while sorting is easy (and fast) to implement via the Decorator pattern (making the overall table model a MDVC one) it requires the entire contents of a column to be available. Thus no matter the speed of your sort algorithm you will end up making N calls to getValueAt() in the table data model, for N records. This is not a problem for the initial model, hence the small sort times. However when you attempt to place another deocrator model (or modify the existing one) in order to filter only selected rows, even if the filtering itself takes little time, this little time quickly grows to unacceptable levels. In fact testing has shown it to grow much faster than linear time (though I'm not sure where). Doubling the number of records to filter increases the processing time by 5-7 times.
In attempting to solve this problem, I have found many resources that mention a similar problem when trying to build visual representations of database tables, especially over networks or other temporally-non-deterministic connections. The common solution is to 'page' only those records necessary into memory on demand, thus making initial response significantly faster, while paying a small price for subsequent page seeks. There are even studies and algorithms for determining pages loads etc, I would imagine garnered from the memory management community. However none of these really help me usless I can get around the problem of having to have the entire columns population immeditaly accessable for sorting purposes.
I believe with more time is would be possible to make a hybrid table model with properties such as you would require for the aforemenetioned database application, but which also provides fast methods for determining the highest and lowest records perhaps by building traversable heaps in the original model. Such a solution would incur a build penalty, and could consume significant memory, but would provide ordered and sequential access to the data within.
The discussion aside, I have run out of time to do anything further on this, so will include as is, and provide a warning dialog whenever the number of records might suffer slow processing (1000+ records).

Version:
2.3

Nested Class Summary
private  class MetaAuditFrame.CloseListener
          Listens for actions upon the close button, and if detected closes the dialog
 
Nested classes inherited from class javax.swing.JDialog
javax.swing.JDialog.AccessibleJDialog
 
Nested classes inherited from class java.awt.Dialog
java.awt.Dialog.AccessibleAWTDialog
 
Nested classes inherited from class java.awt.Window
java.awt.Window.AccessibleAWTWindow
 
Nested classes inherited from class java.awt.Container
java.awt.Container.AccessibleAWTContainer
 
Nested classes inherited from class java.awt.Component
java.awt.Component.AccessibleAWTComponent, java.awt.Component.BltBufferStrategy, java.awt.Component.FlipBufferStrategy
 
Field Summary
 AutofilterDialog autofilter_dialog
           
private  boolean invalid
          Whether the selection has changed since the last time we built the model (because it has been hidden and theres no point refreshing a model you can't see!).
private  org.greenstone.gatherer.file.FileNode[] records
          An array holding the most recent list of paths selected (plus some nulls for those paths removed).
private  MetaAuditFrame self
          A reference to ourselves so that inner classes can interact with us.
private static java.awt.Dimension SIZE
          The default size for the metaaudit dialog.
private  MetaAuditTable table
          The table in which the metadata is shown.
 
Fields inherited from class org.greenstone.gatherer.gui.ModalDialog
modal, waiting
 
Fields inherited from class javax.swing.JDialog
accessibleContext, rootPane, rootPaneCheckingEnabled
 
Fields inherited from class java.awt.Dialog
 
Fields inherited from class java.awt.Window
 
Fields inherited from class java.awt.Container
 
Fields inherited from class java.awt.Component
BOTTOM_ALIGNMENT, CENTER_ALIGNMENT, LEFT_ALIGNMENT, RIGHT_ALIGNMENT, TOP_ALIGNMENT
 
Fields inherited from interface javax.swing.WindowConstants
DISPOSE_ON_CLOSE, DO_NOTHING_ON_CLOSE, EXIT_ON_CLOSE, HIDE_ON_CLOSE
 
Fields inherited from interface java.awt.image.ImageObserver
ABORT, ALLBITS, ERROR, FRAMEBITS, HEIGHT, PROPERTIES, SOMEBITS, WIDTH
 
Constructor Summary
MetaAuditFrame(org.greenstone.gatherer.util.TreeSynchronizer tree_sync, org.greenstone.gatherer.file.FileNode[] records)
          Constructor.
 
Method Summary
 void destroy()
          Destructor.
 void display()
          Display the dialog on screen.
private  void rebuildModel()
          Rebuild the metaaudit table model using the current collection tree selection.
 void setRecords(org.greenstone.gatherer.file.FileNode[] records)
           
 void valueChanged(javax.swing.event.TreeSelectionEvent event)
          This method is called whenever the selection within the collection tree changes.
 void wait(boolean waiting)
           
 
Methods inherited from class org.greenstone.gatherer.gui.ModalDialog
setModal, setVisible
 
Methods inherited from class javax.swing.JDialog
addImpl, createRootPane, dialogInit, getAccessibleContext, getContentPane, getDefaultCloseOperation, getGlassPane, getJMenuBar, getLayeredPane, getPreferredSize, getRootPane, isDefaultLookAndFeelDecorated, isRootPaneCheckingEnabled, paramString, processWindowEvent, remove, setContentPane, setDefaultCloseOperation, setDefaultLookAndFeelDecorated, setGlassPane, setJMenuBar, setLayeredPane, setLayout, setRootPane, setRootPaneCheckingEnabled, update
 
Methods inherited from class java.awt.Dialog
addNotify, dispose, getTitle, hide, isModal, isResizable, isUndecorated, setResizable, setTitle, setUndecorated, show
 
Methods inherited from class java.awt.Window
addWindowFocusListener, addWindowListener, addWindowStateListener, applyResourceBundle, applyResourceBundle, createBufferStrategy, createBufferStrategy, getBufferStrategy, getFocusableWindowState, getFocusOwner, getGraphicsConfiguration, getListeners, getLocale, getMostRecentFocusOwner, getOwnedWindows, getOwner, getToolkit, getWarningString, getWindowFocusListeners, getWindowListeners, getWindowStateListeners, isActive, isFocusableWindow, isFocused, isShowing, pack, postEvent, processEvent, processWindowFocusEvent, processWindowStateEvent, removeWindowFocusListener, removeWindowListener, removeWindowStateListener, setCursor, setFocusableWindowState, setLocationRelativeTo, toBack, toFront
 
Methods inherited from class java.awt.Container
add, add, add, add, add, addContainerListener, addPropertyChangeListener, addPropertyChangeListener, applyComponentOrientation, areFocusTraversalKeysSet, countComponents, deliverEvent, doLayout, findComponentAt, findComponentAt, getAlignmentX, getAlignmentY, getComponent, getComponentAt, getComponentAt, getComponentCount, getComponents, getContainerListeners, getFocusTraversalKeys, getFocusTraversalPolicy, getInsets, getLayout, getMaximumSize, getMinimumSize, insets, invalidate, isAncestorOf, isFocusCycleRoot, isFocusCycleRoot, isFocusTraversalPolicySet, layout, list, list, locate, minimumSize, paint, paintComponents, preferredSize, print, printComponents, processContainerEvent, remove, removeAll, removeContainerListener, removeNotify, setFocusCycleRoot, setFocusTraversalKeys, setFocusTraversalPolicy, setFont, swapComponents, transferFocusDownCycle, validate, validateTree
 
Methods inherited from class java.awt.Component
action, add, addComponentListener, addFocusListener, addHierarchyBoundsListener, addHierarchyListener, addInputMethodListener, addKeyListener, addMouseListener, addMouseMotionListener, addMouseWheelListener, bounds, checkImage, checkImage, coalesceEvents, contains, contains, createImage, createImage, createVolatileImage, createVolatileImage, disable, disableEvents, dispatchEvent, enable, enable, enableEvents, enableInputMethods, firePropertyChange, firePropertyChange, firePropertyChange, getBackground, getBounds, getBounds, getColorModel, getComponentListeners, getComponentOrientation, getCursor, getDropTarget, getFocusCycleRootAncestor, getFocusListeners, getFocusTraversalKeysEnabled, getFont, getFontMetrics, getForeground, getGraphics, getHeight, getHierarchyBoundsListeners, getHierarchyListeners, getIgnoreRepaint, getInputContext, getInputMethodListeners, getInputMethodRequests, getKeyListeners, getLocation, getLocation, getLocationOnScreen, getMouseListeners, getMouseMotionListeners, getMouseWheelListeners, getName, getParent, getPeer, getPropertyChangeListeners, getPropertyChangeListeners, getSize, getSize, getTreeLock, getWidth, getX, getY, gotFocus, handleEvent, hasFocus, imageUpdate, inside, isBackgroundSet, isCursorSet, isDisplayable, isDoubleBuffered, isEnabled, isFocusable, isFocusOwner, isFocusTraversable, isFontSet, isForegroundSet, isLightweight, isOpaque, isValid, isVisible, keyDown, keyUp, list, list, list, location, lostFocus, mouseDown, mouseDrag, mouseEnter, mouseExit, mouseMove, mouseUp, move, nextFocus, paintAll, prepareImage, prepareImage, printAll, processComponentEvent, processFocusEvent, processHierarchyBoundsEvent, processHierarchyEvent, processInputMethodEvent, processKeyEvent, processMouseEvent, processMouseMotionEvent, processMouseWheelEvent, remove, removeComponentListener, removeFocusListener, removeHierarchyBoundsListener, removeHierarchyListener, removeInputMethodListener, removeKeyListener, removeMouseListener, removeMouseMotionListener, removeMouseWheelListener, removePropertyChangeListener, removePropertyChangeListener, repaint, repaint, repaint, repaint, requestFocus, requestFocus, requestFocusInWindow, requestFocusInWindow, reshape, resize, resize, setBackground, setBounds, setBounds, setComponentOrientation, setDropTarget, setEnabled, setFocusable, setFocusTraversalKeysEnabled, setForeground, setIgnoreRepaint, setLocale, setLocation, setLocation, setName, setSize, setSize, show, size, toString, transferFocus, transferFocusBackward, transferFocusUpCycle
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

autofilter_dialog

public AutofilterDialog autofilter_dialog

invalid

private boolean invalid
Whether the selection has changed since the last time we built the model (because it has been hidden and theres no point refreshing a model you can't see!).


records

private org.greenstone.gatherer.file.FileNode[] records
An array holding the most recent list of paths selected (plus some nulls for those paths removed).


self

private MetaAuditFrame self
A reference to ourselves so that inner classes can interact with us.


table

private MetaAuditTable table
The table in which the metadata is shown.


SIZE

private static final java.awt.Dimension SIZE
The default size for the metaaudit dialog.

Constructor Detail

MetaAuditFrame

public MetaAuditFrame(org.greenstone.gatherer.util.TreeSynchronizer tree_sync,
                      org.greenstone.gatherer.file.FileNode[] records)
Constructor.

Method Detail

destroy

public void destroy()
Destructor.


display

public void display()
Display the dialog on screen.


setRecords

public void setRecords(org.greenstone.gatherer.file.FileNode[] records)

valueChanged

public void valueChanged(javax.swing.event.TreeSelectionEvent event)
This method is called whenever the selection within the collection tree changes. This causes the table to be rebuilt with a new model.

Specified by:
valueChanged in interface javax.swing.event.TreeSelectionListener

wait

public void wait(boolean waiting)

rebuildModel

private void rebuildModel()
Rebuild the metaaudit table model using the current collection tree selection.