Java 7 is now used.
authorErik Brakkee <erik@brakkee.org>
Sat, 21 Sep 2013 19:46:12 +0000 (21:46 +0200)
committerErik Brakkee <erik@brakkee.org>
Sat, 21 Sep 2013 19:46:12 +0000 (21:46 +0200)
First version of view of album.

pom.xml
src/main/java/org/wamblee/photos/model/filesystem/FileSystemAlbum.java
src/main/java/org/wamblee/photos/wicket/HomePage.html
src/main/java/org/wamblee/photos/wicket/HomePage.java
src/main/java/org/wamblee/photos/wicket/folder.png [new file with mode: 0644]

diff --git a/pom.xml b/pom.xml
index ab055870df09fe3710c557441bbb27a85f9c91a1..9246313d812f0d6ba6bdb2e1a1f51d38e976f831 100644 (file)
--- a/pom.xml
+++ b/pom.xml
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-       <modelVersion>4.0.0</modelVersion>
-       <groupId>org.wamblee.photos</groupId>
-       <artifactId>wamblee-photos</artifactId>
-       <packaging>war</packaging>
-       <version>0.1-SNAPSHOT</version>
-       <name>photos</name>
-       <description>
-         Photos application.
-       </description>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.wamblee.photos</groupId>
+    <artifactId>wamblee-photos</artifactId>
+    <packaging>war</packaging>
+    <version>0.1-SNAPSHOT</version>
+    <name>photos</name>
+    <description>
+        Photos application.
+    </description>
 
-       <properties>
-               <wicket.version>1.4.9</wicket.version>
-               <jetty.version>6.1.4</jetty.version>
-               <utils.version>0.6</utils.version>
-       </properties>
+    <properties>
+        <wicket.version>1.4.9</wicket.version>
+        <jetty.version>6.1.4</jetty.version>
+        <utils.version>0.6</utils.version>
+    </properties>
 
-       <!--
-               TODO <organization> <name>company name</name> <url>company url</url>
-               </organization>
-       -->
-       <url>http://wamblee.org</url>
-       <licenses>
-               <license>
-                       <name>The Apache Software License, Version 2.0</name>
-                       <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
-                       <distribution>repo</distribution>
-               </license>
-       </licenses>
-       <scm>
-               <url>http://wamblee.org/gitweb/photos</url>
-               <connection>scm:git:https://wamblee.org/git/public/photos</connection>
-               <developerConnection>scm:git:https://wamblee.org/git/public/photos</developerConnection>
-       </scm>
-       <developers>
-               <developer>
-                       <email>erik@wamblee.org</email>
-                       <name>Erik Brakkee</name>
-                       <url>http://brakkee.org</url>
-               </developer>
-       </developers>
+    <!--
+        TODO <organization> <name>company name</name> <url>company url</url>
+        </organization>
+    -->
+    <url>http://wamblee.org</url>
+    <licenses>
+        <license>
+            <name>The Apache Software License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+            <distribution>repo</distribution>
+        </license>
+    </licenses>
+    <scm>
+        <url>http://wamblee.org/gitweb/photos</url>
+        <connection>scm:git:https://wamblee.org/git/public/photos</connection>
+        <developerConnection>scm:git:https://wamblee.org/git/public/photos</developerConnection>
+    </scm>
+    <developers>
+        <developer>
+            <email>erik@wamblee.org</email>
+            <name>Erik Brakkee</name>
+            <url>http://brakkee.org</url>
+        </developer>
+    </developers>
 
-       <dependencies>
+    <dependencies>
 
