added new generator for google link extension
This commit is contained in:
parent
deb1862436
commit
0eccebb6c2
55
pom.xml
55
pom.xml
|
@ -1,12 +1,12 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.github.dfabulich</groupId>
|
||||
<groupId>com.github.sergiovm</groupId>
|
||||
<artifactId>sitemapgen4j</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>1.0.7-SNAPSHOT</version>
|
||||
<name>SitemapGen4J</name>
|
||||
<url>https://github.com/dfabulich/sitemapgen4j/</url>
|
||||
<url>https://github.com/sergiovm/sitemapgen4j</url>
|
||||
<description>SitemapGen4j is an XML sitemap generator written in Java.</description>
|
||||
<licenses>
|
||||
<license>
|
||||
|
@ -16,33 +16,13 @@
|
|||
</license>
|
||||
</licenses>
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com:dfabulich/sitemapgen4j.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:dfabulich/sitemapgen4j.git</developerConnection>
|
||||
<url>https://github.com/dfabulich/sitemapgen4j/</url>
|
||||
<connection>scm:git:git://github.com:sergiovm/sitemapgen4j.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:sergiovm/sitemapgen4j.git</developerConnection>
|
||||
<url>https://github.com/sergiovm/sitemapgen4j/</url>
|
||||
</scm>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>dfabulich</id>
|
||||
<name>Dan Fabulich</name>
|
||||
<email>dan@fabulich.com</email>
|
||||
<organization>Redfin</organization>
|
||||
<organizationUrl>http://www.redfin.com/</organizationUrl>
|
||||
<timezone>-8</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
<distributionManagement>
|
||||
<snapshotRepository>
|
||||
<id>ossrh</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
</snapshotRepository>
|
||||
<repository>
|
||||
<id>ossrh</id>
|
||||
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
<build>
|
||||
<defaultGoal>install</defaultGoal>
|
||||
<plugins>
|
||||
|
@ -88,31 +68,6 @@
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>1.5</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.sonatype.plugins</groupId>
|
||||
<artifactId>nexus-staging-maven-plugin</artifactId>
|
||||
<version>1.6.3</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<serverId>ossrh</serverId>
|
||||
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
|
||||
<autoReleaseAfterClose>false</autoReleaseAfterClose>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
package com.redfin.sitemapgenerator;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.*;
|
||||
import java.util.Locale;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* Builds a Google Link Sitemap (to indicate alternate language pages).
|
||||
*
|
||||
* @author Sergio Vico
|
||||
* @see <a href="https://support.google.com/webmasters/answer/2620865">Creating alternate language pages Sitemaps</a>
|
||||
*/
|
||||
public class GoogleLinkSitemapGenerator extends SitemapGenerator<GoogleLinkSitemapUrl, GoogleLinkSitemapGenerator> {
|
||||
|
||||
private static class Renderer extends AbstractSitemapUrlRenderer<GoogleLinkSitemapUrl>
|
||||
implements ISitemapUrlRenderer<GoogleLinkSitemapUrl> {
|
||||
|
||||
public Class<GoogleLinkSitemapUrl> getUrlClass() {
|
||||
|
||||
return GoogleLinkSitemapUrl.class;
|
||||
}
|
||||
|
||||
public String getXmlNamespaces() {
|
||||
|
||||
return "xmlns:xhtml=\"http://www.w3.org/1999/xhtml\"";
|
||||
}
|
||||
|
||||
public void render(final GoogleLinkSitemapUrl url, final StringBuilder sb, final W3CDateFormat dateFormat) {
|
||||
|
||||
final StringBuilder tagSb = new StringBuilder();
|
||||
for (final Entry<Locale, URL> entry : url.getAlternates().entrySet()) {
|
||||
tagSb.append(" <xhtml:link\n");
|
||||
tagSb.append(" rel=\"alternate\"\n");
|
||||
tagSb.append(" hreflang=\"" + entry.getKey().toLanguageTag() + "\"\n");
|
||||
tagSb.append(" href=\"" + UrlUtils.escapeXml(entry.getValue().toString()) + "\"\n");
|
||||
tagSb.append(" />\n");
|
||||
}
|
||||
super.render(url, sb, dateFormat, tagSb.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a builder so you can specify sitemap generator options
|
||||
*
|
||||
* @param baseUrl
|
||||
* All URLs in the generated sitemap(s) should appear under this base URL
|
||||
* @param baseDir
|
||||
* Sitemap files will be generated in this directory as either "sitemap.xml" or
|
||||
* "sitemap1.xml" "sitemap2.xml" and so on.
|
||||
* @return a builder; call .build() on it to make a sitemap generator
|
||||
*/
|
||||
public static SitemapGeneratorBuilder<GoogleLinkSitemapGenerator> builder(final String baseUrl, final File baseDir)
|
||||
throws MalformedURLException {
|
||||
|
||||
return new SitemapGeneratorBuilder<GoogleLinkSitemapGenerator>(baseUrl, baseDir,
|
||||
GoogleLinkSitemapGenerator.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a builder so you can specify sitemap generator options
|
||||
*
|
||||
* @param baseUrl
|
||||
* All URLs in the generated sitemap(s) should appear under this base URL
|
||||
* @param baseDir
|
||||
* Sitemap files will be generated in this directory as either "sitemap.xml" or
|
||||
* "sitemap1.xml" "sitemap2.xml" and so on.
|
||||
* @return a builder; call .build() on it to make a sitemap generator
|
||||
*/
|
||||
public static SitemapGeneratorBuilder<GoogleLinkSitemapGenerator> builder(final URL baseUrl, final File baseDir) {
|
||||
|
||||
return new SitemapGeneratorBuilder<GoogleLinkSitemapGenerator>(baseUrl, baseDir,
|
||||
GoogleLinkSitemapGenerator.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the generator with a base URL and a null directory. The object constructed is not
|
||||
* intended to be used to write to files. Rather, it is intended to be used to obtain
|
||||
* XML-formatted strings that represent sitemaps.
|
||||
*
|
||||
* @param baseUrl
|
||||
* All URLs in the generated sitemap(s) should appear under this base URL
|
||||
*/
|
||||
public GoogleLinkSitemapGenerator(final String baseUrl) throws MalformedURLException {
|
||||
this(new SitemapGeneratorOptions(new URL(baseUrl)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the generator with a base URL and directory to write the sitemap files.
|
||||
*
|
||||
* @param baseUrl
|
||||
* All URLs in the generated sitemap(s) should appear under this base URL
|
||||
* @param baseDir
|
||||
* Sitemap files will be generated in this directory as either "sitemap.xml" or
|
||||
* "sitemap1.xml" "sitemap2.xml" and so on.
|
||||
* @throws MalformedURLException
|
||||
*/
|
||||
public GoogleLinkSitemapGenerator(final String baseUrl, final File baseDir) throws MalformedURLException {
|
||||
this(new SitemapGeneratorOptions(baseUrl, baseDir));
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the generator with a base URL and a null directory. The object constructed is not
|
||||
* intended to be used to write to files. Rather, it is intended to be used to obtain
|
||||
* XML-formatted strings that represent sitemaps.
|
||||
*
|
||||
* @param baseUrl
|
||||
* All URLs in the generated sitemap(s) should appear under this base URL
|
||||
*/
|
||||
public GoogleLinkSitemapGenerator(final URL baseUrl) {
|
||||
this(new SitemapGeneratorOptions(baseUrl));
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the generator with a base URL and directory to write the sitemap files.
|
||||
*
|
||||
* @param baseUrl
|
||||
* All URLs in the generated sitemap(s) should appear under this base URL
|
||||
* @param baseDir
|
||||
* Sitemap files will be generated in this directory as either "sitemap.xml" or
|
||||
* "sitemap1.xml" "sitemap2.xml" and so on.
|
||||
*/
|
||||
public GoogleLinkSitemapGenerator(final URL baseUrl, final File baseDir) {
|
||||
this(new SitemapGeneratorOptions(baseUrl, baseDir));
|
||||
}
|
||||
|
||||
GoogleLinkSitemapGenerator(final AbstractSitemapGeneratorOptions<?> options) {
|
||||
super(options, new Renderer());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package com.redfin.sitemapgenerator;
|
||||
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* One configurable Google Link URL. To configure, use {@link Options}
|
||||
*
|
||||
* @author Sergio Vico
|
||||
* @see Options
|
||||
* @see <a href="https://support.google.com/webmasters/answer/2620865">Creating alternate language pages Sitemaps</a>
|
||||
*/
|
||||
public class GoogleLinkSitemapUrl extends WebSitemapUrl {
|
||||
|
||||
/** Options to configure mobile URLs */
|
||||
public static class Options extends AbstractSitemapUrlOptions<GoogleLinkSitemapUrl, Options> {
|
||||
private final Map<Locale, URL> alternates;
|
||||
|
||||
private static Map<Locale, URL> convertAlternates(final Map<String, String> alternates)
|
||||
throws MalformedURLException {
|
||||
|
||||
final Map<Locale, URL> converted = new LinkedHashMap<Locale, URL>(alternates.size());
|
||||
for (final Entry<String, String> entry : alternates.entrySet()) {
|
||||
converted.put(Locale.forLanguageTag(entry.getKey()), new URL(entry.getValue()));
|
||||
}
|
||||
return converted;
|
||||
}
|
||||
|
||||
/** Specifies the url */
|
||||
public Options(final String url, final Map<String, String> alternates) throws MalformedURLException {
|
||||
|
||||
this(new URL(url), convertAlternates(alternates));
|
||||
}
|
||||
|
||||
/** Specifies the url */
|
||||
public Options(final URL url, final Map<Locale, URL> alternates) {
|
||||
super(url, GoogleLinkSitemapUrl.class);
|
||||
this.alternates = new LinkedHashMap<Locale, URL>(alternates);
|
||||
}
|
||||
}
|
||||
|
||||
private final Map<Locale, URL> alternates;
|
||||
|
||||
/** Specifies configures url with options */
|
||||
public GoogleLinkSitemapUrl(final Options options) {
|
||||
super(options);
|
||||
alternates = options.alternates;
|
||||
}
|
||||
|
||||
/** Specifies the url */
|
||||
public GoogleLinkSitemapUrl(final String url, final Map<String, String> alternates) throws MalformedURLException {
|
||||
this(new Options(url, alternates));
|
||||
}
|
||||
|
||||
/** Specifies the url */
|
||||
public GoogleLinkSitemapUrl(final URL url, final Map<Locale, URL> alternates) {
|
||||
this(new Options(url, alternates));
|
||||
}
|
||||
|
||||
public Map<Locale, URL> getAlternates() {
|
||||
|
||||
return this.alternates;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package com.redfin.sitemapgenerator;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class GoogleLinkSitemapUrlTest extends TestCase {
|
||||
|
||||
File dir;
|
||||
GoogleLinkSitemapGenerator wsg;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
|
||||
dir = File.createTempFile(GoogleLinkSitemapUrlTest.class.getSimpleName(), "");
|
||||
dir.delete();
|
||||
dir.mkdir();
|
||||
dir.deleteOnExit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() {
|
||||
|
||||
wsg = null;
|
||||
for (final File file : dir.listFiles()) {
|
||||
file.deleteOnExit();
|
||||
file.delete();
|
||||
}
|
||||
dir.delete();
|
||||
dir = null;
|
||||
}
|
||||
|
||||
public void testSimpleUrl() throws Exception {
|
||||
|
||||
wsg = new GoogleLinkSitemapGenerator("http://www.example.com", dir);
|
||||
final Map<String, String> alternates = new LinkedHashMap<String, String>();
|
||||
alternates.put("en-GB", "http://www.example/en/index.html");
|
||||
alternates.put("fr-FR", "http://www.example/fr/index.html");
|
||||
alternates.put("es-ES", "http://www.example/es/index.html");
|
||||
|
||||
final GoogleLinkSitemapUrl url = new GoogleLinkSitemapUrl("http://www.example.com/index.html", alternates);
|
||||
wsg.addUrl(url);
|
||||
//@formatter:off
|
||||
final String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
+ "<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\" "
|
||||
+ "xmlns:xhtml=\"http://www.w3.org/1999/xhtml\" >\n"
|
||||
+ " <url>\n"
|
||||
+ " <loc>http://www.example.com/index.html</loc>\n"
|
||||
+ " <xhtml:link\n"
|
||||
+ " rel=\"alternate\"\n"
|
||||
+ " hreflang=\"en-GB\"\n"
|
||||
+ " href=\"http://www.example/en/index.html\"\n"
|
||||
+ " />\n"
|
||||
+ " <xhtml:link\n"
|
||||
+ " rel=\"alternate\"\n"
|
||||
+ " hreflang=\"fr-FR\"\n"
|
||||
+ " href=\"http://www.example/fr/index.html\"\n"
|
||||
+ " />\n"
|
||||
+ " <xhtml:link\n"
|
||||
+ " rel=\"alternate\"\n"
|
||||
+ " hreflang=\"es-ES\"\n"
|
||||
+ " href=\"http://www.example/es/index.html\"\n"
|
||||
+ " />\n"
|
||||
+ " </url>\n"
|
||||
+ "</urlset>";
|
||||
//@formatter:on
|
||||
final String sitemap = writeSingleSiteMap(wsg);
|
||||
assertEquals(expected, sitemap);
|
||||
}
|
||||
|
||||
private String writeSingleSiteMap(final GoogleLinkSitemapGenerator wsg) {
|
||||
|
||||
final List<File> files = wsg.write();
|
||||
assertEquals("Too many files: " + files.toString(), 1, files.size());
|
||||
assertEquals("Sitemap misnamed", "sitemap.xml", files.get(0).getName());
|
||||
return TestUtil.slurpFileAndDelete(files.get(0));
|
||||
}
|
||||
}
|
|
@ -315,6 +315,7 @@ public class SitemapGeneratorTest extends TestCase {
|
|||
while ((c = reader.read()) != -1) {
|
||||
sb.append((char)c);
|
||||
}
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ public class TestUtil {
|
|||
while ((c = reader.read()) != -1) {
|
||||
sb.append((char)c);
|
||||
}
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue