View Javadoc
1   /*
2    *  jDTAUS Banking Utilities
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.util.swing;
22  
23  import java.text.ParseException;
24  import javax.swing.JFormattedTextField;
25  import javax.swing.JFormattedTextField.AbstractFormatter;
26  import javax.swing.text.AttributeSet;
27  import javax.swing.text.BadLocationException;
28  import javax.swing.text.DocumentFilter;
29  import org.jdtaus.banking.AlphaNumericText27;
30  import org.jdtaus.core.container.ContainerFactory;
31  
32  /**
33   * {@code JFormattedTextField} supporting the {@code AlphaNumericText27} type.
34   * <p>This textfield uses the {@link AlphaNumericText27} type for parsing and formatting. An empty string value is
35   * treated as {@code null}. The {@code normalizing} flag controls parsing. If {@code true} (default) the field's value
36   * is normalized using the {@link AlphaNumericText27#normalize(String)} method prior to parsing. The {@code validating}
37   * flag controls validation of values entered into the textfield. If {@code true} (default), a {@code DocumentFilter} is
38   * registered with the textfield disallowing invalid values, that is, values which are not {@code null} and not empty
39   * strings and for which the {@link AlphaNumericText27#parse(String)} method throws a {@code ParseException}.</p>
40   *
41   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
42   * @version $JDTAUS: AlphaNumericText27TextField.java 8864 2014-01-10 17:13:30Z schulte $
43   */
44  public final class AlphaNumericText27TextField extends JFormattedTextField
45  {
46  
47      /** Serial version UID for backwards compatibility with 1.1.x classes. */
48      private static final long serialVersionUID = -8152767220100367519L;
49  
50      /**
51       * Flag indicating if a normalizing parser is used.
52       * @serial
53       */
54      private Boolean normalizing;
55  
56      /**
57       * Flag indicating if validation is performed.
58       * @serial
59       */
60      private Boolean validating;
61  
62      /** Creates a new default {@code AlphaNumericText27TextField} instance. */
63      public AlphaNumericText27TextField()
64      {
65          super();
66          this.setColumns( AlphaNumericText27.MAX_LENGTH );
67          this.setFormatterFactory( new AbstractFormatterFactory()
68          {
69  
70              public AbstractFormatter getFormatter( final JFormattedTextField ftf )
71              {
72                  return new AbstractFormatter()
73                  {
74  
75                      public Object stringToValue( final String text ) throws ParseException
76                      {
77                          Object value = null;
78  
79                          if ( text != null && text.trim().length() > 0 )
80                          {
81                              value = AlphaNumericText27.parse(
82                                  isNormalizing() ? AlphaNumericText27.normalize( text ) : text );
83  
84                          }
85  
86                          return value;
87                      }
88  
89                      public String valueToString( final Object value ) throws ParseException
90                      {
91                          String ret = null;
92  
93                          if ( value instanceof AlphaNumericText27 )
94                          {
95                              final AlphaNumericText27 txt = (AlphaNumericText27) value;
96                              ret = txt.isEmpty() ? null : txt.format().trim();
97                          }
98  
99                          return ret;
100                     }
101 
102                     protected DocumentFilter getDocumentFilter()
103                     {
104                         return new DocumentFilter()
105                         {
106 
107                             public void insertString( final FilterBypass fb, final int o, String s,
108                                                       final AttributeSet a ) throws BadLocationException
109                             {
110                                 if ( isValidating() )
111                                 {
112                                     if ( isNormalizing() )
113                                     {
114                                         final char[] chars = s.toCharArray();
115                                         for ( int i = chars.length - 1; i >= 0; i-- )
116                                         {
117                                             chars[i] = Character.toUpperCase( chars[i] );
118                                         }
119                                         s = String.valueOf( chars );
120                                     }
121 
122                                     final StringBuffer b =
123                                         new StringBuffer( fb.getDocument().getLength() + s.length() );
124 
125                                     b.append( fb.getDocument().getText( 0, fb.getDocument().getLength() ) );
126                                     b.insert( o, s );
127 
128                                     try
129                                     {
130                                         AlphaNumericText27.parse( b.toString() );
131                                     }
132                                     catch ( ParseException e )
133                                     {
134                                         invalidEdit();
135                                         return;
136                                     }
137                                 }
138 
139                                 super.insertString( fb, o, s, a );
140                             }
141 
142                             public void replace( final FilterBypass fb, final int o, final int l, String s,
143                                                  final AttributeSet a ) throws BadLocationException
144                             {
145                                 if ( isValidating() )
146                                 {
147                                     if ( isNormalizing() )
148                                     {
149                                         final char[] chars = s.toCharArray();
150                                         for ( int i = chars.length - 1; i >= 0; i-- )
151                                         {
152                                             chars[i] = Character.toUpperCase( chars[i] );
153                                         }
154                                         s = String.valueOf( chars );
155                                     }
156 
157                                     final StringBuffer b = new StringBuffer(
158                                         fb.getDocument().getText( 0, fb.getDocument().getLength() ) );
159 
160                                     b.delete( o, o + l );
161 
162                                     if ( s != null )
163                                     {
164                                         b.insert( o, s );
165                                     }
166 
167                                     try
168                                     {
169                                         AlphaNumericText27.parse( b.toString() );
170                                     }
171                                     catch ( ParseException e )
172                                     {
173                                         invalidEdit();
174                                         return;
175                                     }
176                                 }
177 
178                                 super.replace( fb, o, l, s, a );
179                             }
180 
181                         };
182                     }
183 
184                 };
185             }
186 
187         } );
188     }
189 
190     /**
191      * Gets the last valid {@code AlphaNumericText27}.
192      *
193      * @return the last valid {@code AlphaNumericText27} or {@code null}.
194      */
195     public AlphaNumericText27 getAlphaNumericText27()
196     {
197         return (AlphaNumericText27) this.getValue();
198     }
199 
200     /**
201      * Gets the flag indicating if a normalizing parser is used.
202      *
203      * @return {@code true} if a normalizing parser is used; {@code false} if a strict parser is used
204      * (defaults to {@code true}).
205      */
206     public boolean isNormalizing()
207     {
208         if ( this.normalizing == null )
209         {
210             this.normalizing = this.isDefaultNormalizing();
211         }
212 
213         return this.normalizing.booleanValue();
214     }
215 
216     /**
217      * Sets the flag indicating if a normalizing parser should be used.
218      *
219      * @param value {@code true} to use a normalizing parser; {@code false} to use a strict parser
220      * (defaults to {@code true}).
221      */
222     public void setNormalizing( final boolean value )
223     {
224         this.normalizing = Boolean.valueOf( value );
225     }
226 
227     /**
228      * Gets the flag indicating if validation is performed.
229      *
230      * @return {@code true} if the field's value is validated; {@code false} if no validation of the field's value is
231      * performed.
232      */
233     public boolean isValidating()
234     {
235         if ( this.validating == null )
236         {
237             this.validating = this.isDefaultValidating();
238         }
239 
240         return this.validating.booleanValue();
241     }
242 
243     /**
244      * Sets the flag indicating if validation should be performed.
245      *
246      * @param value {@code true} to validate the field's value; {@code false} to not validate the field's value.
247      */
248     public void setValidating( boolean value )
249     {
250         this.validating = Boolean.valueOf( value );
251     }
252 
253     //--Properties--------------------------------------------------------------
254 
255 // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausProperties
256     // This section is managed by jdtaus-container-mojo.
257 
258     /**
259      * Gets the value of property <code>defaultValidating</code>.
260      *
261      * @return Default value of the flag indicating if validation should be performed.
262      */
263     private java.lang.Boolean isDefaultValidating()
264     {
265         return (java.lang.Boolean) ContainerFactory.getContainer().
266             getProperty( this, "defaultValidating" );
267 
268     }
269 
270     /**
271      * Gets the value of property <code>defaultNormalizing</code>.
272      *
273      * @return Default value of the flag indicating if a normalizing parser should be used.
274      */
275     private java.lang.Boolean isDefaultNormalizing()
276     {
277         return (java.lang.Boolean) ContainerFactory.getContainer().
278             getProperty( this, "defaultNormalizing" );
279 
280     }
281 
282 // </editor-fold>//GEN-END:jdtausProperties
283 
284     //--------------------------------------------------------------Properties--
285 }