🔀 Merge branch 'release/v82' master v82
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Tue, 28 Apr 2020 08:44:24 +0000 (10:44 +0200)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Tue, 28 Apr 2020 08:44:24 +0000 (10:44 +0200)
528 files changed:
.builds/jdk-1.8.yml
.gitignore
build.gradle
gradle/wrapper/gradle-wrapper.properties
src/main/java/net/pterodactylus/sone/core/Core.java
src/main/java/net/pterodactylus/sone/core/FreenetInterface.java
src/main/java/net/pterodactylus/sone/core/ImageInserter.java
src/main/java/net/pterodactylus/sone/core/Options.java
src/main/java/net/pterodactylus/sone/core/PreferenceChangedEvent.kt [deleted file]
src/main/java/net/pterodactylus/sone/core/PreferencesLoader.java [deleted file]
src/main/java/net/pterodactylus/sone/core/SoneDownloaderImpl.java
src/main/java/net/pterodactylus/sone/core/SoneException.java
src/main/java/net/pterodactylus/sone/core/SoneInsertException.java
src/main/java/net/pterodactylus/sone/core/SoneInserter.java
src/main/java/net/pterodactylus/sone/core/SoneModificationDetector.java
src/main/java/net/pterodactylus/sone/core/SoneParser.java
src/main/java/net/pterodactylus/sone/core/SoneRescuer.java
src/main/java/net/pterodactylus/sone/core/SoneUri.java [deleted file]
src/main/java/net/pterodactylus/sone/core/UpdateChecker.java [deleted file]
src/main/java/net/pterodactylus/sone/core/WebOfTrustUpdater.java
src/main/java/net/pterodactylus/sone/core/WebOfTrustUpdaterImpl.java
src/main/java/net/pterodactylus/sone/core/event/ImageEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/ImageInsertAbortedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/ImageInsertFailedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/ImageInsertFinishedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/ImageInsertStartedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/MarkPostKnownEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/MarkPostReplyKnownEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/MarkSoneKnownEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/NewSoneFoundEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/PostEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/PostReplyEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/SoneEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/SoneInsertAbortedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/SoneInsertedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/SoneInsertingEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/SoneLockedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/SoneRemovedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/SoneUnlockedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/core/event/UpdateFoundEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/data/Album.java
src/main/java/net/pterodactylus/sone/data/Client.java
src/main/java/net/pterodactylus/sone/data/Image.java
src/main/java/net/pterodactylus/sone/data/Post.java
src/main/java/net/pterodactylus/sone/data/PostReply.java
src/main/java/net/pterodactylus/sone/data/Profile.java
src/main/java/net/pterodactylus/sone/data/Reply.java
src/main/java/net/pterodactylus/sone/data/Sone.java
src/main/java/net/pterodactylus/sone/data/TemporaryImage.java
src/main/java/net/pterodactylus/sone/data/impl/AbstractAlbumBuilder.java
src/main/java/net/pterodactylus/sone/data/impl/AbstractImageBuilder.java
src/main/java/net/pterodactylus/sone/data/impl/AbstractPostBuilder.java
src/main/java/net/pterodactylus/sone/data/impl/AbstractPostReplyBuilder.java
src/main/java/net/pterodactylus/sone/data/impl/AbstractReplyBuilder.java
src/main/java/net/pterodactylus/sone/data/impl/AlbumBuilderImpl.java
src/main/java/net/pterodactylus/sone/data/impl/AlbumImpl.java
src/main/java/net/pterodactylus/sone/data/impl/IdOnlySone.java
src/main/java/net/pterodactylus/sone/data/impl/ImageBuilderImpl.java
src/main/java/net/pterodactylus/sone/data/impl/ImageImpl.java
src/main/java/net/pterodactylus/sone/data/impl/SoneImpl.java
src/main/java/net/pterodactylus/sone/database/DatabaseException.java
src/main/java/net/pterodactylus/sone/database/memory/MemoryDatabase.kt [deleted file]
src/main/java/net/pterodactylus/sone/database/memory/MemoryPost.java
src/main/java/net/pterodactylus/sone/database/memory/MemoryPostBuilder.java
src/main/java/net/pterodactylus/sone/database/memory/MemoryPostReply.java
src/main/java/net/pterodactylus/sone/database/memory/MemoryPostReplyBuilder.java
src/main/java/net/pterodactylus/sone/fcp/CreatePostCommand.java
src/main/java/net/pterodactylus/sone/fcp/CreateReplyCommand.java
src/main/java/net/pterodactylus/sone/fcp/DeletePostCommand.java
src/main/java/net/pterodactylus/sone/fcp/DeleteReplyCommand.java
src/main/java/net/pterodactylus/sone/fcp/FcpInterface.java
src/main/java/net/pterodactylus/sone/fcp/GetLocalSonesCommand.java
src/main/java/net/pterodactylus/sone/fcp/GetPostCommand.java
src/main/java/net/pterodactylus/sone/fcp/GetPostFeedCommand.java
src/main/java/net/pterodactylus/sone/fcp/GetPostsCommand.java
src/main/java/net/pterodactylus/sone/fcp/GetSoneCommand.java
src/main/java/net/pterodactylus/sone/fcp/GetSonesCommand.java
src/main/java/net/pterodactylus/sone/fcp/LikePostCommand.java
src/main/java/net/pterodactylus/sone/fcp/LikeReplyCommand.java
src/main/java/net/pterodactylus/sone/fcp/LockSoneCommand.java
src/main/java/net/pterodactylus/sone/fcp/UnlockSoneCommand.java
src/main/java/net/pterodactylus/sone/fcp/VersionCommand.java
src/main/java/net/pterodactylus/sone/freenet/Key.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/L10nFilter.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/PluginStoreConfigurationBackend.java
src/main/java/net/pterodactylus/sone/freenet/SimpleFieldSetBuilder.java
src/main/java/net/pterodactylus/sone/freenet/fcp/AbstractCommand.java
src/main/java/net/pterodactylus/sone/freenet/fcp/Command.java
src/main/java/net/pterodactylus/sone/freenet/fcp/FcpException.java
src/main/java/net/pterodactylus/sone/freenet/plugin/PluginConnector.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/plugin/PluginException.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/plugin/event/ReceivedReplyEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/Context.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/DefaultIdentity.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/DefaultOwnIdentity.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/Identity.java
src/main/java/net/pterodactylus/sone/freenet/wot/IdentityChangeDetector.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/IdentityChangeEventSender.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/IdentityLoader.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/IdentityManager.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/IdentityManagerImpl.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/OwnIdentity.java
src/main/java/net/pterodactylus/sone/freenet/wot/Trust.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/WebOfTrustConnector.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/WebOfTrustException.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/event/IdentityAddedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/event/IdentityEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/event/IdentityRemovedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/event/IdentityUpdatedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/event/OwnIdentityAddedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/event/OwnIdentityEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/freenet/wot/event/OwnIdentityRemovedEvent.java [deleted file]
src/main/java/net/pterodactylus/sone/main/DebugLoaders.java
src/main/java/net/pterodactylus/sone/main/DefaultLoaders.java
src/main/java/net/pterodactylus/sone/main/Loaders.java
src/main/java/net/pterodactylus/sone/main/SonePlugin.java
src/main/java/net/pterodactylus/sone/main/SonePlugin.kt [deleted file]
src/main/java/net/pterodactylus/sone/notify/ListNotification.java [deleted file]
src/main/java/net/pterodactylus/sone/notify/ListNotificationFilter.java
src/main/java/net/pterodactylus/sone/template/AlbumAccessor.java
src/main/java/net/pterodactylus/sone/template/CollectionAccessor.java
src/main/java/net/pterodactylus/sone/template/CssClassNameFilter.java
src/main/java/net/pterodactylus/sone/template/GetPagePlugin.java
src/main/java/net/pterodactylus/sone/template/HttpRequestAccessor.java
src/main/java/net/pterodactylus/sone/template/IdentityAccessor.java
src/main/java/net/pterodactylus/sone/template/ImageAccessor.java
src/main/java/net/pterodactylus/sone/template/ImageLinkFilter.java
src/main/java/net/pterodactylus/sone/template/JavascriptFilter.java
src/main/java/net/pterodactylus/sone/template/PostAccessor.java [deleted file]
src/main/java/net/pterodactylus/sone/template/ProfileAccessor.java
src/main/java/net/pterodactylus/sone/template/ReplyAccessor.java
src/main/java/net/pterodactylus/sone/template/ReplyGroupFilter.java
src/main/java/net/pterodactylus/sone/template/RequestChangeFilter.java
src/main/java/net/pterodactylus/sone/template/SoneAccessor.java
src/main/java/net/pterodactylus/sone/template/SubstringFilter.java
src/main/java/net/pterodactylus/sone/template/TrustAccessor.java
src/main/java/net/pterodactylus/sone/template/UniqueElementFilter.java
src/main/java/net/pterodactylus/sone/template/UnknownDateFilter.java
src/main/java/net/pterodactylus/sone/text/Parser.java
src/main/java/net/pterodactylus/sone/text/ParserContext.java
src/main/java/net/pterodactylus/sone/text/PostPart.java
src/main/java/net/pterodactylus/sone/text/SoneTextParserContext.java
src/main/java/net/pterodactylus/sone/text/TextFilter.java
src/main/java/net/pterodactylus/sone/utils/DefaultOption.java [deleted file]
src/main/java/net/pterodactylus/sone/utils/IntegerRangePredicate.java [deleted file]
src/main/java/net/pterodactylus/sone/utils/NumberParsers.java
src/main/java/net/pterodactylus/sone/web/AllPages.kt [deleted file]
src/main/java/net/pterodactylus/sone/web/WebInterface.java
src/main/java/net/pterodactylus/sone/web/page/PageToadlet.java [deleted file]
src/main/kotlin/net/pterodactylus/sone/core/DefaultElementLoader.kt
src/main/kotlin/net/pterodactylus/sone/core/PreferenceChangedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/Preferences.kt
src/main/kotlin/net/pterodactylus/sone/core/PreferencesLoader.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/SoneUriCreator.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/UpdateChecker.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/UpdatedSoneProcessor.kt
src/main/kotlin/net/pterodactylus/sone/core/event/ConfigNotRead.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/DebugActivatedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/FirstStart.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/ImageEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/ImageInsertAbortedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/ImageInsertFailedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/ImageInsertFinishedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/ImageInsertStartedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/MarkPostKnownEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/MarkPostReplyKnownEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/MarkSoneKnownEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/MentionOfLocalSoneFoundEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/MentionOfLocalSoneRemovedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/NewPostFoundEvent.kt
src/main/kotlin/net/pterodactylus/sone/core/event/NewPostReplyFoundEvent.kt
src/main/kotlin/net/pterodactylus/sone/core/event/NewSoneFoundEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/PostEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/PostRemovedEvent.kt
src/main/kotlin/net/pterodactylus/sone/core/event/PostReplyEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/PostReplyRemovedEvent.kt
src/main/kotlin/net/pterodactylus/sone/core/event/Shutdown.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/SoneEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/SoneInsertAbortedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/SoneInsertedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/SoneInsertingEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/SoneLockedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/SoneLockedOnStartup.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/SoneRemovedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/SoneUnlockedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/Startup.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/StrictFilteringEvents.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/UpdateFoundEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/WebOfTrustAppeared.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/core/event/WebOfTrustDisappeared.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/data/Album.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/data/Fingerprintable.kt
src/main/kotlin/net/pterodactylus/sone/data/Identified.kt
src/main/kotlin/net/pterodactylus/sone/data/Post.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/data/Reply.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/data/Sone.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/database/AlbumBuilder.kt
src/main/kotlin/net/pterodactylus/sone/database/AlbumBuilderFactory.kt
src/main/kotlin/net/pterodactylus/sone/database/AlbumDatabase.kt
src/main/kotlin/net/pterodactylus/sone/database/AlbumProvider.kt
src/main/kotlin/net/pterodactylus/sone/database/AlbumStore.kt
src/main/kotlin/net/pterodactylus/sone/database/Database.kt
src/main/kotlin/net/pterodactylus/sone/database/ImageBuilder.kt
src/main/kotlin/net/pterodactylus/sone/database/ImageBuilderFactory.kt
src/main/kotlin/net/pterodactylus/sone/database/ImageDatabase.kt
src/main/kotlin/net/pterodactylus/sone/database/ImageProvider.kt
src/main/kotlin/net/pterodactylus/sone/database/ImageStore.kt
src/main/kotlin/net/pterodactylus/sone/database/PostBuilder.kt
src/main/kotlin/net/pterodactylus/sone/database/PostBuilderFactory.kt
src/main/kotlin/net/pterodactylus/sone/database/PostDatabase.kt
src/main/kotlin/net/pterodactylus/sone/database/PostProvider.kt
src/main/kotlin/net/pterodactylus/sone/database/PostReplyBuilder.kt
src/main/kotlin/net/pterodactylus/sone/database/PostReplyBuilderFactory.kt
src/main/kotlin/net/pterodactylus/sone/database/PostReplyDatabase.kt
src/main/kotlin/net/pterodactylus/sone/database/PostReplyProvider.kt
src/main/kotlin/net/pterodactylus/sone/database/PostReplyStore.kt
src/main/kotlin/net/pterodactylus/sone/database/PostStore.kt
src/main/kotlin/net/pterodactylus/sone/database/ReplyBuilder.kt
src/main/kotlin/net/pterodactylus/sone/database/SoneProvider.kt
src/main/kotlin/net/pterodactylus/sone/database/memory/MemoryDatabase.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/fcp/AbstractSoneCommand.kt
src/main/kotlin/net/pterodactylus/sone/freenet/AsyncFreenetInterface.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/BaseL10nTranslation.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/FreenetClient.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/FreenetURIs.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/L10nFilter.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/Translation.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/plugin/FredPluginConnector.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/plugin/PluginConnector.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/plugin/PluginException.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/plugin/PluginRespiratorFacade.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/Context.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/DefaultIdentity.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/DefaultOwnIdentity.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/IdentityChangeDetector.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/IdentityChangeEventSender.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/IdentityLoader.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/IdentityManager.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/IdentityManagerImpl.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/PluginWebOfTrustConnector.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/Trust.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/WebOfTrustConnector.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/WebOfTrustException.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/WebOfTrustPinger.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/event/IdentityAddedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/event/IdentityRemovedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/event/IdentityUpdatedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/event/OwnIdentityAddedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/freenet/wot/event/OwnIdentityRemovedEvent.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/main/FreenetModule.kt
src/main/kotlin/net/pterodactylus/sone/main/SoneModule.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/main/SoneModuleCreator.kt [deleted file]
src/main/kotlin/net/pterodactylus/sone/main/SonePlugin.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/main/TickerShutdown.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/notify/ListNotification.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/notify/Notifications.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/template/DurationFormatFilter.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/template/HistogramRenderer.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/template/PostAccessor.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/text/SoneMentionDetector.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/text/SoneTextParser.kt
src/main/kotlin/net/pterodactylus/sone/utils/AutoCloseableBucket.kt [deleted file]
src/main/kotlin/net/pterodactylus/sone/utils/Booleans.kt
src/main/kotlin/net/pterodactylus/sone/utils/DefaultOption.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/utils/Freenet.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/utils/Functions.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/utils/Objects.kt
src/main/kotlin/net/pterodactylus/sone/utils/Renderables.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/AllPages.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/FreenetSessionProvider.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/PageToadletRegistry.kt
src/main/kotlin/net/pterodactylus/sone/web/SessionProvider.kt
src/main/kotlin/net/pterodactylus/sone/web/WebInterfaceModule.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/CreatePostAjaxPage.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/DistrustAjaxPage.kt [deleted file]
src/main/kotlin/net/pterodactylus/sone/web/ajax/GetNotificationsAjaxPage.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/GetStatusAjaxPage.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/GetTranslationAjaxPage.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/JsonPage.kt
src/main/kotlin/net/pterodactylus/sone/web/ajax/TrustAjaxPage.kt [deleted file]
src/main/kotlin/net/pterodactylus/sone/web/ajax/UntrustAjaxPage.kt [deleted file]
src/main/kotlin/net/pterodactylus/sone/web/notification/ConfigNotReadHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/FirstStartHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/ImageInsertHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/LocalPostHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/LocalReplyHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/MarkPostKnownDuringFirstStartHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/MarkPostReplyKnownDuringFirstStartHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/NewRemotePostHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/NewSoneHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/NewVersionHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/NotificationHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/NotificationHandlerModule.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/RemotePostReplyHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/SoneInsertHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/SoneLockedHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/SoneLockedOnStartupHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/SoneMentionedHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/StartupHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/WebOfTrustHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/page/FreenetPage.kt
src/main/kotlin/net/pterodactylus/sone/web/page/FreenetRequest.kt
src/main/kotlin/net/pterodactylus/sone/web/page/FreenetTemplatePage.kt
src/main/kotlin/net/pterodactylus/sone/web/page/PageToadlet.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/page/PageToadletFactory.kt
src/main/kotlin/net/pterodactylus/sone/web/page/SoneRequest.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/BookmarkPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/CreateAlbumPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/CreatePostPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/CreateReplyPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/CreateSonePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/DebugPage.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/pages/DeleteAlbumPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/DeleteImagePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/DeletePostPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/DeleteProfileFieldPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/DeleteReplyPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/DeleteSonePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/DismissNotificationPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/DistrustPage.kt [deleted file]
src/main/kotlin/net/pterodactylus/sone/web/pages/EditAlbumPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/EditImagePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/EditProfileFieldPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/EditProfilePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/FollowSonePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/ImageBrowserPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/KnownSonesPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/LikePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/LockSonePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/LoginPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/LogoutPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/MarkAsKnownPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/MetricsPage.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/pages/OptionsPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/SearchPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/SoneTemplatePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/TrustPage.kt [deleted file]
src/main/kotlin/net/pterodactylus/sone/web/pages/UnbookmarkPage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/UnfollowSonePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/UnlikePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/UnlockSonePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/UntrustPage.kt [deleted file]
src/main/kotlin/net/pterodactylus/sone/web/pages/UploadImagePage.kt
src/main/kotlin/net/pterodactylus/sone/web/pages/ViewSonePage.kt
src/main/resources/i18n/sone.de.properties
src/main/resources/i18n/sone.en.properties
src/main/resources/i18n/sone.es.properties
src/main/resources/i18n/sone.fr.properties
src/main/resources/i18n/sone.it.properties [new file with mode: 0644]
src/main/resources/i18n/sone.ja.properties
src/main/resources/i18n/sone.no.properties
src/main/resources/i18n/sone.pl.properties
src/main/resources/i18n/sone.ru.properties
src/main/resources/static/css/sone.css
src/main/resources/static/javascript/jquery-1.4.2.js [deleted file]
src/main/resources/static/javascript/jquery-3.4.1.js [new file with mode: 0644]
src/main/resources/static/javascript/sone.js
src/main/resources/templates/editProfile.html
src/main/resources/templates/imageBrowser.html
src/main/resources/templates/include/head.html
src/main/resources/templates/include/soneMenu.html
src/main/resources/templates/include/viewPost.html
src/main/resources/templates/include/viewReply.html
src/main/resources/templates/knownSones.html
src/main/resources/templates/metrics.html [new file with mode: 0644]
src/main/resources/templates/notify/soneLockedOnStartupNotification.html [new file with mode: 0644]
src/main/resources/templates/options.html
src/test/java/net/pterodactylus/sone/core/ConfigurationSoneParserTest.java [deleted file]
src/test/java/net/pterodactylus/sone/core/CoreTest.java [deleted file]
src/test/java/net/pterodactylus/sone/core/FreenetInterfaceTest.java [deleted file]
src/test/java/net/pterodactylus/sone/core/PreferencesLoaderTest.java [deleted file]
src/test/java/net/pterodactylus/sone/core/SoneInserterTest.java [deleted file]
src/test/java/net/pterodactylus/sone/core/SoneParserTest.java [deleted file]
src/test/java/net/pterodactylus/sone/core/SoneUriTest.java [deleted file]
src/test/java/net/pterodactylus/sone/core/UpdateCheckerTest.java [deleted file]
src/test/java/net/pterodactylus/sone/core/WebOfTrustUpdaterTest.java
src/test/java/net/pterodactylus/sone/freenet/KeyTest.java [deleted file]
src/test/java/net/pterodactylus/sone/freenet/wot/DefaultIdentityTest.java [deleted file]
src/test/java/net/pterodactylus/sone/freenet/wot/DefaultOwnIdentityTest.java [deleted file]
src/test/java/net/pterodactylus/sone/freenet/wot/Identities.java [deleted file]
src/test/java/net/pterodactylus/sone/freenet/wot/IdentityChangeDetectorTest.java [deleted file]
src/test/java/net/pterodactylus/sone/freenet/wot/IdentityChangeEventSenderTest.java [deleted file]
src/test/java/net/pterodactylus/sone/freenet/wot/IdentityLoaderTest.java [deleted file]
src/test/java/net/pterodactylus/sone/freenet/wot/IdentityManagerTest.java [deleted file]
src/test/java/net/pterodactylus/sone/freenet/wot/event/IdentityEventTest.java [deleted file]
src/test/java/net/pterodactylus/sone/freenet/wot/event/OwnIdentityEventTest.java [deleted file]
src/test/java/net/pterodactylus/sone/main/DebugLoadersTest.java
src/test/java/net/pterodactylus/sone/main/DefaultLoadersTest.java
src/test/java/net/pterodactylus/sone/notify/ListNotificationTest.java [deleted file]
src/test/java/net/pterodactylus/sone/template/FilesystemTemplateTest.java [deleted file]
src/test/java/net/pterodactylus/sone/template/PostAccessorTest.java [deleted file]
src/test/java/net/pterodactylus/sone/test/Matchers.java
src/test/java/net/pterodactylus/sone/text/TextFilterTest.java
src/test/java/net/pterodactylus/sone/utils/DefaultOptionTest.java [deleted file]
src/test/java/net/pterodactylus/sone/utils/IntegerRangePredicateTest.java [deleted file]
src/test/kotlin/net/pterodactylus/sone/core/ConfigurationSoneParserTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/core/CoreTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/core/DefaultElementLoaderTest.kt
src/test/kotlin/net/pterodactylus/sone/core/FreenetInterfaceTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/core/ImageInserterTest.kt
src/test/kotlin/net/pterodactylus/sone/core/PreferencesLoaderTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/core/PreferencesTest.kt
src/test/kotlin/net/pterodactylus/sone/core/SoneInserterTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/core/SoneParserTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/core/SoneUriCreatorTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/core/UpdateCheckerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/core/UpdatedSoneProcessorTest.kt
src/test/kotlin/net/pterodactylus/sone/data/AlbumTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/data/ClientTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/data/PostTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/data/ReplyTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/data/SoneTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/database/memory/MemoryDatabaseTest.kt
src/test/kotlin/net/pterodactylus/sone/fcp/CreatePostCommandTest.kt
src/test/kotlin/net/pterodactylus/sone/freenet/AsyncFreenetInterfaceTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/BaseL10nTranslationTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/FreenetClientTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/FreenetURIsTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/L10nFilterTest.kt
src/test/kotlin/net/pterodactylus/sone/freenet/plugin/FredPluginConnectorTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/plugin/PluginRespiratorFacadeTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/wot/DefaultIdentityTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/wot/DefaultOwnIdentityTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/wot/Identities.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/wot/IdentityChangeDetectorTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/wot/IdentityChangeEventSenderTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/wot/IdentityLoaderTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/wot/IdentityManagerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/wot/PluginWebOfTrustConnectorTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/freenet/wot/WebOfTrustPingerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/main/FreenetModuleTest.kt
src/test/kotlin/net/pterodactylus/sone/main/SoneModuleCreatorTest.kt [deleted file]
src/test/kotlin/net/pterodactylus/sone/main/SoneModuleTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/main/SonePluginTest.kt
src/test/kotlin/net/pterodactylus/sone/main/TickerShutdownTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/notify/ListNotificationTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/template/DurationFormatFilterTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/template/FilesystemTemplateTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/template/HistogramRendererTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/template/ImageAccessorTest.kt
src/test/kotlin/net/pterodactylus/sone/template/LinkedElementsFilterTest.kt
src/test/kotlin/net/pterodactylus/sone/template/ParserFilterTest.kt
src/test/kotlin/net/pterodactylus/sone/template/PostAccessorTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/template/ProfileAccessorTest.kt
src/test/kotlin/net/pterodactylus/sone/template/ShortenFilterTest.kt
src/test/kotlin/net/pterodactylus/sone/template/SoneAccessorTest.kt
src/test/kotlin/net/pterodactylus/sone/template/UnknownDateFilterTest.kt
src/test/kotlin/net/pterodactylus/sone/test/Guice.kt
src/test/kotlin/net/pterodactylus/sone/test/Logging.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/test/Matchers.kt
src/test/kotlin/net/pterodactylus/sone/test/Mockotlin.kt
src/test/kotlin/net/pterodactylus/sone/test/Mocks.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/test/NotParallel.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/test/TestLoaders.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/test/TestPage.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/test/TestUtils.kt
src/test/kotlin/net/pterodactylus/sone/text/FreenetLinkPartTest.kt
src/test/kotlin/net/pterodactylus/sone/text/LinkPartTest.kt
src/test/kotlin/net/pterodactylus/sone/text/SoneMentionDetectorTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/text/SonePartTest.kt
src/test/kotlin/net/pterodactylus/sone/text/SoneTextParserTest.kt
src/test/kotlin/net/pterodactylus/sone/utils/AutoCloseableBucketTest.kt [deleted file]
src/test/kotlin/net/pterodactylus/sone/utils/BooleansTest.kt
src/test/kotlin/net/pterodactylus/sone/utils/DefaultOptionTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/utils/ObjectsTest.kt
src/test/kotlin/net/pterodactylus/sone/utils/OptionalsTest.kt
src/test/kotlin/net/pterodactylus/sone/utils/RenderablesTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/AllPagesTest.kt
src/test/kotlin/net/pterodactylus/sone/web/FreenetSessionProviderTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/PageToadletRegistryTest.kt
src/test/kotlin/net/pterodactylus/sone/web/WebInterfaceModuleTest.kt
src/test/kotlin/net/pterodactylus/sone/web/ajax/CreatePostAjaxPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/ajax/DistrustAjaxPageTest.kt [deleted file]
src/test/kotlin/net/pterodactylus/sone/web/ajax/EditAlbumAjaxPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/ajax/EditImageAjaxPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/ajax/TestObjects.kt
src/test/kotlin/net/pterodactylus/sone/web/ajax/TrustAjaxPageTest.kt [deleted file]
src/test/kotlin/net/pterodactylus/sone/web/ajax/UntrustAjaxPageTest.kt [deleted file]
src/test/kotlin/net/pterodactylus/sone/web/notification/ConfigNotReadHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/FirstStartHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/ImageInsertHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/LocalPostHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/LocalReplyHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/MarkPostKnownDuringFirstStartHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/MarkPostReplyKnownDuringFirstStartHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/NewRemotePostHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/NewSoneHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/NewVersionHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/NotificationHandlerModuleTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/NotificationHandlerTester.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/RemotePostReplyHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/SoneInsertHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/SoneLockedHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/SoneLockedOnStartupHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/SoneMentionedHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/StartupHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/Testing.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/WebOfTrustHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/page/FreenetRequestTest.kt
src/test/kotlin/net/pterodactylus/sone/web/page/PageToadletFactoryTest.kt
src/test/kotlin/net/pterodactylus/sone/web/page/PageToadletTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/page/SoneRequestTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/CreatePostPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/DebugPageTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/pages/DeleteAlbumPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/DeleteImagePageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/DeleteSonePageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/DismissNotificationPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/DistrustPageTest.kt [deleted file]
src/test/kotlin/net/pterodactylus/sone/web/pages/EditAlbumPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/EditImagePageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/EditProfileFieldPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/EditProfilePageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/FollowSonePageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/ImageBrowserPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/IndexPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/KnownSonesPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/MetricsPageTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/pages/OptionsPageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/SoneTemplatePageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/TrustPageTest.kt [deleted file]
src/test/kotlin/net/pterodactylus/sone/web/pages/UntrustPageTest.kt [deleted file]
src/test/kotlin/net/pterodactylus/sone/web/pages/UploadImagePageTest.kt
src/test/kotlin/net/pterodactylus/sone/web/pages/WebPageTest.kt
src/test/resources/net/pterodactylus/sone/core/sone-parser-with-invalid-recipient.xml
src/test/resources/net/pterodactylus/sone/core/sone-parser-with-recipient.xml
src/test/resources/net/pterodactylus/sone/core/sone-parser-with-valid-post-reply-time.xml
src/test/resources/net/pterodactylus/sone/core/sone-parser-with-valid-post-time.xml

