SitemapService.java
/*
* Copyright © 2024-2025 The CTAN Team and individual authors
*
* This file is distributed under the 3-clause BSD license.
* See file LICENSE for details.
*/
package org.ctan.site.services;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.ctan.site.resources.catalogue.api.XmlWriter;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.databind.ObjectMapper;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
/**
* The class <code>Sitemap3Resource</code> contains the controller for the
* version resource.
*
* @author <a href="mailto:gene@ctan.org">Gerd Neugebauer</a>
*/
@Slf4j
public class SitemapService {
/**
* The class <code>SitemapBanner</code> contains the transport object to
* encode a sitemap banner.
*/
@Getter
@JsonInclude(Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
static class SitemapBanner {
private String by;
private String height;
private String position;
private String source;
private String src;
}
/**
* The class <code>SitemapList</code> contains the transport object to
* encode a list of sitemap pages.
*/
@Getter
@JsonInclude(Include.NON_NULL)
public static class SitemapList extends ArrayList<SitemapPage> {
/**
* The field <code>serialVersionUID</code> contains the id for
* serialisation.
*/
private static final long serialVersionUID = 1L;
}
/**
* The class <code>SitemapPage</code> contains the transport object to
* encode a sitemap page.
*/
@Getter
@JsonInclude(Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
@SuppressFBWarnings(value = "EI_EXPOSE_REP")
public static class SitemapPage {
private String arg;
private SitemapBanner banner;
private List<SitemapPage> children;
private String clip;
private String cond;
private Boolean hide;
private String icon;
private String id;
private String title;
private String to;
}
/**
* The field <code>MAPPER</code> contains the object mapper.
*/
static final ObjectMapper MAPPER =
new ObjectMapper().enable(Feature.ALLOW_COMMENTS);
/**
* The method <code>asJson</code> provides means to create a sitemap as
* object tree.
*
* @return the sitemap
*/
public SitemapList asJson() {
try (var is = SitemapService.class.getClassLoader()
.getResourceAsStream("data/sitemap.json")) {
return MAPPER.readValue(is, SitemapList.class);
} catch (IOException e) {
log.error("parsing data/sitemap.json failed", e);
return null;
}
}
/**
* The method <code>asXml</code> provides means to create a sitemap as
* XML-formatted String.
*
* @return the XML
*/
public String asXml() {
var sitemap = new XmlWriter();
sitemap.out("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
sitemap.out(
"<urlset xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
+ " xsi:schemaLocation=\"http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd\"\n"
+ " xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">");
asXml(sitemap, " ", asJson());
sitemap.out("</urlset>");
return sitemap.toString();
}
/**
* The method <code>asXml</code> provides means to create a sitemap as
* XML-formatted String.
*
* @param sitemap the site map
* @param prefix the whitespace for indentation
* @param list the list of pages
*/
private void asXml(XmlWriter sitemap, String prefix,
List<SitemapPage> list) {
if (list == null) {
return;
}
var prefix2 = prefix + " ";
for (var it : list) {
sitemap.out(prefix, "<url>\n",
prefix, " <loc>https://ctan.org", it.getTo(), "</loc>\n",
prefix, "</url>\n");
asXml(sitemap, prefix2, it.getChildren());
}
}
}