1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
34
35
36
37
38
39 public final class Referenznummer10 extends Number implements Comparable
40 {
41
42
43
44
45
46 public static final int ELECTRONIC_FORMAT = 5001;
47
48
49
50
51
52
53
54 public static final int LETTER_FORMAT = 5002;
55
56
57 public static final int MAX_DIGITS = 10;
58
59
60 public static final int MAX_CHARACTERS = 13;
61
62
63 private static final double[] EXP10 =
64 {
65 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000,
66 1000000000
67 };
68
69
70 private static final long serialVersionUID = -72660089907415650L;
71
72
73 private static volatile Reference cacheReference = new SoftReference( null );
74
75
76
77
78
79 private long ref;
80
81
82
83
84
85
86
87
88
89
90 private Referenznummer10( final Number referenceCode )
91 {
92 if ( !Referenznummer10.checkReferenznummer10( referenceCode ) )
93 {
94 throw new IllegalArgumentException( referenceCode.toString() );
95 }
96
97 this.ref = referenceCode.longValue();
98 }
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114 public static Referenznummer10 parse( final String referenceCode, final ParsePosition pos )
115 {
116 if ( referenceCode == null )
117 {
118 throw new NullPointerException( "referenceCode" );
119 }
120 if ( pos == null )
121 {
122 throw new NullPointerException( "pos" );
123 }
124
125 Referenznummer10 ret = null;
126 boolean sawSpace = false;
127 boolean failed = false;
128
129 final ParsePosition fmtPos = new ParsePosition( 0 );
130 final int len = referenceCode.length();
131 final int startIndex = pos.getIndex();
132 final int maxIndex = startIndex + MAX_CHARACTERS;
133 final StringBuffer digits = new StringBuffer( MAX_DIGITS );
134 int mode = ELECTRONIC_FORMAT;
135 int part = 0;
136 int partStart = 0;
137 int partEnd = 2;
138 int digit = 0;
139 int i = startIndex;
140
141 for ( ; i < len && i < maxIndex && digits.length() < MAX_DIGITS; i++ )
142 {
143 final char c = referenceCode.charAt( i );
144
145 if ( Character.isDigit( c ) )
146 {
147 sawSpace = false;
148
149 if ( mode == LETTER_FORMAT )
150 {
151 if ( digit < partStart || digit > partEnd )
152 {
153 failed = true;
154 }
155 else
156 {
157 digits.append( c );
158 }
159 }
160 else
161 {
162 digits.append( c );
163 }
164
165 digit++;
166 }
167 else if ( c == ' ' )
168 {
169 if ( sawSpace || i == startIndex || ( mode == ELECTRONIC_FORMAT && digit != 3 ) )
170 {
171 failed = true;
172 }
173 else
174 {
175 mode = LETTER_FORMAT;
176 switch ( part )
177 {
178 case 0:
179 partStart = 3;
180 partEnd = 5;
181 break;
182 case 1:
183 partStart = 6;
184 partEnd = 8;
185 break;
186 case 2:
187 partStart = 9;
188 partEnd = 9;
189 break;
190 default:
191 failed = true;
192 break;
193 }
194 part++;
195
196 if ( digit < partStart || digit > partEnd )
197 {
198 failed = true;
199 }
200 }
201
202 sawSpace = true;
203 }
204 else
205 {
206 failed = true;
207 }
208
209 if ( failed )
210 {
211 pos.setErrorIndex( i );
212 break;
213 }
214 }
215
216 if ( !failed )
217 {
218 final Number num = new DecimalFormat( "##########" ).parse( digits.toString(), fmtPos );
219 if ( num != null && fmtPos.getErrorIndex() == -1 )
220 {
221 final String key = num.toString();
222 ret = (Referenznummer10) getCache().get( key );
223
224 if ( ret == null )
225 {
226 if ( !Referenznummer10.checkReferenznummer10( num ) )
227 {
228 pos.setErrorIndex( startIndex );
229 ret = null;
230 }
231 else
232 {
233 pos.setIndex( i );
234 ret = new Referenznummer10( num );
235 getCache().put( key, ret );
236 }
237 }
238 else
239 {
240 pos.setIndex( i );
241 }
242 }
243 else
244 {
245 pos.setErrorIndex( startIndex );
246 }
247 }
248
249 return ret;
250 }
251
252
253
254
255
256
257
258
259
260
261
262
263
264 public static Referenznummer10 parse( final String referenceCode ) throws ParseException
265 {
266 if ( referenceCode == null )
267 {
268 throw new NullPointerException( "referenceCode" );
269 }
270
271 Referenznummer10 ref = (Referenznummer10) getCache().get( referenceCode );
272
273 if ( ref == null )
274 {
275 final ParsePosition pos = new ParsePosition( 0 );
276 ref = Referenznummer10.parse( referenceCode, pos );
277 if ( ref == null || pos.getErrorIndex() != -1 || pos.getIndex() < referenceCode.length() )
278 {
279 throw new ParseException( referenceCode,
280 pos.getErrorIndex() != -1 ? pos.getErrorIndex() : pos.getIndex() );
281
282 }
283 else
284 {
285 getCache().put( referenceCode, ref );
286 }
287 }
288
289 return ref;
290 }
291
292
293
294
295
296
297
298
299
300
301
302
303
304 public static Referenznummer10 valueOf( final Number referenceCode )
305 {
306 if ( referenceCode == null )
307 {
308 throw new NullPointerException( "referenceCode" );
309 }
310
311 final String key = referenceCode.toString();
312 Referenznummer10 ret = (Referenznummer10) getCache().get( key );
313
314 if ( ret == null )
315 {
316 ret = new Referenznummer10( referenceCode );
317 getCache().put( key, ret );
318 }
319
320 return ret;
321 }
322
323
324
325
326
327
328
329
330
331
332
333
334
335 public static Referenznummer10 valueOf( final String referenceCode )
336 {
337 try
338 {
339 return Referenznummer10.parse( referenceCode );
340 }
341 catch ( final ParseException e )
342 {
343 throw (IllegalArgumentException) new IllegalArgumentException( referenceCode ).initCause( e );
344 }
345 }
346
347
348
349
350
351
352
353
354 public static boolean checkReferenznummer10( final Number referenceCode )
355 {
356 boolean valid = referenceCode != null;
357
358 if ( valid )
359 {
360 final long num = referenceCode.longValue();
361 valid = num >= 0L && num < 10000000000L;
362 }
363
364 return valid;
365 }
366
367
368
369
370
371
372 public int intValue()
373 {
374 return (int) this.ref;
375 }
376
377
378
379
380
381
382 public long longValue()
383 {
384 return this.ref;
385 }
386
387
388
389
390
391
392 public float floatValue()
393 {
394 return this.ref;
395 }
396
397
398
399
400
401
402 public double doubleValue()
403 {
404 return this.ref;
405 }
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421 public StringBuffer format( final int style, final StringBuffer toAppendTo )
422 {
423 if ( toAppendTo == null )
424 {
425 throw new NullPointerException( "toAppendTo" );
426 }
427 if ( style != Referenznummer10.ELECTRONIC_FORMAT && style != Referenznummer10.LETTER_FORMAT )
428 {
429 throw new IllegalArgumentException( Integer.toString( style ) );
430 }
431
432 if ( this.ref == 0L )
433 {
434 toAppendTo.append( '0' );
435 }
436 else
437 {
438 final int[] digits = Referenznummer10.toDigits( this.ref );
439 for ( int i = digits.length - 1, lastDigit = 0; i >= 0; i-- )
440 {
441 if ( digits[i] != 0 || lastDigit > 0 )
442 {
443 toAppendTo.append( digits[i] );
444 lastDigit++;
445 }
446
447 if ( style == Referenznummer10.LETTER_FORMAT && ( lastDigit == 3 || lastDigit == 6 || lastDigit == 9 ) )
448 {
449 toAppendTo.append( ' ' );
450 }
451 }
452 }
453
454 return toAppendTo;
455 }
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472 public String format( final int style )
473 {
474 return this.format( style, new StringBuffer() ).toString();
475 }
476
477
478
479
480
481
482
483
484
485
486
487
488
489 public static String toString( final Referenznummer10 referenznummer10 )
490 {
491 if ( referenznummer10 == null )
492 {
493 throw new NullPointerException( "referenznummer10" );
494 }
495
496 return referenznummer10.format( ELECTRONIC_FORMAT );
497 }
498
499
500
501
502
503
504
505
506 private static int[] toDigits( final long number )
507 {
508 int i;
509 int j;
510 long subst;
511 final int[] ret = new int[ MAX_DIGITS ];
512
513 for ( i = MAX_DIGITS - 1; i >= 0; i-- )
514 {
515 for ( j = i + 1, subst = 0L; j < MAX_DIGITS; j++ )
516 {
517 subst += ret[j] * EXP10[j];
518 }
519 ret[i] = (int) Math.floor( ( number - subst ) / EXP10[i] );
520 }
521
522 return ret;
523 }
524
525
526
527
528
529
530 private String internalString()
531 {
532 return new StringBuffer( 500 ).append( "{referenceNumber=" ).append( this.ref ).append( '}' ).toString();
533 }
534
535
536
537
538
539
540 private static Map getCache()
541 {
542 Map cache = (Map) cacheReference.get();
543 if ( cache == null )
544 {
545 cache = Collections.synchronizedMap( new HashMap( 1024 ) );
546 cacheReference = new SoftReference( cache );
547 }
548
549 return cache;
550 }
551
552
553
554
555
556
557
558
559
560
561
562
563 public int compareTo( final Object o )
564 {
565 if ( o == null )
566 {
567 throw new NullPointerException( "o" );
568 }
569 if ( !( o instanceof Referenznummer10 ) )
570 {
571 throw new ClassCastException( o.getClass().getName() );
572 }
573
574 int result = 0;
575 final Referenznummer10 that = (Referenznummer10) o;
576
577 if ( !this.equals( that ) )
578 {
579 result = this.ref > that.ref ? 1 : -1;
580 }
581
582 return result;
583 }
584
585
586
587
588
589
590
591
592 public boolean equals( final Object o )
593 {
594 boolean equal = o == this;
595
596 if ( !equal && o instanceof Referenznummer10 )
597 {
598 equal = this.ref == ( (Referenznummer10) o ).ref;
599 }
600
601 return equal;
602 }
603
604
605
606
607
608
609 public int hashCode()
610 {
611 return (int) ( this.ref ^ ( this.ref >>> 32 ) );
612 }
613
614
615
616
617
618
619 public String toString()
620 {
621 return super.toString() + this.internalString();
622 }
623
624 }