Write empty sitemap and index files (#23)

* Allow SitemapGenerators to write an empty sitemap.

* Allow SitemapIndexGenerators to write an empty sitemap index.
This commit is contained in:
Joseph Beard 2016-08-03 11:04:52 -04:00 committed by dfabulich
parent 6e9832beaf
commit e10e166b39
5 changed files with 60 additions and 3 deletions

View File

@ -9,6 +9,7 @@ abstract class AbstractSitemapGeneratorOptions<THIS extends AbstractSitemapGener
File baseDir; File baseDir;
URL baseUrl; URL baseUrl;
String fileNamePrefix = "sitemap"; String fileNamePrefix = "sitemap";
boolean allowEmptySitemap = false;
boolean allowMultipleSitemaps = true; boolean allowMultipleSitemaps = true;
String suffixStringPattern; // this will store some type of string pattern suitable per needs. String suffixStringPattern; // this will store some type of string pattern suitable per needs.
W3CDateFormat dateFormat; W3CDateFormat dateFormat;
@ -38,6 +39,17 @@ abstract class AbstractSitemapGeneratorOptions<THIS extends AbstractSitemapGener
return getThis(); return getThis();
} }
/**
* Permit writing a sitemap that contains no URLs.
*
* @param allowEmpty {@code true} if an empty sitemap is permissible
* @return this instance, for chaining
*/
public THIS allowEmptySitemap(boolean allowEmpty) {
this.allowEmptySitemap = allowEmpty;
return getThis();
}
/** When more than the maximum number of URLs are passed in, should we split into multiple sitemaps automatically, or just throw an exception? */ /** When more than the maximum number of URLs are passed in, should we split into multiple sitemaps automatically, or just throw an exception? */
public THIS allowMultipleSitemaps(boolean allowMultipleSitemaps) { public THIS allowMultipleSitemaps(boolean allowMultipleSitemaps) {
this.allowMultipleSitemaps = allowMultipleSitemaps; this.allowMultipleSitemaps = allowMultipleSitemaps;

View File

@ -21,6 +21,7 @@ abstract class SitemapGenerator<U extends ISitemapUrl, THIS extends SitemapGener
private final File baseDir; private final File baseDir;
private final String fileNamePrefix; private final String fileNamePrefix;
private final String fileNameSuffix; private final String fileNameSuffix;
private final boolean allowEmptySitemap;
private final boolean allowMultipleSitemaps; private final boolean allowMultipleSitemaps;
private final ArrayList<U> urls = new ArrayList<U>(); private final ArrayList<U> urls = new ArrayList<U>();
private final W3CDateFormat dateFormat; private final W3CDateFormat dateFormat;
@ -40,6 +41,7 @@ abstract class SitemapGenerator<U extends ISitemapUrl, THIS extends SitemapGener
W3CDateFormat dateFormat = options.dateFormat; W3CDateFormat dateFormat = options.dateFormat;
if (dateFormat == null) dateFormat = new W3CDateFormat(); if (dateFormat == null) dateFormat = new W3CDateFormat();
this.dateFormat = dateFormat; this.dateFormat = dateFormat;
allowEmptySitemap = options.allowEmptySitemap;
allowMultipleSitemaps = options.allowMultipleSitemaps; allowMultipleSitemaps = options.allowMultipleSitemaps;
maxUrls = options.maxUrls; maxUrls = options.maxUrls;
autoValidate = options.autoValidate; autoValidate = options.autoValidate;
@ -165,7 +167,7 @@ abstract class SitemapGenerator<U extends ISitemapUrl, THIS extends SitemapGener
*/ */
public List<File> write() { public List<File> write() {
if (finished) throw new RuntimeException("Sitemap already printed; you must create a new generator to make more sitemaps"); if (finished) throw new RuntimeException("Sitemap already printed; you must create a new generator to make more sitemaps");
if (urls.size() == 0 && mapCount == 0) throw new RuntimeException("No URLs added, sitemap would be empty; you must add some URLs with addUrls"); if (!allowEmptySitemap && urls.isEmpty() && mapCount == 0) throw new RuntimeException("No URLs added, sitemap would be empty; you must add some URLs with addUrls");
writeSiteMap(); writeSiteMap();
finished = true; finished = true;
return outFiles; return outFiles;
@ -221,7 +223,7 @@ abstract class SitemapGenerator<U extends ISitemapUrl, THIS extends SitemapGener
if (baseDir == null) { if (baseDir == null) {
throw new NullPointerException("To write to files, baseDir must not be null"); throw new NullPointerException("To write to files, baseDir must not be null");
} }
if (urls.size() == 0) return; if (urls.isEmpty() && (mapCount > 0 || !allowEmptySitemap)) return;
String fileNamePrefix; String fileNamePrefix;
if (mapCount > 0) { if (mapCount > 0) {
fileNamePrefix = this.fileNamePrefix + mapCount; fileNamePrefix = this.fileNamePrefix + mapCount;

View File

@ -19,6 +19,7 @@ import org.xml.sax.SAXException;
public class SitemapIndexGenerator { public class SitemapIndexGenerator {
private final URL baseUrl; private final URL baseUrl;
private final File outFile; private final File outFile;
private final boolean allowEmptyIndex;
private final ArrayList<SitemapIndexUrl> urls = new ArrayList<SitemapIndexUrl>(); private final ArrayList<SitemapIndexUrl> urls = new ArrayList<SitemapIndexUrl>();
private final int maxUrls; private final int maxUrls;
private final W3CDateFormat dateFormat; private final W3CDateFormat dateFormat;
@ -32,6 +33,7 @@ public class SitemapIndexGenerator {
private URL baseUrl; private URL baseUrl;
private File outFile; private File outFile;
private W3CDateFormat dateFormat = null; private W3CDateFormat dateFormat = null;
private boolean allowEmptyIndex = false;
private int maxUrls = MAX_SITEMAPS_PER_INDEX; private int maxUrls = MAX_SITEMAPS_PER_INDEX;
private Date defaultLastMod = new Date(); private Date defaultLastMod = new Date();
private boolean autoValidate = false; private boolean autoValidate = false;
@ -59,6 +61,18 @@ public class SitemapIndexGenerator {
this.dateFormat = dateFormat; this.dateFormat = dateFormat;
return this; return this;
} }
/**
* Permit writing an index that contains no URLs.
*
* @param allowEmptyIndex {@code true} if an empty index is permissible
* @return this instance, for chaining
*/
public Options allowEmptyIndex(boolean allowEmptyIndex) {
this.allowEmptyIndex = allowEmptyIndex;
return this;
}
/** /**
* The maximum number of sitemaps to allow per sitemap index; the default is the * The maximum number of sitemaps to allow per sitemap index; the default is the
* maximum allowed (1,000), but you can decrease it if you wish (for testing) * maximum allowed (1,000), but you can decrease it if you wish (for testing)
@ -116,6 +130,7 @@ public class SitemapIndexGenerator {
private SitemapIndexGenerator(Options options) { private SitemapIndexGenerator(Options options) {
this.baseUrl = options.baseUrl; this.baseUrl = options.baseUrl;
this.outFile = options.outFile; this.outFile = options.outFile;
this.allowEmptyIndex = options.allowEmptyIndex;
this.maxUrls = options.maxUrls; this.maxUrls = options.maxUrls;
W3CDateFormat dateFormat = options.dateFormat; W3CDateFormat dateFormat = options.dateFormat;
if (dateFormat == null) dateFormat = new W3CDateFormat(); if (dateFormat == null) dateFormat = new W3CDateFormat();
@ -206,7 +221,7 @@ public class SitemapIndexGenerator {
/** Writes out the sitemap index */ /** Writes out the sitemap index */
public void write() { public void write() {
if (urls.size() == 0) throw new RuntimeException("No URLs added, sitemap index would be empty; you must add some URLs with addUrls"); if (!allowEmptyIndex && urls.isEmpty()) throw new RuntimeException("No URLs added, sitemap index would be empty; you must add some URLs with addUrls");
try { try {
// TODO gzip? is that legal for a sitemap index? // TODO gzip? is that legal for a sitemap index?
FileWriter out = new FileWriter(outFile); FileWriter out = new FileWriter(outFile);

View File

@ -347,6 +347,24 @@ public class SitemapGeneratorTest extends TestCase {
assertEquals("First string didn't match", SITEMAP1, siteMapsAsStrings.get(0)); assertEquals("First string didn't match", SITEMAP1, siteMapsAsStrings.get(0));
assertEquals("Second string didn't match", SITEMAP_PLUS_ONE, siteMapsAsStrings.get(1)); assertEquals("Second string didn't match", SITEMAP_PLUS_ONE, siteMapsAsStrings.get(1));
} }
public void testWriteEmptySitemap() throws Exception {
wsg = WebSitemapGenerator.builder("http://www.example.com", dir).allowEmptySitemap(true).build();
String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\" >\n" +
"</urlset>";
String sitemap = writeSingleSiteMap(wsg);
assertEquals(expected, sitemap);
}
public void testMaxUrlsAllowingEmptyDoesNotWriteExtraSitemap() throws Exception {
wsg = WebSitemapGenerator.builder("http://www.example.com", dir).allowEmptySitemap(true).maxUrls(10).build();
for (int i = 0; i < 10; i++) {
wsg.addUrl("http://www.example.com/"+i);
}
String sitemap = writeSingleSiteMap(wsg);
assertEquals(SITEMAP1, sitemap);
}
private String writeSingleSiteMap(WebSitemapGenerator wsg) { private String writeSingleSiteMap(WebSitemapGenerator wsg) {
List<File> files = wsg.write(); List<File> files = wsg.write();

View File

@ -86,6 +86,16 @@ public class SitemapIndexGeneratorTest extends TestCase {
fail("Allowed write with no URLs"); fail("Allowed write with no URLs");
} catch (RuntimeException e) {} } catch (RuntimeException e) {}
} }
public void testNoUrlsEmptyIndexAllowed() throws Exception {
sig = new SitemapIndexGenerator.Options(EXAMPLE, outFile).allowEmptyIndex(true).build();
sig.write();
String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n" +
"</sitemapindex>";
String actual = TestUtil.slurpFileAndDelete(outFile);
assertEquals(expected, actual);
}
public void testMaxUrls() throws Exception { public void testMaxUrls() throws Exception {
sig = new SitemapIndexGenerator.Options(EXAMPLE, outFile).autoValidate(true) sig = new SitemapIndexGenerator.Options(EXAMPLE, outFile).autoValidate(true)