index 5edd26d..2c43d38 100644 (file)
@@ -9,7 +9,7 @@ tasks:
       ./gradlew clean
   - build: |
       cd sone
-      ./gradlew build
+      ./gradlew -x findbugsTest build
   - test: |
       cd sone
       ./gradlew test
index fce4db9..abaaab1 100644 (file)
@@ -3,3 +3,5 @@
 
 /.gradle/
 /build/
+
+sone.properties
index 0beb42a..db5af2b 100644 (file)
@@ -1,18 +1,14 @@
-group = 'net.pterodactylus'
-version = '80'
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
 
-buildscript {
-    ext.kotlinVersion = '1.2.71'
-    repositories {
-        mavenCentral()
-    }
-    dependencies {
-        classpath group: 'info.solidsoft.gradle.pitest', name: 'gradle-pitest-plugin', version: '1.4.0'
-        classpath group: 'org.jetbrains.kotlin', name: 'kotlin-gradle-plugin', version: kotlinVersion
-        classpath group: 'org.jetbrains.kotlin', name: 'kotlin-noarg', version: kotlinVersion
-    }
+plugins {
+    id 'org.jetbrains.kotlin.jvm' version '1.3.70'
+    id 'org.jetbrains.kotlin.plugin.noarg' version '1.3.70'
+    id 'info.solidsoft.pitest' version '1.4.5'
 }
 
+group = 'net.pterodactylus'
+version = '82'
+
 repositories {
      mavenCentral()
      maven { url "https://maven.pterodactylus.net/" }
@@ -20,14 +16,18 @@ repositories {
 
 apply plugin: 'java'
 
-sourceCompatibility = 1.7
-targetCompatibility = 1.7
+sourceCompatibility = 1.8
+targetCompatibility = 1.8
 
 tasks.withType(JavaCompile) {
        options.encoding = 'UTF-8'
 }
 
-apply plugin: 'kotlin'
+tasks.withType(KotlinCompile) {
+    kotlinOptions {
+        jvmTarget = "1.8"
+    }
+}
 
 configurations {
     provided {
@@ -37,35 +37,55 @@ configurations {
     }
     compile.extendsFrom provided
 }
+
 dependencies {
     provided group: 'org.freenetproject', name: 'fred', version: '0.7.5.1475'
     provided group: 'org.freenetproject', name: 'freenet-ext', version: '29'
     provided group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.54'
 
-    compile group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib'
-    compile group: 'net.pterodactylus', name: 'utils', version: '0.12.4'
+    compile group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8'
+    compile group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: '1.3.0-RC'
+
+    compile group: 'net.pterodactylus', name: 'utils', version: '0.13.1'
     compile group: 'com.google.inject', name: 'guice', version: '4.2.2'
-    compile group: 'com.google.guava', name: 'guava', version: '27.0.1-android'
+    compile group: 'com.google.guava', name: 'guava', version: '27.0.1-jre'
     compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.1'
     compile group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: '2.9.1'
     compile group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.2'
     compile group: 'org.jsoup', name: 'jsoup', version: '1.10.2'
+    compile group: 'io.dropwizard.metrics', name: 'metrics-core', version: '4.1.0'
+    compile group: 'javax.activation', name: 'javax.activation-api', version: '1.2.0'
 
     testCompile group: 'org.jetbrains.kotlin', name: 'kotlin-test-junit'
     testCompile group: 'junit', name: 'junit', version: '4.11'
-    testCompile group: 'org.mockito', name: 'mockito-core', version: '2.10.0'
+    testCompile group: 'org.mockito', name: 'mockito-core', version: '2.28.2'
     testCompile group: 'org.hamcrest', name: 'hamcrest-all', version: '1.3'
 }
 
 apply from: 'version.gradle'
 
-test {
+task parallelTest(type: Test) {
     maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1
+    useJUnit {
+        excludeCategories 'net.pterodactylus.sone.test.NotParallel'
+    }
+}
+
+task notParallelTest(type: Test) {
+    maxParallelForks = 1
+    useJUnit {
+        includeCategories 'net.pterodactylus.sone.test.NotParallel'
+    }
+    dependsOn parallelTest
+}
+
+test {
+    exclude '**'
+    dependsOn parallelTest, notParallelTest
 }
 
 task fatJar(type: Jar) {
-    archiveName = project.name.toLowerCase() + '-jar-with-dependencies.jar'
+    archiveFileName = project.name.toLowerCase() + '-jar-with-dependencies.jar'
     from { (configurations.runtime - configurations.provided).collect { it.isDirectory() ? it : zipTree(it) } }
     manifest {
         attributes('Plugin-Main-Class': 'net.pterodactylus.sone.main.SonePlugin')
@@ -86,14 +106,13 @@ javadoc {
 apply plugin: 'jacoco'
 
 jacoco {
-    toolVersion = '0.7.9'
+    toolVersion = '0.8.4'
 }
 
 jacocoTestReport.dependsOn test
 
-apply plugin: 'info.solidsoft.pitest'
-
 pitest {
+    pitestVersion = '1.4.10'
     outputFormats = ['HTML', 'XML']
     timestampedReports = false
     timeoutFactor = 3.0
@@ -125,8 +144,6 @@ task countLines {
     dependsOn tasks.countLinesTest
 }
 
-apply plugin: 'kotlin-noarg'
-
 noArg {
     annotation('net.pterodactylus.sone.main.NoArg')
 }
index c19a936..1cdded7 100644 (file)
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.5-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.1-all.zip
index b0df7a9..da1b2f8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - Core.java - Copyright © 2010–2019 David Roden
+ * Sone - Core.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@ import static com.google.common.primitives.Longs.tryParse;
 import static java.lang.String.format;
 import static java.util.logging.Level.WARNING;
 import static java.util.logging.Logger.getLogger;
+import static net.pterodactylus.sone.data.AlbumKt.getAllImages;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -37,30 +38,20 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.*;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import com.codahale.metrics.*;
 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidAlbumFound;
 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidImageFound;
 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidParentAlbumFound;
 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostFound;
 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostReplyFound;
-import net.pterodactylus.sone.core.event.ImageInsertFinishedEvent;
-import net.pterodactylus.sone.core.event.InsertionDelayChangedEvent;
-import net.pterodactylus.sone.core.event.MarkPostKnownEvent;
-import net.pterodactylus.sone.core.event.MarkPostReplyKnownEvent;
-import net.pterodactylus.sone.core.event.MarkSoneKnownEvent;
-import net.pterodactylus.sone.core.event.NewPostFoundEvent;
-import net.pterodactylus.sone.core.event.NewPostReplyFoundEvent;
-import net.pterodactylus.sone.core.event.NewSoneFoundEvent;
-import net.pterodactylus.sone.core.event.PostRemovedEvent;
-import net.pterodactylus.sone.core.event.PostReplyRemovedEvent;
-import net.pterodactylus.sone.core.event.SoneLockedEvent;
-import net.pterodactylus.sone.core.event.SoneRemovedEvent;
-import net.pterodactylus.sone.core.event.SoneUnlockedEvent;
+import net.pterodactylus.sone.core.event.*;
 import net.pterodactylus.sone.data.Album;
 import net.pterodactylus.sone.data.Client;
 import net.pterodactylus.sone.data.Image;
@@ -71,6 +62,7 @@ import net.pterodactylus.sone.data.Profile.Field;
 import net.pterodactylus.sone.data.Reply;
 import net.pterodactylus.sone.data.Sone;
 import net.pterodactylus.sone.data.Sone.SoneStatus;
+import net.pterodactylus.sone.data.SoneKt;
 import net.pterodactylus.sone.data.SoneOptions.LoadExternalContent;
 import net.pterodactylus.sone.data.TemporaryImage;
 import net.pterodactylus.sone.database.AlbumBuilder;
@@ -98,8 +90,7 @@ import net.pterodactylus.util.service.AbstractService;
 import net.pterodactylus.util.thread.NamedThreadFactory;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
-import com.google.common.collect.FluentIterable;
+import com.google.common.base.Stopwatch;
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Multimaps;
@@ -121,6 +112,8 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
        /** The start time. */
        private final long startupTime = System.currentTimeMillis();
 
+       private final AtomicBoolean debug = new AtomicBoolean(false);
+
        /** The preferences. */
        private final Preferences preferences;
 
@@ -184,24 +177,13 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
        /** The time the configuration was last touched. */
        private volatile long lastConfigurationUpdate;
 
-       /**
-        * Creates a new core.
-        *
-        * @param configuration
-        *            The configuration of the core
-        * @param freenetInterface
-        *            The freenet interface
-        * @param identityManager
-        *            The identity manager
-        * @param webOfTrustUpdater
-        *            The WebOfTrust updater
-        * @param eventBus
-        *            The event bus
-        * @param database
-        *            The database
-        */
+       private final MetricRegistry metricRegistry;
+       private final Histogram configurationSaveTimeHistogram;
+
+       private final SoneUriCreator soneUriCreator;
+
        @Inject
-       public Core(Configuration configuration, FreenetInterface freenetInterface, IdentityManager identityManager, SoneDownloader soneDownloader, ImageInserter imageInserter, UpdateChecker updateChecker, WebOfTrustUpdater webOfTrustUpdater, EventBus eventBus, Database database) {
+       public Core(Configuration configuration, FreenetInterface freenetInterface, IdentityManager identityManager, SoneDownloader soneDownloader, ImageInserter imageInserter, UpdateChecker updateChecker, WebOfTrustUpdater webOfTrustUpdater, EventBus eventBus, Database database, MetricRegistry metricRegistry, SoneUriCreator soneUriCreator) {
                super("Sone Core");
                this.configuration = configuration;
                this.freenetInterface = freenetInterface;
@@ -212,7 +194,10 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                this.webOfTrustUpdater = webOfTrustUpdater;
                this.eventBus = eventBus;
                this.database = database;
+               this.metricRegistry = metricRegistry;
+               this.soneUriCreator = soneUriCreator;
                preferences = new Preferences(eventBus);
+               this.configurationSaveTimeHistogram = metricRegistry.histogram("configuration.save.duration", () -> new Histogram(new ExponentiallyDecayingReservoir(3000, 0)));
        }
 
        //
@@ -228,6 +213,16 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                return startupTime;
        }
 
+       @Nonnull
+       public boolean getDebug() {
+               return debug.get();
+       }
+
+       public void setDebug() {
+               debug.set(true);
+               eventBus.post(new DebugActivatedEvent());
+       }
+
        /**
         * Returns the options used by the core.
         *
@@ -618,7 +613,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                sone.setLatestEdition(fromNullable(tryParse(property)).or(0L));
                sone.setClient(new Client("Sone", SonePlugin.getPluginVersion()));
                sone.setKnown(true);
-               SoneInserter soneInserter = new SoneInserter(this, eventBus, freenetInterface, ownIdentity.getId());
+               SoneInserter soneInserter = new SoneInserter(this, eventBus, freenetInterface, metricRegistry, soneUriCreator, ownIdentity.getId());
                soneInserter.insertionDelayChanged(new InsertionDelayChangedEvent(preferences.getInsertionDelay()));
                eventBus.register(soneInserter);
                synchronized (soneInserters) {
@@ -627,6 +622,11 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                loadSone(sone);
                database.storeSone(sone);
                sone.setStatus(SoneStatus.idle);
+               if (sone.getPosts().isEmpty() && sone.getReplies().isEmpty() && getAllImages(sone.getRootAlbum()).isEmpty()) {
+                       // dirty hack
+                       lockSone(sone);
+                       eventBus.post(new SoneLockedOnStartup(sone));
+               }
                soneInserter.start();
                return sone;
        }
@@ -738,75 +738,6 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
        }
 
        /**
-        * Sets the trust value of the given origin Sone for the target Sone.
-        *
-        * @param origin
-        *            The origin Sone
-        * @param target
-        *            The target Sone
-        * @param trustValue
-        *            The trust value (from {@code -100} to {@code 100})
-        */
-       public void setTrust(Sone origin, Sone target, int trustValue) {
-               checkNotNull(origin, "origin must not be null");
-               checkArgument(origin.getIdentity() instanceof OwnIdentity, "origin must be a local Sone");
-               checkNotNull(target, "target must not be null");
-               checkArgument((trustValue >= -100) && (trustValue <= 100), "trustValue must be within [-100, 100]");
-               webOfTrustUpdater.setTrust((OwnIdentity) origin.getIdentity(), target.getIdentity(), trustValue, preferences.getTrustComment());
-       }
-
-       /**
-        * Removes any trust assignment for the given target Sone.
-        *
-        * @param origin
-        *            The trust origin
-        * @param target
-        *            The trust target
-        */
-       public void removeTrust(Sone origin, Sone target) {
-               checkNotNull(origin, "origin must not be null");
-               checkNotNull(target, "target must not be null");
-               checkArgument(origin.getIdentity() instanceof OwnIdentity, "origin must be a local Sone");
-               webOfTrustUpdater.setTrust((OwnIdentity) origin.getIdentity(), target.getIdentity(), null, null);
-       }
-
-       /**
-        * Assigns the configured positive trust value for the given target.
-        *
-        * @param origin
-        *            The trust origin
-        * @param target
-        *            The trust target
-        */
-       public void trustSone(Sone origin, Sone target) {
-               setTrust(origin, target, preferences.getPositiveTrust());
-       }
-
-       /**
-        * Assigns the configured negative trust value for the given target.
-        *
-        * @param origin
-        *            The trust origin
-        * @param target
-        *            The trust target
-        */
-       public void distrustSone(Sone origin, Sone target) {
-               setTrust(origin, target, preferences.getNegativeTrust());
-       }
-
-       /**
-        * Removes the trust assignment for the given target.
-        *
-        * @param origin
-        *            The trust origin
-        * @param target
-        *            The trust target
-        */
-       public void untrustSone(Sone origin, Sone target) {
-               removeTrust(origin, target);
-       }
-
-       /**
         * Updates the stored Sone with the given Sone.
         *
         * @param sone
@@ -866,9 +797,9 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                }
                for (PostReply postReply : soneComparison.getNewPostReplies()) {
                        if (postReply.getSone().equals(newSone)) {
-                               postReply.setKnown(true);
+                               database.setPostReplyKnown(postReply);
                        } else if (postReply.getTime() < database.getFollowingTime(newSone.getId())) {
-                               postReply.setKnown(true);
+                               database.setPostReplyKnown(postReply);
                        } else if (!postReply.isKnown()) {
                                events.add(new NewPostReplyFoundEvent(postReply));
                        }
@@ -1045,7 +976,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                        post.setKnown(true);
                }
                for (PostReply reply : replies) {
-                       reply.setKnown(true);
+                       database.setPostReplyKnown(reply);
                }
 
                logger.info(String.format("Sone loaded successfully: %s", sone));
@@ -1063,7 +994,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         *            The text of the post
         * @return The created post
         */
-       public Post createPost(Sone sone, Optional<Sone> recipient, String text) {
+       public Post createPost(Sone sone, @Nullable Sone recipient, String text) {
                checkNotNull(text, "text must not be null");
                checkArgument(text.trim().length() > 0, "text must not be empty");
                if (!sone.isLocal()) {
@@ -1072,8 +1003,8 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                }
                PostBuilder postBuilder = database.newPostBuilder();
                postBuilder.from(sone.getId()).randomId().currentTime().withText(text.trim());
-               if (recipient.isPresent()) {
-                       postBuilder.to(recipient.get().getId());
+               if (recipient != null) {
+                       postBuilder.to(recipient.getId());
                }
                final Post post = postBuilder.build();
                database.storePost(post);
@@ -1187,7 +1118,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         */
        public void markReplyKnown(PostReply reply) {
                boolean previouslyKnown = reply.isKnown();
-               reply.setKnown(true);
+               database.setPostReplyKnown(reply);
                eventBus.post(new MarkPostReplyKnownEvent(reply));
                if (!previouslyKnown) {
                        touchConfiguration();
@@ -1359,7 +1290,8 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                synchronized (soneInserters) {
                        for (Entry<Sone, SoneInserter> soneInserter : soneInserters.entrySet()) {
                                soneInserter.getValue().stop();
-                               saveSone(soneInserter.getKey());
+                               Sone latestSone = getLocalSone(soneInserter.getKey().getId());
+                               saveSone(latestSone);
                        }
                }
                synchronized (soneRescuers) {
@@ -1460,7 +1392,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                        configuration.getStringValue(sonePrefix + "/Likes/Reply/" + replyLikeCounter + "/ID").setValue(null);
 
                        /* save albums. first, collect in a flat structure, top-level first. */
-                       List<Album> albums = FluentIterable.from(sone.getRootAlbum().getAlbums()).transformAndConcat(Album.FLATTENER).toList();
+                       List<Album> albums = SoneKt.getAllAlbums(sone);
 
                        int albumCounter = 0;
                        for (Album album : albums) {
@@ -1501,8 +1433,6 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                        configuration.getStringValue(sonePrefix + "/Options/ShowCustomAvatars").setValue(sone.getOptions().getShowCustomAvatars().name());
                        configuration.getStringValue(sonePrefix + "/Options/LoadLinkedImages").setValue(sone.getOptions().getLoadLinkedImages().name());
 
-                       configuration.save();
-
                        webOfTrustUpdater.setProperty((OwnIdentity) sone.getIdentity(), "Sone.LatestEdition", String.valueOf(sone.getLatestEdition()));
 
                        logger.log(Level.INFO, String.format("Sone %s saved.", sone));
@@ -1540,7 +1470,9 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
                        database.save();
 
                        /* now save it. */
+                       Stopwatch stopwatch = Stopwatch.createStarted();
                        configuration.save();
+                       configurationSaveTimeHistogram.update(stopwatch.elapsed(TimeUnit.MICROSECONDS));
 
                } catch (ConfigurationException ce1) {
                        logger.log(Level.SEVERE, "Could not store configuration!", ce1);
@@ -1580,7 +1512,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         */
        @Subscribe
        public void ownIdentityAdded(OwnIdentityAddedEvent ownIdentityAddedEvent) {
-               OwnIdentity ownIdentity = ownIdentityAddedEvent.ownIdentity();
+               OwnIdentity ownIdentity = ownIdentityAddedEvent.getOwnIdentity();
                logger.log(Level.FINEST, String.format("Adding OwnIdentity: %s", ownIdentity));
                if (ownIdentity.hasContext("Sone")) {
                        addLocalSone(ownIdentity);
@@ -1595,7 +1527,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         */
        @Subscribe
        public void ownIdentityRemoved(OwnIdentityRemovedEvent ownIdentityRemovedEvent) {
-               OwnIdentity ownIdentity = ownIdentityRemovedEvent.ownIdentity();
+               OwnIdentity ownIdentity = ownIdentityRemovedEvent.getOwnIdentity();
                logger.log(Level.FINEST, String.format("Removing OwnIdentity: %s", ownIdentity));
                trustedIdentities.removeAll(ownIdentity);
        }
@@ -1608,9 +1540,9 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         */
        @Subscribe
        public void identityAdded(IdentityAddedEvent identityAddedEvent) {
-               Identity identity = identityAddedEvent.identity();
+               Identity identity = identityAddedEvent.getIdentity();
                logger.log(Level.FINEST, String.format("Adding Identity: %s", identity));
-               trustedIdentities.put(identityAddedEvent.ownIdentity(), identity);
+               trustedIdentities.put(identityAddedEvent.getOwnIdentity(), identity);
                addRemoteSone(identity);
        }
 
@@ -1622,7 +1554,7 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         */
        @Subscribe
        public void identityUpdated(IdentityUpdatedEvent identityUpdatedEvent) {
-               Identity identity = identityUpdatedEvent.identity();
+               Identity identity = identityUpdatedEvent.getIdentity();
                final Sone sone = getRemoteSone(identity.getId());
                if (sone.isLocal()) {
                        return;
@@ -1646,8 +1578,8 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         */
        @Subscribe
        public void identityRemoved(IdentityRemovedEvent identityRemovedEvent) {
-               OwnIdentity ownIdentity = identityRemovedEvent.ownIdentity();
-               Identity identity = identityRemovedEvent.identity();
+               OwnIdentity ownIdentity = identityRemovedEvent.getOwnIdentity();
+               Identity identity = identityRemovedEvent.getIdentity();
                trustedIdentities.remove(ownIdentity, identity);
                for (Entry<OwnIdentity, Collection<Identity>> trustedIdentity : trustedIdentities.asMap().entrySet()) {
                        if (trustedIdentity.getKey().equals(ownIdentity)) {
@@ -1680,9 +1612,9 @@ public class Core extends AbstractService implements SoneProvider, PostProvider,
         */
        @Subscribe
        public void imageInsertFinished(ImageInsertFinishedEvent imageInsertFinishedEvent) {
-               logger.log(Level.WARNING, String.format("Image insert finished for %s: %s", imageInsertFinishedEvent.image(), imageInsertFinishedEvent.resultingUri()));
-               imageInsertFinishedEvent.image().modify().setKey(imageInsertFinishedEvent.resultingUri().toString()).update();
-               deleteTemporaryImage(imageInsertFinishedEvent.image().getId());
+               logger.log(Level.WARNING, String.format("Image insert finished for %s: %s", imageInsertFinishedEvent.getImage(), imageInsertFinishedEvent.getResultingUri()));
+               imageInsertFinishedEvent.getImage().modify().setKey(imageInsertFinishedEvent.getResultingUri().toString()).update();
+               deleteTemporaryImage(imageInsertFinishedEvent.getImage().getId());
                touchConfiguration();
        }
 
index 1ed2024..35ac6a1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - FreenetInterface.java - Copyright © 2010–2019 David Roden
+ * Sone - FreenetInterface.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,7 +21,6 @@ import static freenet.keys.USK.create;
 import static java.lang.String.format;
 import static java.util.logging.Level.WARNING;
 import static java.util.logging.Logger.getLogger;
-import static net.pterodactylus.sone.freenet.Key.routingKey;
 
 import java.io.IOException;
 import java.net.MalformedURLException;
@@ -75,6 +74,7 @@ import freenet.support.api.Bucket;
 import freenet.support.api.RandomAccessBucket;
 import freenet.support.io.ArrayBucket;
 import freenet.support.io.ResumeFailedException;
+import net.pterodactylus.sone.freenet.*;
 
 /**
  * Contains all necessary functionality for interacting with the Freenet node.
@@ -91,6 +91,8 @@ public class FreenetInterface {
        /** The node to interact with. */
        private final Node node;
 
+       private final SoneUriCreator soneUriCreator;
+
        /** The high-level client to use for requests. */
        private final HighLevelSimpleClient client;
        private final RequestClient requestClient = new RequestClientBuilder().realTime().build();
@@ -104,18 +106,11 @@ public class FreenetInterface {
        private final RequestClient imageInserts = new RequestClientBuilder().realTime().build();
        private final RequestClient imageLoader = new RequestClientBuilder().realTime().build();
 
-       /**
-        * Creates a new Freenet interface.
-        *
-        * @param eventBus
-        *            The event bus
-        * @param node
-        *            The node to interact with
-        */
        @Inject
-       public FreenetInterface(EventBus eventBus, Node node) {
+       public FreenetInterface(EventBus eventBus, Node node, SoneUriCreator soneUriCreator) {
                this.eventBus = eventBus;
                this.node = node;
+               this.soneUriCreator = soneUriCreator;
                this.client = node.clientCore.makeClient(RequestStarter.INTERACTIVE_PRIORITY_CLASS, false, true);
        }
 
@@ -255,7 +250,7 @@ public class FreenetInterface {
        public void registerActiveUsk(FreenetURI requestUri,
                        USKCallback uskCallback) {
                try {
-                       soneUskCallbacks.put(routingKey(requestUri), uskCallback);
+                       soneUskCallbacks.put(FreenetURIsKt.getRoutingKeyString(requestUri), uskCallback);
                        node.clientCore.uskManager.subscribe(create(requestUri),
                                        uskCallback, true, requestClient);
                } catch (MalformedURLException mue1) {
@@ -267,7 +262,7 @@ public class FreenetInterface {
        public void registerPassiveUsk(FreenetURI requestUri,
                        USKCallback uskCallback) {
                try {
-                       soneUskCallbacks.put(routingKey(requestUri), uskCallback);
+                       soneUskCallbacks.put(FreenetURIsKt.getRoutingKeyString(requestUri), uskCallback);
                        node.clientCore
                                        .uskManager
                                        .subscribe(create(requestUri), uskCallback, false, requestClient);
@@ -291,9 +286,9 @@ public class FreenetInterface {
                }
                try {
                        logger.log(Level.FINEST, String.format("Unsubscribing from USK for %s…", sone));
-                       node.clientCore.uskManager.unsubscribe(USK.create(sone.getRequestUri()), uskCallback);
+                       node.clientCore.uskManager.unsubscribe(USK.create(soneUriCreator.getRequestUri(sone)), uskCallback);
                } catch (MalformedURLException mue1) {
-                       logger.log(Level.FINE, String.format("Could not unsubscribe USK “%s”!", sone.getRequestUri()), mue1);
+                       logger.log(Level.FINE, String.format("Could not unsubscribe USK “%s”!", soneUriCreator.getRequestUri(sone)), mue1);
                }
        }
 
@@ -327,7 +322,7 @@ public class FreenetInterface {
                };
                try {
                        node.clientCore.uskManager.subscribe(USK.create(uri), uskCallback, true, requestClient);
-                       uriUskCallbacks.put(uri, uskCallback);
+                       uriUskCallbacks.put(USK.create(uri).clearCopy().getURI(), uskCallback);
                } catch (MalformedURLException mue1) {
                        logger.log(Level.WARNING, String.format("Could not subscribe to USK: %s", uri), mue1);
                }
@@ -340,12 +335,12 @@ public class FreenetInterface {
         *            The URI to unregister the USK watcher for
         */
        public void unregisterUsk(FreenetURI uri) {
-               USKCallback uskCallback = uriUskCallbacks.remove(uri);
-               if (uskCallback == null) {
-                       logger.log(Level.INFO, String.format("Could not unregister unknown USK: %s", uri));
-                       return;
-               }
                try {
+                       USKCallback uskCallback = uriUskCallbacks.remove(USK.create(uri).clearCopy().getURI());
+                       if (uskCallback == null) {
+                               logger.log(Level.INFO, String.format("Could not unregister unknown USK: %s", uri));
+                               return;
+                       }
                        node.clientCore.uskManager.unsubscribe(USK.create(uri), uskCallback);
                } catch (MalformedURLException mue1) {
                        logger.log(Level.INFO, String.format("Could not unregister invalid USK: %s", uri), mue1);
index fc76ca9..76519f4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - ImageInserter.java - Copyright © 2011–2019 David Roden
+ * Sone - ImageInserter.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index af88dd8..398374a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - Options.java - Copyright © 2010–2019 David Roden
+ * Sone - Options.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -23,8 +23,6 @@ import java.util.Map;
 
 import net.pterodactylus.sone.utils.Option;
 
-import com.google.common.base.Predicate;
-
 /**
  * Stores various options that influence Sone’s behaviour.
  */
diff --git a/src/main/java/net/pterodactylus/sone/core/PreferenceChangedEvent.kt b/src/main/java/net/pterodactylus/sone/core/PreferenceChangedEvent.kt
deleted file mode 100644 (file)
index 2ebb62d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-package net.pterodactylus.sone.core
-
-data class PreferenceChangedEvent(val preferenceName: String, val newValue: Any)
diff --git a/src/main/java/net/pterodactylus/sone/core/PreferencesLoader.java b/src/main/java/net/pterodactylus/sone/core/PreferencesLoader.java
deleted file mode 100644 (file)
index a730983..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-package net.pterodactylus.sone.core;
-
-import net.pterodactylus.sone.fcp.FcpInterface.FullAccessRequired;
-import net.pterodactylus.util.config.Configuration;
-import net.pterodactylus.util.config.ConfigurationException;
-
-/**
- * Loads preferences stored in a {@link Configuration} into a {@link
- * Preferences} object.
- */
-public class PreferencesLoader {
-
-       private final Preferences preferences;
-
-       public PreferencesLoader(Preferences preferences) {
-               this.preferences = preferences;
-       }
-
-       public void loadFrom(Configuration configuration) {
-               loadInsertionDelay(configuration);
-               loadPostsPerPage(configuration);
-               loadImagesPerPage(configuration);
-               loadCharactersPerPost(configuration);
-               loadPostCutOffLength(configuration);
-               loadRequireFullAccess(configuration);
-               loadPositiveTrust(configuration);
-               loadNegativeTrust(configuration);
-               loadTrustComment(configuration);
-               loadFcpInterfaceActive(configuration);
-               loadFcpFullAccessRequired(configuration);
-       }
-
-       private void loadInsertionDelay(Configuration configuration) {
-               preferences.setNewInsertionDelay(configuration.getIntValue(
-                               "Option/InsertionDelay").getValue(null));
-       }
-
-       private void loadPostsPerPage(Configuration configuration) {
-               preferences.setNewPostsPerPage(
-                               configuration.getIntValue("Option/PostsPerPage")
-                                               .getValue(null));
-       }
-
-       private void loadImagesPerPage(Configuration configuration) {
-               preferences.setNewImagesPerPage(
-                               configuration.getIntValue("Option/ImagesPerPage")
-                                               .getValue(null));
-       }
-
-       private void loadCharactersPerPost(Configuration configuration) {
-               preferences.setNewCharactersPerPost(
-                               configuration.getIntValue("Option/CharactersPerPost")
-                                               .getValue(null));
-       }
-
-       private void loadPostCutOffLength(Configuration configuration) {
-               try {
-                       preferences.setNewPostCutOffLength(
-                                       configuration.getIntValue("Option/PostCutOffLength")
-                                                       .getValue(null));
-               } catch (IllegalArgumentException iae1) {
-                       /* previous versions allowed -1, ignore and use default. */
-               }
-       }
-
-       private void loadRequireFullAccess(Configuration configuration) {
-               preferences.setNewRequireFullAccess(
-                               configuration.getBooleanValue("Option/RequireFullAccess")
-                                               .getValue(null));
-       }
-
-       private void loadPositiveTrust(Configuration configuration) {
-               preferences.setNewPositiveTrust(
-                               configuration.getIntValue("Option/PositiveTrust")
-                                               .getValue(null));
-       }
-
-       private void loadNegativeTrust(Configuration configuration) {
-               preferences.setNewNegativeTrust(
-                               configuration.getIntValue("Option/NegativeTrust")
-                                               .getValue(null));
-       }
-
-       private void loadTrustComment(Configuration configuration) {
-               preferences.setNewTrustComment(
-                               configuration.getStringValue("Option/TrustComment")
-                                               .getValue(null));
-       }
-
-       private void loadFcpInterfaceActive(Configuration configuration) {
-               preferences.setNewFcpInterfaceActive(configuration.getBooleanValue(
-                               "Option/ActivateFcpInterface").getValue(null));
-       }
-
-       private void loadFcpFullAccessRequired(Configuration configuration) {
-               Integer fullAccessRequiredInteger = configuration
-                               .getIntValue("Option/FcpFullAccessRequired").getValue(null);
-               preferences.setNewFcpFullAccessRequired(
-                               (fullAccessRequiredInteger == null) ? null :
-                                               FullAccessRequired.values()[fullAccessRequiredInteger]);
-       }
-
-}
index ba1c632..43a87fb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - SoneDownloaderImpl.java - Copyright © 2010–2019 David Roden
+ * Sone - SoneDownloaderImpl.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -17,7 +17,6 @@
 
 package net.pterodactylus.sone.core;
 
-import static freenet.support.io.Closer.close;
 import static java.lang.String.format;
 import static java.lang.System.currentTimeMillis;
 import static java.util.concurrent.TimeUnit.DAYS;
@@ -183,23 +182,19 @@ public class SoneDownloaderImpl extends AbstractService implements SoneDownloade
         * @return The parsed Sone, or {@code null} if the Sone could not be parsed
         */
        private Sone parseSone(Sone originalSone, FetchResult fetchResult, FreenetURI requestUri) {
-               logger.log(Level.FINEST, String.format("Parsing FetchResult (%d bytes, %s) for %s…", fetchResult.size(), fetchResult.getMimeType(), originalSone));
+               logger.finest(() -> format("Parsing FetchResult (%d bytes, %s) for %s…", fetchResult.size(), fetchResult.getMimeType(), originalSone));
                Bucket soneBucket = fetchResult.asBucket();
-               InputStream soneInputStream = null;
-               try {
-                       soneInputStream = soneBucket.getInputStream();
-                       Sone parsedSone = soneParser.parseSone(originalSone,
-                                       soneInputStream);
+               try (InputStream soneInputStream = soneBucket.getInputStream()) {
+                       Sone parsedSone = soneParser.parseSone(originalSone, soneInputStream);
                        if (parsedSone != null) {
-                               logger.log(Level.FINER, "Sone %s was successfully parsed.", parsedSone);
+                               logger.finer(() -> format("Sone %s was successfully parsed.", parsedSone));
                                parsedSone.setLatestEdition(requestUri.getEdition());
                        }
                        return parsedSone;
                } catch (Exception e1) {
-                       logger.log(Level.WARNING, String.format("Could not parse Sone from %s!", requestUri), e1);
+                       logger.log(Level.WARNING, e1, () -> format("Could not parse Sone from %s!", requestUri));
                } finally {
-                       close(soneInputStream);
-                       close(soneBucket);
+                       soneBucket.free();
                }
                return null;
        }
index e460ee7..152f629 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - SoneException.java - Copyright © 2010–2019 David Roden
+ * Sone - SoneException.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 8a0ff53..4aa71c1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - SoneInsertException.java - Copyright © 2011–2019 David Roden
+ * Sone - SoneInsertException.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 79a6259..fcbe1b5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - SoneInserter.java - Copyright © 2010–2019 David Roden
+ * Sone - SoneInserter.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,13 +19,13 @@ package net.pterodactylus.sone.core;
 
 import static java.lang.String.format;
 import static java.lang.System.currentTimeMillis;
+import static java.util.concurrent.TimeUnit.*;
 import static java.util.logging.Logger.getLogger;
-import static net.pterodactylus.sone.data.Album.NOT_EMPTY;
+import static java.util.stream.Collectors.toList;
+import static net.pterodactylus.sone.data.PostKt.newestPostFirst;
+import static net.pterodactylus.sone.data.ReplyKt.newestReplyFirst;
 
-import java.io.Closeable;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.StringWriter;
+import java.io.*;
 import java.nio.charset.Charset;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -35,18 +35,18 @@ import java.util.concurrent.atomic.AtomicInteger;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import com.codahale.metrics.*;
+import com.google.common.base.*;
 import net.pterodactylus.sone.core.SoneModificationDetector.LockableFingerprintProvider;
 import net.pterodactylus.sone.core.event.InsertionDelayChangedEvent;
 import net.pterodactylus.sone.core.event.SoneInsertAbortedEvent;
 import net.pterodactylus.sone.core.event.SoneInsertedEvent;
 import net.pterodactylus.sone.core.event.SoneInsertingEvent;
-import net.pterodactylus.sone.data.Album;
-import net.pterodactylus.sone.data.Post;
-import net.pterodactylus.sone.data.Reply;
+import net.pterodactylus.sone.data.AlbumKt;
 import net.pterodactylus.sone.data.Sone;
 import net.pterodactylus.sone.data.Sone.SoneStatus;
+import net.pterodactylus.sone.data.SoneKt;
 import net.pterodactylus.sone.main.SonePlugin;
-import net.pterodactylus.util.io.Closer;
 import net.pterodactylus.util.service.AbstractService;
 import net.pterodactylus.util.template.HtmlFilter;
 import net.pterodactylus.util.template.ReflectionAccessor;
@@ -58,8 +58,6 @@ import net.pterodactylus.util.template.TemplateParser;
 import net.pterodactylus.util.template.XmlFilter;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Charsets;
-import com.google.common.collect.FluentIterable;
 import com.google.common.collect.Ordering;
 import com.google.common.eventbus.EventBus;
 import com.google.common.eventbus.Subscribe;
@@ -103,8 +101,11 @@ public class SoneInserter extends AbstractService {
        private final FreenetInterface freenetInterface;
 
        private final SoneModificationDetector soneModificationDetector;
+       private final SoneUriCreator soneUriCreator;
        private final long delay;
        private final String soneId;
+       private final Histogram soneInsertDurationHistogram;
+       private final Meter soneInsertErrorMeter;
 
        /**
         * Creates a new Sone inserter.
@@ -118,8 +119,8 @@ public class SoneInserter extends AbstractService {
         * @param soneId
         *            The ID of the Sone to insert
         */
-       public SoneInserter(final Core core, EventBus eventBus, FreenetInterface freenetInterface, final String soneId) {
-               this(core, eventBus, freenetInterface, soneId, new SoneModificationDetector(new LockableFingerprintProvider() {
+       public SoneInserter(final Core core, EventBus eventBus, FreenetInterface freenetInterface, MetricRegistry metricRegistry, SoneUriCreator soneUriCreator, final String soneId) {
+               this(core, eventBus, freenetInterface, metricRegistry, soneUriCreator, soneId, new SoneModificationDetector(new LockableFingerprintProvider() {
                        @Override
                        public boolean isLocked() {
                                Sone sone = core.getSone(soneId);
@@ -141,11 +142,14 @@ public class SoneInserter extends AbstractService {
        }
 
        @VisibleForTesting
-       SoneInserter(Core core, EventBus eventBus, FreenetInterface freenetInterface, String soneId, SoneModificationDetector soneModificationDetector, long delay) {
+       SoneInserter(Core core, EventBus eventBus, FreenetInterface freenetInterface, MetricRegistry metricRegistry, SoneUriCreator soneUriCreator, String soneId, SoneModificationDetector soneModificationDetector, long delay) {
                super("Sone Inserter for “" + soneId + "”", false);
                this.core = core;
                this.eventBus = eventBus;
                this.freenetInterface = freenetInterface;
+               this.soneInsertDurationHistogram = metricRegistry.histogram("sone.insert.duration", () -> new Histogram(new ExponentiallyDecayingReservoir(3000, 0)));
+               this.soneInsertErrorMeter = metricRegistry.meter("sone.insert.errors");
+               this.soneUriCreator = soneUriCreator;
                this.soneId = soneId;
                this.soneModificationDetector = soneModificationDetector;
                this.delay = delay;
@@ -229,8 +233,11 @@ public class SoneInserter extends AbstractService {
                                                sone.setStatus(SoneStatus.inserting);
                                                long insertTime = currentTimeMillis();
                                                eventBus.post(new SoneInsertingEvent(sone));
-                                               FreenetURI finalUri = freenetInterface.insertDirectory(sone.getInsertUri(), insertInformation.generateManifestEntries(), "index.html");
-                                               eventBus.post(new SoneInsertedEvent(sone, currentTimeMillis() - insertTime, insertInformation.getFingerprint()));
+                                               Stopwatch stopwatch = Stopwatch.createStarted();
+                                               FreenetURI finalUri = freenetInterface.insertDirectory(soneUriCreator.getInsertUri(sone), insertInformation.generateManifestEntries(), "index.html");
+                                               stopwatch.stop();
+                                               soneInsertDurationHistogram.update(stopwatch.elapsed(MICROSECONDS));
+                                               eventBus.post(new SoneInsertedEvent(sone, stopwatch.elapsed(MILLISECONDS), insertInformation.getFingerprint()));
                                                /* at this point we might already be stopped. */
                                                if (shouldStop()) {
                                                        /* if so, bail out, don’t change anything. */
@@ -242,6 +249,7 @@ public class SoneInserter extends AbstractService {
                                                success = true;
                                                logger.log(Level.INFO, String.format("Inserted Sone “%s” at %s.", sone.getName(), finalUri));
                                        } catch (SoneException se1) {
+                                               soneInsertErrorMeter.mark();
                                                eventBus.post(new SoneInsertAbortedEvent(sone, se1));
                                                logger.log(Level.WARNING, String.format("Could not insert Sone “%s”!", sone.getName()), se1);
                                        } finally {
@@ -299,13 +307,12 @@ public class SoneInserter extends AbstractService {
                        soneProperties.put("id", sone.getId());
                        soneProperties.put("name", sone.getName());
                        soneProperties.put("time", currentTimeMillis());
-                       soneProperties.put("requestUri", sone.getRequestUri());
                        soneProperties.put("profile", sone.getProfile());
-                       soneProperties.put("posts", Ordering.from(Post.NEWEST_FIRST).sortedCopy(sone.getPosts()));
-                       soneProperties.put("replies", Ordering.from(Reply.TIME_COMPARATOR).reverse().sortedCopy(sone.getReplies()));
+                       soneProperties.put("posts", Ordering.from(newestPostFirst()).sortedCopy(sone.getPosts()));
+                       soneProperties.put("replies", Ordering.from(newestReplyFirst()).sortedCopy(sone.getReplies()));
                        soneProperties.put("likedPostIds", new HashSet<>(sone.getLikedPostIds()));
                        soneProperties.put("likedReplyIds", new HashSet<>(sone.getLikedReplyIds()));
-                       soneProperties.put("albums", FluentIterable.from(sone.getRootAlbum().getAlbums()).transformAndConcat(Album.FLATTENER).filter(NOT_EMPTY).toList());
+                       soneProperties.put("albums", SoneKt.getAllAlbums(sone).stream().filter(AlbumKt.notEmpty()::invoke).collect(toList()));
                        manifestCreator = new ManifestCreator(core, soneProperties);
                }
 
@@ -366,19 +373,13 @@ public class SoneInserter extends AbstractService {
                }
 
                public ManifestElement createManifestElement(String name, String contentType, String templateName) {
-                       InputStreamReader templateInputStreamReader = null;
-                       InputStream templateInputStream = null;
                        Template template;
-                       try {
-                               templateInputStream = getClass().getResourceAsStream(templateName);
-                               templateInputStreamReader = new InputStreamReader(templateInputStream, utf8Charset);
+                       try (InputStream templateInputStream = getClass().getResourceAsStream(templateName);
+                                       InputStreamReader templateInputStreamReader = new InputStreamReader(templateInputStream, utf8Charset)) {
                                template = TemplateParser.parse(templateInputStreamReader);
-                       } catch (TemplateException te1) {
-                               logger.log(Level.SEVERE, String.format("Could not parse template “%s”!", templateName), te1);
+                       } catch (IOException | TemplateException e1) {
+                               logger.log(Level.SEVERE, String.format("Could not parse template “%s”!", templateName), e1);
                                return null;
-                       } finally {
-                               Closer.close(templateInputStreamReader);
-                               Closer.close(templateInputStream);
                        }
 
                        TemplateContext templateContext = templateContextFactory.createTemplateContext();
@@ -386,17 +387,14 @@ public class SoneInserter extends AbstractService {
                        templateContext.set("currentSone", soneProperties);
                        templateContext.set("currentEdition", core.getUpdateChecker().getLatestEdition());
                        templateContext.set("version", SonePlugin.getPluginVersion());
-                       StringWriter writer = new StringWriter();
-                       try {
+                       try (StringWriter writer = new StringWriter()) {
                                template.render(templateContext, writer);
                                RandomAccessBucket bucket = new ArrayBucket(writer.toString().getBytes(Charsets.UTF_8));
                                buckets.add(bucket);
                                return new ManifestElement(name, bucket, contentType, bucket.size());
-                       } catch (TemplateException te1) {
-                               logger.log(Level.SEVERE, String.format("Could not render template “%s”!", templateName), te1);
+                       } catch (IOException | TemplateException e1) {
+                               logger.log(Level.SEVERE, String.format("Could not render template “%s”!", templateName), e1);
                                return null;
-                       } finally {
-                               Closer.close(writer);
                        }
                }
 
index 92fa3dc..793d332 100644 (file)
@@ -1,7 +1,5 @@
 package net.pterodactylus.sone.core;
 
-import static com.google.common.base.Optional.absent;
-import static com.google.common.base.Optional.of;
 import static com.google.common.base.Ticker.systemTicker;
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
 
@@ -11,7 +9,6 @@ import net.pterodactylus.sone.data.Sone;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Objects;
-import com.google.common.base.Optional;
 import com.google.common.base.Ticker;
 
 /**
@@ -24,7 +21,7 @@ class SoneModificationDetector {
        private final Ticker ticker;
        private final LockableFingerprintProvider lockableFingerprintProvider;
        private final AtomicInteger insertionDelay;
-       private Optional<Long> lastModificationTime;
+       private Long lastModificationTime;
        private String lastInsertFingerprint;
        private String lastCheckFingerprint;
 
@@ -42,18 +39,18 @@ class SoneModificationDetector {
 
        public boolean isEligibleForInsert() {
                if (lockableFingerprintProvider.isLocked()) {
-                       lastModificationTime = absent();
+                       lastModificationTime = null;
                        lastCheckFingerprint = "";
                        return false;
                }
                String fingerprint = lockableFingerprintProvider.getFingerprint();
                if (fingerprint.equals(lastInsertFingerprint)) {
-                       lastModificationTime = absent();
+                       lastModificationTime = null;
                        lastCheckFingerprint = fingerprint;
                        return false;
                }
                if (!Objects.equal(lastCheckFingerprint, fingerprint)) {
-                       lastModificationTime = of(ticker.read());
+                       lastModificationTime = ticker.read();
                        lastCheckFingerprint = fingerprint;
                        return false;
                }
@@ -67,11 +64,11 @@ class SoneModificationDetector {
        public void setFingerprint(String fingerprint) {
                lastInsertFingerprint = fingerprint;
                lastCheckFingerprint = lastInsertFingerprint;
-               lastModificationTime = absent();
+               lastModificationTime = null;
        }
 
        private boolean insertionDelayHasPassed() {
-               return NANOSECONDS.toSeconds(ticker.read() - lastModificationTime.get()) >= insertionDelay.get();
+               return NANOSECONDS.toSeconds(ticker.read() - lastModificationTime) >= insertionDelay.get();
        }
 
        public boolean isModified() {
index 1f30565..e1fd9ff 100644 (file)
@@ -1,38 +1,24 @@
 package net.pterodactylus.sone.core;
 
-import static java.util.logging.Logger.getLogger;
-import static net.pterodactylus.sone.utils.NumberParsers.parseInt;
-import static net.pterodactylus.sone.utils.NumberParsers.parseLong;
+import static java.util.concurrent.TimeUnit.*;
+import static java.util.logging.Logger.*;
+import static net.pterodactylus.sone.utils.NumberParsers.*;
 
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
+import java.io.*;
+import java.util.*;
+import java.util.logging.*;
 
-import javax.inject.Inject;
+import javax.annotation.*;
+import javax.inject.*;
 
-import net.pterodactylus.sone.data.Album;
-import net.pterodactylus.sone.data.Client;
-import net.pterodactylus.sone.data.Image;
-import net.pterodactylus.sone.data.Post;
-import net.pterodactylus.sone.data.PostReply;
-import net.pterodactylus.sone.data.Profile;
-import net.pterodactylus.sone.data.Profile.DuplicateField;
-import net.pterodactylus.sone.data.Profile.EmptyFieldName;
-import net.pterodactylus.sone.data.Sone;
-import net.pterodactylus.sone.database.Database;
-import net.pterodactylus.sone.database.PostBuilder;
-import net.pterodactylus.sone.database.PostReplyBuilder;
-import net.pterodactylus.sone.database.SoneBuilder;
-import net.pterodactylus.util.xml.SimpleXML;
-import net.pterodactylus.util.xml.XML;
+import net.pterodactylus.sone.data.*;
+import net.pterodactylus.sone.data.Profile.*;
+import net.pterodactylus.sone.database.*;
+import net.pterodactylus.util.xml.*;
 
-import org.w3c.dom.Document;
+import com.codahale.metrics.*;
+import com.google.common.base.*;
+import org.w3c.dom.*;
 
 /**
  * Parses a {@link Sone} from an XML {@link InputStream}.
@@ -42,15 +28,19 @@ public class SoneParser {
        private static final Logger logger = getLogger(SoneParser.class.getName());
        private static final int MAX_PROTOCOL_VERSION = 0;
        private final Database database;
+       private final Histogram soneParsingDurationHistogram;
 
        @Inject
-       public SoneParser(Database database) {
+       public SoneParser(Database database, MetricRegistry metricRegistry) {
                this.database = database;
+               this.soneParsingDurationHistogram = metricRegistry.histogram("sone.parse.duration", () -> new Histogram(new ExponentiallyDecayingReservoir(3000, 0)));
        }
 
+       @Nullable
        public Sone parseSone(Sone originalSone, InputStream soneInputStream) throws SoneException {
                /* TODO - impose a size limit? */
 
+               Stopwatch stopwatch = Stopwatch.createStarted();
                Document document;
                /* XML parsing is not thread-safe. */
                synchronized (this) {
@@ -257,6 +247,7 @@ public class SoneParser {
                SimpleXML albumsXml = soneXml.getNode("albums");
                Map<String, Image> allImages = new HashMap<>();
                List<Album> topLevelAlbums = new ArrayList<>();
+               Map<String, Album> allAlbums = new HashMap<>();
                if (albumsXml != null) {
                        for (SimpleXML albumXml : albumsXml.getNodes("album")) {
                                String id = albumXml.getValue("id", null);
@@ -269,7 +260,7 @@ public class SoneParser {
                                }
                                Album parent = null;
                                if (parentId != null) {
-                                       parent = database.getAlbum(parentId);
+                                       parent = allAlbums.get(parentId);
                                        if (parent == null) {
                                                logger.log(Level.WARNING, String.format("Downloaded Sone %s has album with invalid parent!", sone));
                                                return null;
@@ -288,6 +279,7 @@ public class SoneParser {
                                } else {
                                        topLevelAlbums.add(album);
                                }
+                               allAlbums.put(album.getId(), album);
                                SimpleXML imagesXml = albumXml.getNode("images");
                                if (imagesXml != null) {
                                        for (SimpleXML imageXml : imagesXml.getNodes("image")) {
@@ -334,6 +326,11 @@ public class SoneParser {
                        sone.getRootAlbum().addAlbum(album);
                }
 
+               // record the duration
+               stopwatch.stop();
+               soneParsingDurationHistogram.update(stopwatch.elapsed(MICROSECONDS));
+               logger.fine(() -> "Parsed " + originalSone.getIdentity().getId() + "@" + originalSone.getLatestEdition() + " in " + stopwatch.elapsed(MICROSECONDS) + "μs.");
+
                return sone;
 
        }
index 2246ac9..2a1d14d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - SoneRescuer.java - Copyright © 2011–2019 David Roden
+ * Sone - SoneRescuer.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/src/main/java/net/pterodactylus/sone/core/SoneUri.java b/src/main/java/net/pterodactylus/sone/core/SoneUri.java
deleted file mode 100644 (file)
index 373077f..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Sone - SoneUri.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core;
-
-import static java.util.logging.Logger.getLogger;
-
-import java.net.MalformedURLException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import freenet.keys.FreenetURI;
-
-/**
- * Helper class that creates {@link FreenetURI}s for Sone to insert to and
- * request from.
- */
-public class SoneUri {
-
-       /** The logger. */
-       private static final Logger logger = getLogger(SoneUri.class.getName());
-
-       /**
-        * Generate a Sone URI from the given URI.
-        *
-        * @param uri
-        *            The URI to derive the Sone URI from
-        * @return The derived URI
-        */
-       public static FreenetURI create(String uri) {
-               try {
-                       return new FreenetURI(uri).setDocName("Sone").setMetaString(new String[0]);
-               } catch (MalformedURLException mue1) {
-                       /* this should never happen. */
-                       logger.log(Level.WARNING, String.format("Could not create Sone URI from URI: %s", uri), mue1);
-                       return null;
-               }
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/UpdateChecker.java b/src/main/java/net/pterodactylus/sone/core/UpdateChecker.java
deleted file mode 100644 (file)
index 9f6963f..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Sone - UpdateChecker.java - Copyright © 2011–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core;
-
-import static java.util.logging.Logger.getLogger;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.MalformedURLException;
-import java.util.Date;
-import java.util.Properties;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.inject.Singleton;
-
-import net.pterodactylus.sone.core.event.UpdateFoundEvent;
-import net.pterodactylus.sone.main.PluginHomepage;
-import net.pterodactylus.sone.main.SonePlugin;
-import net.pterodactylus.util.io.Closer;
-import net.pterodactylus.util.version.Version;
-
-import com.google.common.eventbus.EventBus;
-import com.google.inject.Inject;
-
-import freenet.keys.FreenetURI;
-import freenet.support.api.Bucket;
-
-/**
- * Watches the official Sone homepage for new releases.
- */
-@Singleton
-public class UpdateChecker {
-
-       /** The logger. */
-       private static final Logger logger = getLogger(UpdateChecker.class.getName());
-
-       /** The event bus. */
-       private final EventBus eventBus;
-
-       /** The Freenet interface. */
-       private final FreenetInterface freenetInterface;
-
-       /** The current URI of the homepage. */
-       private FreenetURI currentUri;
-
-       /** The latest known edition. */
-       private long latestEdition = SonePlugin.getLatestEdition();
-
-       /** The current latest known version. */
-       private Version currentLatestVersion;
-       private final Version currentRunningVersion;
-
-       /** The release date of the latest version. */
-       private long latestVersionDate;
-
-       private final PluginHomepage pluginHomepage;
-
-       /**
-        * Creates a new update checker.
-        *
-        * @param eventBus
-        *            The event bus
-        * @param freenetInterface
-        *            The freenet interface to use
-        */
-       @Inject
-       public UpdateChecker(EventBus eventBus, FreenetInterface freenetInterface, Version currentVersion, PluginHomepage pluginHomepage) {
-               this.eventBus = eventBus;
-               this.freenetInterface = freenetInterface;
-               this.currentRunningVersion = currentVersion;
-               this.currentLatestVersion = currentVersion;
-               this.pluginHomepage = pluginHomepage;
-       }
-
-       //
-       // ACCESSORS
-       //
-
-       /**
-        * Returns whether a version that is later than the currently running
-        * version has been found.
-        *
-        * @return {@code true} if a new version was found
-        */
-       public boolean hasLatestVersion() {
-               return currentLatestVersion.compareTo(currentRunningVersion) > 0;
-       }
-
-       /**
-        * Returns the latest version. If no new latest version has been found, the
-        * current version is returned.
-        *
-        * @return The latest known version
-        */
-       public Version getLatestVersion() {
-               return currentLatestVersion;
-       }
-
-       /**
-        * Returns the release time of the latest version. If no new latest version
-        * has been found, the returned value is undefined.
-        *
-        * @return The release time of the latest version, if a new version was
-        *         found
-        */
-       public long getLatestVersionDate() {
-               return latestVersionDate;
-       }
-
-       /**
-        * Returns the latest known edition of the Sone homepage.
-        *
-        * @return The latest edition of the Sone homepage
-        */
-       public long getLatestEdition() {
-               return latestEdition;
-       }
-
-       //
-       // ACTIONS
-       //
-
-       /**
-        * Starts the update checker.
-        */
-       public void start() {
-               try {
-                       currentUri = new FreenetURI(pluginHomepage.getHomepage());
-               } catch (MalformedURLException mue1) {
-                       /* this can not really happen unless I screw up. */
-                       logger.log(Level.SEVERE, "Sone Homepage URI invalid!", mue1);
-               }
-               freenetInterface.registerUsk(currentUri, new FreenetInterface.Callback() {
-
-                       @Override
-                       @SuppressWarnings("synthetic-access")
-                       public void editionFound(FreenetURI uri, long edition, boolean newKnownGood, boolean newSlot) {
-                               logger.log(Level.FINEST, String.format("Found update for %s: %d, %s, %s", uri, edition, newKnownGood, newSlot));
-                               if (newKnownGood || newSlot) {
-                                       Fetched uriResult = freenetInterface.fetchUri(uri.setMetaString(new String[] { "sone.properties" }));
-                                       if (uriResult == null) {
-                                               logger.log(Level.WARNING, String.format("Could not fetch properties of latest homepage: %s", uri));
-                                               return;
-                                       }
-                                       Bucket resultBucket = uriResult.getFetchResult().asBucket();
-                                       try {
-                                               parseProperties(resultBucket.getInputStream(), edition);
-                                               latestEdition = edition;
-                                       } catch (IOException ioe1) {
-                                               logger.log(Level.WARNING, String.format("Could not parse sone.properties of %s!", uri), ioe1);
-                                       } finally {
-                                               resultBucket.free();
-                                       }
-                               }
-                       }
-               });
-       }
-
-       /**
-        * Stops the update checker.
-        */
-       public void stop() {
-               freenetInterface.unregisterUsk(currentUri);
-       }
-
-       //
-       // PRIVATE ACTIONS
-       //
-
-       /**
-        * Parses the properties of the latest version and fires events, if
-        * necessary.
-        *
-        * @see UpdateFoundEvent
-        * @param propertiesInputStream
-        *            The input stream to parse
-        * @param edition
-        *            The latest edition of the Sone homepage
-        * @throws IOException
-        *             if an I/O error occured
-        */
-       private void parseProperties(InputStream propertiesInputStream, long edition) throws IOException {
-               Properties properties = new Properties();
-               InputStreamReader inputStreamReader = null;
-               try {
-                       inputStreamReader = new InputStreamReader(propertiesInputStream, "UTF-8");
-                       properties.load(inputStreamReader);
-               } finally {
-                       Closer.close(inputStreamReader);
-               }
-               String versionString = properties.getProperty("CurrentVersion/Version");
-               String releaseTimeString = properties.getProperty("CurrentVersion/ReleaseTime");
-               if ((versionString == null) || (releaseTimeString == null)) {
-                       logger.log(Level.INFO, "Invalid data parsed from properties.");
-                       return;
-               }
-               Version version = Version.parse(versionString);
-               long releaseTime = 0;
-               try {
-                       releaseTime = Long.parseLong(releaseTimeString);
-               } catch (NumberFormatException nfe1) {
-                       /* ignore. */
-               }
-               if ((version == null) || (releaseTime == 0)) {
-                       logger.log(Level.INFO, "Could not parse data from properties.");
-                       return;
-               }
-               if (version.compareTo(currentLatestVersion) > 0) {
-                       currentLatestVersion = version;
-                       latestVersionDate = releaseTime;
-                       boolean disruptive = disruptiveVersionBetweenCurrentAndFound(properties);
-                       logger.log(Level.INFO, String.format("Found new version: %s (%tc%s)", version, new Date(releaseTime), disruptive ? ", disruptive" : ""));
-                       eventBus.post(new UpdateFoundEvent(version, releaseTime, edition, disruptive));
-               }
-       }
-
-       private boolean disruptiveVersionBetweenCurrentAndFound(Properties properties) {
-               for (String key : properties.stringPropertyNames()) {
-                       if (key.startsWith("DisruptiveVersion/")) {
-                               Version disruptiveVersion = Version.parse(key.substring("DisruptiveVersion/".length()));
-                               if (disruptiveVersion.compareTo(currentRunningVersion) > 0) {
-                                       return true;
-                               }
-                       }
-               }
-               return false;
-       }
-
-}
index 35c3203..95d066d 100644 (file)
@@ -1,6 +1,5 @@
 package net.pterodactylus.sone.core;
 
-import net.pterodactylus.sone.freenet.wot.Identity;
 import net.pterodactylus.sone.freenet.wot.OwnIdentity;
 import net.pterodactylus.util.service.Service;
 
@@ -12,7 +11,6 @@ import com.google.inject.ImplementedBy;
 @ImplementedBy(WebOfTrustUpdaterImpl.class)
 public interface WebOfTrustUpdater extends Service {
 
-       void setTrust(OwnIdentity truster, Identity trustee, Integer score, String comment);
        boolean addContextWait(OwnIdentity ownIdentity, String context);
        void removeContext(OwnIdentity ownIdentity, String context);
        void setProperty(OwnIdentity ownIdentity, String propertyName, String propertyValue);
index 809ca20..da27152 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - WebOfTrustUpdaterImpl.java - Copyright © 2013–2019 David Roden
+ * Sone - WebOfTrustUpdaterImpl.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -26,11 +26,8 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import net.pterodactylus.sone.freenet.plugin.PluginException;
-import net.pterodactylus.sone.freenet.wot.Identity;
 import net.pterodactylus.sone.freenet.wot.OwnIdentity;
-import net.pterodactylus.sone.freenet.wot.Trust;
 import net.pterodactylus.sone.freenet.wot.WebOfTrustConnector;
-import net.pterodactylus.sone.freenet.wot.WebOfTrustException;
 import net.pterodactylus.util.service.AbstractService;
 
 import com.google.common.annotations.VisibleForTesting;
@@ -74,34 +71,6 @@ public class WebOfTrustUpdaterImpl extends AbstractService implements WebOfTrust
        //
 
        /**
-        * Updates the trust relation between the truster and the trustee. This method
-        * will return immediately and perform a trust update in the background.
-        *
-        * @param truster
-        *              The identity giving the trust
-        * @param trustee
-        *              The identity receiving the trust
-        * @param score
-        *              The new level of trust (from -100 to 100, may be {@code null} to remove
-        *              the trust completely)
-        * @param comment
-        *              The comment of the trust relation
-        */
-       @Override
-       public void setTrust(OwnIdentity truster, Identity trustee, Integer score, String comment) {
-               SetTrustJob setTrustJob = new SetTrustJob(truster, trustee, score, comment);
-               if (updateJobs.contains(setTrustJob)) {
-                       updateJobs.remove(setTrustJob);
-               }
-               logger.log(Level.FINER, "Adding Trust Update Job: " + setTrustJob);
-               try {
-                       updateJobs.put(setTrustJob);
-               } catch (InterruptedException e) {
-                       /* the queue is unbounded so it should never block. */
-               }
-       }
-
-       /**
         * Adds the given context to the given own identity, waiting for completion of
         * the operation.
         *
@@ -297,91 +266,6 @@ public class WebOfTrustUpdaterImpl extends AbstractService implements WebOfTrust
        }
 
        /**
-        * Update job that sets the trust relation between two identities.
-        */
-       @VisibleForTesting
-       class SetTrustJob extends WebOfTrustUpdateJob {
-
-               /** The identity giving the trust. */
-               private final OwnIdentity truster;
-
-               /** The identity receiving the trust. */
-               private final Identity trustee;
-
-               /** The score of the relation. */
-               private final Integer score;
-
-               /** The comment of the relation. */
-               private final String comment;
-
-               /**
-                * Creates a new set trust job.
-                *
-                * @param truster
-                *              The identity giving the trust
-                * @param trustee
-                *              The identity receiving the trust
-                * @param score
-                *              The score of the trust (from -100 to 100, may be {@code null} to remote
-                *              the trust relation completely)
-                * @param comment
-                *              The comment of the trust relation
-                */
-               public SetTrustJob(OwnIdentity truster, Identity trustee, Integer score, String comment) {
-                       this.truster = checkNotNull(truster, "truster must not be null");
-                       this.trustee = checkNotNull(trustee, "trustee must not be null");
-                       this.score = score;
-                       this.comment = comment;
-               }
-
-               /** {@inheritDoc} */
-               @Override
-               @SuppressWarnings("synthetic-access")
-               public void run() {
-                       try {
-                               if (score != null) {
-                                       webOfTrustConnector.setTrust(truster, trustee, score, comment);
-                                       trustee.setTrust(truster, new Trust(score, null, 0));
-                               } else {
-                                       webOfTrustConnector.removeTrust(truster, trustee);
-                                       trustee.removeTrust(truster);
-                               }
-                               finish(true);
-                       } catch (WebOfTrustException wote1) {
-                               logger.log(Level.WARNING, "Could not set Trust value for " + truster + " -> " + trustee + " to " + score + " (" + comment + ")!", wote1);
-                               finish(false);
-                       }
-               }
-
-               //
-               // OBJECT METHODS
-               //
-
-               /** {@inheritDoc} */
-               @Override
-               public boolean equals(Object object) {
-                       if ((object == null) || !object.getClass().equals(getClass())) {
-                               return false;
-                       }
-                       SetTrustJob updateJob = (SetTrustJob) object;
-                       return updateJob.truster.equals(truster) && updateJob.trustee.equals(trustee);
-               }
-
-               /** {@inheritDoc} */
-               @Override
-               public int hashCode() {
-                       return getClass().hashCode() ^ truster.hashCode() ^ trustee.hashCode();
-               }
-
-               /** {@inheritDoc} */
-               @Override
-               public String toString() {
-                       return String.format("%s[truster=%s,trustee=%s]", getClass().getSimpleName(), truster.getId(), trustee.getId());
-               }
-
-       }
-
-       /**
         * Base class for context updates of an {@link OwnIdentity}.
         */
        @VisibleForTesting
diff --git a/src/main/java/net/pterodactylus/sone/core/event/ImageEvent.java b/src/main/java/net/pterodactylus/sone/core/event/ImageEvent.java
deleted file mode 100644 (file)
index 6daef1a..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Sone - ImageEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Image;
-
-/**
- * Base class for {@link Image} events.
- */
-public abstract class ImageEvent {
-
-       /** The image this event is about. */
-       private final Image image;
-
-       /**
-        * Creates a new image event.
-        *
-        * @param image
-        *            The image this event is about
-        */
-       protected ImageEvent(Image image) {
-               this.image = image;
-       }
-
-       //
-       // ACCESSORS
-       //
-
-       /**
-        * Returns the image this event is about.
-        *
-        * @return The image this event is about
-        */
-       public Image image() {
-               return image;
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/ImageInsertAbortedEvent.java b/src/main/java/net/pterodactylus/sone/core/event/ImageInsertAbortedEvent.java
deleted file mode 100644 (file)
index 2bfa3a2..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Sone - ImageInsertAbortedEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Image;
-
-/**
- * Event that signals that an {@link Image} insert is aborted.
- */
-public class ImageInsertAbortedEvent extends ImageEvent {
-
-       /**
-        * Creates a new “image insert aborted” event.
-        *
-        * @param image
-        *            The image whose insert aborted
-        */
-       public ImageInsertAbortedEvent(Image image) {
-               super(image);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/ImageInsertFailedEvent.java b/src/main/java/net/pterodactylus/sone/core/event/ImageInsertFailedEvent.java
deleted file mode 100644 (file)
index 430c64b..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Sone - ImageInsertFailedEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Image;
-
-/**
- * Event that signals that an {@link Image} insert has failed.
- */
-public class ImageInsertFailedEvent extends ImageEvent {
-
-       /** The cause of the insert failure. */
-       private final Throwable cause;
-
-       /**
-        * Creates a new “image insert failed” event.
-        *
-        * @param image
-        *            The image whose insert failed
-        * @param cause
-        *            The cause of the insert failure
-        */
-       public ImageInsertFailedEvent(Image image, Throwable cause) {
-               super(image);
-               this.cause = cause;
-       }
-
-       //
-       // ACCESSORS
-       //
-
-       /**
-        * Returns the cause of the insert failure.
-        *
-        * @return The cause of the insert failure
-        */
-       public Throwable cause() {
-               return cause;
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/ImageInsertFinishedEvent.java b/src/main/java/net/pterodactylus/sone/core/event/ImageInsertFinishedEvent.java
deleted file mode 100644 (file)
index 4419311..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Sone - ImageInsertFinishedEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Image;
-import freenet.keys.FreenetURI;
-
-/**
- * Event that signals that an {@link Image} insert is finished.
- */
-public class ImageInsertFinishedEvent extends ImageEvent {
-
-       /** The URI of the image. */
-       private final FreenetURI resultingUri;
-
-       /**
-        * Creates a new “image insert finished” event.
-        *
-        * @param image
-        *            The image whose insert finished
-        * @param resultingUri
-        *            The resulting URI of the image
-        */
-       public ImageInsertFinishedEvent(Image image, FreenetURI resultingUri) {
-               super(image);
-               this.resultingUri = resultingUri;
-       }
-
-       //
-       // ACCESSORS
-       //
-
-       /**
-        * Returns the URI of the image.
-        *
-        * @return The URI of the image
-        */
-       public FreenetURI resultingUri() {
-               return resultingUri;
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/ImageInsertStartedEvent.java b/src/main/java/net/pterodactylus/sone/core/event/ImageInsertStartedEvent.java
deleted file mode 100644 (file)
index ac9e3e3..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Sone - ImageInsertStartedEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Image;
-
-/**
- * Event that signals that an {@link Image} is not being inserted.
- */
-public class ImageInsertStartedEvent extends ImageEvent {
-
-       /**
-        * Creates a new “image is inserted” event.
-        *
-        * @param image
-        *            The image that is being inserted
-        */
-       public ImageInsertStartedEvent(Image image) {
-               super(image);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/MarkPostKnownEvent.java b/src/main/java/net/pterodactylus/sone/core/event/MarkPostKnownEvent.java
deleted file mode 100644 (file)
index 7c8a6c3..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Sone - MarkPostKnownEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Post;
-
-/**
- * Event that signals that a {@link Post} has been marked as
- * {@link Post#isKnown() known}.
- */
-public class MarkPostKnownEvent extends PostEvent {
-
-       /**
-        * Creates a new “post marked known” event.
-        *
-        * @param post
-        *            The post that was marked as known
-        */
-       public MarkPostKnownEvent(Post post) {
-               super(post);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/MarkPostReplyKnownEvent.java b/src/main/java/net/pterodactylus/sone/core/event/MarkPostReplyKnownEvent.java
deleted file mode 100644 (file)
index 4c0e2fc..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Sone - MarkPostReplyKnownEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.PostReply;
-
-/**
- * Event that signals that a {@link PostReply} has been marked as
- * {@link PostReply#isKnown() known}.
- */
-public class MarkPostReplyKnownEvent extends PostReplyEvent {
-
-       /**
-        * Creates a new “post reply marked known” event.
-        *
-        * @param postReply
-        *            The post reply that was marked as known
-        */
-       public MarkPostReplyKnownEvent(PostReply postReply) {
-               super(postReply);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/MarkSoneKnownEvent.java b/src/main/java/net/pterodactylus/sone/core/event/MarkSoneKnownEvent.java
deleted file mode 100644 (file)
index 5bbdf5e..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Sone - MarkSoneKnownEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Sone;
-
-/**
- * Event that signals that a {@link Sone} has been marked as
- * {@link Sone#isKnown() known}.
- */
-public class MarkSoneKnownEvent extends SoneEvent {
-
-       /**
-        * Creates a new “Sone marked known” event.
-        *
-        * @param sone
-        *            The Sone that was marked as known
-        */
-       public MarkSoneKnownEvent(Sone sone) {
-               super(sone);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/NewSoneFoundEvent.java b/src/main/java/net/pterodactylus/sone/core/event/NewSoneFoundEvent.java
deleted file mode 100644 (file)
index 8fb17d2..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Sone - NewSoneFoundEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Sone;
-
-/**
- * Event that signals that a new remote Sone was found.
- */
-public class NewSoneFoundEvent extends SoneEvent {
-
-       /**
-        * Creates a new “new Sone found” event.
-        *
-        * @param sone
-        *            The Sone that was found
-        */
-       public NewSoneFoundEvent(Sone sone) {
-               super(sone);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/PostEvent.java b/src/main/java/net/pterodactylus/sone/core/event/PostEvent.java
deleted file mode 100644 (file)
index 93a61c6..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Sone - PostEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Post;
-
-/**
- * Base class for post events.
- */
-public class PostEvent {
-
-       /** The post the event is about. */
-       private final Post post;
-
-       /**
-        * Creates a new post event.
-        *
-        * @param post
-        *            The post the event is about
-        */
-       protected PostEvent(Post post) {
-               this.post = post;
-       }
-
-       //
-       // ACCESSORS
-       //
-
-       /**
-        * Returns the post the event is about.
-        *
-        * @return The post the event is about
-        */
-       public Post post() {
-               return post;
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/PostReplyEvent.java b/src/main/java/net/pterodactylus/sone/core/event/PostReplyEvent.java
deleted file mode 100644 (file)
index e31870b..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Sone - PostReplyEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.PostReply;
-
-/**
- * Base class for {@link PostReply} events.
- */
-public class PostReplyEvent {
-
-       /** The post reply the event is about. */
-       private final PostReply postReply;
-
-       /**
-        * Creates a new post reply event.
-        *
-        * @param postReply
-        *            The post reply the event is about
-        */
-       protected PostReplyEvent(PostReply postReply) {
-               this.postReply = postReply;
-       }
-
-       //
-       // ACCESSORS
-       //
-
-       /**
-        * Returns the post reply the event is about.
-        *
-        * @return The post reply the event is about
-        */
-       public PostReply postReply() {
-               return postReply;
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/SoneEvent.java b/src/main/java/net/pterodactylus/sone/core/event/SoneEvent.java
deleted file mode 100644 (file)
index b7497ff..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Sone - SoneEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Sone;
-
-/**
- * Base class for Sone events.
- */
-public abstract class SoneEvent {
-
-       /** The Sone this event is about. */
-       private final Sone sone;
-
-       /**
-        * Creates a new Sone event.
-        *
-        * @param sone
-        *            The Sone this event is about
-        */
-       protected SoneEvent(Sone sone) {
-               this.sone = sone;
-       }
-
-       //
-       // ACCESSORS
-       //
-
-       /**
-        * Returns the Sone this event is about.
-        *
-        * @return The Sone this event is about
-        */
-       public Sone sone() {
-               return sone;
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/SoneInsertAbortedEvent.java b/src/main/java/net/pterodactylus/sone/core/event/SoneInsertAbortedEvent.java
deleted file mode 100644 (file)
index a8c9bb6..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Sone - SoneInsertAbortedEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Sone;
-
-/**
- * Event that signals that a {@link Sone} insert was aborted.
- */
-public class SoneInsertAbortedEvent extends SoneEvent {
-
-       /** The cause of the abortion. */
-       private final Throwable cause;
-
-       /**
-        * Creates a new “Sone was inserted” event.
-        *
-        * @param sone
-        *            The Sone that was inserted
-        * @param cause
-        *            The cause of the abortion
-        */
-       public SoneInsertAbortedEvent(Sone sone, Throwable cause) {
-               super(sone);
-               this.cause = cause;
-       }
-
-       //
-       // ACCESSORS
-       //
-
-       /**
-        * Returns the cause of the abortion.
-        *
-        * @return The cause of the abortion (may be {@code null})
-        */
-       public Throwable cause() {
-               return cause;
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/SoneInsertedEvent.java b/src/main/java/net/pterodactylus/sone/core/event/SoneInsertedEvent.java
deleted file mode 100644 (file)
index 53fa935..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Sone - SoneInsertedEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Sone;
-
-/**
- * Event that signals that a {@link Sone} was inserted.
- */
-public class SoneInsertedEvent extends SoneEvent {
-
-       private final long insertDuration;
-       private final String insertFingerprint;
-
-       public SoneInsertedEvent(Sone sone, long insertDuration, String insertFingerprint) {
-               super(sone);
-               this.insertDuration = insertDuration;
-               this.insertFingerprint = insertFingerprint;
-       }
-
-       public long insertDuration() {
-               return insertDuration;
-       }
-
-       public String insertFingerprint() {
-               return insertFingerprint;
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/SoneInsertingEvent.java b/src/main/java/net/pterodactylus/sone/core/event/SoneInsertingEvent.java
deleted file mode 100644 (file)
index a9ef6fb..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Sone - SoneInsertingEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Sone;
-
-/**
- * Event that signals that a {@link Sone} is now being inserted.
- */
-public class SoneInsertingEvent extends SoneEvent {
-
-       /**
-        * Creates a new “Sone is being inserted” event.
-        *
-        * @param sone
-        *            The Sone that is being inserted
-        */
-       public SoneInsertingEvent(Sone sone) {
-               super(sone);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/SoneLockedEvent.java b/src/main/java/net/pterodactylus/sone/core/event/SoneLockedEvent.java
deleted file mode 100644 (file)
index cdc9e3a..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Sone - SoneLockedEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Sone;
-
-/**
- * Event that signals that a {@link Sone} was locked. Only
- * {@link Sone#isLocal() local Sones} can be locked.
- */
-public class SoneLockedEvent extends SoneEvent {
-
-       /**
-        * Creates a new “Sone locked” event.
-        *
-        * @param sone
-        *            The Sone that was locked
-        */
-       public SoneLockedEvent(Sone sone) {
-               super(sone);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/SoneRemovedEvent.java b/src/main/java/net/pterodactylus/sone/core/event/SoneRemovedEvent.java
deleted file mode 100644 (file)
index e46272d..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Sone - SoneRemovedEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Sone;
-
-/**
- * Event that signals that a {@link Sone} was removed.
- */
-public class SoneRemovedEvent extends SoneEvent {
-
-       /**
-        * Creates a new “Sone removed” event.
-        *
-        * @param sone
-        *            The Sone that was removed
-        */
-       public SoneRemovedEvent(Sone sone) {
-               super(sone);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/SoneUnlockedEvent.java b/src/main/java/net/pterodactylus/sone/core/event/SoneUnlockedEvent.java
deleted file mode 100644 (file)
index 106d32d..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Sone - SoneUnlockedEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.sone.data.Sone;
-
-/**
- * Event that signals that a {@link Sone} was unlocked. Only
- * {@link Sone#isLocal() local Sones} can be locked.
- */
-public class SoneUnlockedEvent extends SoneEvent {
-
-       /**
-        * Creates a new “Sone unlocked” event.
-        *
-        * @param sone
-        *            The Sone that was unlocked
-        */
-       public SoneUnlockedEvent(Sone sone) {
-               super(sone);
-       }
-
-}
diff --git a/src/main/java/net/pterodactylus/sone/core/event/UpdateFoundEvent.java b/src/main/java/net/pterodactylus/sone/core/event/UpdateFoundEvent.java
deleted file mode 100644 (file)
index 2884090..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Sone - UpdateFoundEvent.java - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.core.event;
-
-import net.pterodactylus.util.version.Version;
-
-/**
- * Event that signals that an update for Sone was found.
- */
-public class UpdateFoundEvent {
-
-       private final Version version;
-       private final long releaseTime;
-       private final long latestEdition;
-       private final boolean disruptive;
-
-       public UpdateFoundEvent(Version version, long releaseTime, long latestEdition, boolean disruptive) {
-               this.version = version;
-               this.releaseTime = releaseTime;
-               this.latestEdition = latestEdition;
-               this.disruptive = disruptive;
-       }
-
-       public Version version() {
-               return version;
-       }
-
-       public long releaseTime() {
-               return releaseTime;
-       }
-
-       public long latestEdition() {
-               return latestEdition;
-       }
-
-       public boolean disruptive() {
-               return disruptive;
-       }
-
-}
index c4af294..bf8f3ec 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - Album.java - Copyright © 2011–2019 David Roden
+ * Sone - Album.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 package net.pterodactylus.sone.data;
 
-import static java.util.Arrays.asList;
-import static java.util.Collections.emptyList;
-
-import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
-import javax.annotation.Nonnull;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableList;
 
 /**
  * Container for images that can also contain nested {@link Album}s.
  */
 public interface Album extends Identified, Fingerprintable {
 
-       /** Function that flattens the given album and all albums beneath it. */
-       Function<Album, List<Album>> FLATTENER = new Function<Album, List<Album>>() {
-
-               @Override
-               @Nonnull
-               public List<Album> apply(Album album) {
-                       if (album == null) {
-                               return emptyList();
-                       }
-                       List<Album> albums = new ArrayList<>();
-                       albums.add(album);
-                       for (Album subAlbum : album.getAlbums()) {
-                               albums.addAll(FluentIterable.from(ImmutableList.of(subAlbum)).transformAndConcat(FLATTENER).toList());
-                       }
-                       return albums;
-               }
-       };
-
-       /** Function that transforms an album into the images it contains. */
-       Function<Album, List<Image>> IMAGES = new Function<Album, List<Image>>() {
-
-               @Override
-               @Nonnull
-               public List<Image> apply(Album album) {
-                       return (album != null) ? album.getImages() : Collections.<Image>emptyList();
-               }
-       };
-
-       /**
-        * Filter that removes all albums that do not have any images in any album
-        * below it.
-        */
-       Predicate<Album> NOT_EMPTY = new Predicate<Album>() {
-
-               @Override
-               public boolean apply(Album album) {
-                       /* so, we flatten all albums below the given one and check whether at least one album… */
-                       return FluentIterable.from(asList(album)).transformAndConcat(FLATTENER).anyMatch(new Predicate<Album>() {
-
-                               @Override
-                               public boolean apply(Album album) {
-                                       /* …contains any inserted images. */
-                                       return !album.getImages().isEmpty() && FluentIterable.from(album.getImages()).allMatch(new Predicate<Image>() {
-
-                                               @Override
-                                               public boolean apply(Image input) {
-                                                       return input.isInserted();
-                                               }
-                                       });
-                               }
-                       });
-               }
-       };
-
        /**
         * Returns the ID of this album.
         *
index f23decf..7642957 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - Client.java - Copyright © 2010–2019 David Roden
+ * Sone - Client.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -81,4 +81,9 @@ public class Client {
                return Objects.hashCode(name, version);
        }
 
+       @Override
+       public String toString() {
+               return name + " " + version;
+       }
+
 }
index 93d0702..8414f3a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - Image.java - Copyright © 2011–2019 David Roden
+ * Sone - Image.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index b6648e2..d4d34e6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - Post.java - Copyright © 2010–2019 David Roden
+ * Sone - Post.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,10 +19,7 @@ package net.pterodactylus.sone.data;
 
 import static com.google.common.base.Optional.absent;
 
-import java.util.Comparator;
-
 import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
 
 /**
  * A post is a short message that a user writes in his Sone to let other users
@@ -30,26 +27,6 @@ import com.google.common.base.Predicate;
  */
 public interface Post extends Identified {
 
-       /** Comparator for posts, sorts descending by time. */
-       public static final Comparator<Post> NEWEST_FIRST = new Comparator<Post>() {
-
-               @Override
-               public int compare(Post leftPost, Post rightPost) {
-                       return (int) Math.max(Integer.MIN_VALUE, Math.min(Integer.MAX_VALUE, rightPost.getTime() - leftPost.getTime()));
-               }
-
-       };
-
-       /** Filter for posts with timestamps from the future. */
-       public static final Predicate<Post> FUTURE_POSTS_FILTER = new Predicate<Post>() {
-
-               @Override
-               public boolean apply(Post post) {
-                       return (post != null) && (post.getTime() <= System.currentTimeMillis());
-               }
-
-       };
-
        //
        // ACCESSORS
        //
index dc4a903..6db3876 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - PostReply.java - Copyright © 2010–2019 David Roden
+ * Sone - PostReply.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,7 +18,6 @@
 package net.pterodactylus.sone.data;
 
 import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
 
 /**
  * A reply is like a {@link Post} but can never be posted on its own, it always
@@ -27,18 +26,6 @@ import com.google.common.base.Predicate;
 public interface PostReply extends Reply<PostReply> {
 
        /**
-        * Filter that selects {@link PostReply}s that have a
-        * {@link Optional#isPresent() present} {@link #getPost() post}.
-        */
-       public static final Predicate<PostReply> HAS_POST_FILTER = new Predicate<PostReply>() {
-
-               @Override
-               public boolean apply(PostReply postReply) {
-                       return (postReply != null) && postReply.getPost().isPresent();
-               }
-       };
-
-       /**
         * Returns the ID of the post this reply refers to.
         *
         * @return The ID of the post this reply refers to
index 8ea09f7..34246cb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - Profile.java - Copyright © 2010–2019 David Roden
+ * Sone - Profile.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,7 +19,6 @@ package net.pterodactylus.sone.data;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
 import static java.nio.charset.StandardCharsets.UTF_8;
 
 import java.util.ArrayList;
index c596605..0cf2a52 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - Reply.java - Copyright © 2010–2019 David Roden
+ * Sone - Reply.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 package net.pterodactylus.sone.data;
 
-import java.util.Comparator;
-
-import com.google.common.base.Predicate;
-
 /**
  * Defines methods common for all replies.
  *
@@ -29,32 +25,6 @@ import com.google.common.base.Predicate;
  */
 public interface Reply<T extends Reply<T>> extends Identified {
 
-       /** Comparator that sorts replies ascending by time. */
-       public static final Comparator<? super Reply<?>> TIME_COMPARATOR = new Comparator<Reply<?>>() {
-
-               /**
-                * {@inheritDoc}
-                */
-               @Override
-               public int compare(Reply<?> leftReply, Reply<?> rightReply) {
-                       return (int) Math.max(Integer.MIN_VALUE, Math.min(Integer.MAX_VALUE, leftReply.getTime() - rightReply.getTime()));
-               }
-
-       };
-
-       /** Filter for replies with timestamps from the future. */
-       public static final Predicate<Reply<?>> FUTURE_REPLY_FILTER = new Predicate<Reply<?>>() {
-
-               /**
-                * {@inheritDoc}
-                */
-               @Override
-               public boolean apply(Reply<?> reply) {
-                       return (reply != null) && (reply.getTime() <= System.currentTimeMillis());
-               }
-
-       };
-
        /**
         * Returns the ID of the reply.
         *
@@ -90,13 +60,4 @@ public interface Reply<T extends Reply<T>> extends Identified {
         */
        public boolean isKnown();
 
-       /**
-        * Sets whether this reply is known.
-        *
-        * @param known
-        *            {@code true} if this reply is known, {@code false} otherwise
-        * @return This reply
-        */
-       public T setKnown(boolean known);
-
 }
index 273b73e..2b0a2eb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - Sone.java - Copyright © 2010–2019 David Roden
+ * Sone - Sone.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 package net.pterodactylus.sone.data;
 
-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.Collection;
-import java.util.Collections;
-import java.util.Comparator;
 import java.util.List;
 import java.util.Set;
 
@@ -32,15 +25,9 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import net.pterodactylus.sone.freenet.wot.Identity;
-import net.pterodactylus.sone.freenet.wot.OwnIdentity;
-import net.pterodactylus.sone.template.SoneAccessor;
 
 import freenet.keys.FreenetURI;
 
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.primitives.Ints;
-
 /**
  * A Sone defines everything about a user: her profile, her status updates, her
  * replies, her likes and dislikes, etc.
@@ -65,101 +52,6 @@ public interface Sone extends Identified, Fingerprintable, Comparable<Sone> {
                downloading,
        }
 
-       /** comparator that sorts Sones by their nice name. */
-       public static final Comparator<Sone> NICE_NAME_COMPARATOR = new Comparator<Sone>() {
-
-               @Override
-               public int compare(Sone leftSone, Sone rightSone) {
-                       int diff = SoneAccessor.getNiceName(leftSone).compareToIgnoreCase(SoneAccessor.getNiceName(rightSone));
-                       if (diff != 0) {
-                               return diff;
-                       }
-                       return leftSone.getId().compareToIgnoreCase(rightSone.getId());
-               }
-
-       };
-
-       /** Comparator that sorts Sones by last activity (least recent active first). */
-       public static final Comparator<Sone> LAST_ACTIVITY_COMPARATOR = new Comparator<Sone>() {
-
-               @Override
-               public int compare(Sone firstSone, Sone secondSone) {
-                       return (int) Math.min(Integer.MAX_VALUE, Math.max(Integer.MIN_VALUE, secondSone.getTime() - firstSone.getTime()));
-               }
-       };
-
-       /** Comparator that sorts Sones by numbers of posts (descending). */
-       public static final Comparator<Sone> POST_COUNT_COMPARATOR = new Comparator<Sone>() {
-
-               /**
-                * {@inheritDoc}
-                */
-               @Override
-               public int compare(Sone leftSone, Sone rightSone) {
-                       return (leftSone.getPosts().size() != rightSone.getPosts().size()) ? (rightSone.getPosts().size() - leftSone.getPosts().size()) : (rightSone.getReplies().size() - leftSone.getReplies().size());
-               }
-       };
-
-       /** Comparator that sorts Sones by number of images (descending). */
-       public static final Comparator<Sone> IMAGE_COUNT_COMPARATOR = new Comparator<Sone>() {
-
-               /**
-                * {@inheritDoc}
-                */
-               @Override
-               public int compare(Sone leftSone, Sone rightSone) {
-                       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);
-               }
-       };
-
-       /** Filter to remove Sones that have not been downloaded. */
-       public static final Predicate<Sone> EMPTY_SONE_FILTER = new Predicate<Sone>() {
-
-               @Override
-               public boolean apply(Sone sone) {
-                       return (sone != null) && (sone.getTime() != 0);
-               }
-       };
-
-       /** Filter that matches all {@link Sone#isLocal() local Sones}. */
-       public static final Predicate<Sone> LOCAL_SONE_FILTER = new Predicate<Sone>() {
-
-               @Override
-               public boolean apply(Sone sone) {
-                       return (sone != null) && (sone.getIdentity() instanceof OwnIdentity);
-               }
-
-       };
-
-       /** Filter that matches Sones that have at least one album. */
-       public static final Predicate<Sone> HAS_ALBUM_FILTER = new Predicate<Sone>() {
-
-               @Override
-               public boolean apply(Sone sone) {
-                       return (sone != null) && !sone.getRootAlbum().getAlbums().isEmpty();
-               }
-       };
-
-       public static final Function<Sone, List<Album>> toAllAlbums = new Function<Sone, List<Album>>() {
-               @Override
-               public List<Album> apply(@Nullable Sone sone) {
-                       return (sone == null) ? Collections.<Album>emptyList() : FLATTENER.apply(
-                                       sone.getRootAlbum());
-               }
-       };
-
-       public static final Function<Sone, List<Image>> toAllImages = new Function<Sone, List<Image>>() {
-               @Override
-               public List<Image> apply(@Nullable Sone sone) {
-                       return (sone == null) ? Collections.<Image>emptyList() :
-                                       from(FLATTENER.apply(sone.getRootAlbum()))
-                                                       .transformAndConcat(IMAGES).toList();
-               }
-       };
-
        /**
         * Returns the identity of this Sone.
         *
@@ -192,14 +84,6 @@ public interface Sone extends Identified, Fingerprintable, Comparable<Sone> {
        FreenetURI getRequestUri();
 
        /**
-        * Returns the insert URI of this Sone.
-        *
-        * @return The insert URI of this Sone
-        */
-       @Nullable
-       FreenetURI getInsertUri();
-
-       /**
         * Returns the latest edition of this Sone.
         *
         * @return The latest edition of this Sone
index 378a348..b76c3cd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - TemporaryImage.java - Copyright © 2011–2019 David Roden
+ * Sone - TemporaryImage.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 460be4e..04b0eac 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - AbstractAlbumBuilder.java - Copyright © 2013–2019 David Roden
+ * Sone - AbstractAlbumBuilder.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index f545ae9..56ceb6d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - AbstractImageBuilder.java - Copyright © 2013–2019 David Roden
+ * Sone - AbstractImageBuilder.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index cabe8d5..ca927b2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - AbstractPostBuilder.java - Copyright © 2013–2019 David Roden
+ * Sone - AbstractPostBuilder.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 0fe124e..8dffdcd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - AbstractPostReplyBuilder.java - Copyright © 2013–2019 David Roden
+ * Sone - AbstractPostReplyBuilder.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 052ca2d..7e95f38 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - AbstractReplyBuilder.java - Copyright © 2013–2019 David Roden
+ * Sone - AbstractReplyBuilder.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 601daa8..696d08d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - AlbumBuilderImpl.java - Copyright © 2013–2019 David Roden
+ * Sone - AlbumBuilderImpl.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 3ec362f..04ab8e9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - AlbumImpl.java - Copyright © 2011–2019 David Roden
+ * Sone - AlbumImpl.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 package net.pterodactylus.sone.data.impl;
 
-import static com.google.common.base.Optional.absent;
-import static com.google.common.base.Optional.fromNullable;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import net.pterodactylus.sone.data.Album;
-import net.pterodactylus.sone.data.Image;
-import net.pterodactylus.sone.data.Sone;
-
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicates;
-import com.google.common.collect.Collections2;
-import com.google.common.hash.Hasher;
+import java.util.*;
+import javax.annotation.*;
+
+import com.google.common.base.*;
+import com.google.common.collect.*;
 import com.google.common.hash.Hashing;
+import com.google.common.hash.*;
+import net.pterodactylus.sone.data.*;
+
+import static com.google.common.base.Preconditions.*;
+import static java.nio.charset.StandardCharsets.*;
 
 /**
  * Container for images that can also contain nested {@link AlbumImpl}s.
@@ -258,32 +247,33 @@ public class AlbumImpl implements Album {
        public Modifier modify() throws IllegalStateException {
                // TODO: reenable check for local Sones
                return new Modifier() {
-                       private Optional<String> title = absent();
-
-                       private Optional<String> description = absent();
+                       @Nullable
+                       private String title;
+                       @Nullable
+                       private String description;
 
                        @Override
                        public Modifier setTitle(String title) {
-                               this.title = fromNullable(title);
+                               this.title = title;
                                return this;
                        }
 
                        @Override
                        public Modifier setDescription(String description) {
-                               this.description = fromNullable(description);
+                               this.description = description;
                                return this;
                        }
 
                        @Override
                        public Album update() throws IllegalStateException {
-                               if (title.isPresent() && title.get().trim().isEmpty()) {
+                               if (title != null && title.trim().isEmpty()) {
                                        throw new AlbumTitleMustNotBeEmpty();
                                }
-                               if (title.isPresent()) {
-                                       AlbumImpl.this.title = title.get();
+                               if (title != null) {
+                                       AlbumImpl.this.title = title;
                                }
-                               if (description.isPresent()) {
-                                       AlbumImpl.this.description = description.get();
+                               if (description != null) {
+                                       AlbumImpl.this.description = description;
                                }
                                return AlbumImpl.this;
                        }
index e06e5a7..ddd96b9 100644 (file)
@@ -53,11 +53,6 @@ public class IdOnlySone implements Sone {
        }
 
        @Override
-       public FreenetURI getInsertUri() {
-               return null;
-       }
-
-       @Override
        public long getLatestEdition() {
                return 0;
        }
index b62cc40..e74b71a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - ImageBuilderImpl.java - Copyright © 2013–2019 David Roden
+ * Sone - ImageBuilderImpl.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index a54a8de..0dd84fe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - ImageImpl.java - Copyright © 2011–2019 David Roden
+ * Sone - ImageImpl.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  */
 package net.pterodactylus.sone.data.impl;
 
-import static com.google.common.base.Optional.absent;
-import static com.google.common.base.Optional.fromNullable;
-import static com.google.common.base.Optional.of;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static java.nio.charset.StandardCharsets.UTF_8;
+import java.util.*;
+import javax.annotation.*;
 
-import java.util.UUID;
+import com.google.common.hash.*;
+import net.pterodactylus.sone.data.*;
 
-import net.pterodactylus.sone.data.Album;
-import net.pterodactylus.sone.data.Image;
-import net.pterodactylus.sone.data.Sone;
-
-import com.google.common.base.Optional;
-import com.google.common.hash.Hasher;
-import com.google.common.hash.Hashing;
+import static com.google.common.base.Preconditions.*;
+import static java.nio.charset.StandardCharsets.*;
 
 /**
  * Container for image metadata.
@@ -146,93 +138,94 @@ public class ImageImpl implements Image {
        public Modifier modify() throws IllegalStateException {
                // TODO: reenable check for local images
                return new Modifier() {
-                       private Optional<Sone> sone = absent();
-
-                       private Optional<Long> creationTime = absent();
-
-                       private Optional<String> key = absent();
-
-                       private Optional<String> title = absent();
-
-                       private Optional<String> description = absent();
-
-                       private Optional<Integer> width = absent();
-
-                       private Optional<Integer> height = absent();
+                       @Nullable
+                       private Sone sone;
+                       @Nullable
+                       private Long creationTime;
+                       @Nullable
+                       private String key;
+                       @Nullable
+                       private String title;
+                       @Nullable
+                       private String description;
+                       @Nullable
+                       private Integer width;
+                       @Nullable
+                       private Integer height;
 
                        @Override
                        public Modifier setSone(Sone sone) {
-                               this.sone = fromNullable(sone);
+                               this.sone = sone;
                                return this;
                        }
 
                        @Override
                        public Modifier setCreationTime(long creationTime) {
-                               this.creationTime = of(creationTime);
+                               this.creationTime = creationTime;
                                return this;
                        }
 
                        @Override
                        public Modifier setKey(String key) {
-                               this.key = fromNullable(key);
+                               this.key = key;
                                return this;
                        }
 
                        @Override
                        public Modifier setTitle(String title) {
-                               this.title = fromNullable(title);
+                               this.title = title;
                                return this;
                        }
 
                        @Override
                        public Modifier setDescription(String description) {
-                               this.description = fromNullable(description);
+                               this.description = description;
                                return this;
                        }
 
                        @Override
                        public Modifier setWidth(int width) {
-                               this.width = of(width);
+                               this.width = width;
                                return this;
                        }
 
                        @Override
                        public Modifier setHeight(int height) {
-                               this.height = of(height);
+                               this.height = height;
                                return this;
                        }
 
                        @Override
                        public Image update() throws IllegalStateException {
-                               checkState(!sone.isPresent() || (ImageImpl.this.sone == null) || sone.get().equals(ImageImpl.this.sone), "can not change Sone once set");
-                               checkState(!creationTime.isPresent() || ((ImageImpl.this.creationTime == 0) || (ImageImpl.this.creationTime == creationTime.get())), "can not change creation time once set");
-                               checkState(!key.isPresent() || (ImageImpl.this.key == null) || key.get().equals(ImageImpl.this.key), "can not change key once set");
-                               if (title.isPresent() && title.get().trim().isEmpty()) {
+                               checkState(sone == null || (ImageImpl.this.sone == null) || sone.equals(ImageImpl.this.sone), "can not change Sone once set");
+                               checkState(creationTime == null || ((ImageImpl.this.creationTime == 0) || (ImageImpl.this.creationTime == creationTime)), "can not change creation time once set");
+                               checkState(key == null || (ImageImpl.this.key == null) || key.equals(ImageImpl.this.key), "can not change key once set");
+                               if (title != null && title.trim().isEmpty()) {
                                        throw new ImageTitleMustNotBeEmpty();
                                }
-                               checkState(!width.isPresent() || (ImageImpl.this.width == 0) || width.get().equals(ImageImpl.this.width), "can not change width once set");
-                               checkState(!height.isPresent() || (ImageImpl.this.height == 0) || height.get().equals(ImageImpl.this.height), "can not change height once set");
+                               checkState(width == null || (ImageImpl.this.width == 0) || width.equals(ImageImpl.this.width), "can not change width once set");
+                               checkState(height == null || (ImageImpl.this.height == 0) || height.equals(ImageImpl.this.height), "can not change height once set");
 
-                               if (sone.isPresent()) {
-                                       ImageImpl.this.sone = sone.get();
+                               if (sone != null) {
+                                       ImageImpl.this.sone = sone;
                                }
-                               if (creationTime.isPresent()) {
-                                       ImageImpl.this.creationTime = creationTime.get();
+                               if (creationTime != null) {
+                                       ImageImpl.this.creationTime = creationTime;
                                }
-                               if (key.isPresent()) {
-                                       ImageImpl.this.key = key.get();
+                               if (key != null) {
+                                       ImageImpl.this.key = key;
                                }
-                               if (title.isPresent()) {
-                                       ImageImpl.this.title = title.get();
+                               if (title != null) {
+                                       ImageImpl.this.title = title;
                                }
-                               if (description.isPresent()) {
-                                       ImageImpl.this.description = description.get();
+                               if (description != null) {
+                                       ImageImpl.this.description = description;
                                }
-                               if (width.isPresent()) {
-                                       ImageImpl.this.width = width.get();
+                               if (width != null) {
+                                       ImageImpl.this.width = width;
                                }
-                               if (height.isPresent()) {
-                                       ImageImpl.this.height = height.get();
+                               if (height != null) {
+                                       ImageImpl.this.height = height;
                                }
 
                                return ImageImpl.this;
index 3366448..f2f2ea6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - SoneImpl.java - Copyright © 2010–2019 David Roden
+ * Sone - SoneImpl.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,6 +21,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
 import static java.lang.String.format;
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.logging.Logger.getLogger;
+import static net.pterodactylus.sone.data.PostKt.newestPostFirst;
+import static net.pterodactylus.sone.data.ReplyKt.newestReplyFirst;
+import static net.pterodactylus.sone.data.SoneKt.*;
 
 import java.net.MalformedURLException;
 import java.util.ArrayList;
@@ -36,17 +39,16 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import net.pterodactylus.sone.data.Album;
+import net.pterodactylus.sone.data.AlbumKt;
 import net.pterodactylus.sone.data.Client;
 import net.pterodactylus.sone.data.Post;
 import net.pterodactylus.sone.data.PostReply;
 import net.pterodactylus.sone.data.Profile;
-import net.pterodactylus.sone.data.Reply;
 import net.pterodactylus.sone.data.Sone;
 import net.pterodactylus.sone.data.SoneOptions;
 import net.pterodactylus.sone.data.SoneOptions.DefaultSoneOptions;
 import net.pterodactylus.sone.database.Database;
 import net.pterodactylus.sone.freenet.wot.Identity;
-import net.pterodactylus.sone.freenet.wot.OwnIdentity;
 
 import freenet.keys.FreenetURI;
 
@@ -191,26 +193,6 @@ public class SoneImpl implements Sone {
        }
 
        /**
-        * Returns the insert URI of this Sone.
-        *
-        * @return The insert URI of this Sone
-        */
-       @Nullable
-       public FreenetURI getInsertUri() {
-               if (!isLocal()) {
-                       return null;
-               }
-               try {
-                       return new FreenetURI(((OwnIdentity) getIdentity()).getInsertUri())
-                                       .setDocName("Sone")
-                                       .setMetaString(new String[0])
-                                       .setSuggestedEdition(latestEdition);
-               } catch (MalformedURLException e) {
-                       throw new IllegalStateException(format("Own identity %s's insert URI is incorrect.", getIdentity()), e);
-               }
-       }
-
-       /**
         * Returns the latest edition of this Sone.
         *
         * @return The latest edition of this Sone
@@ -384,7 +366,7 @@ public class SoneImpl implements Sone {
                synchronized (this) {
                        sortedPosts = new ArrayList<>(posts);
                }
-               Collections.sort(sortedPosts, Post.NEWEST_FIRST);
+               sortedPosts.sort(newestPostFirst());
                return sortedPosts;
        }
 
@@ -644,7 +626,7 @@ public class SoneImpl implements Sone {
                hash.putString(")", UTF_8);
 
                List<PostReply> replies = new ArrayList<>(getReplies());
-               Collections.sort(replies, Reply.TIME_COMPARATOR);
+               replies.sort(newestReplyFirst().reversed());
                hash.putString("Replies(", UTF_8);
                for (PostReply reply : replies) {
                        hash.putString("Reply(", UTF_8).putString(reply.getId(), UTF_8).putString(")", UTF_8);
@@ -669,7 +651,7 @@ public class SoneImpl implements Sone {
 
                hash.putString("Albums(", UTF_8);
                for (Album album : rootAlbum.getAlbums()) {
-                       if (!Album.NOT_EMPTY.apply(album)) {
+                       if (!AlbumKt.notEmpty().invoke(album)) {
                                continue;
                        }
                        hash.putString(album.getFingerprint(), UTF_8);
@@ -686,7 +668,7 @@ public class SoneImpl implements Sone {
        /** {@inheritDoc} */
        @Override
        public int compareTo(Sone sone) {
-               return NICE_NAME_COMPARATOR.compare(this, sone);
+               return niceNameComparator().compare(this, sone);
        }
 
        //
index 9763ad6..6a24756 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - DatabaseException.java - Copyright © 2013–2019 David Roden
+ * Sone - DatabaseException.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/src/main/java/net/pterodactylus/sone/database/memory/MemoryDatabase.kt b/src/main/java/net/pterodactylus/sone/database/memory/MemoryDatabase.kt
deleted file mode 100644 (file)
index 6fce7e0..0000000
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * Sone - MemoryDatabase.kt - Copyright © 2013–2019 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.sone.database.memory
-
-import com.google.common.base.Preconditions.checkNotNull
-import com.google.common.collect.HashMultimap
-import com.google.common.collect.Multimap
-import com.google.common.collect.TreeMultimap
-import com.google.common.util.concurrent.AbstractService
-import com.google.inject.Inject
-import com.google.inject.Singleton
-import net.pterodactylus.sone.data.Album
-import net.pterodactylus.sone.data.Image
-import net.pterodactylus.sone.data.Post
-import net.pterodactylus.sone.data.PostReply
-import net.pterodactylus.sone.data.Reply.TIME_COMPARATOR
-import net.pterodactylus.sone.data.Sone
-import net.pterodactylus.sone.data.Sone.toAllAlbums
-import net.pterodactylus.sone.data.Sone.toAllImages
-import net.pterodactylus.sone.data.impl.AlbumBuilderImpl
-import net.pterodactylus.sone.data.impl.ImageBuilderImpl
-import net.pterodactylus.sone.database.AlbumBuilder
-import net.pterodactylus.sone.database.Database
-import net.pterodactylus.sone.database.DatabaseException
-import net.pterodactylus.sone.database.ImageBuilder
-import net.pterodactylus.sone.database.PostBuilder
-import net.pterodactylus.sone.database.PostDatabase
-import net.pterodactylus.sone.database.PostReplyBuilder
-import net.pterodactylus.sone.utils.unit
-import net.pterodactylus.util.config.Configuration
-import net.pterodactylus.util.config.ConfigurationException
-import java.util.concurrent.locks.ReentrantReadWriteLock
-import kotlin.concurrent.withLock
-
-/**
- * Memory-based [PostDatabase] implementation.
- */
-@Singleton
-class MemoryDatabase @Inject constructor(private val configuration: Configuration) : AbstractService(), Database {
-
-       private val lock = ReentrantReadWriteLock()
-       private val readLock by lazy { lock.readLock()!! }
-       private val writeLock by lazy { lock.writeLock()!! }
-       private val configurationLoader = ConfigurationLoader(configuration)
-       private val allSones = mutableMapOf<String, Sone>()
-       private val allPosts = mutableMapOf<String, Post>()
-       private val sonePosts: Multimap<String, Post> = HashMultimap.create<String, Post>()
-       private val knownPosts = mutableSetOf<String>()
-       private val allPostReplies = mutableMapOf<String, PostReply>()
-       private val sonePostReplies: Multimap<String, PostReply> = TreeMultimap.create<String, PostReply>(Comparator { leftString, rightString -> leftString.compareTo(rightString) }, TIME_COMPARATOR)
-       private val knownPostReplies = mutableSetOf<String>()
-       private val allAlbums = mutableMapOf<String, Album>()
-       private val soneAlbums: Multimap<String, Album> = HashMultimap.create<String, Album>()
-       private val allImages = mutableMapOf<String, Image>()
-       private val soneImages: Multimap<String, Image> = HashMultimap.create<String, Image>()
-       private val memoryBookmarkDatabase = MemoryBookmarkDatabase(this, configurationLoader)
-       private val memoryFriendDatabase = MemoryFriendDatabase(configurationLoader)
-
-       override val soneLoader get() = this::getSone
-
-       override val sones get() = readLock.withLock { allSones.values.toSet() }
-
-       override val localSones get() = readLock.withLock { allSones.values.filter(Sone::isLocal) }
-
-       override val remoteSones get() = readLock.withLock { allSones.values.filterNot(Sone::isLocal) }
-
-       override val bookmarkedPosts get() = memoryBookmarkDatabase.bookmarkedPosts
-
-       override fun save() {
-               saveKnownPosts()
-               saveKnownPostReplies()
-       }
-
-       override fun doStart() {
-               memoryBookmarkDatabase.start()
-               loadKnownPosts()
-               loadKnownPostReplies()
-               notifyStarted()
-       }
-
-       override fun doStop() {
-               try {
-                       memoryBookmarkDatabase.stop()
-                       save()
-                       notifyStopped()
-               } catch (de1: DatabaseException) {
-                       notifyFailed(de1)
-               }
-       }
-
-       override fun newSoneBuilder() = MemorySoneBuilder(this)
-
-       override fun storeSone(sone: Sone) {
-               writeLock.withLock {
-                       removeSone(sone)
-
-                       allSones[sone.id] = sone
-                       sonePosts.putAll(sone.id, sone.posts)
-                       for (post in sone.posts) {
-                               allPosts[post.id] = post
-                       }
-                       sonePostReplies.putAll(sone.id, sone.replies)
-                       for (postReply in sone.replies) {
-                               allPostReplies[postReply.id] = postReply
-                       }
-                       soneAlbums.putAll(sone.id, toAllAlbums.apply(sone)!!)
-                       for (album in toAllAlbums.apply(sone)!!) {
-                               allAlbums[album.id] = album
-                       }
-                       soneImages.putAll(sone.id, toAllImages.apply(sone)!!)
-                       for (image in toAllImages.apply(sone)!!) {
-                               allImages[image.id] = image
-                       }
-               }
-       }
-
-       override fun removeSone(sone: Sone) {
-               writeLock.withLock {
-                       allSones.remove(sone.id)
-                       val removedPosts = sonePosts.removeAll(sone.id)
-                       for (removedPost in removedPosts) {
-                               allPosts.remove(removedPost.id)
-                       }
-                       val removedPostReplies = sonePostReplies.removeAll(sone.id)
-                       for (removedPostReply in removedPostReplies) {
-                               allPostReplies.remove(removedPostReply.id)
-                       }
-                       val removedAlbums = soneAlbums.removeAll(sone.id)
-                       for (removedAlbum in removedAlbums) {
-                               allAlbums.remove(removedAlbum.id)
-                       }
-                       val removedImages = soneImages.removeAll(sone.id)
-                       for (removedImage in removedImages) {
-                               allImages.remove(removedImage.id)
-                       }
-               }
-       }
-
-       override fun getSone(soneId: String) = readLock.withLock { allSones[soneId] }
-
-       override fun getFriends(localSone: Sone): Collection<String> =
-                       if (!localSone.isLocal) {
-                               emptySet()
-                       } else {
-                               memoryFriendDatabase.getFriends(localSone.id)
-                       }
-
-       override fun isFriend(localSone: Sone, friendSoneId: String) =
-                       if (!localSone.isLocal) {
-                               false
-                       } else {
-                               memoryFriendDatabase.isFriend(localSone.id, friendSoneId)
-                       }
-
-       override fun addFriend(localSone: Sone, friendSoneId: String) {
-               if (!localSone.isLocal) {
-                       return
-               }
-               memoryFriendDatabase.addFriend(localSone.id, friendSoneId)
-       }
-
-       override fun removeFriend(localSone: Sone, friendSoneId: String) {
-               if (!localSone.isLocal) {
-                       return
-               }
-               memoryFriendDatabase.removeFriend(localSone.id, friendSoneId)
-       }
-
-       override fun getFollowingTime(friendSoneId: String) =
-                       memoryFriendDatabase.getFollowingTime(friendSoneId)
-
-       override fun getPost(postId: String) =
-                       readLock.withLock { allPosts[postId] }
-
-       override fun getPosts(soneId: String): Collection<Post> =
-                       sonePosts[soneId].toSet()
-
-       override fun getDirectedPosts(recipientId: String) =
-                       readLock.withLock {
-                               allPosts.values.filter {
-                                       it.recipientId.orNull() == recipientId
-                               }
-                       }
-
-       override fun newPostBuilder(): PostBuilder = MemoryPostBuilder(this, this)
-
-       override fun storePost(post: Post) {
-               checkNotNull(post, "post must not be null")
-               writeLock.withLock {
-                       allPosts[post.id] = post
-                       sonePosts[post.sone.id].add(post)
-               }
-       }
-
-       override fun removePost(post: Post) {
-               checkNotNull(post, "post must not be null")
-               writeLock.withLock {
-                       allPosts.remove(post.id)
-                       sonePosts[post.sone.id].remove(post)
-                       post.sone.removePost(post)
-               }
-       }
-
-       override fun getPostReply(id: String) = readLock.withLock { allPostReplies[id] }
-
-       override fun getReplies(postId: String) =
-                       readLock.withLock {
-                               allPostReplies.values
-                                               .filter { it.postId == postId }
-                                               .sortedWith(TIME_COMPARATOR)
-                       }
-
-       override fun newPostReplyBuilder(): PostReplyBuilder =
-                       MemoryPostReplyBuilder(this, this)
-
-       override fun storePostReply(postReply: PostReply) =
-                       writeLock.withLock {
-                               allPostReplies[postReply.id] = postReply
-                       }
-
-       override fun removePostReply(postReply: PostReply) =
-                       writeLock.withLock {
-                               allPostReplies.remove(postReply.id)
-                       }.unit
-
-       override fun getAlbum(albumId: String) = readLock.withLock { allAlbums[albumId] }
-
-       override fun newAlbumBuilder(): AlbumBuilder = AlbumBuilderImpl()
-
-       override fun storeAlbum(album: Album) =
-                       writeLock.withLock {
-                               allAlbums[album.id] = album
-                               soneAlbums.put(album.sone.id, album)
-                       }.unit
-
-       override fun removeAlbum(album: Album) =
-                       writeLock.withLock {
-                               allAlbums.remove(album.id)
-                               soneAlbums.remove(album.sone.id, album)
-                       }.unit
-
-       override fun getImage(imageId: String) = readLock.withLock { allImages[imageId] }
-
-       override fun newImageBuilder(): ImageBuilder = ImageBuilderImpl()
-
-       override fun storeImage(image: Image): Unit =
-                       writeLock.withLock {
-                               allImages[image.id] = image
-                               soneImages.put(image.sone.id, image)
-                       }
-
-       override fun removeImage(image: Image): Unit =
-                       writeLock.withLock {
-                               allImages.remove(image.id)
-                               soneImages.remove(image.sone.id, image)
-                       }
-
-       override fun bookmarkPost(post: Post) =
-                       memoryBookmarkDatabase.bookmarkPost(post)
-
-       override fun unbookmarkPost(post: Post) =
-                       memoryBookmarkDatabase.unbookmarkPost(post)
-
-       override fun isPostBookmarked(post: Post) =
-                       memoryBookmarkDatabase.isPostBookmarked(post)
-
-       protected fun isPostKnown(post: Post) = readLock.withLock { post.id in knownPosts }
-
-       fun setPostKnown(post: Post, known: Boolean): Unit =
-                       writeLock.withLock {
-                               if (known)
-                                       knownPosts.add(post.id)
-                               else
-                                       knownPosts.remove(post.id)
-                               saveKnownPosts()
-                       }
-
-       protected fun isPostReplyKnown(postReply: PostReply) = readLock.withLock { postReply.id in knownPostReplies }
-
-       fun setPostReplyKnown(postReply: PostReply, known: Boolean): Unit =
-                       writeLock.withLock {
-                               if (known)
-                                       knownPostReplies.add(postReply.id)
-                               else
-                                       knownPostReplies.remove(postReply.id)
-                               saveKnownPostReplies()
-                       }
-
-       private fun loadKnownPosts() =
-                       configurationLoader.loadKnownPosts()
-                                       .let {
-                                               writeLock.withLock {
-                                                       knownPosts.clear()
-                                                       knownPosts.addAll(it)
-                                               }
-                                       }
-
-       private fun saveKnownPosts() =
-                       try {
-                               readLock.withLock {
-                                       knownPosts.forEachIndexed { index, knownPostId ->
-                                               configuration.getStringValue("KnownPosts/$index/ID").value = knownPostId
-                                       }
-                                       configuration.getStringValue("KnownPosts/${knownPosts.size}/ID").value = null
-                               }
-                       } catch (ce1: ConfigurationException) {
-                               throw DatabaseException("Could not save database.", ce1)
-                       }
-
-       private fun loadKnownPostReplies(): Unit =
-                       configurationLoader.loadKnownPostReplies().let { knownPostReplies ->
-                               writeLock.withLock {
-                                       this.knownPostReplies.clear()
-                                       this.knownPostReplies.addAll(knownPostReplies)
-                               }
-                       }
-
-       private fun saveKnownPostReplies() =
-                       try {
-                               readLock.withLock {
-                                       knownPostReplies.forEachIndexed { index, knownPostReply ->
-                                               configuration.getStringValue("KnownReplies/$index/ID").value = knownPostReply
-                                       }
-                                       configuration.getStringValue("KnownReplies/${knownPostReplies.size}/ID").value = null
-                               }
-                       } catch (ce1: ConfigurationException) {
-                               throw DatabaseException("Could not save database.", ce1)
-                       }
-
-}
index 30fc2b0..451b6b5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - MemoryPost.java - Copyright © 2010–2019 David Roden
+ * Sone - MemoryPost.java - Copyright © 2010–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index dea3449..b9e66fe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - MemoryPostBuilder.java - Copyright © 2013–2019 David Roden
+ * Sone - MemoryPostBuilder.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 package net.pterodactylus.sone.database.memory;
 
-import java.util.UUID;
+import java.util.*;
+import javax.annotation.*;
 
-import net.pterodactylus.sone.data.Post;
-import net.pterodactylus.sone.data.impl.AbstractPostBuilder;
-import net.pterodactylus.sone.database.PostBuilder;
-import net.pterodactylus.sone.database.SoneProvider;
+import net.pterodactylus.sone.data.*;
+import net.pterodactylus.sone.data.impl.*;
+import net.pterodactylus.sone.database.*;
 
 /**
  * {@link PostBuilder} implementation that creates a {@link MemoryPost}.
  */
 class MemoryPostBuilder extends AbstractPostBuilder {
 
-       /** The database. */
        private final MemoryDatabase database;
 
-       /**
-        * Creates a new memory post builder.
-        *
-        * @param memoryDatabase
-        *            The database
-        * @param soneProvider
-        *            The Sone provider
-        */
        public MemoryPostBuilder(MemoryDatabase memoryDatabase, SoneProvider soneProvider) {
                super(soneProvider);
                database = memoryDatabase;
        }
 
-       /**
-        * {@inheritDocs}
-        */
+       @Nonnull
        @Override
        public Post build() throws IllegalStateException {
                validate();
-               Post post = new MemoryPost(database, soneProvider, randomId ? UUID.randomUUID().toString() : id, senderId, recipientId, currentTime ? System.currentTimeMillis() : time, text);
-               post.setKnown(database.isPostKnown(post));
-               return post;
+               return new MemoryPost(database, soneProvider, randomId ? UUID.randomUUID().toString() : id, senderId, recipientId, currentTime ? System.currentTimeMillis() : time, text);
        }
 
 }
index 40f0775..5764622 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - MemoryPostReply.java - Copyright © 2013–2019 David Roden
+ * Sone - MemoryPostReply.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -124,15 +124,6 @@ class MemoryPostReply implements PostReply {
                return database.isPostReplyKnown(this);
        }
 
-       /**
-        * {@inheritDocs}
-        */
-       @Override
-       public PostReply setKnown(boolean known) {
-               database.setPostReplyKnown(this, known);
-               return this;
-       }
-
        //
        // POSTREPLY METHODS
        //
@@ -177,4 +168,17 @@ class MemoryPostReply implements PostReply {
                return memoryPostReply.id.equals(id);
        }
 
+       @Override
+       public String toString() {
+               return "MemoryPostReply{" +
+                               "database=" + database +
+                               ", soneProvider=" + soneProvider +
+                               ", id='" + id + '\'' +
+                               ", soneId='" + soneId + '\'' +
+                               ", time=" + time +
+                               ", text='" + text + '\'' +
+                               ", postId='" + postId + '\'' +
+                               '}';
+       }
+
 }
index 3bcfe33..b6e2e24 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - MemoryPostReplyBuilder.java - Copyright © 2013–2019 David Roden
+ * Sone - MemoryPostReplyBuilder.java - Copyright © 2013–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 package net.pterodactylus.sone.database.memory;
 
-import java.util.UUID;
+import java.util.*;
+import javax.annotation.*;
 
-import net.pterodactylus.sone.data.PostReply;
-import net.pterodactylus.sone.data.impl.AbstractPostReplyBuilder;
-import net.pterodactylus.sone.database.PostReplyBuilder;
-import net.pterodactylus.sone.database.SoneProvider;
+import net.pterodactylus.sone.data.*;
+import net.pterodactylus.sone.data.impl.*;
+import net.pterodactylus.sone.database.*;
 
 /**
  * {@link PostReplyBuilder} implementation that creates {@link MemoryPostReply}
@@ -30,35 +30,20 @@ import net.pterodactylus.sone.database.SoneProvider;
  */
 class MemoryPostReplyBuilder extends AbstractPostReplyBuilder {
 
-       /** The database. */
        private final MemoryDatabase database;
-
-       /** The Sone provider. */
        private final SoneProvider soneProvider;
 
-       /**
-        * Creates a new {@link MemoryPostReply} builder.
-        *
-        * @param database
-        *            The database
-        * @param soneProvider
-        *            The Sone provider
-        */
        public MemoryPostReplyBuilder(MemoryDatabase database, SoneProvider soneProvider) {
                this.database = database;
                this.soneProvider = soneProvider;
        }
 
-       /**
-        * {@inheritDocs}
-        */
+       @Nonnull
        @Override
        public PostReply build() throws IllegalStateException {
                validate();
 
-               PostReply postReply = new MemoryPostReply(database, soneProvider, randomId ? UUID.randomUUID().toString() : id, senderId, currentTime ? System.currentTimeMillis() : time, text, postId);
-               postReply.setKnown(database.isPostReplyKnown(postReply));
-               return postReply;
+               return new MemoryPostReply(database, soneProvider, randomId ? UUID.randomUUID().toString() : id, senderId, currentTime ? System.currentTimeMillis() : time, text, postId);
        }
 
 }
index 2c8456d..3cb1d6b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - CreatePostCommand.java - Copyright © 2011–2019 David Roden
+ * Sone - CreatePostCommand.java - Copyright © 2011–2020 David Roden
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -17,8 +17,6 @@
 
 package net.pterodactylus.sone.fcp;
 
-import com.google.common.base.Optional;
-
 import net.pterodactylus.sone.core.Core;
 import net.pterodactylus.sone.data.Post;
 import net.pterodactylus.sone.data.Sone;
@@ -29,7