Ignore commas at the end of links, too
[Sone.git] / src / main / java / net / pterodactylus / sone / text / SoneTextParser.java
index 18dd53f..dbfa0f3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sone - SoneTextParser.java - Copyright © 2010–2015 David Roden
+ * Sone - SoneTextParser.java - Copyright © 2010–2016 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
@@ -28,6 +28,9 @@ import java.util.logging.Logger;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 import net.pterodactylus.sone.data.Post;
 import net.pterodactylus.sone.data.Sone;
 import net.pterodactylus.sone.data.impl.IdOnlySone;
@@ -117,8 +120,9 @@ public class SoneTextParser implements Parser<SoneTextParserContext> {
        /**
         * {@inheritDoc}
         */
+       @Nonnull
        @Override
-       public Iterable<Part> parse(SoneTextParserContext context, String source) {
+       public Iterable<Part> parse(@Nonnull String source, @Nullable SoneTextParserContext context) {
                PartContainer parts = new PartContainer();
                BufferedReader bufferedReader = new BufferedReader(new StringReader(source));
                try {
@@ -171,9 +175,8 @@ public class SoneTextParser implements Parser<SoneTextParserContext> {
                                        }
                                        lineComplete = false;
 
-                                       Matcher matcher = whitespacePattern.matcher(line);
-                                       int nextSpace = matcher.find(0) ? matcher.start() : line.length();
-                                       String link = line.substring(0, nextSpace);
+                                       int endOfLink = findEndOfLink(line);
+                                       String link = line.substring(0, endOfLink);
                                        String name = link;
                                        logger.log(Level.FINER, String.format("Found link: %s", link));
 
@@ -267,7 +270,7 @@ public class SoneTextParser implements Parser<SoneTextParserContext> {
                                                }
                                                parts.add(new LinkPart(link, name));
                                        }
-                                       line = line.substring(nextSpace);
+                                       line = line.substring(endOfLink);
                                }
                                lastLineEmpty = false;
                        }
@@ -287,6 +290,40 @@ public class SoneTextParser implements Parser<SoneTextParserContext> {
                return parts;
        }
 
+       private int findEndOfLink(String line) {
+               Matcher matcher = whitespacePattern.matcher(line);
+               if (!matcher.find(0)) {
+                       return line.length();
+               }
+               int nextWhitespace = matcher.start();
+               int lastPunctuation = nextWhitespace;
+               while (isPunctuation(line.charAt(lastPunctuation - 1))) {
+                       lastPunctuation -= 1;
+               }
+               if (lastPunctuation < nextWhitespace) {
+                       return lastPunctuation;
+               }
+               int openParens = 0;
+               for (int i = 0; i < nextWhitespace; i++) {
+                       switch (line.charAt(i)) {
+                               case '(':
+                                       openParens++;
+                                       break;
+                               case ')':
+                                       openParens--;
+                                       if (openParens < 0) {
+                                               return i;
+                                       }
+                               default:
+                       }
+               }
+               return nextWhitespace;
+       }
+
+       private boolean isPunctuation(char character) {
+               return (character == '.') || (character == ',');
+       }
+
        private static class NextLink {
 
                private final int position;