From: David ‘Bombe’ Roden Date: Mon, 21 Oct 2013 05:13:21 +0000 (+0200) Subject: Return an optional from the Sone parser. X-Git-Url: https://git.pterodactylus.net/?a=commitdiff_plain;h=d35ab97a494fd187d3b8fe6b3253b65e3427a077;p=Sone.git Return an optional from the Sone parser. --- diff --git a/src/main/java/net/pterodactylus/sone/core/SoneDownloader.java b/src/main/java/net/pterodactylus/sone/core/SoneDownloader.java index eb263ed..bea7702 100644 --- a/src/main/java/net/pterodactylus/sone/core/SoneDownloader.java +++ b/src/main/java/net/pterodactylus/sone/core/SoneDownloader.java @@ -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 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 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 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 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 parseSone(Sone originalSone, InputStream soneInputStream) { return new SoneParser().parseSone(core.getDatabase(), originalSone, soneInputStream); } diff --git a/src/main/java/net/pterodactylus/sone/core/SoneParser.java b/src/main/java/net/pterodactylus/sone/core/SoneParser.java index 470e163..d251989 100644 --- a/src/main/java/net/pterodactylus/sone/core/SoneParser.java +++ b/src/main/java/net/pterodactylus/sone/core/SoneParser.java @@ -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 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 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 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.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 parseProtocolVersion(SimpleXML soneXml) { diff --git a/src/main/java/net/pterodactylus/sone/core/SoneRescuer.java b/src/main/java/net/pterodactylus/sone/core/SoneRescuer.java index 173a67e..e28f49d 100644 --- a/src/main/java/net/pterodactylus/sone/core/SoneRescuer.java +++ b/src/main/java/net/pterodactylus/sone/core/SoneRescuer.java @@ -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 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; } diff --git a/src/test/java/net/pterodactylus/sone/core/SoneParserTest.java b/src/test/java/net/pterodactylus/sone/core/SoneParserTest.java index baa3fdc..3e323ec 100644 --- a/src/test/java/net/pterodactylus/sone/core/SoneParserTest.java +++ b/src/test/java/net/pterodactylus/sone/core/SoneParserTest.java @@ -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("This is not valid XML.")), nullValue()); + Optional sone = soneParser.parseSone(database, originalSone, getInputStream("This is not valid XML.")); + assertThat(sone, notNullValue()); + assertThat(sone.isPresent(), is(false)); } @Test public void verifyThatANegativeProtocolVersionCausesAnError() { - assertThat(soneParser.parseSone(database, originalSone, soneXmlBuilder.setProtocolVersion("-1").get()), nullValue()); + Optional 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 = 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 = 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 = 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 {