001/* 002 * jDTAUS Banking API 003 * Copyright (C) 2005 Christian Schulte 004 * <cs@schulte.it> 005 * 006 * This library is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 2.1 of the License, or any later version. 010 * 011 * This library is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with this library; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 019 * 020 */ 021package org.jdtaus.banking; 022 023import java.io.Serializable; 024import java.text.DecimalFormat; 025import java.text.NumberFormat; 026import java.text.ParseException; 027import java.util.Date; 028 029/** 030 * Record of the {@code BankleitzahlenVerzeichnis}. 031 * 032 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 033 * @version $JDTAUS: BankleitzahlInfo.java 8861 2014-01-10 17:09:50Z schulte $ 034 * 035 * @see BankleitzahlenVerzeichnis 036 */ 037public class BankleitzahlInfo implements Cloneable, Serializable 038{ 039 040 /** Serial version UID for backwards compatibility with 1.1.x classes. */ 041 private static final long serialVersionUID = -7251689236798391940L; 042 043 /** 044 * index = index of the field in the record line; value = offset the field's value starts in the record line. 045 */ 046 private static final int[] FIELD_TO_OFFSET = 047 { 048 0, 8, 9, 67, 72, 107, 134, 139, 150, 152, 158, 159, 160 049 }; 050 051 /** 052 * index = index of the field in the record line; value = length of the field's value in the record line. 053 */ 054 private static final int[] FIELD_TO_LENGTH = 055 { 056 8, 1, 58, 5, 35, 27, 5, 11, 2, 6, 1, 1, 8 057 }; 058 059 /** 060 * index = index of the field in the record line; value = end offset in the record line exclusive. 061 */ 062 private static final int[] FIELD_TO_ENDOFFSET = 063 { 064 BankleitzahlInfo.FIELD_TO_OFFSET[0] + BankleitzahlInfo.FIELD_TO_LENGTH[0], 065 BankleitzahlInfo.FIELD_TO_OFFSET[1] + BankleitzahlInfo.FIELD_TO_LENGTH[1], 066 BankleitzahlInfo.FIELD_TO_OFFSET[2] + BankleitzahlInfo.FIELD_TO_LENGTH[2], 067 BankleitzahlInfo.FIELD_TO_OFFSET[3] + BankleitzahlInfo.FIELD_TO_LENGTH[3], 068 BankleitzahlInfo.FIELD_TO_OFFSET[4] + BankleitzahlInfo.FIELD_TO_LENGTH[4], 069 BankleitzahlInfo.FIELD_TO_OFFSET[5] + BankleitzahlInfo.FIELD_TO_LENGTH[5], 070 BankleitzahlInfo.FIELD_TO_OFFSET[6] + BankleitzahlInfo.FIELD_TO_LENGTH[6], 071 BankleitzahlInfo.FIELD_TO_OFFSET[7] + BankleitzahlInfo.FIELD_TO_LENGTH[7], 072 BankleitzahlInfo.FIELD_TO_OFFSET[8] + BankleitzahlInfo.FIELD_TO_LENGTH[8], 073 BankleitzahlInfo.FIELD_TO_OFFSET[9] + BankleitzahlInfo.FIELD_TO_LENGTH[9], 074 BankleitzahlInfo.FIELD_TO_OFFSET[10] + BankleitzahlInfo.FIELD_TO_LENGTH[10], 075 BankleitzahlInfo.FIELD_TO_OFFSET[11] + BankleitzahlInfo.FIELD_TO_LENGTH[11], 076 BankleitzahlInfo.FIELD_TO_OFFSET[12] + BankleitzahlInfo.FIELD_TO_LENGTH[12] 077 }; 078 079 /** 080 * Bankleitzahl (german bank code). 081 * @serial 082 */ 083 private Bankleitzahl bankCode; 084 085 /** 086 * Specifies if this record identifies a bank which is to be used for transactions. 087 * @serial 088 */ 089 private boolean headOffice; 090 091 /** 092 * The name of the bank. 093 * @serial 094 */ 095 private String name; 096 097 /** 098 * Postal code of the city the bank is resident. 099 * @serial 100 */ 101 private int postalCode = -1; 102 103 /** 104 * City the bank resides at. 105 * @serial 106 */ 107 private String city; 108 109 /** 110 * Description of the bank including information regarding the city the bank resides. 111 * @serial 112 */ 113 private String description; 114 115 /** 116 * Institute number for PAN. 117 * @serial 118 */ 119 private int panInstituteNumber = -1; 120 121 /** 122 * SWIFT Bank Identifier Code. 123 * @serial 124 */ 125 private String bic; 126 127 /** 128 * Label for the algorithm used for validating account numbers. 129 * @serial 130 */ 131 private String validationLabel; 132 133 /** 134 * The serial number of the record. 135 * @serial 136 */ 137 private Integer serialNumber; 138 139 /** 140 * Label indicating changes of the record to previous files. 141 * @serial 142 */ 143 private char changeLabel; 144 145 /** 146 * Indicates if this record will be deleted in upcoming files. 147 * @serial 148 */ 149 private boolean markedForDeletion; 150 151 /** 152 * Bankleitzahl of the bank the record is replaced with. 153 * @serial 154 */ 155 private Bankleitzahl replacingBankCode; 156 157 /** 158 * Label of the rule used for generating international bank account numbers. 159 * @serial 160 * @since 1.15 161 */ 162 private Integer ibanRuleLabel; 163 164 /** 165 * Version of the rule used for generating international bank account numbers. 166 * @serial 167 * @since 1.15 168 */ 169 private Integer ibanRuleVersion; 170 171 /** 172 * The date the record got created at. 173 * @since 1.15 174 */ 175 private Date creationDate; 176 177 /** 178 * The date the record got modified at. 179 * @since 1.15 180 */ 181 private Date modificationDate; 182 183 /** 184 * The date the record got deleted at. 185 * @since 1.15 186 */ 187 private Date deletionDate; 188 189 /** Creates a new {@code BankleitzahlInfo} instance. */ 190 public BankleitzahlInfo() 191 { 192 super(); 193 } 194 195 /** 196 * Getter for property {@code bankCode}. 197 * 198 * @return The german bank code identifying the bank (field 1). 199 */ 200 public Bankleitzahl getBankCode() 201 { 202 return this.bankCode; 203 } 204 205 /** 206 * Setter for property {@code bankCode}. 207 * 208 * @param value The german bank code identifying the bank (field 1). 209 */ 210 public void setBankCode( final Bankleitzahl value ) 211 { 212 this.bankCode = value; 213 } 214 215 /** 216 * Getter for property {@code headOffice}. 217 * 218 * @return {@code true} if this record specifies a bank which is to be used for transactions; {@code false} if this 219 * record specifies a branch office of a bank not to be used for transactions but sharing a bank code (field 2). 220 */ 221 public boolean isHeadOffice() 222 { 223 return this.headOffice; 224 } 225 226 /** 227 * Setter for property {@code headOffice}. 228 * 229 * @param value {@code true} if this record specifies a bank which is to be used for transactions; {@code false} if 230 * this record specifies a branch office of a bank not to be used for transactions but sharing a bank code 231 * (field 2). 232 */ 233 public void setHeadOffice( final boolean value ) 234 { 235 this.headOffice = value; 236 } 237 238 /** 239 * Getter for property {@code name}. 240 * 241 * @return The name of the bank (field 3). 242 */ 243 public String getName() 244 { 245 return this.name; 246 } 247 248 /** 249 * Setter for property {@code name}. 250 * 251 * @param value The name of the bank (field 3). 252 */ 253 public void setName( final String value ) 254 { 255 this.name = value; 256 } 257 258 /** 259 * Getter for property {@code postalCode}. 260 * 261 * @return The postal code of the city the bank is resident (field 4). 262 */ 263 public int getPostalCode() 264 { 265 return this.postalCode; 266 } 267 268 /** 269 * Setter for property {@code postalCode}. 270 * 271 * @param value The postal code of the city the bank is resident (field 4). 272 */ 273 public void setPostalCode( final int value ) 274 { 275 this.postalCode = value; 276 } 277 278 /** 279 * Getter for property {@code city}. 280 * 281 * @return The city the bank resides at (field 5). 282 */ 283 public String getCity() 284 { 285 return this.city; 286 } 287 288 /** 289 * Setter for property {@code city}. 290 * 291 * @param value The city the bank resides at (field 5). 292 */ 293 public void setCity( final String value ) 294 { 295 this.city = value; 296 } 297 298 /** 299 * Getter for property {@code description}. 300 * 301 * @return A description of the bank including information regarding the city the bank resides to be used for 302 * displaying on e.g. invoices (field 6). 303 */ 304 public String getDescription() 305 { 306 return this.description; 307 } 308 309 /** 310 * Setter for property {@code description}. 311 * 312 * @param value A description of the bank including information regarding the city the bank resides to be used for 313 * displaying on e.g. invoices (field 6). 314 */ 315 public void setDescription( final String value ) 316 { 317 this.description = value; 318 } 319 320 /** 321 * Getter for property {@code panInstituteNumber}. 322 * 323 * @return The institute number for PAN or {@code 0} if no number is available (field 7). 324 */ 325 public int getPanInstituteNumber() 326 { 327 return this.panInstituteNumber; 328 } 329 330 /** 331 * Setter for property {@code panInstituteNumber}. 332 * 333 * @param value The institute number for PAN or {@code 0} if no number is available (field 7). 334 */ 335 public void setPanInstituteNumber( final int value ) 336 { 337 this.panInstituteNumber = value; 338 } 339 340 /** 341 * Getter for property {@code bic}. 342 * 343 * @return The SWIFT Bank Identifier Code (field 8). 344 */ 345 public String getBic() 346 { 347 return this.bic; 348 } 349 350 /** 351 * Setter for property {@code bic}. 352 * 353 * @param value The SWIFT Bank Identifier Code (field 8). 354 */ 355 public void setBic( final String value ) 356 { 357 this.bic = value; 358 } 359 360 /** 361 * Getter for property {@code validationLabel}. 362 * 363 * @return The label for the algorithm to be used for validating account numbers (field 9). 364 */ 365 public String getValidationLabel() 366 { 367 return this.validationLabel; 368 } 369 370 /** 371 * Setter for property {@code validationLabel}. 372 * 373 * @param value The label for the algorithm to be used for validating account numbers (field 9). 374 */ 375 public void setValidationLabel( final String value ) 376 { 377 this.validationLabel = value; 378 } 379 380 /** 381 * Getter for property {@code serialNumber}. 382 * 383 * @return The serial number of the record (field 10). 384 */ 385 public Integer getSerialNumber() 386 { 387 return this.serialNumber; 388 } 389 390 /** 391 * Setter for property {@code serialNumber}. 392 * 393 * @param value The serial number of the record (field 10). 394 */ 395 public void setSerialNumber( final Integer value ) 396 { 397 this.serialNumber = value; 398 } 399 400 /** 401 * Getter for property {@code changeLabel}. 402 * 403 * @return The label used to indicate changes of the record since previous files (field 11). 404 */ 405 public char getChangeLabel() 406 { 407 return this.changeLabel; 408 } 409 410 /** 411 * Setter for property {@code changeLabel}. 412 * 413 * @param value The label used to indicate changes of the record since previous files (field 11). 414 */ 415 public void setChangeLabel( final char value ) 416 { 417 this.changeLabel = value; 418 } 419 420 /** 421 * Getter for property {@code markedForDeletion}. 422 * 423 * @return {@code true} if this record will be deleted from upcoming files; {@code false} if not (field 12). 424 */ 425 public boolean isMarkedForDeletion() 426 { 427 return this.markedForDeletion; 428 } 429 430 /** 431 * Setter for property {@code markedForDeletion}. 432 * 433 * @param value {@code true} if this record will be deleted from upcoming files; {@code false} if not (field 12). 434 */ 435 public void setMarkedForDeletion( final boolean value ) 436 { 437 this.markedForDeletion = value; 438 } 439 440 /** 441 * Getter for property {@code replacingBankCode}. 442 * 443 * @return The bank code of the bank replacing this bank if this record is marked for deletion or {@code null} if no 444 * replacing bank code is specified or the record is not to be deleted (field 13). 445 */ 446 public Bankleitzahl getReplacingBankCode() 447 { 448 return this.replacingBankCode; 449 } 450 451 /** 452 * Setter for property {@code replacingBankCode}. 453 * 454 * @param value The bank code of the bank replacing this bank if this record is marked for deletion or {@code null} 455 * if no replacing bank code is specified or the record is not to be deleted (field 13). 456 */ 457 public void setReplacingBankCode( final Bankleitzahl value ) 458 { 459 this.replacingBankCode = value; 460 } 461 462 /** 463 * Getter for property {@code ibanRuleLabel}. 464 * 465 * @return The label of the rule to use for generating international bank account numbers or {@code null}, if 466 * generating an IBAN for an account at the bank identified by the bank code of this record is not supported 467 * (field 14). 468 * 469 * @since 1.15 470 */ 471 public Integer getIbanRuleLabel() 472 { 473 return this.ibanRuleLabel; 474 } 475 476 /** 477 * Setter for property {@code ibanRuleLabel}. 478 * 479 * @param value The label of the algorithm to use for generating international bank account numbers or {@code null}, 480 * if generating an IBAN for an account at the bank identified by the bank code of this record should not be 481 * supported (field 14). 482 * 483 * @since 1.15 484 */ 485 public void setIbanRuleLabel( final Integer value ) 486 { 487 this.ibanRuleLabel = value; 488 } 489 490 /** 491 * Getter for property {@code ibanRuleVersion}. 492 * 493 * @return The version of the rule to use for generating international bank account numbers or {@code null}, if 494 * generating an IBAN for an account at the bank identified by the bank code of this record is not supported 495 * (field 14). 496 * 497 * @since 1.15 498 */ 499 public Integer getIbanRuleVersion() 500 { 501 return this.ibanRuleVersion; 502 } 503 504 /** 505 * Setter for property {@code ibanRuleVersion}. 506 * 507 * @param value The label of the rule to use for generating international bank account numbers or {@code null}, 508 * if generating an IBAN for an account at the bank identified by the bank code of this record should not be 509 * supported (field 14). 510 * 511 * @since 1.15 512 */ 513 public void setIbanRuleVersion( final Integer value ) 514 { 515 this.ibanRuleVersion = value; 516 } 517 518 /** 519 * Getter for property {@code creationDate}. 520 * 521 * @return The date the record got created at. 522 * 523 * @since 1.15 524 */ 525 public Date getCreationDate() 526 { 527 return (Date) ( this.creationDate != null ? this.creationDate.clone() : null ); 528 } 529 530 /** 531 * Setter for property {@code creationDate}. 532 * 533 * @param value The new date the record got created at. 534 * 535 * @since 1.15 536 */ 537 public void setCreationDate( final Date value ) 538 { 539 this.creationDate = (Date) ( value != null ? value.clone() : null ); 540 } 541 542 /** 543 * Getter for property {@code modificationDate}. 544 * 545 * @return The date the record got modified at. 546 * 547 * @since 1.15 548 */ 549 public Date getModificationDate() 550 { 551 return (Date) ( this.modificationDate != null ? this.modificationDate.clone() : null ); 552 } 553 554 /** 555 * Setter for property {@code modificationDate}. 556 * 557 * @param value The new date the record got modified at. 558 * 559 * @since 1.15 560 */ 561 public void setModificationDate( final Date value ) 562 { 563 this.modificationDate = (Date) ( value != null ? value.clone() : null ); 564 } 565 566 /** 567 * Getter for property {@code deletionDate}. 568 * 569 * @return The date the record got deleted at. 570 * 571 * @since 1.15 572 */ 573 public Date getDeletionDate() 574 { 575 return (Date) ( this.deletionDate != null ? this.deletionDate.clone() : null ); 576 } 577 578 /** 579 * Setter for property {@code deletionDate}. 580 * 581 * @param value The new date the record got deleted at. 582 * 583 * @since 1.15 584 */ 585 public void setDeletionDate( final Date value ) 586 { 587 this.deletionDate = (Date) ( value != null ? value.clone() : null ); 588 } 589 590 /** 591 * Parses text from a Bankleitzahlendatei to initialize the instance. 592 * <p>This method may be used for reading records from the german Bankleitzahlendatei as published by 593 * <a href="http://www.bundesbank.de/index.en.php">Deutsche Bundesbank</a>. 594 * It supports reading the format as of june 2006.</p> 595 * 596 * @param line A line from a Bankleitzahlendatei to parse. 597 * 598 * @throws NullPointerException if {@code text} is {@code null}. 599 * @throws IllegalArgumentException if the parse fails. 600 * 601 * @deprecated As of 1.15, please use class {@link org.jdtaus.banking.util.BankleitzahlenDatei}. 602 */ 603 public void parse( final String line ) 604 { 605 if ( line == null ) 606 { 607 throw new NullPointerException( "line" ); 608 } 609 610 Number blz; 611 String field; 612 final NumberFormat plzFmt = new DecimalFormat( "00000" ); 613 final NumberFormat serFmt = new DecimalFormat( "000000" ); 614 final NumberFormat blzFmt = new DecimalFormat( "00000000" ); 615 616 try 617 { 618 // Field 1 619 this.bankCode = Bankleitzahl.parse( line.substring( FIELD_TO_OFFSET[0], FIELD_TO_ENDOFFSET[0] ).trim() ); 620 // Field 2 621 this.headOffice = "1".equals( line.substring( FIELD_TO_OFFSET[1], FIELD_TO_ENDOFFSET[1] ) ); 622 // Field 3 623 this.name = line.substring( FIELD_TO_OFFSET[2], FIELD_TO_ENDOFFSET[2] ).trim(); 624 // Field 4 625 this.postalCode = 626 plzFmt.parse( line.substring( FIELD_TO_OFFSET[3], FIELD_TO_ENDOFFSET[3] ).trim() ).intValue(); 627 628 // Field 5 629 this.city = line.substring( FIELD_TO_OFFSET[4], FIELD_TO_ENDOFFSET[4] ).trim(); 630 // Field 6 631 this.description = line.substring( FIELD_TO_OFFSET[5], FIELD_TO_ENDOFFSET[5] ).trim(); 632 // Field 7 633 field = line.substring( FIELD_TO_OFFSET[6], FIELD_TO_ENDOFFSET[6] ).trim(); 634 this.panInstituteNumber = field.length() > 0 ? plzFmt.parse( field ).intValue() : 0; 635 // Field 8 636 this.bic = line.substring( FIELD_TO_OFFSET[7], FIELD_TO_ENDOFFSET[7] ).trim(); 637 // Field 9 638 this.validationLabel = line.substring( FIELD_TO_OFFSET[8], FIELD_TO_ENDOFFSET[8] ).trim(); 639 // Field 10 640 this.serialNumber = new Integer( 641 serFmt.parse( line.substring( FIELD_TO_OFFSET[9], FIELD_TO_ENDOFFSET[9] ).trim() ).intValue() ); 642 643 // Field 11 644 this.changeLabel = line.substring( FIELD_TO_OFFSET[10], FIELD_TO_ENDOFFSET[10] ).toCharArray()[0]; 645 // Field 12 646 this.markedForDeletion = "1".equals( line.substring( FIELD_TO_OFFSET[11], FIELD_TO_ENDOFFSET[11] ) ); 647 // Field 13 648 blz = blzFmt.parse( line.substring( FIELD_TO_OFFSET[12], FIELD_TO_ENDOFFSET[12] ).trim() ); 649 if ( blz.intValue() != 0 ) 650 { 651 this.replacingBankCode = Bankleitzahl.valueOf( blz ); 652 } 653 else 654 { 655 this.replacingBankCode = null; 656 } 657 } 658 catch ( final ParseException e ) 659 { 660 throw (IllegalArgumentException) new IllegalArgumentException( line ).initCause( e ); 661 } 662 catch ( final IndexOutOfBoundsException e ) 663 { 664 throw (IllegalArgumentException) new IllegalArgumentException( line ).initCause( e ); 665 } 666 } 667 668 /** 669 * Creates and returns a copy of this object. 670 * 671 * @return A clone of this instance. 672 */ 673 public Object clone() 674 { 675 try 676 { 677 return super.clone(); 678 } 679 catch ( final CloneNotSupportedException e ) 680 { 681 throw new AssertionError( e ); 682 } 683 } 684 685 /** 686 * Indicates whether some other object is equal to this one. 687 * 688 * @param o The reference object with which to compare. 689 * 690 * @return {@code true} if this object is the same as {@code o}; {@code false} otherwise. 691 */ 692 public boolean equals( final Object o ) 693 { 694 boolean ret = o == this; 695 696 if ( !ret && o instanceof BankleitzahlInfo ) 697 { 698 final BankleitzahlInfo that = (BankleitzahlInfo) o; 699 ret = this.serialNumber == null ? that.serialNumber == null : this.serialNumber.equals( that.serialNumber ); 700 } 701 702 return ret; 703 } 704 705 /** 706 * Returns a hash code value for this object. 707 * 708 * @return A hash code value for this object. 709 */ 710 public int hashCode() 711 { 712 return this.serialNumber == null ? 0 : this.serialNumber.intValue(); 713 } 714 715 /** 716 * Returns a string representation of the object. 717 * 718 * @return A string representation of the object. 719 */ 720 public String toString() 721 { 722 return super.toString() + this.internalString(); 723 } 724 725 /** 726 * Creates a string representing the properties of the instance. 727 * 728 * @return a string representing the properties of the instance. 729 */ 730 private String internalString() 731 { 732 return new StringBuffer( 500 ).append( '{' ). 733 append( "headOffice=" ).append( this.headOffice ). 734 append( ", bankCode=" ).append( this.bankCode ). 735 append( ", name=" ).append( this.name ). 736 append( ", bic=" ).append( this.bic ). 737 append( ", changeLabel=" ).append( this.changeLabel ). 738 append( ", city=" ).append( this.city ). 739 append( ", markedForDeletion=" ).append( this.markedForDeletion ). 740 append( ", panInstituteNumber=" ).append( this.panInstituteNumber ). 741 append( ", postalCode=" ).append( this.postalCode ). 742 append( ", replacingBankCode=" ).append( this.replacingBankCode ). 743 append( ", serialNumber=" ).append( this.serialNumber ). 744 append( ", description=" ).append( this.description ). 745 append( ", validationLabel=" ).append( this.validationLabel ). 746 append( ", ibanRuleLabel=" ).append( this.ibanRuleLabel ). 747 append( ", ibanRuleVersion=" ).append( this.ibanRuleVersion ). 748 append( ", creationDate=" ).append( this.creationDate ). 749 append( ", modificationDate=" ).append( this.modificationDate ). 750 append( ", deletionDate=" ).append( this.deletionDate ). 751 append( '}' ).toString(); 752 753 } 754 755}