[skycastle-commits] SF.net SVN: skycastle:[591] trunk/skycastle/modules

Revision: 591
          http://skycastle.svn.sourceforge.net/skycastle/?rev=591&view=rev
Author:   zzorn
Date:     2008-09-14 09:55:18 +0000 (Sun, 14 Sep 2008)

Log Message:
-----------
Fixed and implemented the Library system, now has unit tests and the file tome 
source also works.

Modified Paths:
--------------
    
trunk/skycastle/modules/scratchpad/src/main/java/org/skycastle/scratchpad/sketch/screen/TextureBufferedScreen.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/ParameterChecker.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/file/FileUtil.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/AbstractLibraryNode.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/Library.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/LibraryImpl.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/LibraryLocation.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/LibraryLocationImpl.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/Shelf.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/Tome.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/TomeImpl.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/tomesources/AbstractTomeSource.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/tomesources/FilesystemTomeSource.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/tomesources/MemoryTomeSource.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/tomesources/TomeSource.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/view/ListLibraryView.java

Added Paths:
-----------
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/file/RejectedFileFilter.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/example/
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/example/LibraryExample.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/view/DefaultLibraryViewModel.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/view/LibraryViewModel.java
    trunk/skycastle/modules/utils/src/test/java/org/skycastle/util/library/
    
trunk/skycastle/modules/utils/src/test/java/org/skycastle/util/library/LibraryTest.java

Modified: 
trunk/skycastle/modules/scratchpad/src/main/java/org/skycastle/scratchpad/sketch/screen/TextureBufferedScreen.java
===================================================================
--- 
trunk/skycastle/modules/scratchpad/src/main/java/org/skycastle/scratchpad/sketch/screen/TextureBufferedScreen.java
  2008-08-26 23:15:37 UTC (rev 590)
+++ 
trunk/skycastle/modules/scratchpad/src/main/java/org/skycastle/scratchpad/sketch/screen/TextureBufferedScreen.java
  2008-09-14 09:55:18 UTC (rev 591)
