diff --git a/pom.xml b/pom.xml index e58c56b..b8d6cc4 100644 --- a/pom.xml +++ b/pom.xml @@ -76,6 +76,10 @@ junit test + + org.hamcrest + hamcrest-library + xmlunit xmlunit diff --git a/src/main/java/com/rometools/opml/io/impl/OPML20Generator.java b/src/main/java/com/rometools/opml/io/impl/OPML20Generator.java index dfc4137..a774291 100644 --- a/src/main/java/com/rometools/opml/io/impl/OPML20Generator.java +++ b/src/main/java/com/rometools/opml/io/impl/OPML20Generator.java @@ -1,5 +1,7 @@ package com.rometools.opml.io.impl; +import java.util.Collection; +import java.util.List; import java.util.Locale; import org.jdom2.Document; @@ -12,7 +14,9 @@ import com.rometools.rome.io.FeedException; import com.rometools.rome.io.impl.DateParser; /** - * @author cooper + * Generator for OPML 2.0 documents. + * + * @see http://dev.opml.org/spec2.html */ public class OPML20Generator extends OPML10Generator { @@ -41,34 +45,54 @@ public class OPML20Generator extends OPML10Generator { */ @Override public Document generate(final WireFeed feed) throws IllegalArgumentException, FeedException { - final Document retValue = super.generate(feed); - retValue.getRootElement().setAttribute("version", "2.0"); - return retValue; + final Document document = super.generate(feed); + document.getRootElement().setAttribute("version", "2.0"); + return document; } @Override protected Element generateHead(final Opml opml) { - final Element docs = new Element("docs"); - docs.setText(opml.getDocs()); + final Element docsElement = new Element("docs"); + docsElement.setText(opml.getDocs()); - final Element retValue = super.generateHead(opml); - retValue.addContent(docs); - return retValue; + final Element headElement = super.generateHead(opml); + headElement.addContent(docsElement); + return headElement; } @Override protected Element generateOutline(final Outline outline) { - final Element retValue = super.generateOutline(outline); + final Element outlineElement = super.generateOutline(outline); if (outline.getCreated() != null) { - retValue.setAttribute("created", DateParser.formatRFC822(outline.getCreated(), Locale.US)); + outlineElement.setAttribute("created", DateParser.formatRFC822(outline.getCreated(), Locale.US)); } - return retValue; + final List categories = outline.getCategories(); + final String categoriesValue = generateCategoriesValue(categories); + addNotNullAttribute(outlineElement, "category", categoriesValue); + + return outlineElement; } + private String generateCategoriesValue(final Collection categories) { + final StringBuilder builder = new StringBuilder(); + for (final String category : categories) { + if (category != null && !category.trim().isEmpty()) { + builder.append("/"); + builder.append(category.trim()); + } + } + final String categoryString = builder.toString(); + if (categoryString == null || categoryString.trim().isEmpty()) { + return null; + } else { + return categoryString; + } + } + } diff --git a/src/test/java/com/rometools/opml/io/impl/OPML20GeneratorTest.java b/src/test/java/com/rometools/opml/io/impl/OPML20GeneratorTest.java new file mode 100644 index 0000000..d4359b8 --- /dev/null +++ b/src/test/java/com/rometools/opml/io/impl/OPML20GeneratorTest.java @@ -0,0 +1,52 @@ +package com.rometools.opml.io.impl; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import org.custommonkey.xmlunit.XMLUnit; +import org.custommonkey.xmlunit.exceptions.XpathException; +import org.junit.Test; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import com.rometools.opml.feed.opml.Opml; +import com.rometools.opml.feed.opml.Outline; +import com.rometools.rome.io.FeedException; +import com.rometools.rome.io.WireFeedOutput; + +public class OPML20GeneratorTest { + + @Test + public void testCategoryOutput() throws IllegalArgumentException, FeedException, SAXException, IOException, XpathException { + checkCategoryOutput(null, ""); + checkCategoryOutput(Arrays.asList("category1"), "/category1"); + checkCategoryOutput(Arrays.asList("category1", "category2"), "/category1/category2"); + } + + private void checkCategoryOutput(final List categories, final String asserted) + throws IllegalArgumentException, FeedException, SAXException, IOException, XpathException { + + final Outline outline = new Outline("outline1", null); + outline.setCategories(categories); + final List outlines = Arrays.asList(outline); + + final Opml opml = new Opml(); + opml.setFeedType("opml_2.0"); + opml.setTitle("title"); + opml.setOutlines(outlines); + + final WireFeedOutput output = new WireFeedOutput(); + final String xml = output.outputString(opml); + + final Document document = XMLUnit.buildControlDocument(xml); + final String categoryValue = XMLUnit.newXpathEngine().evaluate("/opml/body/outline/@category", document); + assertThat(categoryValue, is(equalTo(asserted))); + + } + +}