From c2e868714435ac7c75d77d1911d0dfb00393d051 Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Thu, 11 Jul 2013 22:44:56 +0200 Subject: [PATCH] Insert a root album into all Sones to get rid of album manipulation in the Sone. --- .../java/net/pterodactylus/sone/core/Core.java | 29 +++-- .../pterodactylus/sone/core/SoneDownloader.java | 4 +- .../net/pterodactylus/sone/core/SoneInserter.java | 3 +- .../java/net/pterodactylus/sone/data/Album.java | 10 +- .../java/net/pterodactylus/sone/data/Sone.java | 124 +++------------------ .../pterodactylus/sone/template/AlbumAccessor.java | 2 +- .../pterodactylus/sone/template/SoneAccessor.java | 7 ++ .../pterodactylus/sone/web/CreateAlbumPage.java | 3 + .../pterodactylus/sone/web/DeleteAlbumPage.java | 2 +- .../net/pterodactylus/sone/web/EditAlbumPage.java | 10 -- .../pterodactylus/sone/web/ImageBrowserPage.java | 4 +- .../sone/web/ajax/EditAlbumAjaxPage.java | 4 +- src/main/resources/templates/imageBrowser.html | 2 +- 13 files changed, 60 insertions(+), 144 deletions(-) diff --git a/src/main/java/net/pterodactylus/sone/core/Core.java b/src/main/java/net/pterodactylus/sone/core/Core.java index af2c3bf..5103b7d 100644 --- a/src/main/java/net/pterodactylus/sone/core/Core.java +++ b/src/main/java/net/pterodactylus/sone/core/Core.java @@ -1035,13 +1035,13 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, database.storePostReplies(sone, sone.getReplies()); synchronized (albums) { synchronized (images) { - for (Album album : storedSone.get().getAlbums()) { + for (Album album : storedSone.get().getRootAlbum().getAlbums()) { albums.remove(album.getId()); for (Image image : album.getImages()) { images.remove(image.getId()); } } - for (Album album : sone.getAlbums()) { + for (Album album : sone.getRootAlbum().getAlbums()) { albums.put(album.getId(), album); for (Image image : album.getImages()) { images.put(image.getId(), image); @@ -1319,7 +1319,12 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, for (String friendId : friends) { followSone(sone, friendId); } - sone.setAlbums(topLevelAlbums); + for (Album album : sone.getRootAlbum().getAlbums()) { + sone.getRootAlbum().removeAlbum(album); + } + for (Album album : topLevelAlbums) { + sone.getRootAlbum().addAlbum(album); + } soneInserters.get(sone).setLastInsertFingerprint(lastInsertFingerprint); } synchronized (knownSones) { @@ -1584,7 +1589,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, * @return The new album */ public Album createAlbum(Sone sone) { - return createAlbum(sone, null); + return createAlbum(sone, sone.getRootAlbum()); } /** @@ -1603,11 +1608,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, albums.put(album.getId(), album); } album.setSone(sone); - if (parent != null) { - parent.addAlbum(album); - } else { - sone.addAlbum(album); - } + parent.addAlbum(album); return album; } @@ -1624,11 +1625,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, if (!album.isEmpty()) { return; } - if (album.getParent() == null) { - album.getSone().removeAlbum(album); - } else { - album.getParent().removeAlbum(album); - } + album.getParent().removeAlbum(album); synchronized (albums) { albums.remove(album.getId()); } @@ -1883,7 +1880,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, configuration.getStringValue(sonePrefix + "/Friends/" + friendCounter + "/ID").setValue(null); /* save albums. first, collect in a flat structure, top-level first. */ - List albums = FluentIterable.from(sone.getAlbums()).transformAndConcat(Album.FLATTENER).toList(); + List albums = FluentIterable.from(sone.getRootAlbum().getAlbums()).transformAndConcat(Album.FLATTENER).toList(); int albumCounter = 0; for (Album album : albums) { @@ -1891,7 +1888,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider, configuration.getStringValue(albumPrefix + "/ID").setValue(album.getId()); configuration.getStringValue(albumPrefix + "/Title").setValue(album.getTitle()); configuration.getStringValue(albumPrefix + "/Description").setValue(album.getDescription()); - configuration.getStringValue(albumPrefix + "/Parent").setValue(album.getParent() == null ? null : album.getParent().getId()); + configuration.getStringValue(albumPrefix + "/Parent").setValue(album.getParent().equals(sone.getRootAlbum()) ? null : album.getParent().getId()); configuration.getStringValue(albumPrefix + "/AlbumImage").setValue(album.getAlbumImage() == null ? null : album.getAlbumImage().getId()); } configuration.getStringValue(sonePrefix + "/Albums/" + albumCounter + "/ID").setValue(null); diff --git a/src/main/java/net/pterodactylus/sone/core/SoneDownloader.java b/src/main/java/net/pterodactylus/sone/core/SoneDownloader.java index 5b56de8..9af6328 100644 --- a/src/main/java/net/pterodactylus/sone/core/SoneDownloader.java +++ b/src/main/java/net/pterodactylus/sone/core/SoneDownloader.java @@ -518,7 +518,9 @@ public class SoneDownloader extends AbstractService { sone.setReplies(replies); sone.setLikePostIds(likedPostIds); sone.setLikeReplyIds(likedReplyIds); - sone.setAlbums(topLevelAlbums); + for (Album album : topLevelAlbums) { + sone.getRootAlbum().addAlbum(album); + } } return sone; diff --git a/src/main/java/net/pterodactylus/sone/core/SoneInserter.java b/src/main/java/net/pterodactylus/sone/core/SoneInserter.java index 01e414d..a1bb903 100644 --- a/src/main/java/net/pterodactylus/sone/core/SoneInserter.java +++ b/src/main/java/net/pterodactylus/sone/core/SoneInserter.java @@ -18,6 +18,7 @@ package net.pterodactylus.sone.core; import static com.google.common.base.Preconditions.checkArgument; +import static net.pterodactylus.sone.data.Album.NOT_EMPTY; import java.io.InputStreamReader; import java.io.StringWriter; @@ -308,7 +309,7 @@ public class SoneInserter extends AbstractService { soneProperties.put("replies", Ordering.from(Reply.TIME_COMPARATOR).reverse().sortedCopy(sone.getReplies())); soneProperties.put("likedPostIds", new HashSet(sone.getLikedPostIds())); soneProperties.put("likedReplyIds", new HashSet(sone.getLikedReplyIds())); - soneProperties.put("albums", FluentIterable.from(sone.getAlbums()).transformAndConcat(Album.FLATTENER).toList()); + soneProperties.put("albums", FluentIterable.from(sone.getRootAlbum().getAlbums()).transformAndConcat(Album.FLATTENER).filter(NOT_EMPTY).toList()); } // diff --git a/src/main/java/net/pterodactylus/sone/data/Album.java b/src/main/java/net/pterodactylus/sone/data/Album.java index cb7b4f3..aa14ede 100644 --- a/src/main/java/net/pterodactylus/sone/data/Album.java +++ b/src/main/java/net/pterodactylus/sone/data/Album.java @@ -69,6 +69,15 @@ public class Album implements Fingerprintable { } }; + /** Function that transforms an album into the images it contains. */ + public static final Function> IMAGES = new Function>() { + + @Override + public List apply(Album album) { + return album.getImages(); + } + }; + /** * Filter that removes all albums that do not have any images in any album * below it. @@ -186,7 +195,6 @@ public class Album implements Fingerprintable { public void addAlbum(Album album) { checkNotNull(album, "album must not be null"); checkArgument(album.getSone().equals(sone), "album must belong to the same Sone as this album"); - checkState((this.parent == null) || (this.parent.equals(album.parent)), "album must not already be set to some other Sone"); album.setParent(this); if (!albums.contains(album)) { albums.add(album); diff --git a/src/main/java/net/pterodactylus/sone/data/Sone.java b/src/main/java/net/pterodactylus/sone/data/Sone.java index 4f4fd98..22dc593 100644 --- a/src/main/java/net/pterodactylus/sone/data/Sone.java +++ b/src/main/java/net/pterodactylus/sone/data/Sone.java @@ -18,6 +18,10 @@ package net.pterodactylus.sone.data; import static com.google.common.base.Preconditions.*; +import static com.google.common.collect.FluentIterable.from; +import static java.util.Arrays.asList; +import static net.pterodactylus.sone.data.Album.FLATTENER; +import static net.pterodactylus.sone.data.Album.IMAGES; import java.util.ArrayList; import java.util.Collection; @@ -25,7 +29,6 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Set; -import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; import java.util.logging.Level; import java.util.logging.Logger; @@ -39,9 +42,9 @@ import net.pterodactylus.util.logging.Logging; import freenet.keys.FreenetURI; import com.google.common.base.Predicate; -import com.google.common.collect.FluentIterable; import com.google.common.hash.Hasher; import com.google.common.hash.Hashing; +import com.google.common.primitives.Ints; /** * A Sone defines everything about a user: her profile, her status updates, her @@ -140,7 +143,10 @@ public class Sone implements Fingerprintable, Comparable { */ @Override public int compare(Sone leftSone, Sone rightSone) { - return rightSone.getAllImages().size() - leftSone.getAllImages().size(); + int rightSoneImageCount = from(asList(rightSone.getRootAlbum())).transformAndConcat(FLATTENER).transformAndConcat(IMAGES).size(); + int leftSoneImageCount = from(asList(leftSone.getRootAlbum())).transformAndConcat(FLATTENER).transformAndConcat(IMAGES).size(); + /* sort descending. */ + return Ints.compare(rightSoneImageCount, leftSoneImageCount); } }; @@ -168,7 +174,7 @@ public class Sone implements Fingerprintable, Comparable { @Override public boolean apply(Sone sone) { - return !sone.getAlbums().isEmpty(); + return !sone.getRootAlbum().getAlbums().isEmpty(); } }; @@ -224,8 +230,8 @@ public class Sone implements Fingerprintable, Comparable { /** The IDs of all liked replies. */ private final Set likedReplyIds = new CopyOnWriteArraySet(); - /** The albums of this Sone. */ - private final List albums = new CopyOnWriteArrayList(); + /** The root album containing all albums. */ + private final Album rootAlbum = new Album().setSone(this); /** Sone-specific options. */ private Options options = new Options(); @@ -757,110 +763,12 @@ public class Sone implements Fingerprintable, Comparable { } /** - * Returns the albums of this Sone. + * Returns the root album that contains all visible albums of this Sone. * - * @return The albums of this Sone + * @return The root album of this Sone */ - public List getAlbums() { - return Collections.unmodifiableList(albums); - } - - /** - * Returns all images of a Sone. Images of a album are inserted into this list - * before images of all child albums. - * - * @return The list of all images - */ - public List getAllImages() { - List allImages = new ArrayList(); - for (Album album : FluentIterable.from(getAlbums()).transformAndConcat(Album.FLATTENER).toList()) { - allImages.addAll(album.getImages()); - } - return allImages; - } - - /** - * Adds an album to this Sone. - * - * @param album - * The album to add - */ - public void addAlbum(Album album) { - checkNotNull(album, "album must not be null"); - checkArgument(album.getSone().equals(this), "album must belong to this Sone"); - if (!albums.contains(album)) { - albums.add(album); - } - } - - /** - * Sets the albums of this Sone. - * - * @param albums - * The albums of this Sone - */ - public void setAlbums(Collection albums) { - checkNotNull(albums, "albums must not be null"); - this.albums.clear(); - for (Album album : albums) { - addAlbum(album); - } - } - - /** - * Removes an album from this Sone. - * - * @param album - * The album to remove - */ - public void removeAlbum(Album album) { - checkNotNull(album, "album must not be null"); - checkArgument(album.getSone().equals(this), "album must belong to this Sone"); - albums.remove(album); - } - - /** - * Moves the given album up in this album’s albums. If the album is already the - * first album, nothing happens. - * - * @param album - * The album to move up - * @return The album that the given album swapped the place with, or - * null if the album did not change its place - */ - public Album moveAlbumUp(Album album) { - checkNotNull(album, "album must not be null"); - checkArgument(album.getSone().equals(this), "album must belong to this Sone"); - checkArgument(album.getParent() == null, "album must not have a parent"); - int oldIndex = albums.indexOf(album); - if (oldIndex <= 0) { - return null; - } - albums.remove(oldIndex); - albums.add(oldIndex - 1, album); - return albums.get(oldIndex); - } - - /** - * Moves the given album down in this album’s albums. If the album is already - * the last album, nothing happens. - * - * @param album - * The album to move down - * @return The album that the given album swapped the place with, or - * null if the album did not change its place - */ - public Album moveAlbumDown(Album album) { - checkNotNull(album, "album must not be null"); - checkArgument(album.getSone().equals(this), "album must belong to this Sone"); - checkArgument(album.getParent() == null, "album must not have a parent"); - int oldIndex = albums.indexOf(album); - if ((oldIndex < 0) || (oldIndex >= (albums.size() - 1))) { - return null; - } - albums.remove(oldIndex); - albums.add(oldIndex + 1, album); - return albums.get(oldIndex); + public Album getRootAlbum() { + return rootAlbum; } /** diff --git a/src/main/java/net/pterodactylus/sone/template/AlbumAccessor.java b/src/main/java/net/pterodactylus/sone/template/AlbumAccessor.java index 96891e5..fcd7a70 100644 --- a/src/main/java/net/pterodactylus/sone/template/AlbumAccessor.java +++ b/src/main/java/net/pterodactylus/sone/template/AlbumAccessor.java @@ -45,7 +45,7 @@ public class AlbumAccessor extends ReflectionAccessor { if ("backlinks".equals(member)) { List> backlinks = new ArrayList>(); Album currentAlbum = album; - while (currentAlbum != null) { + while (!currentAlbum.equals(album.getSone().getRootAlbum())) { backlinks.add(0, createLink("imageBrowser.html?album=" + currentAlbum.getId(), currentAlbum.getTitle())); currentAlbum = currentAlbum.getParent(); } diff --git a/src/main/java/net/pterodactylus/sone/template/SoneAccessor.java b/src/main/java/net/pterodactylus/sone/template/SoneAccessor.java index c54fc0d..ab872d9 100644 --- a/src/main/java/net/pterodactylus/sone/template/SoneAccessor.java +++ b/src/main/java/net/pterodactylus/sone/template/SoneAccessor.java @@ -17,6 +17,11 @@ package net.pterodactylus.sone.template; +import static com.google.common.collect.FluentIterable.from; +import static java.util.Arrays.asList; +import static net.pterodactylus.sone.data.Album.FLATTENER; +import static net.pterodactylus.sone.data.Album.IMAGES; + import java.util.logging.Level; import java.util.logging.Logger; @@ -111,6 +116,8 @@ public class SoneAccessor extends ReflectionAccessor { return new Trust(null, null, null); } return trust; + } else if (member.equals("allImages")) { + return from(asList(sone.getRootAlbum())).transformAndConcat(FLATTENER).transformAndConcat(IMAGES); } return super.get(templateContext, object, member); } diff --git a/src/main/java/net/pterodactylus/sone/web/CreateAlbumPage.java b/src/main/java/net/pterodactylus/sone/web/CreateAlbumPage.java index 95ca0da..9e9cd9e 100644 --- a/src/main/java/net/pterodactylus/sone/web/CreateAlbumPage.java +++ b/src/main/java/net/pterodactylus/sone/web/CreateAlbumPage.java @@ -64,6 +64,9 @@ public class CreateAlbumPage extends SoneTemplatePage { Sone currentSone = getCurrentSone(request.getToadletContext()); String parentId = request.getHttpRequest().getPartAsStringFailsafe("parent", 36); Album parent = webInterface.getCore().getAlbum(parentId, false); + if (parentId.equals("")) { + parent = currentSone.getRootAlbum(); + } Album album = webInterface.getCore().createAlbum(currentSone, parent); album.setTitle(name).setDescription(TextFilter.filter(request.getHttpRequest().getHeader("host"), description)); webInterface.getCore().touchConfiguration(); diff --git a/src/main/java/net/pterodactylus/sone/web/DeleteAlbumPage.java b/src/main/java/net/pterodactylus/sone/web/DeleteAlbumPage.java index 3dfb8b4..391e9ff 100644 --- a/src/main/java/net/pterodactylus/sone/web/DeleteAlbumPage.java +++ b/src/main/java/net/pterodactylus/sone/web/DeleteAlbumPage.java @@ -62,7 +62,7 @@ public class DeleteAlbumPage extends SoneTemplatePage { } Album parentAlbum = album.getParent(); webInterface.getCore().deleteAlbum(album); - if (parentAlbum == null) { + if (parentAlbum.equals(album.getSone().getRootAlbum())) { throw new RedirectException("imageBrowser.html?sone=" + album.getSone().getId()); } throw new RedirectException("imageBrowser.html?album=" + parentAlbum.getId()); diff --git a/src/main/java/net/pterodactylus/sone/web/EditAlbumPage.java b/src/main/java/net/pterodactylus/sone/web/EditAlbumPage.java index 8ef03e3..c66ae05 100644 --- a/src/main/java/net/pterodactylus/sone/web/EditAlbumPage.java +++ b/src/main/java/net/pterodactylus/sone/web/EditAlbumPage.java @@ -61,20 +61,10 @@ public class EditAlbumPage extends SoneTemplatePage { throw new RedirectException("noPermission.html"); } if ("true".equals(request.getHttpRequest().getPartAsStringFailsafe("moveLeft", 4))) { - if (album.getParent() == null) { - currentSone.moveAlbumUp(album); - webInterface.getCore().touchConfiguration(); - throw new RedirectException("imageBrowser.html?sone=" + currentSone.getId()); - } album.getParent().moveAlbumUp(album); webInterface.getCore().touchConfiguration(); throw new RedirectException("imageBrowser.html?album=" + album.getParent().getId()); } else if ("true".equals(request.getHttpRequest().getPartAsStringFailsafe("moveRight", 4))) { - if (album.getParent() == null) { - currentSone.moveAlbumDown(album); - webInterface.getCore().touchConfiguration(); - throw new RedirectException("imageBrowser.html?sone=" + currentSone.getId()); - } album.getParent().moveAlbumDown(album); webInterface.getCore().touchConfiguration(); throw new RedirectException("imageBrowser.html?album=" + album.getParent().getId()); diff --git a/src/main/java/net/pterodactylus/sone/web/ImageBrowserPage.java b/src/main/java/net/pterodactylus/sone/web/ImageBrowserPage.java index 9dec1dc..766f018 100644 --- a/src/main/java/net/pterodactylus/sone/web/ImageBrowserPage.java +++ b/src/main/java/net/pterodactylus/sone/web/ImageBrowserPage.java @@ -17,6 +17,7 @@ package net.pterodactylus.sone.web; +import static com.google.common.collect.FluentIterable.from; import static net.pterodactylus.sone.data.Album.FLATTENER; import static net.pterodactylus.sone.data.Album.NOT_EMPTY; import static net.pterodactylus.sone.data.Album.TITLE_COMPARATOR; @@ -27,7 +28,6 @@ import java.util.Collections; import java.util.List; import com.google.common.base.Optional; -import com.google.common.collect.FluentIterable; import net.pterodactylus.sone.data.Album; import net.pterodactylus.sone.data.Image; @@ -94,7 +94,7 @@ public class ImageBrowserPage extends SoneTemplatePage { templateContext.set("galleryRequested", true); List albums = new ArrayList(); for (Sone sone : webInterface.getCore().getSones()) { - albums.addAll(FluentIterable.from(sone.getAlbums()).transformAndConcat(FLATTENER).filter(NOT_EMPTY).toList()); + albums.addAll(from(sone.getRootAlbum().getAlbums()).transformAndConcat(FLATTENER).filter(NOT_EMPTY).toList()); } Collections.sort(albums, TITLE_COMPARATOR); Pagination albumPagination = new Pagination(albums, 12).setPage(Numbers.safeParseInteger(request.getHttpRequest().getParam("page"), 0)); diff --git a/src/main/java/net/pterodactylus/sone/web/ajax/EditAlbumAjaxPage.java b/src/main/java/net/pterodactylus/sone/web/ajax/EditAlbumAjaxPage.java index 1bd94ca..5d587db 100644 --- a/src/main/java/net/pterodactylus/sone/web/ajax/EditAlbumAjaxPage.java +++ b/src/main/java/net/pterodactylus/sone/web/ajax/EditAlbumAjaxPage.java @@ -57,12 +57,12 @@ public class EditAlbumAjaxPage extends JsonPage { return createErrorJsonObject("not-authorized"); } if ("true".equals(request.getHttpRequest().getParam("moveLeft"))) { - Album swappedAlbum = (album.getParent() != null) ? album.getParent().moveAlbumUp(album) : album.getSone().moveAlbumUp(album); + Album swappedAlbum = album.getParent().moveAlbumUp(album); webInterface.getCore().touchConfiguration(); return createSuccessJsonObject().put("sourceAlbumId", album.getId()).put("destinationAlbumId", swappedAlbum.getId()); } if ("true".equals(request.getHttpRequest().getParam("moveRight"))) { - Album swappedAlbum = (album.getParent() != null) ? album.getParent().moveAlbumDown(album) : album.getSone().moveAlbumDown(album); + Album swappedAlbum = album.getParent().moveAlbumDown(album); webInterface.getCore().touchConfiguration(); return createSuccessJsonObject().put("sourceAlbumId", album.getId()).put("destinationAlbumId", swappedAlbum.getId()); } diff --git a/src/main/resources/templates/imageBrowser.html b/src/main/resources/templates/imageBrowser.html index a80680f..da8d032 100644 --- a/src/main/resources/templates/imageBrowser.html +++ b/src/main/resources/templates/imageBrowser.html @@ -582,7 +582,7 @@ - <%include include/browseAlbums.html albums=sone.albums> + <%include include/browseAlbums.html albums=sone.rootAlbum.albums> <%if sone.local> -- 2.7.4