Newer
Older
/*
* Copyright 2020 ETSI
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package fr.emse.gitlab.saref.managers;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import org.apache.commons.io.IOUtils;
import org.apache.jena.atlas.io.IndentedWriter;
import org.apache.jena.graph.NodeFactory;
import org.apache.jena.query.Dataset;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.sparql.core.Var;
import org.apache.jena.sparql.engine.binding.Binding;
import org.apache.jena.sparql.engine.binding.BindingHashMap;
import org.apache.jena.sparql.util.Context;
import org.eclipse.jgit.api.Git;
import org.slf4j.Logger;
import fr.emse.ci.sparqlext.SPARQLExt;
import fr.emse.ci.sparqlext.engine.PlanFactory;
import fr.emse.ci.sparqlext.engine.RootPlan;
import fr.emse.ci.sparqlext.stream.LookUpRequest;
import fr.emse.ci.sparqlext.stream.SPARQLExtStreamManager;
import fr.emse.ci.sparqlext.utils.ContextUtils;
import fr.emse.ci.sparqlext.utils.VarUtils;
import fr.emse.gitlab.saref.SAREF;
import fr.emse.gitlab.saref.SAREFErrorLogger;
import fr.emse.gitlab.saref.SAREFPipeline;
import fr.emse.gitlab.saref.SAREFPipeline.Mode;
import fr.emse.gitlab.saref.SAREFPipelineException;
import fr.emse.gitlab.saref.entities.SAREFExample;
import fr.emse.gitlab.saref.entities.SAREFProject;
import fr.emse.gitlab.saref.entities.SAREFRepository;
import fr.emse.gitlab.saref.entities.SAREFTerm;
import fr.emse.gitlab.saref.entities.SAREFVersion;
import fr.emse.gitlab.saref.utils.StreamManagerFactory;
public class SiteManager extends SAREFErrorLogger {
private static final String DOC_BASE = SAREF.BASE + "documentation/";
private static final String TERM_QUERY = DOC_BASE + "term/main.rqg";
private static final Var VAR_TERM = VarUtils.allocVar("term");
private static final String ONTO_QUERY = DOC_BASE + "ontology/main.rqg";
private static final Var VAR_VERSION_IRI = VarUtils.allocVar("versionIRI");
private static final String EXAMPLE_QUERY = DOC_BASE + "example/main.rqg";
private static final Var VAR_EXAMPLE = VarUtils.allocVar("example");
private static final String NAME_STATIC = "static";
private static final String NAME_REPORT_HTML = "report.html";
private static final String HTACCESS_HTML = "RewriteCond %{HTTP_ACCEPT} !(application/rdf\\+xml|text/turtle|text/n3|application/n\\-triples|application/ld\\+json)";
private static final String HTACCESS_RDFXML = "RewriteCond %{HTTP_ACCEPT} application/rdf\\+xml";
private static final String HTACCESS_TURTLE = "RewriteCond %{HTTP_ACCEPT} text/turtle";
private static final String HTACCESS_N3 = "RewriteCond %{HTTP_ACCEPT} text/n3";
private static final String HTACCESS_NTRIPLE = "RewriteCond %{HTTP_ACCEPT} application/n-triples";
private static final String HTACCESS_JSONLD = "RewriteCond %{HTTP_ACCEPT} application/ld\\+json";
private static final SPARQLExtStreamManager STREAM_MANAGER_BASE = StreamManagerFactory.get();
private final File reportFileHTML;
private final RootPlan planForTerm;
private final RootPlan planForOntologyVersion;
private final RootPlan planForExample;
private static enum MESSAGE {
prepare_error;
}
public SiteManager(SAREFPipeline pipeline, Logger errorLogger) throws IOException {
super(pipeline, errorLogger);
siteDir = new File(pipeline.targetDir, SAREF.NAME_SITE);
reportFileHTML = new File(siteDir, NAME_REPORT_HTML);
String query = IOUtils.toString(STREAM_MANAGER_BASE.open(new LookUpRequest(TERM_QUERY, SPARQLExt.MEDIA_TYPE)),
StandardCharsets.UTF_8);
planForTerm = PlanFactory.create(query, DOC_BASE);
query = IOUtils.toString(STREAM_MANAGER_BASE.open(new LookUpRequest(ONTO_QUERY, SPARQLExt.MEDIA_TYPE)),
StandardCharsets.UTF_8);
planForOntologyVersion = PlanFactory.create(query, DOC_BASE);
query = IOUtils.toString(STREAM_MANAGER_BASE.open(new LookUpRequest(EXAMPLE_QUERY, SPARQLExt.MEDIA_TYPE)),
planForExample = PlanFactory.create(query, DOC_BASE);
}
/**
* Prepare the site folder and clone the saref-portal-static project repository.
*/
public void prepareSite() throws SAREFPipelineException {
try (Git git = Git.cloneRepository().setURI(SAREF.SAREF_PORTAL_STATIC_GIT).setDirectory(siteDir).call()) {
} catch (Exception ex) {
try (Git git = Git.open(siteDir)) {
git.pull().call();
} catch (Exception e) {
String msg = getMessage(MESSAGE.prepare_error, SAREF.SAREF_PORTAL_STATIC_GIT);
logError(msg, e);
throw new SAREFPipelineException(msg, e);
}
}
}
public void writeReport(StringWriter sw) throws IOException {
try (IndentedWriter writer = new IndentedWriter(new FileOutputStream(reportFileHTML));) {
boolean debugTemplate = pipeline.mode == Mode.DEVELOP;
Context context = ContextUtils.build(writer).setBase(SAREF.BASE).setDebugTemplate(debugTemplate)
.setStreamManager(STREAM_MANAGER_BASE).build();
BindingHashMap binding = new BindingHashMap();
Var varTestSuites = VarUtils.allocVar("testsuites");
binding.add(varTestSuites, NodeFactory.createLiteral(sw.toString()));
List<Binding> bindings = new ArrayList<>();
bindings.add(binding);
String query = IOUtils.toString(
STREAM_MANAGER_BASE.open(new LookUpRequest("documentation/report/main.rqg", SPARQLExt.MEDIA_TYPE)),
StandardCharsets.UTF_8);
RootPlan reportPlan = PlanFactory.create(query, DOC_BASE);
reportPlan.execTemplateStream(bindings, context);
} catch (IOException ex) {
throw ex;
public void generateOntologyDocumentation(SAREFVersion version, IndentedWriter writer,
SPARQLExtStreamManager streamManager, Dataset dataset) {
Resource resource = version.getResource();
generateHTML(planForOntologyVersion, VAR_VERSION_IRI, resource, writer, streamManager, dataset);
public void generateExampleDocumentation(SAREFExample example, IndentedWriter writer,
SPARQLExtStreamManager streamManager, Dataset dataset) {
Resource resource = example.getResource();
generateHTML(planForExample, VAR_EXAMPLE, resource, writer, streamManager, dataset);
}
public void generateTermDocumentation(SAREFTerm term, IndentedWriter writer, Dataset dataset) {
Resource resource = term.getResource();
generateHTML(planForTerm, VAR_TERM, resource, writer, STREAM_MANAGER_BASE, dataset);
}
private void generateHTML(RootPlan plan, Var var, Resource resource, IndentedWriter writer,
SPARQLExtStreamManager streamManager, Dataset dataset) {
Context context = ContextUtils.build(writer).setBase(SAREF.BASE).setDebugTemplate(pipeline.mode == Mode.DEVELOP)
.setInputDataset(dataset).setStreamManager(streamManager).build();
BindingHashMap binding = new BindingHashMap();
binding.add(var, resource.asNode());
List<Binding> bindings = new ArrayList<>();
bindings.add(binding);
plan.execTemplateStream(bindings, context);
}
public static SPARQLExtStreamManager getStreamManagerBase() {
return STREAM_MANAGER_BASE;
}
public void generateHtaccess() {
File htaccess = new File(siteDir, ".htaccess");
try (FileWriter writer = new FileWriter(htaccess)) {
writer.write("RewriteEngine on\nDirectorySlash Off\n\n");
writer.write("nRewriteRule ^sources/(.*)$ https://forge.etsi.org/rep/SAREF/$1 [R=302,NE]\\n"); // redirect the sources
writer.write(HTACCESS_HTML);
writer.write("\nRewriteRule ^(.*)\\.conneg$ /$1.html\n");
writer.write(HTACCESS_JSONLD);
writer.write("\nRewriteRule ^(.*)\\.conneg$ /$1.jsonld\n");
writer.write(HTACCESS_N3);
writer.write("\nRewriteRule ^(.*)\\.conneg$ /$1.n3\n");
writer.write(HTACCESS_NTRIPLE);
writer.write("\nRewriteRule ^(.*)\\.conneg$ /$1.nt\n");
writer.write(HTACCESS_RDFXML);
writer.write("\nRewriteRule ^(.*)\\.conneg$ /$1.rdf\n");
writer.write(HTACCESS_TURTLE);
writer.write("\nRewriteRule ^(.*)\\.conneg$ /$1.ttl\n");
writer.write("\n");
for (RepositoryManager repositoryManager : pipeline.getSourcesManager().getSourceRepositoryManagers()) {
SAREFRepository repository = repositoryManager.getRepository();
SAREFProject project = repository.getProject();
SAREFVersion lastVersion = repository.getVersions().lastEntry().getValue();
// redirects core to core/v3.1.1/
// redirects core/ to core/v3.1.1/
writer.write(String.format("RewriteRule ^%s/?$ /%s/ [R=302,NE]\n", project.getPath(), lastVersion.getVersionPath()));
// redirects core/Sensor to core/Sensor.conneg
String choiceOfTerms = repository.getTerms().values().stream().map(SAREFTerm::getLocalName)
.collect(Collectors.joining("|", "(", ")"));
writer.write(String.format("RewriteCond %%{REQUEST_URI} ^/%s/%s$\n", project.getPath(), choiceOfTerms));
writer.write(String.format("RewriteRule ^%s/(.*)$ /%s/$1.conneg\n\n", project.getPath(), project.getPath()));
// redirects core.ttl to core/v1.1.1.ttl
writer.write(String.format("RewriteRule ^%s\\.([^\\./]+)$ /%s.$1 [R=302,NE]\n\n",
project.getPath(), lastVersion.getVersionPath()));
for (SAREFVersion version : repository.getVersions().values()) {
writer.write(String.format("RewriteRule ^%s/?$ /%s/%s.conneg\n",
version.getVersionPath(), version.getVersionPath(), project.getOntologyFileName()));
// redirects core/v1.1.1.ttl to core/v1.1.1/saref.ttl
writer.write(String.format("RewriteRule ^%s\\.([^\\./]+)$ /%s/%s.$1 [R=302,NE]\n",
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
version.getVersionPath(), version.getVersionPath(), project.getOntologyFileName()));
// redirects core/v1.1.1/saref to core/v1.1.1/saref.conneg
writer.write(String.format("RewriteRule ^%s/%s$ /%s/%s.conneg\n",
version.getVersionPath(), project.getOntologyFileName(), version.getVersionPath(),
project.getOntologyFileName()));
// redirects core/v1.1.1/tests to core/v1.1.1/tests.conneg
writer.write(String.format("RewriteRule ^%s/tests$ /%s/tests.conneg\n",
version.getVersionPath(), version.getVersionPath()));
// redirects core/v1.1.1/requirements to core/v1.1.1/requirements.conneg
writer.write(String.format("RewriteRule ^%s/requirements$ /%s/requirements.conneg\n",
version.getVersionPath(), version.getVersionPath()));
for (SAREFExample example : version.getExamples().values()) {
writer.write(String.format("RewriteRule ^%s/example/%s$ /%s/example/%s.conneg\n",
version.getVersionPath(), example.getName(), version.getVersionPath(),
example.getName()));
}
writer.write("\n\n");
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}