Java tutorial
/* * 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. */ package org.trellisldp.rdfa; import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Arrays.stream; import static java.util.Objects.requireNonNull; import static java.util.Optional.of; import static java.util.Optional.ofNullable; import static java.util.ServiceLoader.load; import static java.util.stream.Collectors.toList; import static org.apache.tamaya.ConfigurationProvider.getConfiguration; import com.github.mustachejava.DefaultMustacheFactory; import com.github.mustachejava.Mustache; import com.github.mustachejava.MustacheFactory; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.UncheckedIOException; import java.io.Writer; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.ServiceLoader; import java.util.stream.Stream; import javax.inject.Inject; import org.apache.commons.rdf.api.Triple; import org.apache.tamaya.Configuration; import org.trellisldp.api.NamespaceService; import org.trellisldp.api.NoopNamespaceService; import org.trellisldp.api.RDFaWriterService; /** * An RDFa (HTML) serialization service. */ public class HtmlSerializer implements RDFaWriterService { private static final MustacheFactory mf = new DefaultMustacheFactory(); /** The configuration key controlling the HTML template to use. **/ public static final String CONFIG_RDFA_TEMPLATE = "trellis.rdfa.template"; /** The configuration key controlling the CSS URLs to use. **/ public static final String CONFIG_RDFA_CSS = "trellis.rdfa.css"; /** The configuration key controlling the web icon to use. **/ public static final String CONFIG_RDFA_ICON = "trellis.rdfa.icon"; /** The configuration key controlling the JS URLs to use. **/ public static final String CONFIG_RDFA_JS = "trellis.rdfa.js"; private final NamespaceService namespaceService; private final Mustache template; private final List<String> css; private final List<String> js; private final String icon; /** * Create an HTML Serializer object. */ @Inject public HtmlSerializer() { this(of(load(NamespaceService.class)).map(ServiceLoader::iterator).filter(Iterator::hasNext) .map(Iterator::next).orElseGet(NoopNamespaceService::new)); } /** * Create an HTML Serializer object. * * @param namespaceService a namespace service */ public HtmlSerializer(final NamespaceService namespaceService) { this(namespaceService, getConfiguration()); } private HtmlSerializer(final NamespaceService namespaceService, final Configuration config) { this(namespaceService, config.get(CONFIG_RDFA_TEMPLATE), config.getOrDefault(CONFIG_RDFA_CSS, "//www.trellisldp.org/assets/css/trellis.css"), config.getOrDefault(CONFIG_RDFA_JS, ""), config.getOrDefault(CONFIG_RDFA_ICON, "//www.trellisldp.org/assets/img/trellis.png")); } /** * Create an HTML Serializer object. * * @param namespaceService a namespace service * @param template the template location * @param css the css to use (comma-delimited for multiple css documents) * @param js the js to use (comma-delimited for multiple js documents) * @param icon an icon, may be {@code null} */ public HtmlSerializer(final NamespaceService namespaceService, final String template, final String css, final String js, final String icon) { this(namespaceService, template, intoList(css), intoList(js), icon); } /** * Create an HTML Serializer object. * * @param namespaceService a namespace service * @param template the template location * @param css the css to use (comma-delimited for multiple css documents) * @param js the js to use (comma-delimited for multiple js documents) * @param icon an icon, may be {@code null} */ public HtmlSerializer(final NamespaceService namespaceService, final String template, final List<String> css, final List<String> js, final String icon) { this.namespaceService = requireNonNull(namespaceService, "NamespaceService may not be null!"); final String templatePath = ofNullable(template).orElse("org/trellisldp/rdfa/resource.mustache"); final File tpl = new File(templatePath); this.template = tpl.exists() ? mf.compile(templatePath) : mf.compile(getReader(templatePath), templatePath); this.css = ofNullable(css).orElseGet(Collections::emptyList); this.js = ofNullable(js).orElseGet(Collections::emptyList); this.icon = icon; } private Reader getReader(final String template) { if (template.startsWith("/")) { return new InputStreamReader(getClass().getResourceAsStream(template), UTF_8); } return new InputStreamReader(getClass().getResourceAsStream("/" + template), UTF_8); } /** * Send the content to an output stream. * * @param triples the triples * @param out the output stream * @param subject the subject */ @Override public void write(final Stream<Triple> triples, final OutputStream out, final String subject) { final Writer writer = new OutputStreamWriter(out, UTF_8); try { template.execute(writer, new HtmlData(namespaceService, subject, triples.collect(toList()), css, js, icon)).flush(); } catch (final IOException ex) { throw new UncheckedIOException(ex); } } private static List<String> intoList(final String property) { return stream(property.split(",")).map(String::trim).filter(x -> !x.isEmpty()).collect(toList()); } }