1 | /* |
2 | * jDTAUS Banking API |
3 | * Copyright (C) 2005 Christian Schulte |
4 | * <cs@schulte.it> |
5 | * |
6 | * This library is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU Lesser General Public |
8 | * License as published by the Free Software Foundation; either |
9 | * version 2.1 of the License, or any later version. |
10 | * |
11 | * This library is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | * Lesser General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU Lesser General Public |
17 | * License along with this library; if not, write to the Free Software |
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
19 | * |
20 | */ |
21 | package org.jdtaus.banking; |
22 | |
23 | import java.lang.ref.Reference; |
24 | import java.lang.ref.SoftReference; |
25 | import java.text.DecimalFormat; |
26 | import java.text.ParseException; |
27 | import java.text.ParsePosition; |
28 | import java.util.Collections; |
29 | import java.util.HashMap; |
30 | import java.util.Map; |
31 | |
32 | /** |
33 | * Unique identifier to a particular office (branch) of a german bank. |
34 | * <p>A Bankleitzahl (BLZ) is a positive integer with a maximum of eight digits. For further information see the |
35 | * <a href="../../../doc-files/merkblatt_bankleitzahlendatei.pdf">Merkblatt Bankleitzahlendatei</a>. An updated version of the document |
36 | * may be found at <a href="http://www.bundesbank.de">Deutsche Bundesbank</a>.</p> |
37 | * |
38 | * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> |
39 | * @version $JDTAUS: Bankleitzahl.java 8725 2012-10-04 21:26:50Z schulte $ |
40 | * |
41 | * @see BankleitzahlenVerzeichnis |
42 | */ |
43 | public final class Bankleitzahl extends Number implements Comparable |
44 | { |
45 | |
46 | /** |
47 | * Constant for the electronic format of a Bankleitzahl. |
48 | * <p>The electronic format of a Bankleitzahl is an eigth digit number with leading zeros omitted (e.g. 5678).</p> |
49 | */ |
50 | public static final int ELECTRONIC_FORMAT = 3001; |
51 | |
52 | /** |
53 | * Constant for the letter format of a Bankleitzahl. |
54 | * <p>The letter format of a Bankleitzahl is an eigth digit number with leading zeros omitted separated by spaces |
55 | * between the first three digits and the second three digits, and between the second three digits and the last two |
56 | * digits (e.g. 123 456 78).</p> |
57 | */ |
58 | public static final int LETTER_FORMAT = 3002; |
59 | |
60 | /** Maximum number of digits of a Bankleitzahl. */ |
61 | public static final int MAX_DIGITS = 8; |
62 | |
63 | /** Maximum number of characters of a Bankleitzahl. */ |
64 | public static final int MAX_CHARACTERS = 10; |
65 | |
66 | /** {@code 10^0..10^7}. */ |
67 | private static final double[] EXP10 = |
68 | { |
69 | 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000 |
70 | }; |
71 | |
72 | /** Serial version UID for backwards compatibility with 1.0.x classes. */ |
73 | private static final long serialVersionUID = -3329406998979147668L; |
74 | |
75 | /** Used to cache instances. */ |
76 | private static volatile Reference cacheReference = new SoftReference( null ); |
77 | |
78 | /** |
79 | * German bank code. |
80 | * @serial |
81 | */ |
82 | private int blz; |
83 | |
84 | /** |
85 | * Clearing area code of this Bankleitzahl. |
86 | * @serial |
87 | */ |
88 | private int clearingArea; |
89 | |
90 | /** |
91 | * Locality code of this Bankleitzahl. |
92 | * @serial |
93 | */ |
94 | private int localityCode; |
95 | |
96 | /** |
97 | * Network code of this Bankleitzahl. |
98 | * @serial |
99 | */ |
100 | private int networkCode; |
101 | |
102 | /** |
103 | * Institute code of this Bankleitzahl. |
104 | * @serial |
105 | */ |
106 | private int instituteCode; |
107 | |
108 | /** |
109 | * Creates a new {@code Bankleitzahl} instance. |
110 | * |
111 | * @param bankCode The integer to create an instance from. |
112 | * |
113 | * @throws IllegalArgumentException if {@code bankCode} is negative, zero, greater than 99999999 or its first digit |
114 | * is either zero or nine. |
115 | * |
116 | * @see #checkBankleitzahl(Number) |
117 | */ |
118 | private Bankleitzahl( final Number bankCode ) |
119 | { |
120 | if ( !Bankleitzahl.checkBankleitzahl( bankCode ) ) |
121 | { |
122 | throw new IllegalArgumentException( bankCode.toString() ); |
123 | } |
124 | |
125 | final int[] digits = Bankleitzahl.toDigits( bankCode.longValue() ); |
126 | final long lCode = bankCode.longValue(); |
127 | |
128 | this.clearingArea = digits[7]; |
129 | this.localityCode = (int) Math.floor( lCode / Bankleitzahl.EXP10[5] ); |
130 | this.networkCode = digits[4]; |
131 | this.instituteCode = |
132 | (int) Math.floor( lCode - digits[7] * Bankleitzahl.EXP10[7] - |
133 | digits[6] * Bankleitzahl.EXP10[6] - |
134 | digits[5] * Bankleitzahl.EXP10[5] - |
135 | digits[4] * Bankleitzahl.EXP10[4] ); |
136 | |
137 | this.blz = bankCode.intValue(); |
138 | } |
139 | |
140 | /** |
141 | * Parses text from a string to produce a {@code Bankleitzahl}. |
142 | * <p>The method attempts to parse text starting at the index given by {@code pos}. If parsing succeeds, then the |
143 | * index of {@code pos} is updated to the index after the last character used (parsing does not necessarily use all |
144 | * characters up to the end of the string), and the parsed value is returned. The updated {@code pos} can be used to |
145 | * indicate the starting point for the next call to this method.</p> |
146 | * |
147 | * @param bankCode A Bankleitzahl in either electronic or letter format. |
148 | * @param pos A {@code ParsePosition} object with index and error index information as described above. |
149 | * |
150 | * @return The parsed value, or {@code null} if the parse fails. |
151 | * |
152 | * @throws NullPointerException if either {@code bankCode} or {@code pos} is {@code null}. |
153 | */ |
154 | public static Bankleitzahl parse( final String bankCode, final ParsePosition pos ) |
155 | { |
156 | if ( bankCode == null ) |
157 | { |
158 | throw new NullPointerException( "bankCode" ); |
159 | } |
160 | if ( pos == null ) |
161 | { |
162 | throw new NullPointerException( "pos" ); |
163 | } |
164 | |
165 | Bankleitzahl ret = null; |
166 | boolean sawSpace = false; |
167 | boolean failed = false; |
168 | final ParsePosition fmtPos = new ParsePosition( 0 ); |
169 | final int len = bankCode.length(); |
170 | final int startIndex = pos.getIndex(); |
171 | final int maxIndex = startIndex + MAX_CHARACTERS; |
172 | final StringBuffer digits = new StringBuffer( MAX_DIGITS ); |
173 | int mode = ELECTRONIC_FORMAT; |
174 | int part = 0; |
175 | int partStart = 0; |
176 | int partEnd = 2; |
177 | int digit = 0; |
178 | int i = startIndex; |
179 | |
180 | for ( ; i < len && i < maxIndex && digits.length() < MAX_DIGITS; i++ ) |
181 | { |
182 | final char c = bankCode.charAt( i ); |
183 | |
184 | if ( Character.isDigit( c ) ) |
185 | { |
186 | sawSpace = false; |
187 | |
188 | if ( mode == LETTER_FORMAT ) |
189 | { |
190 | if ( digit < partStart || digit > partEnd ) |
191 | { |
192 | failed = true; |
193 | } |
194 | else |
195 | { |
196 | digits.append( c ); |
197 | } |
198 | } |
199 | else |
200 | { |
201 | digits.append( c ); |
202 | } |
203 | |
204 | digit++; |
205 | } |
206 | else if ( c == ' ' ) |
207 | { |
208 | if ( sawSpace || i == startIndex || ( mode == ELECTRONIC_FORMAT && digit != 3 ) ) |
209 | { |
210 | failed = true; |
211 | } |
212 | else |
213 | { |
214 | mode = LETTER_FORMAT; |
215 | switch ( part ) |
216 | { |
217 | case 0: |
218 | partStart = 3; |
219 | partEnd = 5; |
220 | break; |
221 | case 1: |
222 | partStart = 6; |
223 | partEnd = 7; |
224 | break; |
225 | default: |
226 | failed = true; |
227 | break; |
228 | } |
229 | part++; |
230 | |
231 | if ( digit < partStart || digit > partEnd ) |
232 | { |
233 | failed = true; |
234 | } |
235 | } |
236 | |
237 | sawSpace = true; |
238 | } |
239 | else |
240 | { |
241 | failed = true; |
242 | } |
243 | |
244 | if ( failed ) |
245 | { |
246 | pos.setErrorIndex( i ); |
247 | break; |
248 | } |
249 | } |
250 | |
251 | if ( !failed ) |
252 | { |
253 | final Number num = new DecimalFormat( "########" ).parse( digits.toString(), fmtPos ); |
254 | |
255 | if ( num != null && fmtPos.getErrorIndex() == -1 ) |
256 | { |
257 | final String key = num.toString(); |
258 | ret = (Bankleitzahl) getCache().get( key ); |
259 | |
260 | if ( ret == null ) |
261 | { |
262 | if ( !Bankleitzahl.checkBankleitzahl( num ) ) |
263 | { |
264 | pos.setErrorIndex( startIndex ); |
265 | ret = null; |
266 | } |
267 | else |
268 | { |
269 | pos.setIndex( i ); |
270 | ret = new Bankleitzahl( num ); |
271 | getCache().put( key, ret ); |
272 | } |
273 | } |
274 | else |
275 | { |
276 | pos.setIndex( i ); |
277 | } |
278 | } |
279 | else |
280 | { |
281 | pos.setErrorIndex( startIndex ); |
282 | } |
283 | } |
284 | |
285 | return ret; |
286 | } |
287 | |
288 | /** |
289 | * Parses text from the beginning of the given string to produce a {@code Bankleitzahl}. |
290 | * <p>Unlike the {@link #parse(String, ParsePosition)} method this method throws a {@code ParseException} if |
291 | * {@code bankCode} cannot be parsed or is of invalid length.</p> |
292 | * |
293 | * @param bankCode A Bankleitzahl in either electronic or letter format. |
294 | * |
295 | * @return The parsed value. |
296 | * |
297 | * @throws NullPointerException if {@code bankCode} is {@code null}. |
298 | * @throws ParseException if the parse fails or {@code bankCode} is of invalid length. |
299 | */ |
300 | public static Bankleitzahl parse( final String bankCode ) throws ParseException |
301 | { |
302 | if ( bankCode == null ) |
303 | { |
304 | throw new NullPointerException( "bankCode" ); |
305 | } |
306 | |
307 | Bankleitzahl blz = (Bankleitzahl) getCache().get( bankCode ); |
308 | |
309 | if ( blz == null ) |
310 | { |
311 | final ParsePosition pos = new ParsePosition( 0 ); |
312 | blz = Bankleitzahl.parse( bankCode, pos ); |
313 | |
314 | if ( blz == null || pos.getErrorIndex() != -1 || pos.getIndex() < bankCode.length() ) |
315 | { |
316 | throw new ParseException( bankCode, pos.getErrorIndex() != -1 ? pos.getErrorIndex() : pos.getIndex() ); |
317 | } |
318 | else |
319 | { |
320 | getCache().put( bankCode, blz ); |
321 | } |
322 | } |
323 | |
324 | return blz; |
325 | } |
326 | |
327 | /** |
328 | * Gets a {@code Bankleitzahl} for a given number. |
329 | * |
330 | * @param bankCode A number to get a {@code Bankleitzahl} for. |
331 | * |
332 | * @return An instance for {@code bankCode}. |
333 | * |
334 | * @throws NullPointerException if {@code bankCode} is {@code null}. |
335 | * @throws IllegalArgumentException if {@code bankCode} is negative, zero, greater than 99999999 or its first digit |
336 | * is either zero or nine. |
337 | * |
338 | * @see #checkBankleitzahl(Number) |
339 | */ |
340 | public static Bankleitzahl valueOf( final Number bankCode ) |
341 | { |
342 | if ( bankCode == null ) |
343 | { |
344 | throw new NullPointerException( "bankCode" ); |
345 | } |
346 | |
347 | final String key = bankCode.toString(); |
348 | Bankleitzahl ret = (Bankleitzahl) getCache().get( key ); |
349 | |
350 | if ( ret == null ) |
351 | { |
352 | ret = new Bankleitzahl( bankCode ); |
353 | getCache().put( key, ret ); |
354 | } |
355 | |
356 | return ret; |
357 | } |
358 | |
359 | /** |
360 | * Parses text from the beginning of the given string to produce a {@code Bankleitzahl}. |
361 | * <p>Unlike the {@link #parse(String)} method this method throws an {@code IllegalArgumentException} if |
362 | * {@code bankCode} cannot be parsed or is of invalid length.</p> |
363 | * |
364 | * @param bankCode A Bankleitzahl in either electronic or letter format. |
365 | * |
366 | * @return The parsed value. |
367 | * |
368 | * @throws NullPointerException if {@code bankCode} is {@code null}. |
369 | * @throws IllegalArgumentException if the parse fails or {@code bankCode} is of invalid length. |
370 | */ |
371 | public static Bankleitzahl valueOf( final String bankCode ) |
372 | { |
373 | try |
374 | { |
375 | return Bankleitzahl.parse( bankCode ); |
376 | } |
377 | catch ( final ParseException e ) |
378 | { |
379 | throw (IllegalArgumentException) new IllegalArgumentException( bankCode ).initCause( e ); |
380 | } |
381 | } |
382 | |
383 | /** |
384 | * Checks a given number to conform to a Bankleitzahl. |
385 | * |
386 | * @param bankCode The number to check. |
387 | * |
388 | * @return {@code true} if {@code bankCode} is a valid Bankleitzahl; {@code false} if not. |
389 | */ |
390 | public static boolean checkBankleitzahl( final Number bankCode ) |
391 | { |
392 | boolean valid = bankCode != null; |
393 | |
394 | if ( valid ) |
395 | { |
396 | final long num = bankCode.longValue(); |
397 | valid = num > 0L && num < 100000000L; |
398 | if ( valid && num > 9999999 ) |
399 | { |
400 | final int[] digits = Bankleitzahl.toDigits( num ); |
401 | valid = digits[7] != 0 && digits[7] != 9; |
402 | } |
403 | } |
404 | |
405 | return valid; |
406 | } |
407 | |
408 | /** |
409 | * Returns this Bankleitzahl as an int value. |
410 | * |
411 | * @return This Bankleitzahl as an int value. |
412 | */ |
413 | public int intValue() |
414 | { |
415 | return this.blz; |
416 | } |
417 | |
418 | /** |
419 | * Returns this Bankleitzahl as a long value. |
420 | * |
421 | * @return This Bankleitzahl as a long value. |
422 | */ |
423 | public long longValue() |
424 | { |
425 | return this.blz; |
426 | } |
427 | |
428 | /** |
429 | * Returns this Bankleitzahl as a float value. |
430 | * |
431 | * @return This Bankleitzahl as a float value. |
432 | */ |
433 | public float floatValue() |
434 | { |
435 | return this.blz; |
436 | } |
437 | |
438 | /** |
439 | * Returns this Bankleitzahl as a double value. |
440 | * |
441 | * @return This Bankleitzahl as a double value. |
442 | */ |
443 | public double doubleValue() |
444 | { |
445 | return this.blz; |
446 | } |
447 | |
448 | /** |
449 | * Gets a flag indicating that this Bankleitzahl provides a clearing area code. |
450 | * |
451 | * @return {@code true} if property {@code clearingAreaCode} is supported by this instance; {@code false} if |
452 | * property {@code clearingAreaCode} is not supported by this instance. |
453 | * |
454 | * @see #getClearingAreaCode() |
455 | */ |
456 | public boolean isClearingAreaCodeSupported() |
457 | { |
458 | return this.blz > 9999999; |
459 | } |
460 | |
461 | /** |
462 | * Gets the clearing area code of this Bankleitzahl. |
463 | * <p><ol> |
464 | * <li>Berlin, Brandenburg, Mecklenburg-Vorpommern</li> |
465 | * <li>Bremen, Hamburg, Niedersachsen, Schleswig-Holstein</li> |
466 | * <li>Rheinland (Regierungsbezirke Düsseldorf, Köln)</li> |
467 | * <li>Westfalen</li> |
468 | * <li>Hessen, Rheinland-Pfalz, Saarland</li> |
469 | * <li>Baden-Württemberg</li> |
470 | * <li>Bayern</li> |
471 | * <li>Sachsen, Sachsen-Anhalt, Thüringen</li> |
472 | * </ol></p> |
473 | * |
474 | * @return Code identifying the clearing area of this Bankleitzahl. |
475 | * |
476 | * @throws UnsupportedOperationException if this Bankleitzahl does not provide clearing area information. |
477 | * |
478 | * @see #isClearingAreaCodeSupported() |
479 | * |
480 | * @deprecated Renamed to {@link #getClearingAreaCode() }. |
481 | */ |
482 | public int getClearingArea() |
483 | { |
484 | return this.getClearingAreaCode(); |
485 | } |
486 | |
487 | /** |
488 | * Gets the clearing area code of this Bankleitzahl. |
489 | * <p><ol> |
490 | * <li>Berlin, Brandenburg, Mecklenburg-Vorpommern</li> |
491 | * <li>Bremen, Hamburg, Niedersachsen, Schleswig-Holstein</li> |
492 | * <li>Rheinland (Regierungsbezirke Düsseldorf, Köln)</li> |
493 | * <li>Westfalen</li> |
494 | * <li>Hessen, Rheinland-Pfalz, Saarland</li> |
495 | * <li>Baden-Württemberg</li> |
496 | * <li>Bayern</li> |
497 | * <li>Sachsen, Sachsen-Anhalt, Thüringen</li> |
498 | * </ol></p> |
499 | * |
500 | * @return Code identifying the clearing area of this Bankleitzahl. |
501 | * |
502 | * @throws UnsupportedOperationException if this Bankleitzahl does not provide clearing area information. |
503 | * |
504 | * @see #isClearingAreaCodeSupported() |
505 | */ |
506 | public int getClearingAreaCode() |
507 | { |
508 | if ( !this.isClearingAreaCodeSupported() ) |
509 | { |
510 | throw new UnsupportedOperationException(); |
511 | } |
512 | |
513 | return this.clearingArea; |
514 | } |
515 | |
516 | /** |
517 | * Gets a flag indicating that this Bankleitzahl provides a locality code. |
518 | * |
519 | * @return {@code true} if property {@code localityCode} is supported by this instance; {@code false} if property |
520 | * {@code localityCode} is not supported by this instance. |
521 | * |
522 | * @see #getLocalityCode() |
523 | */ |
524 | public boolean isLocalityCodeSupported() |
525 | { |
526 | return this.blz > 99999; |
527 | } |
528 | |
529 | /** |
530 | * Gets the locality code of this Bankleitzahl. |
531 | * |
532 | * @return Locality code of this Bankleitzahl. |
533 | * |
534 | * @throws UnsupportedOperationException if this Bankleitzahl does not provide a locality code. |
535 | * |
536 | * @see #isLocalityCodeSupported() |
537 | */ |
538 | public int getLocalityCode() |
539 | { |
540 | if ( !this.isLocalityCodeSupported() ) |
541 | { |
542 | throw new UnsupportedOperationException(); |
543 | } |
544 | |
545 | return this.localityCode; |
546 | } |
547 | |
548 | /** |
549 | * Gets a flag indicating that this Bankleitzahl provides a network code. |
550 | * |
551 | * @return {@code true} if property {@code networkCode} is supported by this instance; {@code false} if property |
552 | * {@code networkCode} is not supported by this instance. |
553 | * |
554 | * @see #getNetworkCode() |
555 | */ |
556 | public boolean isNetworkCodeSupported() |
557 | { |
558 | return this.blz > 9999; |
559 | } |
560 | |
561 | /** |
562 | * Gets the network code of this Bankleitzahl. |
563 | * <p><table border="0"> |
564 | * <tr> |
565 | * <td>0</td> |
566 | * <td>Deutsche Bundesbank</td> |
567 | * </tr> |
568 | * <tr> |
569 | * <td>1 - 3</td> |
570 | * <td> |
571 | * Kreditinstitute, soweit nicht in einer der anderen Gruppen erfasst |
572 | * </td> |
573 | * </tr> |
574 | * <tr> |
575 | * <td>4</td> |
576 | * <td>Commerzbank</td> |
577 | * </tr> |
578 | * <tr> |
579 | * <td>5</td> |
580 | * <td>Girozentralen und Sparkassen</td> |
581 | * </tr> |
582 | * <tr> |
583 | * <td>6 + 9</td> |
584 | * <td> |
585 | * Genossenschaftliche Zentralbanken, Kreditgenossenschaften sowie ehemalige |
586 | * Genossenschaften |
587 | * </td> |
588 | * </tr> |
589 | * <tr> |
590 | * <td>7</td> |
591 | * <td>Deutsche Bank</td> |
592 | * </tr> |
593 | * <tr> |
594 | * <td>8</td> |
595 | * <td>Dresdner Bank</td> |
596 | * </tr> |
597 | * </table></p> |
598 | * |
599 | * @return Network code of this Bankleitzahl. |
600 | * |
601 | * @throws UnsupportedOperationException if this Bankleitzahl does not provide a network code. |
602 | * |
603 | * @see #isNetworkCodeSupported() |
604 | */ |
605 | public int getNetworkCode() |
606 | { |
607 | if ( !this.isNetworkCodeSupported() ) |
608 | { |
609 | throw new UnsupportedOperationException(); |
610 | } |
611 | |
612 | return this.networkCode; |
613 | } |
614 | |
615 | /** |
616 | * Gets the institute code of this Bankleitzahl. |
617 | * |
618 | * @return Institute code of this Bankleitzahl. |
619 | */ |
620 | public int getInstituteCode() |
621 | { |
622 | return this.instituteCode; |
623 | } |
624 | |
625 | /** |
626 | * Formats a Bankleitzahl and appends the resulting text to the given string buffer. |
627 | * |
628 | * @param style The style to use ({@code ELECTRONIC_FORMAT} or {@code LETTER_FORMAT}). |
629 | * @param toAppendTo The buffer to which the formatted text is to be appended. |
630 | * |
631 | * @return The value passed in as {@code toAppendTo}. |
632 | * |
633 | * @throws NullPointerException if {@code toAppendTo} is {@code null}. |
634 | * @throws IllegalArgumentException if {@code style} is neither {@code ELECTRONIC_FORMAT} nor {@code LETTER_FORMAT}. |
635 | * |
636 | * @see #ELECTRONIC_FORMAT |
637 | * @see #LETTER_FORMAT |
638 | */ |
639 | public StringBuffer format( final int style, final StringBuffer toAppendTo ) |
640 | { |
641 | if ( toAppendTo == null ) |
642 | { |
643 | throw new NullPointerException( "toAppendTo" ); |
644 | } |
645 | if ( style != Bankleitzahl.ELECTRONIC_FORMAT && style != Bankleitzahl.LETTER_FORMAT ) |
646 | { |
647 | throw new IllegalArgumentException( Integer.toString( style ) ); |
648 | } |
649 | |
650 | final int[] digits = Bankleitzahl.toDigits( this.blz ); |
651 | for ( int i = digits.length - 1, lastDigit = 0; i >= 0; i-- ) |
652 | { |
653 | if ( digits[i] != 0 || lastDigit > 0 ) |
654 | { |
655 | toAppendTo.append( digits[i] ); |
656 | lastDigit++; |
657 | } |
658 | |
659 | if ( style == Bankleitzahl.LETTER_FORMAT && ( lastDigit == 3 || lastDigit == 6 ) ) |
660 | { |
661 | toAppendTo.append( ' ' ); |
662 | } |
663 | } |
664 | |
665 | return toAppendTo; |
666 | } |
667 | |
668 | /** |
669 | * Formats a Bankleitzahl to produce a string. Same as |
670 | * <blockquote> |
671 | * {@link #format(int, StringBuffer) format<code>(style, new StringBuffer()).toString()</code>} |
672 | * </blockquote> |
673 | * |
674 | * @param style The style to use ({@code ELECTRONIC_FORMAT} or {@code LETTER_FORMAT}). |
675 | * |
676 | * @return The formatted string. |
677 | * |
678 | * @throws IllegalArgumentException if {@code style} is neither {@code ELECTRONIC_FORMAT} nor {@code LETTER_FORMAT}. |
679 | * |
680 | * @see #ELECTRONIC_FORMAT |
681 | * @see #LETTER_FORMAT |
682 | */ |
683 | public String format( final int style ) |
684 | { |
685 | return this.format( style, new StringBuffer() ).toString(); |
686 | } |
687 | |
688 | /** |
689 | * Formats a Bankleitzahl to produce a string. Same as |
690 | * <blockquote> |
691 | * {@link #format(int) bankleitzahl.format(ELECTRONIC_FORMAT)} |
692 | * </blockquote> |
693 | * |
694 | * @param bankleitzahl The {@code Bankleitzahl} instance to format. |
695 | * |
696 | * @return The formatted string. |
697 | * |
698 | * @throws NullPointerException if {@code bankleitzahl} is {@code null}. |
699 | */ |
700 | public static String toString( final Bankleitzahl bankleitzahl ) |
701 | { |
702 | if ( bankleitzahl == null ) |
703 | { |
704 | throw new NullPointerException( "bankleitzahl" ); |
705 | } |
706 | |
707 | return bankleitzahl.format( ELECTRONIC_FORMAT ); |
708 | } |
709 | |
710 | /** |
711 | * Creates an array holding the digits of {@code number}. |
712 | * |
713 | * @param number The number to return the digits for. |
714 | * |
715 | * @return An array holding the digits of {@code number}. |
716 | */ |
717 | private static int[] toDigits( final long number ) |
718 | { |
719 | int i; |
720 | int j; |
721 | int subst; |
722 | final int[] ret = new int[ MAX_DIGITS ]; |
723 | |
724 | for ( i = MAX_DIGITS - 1; i >= 0; i-- ) |
725 | { |
726 | for ( j = i + 1, subst = 0; j < MAX_DIGITS; j++ ) |
727 | { |
728 | subst += ret[j] * EXP10[j]; |
729 | } |
730 | ret[i] = (int) Math.floor( ( number - subst ) / EXP10[i] ); |
731 | } |
732 | |
733 | return ret; |
734 | } |
735 | |
736 | /** |
737 | * Creates a string representing the properties of the instance. |
738 | * |
739 | * @return A string representing the properties of the instance. |
740 | */ |
741 | private String internalString() |
742 | { |
743 | return new StringBuffer( 500 ).append( '{' ). |
744 | append( "blz=" ).append( this.blz ). |
745 | append( ", clearingAreaCodeSupported=" ). |
746 | append( this.isClearingAreaCodeSupported() ). |
747 | append( ", clearingArea=" ).append( this.clearingArea ). |
748 | append( ", instituteCode=" ).append( this.instituteCode ). |
749 | append( ", localityCodeSupported=" ). |
750 | append( this.isLocalityCodeSupported() ). |
751 | append( ", localityCode=" ).append( this.localityCode ). |
752 | append( ", networkCodeSupported=" ). |
753 | append( this.isNetworkCodeSupported() ). |
754 | append( ", networkCode=" ).append( this.networkCode ). |
755 | append( '}' ).toString(); |
756 | |
757 | } |
758 | |
759 | /** |
760 | * Gets the current cache instance. |
761 | * |
762 | * @return Current cache instance. |
763 | */ |
764 | private static Map getCache() |
765 | { |
766 | Map cache = (Map) cacheReference.get(); |
767 | if ( cache == null ) |
768 | { |
769 | cache = Collections.synchronizedMap( new HashMap( 1024 ) ); |
770 | cacheReference = new SoftReference( cache ); |
771 | } |
772 | |
773 | return cache; |
774 | } |
775 | |
776 | /** |
777 | * Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer |
778 | * as this object is less than, equal to, or greater than the specified object.<p> |
779 | * |
780 | * @param o The Object to be compared. |
781 | * @return A negative integer, zero, or a positive integer as this object is less than, equal to, or greater than |
782 | * the specified object. |
783 | * |
784 | * @throws NullPointerException if {@code o} is {@code null}. |
785 | * @throws ClassCastException if the specified object's type prevents it from being compared to this Object. |
786 | */ |
787 | public int compareTo( final Object o ) |
788 | { |
789 | if ( o == null ) |
790 | { |
791 | throw new NullPointerException( "o" ); |
792 | } |
793 | if ( !( o instanceof Bankleitzahl ) ) |
794 | { |
795 | throw new ClassCastException( o.getClass().getName() ); |
796 | } |
797 | |
798 | int result = 0; |
799 | final Bankleitzahl that = (Bankleitzahl) o; |
800 | |
801 | if ( !this.equals( that ) ) |
802 | { |
803 | result = this.blz > that.blz |
804 | ? 1 |
805 | : -1; |
806 | } |
807 | |
808 | return result; |
809 | } |
810 | |
811 | /** |
812 | * Indicates whether some other object is equal to this one. |
813 | * |
814 | * @param o The reference object with which to compare. |
815 | * |
816 | * @return {@code true} if this object is the same as {@code o}; {@code false} otherwise. |
817 | */ |
818 | public boolean equals( final Object o ) |
819 | { |
820 | boolean equal = o == this; |
821 | |
822 | if ( !equal && o instanceof Bankleitzahl ) |
823 | { |
824 | equal = this.blz == ( (Bankleitzahl) o ).blz; |
825 | } |
826 | |
827 | return equal; |
828 | } |
829 | |
830 | /** |
831 | * Returns a hash code value for this object. |
832 | * |
833 | * @return A hash code value for this object. |
834 | */ |
835 | public int hashCode() |
836 | { |
837 | return this.blz; |
838 | } |
839 | |
840 | /** |
841 | * Returns a string representation of the object. |
842 | * |
843 | * @return A string representation of the object. |
844 | */ |
845 | public String toString() |
846 | { |
847 | return super.toString() + this.internalString(); |
848 | } |
849 | |
850 | } |