From 63b23843a6863030f174b7affa83142e9e7863d3 Mon Sep 17 00:00:00 2001 From: icyerasor Date: Fri, 26 Dec 2014 17:09:13 +0100 Subject: [PATCH 1/6] Added Atom Threading Extensions Module, see (http://purl.org/syndication/thread/1.0 - http://www.ietf.org/rfc/rfc4685.txt ) --- .../modules/thr/ThreadingModule.java | 29 +++++ .../modules/thr/ThreadingModuleImpl.java | 109 ++++++++++++++++++ .../thr/io/ThreadingModuleGenerator.java | 62 ++++++++++ .../modules/thr/io/ThreadingModuleParser.java | 42 +++++++ src/main/resources/rome.properties | 6 +- .../modules/thr/io/ThreadingModuleTest.java | 108 +++++++++++++++++ src/test/resources/thr/threading-main.xml | 25 ++++ 7 files changed, 379 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/rometools/modules/thr/ThreadingModule.java create mode 100644 src/main/java/com/rometools/modules/thr/ThreadingModuleImpl.java create mode 100644 src/main/java/com/rometools/modules/thr/io/ThreadingModuleGenerator.java create mode 100644 src/main/java/com/rometools/modules/thr/io/ThreadingModuleParser.java create mode 100644 src/test/java/com/rometools/modules/thr/io/ThreadingModuleTest.java create mode 100644 src/test/resources/thr/threading-main.xml diff --git a/src/main/java/com/rometools/modules/thr/ThreadingModule.java b/src/main/java/com/rometools/modules/thr/ThreadingModule.java new file mode 100644 index 0000000..fd6495e --- /dev/null +++ b/src/main/java/com/rometools/modules/thr/ThreadingModule.java @@ -0,0 +1,29 @@ +package com.rometools.modules.thr; + +import com.rometools.rome.feed.module.Module; + +/** + * Currently no support for thr:count, thr:updated, thr:total link attributes. + * + * @author Andreas Feldschmid + */ +public interface ThreadingModule extends Module { + + public static final String URI = "http://purl.org/syndication/thread/1.0"; + + public String getRef(); + + public void setRef(String ref); + + public String getType(); + + public void setType(String type); + + public String getHref(); + + public void setHref(String href); + + public String getSource(); + + public void setSource(String href); +} diff --git a/src/main/java/com/rometools/modules/thr/ThreadingModuleImpl.java b/src/main/java/com/rometools/modules/thr/ThreadingModuleImpl.java new file mode 100644 index 0000000..1bd634a --- /dev/null +++ b/src/main/java/com/rometools/modules/thr/ThreadingModuleImpl.java @@ -0,0 +1,109 @@ +package com.rometools.modules.thr; + +import com.rometools.rome.feed.CopyFrom; +import com.rometools.rome.feed.impl.EqualsBean; +import com.rometools.rome.feed.impl.ToStringBean; +import com.rometools.rome.feed.module.ModuleImpl; + +/** + * Currently no support for thr:count, thr:updated, thr:total link attributes. + * + * @author Andreas Feldschmid + */ +public class ThreadingModuleImpl extends ModuleImpl implements ThreadingModule { + + private static final long serialVersionUID = 1L; + + private String ref; + private String href; + private String type; + private String source; + + public ThreadingModuleImpl() { + super(ThreadingModule.class, ThreadingModule.URI); + } + + @Override + public Class getInterface() { + return ThreadingModule.class; + } + + @Override + public void copyFrom(CopyFrom copyFrom) { + if (copyFrom instanceof ThreadingModule) { + ThreadingModule module = (ThreadingModule) copyFrom; + setHref(module.getHref()); + setRef(module.getRef()); + setType(module.getType()); + } + } + + @Override + public String getRef() { + return ref; + } + + @Override + public void setRef(String ref) { + this.ref = ref; + } + + @Override + public String getType() { + return type; + } + + @Override + public void setType(String type) { + this.type = type; + } + + @Override + public String getHref() { + return href; + } + + @Override + public void setHref(String href) { + this.href = href; + } + + @Override + public String getSource() { + return source; + } + + @Override + public void setSource(String source) { + this.source = source; + } + + @Override + public Object clone() { + final ThreadingModule m = new ThreadingModuleImpl(); + m.setHref(href); + m.setRef(ref); + m.setSource(source); + m.setType(type); + return m; + } + + @Override + public boolean equals(final Object obj) { + final EqualsBean eBean = new EqualsBean(ThreadingModuleImpl.class, this); + return eBean.beanEquals(obj); + } + + @Override + public int hashCode() { + final EqualsBean equals = new EqualsBean(ThreadingModuleImpl.class, this); + return equals.beanHashCode(); + } + + @Override + public String toString() { + final ToStringBean tsBean = new ToStringBean(ThreadingModuleImpl.class, this); + return tsBean.toString(); + } + +} diff --git a/src/main/java/com/rometools/modules/thr/io/ThreadingModuleGenerator.java b/src/main/java/com/rometools/modules/thr/io/ThreadingModuleGenerator.java new file mode 100644 index 0000000..09ea982 --- /dev/null +++ b/src/main/java/com/rometools/modules/thr/io/ThreadingModuleGenerator.java @@ -0,0 +1,62 @@ +package com.rometools.modules.thr.io; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.jdom2.Element; +import org.jdom2.Namespace; + +import com.rometools.modules.thr.ThreadingModule; +import com.rometools.rome.feed.module.Module; +import com.rometools.rome.io.ModuleGenerator; + +/** + * Currently no support for thr:count, thr:updated, thr:total link attributes. + * + * @author Andreas Feldschmid + */ +public class ThreadingModuleGenerator implements ModuleGenerator { + + private static final Namespace NAMESPACE = Namespace.getNamespace("thr", ThreadingModule.URI); + private static final Set NAMESPACES; + + static { + Set namespaces = new HashSet(); + namespaces.add(NAMESPACE); + NAMESPACES = Collections.unmodifiableSet(namespaces); + } + + @Override + public String getNamespaceUri() { + return ThreadingModule.URI; + } + + @Override + public Set getNamespaces() { + return NAMESPACES; + } + + @Override + public void generate(Module module, Element element) { + if (module != null && module instanceof ThreadingModule) { + ThreadingModule threadedModule = (ThreadingModule) module; + Element inReplyTo = new Element("in-reply-to", NAMESPACE); + + if (threadedModule.getHref() != null) { + inReplyTo.setAttribute("href", threadedModule.getHref()); + } + if (threadedModule.getRef() != null) { + inReplyTo.setAttribute("ref", threadedModule.getRef()); + } + if (threadedModule.getType() != null) { + inReplyTo.setAttribute("type", threadedModule.getType()); + } + if (threadedModule.getSource() != null) { + inReplyTo.setAttribute("source", threadedModule.getSource()); + } + + element.addContent(inReplyTo); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/rometools/modules/thr/io/ThreadingModuleParser.java b/src/main/java/com/rometools/modules/thr/io/ThreadingModuleParser.java new file mode 100644 index 0000000..ecba871 --- /dev/null +++ b/src/main/java/com/rometools/modules/thr/io/ThreadingModuleParser.java @@ -0,0 +1,42 @@ +package com.rometools.modules.thr.io; + +import java.util.Locale; + +import org.jdom2.Element; +import org.jdom2.Namespace; + +import com.rometools.modules.thr.ThreadingModule; +import com.rometools.modules.thr.ThreadingModuleImpl; +import com.rometools.rome.feed.module.Module; +import com.rometools.rome.io.ModuleParser; + +/** + * Currently no support for thr:count, thr:updated, thr:total link attributes. + * + * @author Andreas Feldschmid + */ +public class ThreadingModuleParser implements ModuleParser { + + private static final Namespace NS = Namespace.getNamespace(ThreadingModule.URI); + + @Override + public String getNamespaceUri() { + return ThreadingModule.URI; + } + + @Override + public Module parse(final Element element, final Locale locale) { + final ThreadingModule tm = new ThreadingModuleImpl(); + Element inReplyTo = element.getChild("in-reply-to", ThreadingModuleParser.NS); + + if (inReplyTo != null) { + tm.setHref(inReplyTo.getAttributeValue("href")); + tm.setRef(inReplyTo.getAttributeValue("ref")); + tm.setSource(inReplyTo.getAttributeValue("source")); + tm.setType(inReplyTo.getAttributeValue("type")); + return tm; + } + + return null; + } +} diff --git a/src/main/resources/rome.properties b/src/main/resources/rome.properties index c05fe38..355dffd 100644 --- a/src/main/resources/rome.properties +++ b/src/main/resources/rome.properties @@ -74,7 +74,8 @@ atom_1.0.item.ModuleParser.classes=com.rometools.modules.cc.io.ModuleParserRSS2 com.rometools.modules.georss.W3CGeoParser \ com.rometools.modules.photocast.io.Parser \ com.rometools.modules.mediarss.io.MediaModuleParser \ - com.rometools.modules.mediarss.io.AlternateMediaModuleParser + com.rometools.modules.mediarss.io.AlternateMediaModuleParser \ + com.rometools.modules.thr.io.ThreadingModuleParser rss_2.0.feed.ModuleGenerator.classes=com.rometools.modules.cc.io.CCModuleGenerator \ com.rometools.modules.content.io.ContentModuleGenerator \ @@ -137,7 +138,8 @@ atom_1.0.item.ModuleGenerator.classes=com.rometools.modules.cc.io.CCModuleGenera com.rometools.modules.georss.SimpleGenerator \ com.rometools.modules.georss.W3CGeoGenerator \ com.rometools.modules.photocast.io.Generator \ - com.rometools.modules.mediarss.io.MediaModuleGenerator + com.rometools.modules.mediarss.io.MediaModuleGenerator \ + com.rometools.modules.thr.io.ThreadingModuleGenerator rss_2.0wNS.feed.ModuleParser.classes=com.rometools.modules.mediarss.io.MediaModuleParser rss_2.0wNS.item.ModuleParser.classes=com.rometools.modules.mediarss.io.MediaModuleParser diff --git a/src/test/java/com/rometools/modules/thr/io/ThreadingModuleTest.java b/src/test/java/com/rometools/modules/thr/io/ThreadingModuleTest.java new file mode 100644 index 0000000..55ee348 --- /dev/null +++ b/src/test/java/com/rometools/modules/thr/io/ThreadingModuleTest.java @@ -0,0 +1,108 @@ +package com.rometools.modules.thr.io; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import com.rometools.modules.AbstractTestCase; +import com.rometools.modules.thr.ThreadingModule; +import com.rometools.modules.thr.ThreadingModuleImpl; +import com.rometools.rome.feed.module.Module; +import com.rometools.rome.feed.synd.SyndEntry; +import com.rometools.rome.feed.synd.SyndEntryImpl; +import com.rometools.rome.feed.synd.SyndFeed; +import com.rometools.rome.io.FeedException; +import com.rometools.rome.io.SyndFeedInput; +import com.rometools.rome.io.SyndFeedOutput; + +/** + * + * @author Andreas Feldschmid + */ +public class ThreadingModuleTest extends AbstractTestCase { + + public ThreadingModuleTest(String testName) { + super(testName); + } + + public void testReadMainSpec() throws IOException, FeedException { + final SyndFeed feed = getSyndFeed("thr/threading-main.xml"); + List entries = feed.getEntries(); + SyndEntry parentEntry = entries.get(0); + assertEquals("should be the parent entry", "My original entry", parentEntry.getTitle()); + assertNull(parentEntry.getModule(ThreadingModule.URI)); + + SyndEntry replyEntry = entries.get(1); + assertEquals("should be the reply entry", "A response to the original", replyEntry.getTitle()); + Module module = replyEntry.getModule(ThreadingModule.URI); + assertNotNull(module); + ThreadingModule threadingModule = (ThreadingModule) module; + assertEquals("tag:example.org,2005:1", threadingModule.getRef()); + assertEquals("application/xhtml+xml", threadingModule.getType()); + assertEquals("http://www.example.org/entries/1", threadingModule.getHref()); + } + + public void testGenerate() throws IOException, FeedException { + final SyndFeed feed = getSyndFeed("thr/threading-main.xml"); + List entries = feed.getEntries(); + + // create a new "root" entry that the next entry will reference to + SyndEntry newRootEntry = new SyndEntryImpl(); + newRootEntry.setTitle("New, 2nd root entry"); + newRootEntry.setUri("tag:example.org,2005:2"); + newRootEntry.setLink("http://www.example.org/entries/2"); + entries.add(newRootEntry); + + // create a new reply entry that will reference the new root entry + SyndEntry newReplyEntry = new SyndEntryImpl(); + newReplyEntry.setTitle("New test reply entry"); + newReplyEntry.setUri("tag:example.org,2005:2,1"); + + ThreadingModule threadingModule = new ThreadingModuleImpl(); + threadingModule.setRef("tag:example.org,2005:2"); + threadingModule.setType("application/xhtml+xml"); + threadingModule.setHref("http://www.example.org/entries/2"); + + newReplyEntry.getModules().add(threadingModule); + entries.add(newReplyEntry); + + File outputFile = new File("target/threading-testGenerate.xml"); + final SyndFeedOutput output = new SyndFeedOutput(); + output.output(feed, outputFile); + + // read back in and validate + final SyndFeed generatedFeed = getSyndFeed(outputFile); + SyndEntry generatedReplyEntry = generatedFeed.getEntries().get(3); + assertNotNull(generatedReplyEntry); + ThreadingModule generatedReplyThreadingModule = (ThreadingModule) generatedReplyEntry.getModule(ThreadingModule.URI); + assertEquals(generatedReplyThreadingModule.getRef(), "tag:example.org,2005:2"); + assertEquals(generatedReplyThreadingModule.getType(), "application/xhtml+xml"); + assertEquals(generatedReplyThreadingModule.getHref(), "http://www.example.org/entries/2"); + } + + public void testEnd2End() throws IOException, FeedException { + final SyndFeed feed = getSyndFeed("thr/threading-main.xml"); + final SyndFeedOutput output = new SyndFeedOutput(); + File outputFile = new File("target/threading-main-generated.xml"); + output.output(feed, outputFile); + + final SyndFeed feedOut = getSyndFeed(outputFile); + + ThreadingModule moduleSrc = (ThreadingModule) feed.getEntries().get(1).getModule(ThreadingModule.URI); + ThreadingModule moduleOut = (ThreadingModule) feedOut.getEntries().get(1).getModule(ThreadingModule.URI); + assertEquals(moduleSrc, moduleOut); + assertEquals("tag:example.org,2005:1", moduleSrc.getRef()); + assertEquals("tag:example.org,2005:1", moduleOut.getRef()); + } + + private SyndFeed getSyndFeed(final File file) throws IOException, FeedException { + return new SyndFeedInput().build(file); + } + + private SyndFeed getSyndFeed(final String filePath) throws IOException, FeedException { + final String fullPath = getTestFile(filePath); + final File file = new File(fullPath); + return new SyndFeedInput().build(file); + } + +} diff --git a/src/test/resources/thr/threading-main.xml b/src/test/resources/thr/threading-main.xml new file mode 100644 index 0000000..fcf392c --- /dev/null +++ b/src/test/resources/thr/threading-main.xml @@ -0,0 +1,25 @@ + + http://www.example.org/myfeed + My Example Feed + 2005-07-28T12:00:00Z + + + James + + + tag:example.org,2005:1 + My original entry + 2006-03-01T12:12:12Z + + This is my original entry + + + tag:example.org,2005:1,1 + A response to the original + 2006-03-01T12:12:12Z + + + This is a response to the original entry + + \ No newline at end of file From c6cdda53ce746887423adb20c0c2b9b03cf1b1b4 Mon Sep 17 00:00:00 2001 From: icyerasor Date: Fri, 26 Dec 2014 17:45:24 +0100 Subject: [PATCH 2/6] added newlines --- .../com/rometools/modules/thr/io/ThreadingModuleGenerator.java | 2 +- src/test/resources/thr/threading-main.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/rometools/modules/thr/io/ThreadingModuleGenerator.java b/src/main/java/com/rometools/modules/thr/io/ThreadingModuleGenerator.java index 09ea982..af51f83 100644 --- a/src/main/java/com/rometools/modules/thr/io/ThreadingModuleGenerator.java +++ b/src/main/java/com/rometools/modules/thr/io/ThreadingModuleGenerator.java @@ -59,4 +59,4 @@ public class ThreadingModuleGenerator implements ModuleGenerator { element.addContent(inReplyTo); } } -} \ No newline at end of file +} diff --git a/src/test/resources/thr/threading-main.xml b/src/test/resources/thr/threading-main.xml index fcf392c..6d22220 100644 --- a/src/test/resources/thr/threading-main.xml +++ b/src/test/resources/thr/threading-main.xml @@ -22,4 +22,4 @@ href="http://www.example.org/entries/1" /> This is a response to the original entry - \ No newline at end of file + From aa16b1a33b9d9ef5a51990a64484b5a0f7230dda Mon Sep 17 00:00:00 2001 From: icyerasor Date: Fri, 26 Dec 2014 18:45:52 +0100 Subject: [PATCH 3/6] improve ThreadingModuleTest - also test source attribute --- .../rometools/modules/thr/io/ThreadingModuleTest.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/rometools/modules/thr/io/ThreadingModuleTest.java b/src/test/java/com/rometools/modules/thr/io/ThreadingModuleTest.java index 55ee348..3c01c8d 100644 --- a/src/test/java/com/rometools/modules/thr/io/ThreadingModuleTest.java +++ b/src/test/java/com/rometools/modules/thr/io/ThreadingModuleTest.java @@ -40,6 +40,7 @@ public class ThreadingModuleTest extends AbstractTestCase { assertEquals("tag:example.org,2005:1", threadingModule.getRef()); assertEquals("application/xhtml+xml", threadingModule.getType()); assertEquals("http://www.example.org/entries/1", threadingModule.getHref()); + assertNull(threadingModule.getSource()); } public void testGenerate() throws IOException, FeedException { @@ -62,6 +63,7 @@ public class ThreadingModuleTest extends AbstractTestCase { threadingModule.setRef("tag:example.org,2005:2"); threadingModule.setType("application/xhtml+xml"); threadingModule.setHref("http://www.example.org/entries/2"); + threadingModule.setSource("http://example.org/entries/2"); newReplyEntry.getModules().add(threadingModule); entries.add(newReplyEntry); @@ -75,9 +77,10 @@ public class ThreadingModuleTest extends AbstractTestCase { SyndEntry generatedReplyEntry = generatedFeed.getEntries().get(3); assertNotNull(generatedReplyEntry); ThreadingModule generatedReplyThreadingModule = (ThreadingModule) generatedReplyEntry.getModule(ThreadingModule.URI); - assertEquals(generatedReplyThreadingModule.getRef(), "tag:example.org,2005:2"); - assertEquals(generatedReplyThreadingModule.getType(), "application/xhtml+xml"); - assertEquals(generatedReplyThreadingModule.getHref(), "http://www.example.org/entries/2"); + assertEquals("tag:example.org,2005:2", generatedReplyThreadingModule.getRef()); + assertEquals("application/xhtml+xml", generatedReplyThreadingModule.getType()); + assertEquals("http://www.example.org/entries/2", generatedReplyThreadingModule.getHref()); + assertEquals("http://example.org/entries/2", generatedReplyThreadingModule.getSource()); } public void testEnd2End() throws IOException, FeedException { From 4b5e4d99264068ff6f331f89ccd0b1cf2b8e813b Mon Sep 17 00:00:00 2001 From: icyerasor Date: Sat, 27 Dec 2014 21:02:07 +0100 Subject: [PATCH 4/6] remove old, unused atomthread package / class --- .../modules/atomthread/ThreadModule.java | 26 ------------------- 1 file changed, 26 deletions(-) delete mode 100644 src/main/java/com/rometools/modules/atomthread/ThreadModule.java diff --git a/src/main/java/com/rometools/modules/atomthread/ThreadModule.java b/src/main/java/com/rometools/modules/atomthread/ThreadModule.java deleted file mode 100644 index 09e0f2a..0000000 --- a/src/main/java/com/rometools/modules/atomthread/ThreadModule.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2011 robert.cooper. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * under the License. - */ - -package com.rometools.modules.atomthread; - -/** - * - * @author robert.cooper - */ -public interface ThreadModule { - -} From 8b92511c60566b9e4b57bf9c841b81f4ea116792 Mon Sep 17 00:00:00 2001 From: icyerasor Date: Mon, 30 Nov 2015 11:55:38 +0100 Subject: [PATCH 5/6] rename param to source --- src/main/java/com/rometools/modules/thr/ThreadingModule.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/rometools/modules/thr/ThreadingModule.java b/src/main/java/com/rometools/modules/thr/ThreadingModule.java index fd6495e..98f19b9 100644 --- a/src/main/java/com/rometools/modules/thr/ThreadingModule.java +++ b/src/main/java/com/rometools/modules/thr/ThreadingModule.java @@ -25,5 +25,5 @@ public interface ThreadingModule extends Module { public String getSource(); - public void setSource(String href); + public void setSource(String source); } From abbb30bb66caf2ee31f5ee9e593f00ef86bf2388 Mon Sep 17 00:00:00 2001 From: icyerasor Date: Mon, 30 Nov 2015 11:56:21 +0100 Subject: [PATCH 6/6] include source in copyFrom --- src/main/java/com/rometools/modules/thr/ThreadingModuleImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/rometools/modules/thr/ThreadingModuleImpl.java b/src/main/java/com/rometools/modules/thr/ThreadingModuleImpl.java index 1bd634a..e0a44c3 100644 --- a/src/main/java/com/rometools/modules/thr/ThreadingModuleImpl.java +++ b/src/main/java/com/rometools/modules/thr/ThreadingModuleImpl.java @@ -35,6 +35,7 @@ public class ThreadingModuleImpl extends ModuleImpl implements ThreadingModule { setHref(module.getHref()); setRef(module.getRef()); setType(module.getType()); + setSource(module.getSource()); } }