1 5 6 package com.hp.hpl.jena.n3; 7 8 import antlr.collections.AST ; 9 import java.util.* ; 10 import com.hp.hpl.jena.rdf.model.* ; 11 import com.hp.hpl.jena.shared.*; 12 13 import com.hp.hpl.jena.vocabulary.*; 14 import org.apache.commons.logging.Log; 15 import org.apache.commons.logging.LogFactory; 16 17 21 public class N3toRDF implements N3ParserEventHandler 22 { 23 protected static Log logger = LogFactory.getLog( N3toRDF.class ); 24 25 Model model ; 26 27 Map resourceRef = new HashMap() ; 29 Map propertyRef = new HashMap() ; 31 32 Map myPrefixMapping = new HashMap() ; 34 35 boolean allowPropertySymbols = true ; 36 boolean allowKeywordA = true ; 37 38 40 static final String NS_rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#" ; 41 static final String NS_rdfs = "http://www.w3.org/2000/01/rdf-schema#" ; 42 43 static final String NS_W3_log = "http://www.w3.org/2000/10/swap/log#" ; 44 static final String LOG_IMPLIES = NS_W3_log+"implies" ; 45 static final String LOG_MEANS = NS_W3_log+"means" ; 46 47 static final String XMLLiteralURI = "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral" ; 48 49 private String base = null ; 50 private String basedir = null ; 51 final String anonPrefix = "_" ; 52 53 N3toRDF() {} 54 55 public void setBase(String str) 56 { 57 if ( str == null ) 58 { 59 base = null ; 60 basedir = null ; 61 return ; 62 } 63 base = str ; 64 if ( base.startsWith("file:")) 65 { 66 int i = base.lastIndexOf('/') ; 67 if ( i >= 0 ) 68 basedir = base.substring(0,i+1) ; 70 else 71 basedir = base ; 72 } 73 else 74 basedir = base ; 75 } 76 77 public void setModel(Model model) 78 { 79 this.model = model ; 80 } 81 82 90 91 public void startDocument() { } 92 public void endDocument() { } 93 94 public void error(Exception ex, String message) { throw new N3Exception(message) ; } 96 public void error(String message) { error(null, message) ; } 97 98 public void warning(Exception ex, String message) { logger.warn(message, ex) ; } 99 public void warning(String message) { logger.warn(message) ; } 100 101 public void deprecated(Exception ex, String message) { throw new N3Exception(message) ; } 102 public void deprecated(String message) { deprecated(null, message) ; } 103 104 public void startFormula(int line, String context) 105 { 106 error("Line "+line+": N3toRDF: All statements are asserted - no formulae in RDF") ; 107 } 108 109 public void endFormula(int line, String context) {} 110 111 public void directive(int line, AST directive, AST[] args, String context) 112 { 113 if ( directive.getType() == N3Parser.AT_PREFIX ) 114 { 115 if ( args[0].getType() != N3Parser.QNAME ) 117 { 118 error("Line "+line+": N3toRDF: Prefix directive does not start with a prefix! "+args[0].getText()+ "["+N3Parser.getTokenNames()[args[0].getType()]+"]") ; 119 return ; 120 } 121 122 String prefix = args[0].getText() ; 123 if ( prefix.endsWith(":") ) 124 prefix = prefix.substring(0,prefix.length()-1) ; 125 126 if ( args[1].getType() != N3Parser.URIREF ) 127 { 128 error("Line "+line+": N3toRDF: Prefix directive does not supply a URIref! "+args[1].getText()) ; 129 return ; 130 } 131 132 String uriref = args[1].getText() ; 133 uriref = expandURIRef(uriref, line) ; 134 135 if ( uriref == null ) 136 error("Line "+line+": N3toRDF: Relative URI can't be resolved in in @prefix directive") ; 137 138 setPrefixMapping(model, prefix, uriref) ; 139 return ; 140 } 141 142 warning("Line "+line+": N3toRDF: Directive not recongized and ignored: "+directive.getText()) ; 143 return ; 144 } 145 146 147 public void quad(int line, AST subj, AST prop, AST obj, String context) 148 { 149 151 if ( context != null ) 152 error("Line "+line+": N3toRDF: All statement are asserted - no formulae") ; 153 154 try 155 { 156 162 167 170 int pType = prop.getType(); 171 String propStr = prop.getText(); 172 Property pNode = null ; 173 174 switch (pType) 175 { 176 case N3Parser.ARROW_R : 177 if ( ! allowPropertySymbols ) 178 error("Line "+line+": N3toRDF: Propertry symbol '=>' not allowed") ; 179 propStr = LOG_IMPLIES ; 180 break; 181 case N3Parser.ARROW_MEANS : 182 if ( ! allowPropertySymbols ) 183 error("Line "+line+": N3toRDF: Propertry symbol '<=>' not allowed") ; 184 propStr = LOG_MEANS ; 185 break; 186 case N3Parser.ARROW_L : 187 if ( ! allowPropertySymbols ) 188 error("Line "+line+": N3toRDF: Propertry symbol '<=' not allowed") ; 189 propStr = LOG_IMPLIES ; 191 AST tmp = obj; obj = subj; subj = tmp; 192 break; 193 case N3Parser.EQUAL : 194 if ( ! allowPropertySymbols ) 197 error("Line "+line+": N3toRDF: Propertry symbol '=' not allowed") ; 198 pNode = OWL.sameAs ; 199 break; 200 case N3Parser.KW_A : 201 if ( ! allowKeywordA ) 202 error("Line "+line+": N3toRDF: Propertry symbol 'a' not allowed") ; 203 pNode = RDF.type ; 204 break ; 205 case N3Parser.QNAME: 206 207 if ( prop.getText().startsWith("_:") ) 208 error("Line "+line+": N3toRDF: Can't have properties with labelled bNodes in RDF") ; 209 210 String uriref = expandPrefix(model, propStr) ; 211 if ( uriref == propStr ) 212 { 213 error("Line "+line+": N3toRDF: Undefined qname namespace: " + propStr); 215 return ; 216 } 217 pNode = model.createProperty(uriref) ; 218 break ; 219 case N3Parser.URIREF: 220 propStr = expandURIRef(propStr, line) ; 221 break ; 222 case N3Parser.TK_LIST_FIRST: 223 pNode = RDF.first ; 224 break ; 225 case N3Parser.TK_LIST_REST: 226 pNode = RDF.rest ; 227 break ; 228 case N3Parser.ANON: 231 error("Line "+line+": N3toRDF: Can't have anon. properties in RDF") ; 232 break ; 233 default: 234 error("Line "+line+": N3toRDF: Shouldn't see "+ 235 N3EventPrinter.formatSlot(prop)+ 236 " at this point!") ; 237 break ; 238 } 239 240 if ( pNode == null ) 242 pNode = model.createProperty(propStr) ; 243 else 244 propStr = pNode.getURI() ; 245 246 RDFNode sNode = createNode(line, subj); 247 if ( sNode instanceof Literal ) 249 error("Line "+line+": N3toRDF: Subject can't be a literal: " +subj.getText()) ; 250 251 RDFNode oNode = createNode(line, obj); 252 253 Statement stmt = model.createStatement((Resource)sNode, pNode, oNode) ; 254 model.add(stmt) ; 255 } 256 catch (JenaException rdfEx) 257 { 258 error("Line "+line+": JenaException: " + rdfEx); 259 } 260 } 261 262 private Map bNodeMap = new HashMap() ; 263 264 private RDFNode createNode(int line, AST thing) 265 { 266 String text = thing.getText() ; 269 switch (thing.getType()) 270 { 271 case N3Parser.NUMBER : 272 Resource xsdType = XSD.integer ; 273 if ( text.indexOf('.') >= 0 ) 274 xsdType = XSD.xdouble ; 276 if ( text.indexOf('e') >= 0 || text.indexOf('E') >= 0 ) 277 xsdType = XSD.xdouble ; 278 return model.createTypedLiteral(text, xsdType.getURI()); 279 280 case N3Parser.LITERAL : 281 284 AST a1 = thing.getNextSibling() ; 285 AST a2 = (a1==null?null:a1.getNextSibling()) ; 286 AST datatype = null ; 287 AST lang = null ; 288 289 if ( a2 != null ) 290 { 291 if ( a2.getType() == N3Parser.DATATYPE ) 292 datatype = a2.getFirstChild() ; 293 else 294 lang = a2 ; 295 } 296 if ( a1 != null ) 298 { 299 if ( a1.getType() == N3Parser.DATATYPE ) 300 datatype = a1.getFirstChild() ; 301 else 302 lang = a1 ; 303 } 304 305 String langTag = (lang!=null)?lang.getText().substring(1):null ; 307 308 if ( datatype == null ) 309 return model.createLiteral(text, langTag) ; 310 311 String typeURI = datatype.getText(); 313 314 if ( datatype.getType() != N3Parser.QNAME && 315 datatype.getType() != N3Parser.URIREF ) 316 { 317 error("Line "+ line+ ": N3toRDF: Must use URIref or QName datatype URI: " 318 + text+ "^^"+ typeURI+"("+N3Parser.getTokenNames()[datatype.getType()]+")"); 319 return model.createLiteral("Illegal literal: " + text + "^^" + typeURI); 320 321 } 322 323 325 if ( datatype.getType() == N3Parser.QNAME ) 326 { 327 if (typeURI.startsWith("_:") || typeURI.startsWith("=:")) 328 { 329 error("Line "+ line+ ": N3toRDF: Can't use bNode for datatype URI: " 330 + text+ "^^"+ typeURI); 331 return model.createLiteral("Illegal literal: " + text + "^^" + typeURI); 332 } 333 334 String typeURI2 = expandPrefix(model, typeURI) ; 335 if ( typeURI2 == typeURI ) 336 { 337 error("Line "+line+": N3toRDF: Undefined qname namespace in datatype: " + typeURI); 338 } 339 340 typeURI = typeURI2 ; 341 } 342 343 typeURI = expandURIRef(typeURI, line); 344 return model.createTypedLiteral(text, typeURI) ; 346 347 case N3Parser.QNAME : 348 if ( text.startsWith("_:") && ( model.getNsPrefixURI("_") == null ) ) 351 { 352 if ( ! bNodeMap.containsKey(text) ) 353 bNodeMap.put(text, model.createResource()) ; 354 return (Resource)bNodeMap.get(text) ; 355 } 356 357 String uriref = expandPrefix(model, text) ; 358 if ( uriref == text ) 359 { 360 error("Line "+line+": N3toRDF: Undefined qname namespace: " + text); 361 return null ; 362 } 363 return model.createResource(expandURIRef(uriref, line)) ; 364 365 case N3Parser.URIREF : 367 return model.createResource(expandURIRef(text, line)) ; 368 369 case N3Parser.TK_LIST_NIL: 371 return RDF.nil ; 372 case N3Parser.TK_LIST: 373 return RDF.List ; 374 375 case N3Parser.ANON: if ( ! bNodeMap.containsKey(text) ) 377 bNodeMap.put(text, model.createResource()) ; 378 return (Resource)bNodeMap.get(text) ; 379 380 case N3Parser.UVAR: 381 error("Line "+line+": N3toRDF: Can't map variables to RDF: "+text) ; 382 break ; 383 384 default: 385 error("Line "+line+": N3toRDF: Can't map to a resource or literal: "+AntlrUtils.ast(thing)) ; 386 break ; 387 } 388 return null ; 389 } 390 391 private String expandURIRef(String text, int line) 393 { 394 if ( text.equals("") && base == null ) 396 error("Line "+line+": N3toRDF: Relative URI but no base for <>") ; 397 398 if ( text.equals("#") && base == null ) 399 error("Line "+line+": N3toRDF: Relative URI but no base for <#>") ; 400 401 if ( text.equals("") ) 402 return base ; 404 405 if ( text.equals("#") ) 406 return base+"#" ; 408 409 if ( base != null && ! hasURIscheme(text) ) 410 { 411 if ( ! base.startsWith("file:")) 412 { 413 if ( text.startsWith("#")) 414 return base+text ; 415 else 416 return base+"#"+text ; 417 } 418 419 if ( text.startsWith("#") ) 421 return base + text ; 422 if ( text.startsWith("/") ) 423 return "file:" + text ; 424 else 425 return basedir + text ; 426 } 427 428 return text; 429 } 430 431 private boolean hasURIscheme(String text) 432 { 433 for ( int i = 0 ; i < text.length() ; i++ ) 434 { 435 char ch = text.charAt(i) ; 436 if ( ch == ':' ) 437 return true ; 438 if ( ( ch >= 'a' && ch <= 'z' ) || 439 ( ch >= 'A' && ch <= 'Z' ) ) 440 continue ; 441 return false ; 442 } 443 return false ; 444 } 445 446 private void setPrefixMapping(Model m, String prefix, String uriref) 447 { 448 try { model.setNsPrefix(prefix, uriref); } 449 catch (PrefixMapping.IllegalPrefixException ex) 450 { 451 warning("Prefix mapping '" + prefix + "' illegal: used but not recorded in model"); 452 } 453 myPrefixMapping.put(prefix, uriref); 454 } 455 456 private String expandPrefix(Model m, String prefixed) 457 { 458 int colon = prefixed.indexOf( ':' ); 461 if (colon < 0) 462 return prefixed; 463 else 464 { 465 String prefix = prefixed.substring( 0, colon ); 466 String uri = (String ) myPrefixMapping.get( prefix ); 467 if ( uri == null ) 468 return prefixed ; 469 return uri + prefixed.substring( colon + 1 ) ; 470 } 471 } 476 } 477 478 504 | Popular Tags |