View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *  http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17
    18  package org.apache.any23.rdf;
    19
    20  import org.apache.any23.util.MathUtils;
    21  import org.apache.any23.util.StringUtils;
    22  import org.eclipse.rdf4j.model.BNode;
    23  import org.eclipse.rdf4j.model.IRI;
    24  import org.eclipse.rdf4j.model.Literal;
    25  import org.eclipse.rdf4j.model.Resource;
    26  import org.eclipse.rdf4j.model.Statement;
    27  import org.eclipse.rdf4j.model.Value;
    28  import org.eclipse.rdf4j.model.ValueFactory;
    29  import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
    30  import org.eclipse.rdf4j.model.vocabulary.RDF;
    31  import org.eclipse.rdf4j.rio.RDFFormat;
    32  import org.eclipse.rdf4j.rio.RDFParser;
    33  import org.eclipse.rdf4j.rio.RDFParserRegistry;
    34  import org.eclipse.rdf4j.rio.RDFWriter;
    35  import org.eclipse.rdf4j.rio.Rio;
    36  import org.eclipse.rdf4j.rio.helpers.BasicParserSettings;
    37  import org.eclipse.rdf4j.rio.helpers.StatementCollector;
    38  import org.slf4j.Logger;
    39  import org.slf4j.LoggerFactory;
    40
    41  import javax.xml.datatype.DatatypeConfigurationException;
    42  import javax.xml.datatype.DatatypeFactory;
    43  import javax.xml.datatype.XMLGregorianCalendar;
    44  import java.io.ByteArrayInputStream;
    45  import java.io.IOException;
    46  import java.io.InputStream;
    47  import java.io.OutputStream;
    48  import java.io.Writer;
    49  import java.net.URISyntaxException;
    50  import java.nio.charset.StandardCharsets;
    51  import java.text.ParseException;
    52  import java.text.SimpleDateFormat;
    53  import java.util.Collection;
    54  import java.util.Date;
    55  import java.util.GregorianCalendar;
    56  import java.util.Locale;
    57  import java.util.Optional;
    58  import java.util.TimeZone;
    59
    60  /**
    61   * Basic class providing a set of utility methods when dealing with <i>RDF</i>.
    62   *
    63   * @author Michele Mostarda (mostarda@fbk.eu)
    64   * @author Davide Palmisano (dpalmisano@gmail.com)
    65   * @author Jacek Grzebyta (jgrzebyta@apache.org)
    66   */
    67  public class RDFUtils {
    68
    69      private static int nodeId = 0;
    70
    71      private static final ValueFactory valueFactory = SimpleValueFactory.getInstance();
    72
    73      private static final Logger LOG = LoggerFactory.getLogger(RDFUtils.class);
    74
    75      private static final Statement[] EMPTY_STATEMENTS = new Statement[0];
    76
    77      private RDFUtils() {
    78      }
    79
    80      /**
    81       * Fixes typical errors in an absolute org.eclipse.rdf4j.model.IRI, such as unescaped spaces.
    82       *
    83       * @param uri
    84       *            An absolute org.eclipse.rdf4j.model.IRI, can have typical syntax errors
    85       *
    86       * @return An absolute org.eclipse.rdf4j.model.IRI that is valid against the org.eclipse.rdf4j.model.IRI syntax
    87       *
    88       * @throws IllegalArgumentException
    89       *             if org.eclipse.rdf4j.model.IRI is not fixable
    90       */
    91      public static String fixAbsoluteIRI(String uri) {
    92          String fixed = fixIRIWithException(uri);
    93          if (!fixed.matches("[a-zA-Z0-9]+:/.*"))
    94              throw new IllegalArgumentException("not a absolute org.eclipse.rdf4j.model.IRI: " + uri);
    95          // Add trailing slash if org.eclipse.rdf4j.model.IRI has only authority but no path.
    96          if (fixed.matches("https?://[a-zA-Z0-9.-]+(:[0-9+])?")) {
    97              fixed = fixed + "/";
    98          }
    99          return fixed;
    100     }
    101
    102     /**
    103      * This method allows to obtain an <a href="http://www.w3.org/TR/xmlschema-2/#date">XML Schema</a> compliant date
    104      * providing a textual representation of a date and textual a pattern for parsing it.
    105      *
    106      * @param dateToBeParsed
    107      *            the String containing the date.
    108      * @param format
    109      *            the pattern as descibed in {@link java.text.SimpleDateFormat}
    110      *
    111      * @return a {@link String} representing the date
    112      *
    113      * @throws java.text.ParseException
    114      *             if there is an error parsing the given date.
    115      * @throws javax.xml.datatype.DatatypeConfigurationException
    116      *             if there is a serious configuration error.
    117      */
    118     public static String getXSDDate(String dateToBeParsed, String format)
    119             throws ParseException, DatatypeConfigurationException {
    120         SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format, Locale.ROOT);
    121         Date date = simpleDateFormat.parse(dateToBeParsed);
    122         GregorianCalendar gc = new GregorianCalendar(TimeZone.getDefault(), Locale.ROOT);
    123         gc.setTime(date);
    124         XMLGregorianCalendar xml = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
    125         xml.setTimezone(0);
    126         return xml.toString();
    127     }
    128
    129     /**
    130      * Prints a <code>date</code> to the XSD datetime format.
    131      *
    132      * @param date
    133      *            date to be printed.
    134      *
    135      * @return the string representation of the input date.
    136      */
    137     public static String toXSDDateTime(Date date) {
    138         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.ROOT);
    139         String s = simpleDateFormat.format(date);
    140         StringBuilder sb = new StringBuilder(s);
    141         sb.insert(22, ':');
    142         return sb.toString();
    143     }
    144
    145     /**
    146      * <p>
    147      * Tries to fix a potentially broken relative or absolute URI.
    148      * </p>
    149      * These appear to be good rules: Remove whitespace or '\' or '"' in beginning and end Replace space with %20 Drop
    150      * the triple if it matches this regex (only protocol): ^[a-zA-Z0-9]+:(//)?$ Drop the triple if it matches this
    151      * regex: ^javascript: Truncate "&gt;.*$ from end of lines (Neko didn't quite manage to fix broken markup) Drop the
    152      * triple if any of these appear in the URL: &lt;&gt;[]|*{}"&lt;&gt;\
    153      *
    154      * @param unescapedIRI
    155      *            uri string to be unescaped.
    156      *
    157      * @return the unescaped string.
    158      */
    159     public static String fixIRIWithException(String unescapedIRI) {
    160         if (unescapedIRI == null)
    161             throw new IllegalArgumentException("org.eclipse.rdf4j.model.IRI was null");
    162
    163         // Remove starting and ending whitespace
    164         String escapedIRI = unescapedIRI.trim();
    165
    166         // Replace space with %20
    167         escapedIRI = escapedIRI.replaceAll(" ", "%20");
    168
    169         // strip linebreaks
    170         escapedIRI = escapedIRI.replaceAll("\n", "");
    171
    172         // 'Remove starting "\" or '"'
    173         if (escapedIRI.startsWith("\\") || escapedIRI.startsWith("\""))
    174             escapedIRI = escapedIRI.substring(1);
    175         // Remove ending "\" or '"'
    176         if (escapedIRI.endsWith("\\") || escapedIRI.endsWith("\""))
    177             escapedIRI = escapedIRI.substring(0, escapedIRI.length() - 1);
    178
    179         // Drop the triple if it matches this regex (only protocol): ^[a-zA-Z0-9]+:/?/?$
    180         if (escapedIRI.matches("^[a-zA-Z0-9]+:/?/?$"))
    181             throw new IllegalArgumentException("no authority in org.eclipse.rdf4j.model.IRI: " + unescapedIRI);
    182
    183         // Drop the triple if it matches this regex: ^javascript:
    184         if (escapedIRI.matches("^javascript:"))
    185             throw new IllegalArgumentException("org.eclipse.rdf4j.model.IRI starts with javascript: " + unescapedIRI);
    186
    187         // stripHTML
    188         // escapedIRI = escapedIRI.replaceAll("\\<.*?\\>", "");
    189
    190         // >.*$ from end of lines (Neko didn't quite manage to fix broken markup)
    191         escapedIRI = escapedIRI.replaceAll(">.*$", "");
    192
    193         // Drop the triple if any of these appear in the URL: <>[]|*{}"<>\
    194         if (escapedIRI.matches("[<>\\[\\]|\\*\\{\\}\"\\\\]"))
    195             throw new IllegalArgumentException("Invalid character in org.eclipse.rdf4j.model.IRI: " + unescapedIRI);
    196
    197         return escapedIRI;
    198     }
    199
    200     /**
    201      * Creates a {@link org.eclipse.rdf4j.model.IRI}.
    202      *
    203      * @param iri
    204      *            a base string for the {@link org.eclipse.rdf4j.model.IRI}
    205      *
    206      * @return a valid {@link org.eclipse.rdf4j.model.IRI}
    207      */
    208     public static org.eclipse.rdf4j.model.IRI iri(String iri) {
    209         return valueFactory.createIRI(iri);
    210     }
    211
    212     /**
    213      * Creates a {@link org.eclipse.rdf4j.model.IRI}.
    214      *
    215      * @param namespace
    216      *            a base namespace for the {@link org.eclipse.rdf4j.model.IRI}
    217      * @param localName
    218      *            a local name to associate with the namespace
    219      *
    220      * @return a valid {@link org.eclipse.rdf4j.model.IRI}
    221      */
    222     public static org.eclipse.rdf4j.model.IRI iri(String namespace, String localName) {
    223         return valueFactory.createIRI(namespace, localName);
    224     }
    225
    226     /**
    227      * Creates a {@link Literal}.
    228      *
    229      * @param s
    230      *            string representation of the {@link org.eclipse.rdf4j.model.Literal}
    231      *
    232      * @return valid {@link org.eclipse.rdf4j.model.Literal}
    233      */
    234     public static Literal literal(String s) {
    235         return valueFactory.createLiteral(s);
    236     }
    237
    238     /**
    239      * Creates a {@link Literal}.
    240      *
    241      * @param b
    242      *            boolean representation of the {@link org.eclipse.rdf4j.model.Literal}
    243      *
    244      * @return valid {@link org.eclipse.rdf4j.model.Literal}
    245      */
    246     public static Literal literal(boolean b) {
    247         return valueFactory.createLiteral(b);
    248     }
    249
    250     /**
    251      * Creates a {@link Literal}.
    252      *
    253      * @param b
    254      *            byte representation of the {@link org.eclipse.rdf4j.model.Literal}
    255      *
    256      * @return valid {@link org.eclipse.rdf4j.model.Literal}
    257      */
    258     public static Literal literal(byte b) {
    259         return valueFactory.createLiteral(b);
    260     }
    261
    262     /**
    263      * Creates a {@link Literal}.
    264      *
    265      * @param s
    266      *            short representation of the {@link org.eclipse.rdf4j.model.Literal}
    267      *
    268      * @return valid {@link org.eclipse.rdf4j.model.Literal}
    269      */
    270     public static Literal literal(short s) {
    271         return valueFactory.createLiteral(s);
    272     }
    273
    274     /**
    275      * Creates a {@link Literal}.
    276      *
    277      * @param i
    278      *            int representation of the {@link org.eclipse.rdf4j.model.Literal}
    279      *
    280      * @return valid {@link org.eclipse.rdf4j.model.Literal}
    281      */
    282     public static Literal literal(int i) {
    283         return valueFactory.createLiteral(i);
    284     }
    285
    286     /**
    287      * Creates a {@link Literal}.
    288      *
    289      * @param l
    290      *            long representation of the {@link org.eclipse.rdf4j.model.Literal}
    291      *
    292      * @return valid {@link org.eclipse.rdf4j.model.Literal}
    293      */
    294     public static Literal literal(long l) {
    295         return valueFactory.createLiteral(l);
    296     }
    297
    298     /**
    299      * Creates a {@link Literal}.
    300      *
    301      * @param f
    302      *            float representation of the {@link org.eclipse.rdf4j.model.Literal}
    303      *
    304      * @return valid {@link org.eclipse.rdf4j.model.Literal}
    305      */
    306     public static Literal literal(float f) {
    307         return valueFactory.createLiteral(f);
    308     }
    309
    310     /**
    311      * Creates a {@link Literal}.
    312      *
    313      * @param d
    314      *            double representation of the {@link org.eclipse.rdf4j.model.Literal}
    315      *
    316      * @return valid {@link org.eclipse.rdf4j.model.Literal}
    317      */
    318     public static Literal literal(double d) {
    319         return valueFactory.createLiteral(d);
    320     }
    321
    322     /**
    323      * Creates a {@link Literal}.
    324      *
    325      * @param s
    326      *            the literal's label
    327      * @param l
    328      *            the literal's language
    329      *
    330      * @return valid {@link org.eclipse.rdf4j.model.Literal}
    331      */
    332     public static Literal literal(String s, String l) {
    333         if (l == null) {
    334             // HACK: Workaround for ANY23 code that passes null in for language tag
    335             return valueFactory.createLiteral(s);
    336         } else {
    337             return valueFactory.createLiteral(s, l);
    338         }
    339     }
    340
    341     /**
    342      * Creates a {@link Literal}.
    343      *
    344      * @param s
    345      *            the literal's label
    346      * @param datatype
    347      *            the literal's datatype
    348      *
    349      * @return valid {@link org.eclipse.rdf4j.model.Literal}
    350      */
    351     public static Literal literal(String s, org.eclipse.rdf4j.model.IRI datatype) {
    352         return valueFactory.createLiteral(s, datatype);
    353     }
    354
    355     /**
    356      * Creates a {@link BNode}.
    357      *
    358      * @param id
    359      *            string representation of the {@link org.eclipse.rdf4j.model.BNode}
    360      *
    361      * @return the valid {@link org.eclipse.rdf4j.model.BNode}
    362      */
    363     // TODO: replace this with all occurrences of #getBNode()
    364     public static BNode bnode(String id) {
    365         return valueFactory.createBNode(id);
    366     }
    367
    368     /**
    369      * @return a <code>bnode</code> with unique id.
    370      */
    371     public static BNode bnode() {
    372         return valueFactory.createBNode();
    373     }
    374
    375     /**
    376      * Creates a {@link BNode} with an MD5 digest as part of the ID.
    377      *
    378      * @param id
    379      *            string representation of the {@link org.eclipse.rdf4j.model.BNode} name for which we will create a md5
    380      *            hash.
    381      *
    382      * @return the valid {@link org.eclipse.rdf4j.model.BNode}
    383      */
    384     public static BNode getBNode(String id) {
    385         return valueFactory.createBNode("node" + MathUtils.md5(id));
    386     }
    387
    388     /**
    389      * Creates a {@link Statement}.
    390      *
    391      * @param s
    392      *            subject {@link org.eclipse.rdf4j.model.Resource}
    393      * @param p
    394      *            predicate {@link org.eclipse.rdf4j.model.URI}
    395      * @param o
    396      *            object {@link org.eclipse.rdf4j.model.Value}
    397      *
    398      * @return valid {@link org.eclipse.rdf4j.model.Statement}
    399      */
    400     public static Statement triple(Resource s, org.eclipse.rdf4j.model.IRI p, Value o) {
    401         return valueFactory.createStatement(s, p, o);
    402     }
    403
    404     /**
    405      * Creates a statement of type: <code>toValue(s), toValue(p), toValue(o)</code>
    406      *
    407      * @param s
    408      *            subject.
    409      * @param p
    410      *            predicate.
    411      * @param o
    412      *            object.
    413      *
    414      * @return a statement instance.
    415      */
    416     public static Statement triple(String s, String p, String o) {
    417         return valueFactory.createStatement((Resource) toValue(s), (org.eclipse.rdf4j.model.IRI) toValue(p),
    418                 toValue(o));
    419     }
    420
    421     /**
    422      * Creates a {@link Statement}.
    423      *
    424      * @param s
    425      *            subject.
    426      * @param p
    427      *            predicate.
    428      * @param o
    429      *            object.
    430      * @param g
    431      *            quad resource
    432      *
    433      * @return a statement instance.
    434      */
    435     public static Statement quad(Resource s, org.eclipse.rdf4j.model.IRI p, Value o, Resource g) {
    436         return valueFactory.createStatement(s, p, o, g);
    437     }
    438
    439     /**
    440      * Creates a statement of type: <code>toValue(s), toValue(p), toValue(o), toValue(g)</code>
    441      *
    442      * @param s
    443      *            subject.
    444      * @param p
    445      *            predicate.
    446      * @param o
    447      *            object.
    448      * @param g
    449      *            quad resource
    450      *
    451      * @return a statement instance.
    452      */
    453     public static Statement quad(String s, String p, String o, String g) {
    454         return valueFactory.createStatement((Resource) toValue(s), (org.eclipse.rdf4j.model.IRI) toValue(p), toValue(o),
    455                 (Resource) toValue(g));
    456     }
    457
    458     /**
    459      * Creates a {@link Value}. If <code>s == 'a'</code> returns an {@link RDF#TYPE}. If
    460      * <code> s.matches('[a-z0-9]+:.*')</code> expands the corresponding prefix using {@link PopularPrefixes}.
    461      *
    462      * @param s
    463      *            string representation of value.
    464      *
    465      * @return a value instance.
    466      */
    467     public static Value toValue(String s) {
    468         if ("a".equals(s))
    469             return RDF.TYPE;
    470         if (s.matches("[a-z0-9]+:.*")) {
    471             return PopularPrefixes.get().expand(s);
    472         }
    473         return valueFactory.createLiteral(s);
    474     }
    475
    476     /**
    477      *
    478      * Returns all the available {@link RDFFormat}s.
    479      *
    480      * @return an unmodifiable collection of formats.
    481      */
    482     public static Collection<RDFFormat> getFormats() {
    483         return RDFParserRegistry.getInstance().getKeys();
    484     }
    485
    486     /**
    487      * Creates a new {@link RDFParser} instance.
    488      *
    489      * @param format
    490      *            parser format.
    491      *
    492      * @return parser instance.
    493      *
    494      * @throws IllegalArgumentException
    495      *             if format is not supported.
    496      */
    497     public static RDFParser getParser(RDFFormat format) {
    498         return Rio.createParser(format);
    499     }
    500
    501     /**
    502      * Creates a new {@link RDFWriter} instance.
    503      *
    504      * @param format
    505      *            output format.
    506      * @param writer
    507      *            data output writer.
    508      *
    509      * @return writer instance.
    510      *
    511      * @throws IllegalArgumentException
    512      *             if format is not supported.
    513      */
    514     public static RDFWriter getWriter(RDFFormat format, Writer writer) {
    515         return Rio.createWriter(format, writer);
    516     }
    517
    518     /**
    519      * Creates a new {@link RDFWriter} instance.
    520      *
    521      * @param format
    522      *            output format.
    523      * @param os
    524      *            output stream.
    525      *
    526      * @return writer instance.
    527      *
    528      * @throws IllegalArgumentException
    529      *             if format is not supported.
    530      */
    531     public static RDFWriter getWriter(RDFFormat format, OutputStream os) {
    532         return Rio.createWriter(format, os);
    533     }
    534
    535     /**
    536      * Returns a parser type from the given extension.
    537      *
    538      * @param ext
    539      *            input extension.
    540      *
    541      * @return parser matching the extension.
    542      *
    543      * @throws IllegalArgumentException
    544      *             if no extension matches.
    545      */
    546     public static Optional<RDFFormat> getFormatByExtension(String ext) {
    547         if (!ext.startsWith("."))
    548             ext = "." + ext;
    549         return Rio.getParserFormatForFileName(ext);
    550     }
    551
    552     /**
    553      * Parses the content of <code>is</code> input stream with the specified parser <code>p</code> using
    554      * <code>baseIRI</code>.
    555      *
    556      * @param format
    557      *            input format type.
    558      * @param is
    559      *            input stream containing <code>RDF</code>.
    560      * @param baseIRI
    561      *            base uri.
    562      *
    563      * @return list of statements detected within the input stream.
    564      *
    565      * @throws IOException
    566      *             if there is an error reading the {@link java.io.InputStream}
    567      */
    568     public static Statement[] parseRDF(RDFFormat format, InputStream is, String baseIRI) throws IOException {
    569         final StatementCollector handler = new StatementCollector();
    570         final RDFParser parser = getParser(format);
    571         parser.getParserConfig().set(BasicParserSettings.VERIFY_DATATYPE_VALUES, true);
    572         parser.setPreserveBNodeIDs(true);
    573         parser.setRDFHandler(handler);
    574         parser.parse(is, baseIRI);
    575         return handler.getStatements().toArray(EMPTY_STATEMENTS);
    576     }
    577
    578     /**
    579      * Parses the content of <code>is</code> input stream with the specified parser <code>p</code> using <code>''</code>
    580      * as base org.eclipse.rdf4j.model.IRI.
    581      *
    582      * @param format
    583      *            input format type.
    584      * @param is
    585      *            input stream containing <code>RDF</code>.
    586      *
    587      * @return list of statements detected within the input stream.
    588      *
    589      * @throws IOException
    590      *             if there is an error reading the {@link java.io.InputStream}
    591      */
    592     public static Statement[] parseRDF(RDFFormat format, InputStream is) throws IOException {
    593         return parseRDF(format, is, "");
    594     }
    595
    596     /**
    597      * Parses the content of <code>in</code> string with the specified parser <code>p</code> using <code>''</code> as
    598      * base org.eclipse.rdf4j.model.IRI.
    599      *
    600      * @param format
    601      *            input format type.
    602      * @param in
    603      *            input string containing <code>RDF</code>.
    604      *
    605      * @return list of statements detected within the input string.
    606      *
    607      * @throws IOException
    608      *             if there is an error reading the {@link java.io.InputStream}
    609      */
    610     public static Statement[] parseRDF(RDFFormat format, String in) throws IOException {
    611         return parseRDF(format, new ByteArrayInputStream(in.getBytes(StandardCharsets.UTF_8)));
    612     }
    613
    614     /**
    615      * Parses the content of the <code>resource</code> file guessing the content format from the extension.
    616      *
    617      * @param resource
    618      *            resource name.
    619      *
    620      * @return the statements declared within the resource file.
    621      *
    622      * @throws java.io.IOException
    623      *             if an error occurs while reading file.
    624      */
    625     public static Statement[] parseRDF(String resource) throws IOException {
    626         final int extIndex = resource.lastIndexOf('.');
    627         if (extIndex == -1)
    628             throw new IllegalArgumentException("Error while detecting the extension in resource name " + resource);
    629         final String extension = resource.substring(extIndex + 1);
    630         return parseRDF(getFormatByExtension(extension).orElseThrow(Rio.unsupportedFormat(extension)),
    631                 RDFUtils.class.getResourceAsStream(resource));
    632     }
    633
    634     /**
    635      * Checks if <code>href</code> is absolute or not.
    636      *
    637      * @param href
    638      *            candidate org.eclipse.rdf4j.model.IRI.
    639      *
    640      * @return <code>true</code> if <code>href</code> is absolute, <code>false</code> otherwise.
    641      */
    642     public static boolean isAbsoluteIRI(String href) {
    643         try {
    644             SimpleValueFactory.getInstance().createIRI(href.trim());
    645             new java.net.URI(href.trim());
    646             return true;
    647         } catch (IllegalArgumentException e) {
    648             LOG.trace("Error processing href: {}", href, e);
    649             return false;
    650         } catch (URISyntaxException e) {
    651             LOG.trace("Error interpreting href: {} as URI.", href, e);
    652             return false;
    653         }
    654     }
    655
    656     /**
    657      * {@link #makeIRI(java.lang.String, org.eclipse.rdf4j.model.IRI, boolean) }.
    658      *
    659      * @param docUri
    660      *            It is a namespace. If it ends with '/' character than stays unchanged otherwise the hash character '#'
    661      *            is added to the end.
    662      *
    663      * @return instance of {@link Resource}.
    664      */
    665     public static Resource makeIRI(IRI docUri) {
    666         return makeIRI("node", docUri);
    667     }
    668
    669     /**
    670      * {@link #makeIRI(java.lang.String, org.eclipse.rdf4j.model.IRI, boolean) }.
    671      *
    672      * @param type
    673      *            This argument is converted following Java naming conventions with
    674      *            {@link StringUtils#implementJavaNaming(java.lang.String) }.
    675      * @param docIRI
    676      *            It is a namespace. If it ends with '/' character than stays unchanged otherwise the hash character '#'
    677      *            is added to the end.
    678      *
    679      * @return instance of {@link Resource}.
    680      */
    681     public static Resource makeIRI(String type, IRI docIRI) {
    682         return makeIRI(type, docIRI, false);
    683     }
    684
    685     /**
    686      * Creates implementation of {@link Resource} from given arguments: <i>type</i> and <i>docIRI</i>.
    687      *
    688      * <b>NB:</b> The Java Naming Conventions is described by
    689      * <a href='http://www.geeksforgeeks.org/java-naming-conventions/'>GeeksForGeeks</a>.
    690      *
    691      * @param type
    692      *            This argument is converted following Java naming conventions with
    693      *            {@link StringUtils#implementJavaNaming(java.lang.String) }.
    694      * @param docIRI
    695      *            It is a namespace. If it ends with '/' character than stays unchanged otherwise the hash character '#'
    696      *            is added to the end.
    697      * @param addId
    698      *            If argument is <b>TRUE</b> than the node identifier is added to the end formated
    699      *            <code>'_{int}'</code>.
    700      *
    701      * @return instance of {@link Resource}.
    702      */
    703     public static Resource makeIRI(String type, IRI docIRI, boolean addId) {
    704
    705         // preprocess string: converts - -> _
    706         // converts <space>: word1 word2 -> word1Word2
    707         String newType = StringUtils.implementJavaNaming(type);
    708
    709         String iriString;
    710         if (docIRI.toString().endsWith("/") || docIRI.toString().endsWith("#")) {
    711             iriString = docIRI.toString() + newType;
    712         } else {
    713             iriString = docIRI.toString() + "#" + newType;
    714         }
    715
    716         if (addId) {
    717             iriString = iriString + "_" + Integer.toString(nodeId);
    718         }
    719
    720         Resource node = RDFUtils.iri(iriString);
    721         if (addId) {
    722             nodeId++;
    723         }
    724         return node;
    725     }
    726
    727     /**
    728      * Convert string to either IRI or Literal.
    729      *
    730      * If string value expresses valid IRI than {@link IRI} is created. Otherwise method creates simple {@link Literal}
    731      * xsd:string.
    732      *
    733      * @param inString
    734      *            an input string to manifest as {@link org.eclipse.rdf4j.model.Value}
    735      *
    736      * @return either {@link IRI} or {@link Literal}.
    737      */
    738     public static Value makeIRI(String inString) {
    739         if (RDFUtils.isAbsoluteIRI(inString)) {
    740             return RDFUtils.iri(inString);
    741         } else {
    742             return RDFUtils.literal(inString);
    743         }
    744     }
    745
    746     public static Value makeIRI() {
    747         BNode bnode = bnode(Integer.toString(nodeId));
    748         nodeId++;
    749         return bnode;
    750     }
    751
    752 }