1 package ca.uhn.hl7v2.parser; 2 3 import java.util.Arrays; 4 import java.util.Collections; 5 import java.util.HashSet; 6 import java.util.Set; 7 8 import ca.uhn.hl7v2.HapiContext; 9 import ca.uhn.hl7v2.model.GenericMessage; 10 import ca.uhn.hl7v2.util.Terser; 11 import ca.uhn.hl7v2.util.idgenerator.FileBasedHiLoGenerator; 12 import ca.uhn.hl7v2.util.idgenerator.IDGenerator; 13 import ca.uhn.hl7v2.validation.ValidationContext; 14 15 /** 16 * Contains configuration which will be applied to any parsers which are a part of the given 17 * HAPI Context. 18 * 19 * @see HapiContext#getParserConfiguration() 20 */ 21 public class ParserConfiguration { 22 23 /** 24 * @link {@link UnexpectedSegmentBehaviourEnum#ADD_INLINE} 25 */ 26 // NB if you change the default, edit the javadoc for the enum itself 27 public static final UnexpectedSegmentBehaviourEnum DEFAULT_UNEXPECTED_SEGMENT_BEHAVIOUR = UnexpectedSegmentBehaviourEnum.ADD_INLINE; 28 29 private boolean allowUnknownVersions; 30 private boolean escapeSubcomponentDelimiterInPrimitive = false; 31 private IDGenerator idGenerator = new FileBasedHiLoGenerator(); 32 private String myDefaultObx2Type; 33 private boolean myEncodeEmptyMandatorySegments = true; 34 private final Set<String> myForcedEncode = new HashSet<>(); 35 private String myInvalidObx2Type; 36 private UnexpectedSegmentBehaviourEnum myUnexpectedSegmentBehaviour; 37 private boolean nonGreedyMode = false; 38 private boolean prettyPrintWhenEncodingXml = true; 39 private boolean validating = true; 40 private Escaping escaping = new DefaultEscaping(); 41 private boolean xmlDisableWhitespaceTrimmingOnAllNodes = false; 42 private Set<String> xmlDisableWhitespaceTrimmingOnNodeNames = Collections.emptySet(); 43 private String myInvalidMfe5Type; 44 private String myDefaultMfe5Type; 45 46 /** 47 * <p> 48 * Forces the parser to encode certain segments/fields, even if they contain 49 * no content. This method may be called multiple times with multiple path 50 * definitions, and each path definition contains the path to the segment or 51 * field which needs to be forced. 52 * </p> 53 * <p> 54 * Path definitions are similar in format to {@link Terser Terser} paths. 55 * They contain a slash-separated lookup path to reach a given segment, and 56 * optionally a field number. The following are examples of paths which 57 * could be added here, as well as the sample output for an otherwise empty 58 * ORU^R01 message: 59 * </p> 60 * <table cellpadding="2" cellspacing="2" border="0"> 61 * <thead> 62 * <tr> 63 * <th style="background: #FFA0FF;">Forced Encode Path</th> 64 * <th style="background: #FFA0FF;">Encode Output</th> 65 * </tr> 66 * </thead> 67 * <tr> 68 * <td>None (for illustration purposes)</td> 69 * <td style=" font-family: monospace;"> 70 * MSH|^~\&|||||||ORU^R01^ORU_R01||T|2.4</td> 71 * </tr> 72 * <tr> 73 * <td style="background: #E0E0E0;">PATIENT_RESULT/ORDER_OBSERVATION/ORC</td> 74 * <td style="background: #E0E0E0; font-family: monospace;"> 75 * MSH|^~\&|||||||ORU^R01^ORU_R01||T|2.4<br> 76 * ORC|</td> 77 * </tr> 78 * <tr> 79 * <td>PATIENT_RESULT/ORDER_OBSERVATION/ORC-4</td> 80 * <td style=" font-family: monospace;"> 81 * MSH|^~\&|||||||ORU^R01^ORU_R01||T|2.4<br> 82 * ORC||||</td> 83 * </tr> 84 * <tr> 85 * <td style="background: #E0E0E0;">PATIENT_RESULT/ORDER_OBSERVATION/ORC-4-2 86 * </td> 87 * <td style="background: #E0E0E0; font-family: monospace;"> 88 * MSH|^~\&|||||||ORU^R01^ORU_R01||T|2.4<br> 89 * ORC||||^</td> 90 * </tr> 91 * </table> 92 * <p> 93 * While empty segments do not generally have any meaning according to HL7, 94 * this may be useful when transmitting to systems which rely on segments 95 * being received even if they have no content. 96 * </p> 97 * <p> 98 * Note that this configuration item currently only applies to 99 * {@link PipeParser} 100 * </p> 101 * 102 * @param theForcedEncode path definition 103 * @since 2.0 104 */ 105 public void addForcedEncode(String theForcedEncode) { 106 if (theForcedEncode == null) { 107 throw new NullPointerException("forced encode may not be null"); 108 } 109 110 int lastSlashIndex = theForcedEncode.lastIndexOf('/'); 111 lastSlashIndex = Math.max(lastSlashIndex, 0); 112 113 if (lastSlashIndex == 0) { 114 if (!theForcedEncode.matches("[A-Z0-9]{3}(-[0-9]+){0,2}$")) { 115 throw new IllegalArgumentException("Definition must end with a segment name or field lookup, e.g. MSH or MSH-2"); 116 } 117 } else { 118 if (lastSlashIndex == theForcedEncode.length() || !theForcedEncode.substring(lastSlashIndex + 1).matches("[A-Z0-9]{3}(-[0-9]+){0,2}$")) { 119 throw new IllegalArgumentException("Definition must end with a segment name or field lookup, e.g. MSH or MSH-2"); 120 } 121 } 122 myForcedEncode.add(theForcedEncode); 123 } 124 125 boolean determineForcedEncodeIncludesTerserPath(String theTerserPath) { 126 for (String next : getForcedEncode()) { 127 if (next.startsWith(theTerserPath)) { 128 return true; 129 } 130 } 131 return false; 132 } 133 134 int determineForcedFieldNumForTerserPath(String theCurrentTerserPath) { 135 int forceUpToFieldNum = 0; 136 for (String nextPath : getForcedEncode()) { 137 if (nextPath.startsWith(theCurrentTerserPath) && nextPath.length() > theCurrentTerserPath.length()) { 138 int endOfFieldDef = nextPath.indexOf('-', theCurrentTerserPath.length() + 1); 139 if (endOfFieldDef == -1) { 140 endOfFieldDef = nextPath.length(); 141 } 142 String fieldNumString = nextPath.substring(theCurrentTerserPath.length() + 1, endOfFieldDef); 143 forceUpToFieldNum = Math.max(forceUpToFieldNum, Integer.parseInt(fieldNumString)); 144 } 145 } 146 return forceUpToFieldNum; 147 } 148 149 /** 150 * Returns the default datatype ("ST", "NM", etc) for an OBX segment with a 151 * missing OBX-2 value 152 * 153 * @return Returns the default datatype ("ST", "NM", etc) for an OBX segment 154 * with a missing OBX-2 value 155 * @see #setDefaultObx2Type(String) 156 */ 157 public String getDefaultObx2Type() { 158 return myDefaultObx2Type; 159 } 160 161 /** 162 * Returns the default datatype ("ST", "NM", etc) for an MFE segment with a 163 * missing MFE-5 value 164 * 165 * @return Returns the default datatype ("ST", "NM", etc) for an OBX segment 166 * with a missing MFE-5 value 167 * @see #setDefaultMfe5Type(String) 168 */ 169 public String getDefaultMfe5Type() { 170 return myDefaultMfe5Type; 171 } 172 173 /** 174 * @return Returns the forced encode strings added by 175 * {@link #addForcedEncode(String)} 176 * 177 * @see #addForcedEncode(String) 178 * @since 1.3 179 */ 180 public Set<String> getForcedEncode() { 181 return Collections.unmodifiableSet(myForcedEncode); 182 } 183 184 /** 185 * @return the ID Generator to be used for generating IDs for new messages 186 */ 187 public IDGenerator getIdGenerator() { 188 return idGenerator; 189 } 190 191 /** 192 * Returns the value provides a default datatype ("ST", "NM", etc) for an 193 * OBX segment with an invalid OBX-2 value. 194 * 195 * @return Returns the value provides a default datatype ("ST", "NM", etc) 196 * for an OBX segment with an invalid OBX-2 value. 197 * @see #setInvalidObx2Type(String) 198 */ 199 public String getInvalidObx2Type() { 200 return myInvalidObx2Type; 201 } 202 203 /** 204 * Returns the value provides a default datatype ("ST", "NM", etc) for an 205 * MFE segment with an invalid MFE-5 value. 206 * 207 * @return Returns the value provides a default datatype ("ST", "NM", etc) 208 * for an MFE segment with an invalid MFE-5 value. 209 * @see #setInvalidMfe5Type(String) 210 */ 211 public String getInvalidMfe5Type() { 212 return myInvalidMfe5Type; 213 } 214 215 216 /** 217 * Returns the behaviour to use when parsing a message and a nonstandard 218 * segment is found. Default is 219 * {@link #DEFAULT_UNEXPECTED_SEGMENT_BEHAVIOUR} 220 * 221 * @return the behaviour to use when a nonstandard egment is found 222 */ 223 public UnexpectedSegmentBehaviourEnum getUnexpectedSegmentBehaviour() { 224 if (myUnexpectedSegmentBehaviour == null) { 225 myUnexpectedSegmentBehaviour = DEFAULT_UNEXPECTED_SEGMENT_BEHAVIOUR; 226 } 227 return myUnexpectedSegmentBehaviour; 228 } 229 230 /** 231 * @see #setXmlDisableWhitespaceTrimmingOnNodeNames(Set) 232 */ 233 public Set<String> getXmlDisableWhitespaceTrimmingOnNodeNames() { 234 return xmlDisableWhitespaceTrimmingOnNodeNames; 235 } 236 237 /** 238 * If set to <code>true</code> (default is <code>false</code>) the parser 239 * will allow messages to parse, even if they contain a version which is not 240 * known to the parser. When operating in this mode, if a message arrives 241 * with an unknown version string, the parser will attempt to parse it using 242 * a {@link GenericMessage Generic Message} class instead of a specific HAPI 243 * structure class. Default is <code>false</code>. 244 * 245 * @return true if parsing messages with unknown versions is allowed 246 */ 247 public boolean isAllowUnknownVersions() { 248 return this.allowUnknownVersions; 249 } 250 251 /** 252 * Returns <code>true</code> if empty segments should still be encoded 253 * if they are mandatory within their message structure. Default is <code>false</code>. 254 * @return <code>true</code> if empty segments should still be encoded 255 * 256 * @see #setEncodeEmptyMandatoryFirstSegments(boolean) 257 */ 258 public boolean isEncodeEmptyMandatorySegments() { 259 return myEncodeEmptyMandatorySegments; 260 } 261 262 /** 263 * Returns code>true</code> if subcomponent delimiters in OBX-5 shall be 264 * ignored. Default is <code>false</code>. 265 * @return <code>true</code> if subcomponent delimiters in OBX-5 shall be 266 * ignored 267 */ 268 public boolean isEscapeSubcomponentDelimiterInPrimitive() { 269 return escapeSubcomponentDelimiterInPrimitive; 270 } 271 272 /** 273 * Returns <code>true</code> if the parser should parse in non-greedy mode. Default 274 * is <code>false</code> 275 * 276 * @see #setNonGreedyMode(boolean) for an explanation of non-greedy mode 277 */ 278 public boolean isNonGreedyMode() { 279 return nonGreedyMode; 280 } 281 282 /** 283 * If set to <code>true</code> (which is the default), {@link XMLParser XML Parsers} 284 * will attempt to pretty-print the XML they generate. This means the messages will look 285 * nicer to humans, but may take up slightly more space/bandwidth. 286 */ 287 public boolean isPrettyPrintWhenEncodingXml() { 288 return prettyPrintWhenEncodingXml; 289 } 290 291 /** 292 * Returns <code>true</code> if the parser validates using a configured 293 * {@link ValidationContext}. Default is <code>true</code>. 294 * @return <code>true</code> if the parser validates using a configured 295 * {@link ValidationContext} 296 */ 297 public boolean isValidating() { 298 return validating; 299 } 300 301 /** 302 * @see #setXmlDisableWhitespaceTrimmingOnAllNodes(boolean) 303 */ 304 public boolean isXmlDisableWhitespaceTrimmingOnAllNodes() { 305 return xmlDisableWhitespaceTrimmingOnAllNodes; 306 } 307 308 /** 309 * Removes a forced encode entry 310 * 311 * @param theForcedEncode path definition to be removed 312 * @see #addForcedEncode(String) 313 * @since 1.3 314 */ 315 public void removeForcedEncode(String theForcedEncode) { 316 if (theForcedEncode == null) { 317 throw new NullPointerException("forced encode may not be null"); 318 } 319 320 myForcedEncode.remove(theForcedEncode); 321 } 322 323 /** 324 * If set to <code>true</code> (default is <code>false</code>) the parser 325 * will allow messages to parse, even if they contain a version which is not 326 * known to the parser. When operating in this mode, if a message arrives 327 * with an unknown version string, the parser will attempt to parse it using 328 * a {@link GenericMessage Generic Message} class instead of a specific HAPI 329 * structure class. 330 * 331 * @param theAllowUnknownVersions true if parsing unknown versions shall be allowed 332 */ 333 public void setAllowUnknownVersions(boolean theAllowUnknownVersions) { 334 allowUnknownVersions = theAllowUnknownVersions; 335 } 336 337 /** 338 * <p> 339 * If this property is set, the value provides a default datatype ("ST", 340 * "NM", etc) for an OBX segment with a missing OBX-2 value. This is useful 341 * when parsing messages from systems which do not correctly populate OBX-2. 342 * </p> 343 * <p> 344 * For example, if this property is set to "ST", and the following OBX 345 * segment is encountered: 346 * 347 * <pre> 348 * OBX|||||This is a value 349 * </pre> 350 * 351 * It will be parsed as though it had read: 352 * 353 * <pre> 354 * OBX||ST|||This is a value 355 * </pre> 356 * 357 * </p> 358 * <p> 359 * Note that this configuration can also be set globally using the system 360 * property {@link FixFieldDataType#DEFAULT_OBX2_TYPE_PROP}, but any value provided to 361 * {@link ParserConfiguration} takes priority over the system property. 362 * </p> 363 * 364 * @param theDefaultObx2Type 365 * If this property is set, the value provides a default datatype 366 * ("ST", "NM", etc) for an OBX segment with a missing OBX-2 367 * value 368 * @see #setInvalidObx2Type(String) 369 * @see FixFieldDataType#INVALID_OBX2_TYPE_PROP 370 */ 371 public void setDefaultObx2Type(String theDefaultObx2Type) { 372 myDefaultObx2Type = theDefaultObx2Type; 373 } 374 375 /** 376 * <p> 377 * If this property is set, the value provides a default datatype ("ST", 378 * "NM", etc) for an MFE segment with a missing MFE-5 value. This is useful 379 * when parsing messages from systems which do not correctly populate MFE-5. 380 * </p> 381 * <p> 382 * For example, if this property is set to "ST", and the following MFE 383 * segment is encountered: 384 * 385 * <pre> 386 * MFE||||This is a value 387 * </pre> 388 * 389 * It will be parsed as though it had read: 390 * 391 * <pre> 392 * MFE||||This is a value|ST 393 * </pre> 394 * 395 * </p> 396 * <p> 397 * Note that this configuration can also be set globally using the system 398 * property {@link FixFieldDataType#DEFAULT_MFE5_TYPE_PROP}, but any value provided to 399 * {@link ParserConfiguration} takes priority over the system property. 400 * </p> 401 * 402 * @param theDefaultMfe5Type 403 * If this property is set, the value provides a default datatype 404 * ("ST", "NM", etc) for an MFE segment with a missing MFE-5 405 * value 406 * @see #setInvalidMfe5Type(String) 407 * @see FixFieldDataType#DEFAULT_MFE5_TYPE_PROP 408 */ 409 public void setDefaultMfe5Type(String theDefaultMfe5Type) { 410 myDefaultMfe5Type = theDefaultMfe5Type; 411 } 412 413 /** 414 * <p> 415 * If set to <code>true</code> (default is <code>true</code>), when encoding 416 * a group using the PipeParser where the first segment is required, but no 417 * data has been populated in that segment, the empty segment is now still 418 * encoded if needed as a blank segment in order to give parsers a hint 419 * about which group subsequent segments are in. This helps to ensure that 420 * messages can be "round tripped", meaning that a message which is parsed, 421 * encoded, and then re-parsed should contain exactly the same structure 422 * from beginning to end. 423 * </p> 424 * <p> 425 * </p> 426 * For example, in an ORU^R01 message with a populated OBX segment, but no 427 * data in the mandatory OBR segment which begins the ORDER_OBSERVATION 428 * group the message would still contain an empty OBR segment when encoded: 429 * 430 * <pre> 431 * MSH|^~\&|REG|W|||201103230042||ORU^R01|32153168|P|2.5 432 * OBR| 433 * OBX||ST|||Value Data 434 * </pre> 435 * 436 * Previously, the following encoding would have occurred, which would have 437 * incorrectly been parsed as having a custom OBX segment instead of having 438 * a normal ORDER_OBSERVATION group: 439 * 440 * <pre> 441 * MSH|^~\&|REG|W|||201103230042||ORU^R01|32153168|P|2.5 442 * OBX||ST|||Value Data 443 * </pre> 444 * 445 * @param theEncodeEmptyMandatorySegments 446 * If set to <code>true</code> (default is <code>true</code>), 447 * when encoding a group using the PipeParser where the first 448 * segment is required, but no data has been populated in that 449 * segment, the empty segment is now still encoded if needed as a 450 * blank segment in order to give parsers a hint about which 451 * group subsequent segments are in 452 */ 453 public void setEncodeEmptyMandatoryFirstSegments(boolean theEncodeEmptyMandatorySegments) { 454 myEncodeEmptyMandatorySegments = theEncodeEmptyMandatorySegments; 455 } 456 457 /** 458 * Set to <code>true</code> if subcomponent delimiters in OBX-5 shall be 459 * ignored 460 * @param escapeSubcomponentDelimiterInPrimitive boolean flag to enable or disable this behavior 461 */ 462 public void setEscapeSubcomponentDelimiterInPrimitive(boolean escapeSubcomponentDelimiterInPrimitive) { 463 this.escapeSubcomponentDelimiterInPrimitive = escapeSubcomponentDelimiterInPrimitive; 464 } 465 466 /** 467 * @param idGenerator 468 * the {@link IDGenerator} to be used for generating IDs for new 469 * messages, preferable initialized using the methods described 470 * in IDGeneratorFactory. 471 * 472 * @see IDGenerator 473 */ 474 public void setIdGenerator(IDGenerator idGenerator) { 475 this.idGenerator = idGenerator; 476 } 477 478 /** 479 * <p> 480 * If this property is set, the value provides a default datatype ("ST", 481 * "NM", etc) for an OBX segment with an invalid OBX-2 value. This is useful 482 * when parsing messages from systems which do not correctly populate OBX-2. 483 * </p> 484 * <p> 485 * For example, if this property is set to "ST", and the following OBX 486 * segment is encountered: 487 * 488 * <pre> 489 * OBX||INVALID|||This is a value 490 * </pre> 491 * 492 * It will be parsed as though it had read: 493 * 494 * <pre> 495 * OBX||ST|||This is a value 496 * </pre> 497 * 498 * </p> 499 * <p> 500 * Note that this configuration can also be set globally using the system 501 * property {@link FixFieldDataType#INVALID_OBX2_TYPE_PROP}, but any value provided to 502 * {@link ParserConfiguration} takes priority over the system property. 503 * </p> 504 * 505 * @param theInvalidObx2Type 506 * If this property is set, the value provides a default datatype 507 * ("ST", "NM", etc) for an OBX segment with an invalid OBX-2 508 * value. This is useful when parsing messages from systems which 509 * do not correctly populate OBX-2. 510 * @see ParserConfiguration#setDefaultObx2Type(String) 511 * @see FixFieldDataType#DEFAULT_OBX2_TYPE_PROP 512 */ 513 public void setInvalidObx2Type(String theInvalidObx2Type) { 514 myInvalidObx2Type = theInvalidObx2Type; 515 } 516 517 /** 518 * <p> 519 * If this property is set, the value provides a default datatype ("ST", 520 * "NM", etc) for an MFE segment with an invalid MFE-5 value. This is useful 521 * when parsing messages from systems which do not correctly populate MFE-5. 522 * </p> 523 * <p> 524 * For example, if this property is set to "ST", and the following MFE 525 * segment is encountered: 526 * 527 * <pre> 528 * MFE||||This is a value|INVALID 529 * </pre> 530 * 531 * It will be parsed as though it had read: 532 * 533 * <pre> 534 * MFE||||This is a value|ST 535 * </pre> 536 * 537 * </p> 538 * <p> 539 * Note that this configuration can also be set globally using the system 540 * property {@link FixFieldDataType#INVALID_MFE5_TYPE_PROP}, but any value provided to 541 * {@link ParserConfiguration} takes priority over the system property. 542 * </p> 543 * 544 * @param theInvalidMfe5Type 545 * If this property is set, the value provides a default datatype 546 * ("ST", "NM", etc) for an MFE segment with an invalid MFE-5 547 * value. This is useful when parsing messages from systems which 548 * do not correctly populate MFE-5. 549 * @see ParserConfiguration#setDefaultMfe5Type(String) 550 * @see FixFieldDataType#INVALID_MFE5_TYPE_PROP 551 */ 552 public void setInvalidMfe5Type(String theInvalidMfe5Type) { 553 myInvalidMfe5Type = theInvalidMfe5Type; 554 } 555 556 /** 557 * If set to <code>true</code> (default is <code>false</code>), pipe parser will be 558 * put in non-greedy mode. This setting applies only to {@link PipeParser Pipe Parsers} and 559 * will have no effect on {@link XMLParser XML Parsers}. 560 * 561 * <p> 562 * In non-greedy mode, if the message structure being parsed has an ambiguous 563 * choice of where to put a segment because there is a segment matching the 564 * current segment name in both a later position in the message, and 565 * in an earlier position as a part of a repeating group, the earlier 566 * position will be chosen. 567 * </p> 568 * <p> 569 * This is perhaps best explained with an example. Consider the following structure: 570 * </p> 571 * <pre> 572 * MSH 573 * GROUP_1 (start) 574 * { 575 * AAA 576 * BBB 577 * GROUP_2 (start) 578 * { 579 * AAA 580 * } 581 * GROUP_2 (end) 582 * } 583 * GROUP_1 (end) 584 * </pre> 585 * <p> 586 * </p> 587 * For the above example, consider a message containing the following segments:<br/> 588 * <code>MSH<br/> 589 * AAA<br/> 590 * BBB<br/> 591 * AAA</code> 592 * </p> 593 * <p> 594 * In this example, when the second AAA segment is encountered, there are two 595 * possible choices. It would be placed in GROUP_2, or it could be placed in 596 * a second repetition of GROUP_1. By default it will be placed in GROUP_2, but 597 * in non-greedy mode it will be put in a new repetition of GROUP_1. 598 * </p> 599 * <p> 600 * This mode is useful for example when parsing OML^O21 messages containing 601 * multiple orders. 602 * </p> 603 */ 604 public void setNonGreedyMode(boolean theNonGreedyMode) { 605 nonGreedyMode = theNonGreedyMode; 606 } 607 608 /** 609 * If set to <code>true</code> (which is the default), {@link XMLParser XML Parsers} 610 * will attempt to pretty-print the XML they generate. This means the messages will look 611 * nicer to humans, but may take up slightly more space/bandwidth. 612 */ 613 public void setPrettyPrintWhenEncodingXml(boolean thePrettyPrintWhenEncodingXml) { 614 prettyPrintWhenEncodingXml = thePrettyPrintWhenEncodingXml; 615 } 616 617 /** 618 * Sets the behaviour to use when parsing a message and a nonstandard 619 * segment is found 620 * 621 * @param theUnexpectedSegmentBehaviour behaviour to use when a nonstandard segment is found 622 */ 623 public void setUnexpectedSegmentBehaviour(UnexpectedSegmentBehaviourEnum theUnexpectedSegmentBehaviour) { 624 if (theUnexpectedSegmentBehaviour == null) { 625 throw new NullPointerException("UnexpectedSegmentBehaviour can not be null"); 626 } 627 myUnexpectedSegmentBehaviour = theUnexpectedSegmentBehaviour; 628 } 629 630 /** 631 * Determines whether the parser validates using a configured 632 * {@link ValidationContext} or not. This allows to disable message 633 * validation although a validation context is defined. 634 * 635 * @param validating 636 * <code>true</code> if parser shall validate, <code>false</code> 637 * if not 638 */ 639 public void setValidating(boolean validating) { 640 this.validating = validating; 641 } 642 643 public Escaping getEscaping() { 644 return escaping; 645 } 646 647 /** 648 * Sets an escaping strategy 649 * @param escaping escaping strategy instance 650 */ 651 public void setEscaping(Escaping escaping) { 652 if (escaping == null) { 653 throw new NullPointerException("Escaping can not be null"); 654 } 655 this.escaping = escaping; 656 } 657 /** 658 * Configures the XML Parser to treat all whitespace within text nodes as literal, meaning that 659 * line breaks, tabs, multiple spaces, etc. will be preserved. If set to <code>true</code>, any values 660 * passed to {@link #setXmlDisableWhitespaceTrimmingOnNodeNames(Set)} will be superceded since all 661 * whitespace will be treated as literal. 662 * <p> 663 * Default is <b>false</b> 664 * </p> 665 */ 666 public void setXmlDisableWhitespaceTrimmingOnAllNodes(boolean theXmlDisableWhitespaceTrimmingOnAllNodes) { 667 this.xmlDisableWhitespaceTrimmingOnAllNodes = theXmlDisableWhitespaceTrimmingOnAllNodes; 668 } 669 670 /** 671 * Configures the XML Parser to treat all whitespace within the given nodes as literal, meaning that 672 * line breaks, tabs, multiple spaces, etc. will be preserved. This method takes individual XML node names 673 * as arguments (e.g. "HD.2", or "TX.1"). 674 * <p> 675 * Default is <b>none</b> 676 * </p> 677 */ 678 public void setXmlDisableWhitespaceTrimmingOnNodeNames(Set<String> theXmlDisableWhitespaceTrimmingOnNodeNames) { 679 if (theXmlDisableWhitespaceTrimmingOnNodeNames==null) { 680 this.xmlDisableWhitespaceTrimmingOnNodeNames = Collections.emptySet(); 681 } else { 682 this.xmlDisableWhitespaceTrimmingOnNodeNames = theXmlDisableWhitespaceTrimmingOnNodeNames; 683 } 684 } 685 686 /** 687 * Configures the XML Parser to treat all whitespace within the given nodes as literal, meaning that 688 * line breaks, tabs, multiple spaces, etc. will be preserved. This method takes individual XML node names 689 * as arguments (e.g. "HD.2", or "TX.1"). 690 * <p> 691 * Default is <b>none</b> 692 * </p> 693 */ 694 public void setXmlDisableWhitespaceTrimmingOnNodeNames(String... theKeepAsOriginalNodes) { 695 if (theKeepAsOriginalNodes==null) { 696 setXmlDisableWhitespaceTrimmingOnNodeNames((Set<String>)null); 697 } else { 698 setXmlDisableWhitespaceTrimmingOnNodeNames(new HashSet<>(Arrays.asList(theKeepAsOriginalNodes))); 699 } 700 } 701 702 }