@@ -60,9 +60,11 @@
             GameTaskQueueManager.getManager().getQueue( GameTaskQueue.RENDER 
).enqueue( new Callable<Object>()
             {
 
-                public Object call() throws Exception
+                public Object call()
+                        throws Exception
                 {
                     final Camera originalCamera = 
myDisplaySystem.getRenderer().getCamera();
+
                     initCamera( originalCamera,
                                 myTextureRenderer.getCamera() );
 /*
@@ -158,6 +160,9 @@
 
     private void initCamera( final Camera originalCamera, final Camera 
cameraToUpdate )
     {
+        ParameterChecker.checkNotNull( originalCamera, "originalCamera" );
+        ParameterChecker.checkNotNull( cameraToUpdate, "cameraToUpdate" );
+
         // Copy camera settings
         JmeUtils.copyCameraSettings( originalCamera, cameraToUpdate );
 

Modified: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/ParameterChecker.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/ParameterChecker.java
        2008-08-26 23:15:37 UTC (rev 590)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/ParameterChecker.java
        2008-09-14 09:55:18 UTC (rev 591)
@@ -379,6 +379,25 @@
         }
     }
 
+    /**
+     * Checks that the specified string is not null and not empty.
+     *
+     * @param s    the string to test
+     * @param name a name to use for the string in exception messages.
+     *
+     * @throws IllegalArgumentException if the string is null or empty.
+     */
+    public static void checkNotEmpty( final String s, final String name )
+            throws IllegalArgumentException
+    {
+        checkNotNull( s, name );
+
+        if ( s.isEmpty() )
+        {
+            throwIllegalArgumentException( name, s, "not be empty" );
+        }
+    }
+
     //======================================================================
     // Private Methods
 

Modified: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/file/FileUtil.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/file/FileUtil.java
   2008-08-26 23:15:37 UTC (rev 590)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/file/FileUtil.java
   2008-09-14 09:55:18 UTC (rev 591)
@@ -341,15 +341,15 @@
     }
 
 
-    private static void iterateDirectory( final File currentDirectory,
-                                          final List<String> relativePath,
-                                          final FileProcessor fileProcessor,
-                                          final boolean recursive )
+    public static void iterateDirectory( final File currentDirectory,
+                                         final List<String> relativePath,
+                                         final FileProcessor fileProcessor,
+                                         final boolean recursive )
     {
         // Check that the directory is valid
         if ( currentDirectory != null &&
              currentDirectory.isDirectory() &&
-                                            currentDirectory.canRead() )
+             currentDirectory.canRead() )
         {
             // Get acceptable files
             File[] files = currentDirectory.listFiles( new FileFilter()

Copied: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/file/RejectedFileFilter.java
 (from rev 590, 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/file/ExtensionFileFilter.java)
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/file/RejectedFileFilter.java
                         (rev 0)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/file/RejectedFileFilter.java
 2008-09-14 09:55:18 UTC (rev 591)
@@ -0,0 +1,62 @@
+package org.skycastle.util.file;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * A {@link java.io.FileFilter} that filters out files with the specified 
names.  Handly for excluding .svn directories etc.
+ *
+ * @author Hans Haggstrom
+ */
+public final class RejectedFileFilter
+        implements FileFilter
+{
+
+    //======================================================================
+    // Private Fields
+
+    private final List<String> myRejectedNames;
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Constructors
+
+    /**
+     * @param rejectedNames the file names that should be rejected.
+     */
+    public RejectedFileFilter( final String... rejectedNames )
+    {
+        this( Arrays.asList( rejectedNames ) );
+    }
+
+    /**
+     * @param rejectedNames the file names that should be rejected.
+     */
+    public RejectedFileFilter( final Collection<String> rejectedNames )
+    {
+        myRejectedNames = new ArrayList<String>( rejectedNames );
+    }
+
+    //----------------------------------------------------------------------
+    // FileFilter Implementation
+
+    public boolean accept( final File pathname )
+    {
+        for ( String rejectedName : myRejectedNames )
+        {
+            if ( pathname.getName().equalsIgnoreCase( rejectedName ) )
+            {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+}
\ No newline at end of file


Property changes on: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/file/RejectedFileFilter.java
___________________________________________________________________
Added: svn:mergeinfo
   + 

Modified: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/AbstractLibraryNode.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/AbstractLibraryNode.java
     2008-08-26 23:15:37 UTC (rev 590)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/AbstractLibraryNode.java
     2008-09-14 09:55:18 UTC (rev 591)
@@ -48,5 +48,4 @@
         myLocation = location;
         myDescription = description;
     }
-
 }

Modified: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/Library.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/Library.java
 2008-08-26 23:15:37 UTC (rev 590)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/Library.java
 2008-09-14 09:55:18 UTC (rev 591)
@@ -16,7 +16,7 @@
     /**
      * @param location the {@link LibraryLocation} to get nodes at.
      *
-     * @return a read only list with the nodes at the specified location,
+     * @return a read only list with the currently loaded nodes at the 
specified location,
      *         or an empty list if there are no nodes at the specified 
location.
      */
     List<LibraryNode<T>> getNodesAt( LibraryLocation location );
@@ -25,7 +25,6 @@
      * Loads the nodes under the specified library location if it is a shelf.  
A callback will be called for each addition.
      *
      * @param location the {@link LibraryLocation} to load nodes at.
-     *
      */
     void refreshNodesAt( LibraryLocation location );
 
@@ -92,4 +91,5 @@
      */
     LibraryNode<T> getLibraryNode( LibraryLocation location );
 
+    String getNameSeparator();
 }

Modified: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/LibraryImpl.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/LibraryImpl.java
     2008-08-26 23:15:37 UTC (rev 590)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/LibraryImpl.java
     2008-09-14 09:55:18 UTC (rev 591)
@@ -79,7 +79,14 @@
 
     public List<LibraryNode<T>> getNodesAt( final LibraryLocation location )
     {
-        throw new UnsupportedOperationException( "This method has not yet been 
implemented." ); // IMPLEMENT
+        final List<LibraryNode<T>> result = new ArrayList<LibraryNode<T>>();
+
+        for ( TomeSource<T> tomeSource : myTomeSources )
+        {
+            tomeSource.getNodesAtLocation( location, result );
+        }
+
+        return result;
     }
 
     public void refreshNodesAt( final LibraryLocation location )

Modified: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/LibraryLocation.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/LibraryLocation.java
 2008-08-26 23:15:37 UTC (rev 590)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/LibraryLocation.java
 2008-09-14 09:55:18 UTC (rev 591)
@@ -11,16 +11,46 @@
 public interface LibraryLocation
 {
 
+    /**
+     * @return name of the leaf node.
+     */
     String getName();
 
+    /**
+     * @return the names of the shelfs up to but not including the leaf node, 
separated by the default file separator.
+     */
+    // TODO: Use a non sysetem specific separator.
     String getPath();
 
+    /**
+     * @return the names of the shelfs and the leaf node, separated by the 
default file separator.
+     */
+    // TODO: Use a non sysetem specific separator.
     String getPathAndName();
 
+    /**
+     * @param separator the separator character(s) to use between shelfs and 
tomes
+     *
+     * @return the names of the shelfs and the tome, separated by the 
separator.
+     */
     String getPathAndName( String separator );
 
+    /**
+     * @return the names of the shelfs and the final node, as a list of 
strings.
+     */
     List<String> getPathAndNodeNamesAsList();
 
+    /**
+     * @param baseLocation the location under which the topmost shelfs are.
+     *
+     * @return a file with the path being made up of the baseLocation and the 
shelfs and node names.
+     */
     File getAsFile( File baseLocation );
 
+    /**
+     * @return true if this node is a child node of the specified location.
+     */
+    boolean isLocatedDirectlyUnder( LibraryLocation location );
+
+    LibraryLocation getParentLocation();
 }

Modified: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/LibraryLocationImpl.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/LibraryLocationImpl.java
     2008-08-26 23:15:37 UTC (rev 590)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/LibraryLocationImpl.java
     2008-09-14 09:55:18 UTC (rev 591)
@@ -26,6 +26,7 @@
     // Private Constants
 
     private static final long serialVersionUID = 1L;
+    private static final String SEPARATOR = File.separator;
 
     //======================================================================
     // Public Methods
@@ -34,6 +35,14 @@
     // Constructors
 
     /**
+     * Creates the root location.
+     */
+    public LibraryLocationImpl()
+    {
+        myPathAndNodeName = new ArrayList<String>( 0 );
+    }
+
+    /**
      * @param pathAndNodeName the path from the library root, including the 
node name as the last element.
      */
     public LibraryLocationImpl( final List<String> pathAndNodeName )
@@ -41,14 +50,34 @@
         ParameterChecker.checkNotNull( pathAndNodeName, "pathAndNodeName" );
 
         myPathAndNodeName = new ArrayList<String>( pathAndNodeName );
+
+        checkPath( myPathAndNodeName );
     }
 
+    private void checkPath( final List<String> pathAndNodeName )
+    {
+        for ( String pathNodeName : pathAndNodeName )
+        {
+            ParameterChecker.checkNotEmpty( pathNodeName, "a node in the path 
name" );
+        }
+    }
+
     public LibraryLocationImpl( final String pathAndNodeName, final String 
separator )
     {
         ParameterChecker.checkNotNull( pathAndNodeName, "pathAndNodeName" );
         ParameterChecker.checkNotNull( separator, "separator" );
 
-        myPathAndNodeName = new ArrayList<String>( Arrays.asList( 
pathAndNodeName.split( separator ) ) );
+        if ( pathAndNodeName.isEmpty() )
+        {
+            myPathAndNodeName = new ArrayList<String>( 0 );
+        }
+        else
+        {
+
+            myPathAndNodeName = new ArrayList<String>( Arrays.asList( 
pathAndNodeName.split( separator ) ) );
+        }
+
+        checkPath( myPathAndNodeName );
     }
 
 
@@ -63,6 +92,8 @@
 
         myPathAndNodeName = new ArrayList<String>( path );
         myPathAndNodeName.add( nodeName );
+
+        checkPath( myPathAndNodeName );
     }
 
     //----------------------------------------------------------------------
@@ -84,7 +115,7 @@
     {
         if ( myPathAndNodeName.size() >= 2 )
         {
-            return StringUtilities.collectionAsString( 
myPathAndNodeName.subList( 0, myPathAndNodeName.size() - 1 ), "", 
File.separator, "", "" );
+            return StringUtilities.collectionAsString( 
myPathAndNodeName.subList( 0, myPathAndNodeName.size() - 1 ), "", SEPARATOR, 
"", "" );
         }
         else
         {
@@ -94,7 +125,7 @@
 
     public String getPathAndName()
     {
-        return getPathAndName( File.separator );
+        return getPathAndName( SEPARATOR );
     }
 
     public String getPathAndName( final String separator )
@@ -112,10 +143,37 @@
         ParameterChecker.checkNotNull( baseLocation, "baseLocation" );
 
         return new File( baseLocation.getPath() +
-                         File.separator +
-                         getPathAndName( File.separator ) );
+                         SEPARATOR +
+                         getPathAndName( SEPARATOR ) );
     }
 
+    public boolean isLocatedDirectlyUnder( final LibraryLocation location )
+    {
+        ParameterChecker.checkNotNull( location, "location" );
+
+        final List<String> parentList = location.getPathAndNodeNamesAsList();
+
+        if ( parentList.size() != myPathAndNodeName.size() - 1 )
+        {
+            return false;
+        }
+
+        for ( int i = 0; i < myPathAndNodeName.size() - 1; i++ )
+        {
+            if ( !myPathAndNodeName.get( i ).equals( parentList.get( i ) ) )
+            {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public LibraryLocation getParentLocation()
+    {
+        return new LibraryLocationImpl( getPath(), SEPARATOR );
+    }
+
     //----------------------------------------------------------------------
     // Caononical Methods
 
@@ -148,4 +206,10 @@
         return ( myPathAndNodeName != null ? myPathAndNodeName.hashCode() : 0 
);
     }
 
+    @Override
+    public String toString()
+    {
+        return getPathAndName();
+
+    }
 }

Modified: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/Shelf.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/Shelf.java
   2008-08-26 23:15:37 UTC (rev 590)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/Shelf.java
   2008-09-14 09:55:18 UTC (rev 591)
@@ -30,4 +30,38 @@
         super( location, description );
     }
 
+
+    @Override
+    public boolean equals( final Object o )
+    {
+        if ( this == o )
+        {
+            return true;
+        }
+        if ( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        final AbstractLibraryNode that = (AbstractLibraryNode) o;
+
+        if ( getLocation() != null ? !getLocation().equals( that.getLocation() 
) : that.getLocation() != null )
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return getLocation() != null ? getLocation().hashCode() : 0;
+    }
+
+    @Override
+    public String toString()
+    {
+        return "Shelf{ " + getLocation() + ", " + getDescription() + " }";
+    }
 }

Modified: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/Tome.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/Tome.java
    2008-08-26 23:15:37 UTC (rev 590)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/Tome.java
    2008-09-14 09:55:18 UTC (rev 591)
@@ -28,16 +28,5 @@
      */
     long getLastModificationTime();
 
-/*
-    */
-/**
-     * @param preferredSize the preferred size for the preview in pixels.
-     *
-     * @return a preview or description of this {@link Tome}.
-     */
-/*
-    // TODO: Who provides the previews?  Maybe we can do the views completely 
separated.
-    JComponent getPreview( Dimension preferredSize );
-*/
 
 }

Modified: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/TomeImpl.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/TomeImpl.java
        2008-08-26 23:15:37 UTC (rev 590)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/TomeImpl.java
        2008-09-14 09:55:18 UTC (rev 591)
@@ -90,4 +90,16 @@
         myLastModifcationTime = lastModifcationTime;
     }
 
+
+    @Override
+    public String toString()
+    {
+        return "Tome{ location:" + getLocation() +
+               ", description: " + getDescription() +
+               ", lastmodified: " + getLastModificationTime() +
+               ", content: " + getContent() +
+               ", tomeSource: " + myTomeSource +
+               " }";
+
+    }
 }

Added: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/example/LibraryExample.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/example/LibraryExample.java
                          (rev 0)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/example/LibraryExample.java
  2008-09-14 09:55:18 UTC (rev 591)
@@ -0,0 +1,63 @@
+package org.skycastle.util.library.example;
+
+import org.skycastle.util.ImageUtils;
+import org.skycastle.util.file.ExtensionFileFilter;
+import org.skycastle.util.file.RejectedFileFilter;
+import org.skycastle.util.library.LibraryImpl;
+import org.skycastle.util.library.LibraryLocationImpl;
+import org.skycastle.util.library.Loader;
+import org.skycastle.util.library.Shelf;
+import org.skycastle.util.library.tomesources.FilesystemTomeSource;
+import org.skycastle.util.library.tomesources.MemoryTomeSource;
+import org.skycastle.util.library.view.ListLibraryView;
+import org.skycastle.util.simpleui.SimpleFrame;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.File;
+
+/**
+ * @author Hans Haggstrom
+ */
+public class LibraryExample
+{
+    public static void main( String[] args )
+    {
+        final MemoryTomeSource<String> memoryTomeSource = new 
MemoryTomeSource<String>();
+        memoryTomeSource.addLibraryNode( new Shelf<String>( new 
LibraryLocationImpl( "TestShelf", "/" ) ) );
+        memoryTomeSource.addLibraryNode( new Shelf<String>( new 
LibraryLocationImpl( "TestShelf/TestShef", "/" ) ) );
+        memoryTomeSource.addLibraryNode( new Shelf<String>( new 
LibraryLocationImpl( "TestShelf/TestShef/Tes", "/" ) ) );
+
+
+        final LibraryImpl library = new LibraryImpl( 
createBufferedImageFileSystemTomeSource( "media" ), memoryTomeSource );
+        final LibraryLocationImpl libraryLocation = new LibraryLocationImpl();
+        final ListLibraryView listLibraryView = new ListLibraryView( 
libraryLocation, library );
+
+
+        new SimpleFrame( listLibraryView.getUi() );
+    }
+
+    private static FilesystemTomeSource<BufferedImage> 
createBufferedImageFileSystemTomeSource( final String rootPath )
+    {
+        return new FilesystemTomeSource<BufferedImage>( false,
+                                                        new File( rootPath ),
+                                                        
createBufferedImageLoader(),
+                                                        new 
ExtensionFileFilter( ImageIO.getReaderFileSuffixes() ),
+                                                        new 
RejectedFileFilter( ".svn", ".cvs" ) );
+
+    }
+
+    private static Loader<BufferedImage> createBufferedImageLoader()
+    {
+        return new Loader<BufferedImage>()
+        {
+
+            public BufferedImage load( final File inputFile )
+            {
+                return ImageUtils.loadImage( inputFile.getPath() );
+            }
+
+        };
+    }
+
+}

Modified: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/tomesources/AbstractTomeSource.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/tomesources/AbstractTomeSource.java
  2008-08-26 23:15:37 UTC (rev 590)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/tomesources/AbstractTomeSource.java
  2008-09-14 09:55:18 UTC (rev 591)
@@ -3,13 +3,13 @@
 import org.skycastle.util.ParameterChecker;
 import org.skycastle.util.library.*;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
+import java.util.Map.Entry;
 
 /**
  * @author Hans Haggstrom
  */
+// TODO: Use a proper cache later that empties out unused nodes.
 public abstract class AbstractTomeSource<T>
         implements TomeSource<T>
 {
@@ -20,6 +20,7 @@
 
     private final List<TomeSourceListener<T>> myListeners = new 
ArrayList<TomeSourceListener<T>>();
     private final boolean myAllowsModifications;
+    private final Map<LibraryLocation, LibraryNode<T>> myCache = new 
HashMap<LibraryLocation, LibraryNode<T>>( 101 );
 
 /*
     private Library<T> myLibrary = null;
@@ -107,11 +108,11 @@
         notifyNodesUpdated( Collections.singletonList( changedNode ), 
updateType );
     }
 
-/*
+    /*
     */
 /**
-     * @return the {@link Library} that this {@link TomeSource} is providing 
{@link Tome}s for.
-     */
+ * @return the {@link Library} that this {@link TomeSource} is providing 
{@link Tome}s for.
+ */
 /*
     protected final Library<T> getLibrary()
     {
@@ -121,8 +122,7 @@
 
     //======================================================================
     // Private Methods
-
-    protected void checkModification( final LibraryNode<T> node, final String 
modification )
+    protected final void checkModification( final LibraryNode<T> node, final 
String modification )
     {
         if ( !allowsMofifications() )
         {
@@ -130,4 +130,66 @@
         }
     }
 
+    public final void getNodesAtLocation( final LibraryLocation 
libraryLocation, final List<LibraryNode<T>> nodesOut )
+    {
+        getNodesFromCache( libraryLocation, nodesOut );
+    }
+
+
+    protected final void getNodesFromCache( final LibraryLocation 
libraryLocation, final List<LibraryNode<T>> nodesOut )
+    {
+        for ( Entry<LibraryLocation, LibraryNode<T>> nodeEntry : 
myCache.entrySet() )
+        {
+            if ( nodeEntry.getKey().isLocatedDirectlyUnder( libraryLocation ) )
+            {
+                nodesOut.add( nodeEntry.getValue() );
+            }
+        }
+    }
+
+    protected final LibraryNode<T> getNodeFromCache( final LibraryLocation 
nodeLocation )
+    {
+        return myCache.get( nodeLocation );
+    }
+
+    protected final void addNodeToCache( final LibraryNode<T> node )
+    {
+        ParameterChecker.checkNotNull( node, "node" );
+
+        final boolean contained = myCache.containsKey( node.getLocation() );
+
+        myCache.put( node.getLocation(), node );
+
+        notifyNodeUpdated( node, contained ? UpdateType.MODIFIED : 
UpdateType.ADDED );
+    }
+
+    protected final void removeNodeFromCache( final LibraryNode<T> node )
+    {
+        ParameterChecker.checkNotNull( node, "node" );
+
+        if ( myCache.containsKey( node.getLocation() ) )
+        {
+            myCache.remove( node.getLocation() );
+
+            notifyNodeUpdated( node, UpdateType.REMOVED );
+        }
+    }
+
+    protected final boolean hasNewerCachedTomeVersion( final LibraryLocation 
location, final long timeToTestAgainst )
+    {
+        final LibraryNode<T> existingEntry = getNodeFromCache( location );
+
+        if ( existingEntry != null &&
+             existingEntry instanceof Tome )
+        {
+            final Tome tome = (Tome) existingEntry;
+            if ( timeToTestAgainst <= tome.getLastModificationTime() )
+            {
+                // Already exists an up-to-date version in the cache.
+                return true;
+            }
+        }
+
+        return false;
+    }
 }

Modified: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/tomesources/FilesystemTomeSource.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/tomesources/FilesystemTomeSource.java
        2008-08-26 23:15:37 UTC (rev 590)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/tomesources/FilesystemTomeSource.java
        2008-09-14 09:55:18 UTC (rev 591)
@@ -9,17 +9,13 @@
 import java.io.File;
 import java.io.FileFilter;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 /**
  * A {@link TomeSource} that loads tomes from under a specified root directory 
in the filesystem.
  *
  * @author Hans Haggstrom
  */
-// TODO: Need to change the logic of how tomes are accessed completely, so 
that we don't need to do a complete file system scan on startup.
-// Instead tomes should be loaded on demand, when the shelf they are in is 
listed.
 public final class FilesystemTomeSource<T>
         extends AbstractTomeSource<T>
 {
@@ -27,8 +23,6 @@
     //======================================================================
     // Private Fields
 
-    // TODO: Use a proper cache later that empties out unused nodes.
-    private final Map<LibraryLocation, LibraryNode<T>> myCache = new 
HashMap<LibraryLocation, LibraryNode<T>>( 101 );
 
     private final File myRootShelfDirectory;
     private final FileFilter myShelfFilter;
@@ -117,6 +111,28 @@
     }
 
     /**
+     * Creates a new {@link FilesystemTomeSource} that includes all 
directories under the root directory.
+     *
+     * @param allowModifications if true, changes can be made to the {@link 
Tome}s provided by this {@link TomeSource} and the changes will
+     *                           be saved back to the file system using the 
{@link Saver}, if false the {@link Tome}s provided by this
+     *                           {@link TomeSource} are all read-only, and the 
file system is not modified
+     * @param rootShelfDirectory the path of the directory that is treated as 
the root shelf by this {@link TomeSource}.
+     *                           All non-hidden directories and files under it 
that match specified patterns are visible as {@link Shelf}s and
+     *                           {@link Tome}s respectively.
+     * @param loader             a {@link Loader} that can load {@link Tome} 
contents from a file.
+     * @param tomeFilter         filter used to check which files should be 
treated as {@link Tome}s.
+     * @param shelfFilter        filter used to check which directories should 
be treated as {@link Shelf}s.
+     */
+    public FilesystemTomeSource( final boolean allowModifications,
+                                 final File rootShelfDirectory,
+                                 final Loader<T> loader,
+                                 final FileFilter tomeFilter,
+                                 final FileFilter shelfFilter )
+    {
+        this( allowModifications, rootShelfDirectory, loader, null, 
tomeFilter, shelfFilter );
+    }
+
+    /**
      * Creates a new {@link FilesystemTomeSource}.
      *
      * @param allowModifications if true, changes can be made to the {@link 
Tome}s provided by this {@link TomeSource} and the changes will
@@ -165,13 +181,13 @@
                                          File.separator +
                                          libraryLocation.getPathAndName( 
File.separator ) );
 
-        FileUtil.iterateFiles( directory, myFileProcessor );
+        FileUtil.iterateDirectory( directory, 
libraryLocation.getPathAndNodeNamesAsList(), myFileProcessor, false );
     }
 
     public LibraryNode<T> getNode( final LibraryLocation nodeLocation )
     {
         // First try to get from cache
-        final LibraryNode<T> libraryNode = myCache.get( nodeLocation );
+        final LibraryNode<T> libraryNode = getNodeFromCache( nodeLocation );
         if ( libraryNode != null )
         {
             return libraryNode;
@@ -203,10 +219,8 @@
     {
         final Shelf<T> shelf = new Shelf<T>( location, null );
 
-        myCache.put( shelf.getLocation(), shelf );
+        addNodeToCache( shelf );
 
-        notifyNodeUpdated( shelf, UpdateType.ADDED );
-
         return shelf;
     }
 
@@ -257,30 +271,15 @@
                                                   file.lastModified(),
                                                   null );
 
-        myCache.put( location, tome );
+        addNodeToCache( tome );
 
-        notifyNodeUpdated( tome, UpdateType.ADDED );
-
         return tome;
     }
 
 
     private boolean hasUpToDateCachedVersion( final File file, final 
LibraryLocation location )
     {
-        final LibraryNode<T> existingEntry = myCache.get( location );
-
-        if ( existingEntry != null &&
-             existingEntry instanceof Tome )
-        {
-            final Tome tome = (Tome) existingEntry;
-            if ( file.lastModified() <= tome.getLastModificationTime() )
-            {
-                // Already exists an up-to-date version in the cache.
-                return true;
-            }
-        }
-
-        return false;
+        return hasNewerCachedTomeVersion( location, file.lastModified() );
     }
 
 

Modified: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/tomesources/MemoryTomeSource.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/tomesources/MemoryTomeSource.java
    2008-08-26 23:15:37 UTC (rev 590)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/tomesources/MemoryTomeSource.java
    2008-09-14 09:55:18 UTC (rev 591)
@@ -1,11 +1,11 @@
 package org.skycastle.util.library.tomesources;
 
 import org.skycastle.util.ParameterChecker;
-import org.skycastle.util.library.*;
+import org.skycastle.util.library.Library;
+import org.skycastle.util.library.LibraryLocation;
+import org.skycastle.util.library.LibraryNode;
+import org.skycastle.util.library.Tome;
 
-import java.util.HashMap;
-import java.util.Map;
-
 /**
  * A simple in-memory {@link Tome} storage.
  * <p/>
@@ -20,7 +20,6 @@
     //======================================================================
     // Private Fields
 
-    private final Map<LibraryLocation, LibraryNode<T>> myLibraryNodes = new 
HashMap<LibraryLocation, LibraryNode<T>>( 101 );
 
     //======================================================================
     // Public Methods
@@ -44,18 +43,9 @@
         // Nothing to do.
     }
 
-    public Tome<T> getNode( final LibraryLocation tomeLocation )
+    public LibraryNode<T> getNode( final LibraryLocation location )
     {
-        final LibraryNode<T> libraryNode = myLibraryNodes.get( tomeLocation );
-
-        if ( libraryNode instanceof Tome )
-        {
-            return (Tome<T>) libraryNode;
-        }
-        else
-        {
-            return null;
-        }
+        return getNodeFromCache( location );
     }
 
     //----------------------------------------------------------------------
@@ -66,11 +56,7 @@
         checkModification( node, "add" );
         ParameterChecker.checkNotNull( node, "node" );
 
-        final boolean contained = myLibraryNodes.containsKey( 
node.getLocation() );
-
-        myLibraryNodes.put( node.getLocation(), node );
-
-        notifyNodeUpdated( node, contained ? UpdateType.MODIFIED : 
UpdateType.ADDED );
+        addNodeToCache( node );
     }
 
     public final void removeLibraryNode( LibraryNode<T> node )
@@ -78,12 +64,8 @@
         checkModification( node, "remove" );
         ParameterChecker.checkNotNull( node, "node" );
 
-        if ( myLibraryNodes.containsKey( node.getLocation() ) )
-        {
-            myLibraryNodes.remove( node.getLocation() );
-
-            notifyNodeUpdated( node, UpdateType.REMOVED );
-        }
+        removeNodeFromCache( node );
     }
 
+
 }

Modified: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/tomesources/TomeSource.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/tomesources/TomeSource.java
  2008-08-26 23:15:37 UTC (rev 590)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/tomesources/TomeSource.java
  2008-09-14 09:55:18 UTC (rev 591)
@@ -2,6 +2,8 @@
 
 import org.skycastle.util.library.*;
 
+import java.util.List;
+
 /**
  * A way to get {@link Tome}s for a {@link Library}.
  * One {@link Library} may have secveral {@link TomeSource}s.
@@ -20,28 +22,26 @@
 public interface TomeSource<T>
 {
 
-/*
-    */
-/**
-     * @return retrieves the {@link LibraryNode}s at the specified {@link 
LibraryLocation}, or an empty list if there are none at that location.
+    /**
+     * Retrieves the {@link LibraryNode}s at the specified {@link 
LibraryLocation}, or an empty list if there are none at that location.
+     *
+     * @param nodesOut the list to add the nodes to.
      */
-/*
-    List<LibraryNode<T>> getNodesAtLocation( LibraryLocation libraryLocation );
-*/
+    void getNodesAtLocation( LibraryLocation libraryLocation, final 
List<LibraryNode<T>> nodesOut );
 
     /**
-     * Retrieves the {@link LibraryNode}s at the specified shelf {@link 
LibraryLocation}, and calls the listener methods for each.
+     * Checks for added or removed {@link LibraryNode}s at the specified shelf 
{@link LibraryLocation}, and calls the listener methods for each.
      * Asynchronous, can do loading and such in a separate thread.
      * Callbacks will be in Swing thread.
      */
     void refreshNodesAtLocation( LibraryLocation shelfLocation );
 
     /**
+     * @param nodeLocation the {@link LibraryLocation} of the {@link 
LibraryNode} to get.
      *
-     * @param nodeLocation the {@link LibraryLocation} of the {@link 
LibraryNode} to get.
      * @return the {@link LibraryNode} at the specified tomeLocation, or null 
if there is no {@link LibraryNode} at that location.
      */
-    LibraryNode<T> getNode(LibraryLocation  nodeLocation);
+    LibraryNode<T> getNode( LibraryLocation nodeLocation );
 
     /**
      * Adds the specified TomeSourceListener.
@@ -65,9 +65,9 @@
 
     */
 /**
-     * Checks to see if there are new tomes or other modifications at the 
specified {@link LibraryLocation}.
-     * Calls the listener method if there are changes.
-     */
+ * Checks to see if there are new tomes or other modifications at the 
specified {@link LibraryLocation}.
+ * Calls the listener method if there are changes.
+ */
 /*
     void refresh( LibraryLocation libraryLocation );
 */

Added: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/view/DefaultLibraryViewModel.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/view/DefaultLibraryViewModel.java
                            (rev 0)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/view/DefaultLibraryViewModel.java
    2008-09-14 09:55:18 UTC (rev 591)
@@ -0,0 +1,134 @@
+package org.skycastle.util.library.view;
+
+import org.skycastle.util.ParameterChecker;
+import org.skycastle.util.library.*;
+
+import javax.swing.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Hans Haggstrom
+ */
+public final class DefaultLibraryViewModel<T>
+        implements LibraryViewModel<T>
+{
+    private final DefaultListModel myListModel = new DefaultListModel();
+
+    private final Library<T> myLibrary;
+    private LibraryLocation myViewedLocation;
+    private final TomeSourceListener<T> myLibraryListener = 
createLibraryListener();
+
+    private final List<LibraryNode<T>> myCurrentlyVisibleNodes = new 
ArrayList<LibraryNode<T>>();
+
+    public DefaultListModel getListModel()
+    {
+        return myListModel;
+    }
+
+    public DefaultLibraryViewModel( final Library library, final 
LibraryLocation viewedLocation )
+    {
+        ParameterChecker.checkNotNull( library, "library" );
+
+        myLibrary = library;
+        myLibrary.addLibraryListener( myLibraryListener );
+
+        setViewedLocation( viewedLocation );
+    }
+
+    public LibraryLocation getViewedLocation()
+    {
+        return myViewedLocation;
+    }
+
+    public void setViewedLocation( final LibraryLocation viewedLocation )
+    {
+        ParameterChecker.checkNotNull( viewedLocation, "viewedLocation" );
+
+        myViewedLocation = viewedLocation;
+
+        myCurrentlyVisibleNodes.clear();
+        myListModel.clear();
+
+        updateListModel();
+    }
+
+    public void onItemActivated( final LibraryNode<T> selectedValue )
+    {
+        if ( selectedValue instanceof Shelf )
+        {
+            Shelf<T> shelf = (Shelf<T>) selectedValue;
+
+            setViewedLocation( shelf.getLocation() );
+        }
+        else if ( selectedValue instanceof Tome )
+        {
+            Tome<T> tome = (Tome<T>) selectedValue;
+
+            // TODO: Notify listener about tome activation
+            throw new UnsupportedOperationException( "This method has not yet 
been implemented." ); // IMPLEMENT
+        }
+    }
+
+
+    private void updateListModel()
+    {
+        for ( LibraryNode<T> node : myLibrary.getNodesAt( myViewedLocation ) )
+        {
+            addNode( node );
+        }
+
+        myLibrary.refreshNodesAt( myViewedLocation );
+    }
+
+    private void addNode( final LibraryNode<T> node )
+    {
+        if ( !myCurrentlyVisibleNodes.contains( node ) )
+        {
+            myCurrentlyVisibleNodes.add( node );
+            myListModel.addElement( node );
+        }
+    }
+
+    private TomeSourceListener<T> createLibraryListener()
+    {
+        return new TomeSourceListener<T>()
+        {
+            public void onUpdate( final List<LibraryNode<T>> changedNodes, 
final UpdateType updateType )
+            {
+                for ( LibraryNode<T> changedNode : changedNodes )
+                {
+                    if ( changedNode.getLocation().isLocatedDirectlyUnder( 
myViewedLocation ) )
+                    {
+                        switch ( updateType )
+                        {
+                            case ADDED:
+
+                                addNode( changedNode );
+                                break;
+
+                            case MODIFIED:
+                                break;
+
+                            case REMOVED:
+                                removeNode( changedNode );
+                                break;
+                        }
+                    }
+                }
+            }
+        };
+    }
+
+    private void removeNode( final LibraryNode<T> node )
+    {
+        if ( myCurrentlyVisibleNodes.contains( node ) )
+        {
+            myCurrentlyVisibleNodes.remove( node );
+            myListModel.removeElement( node );
+        }
+
+
+    }
+
+}

Added: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/view/LibraryViewModel.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/view/LibraryViewModel.java
                           (rev 0)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/view/LibraryViewModel.java
   2008-09-14 09:55:18 UTC (rev 591)
@@ -0,0 +1,22 @@
+package org.skycastle.util.library.view;
+
+import org.skycastle.util.library.LibraryLocation;
+import org.skycastle.util.library.LibraryNode;
+
+import javax.swing.*;
+
+/**
+ * @author Hans Haggstrom
+ */
+public interface LibraryViewModel<T>
+{
+
+
+    DefaultListModel getListModel();
+
+    LibraryLocation getViewedLocation();
+
+    void setViewedLocation( LibraryLocation viewedLocation );
+
+    void onItemActivated( final LibraryNode<T> selectedValue );
+}

Modified: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/view/ListLibraryView.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/view/ListLibraryView.java
    2008-08-26 23:15:37 UTC (rev 590)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/library/view/ListLibraryView.java
    2008-09-14 09:55:18 UTC (rev 591)
@@ -1,15 +1,92 @@
 package org.skycastle.util.library.view;
 
+import org.skycastle.util.ParameterChecker;
+import org.skycastle.util.library.Library;
+import org.skycastle.util.library.LibraryLocation;
+import org.skycastle.util.library.LibraryNode;
+import org.skycastle.util.library.Shelf;
+
 import javax.swing.*;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
 
 /**
+ * List of the {@link LibraryNode}s in a specific {@link Shelf}.
+ *
  * @author Hans Haggstrom
  */
-public class ListLibraryView
+public final class ListLibraryView<T>
         implements LibraryView
 {
+    private JList myJList;
+    private LibraryViewModel myLibraryViewModel;
+
+
+    /**
+     * @param viewedLocation the {@link LibraryLocation} to initially view.  
All {@link LibraryNode}s located under it are shown.
+     * @param library        the  {@link Library} that the viewed {@link 
Shelf} is in.
+     */
+    public ListLibraryView( final LibraryLocation viewedLocation, final 
Library library )
+    {
+        ParameterChecker.checkNotNull( library, "library" );
+
+        myLibraryViewModel = new DefaultLibraryViewModel( library, 
viewedLocation );
+    }
+
+
+    private JComponent myUi;
+
     public JComponent getUi()
     {
-        throw new UnsupportedOperationException( "This method has not yet been 
implemented." ); // IMPLEMENT
+        if ( myUi == null )
+        {
+            myJList = new JList( myLibraryViewModel.getListModel() );
+
+            myJList.addMouseListener( new MouseAdapter()
+            {
+                @Override
+                public void mouseClicked( final MouseEvent e )
+                {
+                    if ( e.getButton() == MouseEvent.BUTTON1 &&
+                         e.getClickCount() == 2 )
+                    {
+                        activate();
+                    }
+                }
+            } );
+            myJList.addKeyListener( new KeyAdapter()
+            {
+                @Override
+                public void keyPressed( final KeyEvent e )
+                {
+                    if ( e.getKeyCode() == KeyEvent.VK_ENTER )
+                    {
+                        activate();
+                    }
+                    else if ( e.getKeyCode() == KeyEvent.VK_BACK_SPACE )
+                    {
+                        moveToParent();
+                    }
+                }
+            } );
+
+            myUi = new JScrollPane( myJList );
+        }
+
+        return myUi;
     }
+
+    private void moveToParent()
+    {
+        myLibraryViewModel.setViewedLocation( 
myLibraryViewModel.getViewedLocation().getParentLocation() );
+    }
+
+    private void activate()
+    {
+        myLibraryViewModel.onItemActivated( (LibraryNode) 
myJList.getSelectedValue() );
+    }
+
+
 }

Added: 
trunk/skycastle/modules/utils/src/test/java/org/skycastle/util/library/LibraryTest.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/test/java/org/skycastle/util/library/LibraryTest.java
                             (rev 0)
+++ 
trunk/skycastle/modules/utils/src/test/java/org/skycastle/util/library/LibraryTest.java
     2008-09-14 09:55:18 UTC (rev 591)
@@ -0,0 +1,108 @@
+package org.skycastle.util.library;
+
+import junit.framework.TestCase;
+import org.skycastle.util.library.tomesources.MemoryTomeSource;
+import org.skycastle.util.library.view.DefaultLibraryViewModel;
+import org.skycastle.util.library.view.LibraryViewModel;
+
+/**
+ * @author Hans Haggstrom
+ */
+public class LibraryTest
+        extends TestCase
+{
+    private Library<String> myLibrary;
+    private MemoryTomeSource<String> myMemoryTomeSource;
+    private LibraryViewModel<String> myLibraryViewModel;
+    private Shelf<String> myFooNode;
+    private Shelf<String> myRootNode;
+    private Shelf<String> myFooFooerNode;
+    private Shelf<String> myBarNode;
+    private Shelf<String> myBarBarerNode;
+    private Shelf<String> myBarBarerBarestNode;
+    private TomeImpl<String> myFubblyNode;
+
+    public void testSeparator()
+            throws Exception
+    {
+        assertEquals( "/", myLibrary.getNameSeparator() );
+    }
+
+    public void testGet()
+            throws Exception
+    {
+        assertNotNull( myLibrary.getLibraryNode( "foo" ) );
+        assertNotNull( myLibrary.getLibraryNode( "foo/fooer" ) );
+        assertNotNull( myLibrary.getLibraryNode( "foo/fooer/fubbly" ) );
+        assertNotNull( myLibrary.getLibraryNode( "" ) );
+    }
+
+
+    public void testDirectlyUnder()
+            throws Exception
+    {
+        assertTrue( myFooNode.getLocation().isLocatedDirectlyUnder( 
myRootNode.getLocation() ) );
+        assertTrue( myBarNode.getLocation().isLocatedDirectlyUnder( 
myRootNode.getLocation() ) );
+        assertTrue( myFooFooerNode.getLocation().isLocatedDirectlyUnder( 
myFooNode.getLocation() ) );
+        assertTrue( myFubblyNode.getLocation().isLocatedDirectlyUnder( 
myFooFooerNode.getLocation() ) );
+
+        assertFalse( myRootNode.getLocation().isLocatedDirectlyUnder( 
myRootNode.getLocation() ) );
+        assertFalse( myRootNode.getLocation().isLocatedDirectlyUnder( 
myFooNode.getLocation() ) );
+        assertFalse( myFubblyNode.getLocation().isLocatedDirectlyUnder( 
myFooNode.getLocation() ) );
+        assertFalse( myBarNode.getLocation().isLocatedDirectlyUnder( 
myFooNode.getLocation() ) );
+        assertFalse( myFooNode.getLocation().isLocatedDirectlyUnder( 
myBarNode.getLocation() ) );
+
+    }
+
+    public void testLibraryModel()
+            throws Exception
+    {
+        assertEquals( myRootNode.getLocation(), 
myLibraryViewModel.getViewedLocation() );
+
+        assertTrue( myLibraryViewModel.getListModel().contains( myFooNode ) );
+        assertTrue( myLibraryViewModel.getListModel().contains( myBarNode ) );
+
+        myLibraryViewModel.setViewedLocation( myFooNode.getLocation() );
+
+        assertTrue( myLibraryViewModel.getListModel().contains( myFooFooerNode 
) );
+        assertFalse( myLibraryViewModel.getListModel().contains( myBarNode ) );
+
+        myLibraryViewModel.setViewedLocation( myRootNode.getLocation() );
+
+        assertFalse( myLibraryViewModel.getListModel().contains( 
myFooFooerNode ) );
+        assertTrue( myLibraryViewModel.getListModel().contains( myFooNode ) );
+        assertTrue( myLibraryViewModel.getListModel().contains( myBarNode ) );
+    }
+
+
+    @Override
+    protected void setUp()
+            throws Exception
+    {
+        myMemoryTomeSource = new MemoryTomeSource<String>();
+
+        myRootNode = new Shelf<String>( new LibraryLocationImpl() );
+        myFooNode = new Shelf<String>( new LibraryLocationImpl( "foo", "/" ) );
+        myFooFooerNode = new Shelf<String>( new LibraryLocationImpl( 
"foo/fooer", "/" ) );
+        myBarNode = new Shelf<String>( new LibraryLocationImpl( "bar", "/" ) );
+        myBarBarerNode = new Shelf<String>( new LibraryLocationImpl( 
"bar/barer", "/" ) );
+        myBarBarerBarestNode = new Shelf<String>( new LibraryLocationImpl( 
"bar/barer/barest", "/" ) );
+        myFubblyNode = new TomeImpl<String>( new LibraryLocationImpl( 
"foo/fooer/fubbly", "/" ),
+                                             "this is fubbly",
+                                             myMemoryTomeSource,
+                                             100,
+                                             "it is a fubbly" );
+
+        myMemoryTomeSource.addLibraryNode( myRootNode );
+        myMemoryTomeSource.addLibraryNode( myFooNode );
+        myMemoryTomeSource.addLibraryNode( myFooFooerNode );
+        myMemoryTomeSource.addLibraryNode( myBarNode );
+        myMemoryTomeSource.addLibraryNode( myBarBarerNode );
+        myMemoryTomeSource.addLibraryNode( myBarBarerBarestNode );
+        myMemoryTomeSource.addLibraryNode( myFubblyNode );
+
+        myLibrary = new LibraryImpl<String>( myMemoryTomeSource );
+
+        myLibraryViewModel = new DefaultLibraryViewModel<String>( myLibrary, 
new LibraryLocationImpl() );
+    }
+}


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

Other related posts:

  • » [skycastle-commits] SF.net SVN: skycastle:[591] trunk/skycastle/modules