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.vocab;
19  
20  import org.apache.any23.rdf.RDFUtils;
21  import org.apache.any23.util.DiscoveryUtils;
22  import org.apache.any23.util.StringUtils;
23  import org.eclipse.rdf4j.model.IRI;
24  import org.eclipse.rdf4j.model.vocabulary.RDF;
25  import org.eclipse.rdf4j.model.vocabulary.RDFS;
26  import org.eclipse.rdf4j.rio.RDFFormat;
27  import org.eclipse.rdf4j.rio.RDFHandlerException;
28  import org.eclipse.rdf4j.rio.RDFWriter;
29  import org.eclipse.rdf4j.rio.Rio;
30  
31  import java.io.ByteArrayOutputStream;
32  import java.io.PrintStream;
33  import java.io.UnsupportedEncodingException;
34  import java.lang.reflect.Constructor;
35  import java.util.List;
36  import java.util.Map;
37  
38  /**
39   * This class provides a set of methods for generating <a href="http://www.w3.org/TR/rdf-schema/">RDF Schema</a>.
40   *
41   * @author Michele Mostarda (mostarda@fbk.eu)
42   */
43  public class RDFSchemaUtils {
44  
45      private static final String RDF_XML_SEPARATOR = StringUtils.multiply('=', 100);
46  
47      private RDFSchemaUtils() {
48      }
49  
50      /**
51       * Serializes a vocabulary composed of the given <code>namespace</code>, <code>resources</code> and
52       * <code>properties</code>.
53       *
54       * @param namespace
55       *            vocabulary namespace.
56       * @param classes
57       *            list of classes.
58       * @param properties
59       *            list of properties.
60       * @param comments
61       *            map of resource comments.
62       * @param writer
63       *            writer to print out the RDF Schema triples.
64       * 
65       * @throws RDFHandlerException
66       *             if there is an error handling the RDF
67       */
68      public static void serializeVocabulary(IRI namespace, IRI[] classes, IRI[] properties, Map<IRI, String> comments,
69              RDFWriter writer) {
70          writer.startRDF();
71          for (IRI clazz : classes) {
72              writer.handleStatement(RDFUtils.quad(clazz, RDF.TYPE, RDFS.CLASS, namespace));
73              writer.handleStatement(RDFUtils.quad(clazz, RDFS.MEMBER, namespace, namespace));
74              final String comment = comments.get(clazz);
75              if (comment != null)
76                  writer.handleStatement(RDFUtils.quad(clazz, RDFS.COMMENT, RDFUtils.literal(comment), namespace));
77          }
78          for (IRI property : properties) {
79              writer.handleStatement(RDFUtils.quad(property, RDF.TYPE, RDF.PROPERTY, namespace));
80              writer.handleStatement(RDFUtils.quad(property, RDFS.MEMBER, namespace, namespace));
81              final String comment = comments.get(property);
82              if (comment != null)
83                  writer.handleStatement(RDFUtils.quad(property, RDFS.COMMENT, RDFUtils.literal(comment), namespace));
84          }
85          writer.endRDF();
86      }
87  
88      /**
89       * Serializes the given <code>vocabulary</code> to triples over the given <code>writer</code>.
90       *
91       * @param vocabulary
92       *            vocabulary to be serialized.
93       * @param writer
94       *            output writer.
95       * 
96       * @throws RDFHandlerException
97       *             if there is an error handling the RDF
98       */
99      public static void serializeVocabulary(Vocabulary vocabulary, RDFWriter writer) {
100         serializeVocabulary(vocabulary.getNamespace(), vocabulary.getClasses(), vocabulary.getProperties(),
101                 vocabulary.getComments(), writer);
102     }
103 
104     /**
105      * Serializes the given <code>vocabulary</code> to <i>NQuads</i> over the given output stream.
106      *
107      * @param vocabulary
108      *            vocabulary to be serialized.
109      * @param format
110      *            output format for vocabulary.
111      * @param willFollowAnother
112      *            if <code>true</code> another vocab will be printed in the same stream.
113      * @param ps
114      *            output stream.
115      * 
116      * @throws RDFHandlerException
117      *             if there is an error handling the RDF
118      */
119     public static void serializeVocabulary(Vocabulary vocabulary, RDFFormat format, boolean willFollowAnother,
120             PrintStream ps) {
121         final RDFWriter rdfWriter;
122         if (format == RDFFormat.RDFXML) {
123             rdfWriter = Rio.createWriter(RDFFormat.RDFXML, ps);
124             if (willFollowAnother)
125                 ps.print("\n");
126             ps.print(RDF_XML_SEPARATOR);
127             ps.print("\n");
128         } else {
129             rdfWriter = Rio.createWriter(format, ps);
130         }
131         serializeVocabulary(vocabulary, rdfWriter);
132     }
133 
134     /**
135      * Serialized the given <code>vocabulary</code> to <i>NQuads</i> and return them as string.
136      *
137      * @param vocabulary
138      *            vocabulary to be serialized.
139      * @param format
140      *            output format for vocabulary.
141      * 
142      * @return string contained serialization.
143      * 
144      * @throws RDFHandlerException
145      *             if there is an error handling the RDF
146      */
147     public static String serializeVocabulary(Vocabulary vocabulary, RDFFormat format) {
148         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
149         PrintStream ps;
150         try {
151             ps = new PrintStream(baos, true, "UTF-8");
152         } catch (UnsupportedEncodingException e1) {
153             throw new RuntimeException("UTF-8 encoding error when serializing the vocabulary to NQuads.", e1);
154         }
155         serializeVocabulary(vocabulary, format, false, ps);
156         ps.close();
157         try {
158             return baos.toString("UTF-8");
159         } catch (UnsupportedEncodingException e) {
160             throw new RuntimeException("Error writing ByteArrayOutputStream to String with \"UTF-8\" encoding!");
161         }
162     }
163 
164     /**
165      * Serializes all the vocabularies to <i>NQuads</i> over the given output stream.
166      *
167      * @param format
168      *            output format for vocabularies.
169      * @param ps
170      *            output print stream.
171      */
172     public static void serializeVocabularies(RDFFormat format, PrintStream ps) {
173         final Class<Vocabulary> vocabularyClass = Vocabulary.class;
174         @SuppressWarnings("rawtypes")
175         final List<Class> vocabularies = DiscoveryUtils.getClassesInPackage(vocabularyClass.getPackage().getName(),
176                 vocabularyClass);
177         int currentIndex = 0;
178         for (Class<?> vocabClazz : vocabularies) {
179             final Vocabulary instance;
180             try {
181                 final Constructor<?> constructor = vocabClazz.getDeclaredConstructor();
182                 constructor.trySetAccessible();
183                 instance = (Vocabulary) constructor.newInstance();
184             } catch (Exception e) {
185                 throw new RuntimeException("Error while instantiating vocabulary class " + vocabClazz, e);
186             }
187             try {
188                 serializeVocabulary(instance, format, currentIndex < vocabularies.size() - 2, ps);
189             } catch (RDFHandlerException rdfhe) {
190                 throw new RuntimeException("Error while serializing vocabulary.", rdfhe);
191             }
192         }
193     }
194 
195 }