001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.marshall.jena; 018 019import static org.apache.juneau.commons.utils.Shorts.*; 020import static org.apache.juneau.commons.utils.SystemUtils.*; 021 022import java.util.*; 023import java.util.concurrent.*; 024 025import org.apache.juneau.commons.bean.*; 026import org.apache.juneau.commons.collections.*; 027import org.apache.juneau.marshall.*; 028import org.apache.juneau.marshall.parser.*; 029import org.apache.juneau.marshall.xml.*; 030 031/** 032 * Parses RDF into POJOs. 033 * 034 * <h5 class='topic'>Behavior-specific subclasses</h5> 035 * <p> 036 * The following direct subclasses are provided for language-specific parsers: 037 * <ul class='spaced-list'> 038 * <li> 039 * {@link RdfXmlParser} - RDF/XML and RDF/XML-ABBREV. 040 * <li> 041 * {@link NTripleParser} - N-TRIPLE. 042 * <li> 043 * {@link TurtleParser} - TURTLE. 044 * <li> 045 * {@link N3Parser} - N3. 046 * </ul> 047 * 048 * <h5 class='section'>Notes:</h5><ul> 049 * <li class='note'>This class is thread safe and reusable. 050 * </ul> 051 * 052 * <h5 class='section'>See Also:</h5><ul> 053 * <li class='link'>{doc jmr.RdfDetails} 054 055 * </ul> 056 */ 057@SuppressWarnings({ 058 "java:S100", // RDF method names (getRdfXml, isXmlLang, etc.) use domain-specific casing 059 "java:S110", // Deep inheritance inherent to the RDF parser hierarchy. 060 "java:S1192" // Duplicated literals (argument/property names) read more clearly inline than as constants 061}) 062public class RdfParser extends ReaderParser implements RdfMetaProvider { 063 064 /** 065 * Builder class. 066 */ 067 @SuppressWarnings({ 068 "java:S119" // 'SELF' (CRTP self-type) is intentional and clearer than a single-letter name. 069 }) 070 public abstract static class Builder<SELF extends Builder<SELF>> extends ReaderParser.Builder<SELF> { 071 072 private static final Cache<HashKey,RdfParser> CACHE = Cache.of(HashKey.class, RdfParser.class).build(); 073 074 private static final Namespace DEFAULT_JUNEAU_NS = Namespace.of("j", "http://www.apache.org/juneau/"); 075 private static final Namespace DEFAULT_JUNEAUBP_NS = Namespace.of("jp", "http://www.apache.org/juneaubp/"); 076 077 boolean trimWhitespace; 078 boolean looseCollections; 079 String language; 080 Namespace juneauNs; 081 Namespace juneauBpNs; 082 RdfCollectionFormat collectionFormat; 083 Map<String,Object> jenaSettings = new TreeMap<>(); 084 085 /** 086 * Constructor, default settings. 087 */ 088 protected Builder() { 089 super(); 090 trimWhitespace = env("Rdf.trimWhitespace", false); 091 looseCollections = env("Rdf.looseCollections", false); 092 language = env("Rdf.language", "RDF/XML-ABBREV"); 093 collectionFormat = env("Rdf.collectionFormat", RdfCollectionFormat.DEFAULT); 094 juneauNs = DEFAULT_JUNEAU_NS; 095 juneauBpNs = DEFAULT_JUNEAUBP_NS; 096 jenaSettings = new TreeMap<>(); 097 } 098 099 /** 100 * Copy constructor. 101 * 102 * @param copyFrom The builder to copy from. 103 * <br>Cannot be <jk>null</jk>. 104 */ 105 protected Builder(Builder<?> copyFrom) { 106 super(reqnn("copyFrom", copyFrom)); 107 collectionFormat = copyFrom.collectionFormat; 108 juneauBpNs = copyFrom.juneauBpNs; 109 juneauNs = copyFrom.juneauNs; 110 language = copyFrom.language; 111 looseCollections = copyFrom.looseCollections; 112 trimWhitespace = copyFrom.trimWhitespace; 113 jenaSettings = new TreeMap<>(copyFrom.jenaSettings); 114 } 115 116 /** 117 * Copy constructor. 118 * 119 * @param copyFrom The bean to copy from. 120 * <br>Cannot be <jk>null</jk>. 121 */ 122 protected Builder(RdfParser copyFrom) { 123 super(reqnn("copyFrom", copyFrom)); 124 collectionFormat = copyFrom.collectionFormat; 125 juneauBpNs = copyFrom.juneauBpNs; 126 juneauNs = copyFrom.juneauNs; 127 language = copyFrom.language; 128 looseCollections = copyFrom.looseCollections; 129 trimWhitespace = copyFrom.trimWhitespace; 130 jenaSettings = new TreeMap<>(copyFrom.jenaSettings); 131 } 132 133 @Override /* Overridden from Context.Builder<?> */ 134 public RdfParser build() { 135 return cache(CACHE).build(RdfParser.class); 136 } 137 138 /** 139 * RDF format for representing collections and arrays. 140 * 141 * <ul class='values spaced-list'> 142 * <li> 143 * <js>"DEFAULT"</js> - Default format. The default is an RDF Sequence container. 144 * <li> 145 * <js>"SEQ"</js> - RDF Sequence container. 146 * <li> 147 * <js>"BAG"</js> - RDF Bag container. 148 * <li> 149 * <js>"LIST"</js> - RDF List container. 150 * <li> 151 * <js>"MULTI_VALUED"</js> - Multi-valued properties. 152 * </ul> 153 * 154 * @param value The new value for this property. 155 * <br>Cannot be <jk>null</jk>. 156 * @return This object. 157 */ 158 public SELF collectionFormat(RdfCollectionFormat value) { 159 collectionFormat = reqnn("value", value); 160 return self(); 161 } 162 163 @Override /* Overridden from Context.Builder<?> */ 164 public abstract SELF copy(); 165 166 @Override /* Overridden from Context.Builder<?> */ 167 public HashKey hashKey() { 168 // @formatter:off 169 return HashKey.of( 170 super.hashKey(), 171 trimWhitespace, 172 looseCollections, 173 language, 174 collectionFormat, 175 juneauNs, 176 juneauBpNs, 177 jenaSettings 178 ); 179 // @formatter:on 180 } 181 182 /** 183 * Default XML namespace for bean properties. 184 * 185 * @param value 186 * The new value for this property. 187 * <br>The default is <code>{j:<js>'http://www.apache.org/juneaubp/'</js>}</code>. 188 * <br>Cannot be <jk>null</jk>. 189 * @return This object. 190 */ 191 public SELF juneauBpNs(Namespace value) { 192 juneauBpNs = reqnn("value", value); 193 return self(); 194 } 195 196 /** 197 * XML namespace for Juneau properties. 198 * 199 * @param value 200 * The new value for this property. 201 * <br>The default is <code>{j:<js>'http://www.apache.org/juneau/'</js>}</code>. 202 * <br>Cannot be <jk>null</jk>. 203 * @return This object. 204 */ 205 public SELF juneauNs(Namespace value) { 206 juneauNs = reqnn("value", value); 207 return self(); 208 } 209 210 /** 211 * RDF language. 212 * 213 * <p> 214 * Can be any of the following: 215 * <ul class='spaced-list'> 216 * <li> 217 * <js>"RDF/XML"</js> 218 * <li> 219 * <js>"RDF/XML-ABBREV"</js> (default) 220 * <li> 221 * <js>"N-TRIPLE"</js> 222 * <li> 223 * <js>"N3"</js> - General name for the N3 writer. 224 * Will make a decision on exactly which writer to use (pretty writer, plain writer or simple writer) when 225 * created. 226 * Default is the pretty writer but can be overridden with system property 227 * <c>org.apache.jena.n3.N3JenaWriter.writer</c>. 228 * <li> 229 * <js>"N3-PP"</js> - Name of the N3 pretty writer. 230 * The pretty writer uses a frame-like layout, with prefixing, clustering like properties and embedding 231 * one-referenced bNodes. 232 * <li> 233 * <js>"N3-PLAIN"</js> - Name of the N3 plain writer. 234 * The plain writer writes records by subject. 235 * <li> 236 * <js>"N3-TRIPLES"</js> - Name of the N3 triples writer. 237 * This writer writes one line per statement, like N-Triples, but does N3-style prefixing. 238 * <li> 239 * <js>"TURTLE"</js> - Turtle writer. 240 * http://www.dajobe.org/2004/01/turtle/ 241 * </ul> 242 * 243 * <h5 class='section'>See Also:</h5><ul> 244 * <li class='jm'>{@link RdfParser.Builder#n3()} 245 * <li class='jm'>{@link RdfParser.Builder#ntriple()} 246 * <li class='jm'>{@link RdfParser.Builder#turtle()} 247 * <li class='jm'>{@link RdfParser.Builder#xml()} 248 * </ul> 249 * 250 * @param value The new value for this property. 251 * <br>Cannot be <jk>null</jk>. 252 * @return This object. 253 */ 254 public SELF language(String value) { 255 language = reqnn("value", value); 256 return self(); 257 } 258 259 /** 260 * Collections should be serialized and parsed as loose collections. 261 * 262 * <p> 263 * When specified, collections of resources are handled as loose collections of resources in RDF instead of 264 * resources that are children of an RDF collection (e.g. Sequence, Bag). 265 * 266 * <p> 267 * Note that this setting is specialized for RDF syntax, and is incompatible with the concept of 268 * losslessly representing POJO models, since the tree structure of these POJO models are lost 269 * when serialized as loose collections. 270 * 271 * <p> 272 * This setting is typically only useful if the beans being parsed into do not have a bean property 273 * annotated with {@link Rdf#beanUri @Rdf(beanUri=true)}. 274 * 275 * <h5 class='section'>Example:</h5> 276 * <p class='bjava'> 277 * WriterSerializer <jv>serializer</jv> = RdfSerializer 278 * .<jsm>create</jsm>() 279 * .xmlabbrev() 280 * .looseCollections() 281 * .build(); 282 * 283 * ReaderParser <jv>parser</jv> = RdfParser 284 * .<jsm>create</jsm>() 285 * .xml() 286 * .looseCollections() 287 * .build(); 288 * 289 * List<MyBean> <jv>list</jv> = <jsm>createListOfMyBeans</jsm>(); 290 * 291 * <jc>// Serialize to RDF/XML as loose resources</jc> 292 * String <jv>rdfXml</jv> = <jv>serializer</jv>.write(<jv>list</jv>); 293 * 294 * <jc>// Parse back into a Java collection</jc> 295 * <jv>list</jv> = <jv>parser</jv>.read(<jv>rdfXml</jv>, LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>); 296 * 297 * MyBean[] <jv>bean</jv> = <jsm>createArrayOfMyBeans</jsm>(); 298 * 299 * <jc>// Serialize to RDF/XML as loose resources</jc> 300 * <jv>rdfXml</jv> = <jv>serializer</jv>.write(<jv>beans</jv>); 301 * 302 * <jc>// Parse back into a bean array</jc> 303 * <jv>beans</jv> = <jv>parser</jv>.read(<jv>rdfXml</jv>, MyBean[].<jk>class</jk>); 304 * </p> 305 * 306 * @return This object. 307 */ 308 public SELF looseCollections() { 309 return looseCollections(true); 310 } 311 312 /** 313 * Same as {@link #looseCollections()} but explicitly specifies the setting value. 314 * 315 * @param value The new value for this property. 316 * @return This object. 317 */ 318 public SELF looseCollections(boolean value) { 319 looseCollections = value; 320 return self(); 321 } 322 323 /** 324 * RDF language. 325 * 326 * <p> 327 * Shortcut for calling <code>language(<jsf>LANG_N3</jsf>)</code>. 328 * 329 * @return This object. 330 */ 331 public SELF n3() { 332 return language(Constants.LANG_N3); 333 } 334 335 /** 336 * N3/Turtle property: <c>disableAbbrevBaseURI</c>. 337 * 338 * <p> 339 * Controls whether to use abbreviations <c><></c> or <c><#></c>. 340 * 341 * @return This object. 342 */ 343 public SELF n3_disableAbbrevBaseUri() { 344 return n3_disableAbbrevBaseUri(true); 345 } 346 347 /** 348 * N3/Turtle property: <c>disableAbbrevBaseURI</c>. 349 * 350 * <p> 351 * Controls whether to use abbreviations <c><></c> or <c><#></c>. 352 * 353 * @param value 354 * The new value for this setting. 355 * @return This object. 356 */ 357 public SELF n3_disableAbbrevBaseUri(boolean value) { 358 return jena("n3.disableAbbrevBaseUri", value); 359 } 360 361 /** 362 * N3/Turtle property: <c>disableObjectLists</c>. 363 * 364 * <p> 365 * Don't print object lists as comma separated lists. 366 * 367 * @return This object. 368 */ 369 public SELF n3_disableObjectLists() { 370 return n3_disableObjectLists(true); 371 } 372 373 /** 374 * N3/Turtle property: <c>disableObjectLists</c>. 375 * 376 * <p> 377 * Don't print object lists as comma separated lists. 378 * 379 * @param value 380 * The new value for this property. 381 * @return This object. 382 */ 383 public SELF n3_disableObjectLists(boolean value) { 384 return jena("n3.disableObjectLists", value); 385 } 386 387 /** 388 * N3/Turtle property: <c>disableUseDoubles</c>. 389 * 390 * <p> 391 * Disallow the use of doubles as <c>123.456</c>. 392 * 393 * @return This object. 394 */ 395 public SELF n3_disableUseDoubles() { 396 return n3_disableUseDoubles(true); 397 } 398 399 /** 400 * N3/Turtle property: <c>disableUseDoubles</c>. 401 * 402 * <p> 403 * Disallow the use of doubles as <c>123.456</c>. 404 * 405 * @param value 406 * The new value for this setting. 407 * @return This object. 408 */ 409 public SELF n3_disableUseDoubles(boolean value) { 410 return jena("n3.disableUseDoubles", value); 411 } 412 413 /** 414 * N3/Turtle property: <c>disableUsePropertySymbols</c>. 415 * 416 * <p> 417 * Controls whether to use <c>a</c>, <c>=</c> and <c>=></c> in output 418 * 419 * @return This object. 420 */ 421 public SELF n3_disableUsePropertySymbols() { 422 return n3_disableUsePropertySymbols(true); 423 } 424 425 /** 426 * N3/Turtle property: <c>disableUsePropertySymbols</c>. 427 * 428 * <p> 429 * Controls whether to use <c>a</c>, <c>=</c> and <c>=></c> in output 430 * 431 * @param value 432 * The new value for this setting. 433 * @return This object. 434 */ 435 public SELF n3_disableUsePropertySymbols(boolean value) { 436 return jena("n3.disableUsePropertySymbols", value); 437 } 438 439 /** 440 * N3/Turtle property: <c>disableUseTripleQuotedStrings</c>. 441 * 442 * <p> 443 * Disallow the use of <c>"""</c> to delimit long strings. 444 * 445 * @return This object. 446 */ 447 public SELF n3_disableUseTripleQuotedStrings() { 448 return n3_disableUseTripleQuotedStrings(true); 449 } 450 451 /** 452 * N3/Turtle property: <c>disableUseTripleQuotedStrings</c>. 453 * 454 * <p> 455 * Disallow the use of <c>"""</c> to delimit long strings. 456 * 457 * @param value 458 * The new value for this setting. 459 * @return This object. 460 */ 461 public SELF n3_disableUseTripleQuotedStrings(boolean value) { 462 return jena("n3.disableUseTripleQuotedStrings", value); 463 } 464 465 /** 466 * N3/Turtle property: <c>indentProperty</c>. 467 * 468 * <p> 469 * Width to indent properties. 470 * 471 * @param value 472 * The new value for this property. 473 * @return This object. 474 */ 475 public SELF n3_indentProperty(int value) { 476 return jena("n3.indentProperty", value); 477 } 478 479 /** 480 * N3/Turtle property: <c>minGap</c>. 481 * 482 * <p> 483 * Minimum gap between items on a line. 484 * 485 * @param value 486 * The new value for this property. 487 * @return This object. 488 */ 489 public SELF n3_minGap(int value) { 490 return jena("n3.minGap", value); 491 } 492 493 /** 494 * N3/Turtle property: <c>propertyColumn</c>. 495 * 496 * <p> 497 * Width of the property column. 498 * 499 * @param value 500 * The new value for this property. 501 * @return This object. 502 */ 503 public SELF n3_propertyColumn(int value) { 504 return jena("n3.propertyColumn", value); 505 } 506 507 /** 508 * N3/Turtle property: <c>subjectColumn</c>. 509 * 510 * <p> 511 * If the subject is shorter than this value, the first property may go on the same line. 512 * 513 * @param value 514 * The new value for this property. 515 * @return This object. 516 */ 517 public SELF n3_subjectColumn(int value) { 518 return jena("n3.subjectColumn", value); 519 } 520 521 /** 522 * N3/Turtle property: <c>widePropertyLen</c>. 523 * 524 * <p> 525 * Width of the property column. 526 * Must be longer than <c>propertyColumn</c>. 527 * 528 * @param value 529 * The new value for this property. 530 * @return This object. 531 */ 532 public SELF n3_widePropertyLen(int value) { 533 return jena("n3.widePropertyLen", value); 534 } 535 536 /** 537 * RDF language. 538 * 539 * <p> 540 * Shortcut for calling <code>language(<jsf>LANG_NTRIPLE</jsf>)</code>. 541 * 542 * @return This object. 543 */ 544 public SELF ntriple() { 545 return language(Constants.LANG_NTRIPLE); 546 } 547 548 /** 549 * RDF/XML property: <c>allowBadURIs</c>. 550 * 551 * <p> 552 * URIs in the graph are, by default, checked prior to serialization. 553 * 554 * @return This object. 555 */ 556 public SELF rdfxml_allowBadUris() { 557 return rdfxml_allowBadUris(true); 558 } 559 560 /** 561 * RDF/XML property: <c>allowBadURIs</c>. 562 * 563 * <p> 564 * URIs in the graph are, by default, checked prior to serialization. 565 * 566 * @param value 567 * The new value for this property. 568 * @return This object. 569 */ 570 public SELF rdfxml_allowBadUris(boolean value) { 571 return jena("rdfXml.allowBadURIs", value); 572 } 573 574 /** 575 * RDF/XML property: <c>attributeQuoteChar</c>. 576 * 577 * <p> 578 * The XML attribute quote character. 579 * 580 * @param value 581 * The new value for this property. 582 * @return This object. 583 */ 584 public SELF rdfxml_attributeQuoteChar(char value) { 585 return jena("rdfXml.attributeQuoteChar", value); 586 } 587 588 /** 589 * RDF/XML property: <c>blockRules</c>. 590 * 591 * <p> 592 * A list of <c>Resource</c> or a <c>String</c> being a comma separated list of fragment IDs from 593 * {doc http://www.w3.org/TR/rdf-syntax-grammar RDF Syntax Grammar} indicating grammar 594 * rules that will not be used. 595 * 596 * @param value 597 * The new value for this property. 598 * @return This object. 599 */ 600 public SELF rdfxml_blockRules(String value) { 601 return jena("rdfXml.blockRules", value); 602 } 603 604 /** 605 * RDF/XML property: <c>disableShowDoctypeDeclaration</c>. 606 * 607 * <p> 608 * If disabled, an XML doctype declaration isn't included in the output. 609 * This declaration includes a <c>!ENTITY</c> declaration for each prefix mapping in the model, and any 610 * attribute value that starts with the URI of that mapping is written as starting with the corresponding entity 611 * invocation. 612 * 613 * @return This object. 614 */ 615 public SELF rdfxml_disableShowDoctypeDeclaration() { 616 return rdfxml_disableShowDoctypeDeclaration(true); 617 } 618 619 /** 620 * RDF/XML property: <c>disableShowDoctypeDeclaration</c>. 621 * 622 * <p> 623 * If disabled, an XML doctype declaration isn't included in the output. 624 * This declaration includes a <c>!ENTITY</c> declaration for each prefix mapping in the model, and any 625 * attribute value that starts with the URI of that mapping is written as starting with the corresponding entity 626 * invocation. 627 * 628 * @param value 629 * The new value for this property. 630 * @return This object. 631 */ 632 public SELF rdfxml_disableShowDoctypeDeclaration(boolean value) { 633 return jena("rdfXml.disableShowDoctypeDeclaration", value); 634 } 635 636 /** 637 * RDF/XML ARP property: <c>embedding</c>. 638 * 639 * <p> 640 * Sets ARP to look for RDF embedded within an enclosing XML document. 641 * 642 * <h5 class='section'>See Also:</h5><ul> 643 * <li> 644 * {doc ext.ARP/ARPOptions.html#setEmbedding(boolean) ARPOptions.setEmbedding(boolean)} 645 * </ul> 646 * 647 * @return This object. 648 */ 649 public SELF rdfxml_embedding() { 650 return rdfxml_embedding(true); 651 } 652 653 /** 654 * RDF/XML ARP property: <c>embedding</c>. 655 * 656 * <p> 657 * Sets ARP to look for RDF embedded within an enclosing XML document. 658 * 659 * <h5 class='section'>See Also:</h5><ul> 660 * <li> 661 * {doc ext.ARP/ARPOptions.html#setEmbedding(boolean) ARPOptions.setEmbedding(boolean)} 662 * </ul> 663 * 664 * @param value 665 * The new value for this property. 666 * @return This object. 667 */ 668 public SELF rdfxml_embedding(boolean value) { 669 return jena("rdfXml.embedding", value); 670 } 671 672 /** 673 * RDF/XML ARP property: <c>error-mode</c>. 674 * 675 * <p> 676 * This allows a coarse-grained approach to control of error handling. 677 * 678 * <ul class='values'> 679 * <li><js>"default"</js> 680 * <li><js>"lax"</js> 681 * <li><js>"strict"</js> 682 * <li><js>"strict-ignore"</js> 683 * <li><js>"strict-warning"</js> 684 * <li><js>"strict-error"</js> 685 * <li><js>"strict-fatal"</js> 686 * </ul> 687 * 688 * <h5 class='section'>See Also:</h5><ul> 689 * <li> 690 * {doc ext.ARP/ARPOptions.html#setDefaultErrorMode() ARPOptions.setDefaultErrorMode()} 691 * <li> 692 * {doc ext.ARP/ARPOptions.html#setLaxErrorMode() ARPOptions.setLaxErrorMode()} 693 * <li> 694 * {doc ext.ARP/ARPOptions.html#setStrictErrorMode() ARPOptions.setStrictErrorMode()} 695 * <li> 696 * {doc ext.ARP/ARPOptions.html#setStrictErrorMode(int) ARPOptions.setStrictErrorMode(int)} 697 * </ul> 698 * 699 * @param value 700 * The new value for this property. 701 * @return This object. 702 */ 703 public SELF rdfxml_errorMode(String value) { 704 return jena("rdfXml.error-mode", value); 705 } 706 707 /** 708 * RDF/XML property: <c>iri_rules</c>. 709 * 710 * <p> 711 * Set the engine for checking and resolving. 712 * 713 * <ul class='values spaced-list'> 714 * <li> 715 * <js>"lax"</js> - The rules for RDF URI references only, which does permit spaces although the use of spaces 716 * is not good practice. 717 * <li> 718 * <js>"strict"</js> - Sets the IRI engine with rules for valid IRIs, XLink and RDF; it does not permit spaces 719 * in IRIs. 720 * <li> 721 * <js>"iri"</js> - Sets the IRI engine to IRI 722 * ({doc http://www.ietf.org/rfc/rfc3986.txt RFC 3986}, 723 * {doc http://www.ietf.org/rfc/rfc3987.txt RFC 3987}). 724 * 725 * </ul> 726 * 727 * @param value 728 * The new value for this property. 729 * @return This object. 730 */ 731 public SELF rdfxml_iriRules(String value) { 732 return jena("rdfXml.iri-rules", value); 733 } 734 735 /** 736 * RDF/XML property: <c>longId</c>. 737 * 738 * <p> 739 * Whether to use long ID's for anon resources. 740 * Short ID's are easier to read, but can run out of memory on very large models. 741 * 742 * @return This object. 743 */ 744 public SELF rdfxml_longId() { 745 return rdfxml_longId(true); 746 } 747 748 /** 749 * RDF/XML property: <c>longId</c>. 750 * 751 * <p> 752 * Whether to use long ID's for anon resources. 753 * Short ID's are easier to read, but can run out of memory on very large models. 754 * 755 * @param value 756 * The new value for this property. 757 * @return This object. 758 */ 759 public SELF rdfxml_longId(boolean value) { 760 return jena("rdfXml.longId", value); 761 } 762 763 /** 764 * RDF/XML property: <c>relativeURIs</c>. 765 * 766 * <p> 767 * What sort of relative URIs should be used. 768 * 769 * <p> 770 * A comma separate list of options: 771 * <ul class='spaced-list'> 772 * <li> 773 * <js>"same-document"</js> - Same-document references (e.g. <js>""</js> or <js>"#foo"</js>) 774 * <li> 775 * <js>"network"</js> - Network paths (e.g. <js>"//example.org/foo"</js> omitting the URI scheme) 776 * <li> 777 * <js>"absolute"</js> - Absolute paths (e.g. <js>"/foo"</js> omitting the scheme and authority) 778 * <li> 779 * <js>"relative"</js> - Relative path not beginning in <js>"../"</js> 780 * <li> 781 * <js>"parent"</js> - Relative path beginning in <js>"../"</js> 782 * <li> 783 * <js>"grandparent"</js> - Relative path beginning in <js>"../../"</js> 784 * </ul> 785 * 786 * <p> 787 * The default value is <js>"same-document, absolute, relative, parent"</js>. 788 * To switch off relative URIs use the value <js>""</js>. 789 * Relative URIs of any of these types are output where possible if and only if the option has been specified. 790 * 791 * @param value 792 * The new value for this property. 793 * @return This object. 794 */ 795 public SELF rdfxml_relativeUris(String value) { 796 return jena("rdfXml.relativeURIs", value); 797 } 798 799 /** 800 * RDF/XML property: <c>showXmlDeclaration</c>. 801 * 802 * <ul class='values spaced-list'> 803 * <li> 804 * <js>"true"</js> - Add XML Declaration to the output. 805 * <li> 806 * <js>"false"</js> - Don't add XML Declaration to the output. 807 * <li> 808 * <js>"default"</js> - Only add an XML Declaration when asked to write to an <c>OutputStreamWriter</c> 809 * that uses some encoding other than <c>UTF-8</c> or <c>UTF-16</c>. 810 * In this case the encoding is shown in the XML declaration. 811 * </ul> 812 * 813 * @param value 814 * The new value for this property. 815 * @return This object. 816 */ 817 public SELF rdfxml_showXmlDeclaration(String value) { 818 return jena("rdfXml.showXmlDeclaration", value); 819 } 820 821 /** 822 * RDF/XML property: <c>tab</c>. 823 * 824 * <p> 825 * The number of spaces with which to indent XML child elements. 826 * 827 * @param value 828 * The new value for this property. 829 * @return This object. 830 */ 831 public SELF rdfxml_tab(int value) { 832 return jena("rdfXml.tab", value); 833 } 834 835 /** 836 * RDF/XML property: <c>xmlbase</c>. 837 * 838 * <p> 839 * The value to be included for an <xa>xml:base</xa> attribute on the root element in the file. 840 * 841 * @param value 842 * The new value for this property. 843 * @return This object. 844 */ 845 public SELF rdfxml_xmlbase(String value) { 846 return jena("rdfXml.xmlbase", value); 847 } 848 849 /** 850 * Trim whitespace from text elements. 851 * 852 * <p> 853 * When enabled, whitespace in text elements will be automatically trimmed. 854 * 855 * <h5 class='section'>Example:</h5> 856 * <p class='bjava'> 857 * <jc>// Create an RDF parser that trims whitespace.</jc> 858 * ReaderParser <jv>parser</jv> = RdfParser 859 * .<jsm>create</jsm>() 860 * .xml() 861 * .trimWhitespace() 862 * .build(); 863 * </p> 864 * 865 * @return This object. 866 */ 867 public SELF trimWhitespace() { 868 return trimWhitespace(true); 869 } 870 871 /** 872 * Same as {@link #trimWhitespace()} but allows you to explicitly specify the value. 873 * 874 * @param value 875 * The new value for this setting. 876 * @return This object. 877 */ 878 public SELF trimWhitespace(boolean value) { 879 trimWhitespace = value; 880 return self(); 881 } 882 883 /** 884 * Shortcut for calling <code>language(<jsf>LANG_TURTLE</jsf>)</code>. 885 * 886 * @return This object. 887 */ 888 public SELF turtle() { 889 return language(Constants.LANG_TURTLE); 890 } 891 892 /** 893 * Shortcut for calling <code>language(<jsf>LANG_JSONLD</jsf>)</code>. 894 * 895 * @return This object. 896 */ 897 public SELF jsonLd() { 898 return language(Constants.LANG_JSONLD); 899 } 900 901 /** 902 * Shortcut for calling <code>language(<jsf>LANG_NQUADS</jsf>)</code>. 903 * 904 * @return This object. 905 */ 906 public SELF nQuads() { 907 return language(Constants.LANG_NQUADS); 908 } 909 910 /** 911 * Shortcut for calling <code>language(<jsf>LANG_TRIG</jsf>)</code>. 912 * 913 * @return This object. 914 */ 915 public SELF triG() { 916 return language(Constants.LANG_TRIG); 917 } 918 919 /** 920 * Shortcut for calling <code>language(<jsf>LANG_TRIX</jsf>)</code>. 921 * 922 * @return This object. 923 */ 924 public SELF triX() { 925 return language(Constants.LANG_TRIX); 926 } 927 928 /** 929 * Shortcut for calling <code>language(<jsf>LANG_RDFJSON</jsf>)</code>. 930 * 931 * @return This object. 932 */ 933 public SELF rdfJson() { 934 return language(Constants.LANG_RDFJSON); 935 } 936 937 938 /** 939 * Shortcut for calling <code>language(<jsf>LANG_RDF_XML</jsf>)</code>. 940 * 941 * @return This object. 942 */ 943 public SELF xml() { 944 return language(Constants.LANG_RDF_XML); 945 } 946 947 /** 948 * Shortcut for calling <code>language(<jsf>LANG_RDF_XML_ABBREV</jsf>)</code>. 949 * 950 * @return This object. 951 */ 952 public SELF xmlabbrev() { 953 return language(Constants.LANG_RDF_XML_ABBREV); 954 } 955 956 SELF jena(String key, Object value) { 957 jenaSettings.put(key, value); 958 return self(); 959 } 960 } 961 962 /** 963 * Concrete default builder leaf for the non-subclassed {@link RdfParser#create()} / {@link RdfParser#copy()} path. 964 */ 965 public static final class DefaultBuilder extends Builder<DefaultBuilder> { 966 967 DefaultBuilder() {} 968 969 DefaultBuilder(RdfParser copyFrom) { 970 super(copyFrom); 971 } 972 973 DefaultBuilder(Builder<?> copyFrom) { 974 super(copyFrom); 975 } 976 977 @Override /* Overridden from Context.Builder<?> */ 978 public DefaultBuilder copy() { 979 return new DefaultBuilder(this); 980 } 981 } 982 983 /** 984 * Creates a new builder for this object. 985 * 986 * @return A new builder. 987 */ 988 @SuppressWarnings({ 989 "java:S1452", // Builder<?> wildcard return intentional; callers chain via fluent API without needing the concrete type 990 "java:S9149" // Public Juneau DSL factory; hiding parent create() is intentional. 991 }) 992 public static Builder<?> create() { 993 return new DefaultBuilder(); 994 } 995 996 private static String getConsumes(Builder<?> builder) { 997 if (nn(builder.getConsumes())) 998 return builder.getConsumes(); 999 return switch (builder.language) { 1000 case "RDF/XML", "RDF/XML-ABBREV" -> "text/xml+rdf"; 1001 case "N-TRIPLE" -> "text/n-triple"; 1002 case "N3" -> "text/n3"; 1003 case "N3-PP" -> "text/n3-pp"; 1004 case "N3-PLAIN" -> "text/n3-plain"; 1005 case "N3-TRIPLES" -> "text/n3-triples"; 1006 case "TURTLE" -> "text/turtle"; 1007 case "JSON-LD" -> "application/ld+json"; 1008 case "N-QUADS" -> "application/n-quads"; 1009 case "TRIG" -> "application/trig"; 1010 case "TRIX" -> "application/trix+xml"; 1011 case "RDF/JSON" -> "application/rdf+json"; 1012 default -> "text/xml+rdf"; 1013 }; 1014 } 1015 1016 protected final boolean looseCollections; 1017 protected final boolean trimWhitespace; 1018 protected final Namespace juneauBpNs; 1019 protected final Namespace juneauNs; 1020 protected final RdfCollectionFormat collectionFormat; 1021 protected final String language; 1022 1023 final Map<String,Object> jenaSettings; 1024 private final Map<ClassMeta<?>,RdfClassMeta> rdfClassMetas = new ConcurrentHashMap<>(); 1025 private final Map<BeanMeta<?>,RdfBeanMeta> rdfBeanMetas = new ConcurrentHashMap<>(); 1026 1027 private final Map<BeanPropertyMeta,RdfBeanPropertyMeta> rdfBeanPropertyMetas = new ConcurrentHashMap<>(); 1028 private final Map<ClassMeta<?>,XmlClassMeta> xmlClassMetas = new ConcurrentHashMap<>(); 1029 private final Map<BeanMeta<?>,XmlBeanMeta> xmlBeanMetas = new ConcurrentHashMap<>(); 1030 1031 private final Map<BeanPropertyMeta,XmlBeanPropertyMeta> xmlBeanPropertyMetas = new ConcurrentHashMap<>(); 1032 1033 /** 1034 * Constructor. 1035 * 1036 * @param builder The builder for this object. 1037 * <br>Cannot be <jk>null</jk>. 1038 */ 1039 public RdfParser(Builder<?> builder) { 1040 super(builder.consumes(getConsumes(builder))); 1041 1042 collectionFormat = builder.collectionFormat; 1043 juneauBpNs = builder.juneauBpNs; 1044 juneauNs = builder.juneauNs; 1045 language = builder.language; 1046 looseCollections = builder.looseCollections; 1047 trimWhitespace = builder.trimWhitespace; 1048 jenaSettings = new TreeMap<>(builder.jenaSettings); 1049 } 1050 1051 @Override /* Overridden from Context */ 1052 public Builder<?> copy() { 1053 return new DefaultBuilder(this); 1054 } 1055 1056 @Override /* Overridden from Context */ 1057 public RdfParserSession.Builder createSession() { 1058 return RdfParserSession.create(this); 1059 } 1060 1061 @Override /* Overridden from RdfMetaProvider */ 1062 public RdfBeanMeta getRdfBeanMeta(BeanMeta<?> bm) { 1063 return rdfBeanMetas.computeIfAbsent(bm, k -> new RdfBeanMeta(k, this)); 1064 } 1065 1066 @Override /* Overridden from RdfMetaProvider */ 1067 public RdfBeanPropertyMeta getRdfBeanPropertyMeta(BeanPropertyMeta bpm) { 1068 return rdfBeanPropertyMetas.computeIfAbsent(bpm, k -> new RdfBeanPropertyMeta(k.getDelegateFor(), this)); 1069 } 1070 1071 @Override /* Overridden from RdfMetaProvider */ 1072 public RdfClassMeta getRdfClassMeta(ClassMeta<?> cm) { 1073 return rdfClassMetas.computeIfAbsent(cm, k -> new RdfClassMeta(k, this)); 1074 } 1075 1076 @Override /* Overridden from Context */ 1077 public RdfParserSession getSession() { return createSession().build(); } 1078 1079 @Override /* Overridden from XmlMetaProvider */ 1080 public XmlBeanMeta getXmlBeanMeta(BeanMeta<?> bm) { 1081 return xmlBeanMetas.computeIfAbsent(bm, k -> new XmlBeanMeta(k, this)); 1082 } 1083 1084 @Override /* Overridden from XmlMetaProvider */ 1085 public XmlBeanPropertyMeta getXmlBeanPropertyMeta(BeanPropertyMeta bpm) { 1086 return xmlBeanPropertyMetas.computeIfAbsent(bpm, k -> new XmlBeanPropertyMeta(k.getDelegateFor(), this)); 1087 } 1088 1089 @Override /* Overridden from XmlMetaProvider */ 1090 public XmlClassMeta getXmlClassMeta(ClassMeta<?> cm) { 1091 return xmlClassMetas.computeIfAbsent(cm, k -> new XmlClassMeta(k, this)); 1092 } 1093 1094 /** 1095 * RDF format for representing collections and arrays. 1096 * 1097 * @see RdfParser.Builder#collectionFormat(RdfCollectionFormat) 1098 * @return 1099 * RDF format for representing collections and arrays. 1100 */ 1101 protected final RdfCollectionFormat getCollectionFormat() { return collectionFormat; } 1102 1103 /** 1104 * All Jena-related configuration properties. 1105 * 1106 * @return 1107 * A map of all Jena-related configuration properties. 1108 */ 1109 protected final Map<String,Object> getJenaSettings() { return u(jenaSettings); } 1110 1111 /** 1112 * Default XML namespace for bean properties. 1113 * 1114 * @see RdfParser.Builder#juneauBpNs(Namespace) 1115 * @return 1116 * Default XML namespace for bean properties. 1117 */ 1118 protected final Namespace getJuneauBpNs() { return juneauBpNs; } 1119 1120 /** 1121 * XML namespace for Juneau properties. 1122 * 1123 * @see RdfParser.Builder#juneauNs(Namespace) 1124 * @return 1125 * XML namespace for Juneau properties. 1126 */ 1127 protected final Namespace getJuneauNs() { return juneauNs; } 1128 1129 /** 1130 * RDF language. 1131 * 1132 * @see RdfParser.Builder#language(String) 1133 * @return 1134 * The RDF language to use. 1135 */ 1136 protected final String getLanguage() { return language; } 1137 1138 /** 1139 * Collections should be serialized and parsed as loose collections. 1140 * 1141 * @see RdfParser.Builder#looseCollections() 1142 * @return 1143 * <jk>true</jk> if collections of resources are handled as loose collections of resources in RDF instead of 1144 * resources that are children of an RDF collection (e.g. Sequence, Bag). 1145 */ 1146 protected final boolean isLooseCollections() { return looseCollections; } 1147 1148 /** 1149 * Trim whitespace from text elements. 1150 * 1151 * @see RdfParser.Builder#trimWhitespace() 1152 * @return 1153 * <jk>true</jk> if whitespace in text elements will be automatically trimmed. 1154 */ 1155 protected final boolean isTrimWhitespace() { return trimWhitespace; } 1156 1157 @Override /* Overridden from ReaderParser */ 1158 protected FluentMap<String,Object> properties() { 1159 return super.properties() 1160 .a("collectionFormat", collectionFormat) 1161 .a("juneauBpNs", juneauBpNs) 1162 .a("juneauNs", juneauNs) 1163 .a("language", language) 1164 .a("looseCollections", looseCollections) 1165 .a("trimWhitespace", trimWhitespace); 1166 } 1167}