Return an optional from the Sone parser.
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Mon, 21 Oct 2013 05:13:21 +0000 (07:13 +0200)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Fri, 28 Feb 2014 21:25:32 +0000 (22:25 +0100)
src/main/java/net/pterodactylus/sone/core/SoneDownloader.java
src/main/java/net/pterodactylus/sone/core/SoneParser.java
src/main/java/net/pterodactylus/sone/core/SoneRescuer.java
src/test/java/net/pterodactylus/sone/core/SoneParserTest.java

index eb263ed..bea7702 100644 (file)
@@ -36,6 +36,8 @@ import freenet.client.FetchResult;
 import freenet.keys.FreenetURI;
 import freenet.support.api.Bucket;
 
+import com.google.common.base.Optional;
+
 /**
  * The Sone downloader is responsible for download Sones as they are updated.
  *
@@ -138,7 +140,7 @@ public class SoneDownloader extends AbstractService {
         * @return The downloaded Sone, or {@code null} if the Sone could not be
         *         downloaded
         */
-       public Sone fetchSone(Sone sone, FreenetURI soneUri, boolean fetchOnly) {
+       public Optional<Sone> fetchSone(Sone sone, FreenetURI soneUri, boolean fetchOnly) {
                logger.log(Level.FINE, String.format("Starting fetch for Sone “%s” from %s…", sone, soneUri));
                FreenetURI requestUri = soneUri.setMetaString(new String[] { "sone.xml" });
                sone.setStatus(SoneStatus.downloading);
@@ -149,12 +151,12 @@ public class SoneDownloader extends AbstractService {
                                return null;
                        }
                        logger.log(Level.FINEST, String.format("Got %d bytes back.", fetchResults.getFetchResult().size()));
-                       Sone parsedSone = parseSone(sone, fetchResults.getFetchResult(), fetchResults.getFreenetUri());
-                       if (parsedSone != null) {
+                       Optional<Sone> parsedSone = parseSone(sone, fetchResults.getFetchResult(), fetchResults.getFreenetUri());
+                       if (parsedSone.isPresent()) {
                                if (!fetchOnly) {
-                                       parsedSone.setStatus((parsedSone.getTime() == 0) ? SoneStatus.unknown : SoneStatus.idle);
-                                       core.updateSone(parsedSone);
-                                       addSone(parsedSone);
+                                       parsedSone.get().setStatus((parsedSone.get().getTime() == 0) ? SoneStatus.unknown : SoneStatus.idle);
+                                       core.updateSone(parsedSone.get());
+                                       addSone(parsedSone.get());
                                }
                        }
                        return parsedSone;
@@ -174,15 +176,15 @@ public class SoneDownloader extends AbstractService {
         *            The requested URI
         * @return The parsed Sone, or {@code null} if the Sone could not be parsed
         */
-       public Sone parseSone(Sone originalSone, FetchResult fetchResult, FreenetURI requestUri) {
+       public Optional<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));
                Bucket soneBucket = fetchResult.asBucket();
                InputStream soneInputStream = null;
                try {
                        soneInputStream = soneBucket.getInputStream();
-                       Sone parsedSone = parseSone(originalSone, soneInputStream);
-                       if (parsedSone != null) {
-                               parsedSone.modify().setLatestEdition(requestUri.getEdition()).update();
+                       Optional<Sone> parsedSone = parseSone(originalSone, soneInputStream);
+                       if (parsedSone.isPresent()) {
+                               parsedSone.get().modify().setLatestEdition(requestUri.getEdition()).update();
                        }
                        return parsedSone;
                } catch (Exception e1) {
@@ -204,7 +206,7 @@ public class SoneDownloader extends AbstractService {
         *            The input stream to parse the Sone from
         * @return The parsed Sone
         */
-       public Sone parseSone(Sone originalSone, InputStream soneInputStream) {
+       public Optional<Sone> parseSone(Sone originalSone, InputStream soneInputStream) {
                return new SoneParser().parseSone(core.getDatabase(), originalSone, soneInputStream);
        }
 
index 470e163..d251989 100644 (file)
@@ -71,7 +71,7 @@ public class SoneParser {
         *              The input stream to parse the Sone from
         * @return The parsed Sone
         */
-       public Sone parseSone(Database database, Sone originalSone, InputStream soneInputStream) {
+       public Optional<Sone> parseSone(Database database, Sone originalSone, InputStream soneInputStream) {
                /* TODO - impose a size limit? */
 
                Document document;
@@ -82,13 +82,13 @@ public class SoneParser {
                if (document == null) {
                        /* TODO - mark Sone as bad. */
                        logger.log(Level.WARNING, String.format("Could not parse XML for Sone %s!", originalSone.getId()));
-                       return null;
+                       return absent();
                }
 
                Optional<SimpleXML> soneXml = parseXml(originalSone, document);
                if (!soneXml.isPresent()) {
                        logger.log(Level.WARNING, String.format("XML for Sone %s can not be parsed!", originalSone.getId()));
-                       return null;
+                       return absent();
                }
 
                Optional<Client> parsedClient = parseClient(originalSone, soneXml.get());
@@ -98,11 +98,11 @@ public class SoneParser {
                if (protocolVersion.isPresent()) {
                        if (protocolVersion.get() < 0) {
                                logger.log(Level.WARNING, String.format("Invalid protocol version: %d! Not parsing Sone.", protocolVersion.get()));
-                               return null;
+                               return absent();
                        }
                        if (protocolVersion.get() > MAX_PROTOCOL_VERSION) {
                                logger.log(Level.WARNING, String.format("Unknown protocol version: %d! Not parsing Sone.", protocolVersion.get()));
-                               return null;
+                               return absent();
                        }
                }
 
@@ -110,21 +110,21 @@ public class SoneParser {
                if (soneTime == null) {
                        /* TODO - mark Sone as bad. */
                        logger.log(Level.WARNING, String.format("Downloaded time for Sone %s was null!", sone));
-                       return null;
+                       return absent();
                }
                try {
                        sone.setTime(Long.parseLong(soneTime));
                } catch (NumberFormatException nfe1) {
                        /* TODO - mark Sone as bad. */
                        logger.log(Level.WARNING, String.format("Downloaded Sone %s with invalid time: %s", sone, soneTime));
-                       return null;
+                       return absent();
                }
 
                SimpleXML profileXml = soneXml.get().getNode("profile");
                if (profileXml == null) {
                        /* TODO - mark Sone as bad. */
                        logger.log(Level.WARNING, String.format("Downloaded Sone %s has no profile!", sone));
-                       return null;
+                       return absent();
                }
 
                /* parse profile. */
@@ -147,13 +147,13 @@ public class SoneParser {
                                String fieldValue = fieldXml.getValue("field-value", "");
                                if (fieldName == null) {
                                        logger.log(Level.WARNING, String.format("Downloaded profile field for Sone %s with missing data! Name: %s, Value: %s", sone, fieldName, fieldValue));
-                                       return null;
+                                       return absent();
                                }
                                try {
                                        profile.addField(fieldName).setValue(fieldValue);
                                } catch (IllegalArgumentException iae1) {
                                        logger.log(Level.WARNING, String.format("Duplicate field: %s", fieldName), iae1);
-                                       return null;
+                                       return absent();
                                }
                        }
                }
@@ -173,7 +173,7 @@ public class SoneParser {
                                if ((postId == null) || (postTime == null) || (postText == null)) {
                                        /* TODO - mark Sone as bad. */
                                        logger.log(Level.WARNING, String.format("Downloaded post for Sone %s with missing data! ID: %s, Time: %s, Text: %s", sone, postId, postTime, postText));
-                                       return null;
+                                       return absent();
                                }
                                try {
                                        PostBuilder postBuilder = sone.newPostBuilder();
@@ -186,7 +186,7 @@ public class SoneParser {
                                } catch (NumberFormatException nfe1) {
                                        /* TODO - mark Sone as bad. */
                                        logger.log(Level.WARNING, String.format("Downloaded post for Sone %s with invalid time: %s", sone, postTime));
-                                       return null;
+                                       return absent();
                                }
                        }
                }
@@ -206,7 +206,7 @@ public class SoneParser {
                                if ((replyId == null) || (replyPostId == null) || (replyTime == null) || (replyText == null)) {
                                        /* TODO - mark Sone as bad. */
                                        logger.log(Level.WARNING, String.format("Downloaded reply for Sone %s with missing data! ID: %s, Post: %s, Time: %s, Text: %s", sone, replyId, replyPostId, replyTime, replyText));
-                                       return null;
+                                       return absent();
                                }
                                try {
                                        /* TODO - parse time correctly. */
@@ -215,7 +215,7 @@ public class SoneParser {
                                } catch (NumberFormatException nfe1) {
                                        /* TODO - mark Sone as bad. */
                                        logger.log(Level.WARNING, String.format("Downloaded reply for Sone %s with invalid time: %s", sone, replyTime));
-                                       return null;
+                                       return absent();
                                }
                        }
                }
@@ -258,14 +258,14 @@ public class SoneParser {
                                String albumImageId = albumXml.getValue("album-image", null);
                                if ((id == null) || (title == null) || (description == null)) {
                                        logger.log(Level.WARNING, String.format("Downloaded Sone %s contains invalid album!", sone));
-                                       return null;
+                                       return absent();
                                }
                                Album parent = sone.getRootAlbum();
                                if (parentId != null) {
                                        parent = albums.get(parentId);
                                        if (parent == null) {
                                                logger.log(Level.WARNING, String.format("Downloaded Sone %s has album with invalid parent!", sone));
-                                               return null;
+                                               return absent();
                                        }
                                }
                                Album album = parent.newAlbumBuilder().withId(id).build().modify().setTitle(title).setDescription(description).update();
@@ -282,14 +282,14 @@ public class SoneParser {
                                                String imageHeightString = imageXml.getValue("height", null);
                                                if ((imageId == null) || (imageCreationTimeString == null) || (imageKey == null) || (imageTitle == null) || (imageWidthString == null) || (imageHeightString == null)) {
                                                        logger.log(Level.WARNING, String.format("Downloaded Sone %s contains invalid images!", sone));
-                                                       return null;
+                                                       return absent();
                                                }
                                                long creationTime = Numbers.safeParseLong(imageCreationTimeString, 0L);
                                                int imageWidth = Numbers.safeParseInteger(imageWidthString, 0);
                                                int imageHeight = Numbers.safeParseInteger(imageHeightString, 0);
                                                if ((imageWidth < 1) || (imageHeight < 1)) {
                                                        logger.log(Level.WARNING, String.format("Downloaded Sone %s contains image %s with invalid dimensions (%s, %s)!", sone, imageId, imageWidthString, imageHeightString));
-                                                       return null;
+                                                       return absent();
                                                }
                                                Image image = album.newImageBuilder().withId(imageId).at(imageKey).created(creationTime).sized(imageWidth, imageHeight).build(Optional.<ImageCreated>absent());
                                                image = image.modify().setTitle(imageTitle).setDescription(imageDescription).update();
@@ -309,7 +309,7 @@ public class SoneParser {
                sone.setLikePostIds(likedPostIds);
                sone.setLikeReplyIds(likedReplyIds);
 
-               return sone;
+               return of(sone);
        }
 
        private Optional<Integer> parseProtocolVersion(SimpleXML soneXml) {
index 173a67e..e28f49d 100644 (file)
@@ -21,8 +21,11 @@ import static net.pterodactylus.sone.data.Sone.TO_FREENET_URI;
 
 import net.pterodactylus.sone.data.Sone;
 import net.pterodactylus.util.service.AbstractService;
+
 import freenet.keys.FreenetURI;
 
+import com.google.common.base.Optional;
+
 /**
  * The Sone rescuer downloads older editions of a Sone and updates the currently
  * stored Sone with it.
@@ -158,11 +161,11 @@ public class SoneRescuer extends AbstractService {
                                core.lockSone(sone);
                                FreenetURI soneUri = TO_FREENET_URI.apply(sone).setKeyType("SSK").setDocName("Sone-" + currentEdition).setMetaString(new String[] { "sone.xml" });
                                System.out.println("URI: " + soneUri);
-                               Sone fetchedSone = soneDownloader.fetchSone(sone, soneUri, true);
+                               Optional<Sone> fetchedSone = soneDownloader.fetchSone(sone, soneUri, true);
                                System.out.println("Sone: " + fetchedSone);
-                               lastFetchSuccessful = (fetchedSone != null);
+                               lastFetchSuccessful = fetchedSone.isPresent();
                                if (lastFetchSuccessful) {
-                                       core.updateSone(fetchedSone, true);
+                                       core.updateSone(fetchedSone.get(), true);
                                }
                                fetching = false;
                        }
index baa3fdc..3e323ec 100644 (file)
@@ -6,7 +6,6 @@ import static com.google.common.base.Optional.of;
 import static java.lang.String.format;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.hamcrest.CoreMatchers.nullValue;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.mock;
@@ -47,43 +46,51 @@ public class SoneParserTest {
 
        @Test
        public void verifyThatAnInvalidXmlDocumentIsNotParsed() throws UnsupportedEncodingException {
-               assertThat(soneParser.parseSone(database, originalSone, getInputStream("<xml>This is not valid XML.</invalid>")), nullValue());
+               Optional<Sone> sone = soneParser.parseSone(database, originalSone, getInputStream("<xml>This is not valid XML.</invalid>"));
+               assertThat(sone, notNullValue());
+               assertThat(sone.isPresent(), is(false));
        }
 
        @Test
        public void verifyThatANegativeProtocolVersionCausesAnError() {
-               assertThat(soneParser.parseSone(database, originalSone, soneXmlBuilder.setProtocolVersion("-1").get()), nullValue());
+               Optional<Sone> sone = soneParser.parseSone(database, originalSone, soneXmlBuilder.setProtocolVersion("-1").get());
+               assertThat(sone, notNullValue());
+               assertThat(sone.isPresent(), is(false));
        }
 
        @Test
        public void verifyThatATooLargeProtocolVersionCausesAnError() {
-               assertThat(soneParser.parseSone(database, originalSone, soneXmlBuilder.setProtocolVersion("1").get()), nullValue());
+               Optional<Sone> sone = soneParser.parseSone(database, originalSone, soneXmlBuilder.setProtocolVersion("1").get());
+               assertThat(sone, notNullValue());
+               assertThat(sone.isPresent(), is(false));
        }
 
        @Test
        public void verifyThatAMissingClientCausesTheOriginalClientToBeUsed() {
-               Sone sone = soneParser.parseSone(database, originalSone, soneXmlBuilder.removeClientInformation().get());
+               Optional<Sone> sone = soneParser.parseSone(database, originalSone, soneXmlBuilder.removeClientInformation().get());
                assertThat(sone, notNullValue());
-               assertThat(sone.getClient(), notNullValue());
-               assertThat(sone.getClient(), is(originalSone.getClient()));
+               assertThat(sone.isPresent(), is(true));
+               assertThat(sone.get().getClient(), notNullValue());
+               assertThat(sone.get().getClient(), is(originalSone.getClient()));
        }
 
        @Test
        public void verifyThatTheCreatedSoneMeetsAllExpectations() {
-               Sone sone = soneParser.parseSone(database, originalSone, soneXmlBuilder.get());
+               Optional<Sone> sone = soneParser.parseSone(database, originalSone, soneXmlBuilder.get());
                assertThat(sone, notNullValue());
-               assertThat(sone.getTime(), is(1000L));
-               assertThat(sone.getClient(), notNullValue());
-               assertThat(sone.getClient().getName(), is("Test-Client"));
-               assertThat(sone.getClient().getVersion(), is("1.0"));
-               assertThat(sone.getProfile(), notNullValue());
-               assertThat(sone.getProfile().getFirstName(), is("First"));
-               assertThat(sone.getProfile().getMiddleName(), is("M."));
-               assertThat(sone.getProfile().getLastName(), is("Last"));
-               assertThat(sone.getProfile().getBirthYear(), is(2000));
-               assertThat(sone.getProfile().getBirthMonth(), is(9));
-               assertThat(sone.getProfile().getBirthDay(), is(13));
-               assertThat(sone.getProfile().getAvatar(), is("avatar-id"));
+               assertThat(sone.isPresent(), is(true));
+               assertThat(sone.get().getTime(), is(1000L));
+               assertThat(sone.get().getClient(), notNullValue());
+               assertThat(sone.get().getClient().getName(), is("Test-Client"));
+               assertThat(sone.get().getClient().getVersion(), is("1.0"));
+               assertThat(sone.get().getProfile(), notNullValue());
+               assertThat(sone.get().getProfile().getFirstName(), is("First"));
+               assertThat(sone.get().getProfile().getMiddleName(), is("M."));
+               assertThat(sone.get().getProfile().getLastName(), is("Last"));
+               assertThat(sone.get().getProfile().getBirthYear(), is(2000));
+               assertThat(sone.get().getProfile().getBirthMonth(), is(9));
+               assertThat(sone.get().getProfile().getBirthDay(), is(13));
+               assertThat(sone.get().getProfile().getAvatar(), is("avatar-id"));
        }
 
        public InputStream getInputStream(String content) throws UnsupportedEncodingException {