RdfUtilities.java

  1. /*
  2.  * *********************************************************************************************************************
  3.  *
  4.  * blueMarine II: Semantic Media Centre
  5.  * http://tidalwave.it/projects/bluemarine2
  6.  *
  7.  * Copyright (C) 2015 - 2021 by Tidalwave s.a.s. (http://tidalwave.it)
  8.  *
  9.  * *********************************************************************************************************************
  10.  *
  11.  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  12.  * the License. You may obtain a copy of the License at
  13.  *
  14.  *     http://www.apache.org/licenses/LICENSE-2.0
  15.  *
  16.  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  17.  * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
  18.  * specific language governing permissions and limitations under the License.
  19.  *
  20.  * *********************************************************************************************************************
  21.  *
  22.  * git clone https://bitbucket.org/tidalwave/bluemarine2-src
  23.  * git clone https://github.com/tidalwave-it/bluemarine2-src
  24.  *
  25.  * *********************************************************************************************************************
  26.  */
  27. package it.tidalwave.bluemarine2.util;

  28. import javax.annotation.Nonnull;
  29. import javax.annotation.Nullable;
  30. import java.time.Instant;
  31. import java.text.Normalizer;
  32. import java.util.Base64;
  33. import java.util.Date;
  34. import java.util.Iterator;
  35. import java.util.Optional;
  36. import java.util.stream.Stream;
  37. import java.io.IOException;
  38. import java.io.PrintWriter;
  39. import java.nio.file.Files;
  40. import java.nio.file.Path;
  41. import java.net.MalformedURLException;
  42. import java.net.URL;
  43. import java.security.MessageDigest;
  44. import java.security.NoSuchAlgorithmException;
  45. import org.eclipse.rdf4j.model.IRI;
  46. import org.eclipse.rdf4j.model.Model;
  47. import org.eclipse.rdf4j.model.Value;
  48. import org.eclipse.rdf4j.model.ValueFactory;
  49. import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
  50. import org.eclipse.rdf4j.repository.RepositoryException;
  51. import org.eclipse.rdf4j.rio.n3.N3Writer;
  52. import org.eclipse.rdf4j.rio.RDFHandler;
  53. import org.eclipse.rdf4j.rio.RDFHandlerException;
  54. import org.eclipse.rdf4j.common.iteration.Iteration;
  55. import it.tidalwave.util.Id;
  56. import lombok.NoArgsConstructor;
  57. import lombok.extern.slf4j.Slf4j;
  58. import static java.text.Normalizer.Form.NFC;
  59. import static java.util.Spliterators.spliteratorUnknownSize;
  60. import static java.util.stream.StreamSupport.stream;
  61. import static java.nio.charset.StandardCharsets.UTF_8;
  62. import static lombok.AccessLevel.PRIVATE;
  63. import static it.tidalwave.bluemarine2.util.Formatters.*;

  64. /***********************************************************************************************************************
  65.  *
  66.  * @author  Fabrizio Giudici
  67.  *
  68.  **********************************************************************************************************************/
  69. @NoArgsConstructor(access = PRIVATE) @Slf4j
  70. public final class RdfUtilities
  71.   {
  72.     private static final String ALGORITHM = "SHA1";

  73.     private static final ValueFactory FACTORY = SimpleValueFactory.getInstance(); // FIXME

  74.     /*******************************************************************************************************************
  75.      *
  76.      * Exports the repository to the given file. FIXME: duplicated in DefaultPerstistence
  77.      *
  78.      ******************************************************************************************************************/
  79.     public static void exportToFile (@Nonnull final Model model, @Nonnull final Path path)
  80.       throws RDFHandlerException, IOException, RepositoryException
  81.       {
  82.         log.info("exportToFile({})", path);
  83.         Files.createDirectories(path.getParent());

  84.         try (final PrintWriter pw = new PrintWriter(Files.newBufferedWriter(path, UTF_8)))
  85.           {
  86.             final RDFHandler writer = new SortingRDFHandler(new N3Writer(pw));
  87.             writer.startRDF();
  88. //            FIXME: use Iterations - and sort
  89. //            for (final Namespace namespace : connection.getNamespaces().asList())
  90. //              {
  91. //                writer.handleNamespace(namespace.getPrefix(), namespace.getName());
  92. //              }

  93.             writer.handleNamespace("bio",   "http://purl.org/vocab/bio/0.1/");
  94.             writer.handleNamespace("bmmo",  "http://bluemarine.tidalwave.it/2015/04/mo/");
  95.             writer.handleNamespace("dc",    "http://purl.org/dc/elements/1.1/");
  96.             writer.handleNamespace("foaf",  "http://xmlns.com/foaf/0.1/");
  97.             writer.handleNamespace("owl",   "http://www.w3.org/2002/07/owl#");
  98.             writer.handleNamespace("mo",    "http://purl.org/ontology/mo/");
  99.             writer.handleNamespace("rdfs",  "http://www.w3.org/2000/01/rdf-schema#");
  100.             writer.handleNamespace("rel",   "http://purl.org/vocab/relationship/");
  101.             writer.handleNamespace("vocab", "http://dbtune.org/musicbrainz/resource/vocab/");
  102.             writer.handleNamespace("xs",    "http://www.w3.org/2001/XMLSchema#");

  103.             model.stream().forEachOrdered(writer::handleStatement);
  104.             writer.endRDF();
  105.           }
  106.       }

  107.     /*******************************************************************************************************************
  108.      *
  109.      *
  110.      ******************************************************************************************************************/
  111.     @Nonnull
  112.     public static <T, X extends RuntimeException> Stream<T> streamOf (@Nonnull final Iteration<T, X> iteration)
  113.       {
  114.         return stream(spliteratorUnknownSize(iteratorOf(iteration), 0), false);
  115.       }

  116.     /*******************************************************************************************************************
  117.      *
  118.      *
  119.      ******************************************************************************************************************/
  120.     @Nonnull
  121.     private static <T, X extends RuntimeException> Iterator<T> iteratorOf (@Nonnull final Iteration<T, X> iteration)
  122.       {
  123.         return new Iterator<>()
  124.           {
  125.             @Override
  126.             public boolean hasNext ()
  127.               {
  128.                 return iteration.hasNext();
  129.               }

  130.             @Override
  131.             public T next ()
  132.               {
  133.                 return iteration.next();
  134.               }
  135.           };
  136.       }

  137.     /*******************************************************************************************************************
  138.      *
  139.      *
  140.      ******************************************************************************************************************/
  141.     @Nonnull
  142.     public static Value literalFor (final Path path)
  143.       {
  144.         return FACTORY.createLiteral(Normalizer.normalize(path.toString(), NFC));
  145.       }

  146.     /*******************************************************************************************************************
  147.      *
  148.      *
  149.      ******************************************************************************************************************/
  150.     @Nonnull
  151.     public static Value literalFor (final String string)
  152.       {
  153.         return FACTORY.createLiteral(string);
  154.       }

  155.     /*******************************************************************************************************************
  156.      *
  157.      *
  158.      ******************************************************************************************************************/
  159.     @Nonnull
  160.     public static Optional<Value> literalFor (final Optional<String> optionalString)
  161.       {
  162.         return optionalString.map(RdfUtilities::literalFor);
  163.       }

  164.     /*******************************************************************************************************************
  165.      *
  166.      *
  167.      ******************************************************************************************************************/
  168.     @Nonnull
  169.     public static Value literalFor (final Id id)
  170.       {
  171.         return FACTORY.createLiteral(id.stringValue());
  172.       }

  173.     /*******************************************************************************************************************
  174.      *
  175.      *
  176.      ******************************************************************************************************************/
  177.     @Nonnull
  178.     public static Value literalFor (final int value)
  179.       {
  180.         return FACTORY.createLiteral(value);
  181.       }

  182.     /*******************************************************************************************************************
  183.      *
  184.      *
  185.      ******************************************************************************************************************/
  186.     @Nonnull
  187.     public static Optional<Value> literalForInt (final Optional<Integer> optionalInteger)
  188.       {
  189.         return optionalInteger.map(RdfUtilities::literalFor);
  190.       }

  191.     /*******************************************************************************************************************
  192.      *
  193.      *
  194.      ******************************************************************************************************************/
  195.     @Nonnull
  196.     public static Value literalFor (final long value)
  197.       {
  198.         return FACTORY.createLiteral(value);
  199.       }

  200.     /*******************************************************************************************************************
  201.      *
  202.      *
  203.      ******************************************************************************************************************/
  204.     @Nonnull
  205.     public static Optional<Value> literalForLong (final Optional<Long> optionalLong)
  206.       {
  207.         return optionalLong.map(RdfUtilities::literalFor);
  208.       }

  209.     /*******************************************************************************************************************
  210.      *
  211.      *
  212.      ******************************************************************************************************************/
  213.     @Nonnull
  214.     public static Value literalFor (final short value)
  215.       {
  216.         return FACTORY.createLiteral(value);
  217.       }

  218.     /*******************************************************************************************************************
  219.      *
  220.      *
  221.      ******************************************************************************************************************/
  222.     @Nonnull
  223.     public static Value literalFor (final float value)
  224.       {
  225.         return FACTORY.createLiteral(value);
  226.       }

  227.     /*******************************************************************************************************************
  228.      *
  229.      *
  230.      ******************************************************************************************************************/
  231.     @Nonnull
  232.     public static Optional<Value> literalForFloat (final Optional<Float> optionalFloat)
  233.       {
  234.         return optionalFloat.map(RdfUtilities::literalFor);
  235.       }

  236.     /*******************************************************************************************************************
  237.      *
  238.      *
  239.      ******************************************************************************************************************/
  240.     @Nonnull
  241.     public static Value literalFor (@Nonnull final Instant instant)
  242.       {
  243.         return FACTORY.createLiteral(new Date(instant.toEpochMilli()));
  244.       }

  245.     /*******************************************************************************************************************
  246.      *
  247.      *
  248.      ******************************************************************************************************************/
  249.     @Nonnull
  250.     public static IRI uriFor (@Nonnull final Id id)
  251.       {
  252.         return uriFor(id.stringValue());
  253.       }

  254.     /*******************************************************************************************************************
  255.      *
  256.      *
  257.      ******************************************************************************************************************/
  258.     @Nonnull
  259.     public static IRI uriFor (@Nonnull final String id)
  260.       {
  261.         return FACTORY.createIRI(id);
  262.       }

  263.     /*******************************************************************************************************************
  264.      *
  265.      *
  266.      ******************************************************************************************************************/
  267.     @Nonnull
  268.     public static IRI uriFor (@Nonnull final URL url)
  269.       {
  270.         return FACTORY.createIRI(url.toString());
  271.       }

  272.     /*******************************************************************************************************************
  273.      *
  274.      *
  275.      ******************************************************************************************************************/
  276.     @Nonnull
  277.     public static URL urlFor (@Nonnull final IRI uri)
  278.       throws MalformedURLException
  279.       {
  280.         return new URL(uri.toString());
  281.       }

  282.     /*******************************************************************************************************************
  283.      *
  284.      *
  285.      ******************************************************************************************************************/
  286.     @Nonnull
  287.     public static String emptyWhenNull (@Nullable final String string)
  288.       {
  289.         return (string != null) ? string : "";
  290.       }

  291.     /*******************************************************************************************************************
  292.      *
  293.      *
  294.      ******************************************************************************************************************/
  295.     @Nonnull
  296.     public static Id createSha1Id (@Nonnull final String string)
  297.       {
  298.         try
  299.           {
  300.             final MessageDigest digestComputer = MessageDigest.getInstance(ALGORITHM);
  301.             digestComputer.update(string.getBytes(UTF_8));
  302.             return Id.of(toHexString(digestComputer.digest()));
  303.           }
  304.         catch (NoSuchAlgorithmException e)
  305.           {
  306.             throw new RuntimeException(e);
  307.           }
  308.       }

  309.     /*******************************************************************************************************************
  310.      *
  311.      *
  312.      ******************************************************************************************************************/
  313.     @Nonnull
  314.     public static Id createSha1IdNew (@Nonnull final String string)
  315.       {
  316.         try
  317.           {
  318.             final MessageDigest digestComputer = MessageDigest.getInstance(ALGORITHM);
  319.             digestComputer.update(string.getBytes(UTF_8));
  320.             return Id.of(Base64.getUrlEncoder().encodeToString(digestComputer.digest()));
  321.           }
  322.         catch (NoSuchAlgorithmException e)
  323.           {
  324.             throw new RuntimeException(e);
  325.           }
  326.       }
  327.   }