View Javadoc

1   /*
2    wsmo4j - a WSMO API and Reference Implementation
3    Copyright (c) 2005, University of Innsbruck, Austria
4    This library is free software; you can redistribute it and/or modify it under
5    the terms of the GNU Lesser General Public License as published by the Free
6    Software Foundation; either version 2.1 of the License, or (at your option)
7    any later version.
8    This library is distributed in the hope that it will be useful, but WITHOUT
9    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10   FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11   details.
12   You should have received a copy of the GNU Lesser General Public License along
13   with this library; if not, write to the Free Software Foundation, Inc.,
14   59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15   */
16  package org.deri.wsmo4j.io.parser.rdf;
17  
18  import java.io.*;
19  import java.util.*;
20  
21  import org.openrdf.model.*;
22  import org.openrdf.model.impl.GraphImpl;
23  import org.openrdf.rio.*;
24  import org.openrdf.rio.ntriples.NTriplesParser;
25  import org.openrdf.rio.rdfxml.RdfXmlParser;
26  import org.openrdf.rio.turtle.TurtleParser;
27  import org.openrdf.sesame.repository.local.LocalRepository;
28  import org.openrdf.vocabulary.RDFS;
29  import org.wsmo.common.TopEntity;
30  import org.wsmo.common.exception.*;
31  import org.wsmo.factory.*;
32  import org.wsmo.wsml.ParserException;
33  import org.wsmo.wsml.Parser;
34  
35  /**
36   * This class parses RDF files and returns an WSML TopEntity.
37   * For parsing, the openrdf rio parser is used.
38   *
39   * <pre>
40   *  Created on May 02, 2006
41   *  Committed by $Author: nathaliest $
42   *  $Source$
43   * </pre>
44   *
45   * @see org.wsmo.wsml.RDFParser
46   * @see org.openrdf.rio.rdfxml.RdfXmlParser
47   * @author nathalie.steinmetz@deri.org
48   * @version $Revision: 2644 $ $Date: 2008-08-08 02:20:48 +0300 (Fri, 08 Aug 2008) $
49   */
50  public class RDFParserImpl implements Parser {
51  
52  	private static final String OLD_RDFS = "http://www.w3.org/TR/1999/PR-rdf-schema-19990303#";
53  
54      private String properties = null;
55      
56      private String labels = null;
57  	
58      /* RDF_PROPERTIES is put into the parsers property map to indicate whether
59       * the properties shall be translated to concept attributes or to relations. 
60       * This decision also decides whether:
61       * - subProperties are translated to subRelations or to axioms.
62       * - instances are translated to instances with attribute values or 
63       *   instances with relationInstances.
64       */
65      public static final String RDF_PROPERTIES = "RDF properties";
66      
67      public static final String RDF_PROP_AS_ATTR = "RDF properties as attributes";
68      
69      public static final String RDF_PROP_AS_REL = "RDF properties as relations";
70      
71      /*
72       * The following strings describe different RDF syntaxes that can be parsed
73       */
74      
75      public static final String RDF_SYNTAX = "RDF syntax";
76      public static final String RDF_XML_SYNTAX = "RDF/XML Syntax";
77      
78      public static final String N_TRIPLES_SYNTAX = "N-Triples Syntax";
79      
80      public static final String TURTLE_SYNTAX = "Turtle Syntax";
81      
82      /*
83       * The following parameters describe whether rdfs#label statements are kept as 
84       * such or are transformed to dc#title statements.
85       */
86      public static final String RDFS_LABEL_CHOICE = "RDFS label choice";
87      public static final String RDFS_LABEL = "RDFS label";
88      public static final String DC_TITLE = "DC title";
89      
90      // A specified LocalRepository to be used as storage backend.
91      public static final String LOCAL_REPOSITORY = "Local Repository";
92      
93      private LocalRepository repository = null;
94      
95      // This map collects the rdf file's namespaces.
96      private HashMap <String, String> namespaces = null;
97      
98      // The RdfXmlParser receives a StatementHandler, a ParseErrorListener
99      // and a NamespaceListener.
100     private org.openrdf.rio.Parser parser = null;
101     
102     private RDFStatementHandler handler = null;
103     
104     private RDFParseErrorListener errorListener = null;
105     
106     private RDFNamespaceListener namespaceListener = null;
107   
108     // The RDFExprParser needs different factories to 
109     // build the Wsml objects.
110     private WsmoFactory factory = null;
111     
112     private LogicalExpressionFactory leFactory = null;
113     
114     private DataFactory dataFactory = null;
115     
116     private RDFExprParser rdfParser = null;  
117     
118     // The RDFParseErrorListener fills  lists with warnings and errors
119     private List <RDFParserWarning> warnings = null;
120     
121     private List <RDFParserError> errors = null;
122     
123     private Graph graph = null;
124     
125     public RDFParserImpl(Map map) {
126         Object o = map.get(Factory.WSMO_FACTORY);
127         if (o == null || !(o instanceof WsmoFactory)) {
128             o = Factory.createWsmoFactory(new HashMap <String, Object> ());
129         }
130         factory = (WsmoFactory) o;
131         assert (factory != null);
132 
133         o = map.get(Factory.LE_FACTORY);
134         if (o == null || !(o instanceof LogicalExpressionFactory)) {
135             o = Factory.createLogicalExpressionFactory(new HashMap <String, Object> ());
136         }
137         leFactory = (LogicalExpressionFactory) o;
138         assert (leFactory != null);
139 
140         o = map.get(Factory.DATA_FACTORY);
141         if (o == null || !(o instanceof DataFactory)) {
142             o = Factory.createDataFactory(new HashMap <String, Object> ());
143         }
144         dataFactory = (DataFactory) o;
145         assert (dataFactory != null);
146         
147         o = map.get(RDF_PROPERTIES);
148         if (o == null || !(o.equals(RDF_PROP_AS_ATTR) || o.equals(RDF_PROP_AS_REL))) {
149             // by default, rdf properties are translated to concept attributes
150             o = RDF_PROP_AS_ATTR;
151         }
152         properties = (String) o;
153         assert (properties != null);
154         
155         o = map.get(RDF_SYNTAX);
156         if (o == null || o.equals(RDF_XML_SYNTAX) || !(o.equals(N_TRIPLES_SYNTAX) || 
157         		o.equals(TURTLE_SYNTAX))) {
158         	// by default, the parser parses rdf/xml syntax
159         	parser = new RdfXmlParser();
160         }
161         else if (o == N_TRIPLES_SYNTAX) {
162         	parser = new NTriplesParser();
163         }
164         else if (o == TURTLE_SYNTAX) {
165         	parser = new TurtleParser();
166         }
167         
168         o = map.get(RDFS_LABEL_CHOICE);
169         if (o == null || o.equals(DC_TITLE) || !(o.equals(RDFS_LABEL))) {
170         	// by default, the parser transforms rdfs#label to dc#title
171         	o = DC_TITLE;
172         }
173         else if (o.equals(RDFS_LABEL)) {
174         	o = RDFS_LABEL;
175         }
176         labels = (String) o;
177         assert (labels != null);
178         
179         o = map.get(LOCAL_REPOSITORY);
180         if (o == null || !(o instanceof LocalRepository)) {
181             repository = null;
182         }
183         repository = (LocalRepository) o;
184         
185         warnings = new Vector <RDFParserWarning>();
186         errors = new Vector <RDFParserError>();
187         
188         if (repository == null) {
189             // by default, an in-memory RdfRepository is used as storage backend
190             graph = new GraphImpl();
191         }
192         else {
193             graph = new GraphImpl(repository);
194         }
195         namespaces = new HashMap <String, String> ();
196         handler = new RDFStatementHandler(graph);
197         errorListener = new RDFParseErrorListener(warnings, errors);
198         namespaceListener = new RDFNamespaceListener(namespaces);
199         rdfParser = new RDFExprParser(factory, leFactory, dataFactory, properties, labels, errorListener);
200         parser.setVerifyData(true);
201         parser.setStopAtFirstError(false);
202         parser.setParseErrorListener(errorListener);
203         parser.setNamespaceListener(namespaceListener);  
204         parser.setStatementHandler(handler);
205     }
206     
207     /*
208      * This is the parse method of the RdfXmlParser. This parser operates 
209      * directly on the SAX events generated by a SAX-enabled XML parser. 
210      * The supplied baseUri is used to resolve any relative URI references.
211      * @param inputStream The input stream to read from
212      * @param uri baseUri
213      */
214     private void parse(Reader src, String uri) throws IOException, ParserException  {
215         if (uri == null) {
216             uri = "http://www.example.org#";
217         }
218         Reader result = checkForOldNS(src);
219         if (result != null) {
220         	src = result;
221         }
222         // Parse the data from inputStream, resolving any relative
223         // URIs against http://www.w3.org/1999/02/22-rdf-syntax-ns#   
224         try {
225             parser.parse(src, uri);
226         } catch (StatementHandlerException e) {
227             throw new ParserException(e.getMessage(), e.getCause());
228         } catch(ParseException e) {
229             throw new ParserException(e.getMessage(), e.getCause());
230         }
231         try {
232             rdfParser.rdf2Wsml(graph, namespaces);
233         } catch (GraphException e) {
234             throw new ParserException(e.getMessage(), e.getCause());
235         } catch (SynchronisationException e) {
236             throw new ParserException(e.getMessage(), e.getCause());
237         } catch (InvalidModelException e) {
238             throw new ParserException(e.getMessage(), e.getCause());
239         } catch (ParserException e) {
240             throw new ParserException(e.getMessage(), e.getCause());
241         }
242     }
243 
244     /**
245      * 
246      * @throws IOException 
247      * @throws ParserException 
248      * @throws ParseException
249      * @see org.wsmo.wsml.Parser#parse(java.io.Reader)
250      */
251     public TopEntity[] parse(Reader src) throws IOException, ParserException, InvalidModelException{
252         parse(src, "");
253         TopEntity[] te = {rdfParser.getOntology()};
254         return te;
255     }
256 
257     /**
258      * 
259      * @see org.wsmo.wsml.Parser#parse(java.io.Reader, java.util.Map)
260      */
261     public TopEntity[] parse(Reader src, Map options) throws IOException, ParserException, InvalidModelException {
262         throw new UnsupportedOperationException("Use method parse(Reader) instead!");
263     }
264 
265     /**
266      * 
267      * @see org.wsmo.wsml.Parser#parse(java.lang.StringBuffer)
268      */
269     public TopEntity[] parse(StringBuffer src) throws ParserException, InvalidModelException {
270         try {
271             return parse(new StringReader(src.toString()));
272         } catch (IOException e) {
273             // should never happens
274             throw new RuntimeException("I/O error occured!", e);
275         }
276     }
277 
278     /**
279      * 
280      * @see org.wsmo.wsml.Parser#parse(java.lang.StringBuffer, java.util.Map)
281      */
282     public TopEntity[] parse(StringBuffer src, Map options) throws ParserException, InvalidModelException {
283         throw new UnsupportedOperationException("Use method parse(StringBuffer) instead!");
284     }
285 
286     /**
287      * 
288      * @see org.wsmo.wsml.Parser#listKeywords()
289      */
290     public Set <String> listKeywords() {
291         return null;
292     }
293     
294     /**
295      * This method returns a List containing warnings that 
296      * occured during the RDF parsing and the transformation 
297      * to the WSMO object model.
298      * <br />
299      * Some warnings don't simply refer to one "error", but represent 
300      * a "kind" of errors. Each warning contains a Set of triples 
301      * that belong to that warning. 
302      * 
303      * @return List of collected warnings
304      */
305     public List <Object> getWarnings() {
306         return new ArrayList <Object>(warnings);
307     }
308     
309     /**
310      * This method returns a List containing errors that occured during 
311      * the RDF parsing and the transformation to the WSMO object model.
312      * 
313      * @return List of collected errors
314      */
315     public List <Object> getErrors() {
316         return new ArrayList <Object>(errors);
317     }
318     
319     private Reader checkForOldNS(Reader in) {
320     	BufferedReader reader = new BufferedReader(in);
321         Reader out = null;
322     	String line;
323     	String text = "";
324         try {
325         	while ((line = reader.readLine()) != null) {
326         		text = text + line + "\n";
327         	}
328             reader.close();
329         } catch (IOException e) {
330         	return null;
331         }
332         if (text.indexOf(OLD_RDFS) != -1) {
333         	text = text.replace(OLD_RDFS, RDFS.NAMESPACE);
334         }
335         out = new StringReader(text);
336         return out;
337     }
338     
339 }
340 /*
341  * $Log$
342  * Revision 1.8  2007/04/20 13:30:44  nathaliest
343  * added parsing of rdf N-Triple and Turtle syntaxes
344  *
345  * Revision 1.7  2007/04/02 12:13:23  morcen
346  * Generics support added to wsmo-api, wsmo4j and wsmo-test
347  *
348  * Revision 1.6  2007/03/15 16:38:49  nathaliest
349  * fixed bug in rdfParser parse(StringBuffer buf) method
350  *
351  * Revision 1.5  2006/11/30 13:46:44  nathaliest
352  * fixed a bug concerning the call of the parse method with a stringbuffer as parameter
353  *
354  * Revision 1.4  2006/11/16 11:05:22  nathaliest
355  * replace old rdf-schema namespace with new one
356  *
357  * Revision 1.3  2006/11/16 09:53:28  nathaliest
358  * added RDFParserError
359  *
360  * Revision 1.2  2006/11/10 11:08:54  nathaliest
361  * added getWarnings() and getErrors() methods to Parser interface, implemented them in the rdf parser implementation and added UnsupportedOperationException to the other parser implementations
362  *
363  * Revision 1.1  2006/05/03 13:32:49  nathaliest
364  * adding RDF parser
365  *
366  * 
367  */