1 7 8 package javax.swing.text; 9 10 import java.io.*; 11 import java.text.*; 12 import java.util.*; 13 import javax.swing.*; 14 import javax.swing.text.*; 15 16 136 public class MaskFormatter extends DefaultFormatter { 137 private static final char DIGIT_KEY = '#'; 139 private static final char LITERAL_KEY = '\''; 140 private static final char UPPERCASE_KEY = 'U'; 141 private static final char LOWERCASE_KEY = 'L'; 142 private static final char ALPHA_NUMERIC_KEY = 'A'; 143 private static final char CHARACTER_KEY = '?'; 144 private static final char ANYTHING_KEY = '*'; 145 private static final char HEX_KEY = 'H'; 146 147 private static final MaskCharacter[] EmptyMaskChars = new MaskCharacter[0]; 148 149 150 private String mask; 151 152 private transient MaskCharacter[] maskChars; 153 154 155 private String validCharacters; 156 157 158 private String invalidCharacters; 159 160 162 private String placeholderString; 163 164 165 private char placeholder; 166 167 168 private boolean containsLiteralChars; 169 170 171 174 public MaskFormatter() { 175 setAllowsInvalid(false); 176 containsLiteralChars = true; 177 maskChars = EmptyMaskChars; 178 placeholder = ' '; 179 } 180 181 188 public MaskFormatter(String mask) throws ParseException { 189 this(); 190 setMask(mask); 191 } 192 193 200 public void setMask(String mask) throws ParseException { 201 this.mask = mask; 202 updateInternalMask(); 203 } 204 205 210 public String getMask() { 211 return mask; 212 } 213 214 224 public void setValidCharacters(String validCharacters) { 225 this.validCharacters = validCharacters; 226 } 227 228 233 public String getValidCharacters() { 234 return validCharacters; 235 } 236 237 247 public void setInvalidCharacters(String invalidCharacters) { 248 this.invalidCharacters = invalidCharacters; 249 } 250 251 256 public String getInvalidCharacters() { 257 return invalidCharacters; 258 } 259 260 267 public void setPlaceholder(String placeholder) { 268 this.placeholderString = placeholder; 269 } 270 271 278 public String getPlaceholder() { 279 return placeholderString; 280 } 281 282 293 public void setPlaceholderCharacter(char placeholder) { 294 this.placeholder = placeholder; 295 } 296 297 304 public char getPlaceholderCharacter() { 305 return placeholder; 306 } 307 308 323 public void setValueContainsLiteralCharacters( 324 boolean containsLiteralChars) { 325 this.containsLiteralChars = containsLiteralChars; 326 } 327 328 335 public boolean getValueContainsLiteralCharacters() { 336 return containsLiteralChars; 337 } 338 339 354 public Object stringToValue(String value) throws ParseException { 355 return stringToValue(value, true); 356 } 357 358 369 public String valueToString(Object value) throws ParseException { 370 String sValue = (value == null) ? "" : value.toString(); 371 StringBuffer result = new StringBuffer (); 372 String placeholder = getPlaceholder(); 373 int[] valueCounter = { 0 }; 374 375 append(result, sValue, valueCounter, placeholder, maskChars); 376 return result.toString(); 377 } 378 379 409 public void install(JFormattedTextField ftf) { 410 super.install(ftf); 411 if (ftf != null) { 414 Object value = ftf.getValue(); 415 416 try { 417 stringToValue(valueToString(value)); 418 } catch (ParseException pe) { 419 setEditValid(false); 420 } 421 } 422 } 423 424 430 private Object stringToValue(String value, boolean completeMatch) throws 431 ParseException { 432 int errorOffset = -1; 433 434 if ((errorOffset = getInvalidOffset(value, completeMatch)) == -1) { 435 if (!getValueContainsLiteralCharacters()) { 436 value = stripLiteralChars(value); 437 } 438 return super.stringToValue(value); 439 } 440 throw new ParseException("stringToValue passed invalid value", 441 errorOffset); 442 } 443 444 448 private int getInvalidOffset(String string, boolean completeMatch) { 449 int iLength = string.length(); 450 451 if (iLength != getMaxLength()) { 452 return iLength; 454 } 455 for (int counter = 0, max = string.length(); counter < max; counter++){ 456 char aChar = string.charAt(counter); 457 458 if (!isValidCharacter(counter, aChar) && 459 (completeMatch || !isPlaceholder(counter, aChar))) { 460 return counter; 461 } 462 } 463 return -1; 464 } 465 466 470 private void append(StringBuffer result, String value, int[] index, 471 String placeholder, MaskCharacter[] mask) 472 throws ParseException { 473 for (int counter = 0, maxCounter = mask.length; 474 counter < maxCounter; counter++) { 475 mask[counter].append(result, value, index, placeholder); 476 } 477 } 478 479 482 private void updateInternalMask() throws ParseException { 483 String mask = getMask(); 484 ArrayList fixed = new ArrayList(); 485 ArrayList temp = fixed; 486 487 if (mask != null) { 488 for (int counter = 0, maxCounter = mask.length(); 489 counter < maxCounter; counter++) { 490 char maskChar = mask.charAt(counter); 491 492 switch (maskChar) { 493 case DIGIT_KEY: 494 temp.add(new DigitMaskCharacter()); 495 break; 496 case LITERAL_KEY: 497 if (++counter < maxCounter) { 498 maskChar = mask.charAt(counter); 499 temp.add(new LiteralCharacter(maskChar)); 500 } 501 break; 503 case UPPERCASE_KEY: 504 temp.add(new UpperCaseCharacter()); 505 break; 506 case LOWERCASE_KEY: 507 temp.add(new LowerCaseCharacter()); 508 break; 509 case ALPHA_NUMERIC_KEY: 510 temp.add(new AlphaNumericCharacter()); 511 break; 512 case CHARACTER_KEY: 513 temp.add(new CharCharacter()); 514 break; 515 case ANYTHING_KEY: 516 temp.add(new MaskCharacter()); 517 break; 518 case HEX_KEY: 519 temp.add(new HexCharacter()); 520 break; 521 default: 522 temp.add(new LiteralCharacter(maskChar)); 523 break; 524 } 525 } 526 } 527 if (fixed.size() == 0) { 528 maskChars = EmptyMaskChars; 529 } 530 else { 531 maskChars = new MaskCharacter[fixed.size()]; 532 fixed.toArray(maskChars); 533 } 534 } 535 536 539 private MaskCharacter getMaskCharacter(int index) { 540 if (index >= maskChars.length) { 541 return null; 542 } 543 return maskChars[index]; 544 } 545 546 549 private boolean isPlaceholder(int index, char aChar) { 550 return (getPlaceholderCharacter() == aChar); 551 } 552 553 557 private boolean isValidCharacter(int index, char aChar) { 558 return getMaskCharacter(index).isValidCharacter(aChar); 559 } 560 561 565 private boolean isLiteral(int index) { 566 return getMaskCharacter(index).isLiteral(); 567 } 568 569 572 private int getMaxLength() { 573 return maskChars.length; 574 } 575 576 579 private char getLiteral(int index) { 580 return getMaskCharacter(index).getChar((char)0); 581 } 582 583 589 private char getCharacter(int index, char aChar) { 590 return getMaskCharacter(index).getChar(aChar); 591 } 592 593 596 private String stripLiteralChars(String string) { 597 StringBuffer sb = null; 598 int last = 0; 599 600 for (int counter = 0, max = string.length(); counter < max; counter++){ 601 if (isLiteral(counter)) { 602 if (sb == null) { 603 sb = new StringBuffer (); 604 if (counter > 0) { 605 sb.append(string.substring(0, counter)); 606 } 607 last = counter + 1; 608 } 609 else if (last != counter) { 610 sb.append(string.substring(last, counter)); 611 } 612 last = counter + 1; 613 } 614 } 615 if (sb == null) { 616 return string; 618 } 619 else if (last != string.length()) { 620 if (sb == null) { 621 return string.substring(last); 622 } 623 sb.append(string.substring(last)); 624 } 625 return sb.toString(); 626 } 627 628 629 633 private void readObject(ObjectInputStream s) 634 throws IOException, ClassNotFoundException { 635 s.defaultReadObject(); 636 try { 637 updateInternalMask(); 638 } catch (ParseException pe) { 639 } 641 } 642 643 648 boolean isNavigatable(int offset) { 649 if (!getAllowsInvalid()) { 650 return (offset < getMaxLength() && !isLiteral(offset)); 651 } 652 return true; 653 } 654 655 662 boolean isValidEdit(ReplaceHolder rh) { 663 if (!getAllowsInvalid()) { 664 String newString = getReplaceString(rh.offset, rh.length, rh.text); 665 666 try { 667 rh.value = stringToValue(newString, false); 668 669 return true; 670 } catch (ParseException pe) { 671 return false; 672 } 673 } 674 return true; 675 } 676 677 699 boolean canReplace(ReplaceHolder rh) { 700 if (!getAllowsInvalid()) { 704 StringBuffer replace = null; 705 String text = rh.text; 706 int tl = (text != null) ? text.length() : 0; 707 708 if (tl == 0 && rh.length == 1 && getFormattedTextField(). 709 getSelectionStart() != rh.offset) { 710 while (rh.offset > 0 && isLiteral(rh.offset)) { 712 rh.offset--; 713 } 714 } 715 int max = Math.min(getMaxLength() - rh.offset, 716 Math.max(tl, rh.length)); 717 for (int counter = 0, textIndex = 0; counter < max; counter++) { 718 if (textIndex < tl && isValidCharacter(rh.offset + counter, 719 text.charAt(textIndex))) { 720 char aChar = text.charAt(textIndex); 721 if (aChar != getCharacter(rh.offset + counter, aChar)) { 722 if (replace == null) { 723 replace = new StringBuffer (); 724 if (textIndex > 0) { 725 replace.append(text.substring(0, textIndex)); 726 } 727 } 728 } 729 if (replace != null) { 730 replace.append(getCharacter(rh.offset + counter, 731 aChar)); 732 } 733 textIndex++; 734 } 735 else if (isLiteral(rh.offset + counter)) { 736 if (replace != null) { 737 replace.append(getLiteral(rh.offset + counter)); 738 if (textIndex < tl) { 739 max = Math.min(max + 1, getMaxLength() - 740 rh.offset); 741 } 742 } 743 else if (textIndex > 0) { 744 replace = new StringBuffer (max); 745 replace.append(text.substring(0, textIndex)); 746 replace.append(getLiteral(rh.offset + counter)); 747 if (textIndex < tl) { 748 max = Math.min(max + 1, getMaxLength() - 750 rh.offset); 751 } 752 else if (rh.cursorPosition == -1) { 753 rh.cursorPosition = rh.offset + counter; 754 } 755 } 756 else { 757 rh.offset++; 758 rh.length--; 759 counter--; 760 max--; 761 } 762 } 763 else if (textIndex >= tl) { 764 if (replace == null) { 766 replace = new StringBuffer (); 767 if (text != null) { 768 replace.append(text); 769 } 770 } 771 replace.append(getPlaceholderCharacter()); 772 if (tl > 0 && rh.cursorPosition == -1) { 773 rh.cursorPosition = rh.offset + counter; 774 } 775 } 776 else { 777 return false; 779 } 780 } 781 if (replace != null) { 782 rh.text = replace.toString(); 783 } 784 else if (text != null && rh.offset + tl > getMaxLength()) { 785 rh.text = text.substring(0, getMaxLength() - rh.offset); 786 } 787 if (getOverwriteMode() && rh.text != null) { 788 rh.length = rh.text.length(); 789 } 790 } 791 return super.canReplace(rh); 792 } 793 794 795 private class MaskCharacter { 799 804 public boolean isLiteral() { 805 return false; 806 } 807 808 816 public boolean isValidCharacter(char aChar) { 817 if (isLiteral()) { 818 return (getChar(aChar) == aChar); 819 } 820 821 aChar = getChar(aChar); 822 823 String filter = getValidCharacters(); 824 825 if (filter != null && filter.indexOf(aChar) == -1) { 826 return false; 827 } 828 filter = getInvalidCharacters(); 829 if (filter != null && filter.indexOf(aChar) != -1) { 830 return false; 831 } 832 return true; 833 } 834 835 841 public char getChar(char aChar) { 842 return aChar; 843 } 844 845 849 public void append(StringBuffer buff, String formatting, int[] index, 850 String placeholder) 851 throws ParseException { 852 boolean inString = index[0] < formatting.length(); 853 char aChar = inString ? formatting.charAt(index[0]) : 0; 854 855 if (isLiteral()) { 856 buff.append(getChar(aChar)); 857 if (getValueContainsLiteralCharacters()) { 858 if (inString && aChar != getChar(aChar)) { 859 throw new ParseException("Invalid character: " + 860 aChar, index[0]); 861 } 862 index[0] = index[0] + 1; 863 } 864 } 865 else if (index[0] >= formatting.length()) { 866 if (placeholder != null && index[0] < placeholder.length()) { 867 buff.append(placeholder.charAt(index[0])); 868 } 869 else { 870 buff.append(getPlaceholderCharacter()); 871 } 872 index[0] = index[0] + 1; 873 } 874 else if (isValidCharacter(aChar)) { 875 buff.append(getChar(aChar)); 876 index[0] = index[0] + 1; 877 } 878 else { 879 throw new ParseException("Invalid character: " + aChar, 880 index[0]); 881 } 882 } 883 } 884 885 886 889 private class LiteralCharacter extends MaskCharacter { 890 private char fixedChar; 891 892 public LiteralCharacter(char fixedChar) { 893 this.fixedChar = fixedChar; 894 } 895 896 public boolean isLiteral() { 897 return true; 898 } 899 900 public char getChar(char aChar) { 901 return fixedChar; 902 } 903 } 904 905 906 909 private class DigitMaskCharacter extends MaskCharacter { 910 public boolean isValidCharacter(char aChar) { 911 return (Character.isDigit(aChar) && 912 super.isValidCharacter(aChar)); 913 } 914 } 915 916 917 921 private class UpperCaseCharacter extends MaskCharacter { 922 public boolean isValidCharacter(char aChar) { 923 return (Character.isLetter(aChar) && 924 super.isValidCharacter(aChar)); 925 } 926 927 public char getChar(char aChar) { 928 return Character.toUpperCase(aChar); 929 } 930 } 931 932 933 937 private class LowerCaseCharacter extends MaskCharacter { 938 public boolean isValidCharacter(char aChar) { 939 return (Character.isLetter(aChar) && 940 super.isValidCharacter(aChar)); 941 } 942 943 public char getChar(char aChar) { 944 return Character.toLowerCase(aChar); 945 } 946 } 947 948 949 953 private class AlphaNumericCharacter extends MaskCharacter { 954 public boolean isValidCharacter(char aChar) { 955 return (Character.isLetterOrDigit(aChar) && 956 super.isValidCharacter(aChar)); 957 } 958 } 959 960 961 964 private class CharCharacter extends MaskCharacter { 965 public boolean isValidCharacter(char aChar) { 966 return (Character.isLetter(aChar) && 967 super.isValidCharacter(aChar)); 968 } 969 } 970 971 972 975 private class HexCharacter extends MaskCharacter { 976 public boolean isValidCharacter(char aChar) { 977 return ((aChar == '0' || aChar == '1' || 978 aChar == '2' || aChar == '3' || 979 aChar == '4' || aChar == '5' || 980 aChar == '6' || aChar == '7' || 981 aChar == '8' || aChar == '9' || 982 aChar == 'a' || aChar == 'A' || 983 aChar == 'b' || aChar == 'B' || 984 aChar == 'c' || aChar == 'C' || 985 aChar == 'd' || aChar == 'D' || 986 aChar == 'e' || aChar == 'E' || 987 aChar == 'f' || aChar == 'F') && 988 super.isValidCharacter(aChar)); 989 } 990 991 public char getChar(char aChar) { 992 if (Character.isDigit(aChar)) { 993 return aChar; 994 } 995 return Character.toUpperCase(aChar); 996 } 997 } 998 } 999 | Popular Tags |