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}.
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 }