content: package org.aksw.rdfunit.examples;
  
  import com.google.common.collect.ImmutableList;
  import java.io.BufferedWriter;
  import java.io.File;
  import java.io.FileOutputStream;
  import java.io.OutputStreamWriter;
  import java.io.Writer;
  import java.nio.charset.StandardCharsets;
  import java.text.SimpleDateFormat;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Date;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.stream.Collectors;
  import org.aksw.rdfunit.enums.TestCaseExecutionType;
  import org.aksw.rdfunit.io.reader.RdfDereferenceReader;
  import org.aksw.rdfunit.io.reader.RdfMultipleReader;
  import org.aksw.rdfunit.io.reader.RdfReader;
  import org.aksw.rdfunit.io.reader.RdfReaderException;
  import org.aksw.rdfunit.io.reader.RdfReaderFactory;
  import org.aksw.rdfunit.model.interfaces.GenericTestCase;
  import org.aksw.rdfunit.model.interfaces.TestSuite;
  import org.aksw.rdfunit.model.interfaces.results.TestExecution;
  import org.aksw.rdfunit.model.writers.results.TestExecutionWriter;
  import org.aksw.rdfunit.services.PrefixNSService;
  import org.aksw.rdfunit.sources.TestSource;
  import org.aksw.rdfunit.sources.TestSourceFactory;
  import org.aksw.rdfunit.utils.TestUtils;
  import org.aksw.rdfunit.validate.wrappers.RDFUnitStaticValidator;
  import org.apache.jena.query.QueryExecution;
  import org.apache.jena.query.QueryExecutionFactory;
  import org.apache.jena.rdf.model.Model;
  import org.apache.jena.rdf.model.ModelFactory;
  
  /**
   * Does validation of the DBpedia mappings
   *
   * @author Dimitris Kontokostas
   * @since 6/30/15 4:15 PM
   */
  public class DBpediaMappingValidator {
  
    //private static final String MAPPING_SERVER = "http://mappings.dbpedia.org"; // "http://localhost:9999";
    private static final String MAPPING_SERVER = "http://localhost:9999";
  
    private static final String DBPEDIA_ONTOLOGY = MAPPING_SERVER + "/server/ontology/dbpedia.owl";
    private static final String RML_MANUAL_TESTS = "/org/aksw/rdfunit/tests/Manual/www.w3.org/ns/r2rml/rr.tests.Manual.ttl";
    private static final Collection<String> languages = //Arrays.asList("ar", "az", "be", "bg", "bn", "ca", "commons", "cs", "cy", "de", "el", "en", "eo", "es", "et", "eu", "fr", "ga", "hi", "hr", "hu", "hy", "id", "it", "ja", "ko", "nl", "pl", "pt", "ro", "ru", "sk", "sl", "sr", "sv", "tr", "uk", "ur", "zh");
        // 2014 languages
        // Arrays.asList("ar", "be", "bg", "bn", "ca", "commons", "cs", "cy", "de", "el", "en", "eo", "es", "et", "eu", "fr", "ga", "hi", "hr", "hu", "id", "it", "ja", "ko", "nl", "pl", "pt", "ru", "sk", "sl", "sr", "tr", "ur", "zh");
        ImmutableList.of("en");
  
    private static final String SPARQL_QUERY = PrefixNSService.getSparqlPrefixDecl() +
        " select ?error ?missing ?predicate ?mapping\n" +
        " where {\n" +
        "  ?v a sh:ValidationResult ;\n" +
        "     rut:testCase rutt:rr-predicateObjectMap-wrong-domain ;\n" +
        "     rdf:predicate ?predicate ;\n" +
        "     sh:expectedObject ?missing ;\n" +
        "     sh:value ?error ;\n" +
        "     rlog:resource ?mapping .\n" +
        " } ORDER BY ?mapping ";
  
  
    private static String getRMLlink(String lang) {
      return MAPPING_SERVER + "/server/mappings/" + lang + "/pages/rdf/all";
    }
  
    private static TestSuite getDBpMappingsTestSuite() throws RdfReaderException {
      Collection<GenericTestCase> tests = TestUtils.instantiateTestsFromModel(
          RdfReaderFactory.createResourceReader(RML_MANUAL_TESTS).read());
  
      return new TestSuite(tests);
    }
  
    public static void main(String[] args) throws Exception {
  
      if (args.length > 1) {
        throw new IllegalArgumentException("Expected at most one argument - the folder");
      }
  
      // get folder name
      String folder = "./";
      if (args.length == 1) {
        folder = args[0];
        if (!folder.endsWith("/")) {
          folder = folder + "/";
        }
      }
  
      String timeStamp = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date());
      final String filenameDefault = folder + "errors.json";
      final String filenameArchive = folder + "/archive/errors." + timeStamp + ".json";
      // create folder if it does not exists
      File archivedFolder = new File(folder + "/archive/");
      boolean dirsCreated = archivedFolder.mkdirs();
      if (!dirsCreated) {
        System.err.println("could not create archive folder");
      }
  
      final String json = new DBpediaMappingValidator().validateAndGetJson();
  
      //write json to filenameDefault
      try (Writer outDeafault = new BufferedWriter(new OutputStreamWriter(
          new FileOutputStream(filenameDefault), StandardCharsets.UTF_8));
          Writer outArchive = new BufferedWriter(new OutputStreamWriter(
              new FileOutputStream(filenameArchive), StandardCharsets.UTF_8))
      ) {
        outDeafault.write(json);
        outArchive.write(json);
      }
  
    }
  
    private RdfReader getRMLReader() {
      Collection<RdfReader> allReaders = new ArrayList<>();
      // we add the ontology
      allReaders.add(new RdfDereferenceReader(DBPEDIA_ONTOLOGY));
      // add all the mapping languages
      allReaders.addAll(
          languages.stream()
              .map(lang -> new RdfDereferenceReader(getRMLlink(lang)))
              .collect(Collectors.toList()));
      return new RdfMultipleReader(allReaders);
    }
  
    private TestSource getMappingSource() {
      return TestSourceFactory
          .createDumpTestSource("dbp-mappings", "http://mappings.dbpedia.org", getRMLReader(),
              new ArrayList<>());
  
    }
  
    public TestExecution validateAllMappings() throws RdfReaderException {
      return RDFUnitStaticValidator
          .validate(TestCaseExecutionType.shaclTestCaseResult, getMappingSource(),
              getDBpMappingsTestSuite());
    }
  
    public List<MappingDomainError> getErrorListFromModel(Model model) {
      List<MappingDomainError> mappingDomainErrors = new ArrayList<>();
      try (QueryExecution qe = QueryExecutionFactory.create(SPARQL_QUERY, model)) {
  
        qe.execSelect().forEachRemaining(qs -> {
  
          String mapping = qs.get("mapping").toString();
          String error = qs.get("error").toString();
          String missing = qs.get("missing").toString();
          String predicate = qs.get("predicate").toString();
  
          mappingDomainErrors.add(new MappingDomainError(mapping, predicate, error, missing));
  
        });
      }
      return mappingDomainErrors;
    }
  
    public Map<String, List<MappingDomainError>> getErrorsAsMap(
        Collection<MappingDomainError> mappingDomainErrors) {
      Map<String, List<MappingDomainError>> errorsAsMap = new HashMap<>();
      for (MappingDomainError error : mappingDomainErrors) {
        List<MappingDomainError> langErrors = errorsAsMap
            .computeIfAbsent(error.language, k -> new ArrayList<>());
        langErrors.add(error);
  
      }
  
      return errorsAsMap;
    }
  
    public String convertToJson(Map<String, List<MappingDomainError>> errorLangMap) {
      StringBuilder builder = new StringBuilder();
  
      builder.append('{');
  
      for (Map.Entry<String, List<MappingDomainError>> entry : errorLangMap.entrySet()) {
        builder.append("\"").append(entry.getKey()).append("\"");
        builder.append(": [ ");
  
        for (MappingDomainError error : entry.getValue()) {
          builder.append("{");
          builder.append("\"mapping\":").append("\"").append(error.mapping).append("\",");
          builder.append("\"predicate\":").append("\"").append(error.predicate).append("\",");
          builder.append("\"expected\":").append("\"").append(error.expected).append("\",");
          builder.append("\"existing\":").append("\"").append(error.wrong).append("\"");
          builder.append("},");
        }
        builder.deleteCharAt(builder.length() - 1);  // delete last ','
  
        builder.append("],");
  
  
      }
      builder.deleteCharAt(builder.length() - 1);  // delete last ','
  
      builder.append('}');
  
      return builder.toString();
    }
  
    public String validateAndGetJson() throws RdfReaderException {
      Model model = ModelFactory.createDefaultModel();
      TestExecutionWriter.create(validateAllMappings()).write(model);
  
      //new RDFFileWriter("mappings.ttl").write(model);
      List<MappingDomainError> errors = getErrorListFromModel(model);
  
      return convertToJson(getErrorsAsMap(errors));
    }
  
    static class MappingDomainError {
  
      public final String language;
      public final String mapping;
      public final String predicate;
      public final String wrong;
      public final String expected;
  
      MappingDomainError(String mappingUri, String predicate, String wrong, String expected) {
        String tmpStr = mappingUri.replace("http://mappings.dbpedia.org/server/mappings/", "");
        int endOfLang = tmpStr.indexOf('/');
        this.language = tmpStr.substring(0, endOfLang);
        int endOfMap = tmpStr.indexOf("/Class");
        this.mapping = tmpStr.substring(endOfLang + 1, endOfMap);
  
        this.predicate = predicate;
        this.wrong = wrong;
        this.expected = expected;
  
      }
  
    }
  }
  
  