From: David ‘Bombe’ Roden Date: Fri, 26 Nov 2010 15:55:35 +0000 (+0100) Subject: Merge commit '0.3.1-RC2' into next X-Git-Tag: 0.3.2-RC1~26^2~1 X-Git-Url: https://git.pterodactylus.net/?p=Sone.git;a=commitdiff_plain;h=e8411efc4eaff6418cad496eb34fd7bc260eb9cd;hp=99d1fdab0ff92c8d99b5ef578ccfce54c8eebd61 Merge commit '0.3.1-RC2' into next --- diff --git a/pom.xml b/pom.xml index 9b2d5ce..003b20d 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ net.pterodactylus utils - 0.7 + 0.7.1 junit @@ -30,9 +30,15 @@ net.pterodactylus utils.json - 0.1-SNAPSHOT + 0.1 + + + pterodactylus + http://maven.pterodactylus.net/ + + UTF-8 @@ -86,4 +92,19 @@ + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + http://download.oracle.com/javase/6/docs/api/ + http://java.pterodactylus.net/utils/apidocs/ + http://java.pterodactylus.net/utils.json/apidocs/ + + + + + diff --git a/src/main/java/net/pterodactylus/sone/template/PostAccessor.java b/src/main/java/net/pterodactylus/sone/template/PostAccessor.java index de96780..746ed25 100644 --- a/src/main/java/net/pterodactylus/sone/template/PostAccessor.java +++ b/src/main/java/net/pterodactylus/sone/template/PostAccessor.java @@ -17,11 +17,16 @@ package net.pterodactylus.sone.template; +import java.io.IOException; +import java.io.StringReader; + import net.pterodactylus.sone.core.Core; import net.pterodactylus.sone.data.Post; import net.pterodactylus.sone.data.Sone; +import net.pterodactylus.sone.text.FreenetLinkParser; import net.pterodactylus.util.template.DataProvider; import net.pterodactylus.util.template.ReflectionAccessor; +import net.pterodactylus.util.template.TemplateFactory; /** * Accessor for {@link Post} objects that adds additional properties: @@ -34,6 +39,9 @@ import net.pterodactylus.util.template.ReflectionAccessor; */ public class PostAccessor extends ReflectionAccessor { + /** Parser for Freenet links. */ + private final FreenetLinkParser linkParser; + /** The core to get the replies from. */ private final Core core; @@ -42,9 +50,12 @@ public class PostAccessor extends ReflectionAccessor { * * @param core * The core to get the replies from + * @param templateFactory + * The template factory for the text parser */ - public PostAccessor(Core core) { + public PostAccessor(Core core, TemplateFactory templateFactory) { this.core = core; + linkParser = new FreenetLinkParser(templateFactory); } /** @@ -62,6 +73,13 @@ public class PostAccessor extends ReflectionAccessor { return (currentSone != null) && (currentSone.isLikedPostId(post.getId())); } else if (member.equals("new")) { return core.isNewPost(post.getId(), false); + } else if (member.equals("text")) { + String text = post.getText(); + try { + return linkParser.parse(new StringReader(text)); + } catch (IOException ioe1) { + /* ignore. */ + } } return super.get(dataProvider, object, member); } diff --git a/src/main/java/net/pterodactylus/sone/template/ReplyAccessor.java b/src/main/java/net/pterodactylus/sone/template/ReplyAccessor.java index d664697..1ec4e04 100644 --- a/src/main/java/net/pterodactylus/sone/template/ReplyAccessor.java +++ b/src/main/java/net/pterodactylus/sone/template/ReplyAccessor.java @@ -17,12 +17,17 @@ package net.pterodactylus.sone.template; +import java.io.IOException; +import java.io.StringReader; + import net.pterodactylus.sone.core.Core; import net.pterodactylus.sone.data.Reply; import net.pterodactylus.sone.data.Sone; +import net.pterodactylus.sone.text.FreenetLinkParser; import net.pterodactylus.util.template.Accessor; import net.pterodactylus.util.template.DataProvider; import net.pterodactylus.util.template.ReflectionAccessor; +import net.pterodactylus.util.template.TemplateFactory; /** * {@link Accessor} implementation that adds a couple of properties to @@ -32,6 +37,9 @@ import net.pterodactylus.util.template.ReflectionAccessor; */ public class ReplyAccessor extends ReflectionAccessor { + /** Parser for Freenet links. */ + private final FreenetLinkParser linkParser; + /** The core. */ private final Core core; @@ -40,9 +48,12 @@ public class ReplyAccessor extends ReflectionAccessor { * * @param core * The core + * @param templateFactory + * The template factory for the text parser */ - public ReplyAccessor(Core core) { + public ReplyAccessor(Core core, TemplateFactory templateFactory) { this.core = core; + linkParser = new FreenetLinkParser(templateFactory); } /** @@ -58,6 +69,13 @@ public class ReplyAccessor extends ReflectionAccessor { return (currentSone != null) && (currentSone.isLikedReplyId(reply.getId())); } else if (member.equals("new")) { return core.isNewReply(reply.getId(), false); + } else if (member.equals("text")) { + String text = reply.getText(); + try { + return linkParser.parse(new StringReader(text)); + } catch (IOException ioe1) { + /* ignore. */ + } } return super.get(dataProvider, object, member); } diff --git a/src/main/java/net/pterodactylus/sone/text/FreenetLinkParser.java b/src/main/java/net/pterodactylus/sone/text/FreenetLinkParser.java new file mode 100644 index 0000000..7749b00 --- /dev/null +++ b/src/main/java/net/pterodactylus/sone/text/FreenetLinkParser.java @@ -0,0 +1,144 @@ +/* + * Sone - FreenetLinkParser.java - Copyright © 2010 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 . + */ + +package net.pterodactylus.sone.text; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import net.pterodactylus.util.logging.Logging; +import net.pterodactylus.util.template.TemplateFactory; + +/** + * {@link Parser} implementation that can recognize Freenet URIs. + * + * @author David ‘Bombe’ Roden + */ +public class FreenetLinkParser implements Parser { + + /** The logger. */ + private static final Logger logger = Logging.getLogger(FreenetLinkParser.class); + + /** Pattern to detect whitespace. */ + private static final Pattern whitespacePattern = Pattern.compile("[\\p{javaWhitespace}]"); + + /** The template factory. */ + private final TemplateFactory templateFactory; + + /** + * Creates a new freenet link parser. + * + * @param templateFactory + * The template factory + */ + public FreenetLinkParser(TemplateFactory templateFactory) { + this.templateFactory = templateFactory; + } + + // + // PART METHODS + // + + /** + * {@inheritDoc} + */ + @Override + public Part parse(Reader source) throws IOException { + PartContainer parts = new PartContainer(); + BufferedReader bufferedReader = (source instanceof BufferedReader) ? (BufferedReader) source : new BufferedReader(source); + String line; + while ((line = bufferedReader.readLine()) != null) { + line = line.trim() + "\n"; + while (line.length() > 0) { + int nextKsk = line.indexOf("KSK@"); + int nextChk = line.indexOf("CHK@"); + int nextSsk = line.indexOf("SSK@"); + int nextUsk = line.indexOf("USK@"); + if ((nextKsk == -1) && (nextChk == -1) && (nextSsk == -1) && (nextUsk == -1)) { + parts.add(createPlainTextPart(line)); + break; + } + int next = Integer.MAX_VALUE; + if ((nextKsk > -1) && (nextKsk < next)) { + next = nextKsk; + } + if ((nextChk > -1) && (nextChk < next)) { + next = nextChk; + } + if ((nextSsk > -1) && (nextSsk < next)) { + next = nextSsk; + } + if ((nextUsk > -1) && (nextUsk < next)) { + next = nextUsk; + } + Matcher matcher = whitespacePattern.matcher(line); + int nextSpace = matcher.find(next) ? matcher.start() : line.length(); + if (nextSpace > (next + 4)) { + parts.add(createPlainTextPart(line.substring(0, next))); + String link = line.substring(next, nextSpace); + String name = link; + logger.log(Level.FINER, "Found link: " + link); + logger.log(Level.FINEST, "Next: %d, CHK: %d, SSK: %d, USK: %d", new Object[] { next, nextChk, nextSsk, nextUsk }); + if (((next == nextChk) || (next == nextSsk) || (next == nextUsk)) && (link.length() > 98) && (link.charAt(47) == ',') && (link.charAt(91) == ',') && (link.charAt(99) == '/')) { + name = link.substring(0, 47) + "…" + link.substring(99); + } + parts.add(createLinkPart(link, name)); + line = line.substring(nextSpace); + } else { + parts.add(createPlainTextPart(line.substring(0, next + 4))); + line = line.substring(next + 4); + } + } + } + return parts; + } + + // + // PRIVATE METHODS + // + + /** + * Creates a new plain text part based on a template. + * + * @param text + * The text to display + * @return The part that displays the given text + */ + private Part createPlainTextPart(String text) { + return new TemplatePart(templateFactory.createTemplate(new StringReader("<% text|html>"))).set("text", text); + } + + /** + * Creates a new link part based on a template. + * + * @param link + * The target of the link + * @param name + * The name of the link + * @return The part that displays the link + */ + private Part createLinkPart(String link, String name) { + return new TemplatePart(templateFactory.createTemplate(new StringReader("\"><% name|html>"))).set("link", link).set("name", name); + } + +} diff --git a/src/main/java/net/pterodactylus/sone/text/Parser.java b/src/main/java/net/pterodactylus/sone/text/Parser.java new file mode 100644 index 0000000..ccec36a --- /dev/null +++ b/src/main/java/net/pterodactylus/sone/text/Parser.java @@ -0,0 +1,42 @@ +/* + * Sone - Parser.java - Copyright © 2010 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 . + */ + +package net.pterodactylus.sone.text; + +import java.io.IOException; +import java.io.Reader; + +/** + * Interface for parsers that can create {@link Part}s from a text source + * (usually a {@link Reader}). + * + * @author David ‘Bombe’ Roden + */ +public interface Parser { + + /** + * Create a {@link Part} from the given text source. + * + * @param source + * The text source + * @return The parsed part + * @throws IOException + * if an I/O error occurs + */ + public Part parse(Reader source) throws IOException; + +} diff --git a/src/main/java/net/pterodactylus/sone/text/Part.java b/src/main/java/net/pterodactylus/sone/text/Part.java new file mode 100644 index 0000000..b9083b7 --- /dev/null +++ b/src/main/java/net/pterodactylus/sone/text/Part.java @@ -0,0 +1,32 @@ +/* + * Sone - Part.java - Copyright © 2010 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 . + */ + +package net.pterodactylus.sone.text; + +import net.pterodactylus.util.io.Renderable; + +/** + * A part is a single piece of information that can be displayed as a single + * element. + * + * @author David ‘Bombe’ Roden + */ +public interface Part extends Renderable { + + /* all required methods are inherited from {@link Renderable}. */ + +} diff --git a/src/main/java/net/pterodactylus/sone/text/PartContainer.java b/src/main/java/net/pterodactylus/sone/text/PartContainer.java new file mode 100644 index 0000000..7399859 --- /dev/null +++ b/src/main/java/net/pterodactylus/sone/text/PartContainer.java @@ -0,0 +1,65 @@ +/* + * Sone - PartContainer.java - Copyright © 2010 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 . + */ + +package net.pterodactylus.sone.text; + +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; + +/** + * Part implementation that can contain an arbitrary amount of other parts. + * Parts are added using the {@link #add(Part)} method and will be rendered in + * the order they are added. + * + * @author David ‘Bombe’ Roden + */ +public class PartContainer implements Part { + + /** The parts to render. */ + private final List parts = new ArrayList(); + + // + // ACCESSORS + // + + /** + * Adds a part to render. + * + * @param part + * The part to add + */ + public void add(Part part) { + parts.add(part); + } + + // + // PART METHODS + // + + /** + * {@inheritDoc} + */ + @Override + public void render(Writer writer) throws IOException { + for (Part part : parts) { + part.render(writer); + } + } + +} diff --git a/src/main/java/net/pterodactylus/sone/text/TemplatePart.java b/src/main/java/net/pterodactylus/sone/text/TemplatePart.java new file mode 100644 index 0000000..2b27a89 --- /dev/null +++ b/src/main/java/net/pterodactylus/sone/text/TemplatePart.java @@ -0,0 +1,75 @@ +/* + * Sone - TemplatePart.java - Copyright © 2010 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 . + */ + +package net.pterodactylus.sone.text; + +import java.io.IOException; +import java.io.Writer; + +import net.pterodactylus.util.template.Template; + +/** + * {@link Part} implementation that is rendered using a {@link Template}. + * + * @author David ‘Bombe’ Roden + */ +public class TemplatePart implements Part { + + /** The template to render for this part. */ + private final Template template; + + /** + * Creates a new template part. + * + * @param template + * The template to render + */ + public TemplatePart(Template template) { + this.template = template; + } + + // + // ACTIONS + // + + /** + * Sets a variable in the template. + * + * @param key + * The key of the variable + * @param value + * The value of the variable + * @return This template part (for method chaining) + */ + public TemplatePart set(String key, String value) { + template.set(key, value); + return this; + } + + // + // PART METHODS + // + + /** + * {@inheritDoc} + */ + @Override + public void render(Writer writer) throws IOException { + template.render(writer); + } + +} diff --git a/src/main/java/net/pterodactylus/sone/web/WebInterface.java b/src/main/java/net/pterodactylus/sone/web/WebInterface.java index f7e6d36..75b218c 100644 --- a/src/main/java/net/pterodactylus/sone/web/WebInterface.java +++ b/src/main/java/net/pterodactylus/sone/web/WebInterface.java @@ -142,8 +142,8 @@ public class WebInterface implements CoreListener { templateFactory.addAccessor(Object.class, new ReflectionAccessor()); templateFactory.addAccessor(Collection.class, new CollectionAccessor()); templateFactory.addAccessor(Sone.class, new SoneAccessor(getCore())); - templateFactory.addAccessor(Post.class, new PostAccessor(getCore())); - templateFactory.addAccessor(Reply.class, new ReplyAccessor(getCore())); + templateFactory.addAccessor(Post.class, new PostAccessor(getCore(), templateFactory)); + templateFactory.addAccessor(Reply.class, new ReplyAccessor(getCore(), templateFactory)); templateFactory.addAccessor(Identity.class, new IdentityAccessor(getCore())); templateFactory.addAccessor(NotificationManager.class, new NotificationManagerAccessor()); templateFactory.addFilter("date", new DateFilter()); diff --git a/src/main/resources/templates/include/viewPost.html b/src/main/resources/templates/include/viewPost.html index e351fd0..5335227 100644 --- a/src/main/resources/templates/include/viewPost.html +++ b/src/main/resources/templates/include/viewPost.html @@ -7,7 +7,7 @@
-
<% post.text|html>
+
<% post.text>
diff --git a/src/main/resources/templates/include/viewReply.html b/src/main/resources/templates/include/viewReply.html index d77625b..d11aa5f 100644 --- a/src/main/resources/templates/include/viewReply.html +++ b/src/main/resources/templates/include/viewReply.html @@ -7,7 +7,7 @@
-
<% reply.text|html>
+
<% reply.text>
<% reply.time|date format="MMM d, yyyy, HH:mm:ss">