-               <dependency>
-                       <groupId>javax.portlet</groupId>
-                       <artifactId>portlet-api</artifactId>
-                       <version>2.0</version>
-               </dependency>
+        <dependency>
+            <groupId>javax.portlet</groupId>
+            <artifactId>portlet-api</artifactId>
+            <version>2.0</version>
+        </dependency>
 
 
-               <dependency>
-                       <groupId>dom4j</groupId>
-                       <artifactId>dom4j</artifactId>
-                       <version>1.6</version>
-                       <exclusions>
-                               <exclusion>
-                                       <groupId>xml-apis</groupId>
-                                       <artifactId>xml-apis</artifactId>
-                               </exclusion>
-                       </exclusions>
-               </dependency>
-               <dependency>
-                       <groupId>jaxen</groupId>
-                       <artifactId>jaxen</artifactId>
-                       <version>1.1-beta-9</version>
-                       <exclusions>
-                               <exclusion>
-                                       <groupId>xom</groupId>
-                                       <artifactId>xom</artifactId>
-                               </exclusion>
-                               <exclusion>
-                                       <groupId>xerces</groupId>
-                                       <artifactId>xmlParserAPIs</artifactId>
-                               </exclusion>
-                       </exclusions>
-               </dependency>
+        <dependency>
+            <groupId>dom4j</groupId>
+            <artifactId>dom4j</artifactId>
+            <version>1.6</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>xml-apis</groupId>
+                    <artifactId>xml-apis</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>jaxen</groupId>
+            <artifactId>jaxen</artifactId>
+            <version>1.1-beta-9</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>xom</groupId>
+                    <artifactId>xom</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>xerces</groupId>
+                    <artifactId>xmlParserAPIs</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
 
 
+        <dependency>
+            <groupId>org.wamblee</groupId>
+            <artifactId>wamblee-wicket-joe</artifactId>
+            <version>${utils.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.wamblee</groupId>
+            <artifactId>wamblee-wicket-components</artifactId>
+            <version>${utils.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.wamblee</groupId>
+            <artifactId>wamblee-support-cdi</artifactId>
+            <version>${utils.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.wamblee</groupId>
+            <artifactId>wamblee-support-cdi</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+            <version>${utils.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.wamblee</groupId>
+            <artifactId>wamblee-security-usermgt</artifactId>
+            <version>${utils.version}</version>
+        </dependency>
 
-               <dependency>
-                       <groupId>org.wamblee</groupId>
-                       <artifactId>wamblee-wicket-joe</artifactId>
-                       <version>${utils.version}</version>
-               </dependency>
-               <dependency>
-                       <groupId>org.wamblee</groupId>
-                       <artifactId>wamblee-wicket-components</artifactId>
-                       <version>${utils.version}</version>
-               </dependency>
-               <dependency>
-                       <groupId>org.wamblee</groupId>
-                       <artifactId>wamblee-support-cdi</artifactId>
-                       <version>${utils.version}</version>
-               </dependency>
-               <dependency>
-                       <groupId>org.wamblee</groupId>
-                       <artifactId>wamblee-support-cdi</artifactId>
-                       <type>test-jar</type>
-                       <scope>test</scope>
-                       <version>${utils.version}</version>
-               </dependency>
-               <dependency>
-                       <groupId>org.wamblee</groupId>
-                       <artifactId>wamblee-security-usermgt</artifactId>
-                       <version>${utils.version}</version>
-               </dependency>
 
+        <!--  WICKET DEPENDENCIES -->
+        <dependency>
+            <groupId>org.apache.wicket</groupId>
+            <artifactId>wicket</artifactId>
+            <version>${wicket.version}</version>
+        </dependency>
+        <!--
+            OPTIONAL <dependency> <groupId>org.apache.wicket</groupId>
+            <artifactId>wicket-extensions</artifactId>
+            <version>${wicket.version}</version> </dependency>
+        -->
 
-               <!--  WICKET DEPENDENCIES -->
-               <dependency>
-                       <groupId>org.apache.wicket</groupId>
-                       <artifactId>wicket</artifactId>
-                       <version>${wicket.version}</version>
-               </dependency>
-               <!--
-                       OPTIONAL <dependency> <groupId>org.apache.wicket</groupId>
-                       <artifactId>wicket-extensions</artifactId>
-                       <version>${wicket.version}</version> </dependency>
-               -->
+        <!-- LOGGING DEPENDENCIES - LOG4J -->
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <version>1.4.2</version>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+            <version>1.2.14</version>
+        </dependency>
 
-               <!-- LOGGING DEPENDENCIES - LOG4J -->
-               <dependency>
-                       <groupId>org.slf4j</groupId>
-                       <artifactId>slf4j-log4j12</artifactId>
-                       <version>1.4.2</version>
-               </dependency>
-               <dependency>
-                       <groupId>log4j</groupId>
-                       <artifactId>log4j</artifactId>
-                       <version>1.2.14</version>
-               </dependency>
+        <!--  JUNIT DEPENDENCY FOR TESTING -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.4</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <version>1.8.5</version>
+            <scope>test</scope>
+        </dependency>
 
-               <!--  JUNIT DEPENDENCY FOR TESTING -->
-               <dependency>
-                       <groupId>junit</groupId>
-                       <artifactId>junit</artifactId>
-                       <version>4.4</version>
-                       <scope>test</scope>
-               </dependency>
-               <dependency>
-                       <groupId>org.mockito</groupId>
-                       <artifactId>mockito-all</artifactId>
-                       <version>1.8.5</version>
-                       <scope>test</scope>
-               </dependency>
 
+        <!--  JETTY DEPENDENCIES FOR TESTING  -->
+        <dependency>
+            <groupId>org.mortbay.jetty</groupId>
+            <artifactId>jetty</artifactId>
+            <version>${jetty.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mortbay.jetty</groupId>
+            <artifactId>jetty-util</artifactId>
+            <version>${jetty.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mortbay.jetty</groupId>
+            <artifactId>jetty-management</artifactId>
+            <version>${jetty.version}</version>
+            <scope>provided</scope>
+        </dependency>
 
-               <!--  JETTY DEPENDENCIES FOR TESTING  -->
-               <dependency>
-                       <groupId>org.mortbay.jetty</groupId>
-                       <artifactId>jetty</artifactId>
-                       <version>${jetty.version}</version>
-                       <scope>provided</scope>
-               </dependency>
-               <dependency>
-                       <groupId>org.mortbay.jetty</groupId>
-                       <artifactId>jetty-util</artifactId>
-                       <version>${jetty.version}</version>
-                       <scope>provided</scope>
-               </dependency>
-               <dependency>
-                       <groupId>org.mortbay.jetty</groupId>
-                       <artifactId>jetty-management</artifactId>
-                       <version>${jetty.version}</version>
-                       <scope>provided</scope>
-               </dependency>
+        <!--  JPA testing -->
+        <dependency>
+            <groupId>org.wamblee</groupId>
+            <artifactId>wamblee-test-enterprise</artifactId>
+            <version>${utils.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.wamblee</groupId>
+            <artifactId>wamblee-test-eclipselink</artifactId>
+            <version>${utils.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.persistence</groupId>
+            <artifactId>javax.persistence</artifactId>
+            <version>2.0.0</version>
+            <scope>provided</scope>
+        </dependency>
 
-               <!--  JPA testing -->
-               <dependency>
-                       <groupId>org.wamblee</groupId>
-                       <artifactId>wamblee-test-enterprise</artifactId>
-                       <version>${utils.version}</version>
-                       <scope>test</scope>
-               </dependency>
-               <dependency>
-                       <groupId>org.wamblee</groupId>
-                       <artifactId>wamblee-test-eclipselink</artifactId>
-                       <version>${utils.version}</version>
-                       <scope>test</scope>
-               </dependency>
-               <dependency>
-                       <groupId>org.eclipse.persistence</groupId>
-                       <artifactId>javax.persistence</artifactId>
-                       <version>2.0.0</version>
-                       <scope>provided</scope>
-               </dependency>
+        <dependency>
+            <groupId>org.eclipse.persistence</groupId>
+            <artifactId>eclipselink</artifactId>
+            <version>2.0.2</version>
+            <scope>test</scope>
+        </dependency>
 
-               <dependency>
-                       <groupId>org.eclipse.persistence</groupId>
-                       <artifactId>eclipselink</artifactId>
-                       <version>2.0.2</version>
-                       <scope>test</scope>
-               </dependency>
+        <dependency>
+            <groupId>javax</groupId>
+            <artifactId>javaee-api</artifactId>
+            <version>6.0</version>
+            <scope>provided</scope>
+        </dependency>
 
-               <dependency>
-                       <groupId>javax</groupId>
-                       <artifactId>javaee-api</artifactId>
-                       <version>6.0</version>
-                       <scope>provided</scope>
-               </dependency>
 
+    </dependencies>
+    <build>
+        <resources>
+            <resource>
+                <filtering>false</filtering>
+                <directory>src/main/resources</directory>
+            </resource>
+            <resource>
+                <filtering>false</filtering>
+                <directory>src/main/java</directory>
+                <includes>
+                    <include>**</include>
+                </includes>
+                <excludes>
+                    <exclude>**/*.java</exclude>
+                </excludes>
+            </resource>
+        </resources>
+        <testResources>
+            <testResource>
+                <filtering>false</filtering>
+                <directory>src/test/java</directory>
+                <includes>
+                    <include>**</include>
+                </includes>
+                <excludes>
+                    <exclude>**/*.java</exclude>
+                </excludes>
+            </testResource>
+        </testResources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-war-plugin</artifactId>
+                <version>2.0</version>
+                <configuration></configuration>
+            </plugin>
 
-       </dependencies>
-       <build>
-               <resources>
-                       <resource>
-                               <filtering>false</filtering>
-                               <directory>src/main/resources</directory>
-                       </resource>
-                       <resource>
-                               <filtering>false</filtering>
-                               <directory>src/main/java</directory>
-                               <includes>
-                                       <include>**</include>
-                               </includes>
-                               <excludes>
-                                       <exclude>**/*.java</exclude>
-                               </excludes>
-                       </resource>
-               </resources>
-               <testResources>
-                       <testResource>
-                               <filtering>false</filtering>
-                               <directory>src/test/java</directory>
-                               <includes>
-                                       <include>**</include>
-                               </includes>
-                               <excludes>
-                                       <exclude>**/*.java</exclude>
-                               </excludes>
-                       </testResource>
-               </testResources>
-               <plugins>
-                       <plugin>
-                               <groupId>org.apache.maven.plugins</groupId>
-                               <artifactId>maven-war-plugin</artifactId>
-                               <version>2.0</version>
-                               <configuration> </configuration>
-                       </plugin>
 
+            <plugin>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy-dependencies</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>copy-dependencies</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
 
-                       <plugin>
-                               <artifactId>maven-dependency-plugin</artifactId>
-                               <executions>
-                                       <execution>
-                                               <id>copy-dependencies</id>
-                                               <phase>package</phase>
-                                               <goals>
-                                                       <goal>copy-dependencies</goal>
-                                               </goals>
-                                       </execution>
-                               </executions>
-                       </plugin>
+            <plugin>
+                <inherited>true</inherited>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>java
+                    <source>1.7</source>
+                    <target>1.7</target>
+                    <optimize>true</optimize>
+                    <debug>true</debug>
+                    <compilerArgument>-XDignore.symbol.file</compilerArgument>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.mortbay.jetty</groupId>
+                <artifactId>maven-jetty-plugin</artifactId>
+            </plugin>
 
-                       <plugin>
-                               <inherited>true</inherited>
-                               <groupId>org.apache.maven.plugins</groupId>
-                               <artifactId>maven-compiler-plugin</artifactId>
-                               <configuration>                 java
-                                       <source>1.6</source>
-                                       <target>1.6</target>
-                                       <optimize>true</optimize>
-                                       <debug>true</debug>
-                                        <compilerArgument>-XDignore.symbol.file</compilerArgument>
-                               </configuration>
-                       </plugin>
-                       <plugin>
-                               <groupId>org.mortbay.jetty</groupId>
-                               <artifactId>maven-jetty-plugin</artifactId>
-                       </plugin>
+        </plugins>
+    </build>
 
-               </plugins>
-       </build>
 
+    <repositories>
+        <repository>
+            <id>EclipseLink Repo</id>
+            <url>http://www.eclipse.org/downloads/download.php?r=1&amp;nf=1&amp;file=/rt/eclipselink/maven.repo</url>
+        </repository>
+    </repositories>
 
-       <repositories>
-               <repository>
-                       <id>EclipseLink Repo</id>
-                       <url>http://www.eclipse.org/downloads/download.php?r=1&amp;nf=1&amp;file=/rt/eclipselink/maven.repo</url>
-               </repository>
-       </repositories>
-
-       <profiles>
-               <profile>
-                       <id>release</id>
-                       <activation>
-                               <property>
-                                       <name>performRelease</name>
-                                       <value>true</value>
-                               </property>
-                       </activation>
+    <profiles>
+        <profile>
+            <id>release</id>
+            <activation>
+                <property>
+                    <name>performRelease</name>
+                    <value>true</value>
+                </property>
+            </activation>
 
-                       <build>
-                               <plugins>
-                                       <plugin>
-                                               <groupId>org.apache.maven.plugins</groupId>
-                                               <artifactId>maven-release-plugin</artifactId>
-                                               <version>2.0</version>
-                                               <configuration>
-                                                       <autoVersionSubmodules>true</autoVersionSubmodules>
-                                                       <goals>javadoc:jar deploy</goals>
-                                               </configuration>
-                                       </plugin>
-                                       <plugin>
-                                               <groupId>org.apache.maven.plugins</groupId>
-                                               <artifactId>maven-gpg-plugin</artifactId>
-                                               <executions>
-                                                       <execution>
-                                                               <id>sign-artifacts</id>
-                                                               <phase>verify</phase>
-                                                               <goals>
-                                                                       <goal>sign</goal>
-                                                               </goals>
-                                                       </execution>
-                                               </executions>
-                                       </plugin>
-                               </plugins>
-                       </build>
-               </profile>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-release-plugin</artifactId>
+                        <version>2.0</version>
+                        <configuration>
+                            <autoVersionSubmodules>true</autoVersionSubmodules>
+                            <goals>javadoc:jar deploy</goals>
+                        </configuration>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-gpg-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>sign-artifacts</id>
+                                <phase>verify</phase>
+                                <goals>
+                                    <goal>sign</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
         <profile>
             <id>ide</id>
             <build>
                 <directory>target-ide</directory>
             </build>
         </profile>
-       </profiles>
+    </profiles>
 
-       <distributionManagement>
-               <repository>
-                       <id>sonatype-nexus-staging</id>
-                       <name>Nexus Release Repository</name>
-                       <url>http://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
-               </repository>
-       </distributionManagement>
+    <distributionManagement>
+        <repository>
+            <id>sonatype-nexus-staging</id>
+            <name>Nexus Release Repository</name>
+            <url>http://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
+        </repository>
+    </distributionManagement>
 
 </project>
index 68a8faf7499899bf4c3c48d34b7a2a70fd193a39..bfff860137c6ad68fafd4e9d3f0ec67436adc2a7 100644 (file)
@@ -22,6 +22,7 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -86,54 +87,54 @@ public class FileSystemAlbum implements Album {
     private String _path;
 
     private class CreateEntryCallback implements EntryFoundCallback {
-        public boolean photoFound(List<PhotoEntry> aEntries, File aThumbnail,
-            File aPhoto, String aPath) {
+        public boolean photoFound(List<PhotoEntry> aEntries, File aThumbnail, File aPhoto, String aPath) {
             PhotoEntry entry = new FileSystemPhoto(aThumbnail, aPhoto, aPath);
             aEntries.add(entry);
             return true;
         }
 
-        public boolean albumFound(List<PhotoEntry> aEntries, File aAlbum,
-            String aPath) throws IOException {
-            PhotoEntry entry = new FileSystemAlbum(aAlbum, aPath,
-                _entries.getCache());
+        public boolean albumFound(List<PhotoEntry> aEntries, File aAlbum, String aPath) throws IOException {
+            PhotoEntry entry = new FileSystemAlbum(aAlbum, aPath, _entries.getCache());
             aEntries.add(entry);
             return true;
         }
     }
 
+    private static final class AlbumComputation
+            implements CachedObject.Computation<String, ArrayList<PhotoEntry>>, Serializable {
+        private FileSystemAlbum album;
+
+        public AlbumComputation(FileSystemAlbum aAlbum) {
+            album = aAlbum;
+        }
+
+        @Override
+        public ArrayList<PhotoEntry> getObject(String aObjectKey) throws Exception {
+            return album.compute();
+        }
+    }
+
     /**
      * Creates the album.
-     * 
-     * @param aDir
-     *            Directory where the album is located.
-     * @param aPath
-     *            Path that this album represents.
-     * @param aCache
-     *            Cache to use.
+     *
+     * @param aDir   Directory where the album is located.
+     * @param aPath  Path that this album represents.
+     * @param aCache Cache to use.
      * @throws IOException
      */
-    public FileSystemAlbum(File aDir, String aPath,
-        Cache<String, ArrayList<PhotoEntry>> aCache) throws IOException {
+    public FileSystemAlbum(File aDir, String aPath, Cache<String, ArrayList<PhotoEntry>> aCache) throws IOException {
         if (!aDir.isDirectory()) {
             throw new IOException("Directory '" + aDir.getPath() +
-                "' does not exist.");
+                    "' does not exist.");
         }
         _dir = aDir;
         _path = aPath;
-        _entries = new CachedObject<String, ArrayList<PhotoEntry>>(aCache,
-            aPath,
-            new CachedObject.Computation<String, ArrayList<PhotoEntry>>() {
-                public ArrayList<PhotoEntry> getObject(String aObjectKey) {
-                    return FileSystemAlbum.this.compute();
-                }
-            });
-
+        _entries = new CachedObject<String, ArrayList<PhotoEntry>>(aCache, aPath, new AlbumComputation(this));
     }
 
     /**
      * Computes the photo entries for this album based on the file system.
-     * 
+     *
      * @return List of photo entries.
      */
     private ArrayList<PhotoEntry> compute() {
@@ -141,7 +142,8 @@ public class FileSystemAlbum implements Album {
         try {
             LOG.info("Initializing album for directory " + _dir);
             traverse(getPath(), result, _dir, new CreateEntryCallback());
-        } catch (IOException e) {
+        }
+        catch (IOException e) {
             LOG.fatal("IOException occurred: " + e.getMessage(), e);
         }
         return result;
@@ -149,25 +151,21 @@ public class FileSystemAlbum implements Album {
 
     /**
      * Initializes the album.
-     * 
-     * @param aPath
-     *            Path of the album
-     * @param aEntries
-     *            Photo entries for the album.
-     * @param aDir
-     *            Directory where the album is stored.
+     *
+     * @param aPath    Path of the album
+     * @param aEntries Photo entries for the album.
+     * @param aDir     Directory where the album is stored.
      * @throws IOException
      */
-    static boolean traverse(String aPath, List<PhotoEntry> aEntries, File aDir,
-        EntryFoundCallback aCallback) throws IOException {
+    static boolean traverse(String aPath, List<PhotoEntry> aEntries, File aDir, EntryFoundCallback aCallback)
+            throws IOException {
         File[] files = listFilesInDir(aDir);
         for (int i = 0; i < files.length; i++) {
             File file = files[i];
             if (file.isDirectory()) {
 
                 if (file.getName().equals(THUMBNAILS_DIR)) {
-                    if (!traverseThumbnails(aPath, aEntries, aDir, aCallback,
-                        file)) {
+                    if (!traverseThumbnails(aPath, aEntries, aDir, aCallback, file)) {
                         return false;
                     }
                 } else if (file.getName().equals(PHOTOS_DIR)) {
@@ -187,21 +185,15 @@ public class FileSystemAlbum implements Album {
 
     /**
      * Traverse the thumnails directory.
-     * 
-     * @param aPath
-     *            Path of the photo album.
-     * @param aEntries
-     *            Entries of the album.
-     * @param aDir
-     *            Directory of the album.
-     * @param aCallback
-     *            Callback to call when a thumbnail has been found.
-     * @param aFile
-     *            Directory of the photo album.
-     */
-    private static boolean traverseThumbnails(String aPath,
-        List<PhotoEntry> aEntries, File aDir, EntryFoundCallback aCallback,
-        File aFile) {
+     *
+     * @param aPath     Path of the photo album.
+     * @param aEntries  Entries of the album.
+     * @param aDir      Directory of the album.
+     * @param aCallback Callback to call when a thumbnail has been found.
+     * @param aFile     Directory of the photo album.
+     */
+    private static boolean traverseThumbnails(String aPath, List<PhotoEntry> aEntries, File aDir,
+            EntryFoundCallback aCallback, File aFile) {
         // Go inside the thumbnails directory to scan
         // for available photos.
 
@@ -214,44 +206,39 @@ public class FileSystemAlbum implements Album {
             }
         } else {
             LOG.info("Thumbnails director " + aFile.getPath() +
-                " exists but corresponding photo directory " +
-                photosDir.getPath() + " not found");
+                    " exists but corresponding photo directory " +
+                    photosDir.getPath() + " not found");
         }
         return true;
     }
 
     /**
      * Builds up the photo album for a given thumbnails and photo directory.
-     * 
-     * @param aPath
-     *            Path of the album.
-     * @param aEntries
-     *            Photo entries of the album.
-     * @param aThumbnailsDir
-     *            Directory containing thumbnail pictures.
-     * @param aPhotosDir
-     *            Directory containing full size photos.
-     */
-    private static boolean buildAlbum(String aPath, List<PhotoEntry> aEntries,
-        File aThumbnailsDir, File aPhotosDir, EntryFoundCallback aCallback) {
+     *
+     * @param aPath          Path of the album.
+     * @param aEntries       Photo entries of the album.
+     * @param aThumbnailsDir Directory containing thumbnail pictures.
+     * @param aPhotosDir     Directory containing full size photos.
+     */
+    private static boolean buildAlbum(String aPath, List<PhotoEntry> aEntries, File aThumbnailsDir, File aPhotosDir,
+            EntryFoundCallback aCallback) {
 
         File[] thumbnails = listFilesInDir(aThumbnailsDir);
         for (int i = 0; i < thumbnails.length; i++) {
             File thumbnail = thumbnails[i];
             if (!isThumbNail(thumbnail)) {
                 LOG.info("Skipping " + thumbnail.getPath() +
-                    " because it is not a thumbnail file.");
+                        " because it is not a thumbnail file.");
                 continue;
             }
             File photo = new File(aPhotosDir, photoName(thumbnail.getName()));
             if (!photo.isFile()) {
                 LOG.info("Photo file " + photo.getPath() + " for thumbnail " +
-                    thumbnail.getPath() + " does not exist.");
+                        thumbnail.getPath() + " does not exist.");
                 continue;
             }
             String photoPath = photo.getName();
-            photoPath = photoPath.substring(0, photoPath.length() -
-                JPG_EXTENSION.length());
+            photoPath = photoPath.substring(0, photoPath.length() - JPG_EXTENSION.length());
             photoPath = aPath + "/" + photoPath;
             photoPath = photoPath.replaceAll("//", "/");
             if (!aCallback.photoFound(aEntries, thumbnail, photo, photoPath)) {
@@ -272,9 +259,8 @@ public class FileSystemAlbum implements Album {
 
     /**
      * Checks if the file represents a thumbnail.
-     * 
-     * @param aFile
-     *            File to check.
+     *
+     * @param aFile File to check.
      * @return True iff the file is a thumbnail.
      */
     private static boolean isThumbNail(File aFile) {
@@ -283,15 +269,12 @@ public class FileSystemAlbum implements Album {
 
     /**
      * Constructs the photo name based on the thumbnail name.
-     * 
-     * @param aThumbnailName
-     *            Thumbnail name.
+     *
+     * @param aThumbnailName Thumbnail name.
      * @return Photo name.
      */
     private static String photoName(String aThumbnailName) {
-        return aThumbnailName.substring(0, aThumbnailName.length() -
-            THUMBNAIL_ENDING.length()) +
-            JPG_EXTENSION;
+        return aThumbnailName.substring(0, aThumbnailName.length() - THUMBNAIL_ENDING.length()) + JPG_EXTENSION;
     }
 
     /*
@@ -301,8 +284,7 @@ public class FileSystemAlbum implements Album {
      */
     public PhotoEntry getEntry(String aPath) {
         if (!aPath.startsWith("/")) {
-            throw new IllegalArgumentException(
-                "Path must start with / character");
+            throw new IllegalArgumentException("Path must start with / character");
         }
         if (aPath.equals("/")) {
             return this;
@@ -320,11 +302,9 @@ public class FileSystemAlbum implements Album {
 
     /**
      * Gets the entry at a given path.
-     * 
-     * @param aPath
-     *            Array of components of the path.
-     * @param aLevel
-     *            Current level in the path.
+     *
+     * @param aPath  Array of components of the path.
+     * @param aLevel Current level in the path.
      * @return Entry.
      */
     private PhotoEntry getEntry(String[] aPath, int aLevel) {
@@ -345,9 +325,8 @@ public class FileSystemAlbum implements Album {
 
     /**
      * Finds an entry in the album with the given id.
-     * 
-     * @param aId
-     *            Photo entry id.
+     *
+     * @param aId Photo entry id.
      * @return Photo entry.
      */
     private PhotoEntry find(String aId) {
@@ -356,9 +335,8 @@ public class FileSystemAlbum implements Album {
 
     /**
      * Finds a photo entry in the map.
-     * 
-     * @param aId
-     *            Id of the photo entry.
+     *
+     * @param aId Id of the photo entry.
      * @return Pair of a photo entry and the index of the item.
      */
     private Pair<PhotoEntry, Integer> findInMap(String aId) {
@@ -405,9 +383,8 @@ public class FileSystemAlbum implements Album {
 
     /**
      * Prints the album with a given indentation.
-     * 
-     * @param aIndent
-     *            Indentation string.
+     *
+     * @param aIndent Indentation string.
      * @return String representation of the album.
      */
     private String print(String aIndent) {
@@ -431,8 +408,7 @@ public class FileSystemAlbum implements Album {
      * @see org.wamblee.photos.database.Album#addImage(java.lang.String,
      *      java.awt.Image)
      */
-    public void addImage(String aId, InputStream aImageStream)
-        throws IOException {
+    public void addImage(String aId, InputStream aImageStream) throws IOException {
         File photoDir = getPhotoDir();
         File thumbnailDir = getThumbnailDir();
 
@@ -441,12 +417,11 @@ public class FileSystemAlbum implements Album {
         BufferedImage image;
         try {
             image = JpegUtils.loadJpegImage(aImageStream);
-        } catch (InterruptedException e) {
-            throw new IOException("Loading image interruptedS: " +
-                e.getMessage());
         }
-        BufferedImage thumbnailImage = JpegUtils.scaleImage(THUMBNAIL_WIDTH,
-            THUMBNAIL_HEIGHT, image);
+        catch (InterruptedException e) {
+            throw new IOException("Loading image interruptedS: " + e.getMessage());
+        }
+        BufferedImage thumbnailImage = JpegUtils.scaleImage(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, image);
 
         File thumbnail = new File(thumbnailDir, aId + THUMBNAIL_ENDING);
         File photo = new File(photoDir, aId + JPG_EXTENSION);
@@ -454,42 +429,37 @@ public class FileSystemAlbum implements Album {
         writeImage(photo, image);
         writeImage(thumbnail, thumbnailImage);
 
-        Photo photoEntry = new FileSystemPhoto(thumbnail, photo, (getPath()
-            .equals("/") ? "" : getPath()) + "/" + aId);
+        Photo photoEntry = new FileSystemPhoto(thumbnail, photo, (getPath().equals("/") ? "" : getPath()) + "/" + aId);
         addEntry(photoEntry);
     }
 
     /**
      * Checks if a given entry can be added to the album.
-     * 
-     * @param aId
-     *            Id of the new entry.
-     * @param aPhotoDir
-     *            Photo directory.
-     * @param aThumbnailDir
-     *            Thumbnail directory.
+     *
+     * @param aId           Id of the new entry.
+     * @param aPhotoDir     Photo directory.
+     * @param aThumbnailDir Thumbnail directory.
      * @throws IOException
      */
-    private void checkPhotoDirs(String aId, File aPhotoDir, File aThumbnailDir)
-        throws IOException {
+    private void checkPhotoDirs(String aId, File aPhotoDir, File aThumbnailDir) throws IOException {
         // Create directories if they do not already exist.
         aPhotoDir.mkdir();
         aThumbnailDir.mkdir();
 
         if (!aPhotoDir.isDirectory() || !aThumbnailDir.isDirectory()) {
             throw new IOException("Album " + getId() +
-                " does not accept new images.");
+                    " does not accept new images.");
         }
 
         if (getEntry("/" + aId) != null) {
             throw new IOException("An entry with the name '" + aId +
-                "' already exists in the album " + getPath());
+                    "' already exists in the album " + getPath());
         }
     }
 
     /**
      * Gets the thumbnail directory for the album.
-     * 
+     *
      * @return Directory.
      */
     private File getThumbnailDir() {
@@ -499,7 +469,7 @@ public class FileSystemAlbum implements Album {
 
     /**
      * Gets the photo directory for the album.
-     * 
+     *
      * @return Photo directory
      */
     private File getPhotoDir() {
@@ -509,17 +479,13 @@ public class FileSystemAlbum implements Album {
 
     /**
      * Writes an image to a file.
-     * 
-     * @param aFile
-     *            File to write to.
-     * @param aImage
-     *            Image.
+     *
+     * @param aFile  File to write to.
+     * @param aImage Image.
      * @throws IOException
      */
-    private static void writeImage(File aFile, BufferedImage aImage)
-        throws IOException {
-        OutputStream output = new BufferedOutputStream(new FileOutputStream(
-            aFile));
+    private static void writeImage(File aFile, BufferedImage aImage) throws IOException {
+        OutputStream output = new BufferedOutputStream(new FileOutputStream(aFile));
         JpegUtils.writeJpegImage(output, JPG_QUALITY, aImage);
         output.close();
     }
@@ -533,7 +499,7 @@ public class FileSystemAlbum implements Album {
         PhotoEntry entry = find(aId);
         if (entry != null) {
             throw new IOException("Entry already exists in album " + getId() +
-                " : " + aId);
+                    " : " + aId);
         }
         // Entry not yet found. Try to create it.
         File albumDir = new File(_dir, aId);
@@ -542,18 +508,15 @@ public class FileSystemAlbum implements Album {
         }
         File photosDir = new File(albumDir, PHOTOS_DIR);
         if (!photosDir.mkdir()) {
-            throw new IOException("Could  not create photo storage dir: " +
-                photosDir.getPath());
+            throw new IOException("Could  not create photo storage dir: " + photosDir.getPath());
         }
         File thumbnailsDir = new File(albumDir, THUMBNAILS_DIR);
         if (!thumbnailsDir.mkdir()) {
-            throw new IOException("Coul dnot create thumbnails storage dir: " +
-                thumbnailsDir.getPath());
+            throw new IOException("Coul dnot create thumbnails storage dir: " + thumbnailsDir.getPath());
         }
         String newPath = _path + "/" + aId;
         newPath = newPath.replaceAll("//", "/");
-        FileSystemAlbum album = new FileSystemAlbum(albumDir, newPath,
-            _entries.getCache());
+        FileSystemAlbum album = new FileSystemAlbum(albumDir, newPath, _entries.getCache());
         addEntry(album);
     }
 
@@ -578,9 +541,8 @@ public class FileSystemAlbum implements Album {
 
     /**
      * Removes a photo entry.
-     * 
-     * @param aEntry
-     *            Photo entry to remove.
+     *
+     * @param aEntry Photo entry to remove.
      * @throws IOException
      */
     private void removePhoto(PhotoEntry aEntry) throws IOException {
@@ -592,25 +554,21 @@ public class FileSystemAlbum implements Album {
             throw new IOException("Photo file not found: " + photo.getPath());
         }
         if (!thumbnail.isFile()) {
-            throw new IOException("Thumbnail file not found: " +
-                thumbnail.getPath());
+            throw new IOException("Thumbnail file not found: " + thumbnail.getPath());
         }
         if (!thumbnail.delete()) {
-            throw new IOException("Could not delete thumbnail file: " +
-                thumbnail.getPath());
+            throw new IOException("Could not delete thumbnail file: " + thumbnail.getPath());
         }
         _entries.get().remove(aEntry);
         if (!photo.delete()) {
-            throw new IOException("Could not delete photo file: " +
-                photo.getPath());
+            throw new IOException("Could not delete photo file: " + photo.getPath());
         }
     }
 
     /**
      * Removes the album entry from this album.
-     * 
-     * @param aAlbum
-     *            Album to remove
+     *
+     * @param aAlbum Album to remove
      * @throws IOException
      */
     private void removeAlbum(FileSystemAlbum aAlbum) throws IOException {
@@ -621,18 +579,16 @@ public class FileSystemAlbum implements Album {
         File photosDir = new File(aAlbum._dir, PHOTOS_DIR);
         File thumbnailsDir = new File(aAlbum._dir, THUMBNAILS_DIR);
         if (!photosDir.delete() || !thumbnailsDir.delete() ||
-            !aAlbum._dir.delete()) {
-            throw new IOException("Could not delete directories for album:" +
-                aAlbum.getId());
+                !aAlbum._dir.delete()) {
+            throw new IOException("Could not delete directories for album:" + aAlbum.getId());
         }
         _entries.get().remove(aAlbum);
     }
 
     /**
      * Adds an entry.
-     * 
-     * @param aEntry
-     *            Entry to add.
+     *
+     * @param aEntry Entry to add.
      */
     private void addEntry(PhotoEntry aEntry) {
         int i = 0;
@@ -674,7 +630,7 @@ public class FileSystemAlbum implements Album {
 
     /**
      * Returns and alphabetically sorted list of files.
-     * 
+     *
      * @param aDir
      * @return Sorted list of files.
      */
@@ -692,13 +648,13 @@ public class FileSystemAlbum implements Album {
         Pair<PhotoEntry, Integer> entry = findInMap(aId);
         if (entry.getFirst() == null) {
             throw new IllegalArgumentException("Entry with id '" + aId +
-                "' not found in album '" + getPath() + "'");
+                    "' not found in album '" + getPath() + "'");
         }
 
         int i = entry.getSecond() - 1;
         List<PhotoEntry> entries = _entries.get();
         while (i >= 0 && i < entries.size() &&
-            !(entries.get(i) instanceof Photo)) {
+                !(entries.get(i) instanceof Photo)) {
             i--;
         }
         if (i >= 0) {
@@ -715,12 +671,12 @@ public class FileSystemAlbum implements Album {
         Pair<PhotoEntry, Integer> entry = findInMap(aId);
         if (entry.getFirst() == null) {
             throw new IllegalArgumentException("Entry with id '" + aId +
-                "' not found in album '" + getPath() + "'");
+                    "' not found in album '" + getPath() + "'");
         }
         int i = entry.getSecond() + 1;
         List<PhotoEntry> entries = _entries.get();
         while (i >= 0 && i < entries.size() &&
-            !(entries.get(i) instanceof Photo)) {
+                !(entries.get(i) instanceof Photo)) {
             i++;
         }
         if (i < entries.size()) {
index 2e7ccfe40cb5db151cc64ac4847f9a82961511d0..705199afcca57460b888d338db13320b93118680 100644 (file)
@@ -1,16 +1,37 @@
 <html
-       xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+        xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
 <head>
-<title>Wicket Quickstart Archetype Homepage</title>
+    <title>Wicket Quickstart Archetype Homepage</title>
 </head>
 <body>
 <strong>Wicket Quickstart Archetype Homepage</strong>
-<br />
-<br />
+<br/>
+<br/>
 
 <wicket:extend>
-       
-       <span wicket:id="message">Message here.</span>
+
+    <span wicket:id="message">Message here.</span>
+
+    <div id="album">
+        <table border=1>
+            <tr wicket:id="row">
+
+                <td wicket:id="column">
+
+                    <a href="#" wicket:id="thumbnail">
+                        <table>
+                            <tr>
+                                <td><img wicket:id="image" border="0"/></td>
+                            </tr>
+                            <tr>
+                                <td><span wicket:id="name">photo name</span></td>
+                            </tr>
+                        </table>
+                    </a>
+                </td>
+            </tr>
+        </table>
+    </div>
 
 </wicket:extend>
 
index 26331e6fec69d83494ca993d8b1aafd61a8c3ba5..289f783e35340e3358eb48ecb0e5669475007446 100644 (file)
  */
 package org.wamblee.photos.wicket;
 
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.List;
-
 import javax.inject.Inject;
 
 import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.image.Image;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.repeater.RepeatingView;
+import org.apache.wicket.resource.ByteArrayResource;
 import org.wamblee.photos.model.Album;
+import org.wamblee.photos.model.Photo;
 import org.wamblee.photos.model.PhotoEntry;
 import org.wamblee.photos.model.plumbing.AllPhotos;
 import org.wamblee.photos.model.plumbing.AuthorizedPhotos;
@@ -36,18 +44,35 @@ public class HomePage extends BasePage {
     private static final long serialVersionUID = 1L;
 
     @Inject
-    private User user;
+    private transient User user;
 
     @Inject
-    private UserAdministration userAdmin;
+    private transient UserAdministration userAdmin;
+
+    // TODO the state should be stored as a path.
 
     @Inject
     @AllPhotos
-    private Album album;
+    private transient Album album;
 
     @Inject
     @AuthorizedPhotos
-    private Album authorized;
+    private transient Album authorized;
+
+    private class SerializableEntryLink extends Link {
+
+        private String path;
+
+        public SerializableEntryLink(String aId, String aPath) {
+            super(aId);
+            path = aPath;
+        }
+
+        @Override
+        public void onClick() {
+            System.out.println("Entry " + path + " was clicked");
+        }
+    }
 
     /**
      * Constructor that is invoked when page is invoked without a session.
@@ -77,5 +102,92 @@ public class HomePage extends BasePage {
             PhotoEntry entry = authorized.getEntry(i);
             System.out.println("Entry " + i + " " + entry.getId() + " " + entry.getPath());
         }
+
+        int ientry = 0;
+        int irow = 0;
+        RepeatingView row = new RepeatingView("row");
+        add(row);
+        while (irow < 5 && ientry < authorized.size()) {
+            int icolumn = 0;
+            WebMarkupContainer columns = new WebMarkupContainer(row.newChildId());
+            row.add(columns);
+            RepeatingView column = new RepeatingView("column");
+            columns.add(column);
+            while (icolumn < 5 && ientry < authorized.size()) {
+                WebMarkupContainer thumbnail = new WebMarkupContainer(column.newChildId());
+                column.add(thumbnail);
+
+                final PhotoEntry entry = authorized.getEntry(ientry);
+                Link link = new SerializableEntryLink("thumbnail", entry.getPath());
+                thumbnail.add(link);
+                ImageData data = getData(entry);
+
+                // TODO very inefficient. all data is loaded when generating the page.
+                link.add(new Image("image", new ByteArrayResource(data.getContentType(), data.getData())));
+
+                link.add(new Label("name", authorized.getEntry(ientry).getId()));
+                icolumn++;
+                ientry++;
+            }
+            irow++;
+        }
+    }
+
+    public static final class ImageData {
+        private String contentType;
+        private byte[] data;
+
+        public ImageData(String aContentType, byte[] aData) {
+            contentType = aContentType;
+            data = aData;
+        }
+
+        public String getContentType() {
+            return contentType;
+        }
+
+        public byte[] getData() {
+            return data;
+        }
+    }
+
+    private ImageData getData(PhotoEntry aEntry) {
+        if (aEntry instanceof Photo) {
+            return getData((Photo) aEntry);
+        } else if (aEntry instanceof Album) {
+            return getData((Album) aEntry);
+        } else {
+            throw new RuntimeException("Unsupported type " + aEntry.getClass().getName());
+        }
+    }
+
+    private ImageData getData(Photo aPhoto) {
+        try (InputStream is = aPhoto.getThumbNail()) {
+            return new ImageData("image/jpeg", getBytes(is));
+        }
+        catch (IOException e) {
+            // to improve.
+            throw new RuntimeException("Cannot read photo", e);
+        }
+    }
+
+    private byte[] getBytes(InputStream is) throws IOException {
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        byte[] block = new byte[1024];
+        int n = is.read(block);
+        while (n > 0) {
+            bos.write(block, 0, n);
+            n = is.read(block);
+        }
+        return bos.toByteArray();
+    }
+
+    private ImageData getData(Album aAlbum) {
+        try (InputStream is = getClass().getResourceAsStream("folder.png")) {
+            return new ImageData("image/png", getBytes(is));
+        }
+        catch (IOException e) {
+            throw new RuntimeException("Cannot read album jpg", e);
+        }
     }
-}
+}
\ No newline at end of file
diff --git a/src/main/java/org/wamblee/photos/wicket/folder.png b/src/main/java/org/wamblee/photos/wicket/folder.png
new file mode 100644 (file)
index 0000000..5e1ced4
Binary files /dev/null and b/src/main/java/org/wamblee/photos/wicket/folder.png differ