home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / VCAFE.3.0A / Main.bin / DatePatternToMaskXLator.java < prev    next >
Text File  |  1998-12-09  |  22KB  |  671 lines

  1. /*
  2.  * @(#DatePatternToMaskXLator.java
  3.  *
  4.  * Copyright (c) 1998 Symantec Corporation. All Rights Reserved.
  5.  *
  6.  */
  7. package com.symantec.itools.swing;
  8. import java.text.SimpleDateFormat;
  9. import java.io.Serializable;
  10.  
  11. /**
  12.  * DatePatternToMaskXLator is a translator that can be used to translate
  13.  * date patterns such as "yyyy.MM.dd G 'at' hh:mm:ss z" to an appropriate mask. 
  14.  * The pattern should not be a localized pattern.
  15.  * <p>
  16.  * The mask could then be used in masked fields and formatted text fields. The 
  17.  * patterns are interpreted using the format syntax specified in 
  18.  * java.text.SimpleDateFormat. The translator also allows some customization to 
  19.  * suit specific needs.
  20.  * <p>
  21.  *
  22.  * @author Vasudev J. Rao
  23.  * @version 1.0 
  24.  * @see java.text.SimpleDateFormat
  25.  * @see com.symantec.itools.swing.JDateMaskedField
  26.  * @see com.symantec.itools.swing.JMaskedTextField
  27.  */
  28.  
  29.  
  30. public class DatePatternToMaskXLator implements Serializable {
  31.     
  32.     public static final int PRECEDE_MASKTOKENS_IN_LITERAL_WITH_ESC = 0;
  33.     public static final int PRECEDE_ALLCHARS_IN_LITERAL_WITH_ESC  = 1;
  34.     
  35.     static final String INVALID_POLICY = "invalid policy";
  36.     
  37.     protected char maskNumericCharacter = '9';
  38.     protected char maskAlphaCharacter = 'C';
  39.     protected char maskEscapeCharacter = '\\';
  40.     //these are all mask filter + command characters 
  41.     protected char[] maskTokens = { '0' , '9' , '#' ,
  42.                                     'L' , '?' , 'A' ,
  43.                                     'a' , '&' , 'C' ,
  44.                                     '.' , ',' , ':' ,
  45.                                     ';' , '-' , '/' ,
  46.                                     '<' , '>' , '\\' };
  47.                                     
  48.     protected int escapeSyntaxPolicy = PRECEDE_MASKTOKENS_IN_LITERAL_WITH_ESC ;                                   
  49.     
  50.     /**
  51.      * Default constructor. Constructs a date pattern to mask translator using
  52.      * '9' for mask numeric character, 'C' for mask alpha character and '\\' for
  53.      * mask escape character.
  54.      */
  55.     
  56.     public DatePatternToMaskXLator ( ) {
  57.         
  58.         this( '9' , 'C' , '\\' );
  59.         
  60.     }
  61.     
  62.     /**
  63.      * Constructor to construct a translator using the specified characters 
  64.      * for numeric and alpha mask and mask escape characters.
  65.      */
  66.    
  67.     public DatePatternToMaskXLator ( char numericMask, char alphaMask, char esc ) {
  68.         
  69.         super();
  70.         setMaskNumericCharacter ( numericMask );
  71.         setMaskAlphaCharacter ( alphaMask );
  72.         setMaskEscapeCharacter ( esc );
  73.         
  74.     }
  75.    
  76.     /**
  77.      * Sets a character to be used for mask numeric character. By default 
  78.      * it is '9'. It may be set to any other character ( for eg., '0', '#', etc).
  79.      */
  80.     public void setMaskNumericCharacter ( char c ) {
  81.         
  82.         maskNumericCharacter = c;
  83.         
  84.     }
  85.     
  86.     /**
  87.      * Returns the character used for mask numeric filter.
  88.      */
  89.     public char getMaskNumericCharacter (  ) {
  90.         
  91.         return maskNumericCharacter ;
  92.         
  93.     }
  94.     
  95.     /**
  96.      * Sets a character to be used for mask alpha character.By default 
  97.      * it is 'C'. It may be set to any other character ( for eg., 'A', 'a', etc).
  98.      */
  99.     public void setMaskAlphaCharacter ( char c ) {
  100.         
  101.         maskAlphaCharacter = c;
  102.         
  103.     }
  104.     
  105.     /**
  106.      * Returns the character used for mask alpha filter.
  107.      */
  108.     public char getMaskAlphaCharacter (  ) {
  109.         
  110.         return maskAlphaCharacter ;
  111.         
  112.     }
  113.     
  114.     /**
  115.      * Sets a character to be used for mask escape character.By default 
  116.      * it is '\\'. 
  117.      */
  118.     public void setMaskEscapeCharacter ( char c ) {
  119.         
  120.         maskEscapeCharacter = c;
  121.         
  122.     }
  123.     
  124.     /**
  125.      * Returns the character used for mask escape character.
  126.      */
  127.     public char getMaskEscapeCharacter ( ) {
  128.         
  129.         return maskEscapeCharacter ;
  130.         
  131.     }
  132.     
  133.     /**
  134.      * Sets an array of characters as reserved mask tokens. If the escape 
  135.      * syntax policy is PRECEDE_MASKTOKENS_IN_LITERAL_WITH_ESC, this list is 
  136.      * checked to determine whether or not to precede a character with the 
  137.      * escape character.
  138.      */
  139.     public void setMaskTokens ( char [] maskTokens ) {
  140.         
  141.         this.maskTokens = maskTokens ;
  142.         
  143.     }
  144.    
  145.     /**
  146.      * Returns an array of characters recognized as reserved mask tokens.
  147.      */
  148.     public char[] getMaskTokens ( ) {
  149.         
  150.         return this.maskTokens ;
  151.         
  152.     }
  153.     
  154.     /**
  155.      * Sets the escape syntax policy. Can be one of 
  156.      * PRECEDE_MASKTOKENS_IN_LITERAL_WITH_ESC or PRECEDE_ALLCHARS_IN_LITERAL_WITH_ESC
  157.      * <p>
  158.      * If the escape syntax policy is PRECEDE_MASKTOKENS_IN_LITERAL_WITH_ESC, 
  159.      * if a reserved mask token occurs within a literal, it is preceded with 
  160.      * the mask escape character.
  161.      * <p>
  162.      * If the escape syntax policy is PRECEDE_ALLCHARS_IN_LITERAL_WITH_ESC, 
  163.      * all character within a literal are preceded with mask escape character.
  164.      *
  165.      * @throws IllegalArgumentException if the policy is invalid.
  166.      */
  167.     public void setEscapeSyntaxPolicy ( int policy ) {
  168.         if ( policy == PRECEDE_MASKTOKENS_IN_LITERAL_WITH_ESC ||
  169.              policy == PRECEDE_ALLCHARS_IN_LITERAL_WITH_ESC     ) {
  170.                 escapeSyntaxPolicy = policy ;
  171.         }
  172.         else {
  173.             throw new IllegalArgumentException ( INVALID_POLICY ) ;
  174.         }
  175.         
  176.     }
  177.     
  178.     /**
  179.      * Returns the currentescape syntax policy.
  180.      */
  181.     
  182.     public int getEscapeSyntaxPolicy ( ) {
  183.         
  184.         return escapeSyntaxPolicy ;
  185.     }
  186.     
  187.     /**
  188.      * Get the mask representation for a DateFormats pattern.
  189.      */
  190.     
  191.     public String getMaskForDatePattern ( String pattern ){
  192.         // Note:
  193.         // String tokenizer cannot be used here!! Because we may have
  194.         // strings like "hh 'o''clock' a, zzzz"
  195.         // in which case the tokens would be "hh ","o","clock" and " a,zzzz".
  196.         // We will not know that we need a "'" embedded b/w "o" and "clock".
  197.         StringBuffer retBuf = new StringBuffer();
  198.         int lastQuotePos = -1 ; // quote position stored away in the last iteration
  199.         int index = 0; // used to exit out of the while loop.
  200.         
  201.         while ( index < pattern.length() ) {
  202.             
  203.             int quotePos = pattern.indexOf( "'" , lastQuotePos + 1 );
  204.             
  205.             if ( quotePos != -1 ) {// found a quote!
  206.                 
  207.                 if ( lastQuotePos + 1 == quotePos ) {
  208.                     // found successive quotes. quote is escape char for date formats
  209.                     // ==> quote is reqd as a literal. so, append one.
  210.                     retBuf.append ('\'');
  211.                 }
  212.                 else {
  213.                     // found the first sub-pattern
  214.                     String tempString = pattern.substring( lastQuotePos + 1 , quotePos );
  215.                     retBuf.append ( getMaskForDateSubPattern ( tempString ) );
  216.                 }
  217.                 index = quotePos + 1;//skip to the next sub pattern.
  218.                 
  219.                 // find if there is a matching closing quote
  220.                 // if found we know that it is a string literal
  221.                 int nextQuotePos = pattern.indexOf( "'" , quotePos + 1 );
  222.                 
  223.                 if ( nextQuotePos != -1 ) {
  224.                     //found!!! 
  225.                     if ( quotePos + 1 == nextQuotePos ) {
  226.                         //successive quotes. should not come here normally.
  227.                         //@todo: check this logic again. kinda confusing!!
  228.                         retBuf.append ('\'');
  229.                     }
  230.                     else {
  231.                         //we have a literal embedded in the pattern.
  232.                         String tempLiteral = pattern.substring( quotePos + 1 , nextQuotePos );
  233.                         retBuf.append (  getMaskLiteralString ( tempLiteral ) );
  234.                     }
  235.                     quotePos = nextQuotePos ;
  236.                     index = nextQuotePos + 1;//skip to the next sub string.
  237.                     
  238.                 }
  239.                 else{
  240.                     //should not normally come here!!
  241.                     retBuf.append ( getMaskEscapeCharacter( ) );
  242.                     index = quotePos + 1;
  243.                 }
  244.                 
  245.                 lastQuotePos = quotePos;
  246.                 
  247.                 
  248.             }
  249.             else{
  250.                 //if no matching quote was found, 
  251.                 // get the mask for the remaining pattern.
  252.                 String tempString = pattern.substring( lastQuotePos + 1 , pattern.length() );
  253.                 retBuf.append ( getMaskForDateSubPattern ( tempString ) );
  254.                 index = pattern.length();
  255.                         
  256.             }
  257.         
  258.         }
  259.         
  260.         return retBuf.toString();
  261.         
  262.     }
  263.     
  264.     //PROTECTED SECTION
  265.     
  266.     /**
  267.      * Get the mask representation for a DateFormats sub-pattern.
  268.      */
  269.  
  270.     protected String getMaskForDateSubPattern ( String pattern ){
  271.         
  272.         StringBuffer retMask = new StringBuffer();
  273.         //first char
  274.         char prevChar = pattern.charAt ( 0 ) ;
  275.         int repeatCount = 1;
  276.         
  277.         for ( int index = 1 ; index < pattern.length() ; index ++ ) {
  278.             //second char to last_but_one char
  279.             char thisChar = pattern.charAt( index ) ;
  280.                 
  281.             if ( thisChar == prevChar ) {
  282.                 //repeated chars in a pattern have some significance.
  283.                 //so accumulate the count
  284.                 repeatCount ++ ;
  285.                     
  286.             }
  287.             else {
  288.                 // a diff character from the last one.
  289.                 //so for the prev character and its count, get the mask.
  290.                 retMask.append ( getMaskStringForPatternChars ( prevChar , repeatCount ) );
  291.                 //set this char as the prev char for the next iteration
  292.                 prevChar = thisChar ;
  293.                 repeatCount = 1;//set the accumulator to 1
  294.                     
  295.             }
  296.                 
  297.         }
  298.         //handle last character 
  299.         retMask.append ( getMaskStringForPatternChars ( prevChar , repeatCount) ) ;
  300.             
  301.         return retMask.toString() ;
  302.         
  303.     }
  304.     
  305.     /**
  306.      * Get the equivalent mask string for a DateFormatSymbol character.
  307.      */
  308.     
  309.     protected String getMaskStringForPatternChars ( char c , int count ) {
  310.         
  311.         StringBuffer retBuffer = new StringBuffer ( ) ;
  312.         int length = 0;
  313.         char maskChar = getMaskNumericCharacter( ) ;
  314.         
  315.         switch ( c ) {
  316.             
  317.             case 'y':        //year                    (Number)            1996
  318.                 if ( count < 4 ) {
  319.                     length = 2;
  320.                 }
  321.                 else {
  322.                     length = 4;
  323.                 }
  324.                 break;
  325.             
  326.             case 'd':        //day in month            (Number)            10
  327.             case 'h':        //hour in am/pm (1~12)    (Number)            12
  328.             case 'H':        //hour in day (0~23)      (Number)            0
  329.             case 'm':        //minute in hour          (Number)            30
  330.             case 's':        //second in minute        (Number)            55
  331.             case 'k':        //hour in day (1~24)      (Number)            24
  332.             case 'K':        //hour in am/pm (0~11)    (Number)            0
  333.             case 'w':        //week in year            (Number)            27
  334.                 length = 2;
  335.                 break;
  336.             
  337.             case 'S':        //millisecond             (Number)            978
  338.             case 'D':        //day in year             (Number)            189
  339.                 length = 3;
  340.                 break;
  341.             
  342.             case 'F':        //day of week in month    (Number)            2 (2nd Wed in July)
  343.             case 'W':        //week in month           (Number)            2
  344.                 length = 1;
  345.                 break;
  346.             
  347.             case 'G':        //era designator          (Text)              AD
  348.                 length = getEraStringLength() ;
  349.                 maskChar = getMaskAlphaCharacter( ) ;
  350.                 break;
  351.             
  352.             case 'E':        //day in week             (Text)              Tuesday
  353.                 if ( count < 4 ) {
  354.                     length = getShortWeekDaysStringLength ();
  355.                 }
  356.                 else {
  357.                     length = getWeekDaysStringLength ();
  358.                 }
  359.                 maskChar = getMaskAlphaCharacter( ) ;
  360.                 break;
  361.             
  362.             case 'a':        //am/pm marker            (Text)              PM
  363.                 length = getAmPmStringLength ();
  364.                 maskChar = getMaskAlphaCharacter( ) ;
  365.                 break;
  366.             
  367.             case 'z':        //time zone               (Text)              Pacific Standard Time
  368.                 if ( count < 4 ) {
  369.                     length = getShortZoneStringLength ();
  370.                 }
  371.                 else {
  372.                     length = getZoneStringLength ();
  373.                 }
  374.                 maskChar = getMaskAlphaCharacter( ) ;
  375.                 break;
  376.             
  377.             case 'M':        //month in year           (Text & Number)     July & 07
  378.                 if ( count < 3 ) {
  379.                     length = 2 ;
  380.                 }
  381.                 else if ( count == 3 ) {
  382.                     length = getShortMonthStringLength ();
  383.                     maskChar = getMaskAlphaCharacter( ) ;
  384.                 }
  385.                 else {
  386.                     length = getMonthStringLength ();
  387.                     maskChar = getMaskAlphaCharacter( ) ;
  388.                 }
  389.                 break;
  390.             
  391.             case '\'':        //escape for text         (Delimiter)
  392.                 //normally would not come here. 
  393.                 //Because we handle "'" differently.
  394.                 length = 1 ;
  395.                 maskChar = getMaskEscapeCharacter( ) ;
  396.                 break; 
  397.             
  398.             default:  
  399.                 length = count ;
  400.                 maskChar = c ;
  401.                 break;
  402.             
  403.         }
  404.         
  405.         for ( int i = 0 ; i < length ; i ++ ) {
  406.             retBuffer.append ( maskChar ) ;
  407.         }
  408.         
  409.         return retBuffer.toString() ; 
  410.         
  411.         
  412.     }
  413.      
  414.     // purpose of this method is to check and find if the literal has any  
  415.     // mask key word. If yes, prefix them with "\";
  416.     // Mask key word is either a filter or a command character
  417.     protected String getMaskLiteralString ( String input ) {
  418.         
  419.         StringBuffer retString = new StringBuffer();
  420.         for ( int index = 0 ; index < input.length() ; index ++ ) {
  421.             char tempChar = input.charAt( index ) ;
  422.             if ( getEscapeSyntaxPolicy () == PRECEDE_MASKTOKENS_IN_LITERAL_WITH_ESC ) {
  423.                 
  424.                 if ( isCharacterMaskToken ( tempChar ) ) {
  425.                     
  426.                     retString.append( getMaskEscapeCharacter() ).append( tempChar );           
  427.                             
  428.                 }
  429.                 else {
  430.                     retString.append( tempChar );           
  431.                 }
  432.             
  433.             }
  434.             else {
  435.                 
  436.                 retString.append( getMaskEscapeCharacter() ).append( tempChar );           
  437.             }
  438.             
  439.         }
  440.         
  441.         return retString.toString();
  442.         
  443.     }
  444.     
  445.     //helper methods
  446.     
  447.     protected boolean isCharacterMaskToken ( char c ) {
  448.         
  449.         boolean retBool = false ;
  450.         for ( int i = 0 ; i < maskTokens.length ; i ++ ) {
  451.             if ( c == maskTokens [i] ) {
  452.                 retBool = true;
  453.                 break;
  454.             }
  455.             
  456.         }
  457.         
  458.         return retBool;
  459.         
  460.     }
  461.     
  462.     
  463.     protected java.text.DateFormatSymbols getDateFormatSymbols(){
  464.         //SimpleDateFormat sdf  = ( SimpleDateFormat ) getFormatter ( getType () , getFormattingStyle() );
  465.         SimpleDateFormat sdf  =  new SimpleDateFormat ( );
  466.         return sdf.getDateFormatSymbols();
  467.     }
  468.     
  469.     protected int getAmPmStringLength( ){
  470.         
  471.         int retLength = 0;
  472.         java.text.DateFormatSymbols dfs = getDateFormatSymbols();
  473.         String [] AmPmStrings;
  474.         
  475.         if ( dfs == null ){
  476.             retLength = 2;
  477.         }
  478.         else {
  479.             
  480.             AmPmStrings = dfs. getAmPmStrings ();
  481.             retLength = getMaximumLength ( AmPmStrings );
  482.         }
  483.         return retLength;
  484.         
  485.     }
  486.     
  487.     protected int getEraStringLength( ){
  488.         
  489.         int retLength = 0;
  490.         java.text.DateFormatSymbols dfs = getDateFormatSymbols();
  491.         String [] eraStrings;
  492.         
  493.         if ( dfs == null ){
  494.             retLength = 2;
  495.         }
  496.         else {
  497.             
  498.             eraStrings = dfs. getEras ();
  499.             retLength = getMaximumLength ( eraStrings );
  500.         }
  501.         return retLength;
  502.         
  503.     }
  504.     
  505.     protected int getMonthStringLength( ){
  506.         
  507.         int retLength = 0;
  508.         java.text.DateFormatSymbols dfs = getDateFormatSymbols();
  509.         String [] monthStrings;
  510.         
  511.         if ( dfs == null ){
  512.             retLength = 12;
  513.         }
  514.         else {
  515.             
  516.             monthStrings = dfs. getMonths ();
  517.             retLength = getMaximumLength ( monthStrings );
  518.         }
  519.         return retLength;
  520.         
  521.     }
  522.    
  523.     protected int getShortMonthStringLength( ){
  524.         
  525.         int retLength = 0;
  526.         java.text.DateFormatSymbols dfs = getDateFormatSymbols();
  527.         String [] monthStrings;
  528.         
  529.         if ( dfs == null ){
  530.             retLength = 4;
  531.         }
  532.         else {
  533.             
  534.             monthStrings = dfs. getShortMonths ();
  535.             retLength = getMaximumLength ( monthStrings );
  536.         }
  537.         return retLength;
  538.         
  539.     }
  540.     
  541.     protected int getShortWeekDaysStringLength( ){
  542.         
  543.         int retLength = 0;
  544.         java.text.DateFormatSymbols dfs = getDateFormatSymbols();
  545.         String [] weekDayStrings;
  546.         
  547.         if ( dfs == null ){
  548.             retLength = 3;
  549.         }
  550.         else {
  551.             
  552.             weekDayStrings = dfs. getShortWeekdays ();
  553.             retLength = getMaximumLength ( weekDayStrings );
  554.         }
  555.         return retLength;
  556.         
  557.     }
  558.  
  559.     protected int getWeekDaysStringLength( ){
  560.         
  561.         int retLength = 0;
  562.         java.text.DateFormatSymbols dfs = getDateFormatSymbols();
  563.         String [] weekDayStrings;
  564.         
  565.         if ( dfs == null ){
  566.             retLength = 10;
  567.         }
  568.         else {
  569.             
  570.             weekDayStrings = dfs. getWeekdays ();
  571.             retLength = getMaximumLength ( weekDayStrings );
  572.         }
  573.         return retLength;
  574.         
  575.     }
  576.     
  577.     /*
  578.     The items in the 2D array looks like this:
  579.     
  580.     item at : 0 , 0 : PST
  581.     item at : 0 , 1 : Pacific Standard Time
  582.     item at : 0 , 2 : PST
  583.     item at : 0 , 3 : Pacific Daylight Time
  584.     item at : 0 , 4 : PDT
  585.     item at : 1 , 0 : America/Los_Angeles
  586.     item at : 1 , 1 : Pacific Standard Time
  587.     item at : 1 , 2 : PST
  588.     item at : 1 , 3 : Pacific Daylight Time
  589.     item at : 1 , 4 : PDT
  590.     item at : 2 , 0 : MST
  591.     item at : 2 , 1 : Mountain Standard Time
  592.     item at : 2 , 2 : MST
  593.     item at : 2 , 3 : Mountain Daylight Time
  594.     item at : 2 , 4 : MDT
  595.     .....
  596.     .....
  597.     
  598.  
  599.     */
  600.     protected int getZoneStringLength( ){
  601.         
  602.         int retLength = 0;
  603.         java.text.DateFormatSymbols dfs = getDateFormatSymbols();
  604.         String [][] zoneStrings;
  605.         
  606.         if ( dfs == null ){
  607.             retLength = 4;
  608.         }
  609.         else {
  610.             
  611.             zoneStrings = dfs. getZoneStrings ();
  612.             for ( int i = 0 ; i < zoneStrings.length ; i++ ) {
  613.                 
  614.                 for (   int j = 1 /* skip item at 0 */;
  615.                         j <  ( zoneStrings [i] ). length ;
  616.                         j = j + 2 ) {
  617.                     retLength = java.lang.Math.max ( retLength , ( zoneStrings [i][j] ).length() );
  618.                             
  619.                 }
  620.                 
  621.             }
  622.         
  623.         }
  624.         return retLength;
  625.         
  626.     }
  627.     
  628.     protected int getShortZoneStringLength( ){
  629.         
  630.         int retLength = 0;
  631.         java.text.DateFormatSymbols dfs = getDateFormatSymbols();
  632.         String [][] zoneStrings;
  633.         
  634.         if ( dfs == null ){
  635.             retLength = 4;
  636.         }
  637.         else {
  638.             
  639.             zoneStrings = dfs. getZoneStrings ();
  640.             for ( int i = 0 ; i < zoneStrings.length ; i++ ) {
  641.                 
  642.                 for (   int j = 2 /* skip item at 0 & 1 */;
  643.                         j <  ( zoneStrings [i] ). length ;
  644.                         j = j + 2 ) {
  645.                     retLength = java.lang.Math.max ( retLength , ( zoneStrings [i][j] ).length() );
  646.                             
  647.                 }
  648.                 
  649.             }
  650.         }
  651.         return retLength;
  652.         
  653.     }
  654.     
  655.     //private section
  656.     private boolean debug = false ;
  657.     
  658.     private int getMaximumLength( String [] strArr ){
  659.         
  660.         int retLength = 0;
  661.         for ( int i = 0 ; i < strArr.length ; i ++ ){
  662.             retLength = java.lang.Math.max ( retLength , strArr [ i ].length() );
  663.         }
  664.         return retLength;
  665.         
  666.     }
  667.     
  668.     
  669. }//end class DatePatternToMaskXLator
  670.     
  671.