X-Git-Url: https://git.pterodactylus.net/?p=Sone.git;a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Fsone%2Ftext%2FSoneTextParser.java;h=1573d1ce3c4f43108edb21e5980664c45cdd9af1;hp=98ff36bb1ac51819f06bcaf7a067dd8566bdf135;hb=fbae4981d8b42f5ad79a82b6c883a45670b175d8;hpb=cd8d01f4da6fc89da0799c27f07b795ea25caec0 diff --git a/src/main/java/net/pterodactylus/sone/text/SoneTextParser.java b/src/main/java/net/pterodactylus/sone/text/SoneTextParser.java index 98ff36b..1573d1c 100644 --- a/src/main/java/net/pterodactylus/sone/text/SoneTextParser.java +++ b/src/main/java/net/pterodactylus/sone/text/SoneTextParser.java @@ -1,5 +1,5 @@ /* - * Sone - FreenetLinkParser.java - Copyright © 2010–2012 David Roden + * Sone - SoneTextParser.java - Copyright © 2010–2013 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,6 +17,8 @@ package net.pterodactylus.sone.text; +import static java.util.logging.Logger.getLogger; + import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; @@ -26,12 +28,15 @@ import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; -import net.pterodactylus.sone.core.PostProvider; -import net.pterodactylus.sone.core.SoneProvider; import net.pterodactylus.sone.data.Post; import net.pterodactylus.sone.data.Sone; +import net.pterodactylus.sone.data.impl.IdOnlySone; +import net.pterodactylus.sone.database.PostProvider; +import net.pterodactylus.sone.database.SoneProvider; import net.pterodactylus.util.io.Closer; -import net.pterodactylus.util.logging.Logging; + +import com.google.common.base.Optional; + import freenet.keys.FreenetURI; /** @@ -42,7 +47,7 @@ import freenet.keys.FreenetURI; public class SoneTextParser implements Parser { /** The logger. */ - private static final Logger logger = Logging.getLogger(SoneTextParser.class); + private static final Logger logger = getLogger(SoneTextParser.class.getName()); /** Pattern to detect whitespace. */ private static final Pattern whitespacePattern = Pattern.compile("[\\u000a\u0020\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u200c\u200d\u202f\u205f\u2060\u2800\u3000]"); @@ -54,41 +59,21 @@ public class SoneTextParser implements Parser { */ private enum LinkType { - /** Link is a KSK. */ - KSK("KSK@"), - - /** Link is a CHK. */ - CHK("CHK@"), - - /** Link is an SSK. */ - SSK("SSK@"), - - /** Link is a USK. */ - USK("USK@"), - - /** Link is HTTP. */ - HTTP("http://"), + KSK("KSK@", true), + CHK("CHK@", true), + SSK("SSK@", true), + USK("USK@", true), + HTTP("http://", false), + HTTPS("https://", false), + SONE("sone://", false), + POST("post://", false); - /** Link is HTTPS. */ - HTTPS("https://"), - - /** Link is a Sone. */ - SONE("sone://"), - - /** Link is a post. */ - POST("post://"); - - /** The scheme identifying this link type. */ private final String scheme; + private final boolean freenetLink; - /** - * Creates a new link type identified by the given scheme. - * - * @param scheme - * The scheme of the link type - */ - private LinkType(String scheme) { + LinkType(String scheme, boolean freenetLink) { this.scheme = scheme; + this.freenetLink = freenetLink; } /** @@ -100,6 +85,10 @@ public class SoneTextParser implements Parser { return scheme; } + public boolean isFreenetLink() { + return freenetLink; + } + } /** The Sone provider. */ @@ -154,15 +143,8 @@ public class SoneTextParser implements Parser { */ boolean lineComplete = true; while (line.length() > 0) { - int nextKsk = line.indexOf("KSK@"); - int nextChk = line.indexOf("CHK@"); - int nextSsk = line.indexOf("SSK@"); - int nextUsk = line.indexOf("USK@"); - int nextHttp = line.indexOf("http://"); - int nextHttps = line.indexOf("https://"); - int nextSone = line.indexOf("sone://"); - int nextPost = line.indexOf("post://"); - if ((nextKsk == -1) && (nextChk == -1) && (nextSsk == -1) && (nextUsk == -1) && (nextHttp == -1) && (nextHttps == -1) && (nextSone == -1) && (nextPost == -1)) { + Optional nextLink = NextLink.findNextLink(line); + if (!nextLink.isPresent()) { if (lineComplete && !lastLineEmpty) { parts.add(new PlainTextPart("\n" + line)); } else { @@ -170,43 +152,11 @@ public class SoneTextParser implements Parser { } break; } - int next = Integer.MAX_VALUE; - LinkType linkType = null; - if ((nextKsk > -1) && (nextKsk < next)) { - next = nextKsk; - linkType = LinkType.KSK; - } - if ((nextChk > -1) && (nextChk < next)) { - next = nextChk; - linkType = LinkType.CHK; - } - if ((nextSsk > -1) && (nextSsk < next)) { - next = nextSsk; - linkType = LinkType.SSK; - } - if ((nextUsk > -1) && (nextUsk < next)) { - next = nextUsk; - linkType = LinkType.USK; - } - if ((nextHttp > -1) && (nextHttp < next)) { - next = nextHttp; - linkType = LinkType.HTTP; - } - if ((nextHttps > -1) && (nextHttps < next)) { - next = nextHttps; - linkType = LinkType.HTTPS; - } - if ((nextSone > -1) && (nextSone < next)) { - next = nextSone; - linkType = LinkType.SONE; - } - if ((nextPost > -1) && (nextPost < next)) { - next = nextPost; - linkType = LinkType.POST; - } + LinkType linkType = nextLink.get().getLinkType(); + int next = nextLink.get().getPosition(); /* cut off “freenet:” from before keys. */ - if (((linkType == LinkType.KSK) || (linkType == LinkType.CHK) || (linkType == LinkType.SSK) || (linkType == LinkType.USK)) && (next >= 8) && (line.substring(next - 8, next).equals("freenet:"))) { + if (linkType.isFreenetLink() && (next >= 8) && (line.substring(next - 8, next).equals("freenet:"))) { next -= 8; line = line.substring(0, next) + line.substring(next + 8); } @@ -218,22 +168,34 @@ public class SoneTextParser implements Parser { if (next > 0) { parts.add(new PlainTextPart(line.substring(0, next))); line = line.substring(next); - next = 0; } lineComplete = false; + Matcher matcher = whitespacePattern.matcher(line); + int nextSpace = matcher.find(0) ? matcher.start() : line.length(); + String link = line.substring(0, nextSpace); + String name = link; + logger.log(Level.FINER, String.format("Found link: %s", link)); + + /* if there is no text after the scheme, it’s not a link! */ + if (link.equals(linkType.getScheme())) { + parts.add(new PlainTextPart(linkType.getScheme())); + line = line.substring(linkType.getScheme().length()); + continue; + } + if (linkType == LinkType.SONE) { if (line.length() >= (7 + 43)) { String soneId = line.substring(7, 50); - Sone sone = soneProvider.getSone(soneId, false); - if (sone == null) { + Optional sone = soneProvider.getSone(soneId); + if (!sone.isPresent()) { /* * don’t use create=true above, we don’t want * the empty shell. */ - sone = new Sone(soneId); + sone = Optional.of(new IdOnlySone(soneId)); } - parts.add(new SonePart(sone)); + parts.add(new SonePart(sone.get())); line = line.substring(50); } else { parts.add(new PlainTextPart(line)); @@ -242,29 +204,17 @@ public class SoneTextParser implements Parser { continue; } if (linkType == LinkType.POST) { - if (line.length() >= (7 + 36)) { - String postId = line.substring(7, 43); - Post post = postProvider.getPost(postId, false); - if ((post != null) && (post.getSone() != null)) { - parts.add(new PostPart(post)); - } else { - parts.add(new PlainTextPart(line.substring(0, 43))); - } - line = line.substring(43); + Optional post = postProvider.getPost(link.substring(7)); + if (post.isPresent()) { + parts.add(new PostPart(post.get(), link.substring(7).equals(post.get().getInternalId()))); } else { - parts.add(new PlainTextPart(line)); - line = ""; + parts.add(new PlainTextPart(link)); } + line = line.substring(link.length()); continue; } - Matcher matcher = whitespacePattern.matcher(line); - int nextSpace = matcher.find(0) ? matcher.start() : line.length(); - String link = line.substring(0, nextSpace); - String name = link; - logger.log(Level.FINER, String.format("Found link: %s", link)); - logger.log(Level.FINEST, String.format("CHK: %d, SSK: %d, USK: %d", nextChk, nextSsk, nextUsk)); - if ((linkType == LinkType.KSK) || (linkType == LinkType.CHK) || (linkType == LinkType.SSK) || (linkType == LinkType.USK)) { + if (linkType.isFreenetLink()) { FreenetURI uri; if (name.indexOf('?') > -1) { name = name.substring(0, name.indexOf('?')); @@ -322,7 +272,7 @@ public class SoneTextParser implements Parser { } for (int partIndex = parts.size() - 1; partIndex >= 0; --partIndex) { Part part = parts.getPart(partIndex); - if (!(part instanceof PlainTextPart) || !"\n".equals(((PlainTextPart) part).getText())) { + if (!(part instanceof PlainTextPart) || !"\n".equals(part.getText())) { break; } parts.removePart(partIndex); @@ -330,4 +280,40 @@ public class SoneTextParser implements Parser { return parts; } + private static class NextLink { + + private final int position; + private final LinkType linkType; + + private NextLink(int position, LinkType linkType) { + this.position = position; + this.linkType = linkType; + } + + public int getPosition() { + return position; + } + + public LinkType getLinkType() { + return linkType; + } + + public static Optional findNextLink(String line) { + int earliestLinkPosition = Integer.MAX_VALUE; + LinkType linkType = null; + for (LinkType possibleLinkType : LinkType.values()) { + int nextLinkPosition = line.indexOf(possibleLinkType.getScheme()); + if (nextLinkPosition > -1) { + if (nextLinkPosition < earliestLinkPosition) { + earliestLinkPosition = nextLinkPosition; + linkType = possibleLinkType; + } + } + } + return earliestLinkPosition < Integer.MAX_VALUE ? + Optional.of(new NextLink(earliestLinkPosition, linkType)) : Optional.absent(); + } + + } + }