Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/clra/member/Telephone.java


1   /*
2    * Copyright (c) Carnegie Lake Rowing Association 2002. All rights reserved.
3    * Distributed under the GPL license. See doc/COPYING.
4    * $RCSfile: Telephone.java,v $
5    * $Date: 2003/02/26 03:38:45 $
6    * $Revision: 1.13 $
7    */
8   
9   package com.clra.member;
10  
11  import java.io.Serializable;
12  
13  /**
14   * Encapsulates telephone information of a member.
15   * @version $Id: Telephone.java,v 1.13 2003/02/26 03:38:45 rphall Exp $
16   * @author <a href="mailto:rphall@pluto.njcc.com">Rick Hall</a>
17   */
18  public class Telephone implements Serializable {
19  
20    public final static String EVENING = "evening";
21  
22    public final static String DAY = "day";
23  
24    public final static String OTHER = "other";
25  
26    private String areaCode = null;
27    private String exchange = null;
28    private String local = null;
29    private String extension = null;
30  
31    // character indices
32    private int ac1;  // starting position of area code
33    private int xch0; // expected position of space before exchange
34    private int loc1; // expected start of local number
35    private int xt0;  // expected position of space before optional extension
36  
37    public static boolean isValidAreaCode( String areaCode ) {
38      boolean retVal = isValidComponent(areaCode);
39      retVal = retVal && areaCode.length() == 3;
40      return retVal;
41    }
42  
43    public static boolean isValidExchange( String exchange ) {
44      return isValidAreaCode(exchange);
45    }
46  
47    public static boolean isValidLocal( String local ) {
48      boolean retVal = isValidComponent(local);
49      retVal = retVal && local.length() == 4;
50      return retVal;
51    }
52  
53    public static boolean isValidExtension( String extension ) {
54      boolean retVal;
55      if ( extension == null ) {
56        retVal = true;
57      }
58      else {
59        retVal = isValidComponent(extension);
60        retVal = retVal && extension.length() > 0;
61      }
62      return retVal;
63    }
64  
65    private static boolean isValidComponent( String number ) {
66  
67      boolean retVal = number != null
68          && number.trim().length() == number.length()
69          && number.length() <= 5;
70  
71      for ( int i=0; retVal && i<number.length(); i++ ) {
72        retVal = Character.isDigit( number.charAt(i) );
73      }
74  
75      return retVal;
76    } // isValidLocal(String)
77  
78    /** Produces an invalid instance. Used only during deserialization. */
79    public Telephone() {}
80  
81    public Telephone( String ac, String ech, String lcl, String ext) {
82  
83      this.areaCode  =  ac == null ? null :  ac.trim();
84      this.exchange  = ech == null ? null : ech.trim();
85      this.local     = lcl == null ? null : lcl.trim();
86  
87      this.extension = ext == null ? null : ext.trim();
88      if ( this.extension != null && this.extension.length() == 0 ) {
89        this.extension = null;
90      }
91  
92      validateComponents();
93  
94    } // ctor(String,String,String,String)
95  
96    /**
97     * @param number a string of the form "(123) 456-7890 Ext. 12345"
98     * or "(123)-456-7890" where<ul>
99     * <li><tt>123</tt> is the area code, OPTIONALLY enclosed in parentheses</li>
100    * <li><tt>456</tt> is the exchange</li>
101    * <li><tt>7890</tt> is the local number, and <tt>12345</tt> is an optional
102    * extension.</li></ul>
103    * The area code, exchange and local number are required, so the minimal
104    * length of a valid number is 12 (or 14) including optional parentheses, a
105    * space or dash, and a second dash.
106    */
107   public Telephone( String number ) {
108 
109     // Precondition
110     if ( number == null || number.length() < 12 ) {
111       throw new IllegalArgumentException( "invalid number == " + number );
112     }
113 
114     // Character indices of components in string [(]ddd[)] ddd-dddd[ {d}*]
115     number = number.trim();
116     if ( number.charAt(0) == '(' && number.charAt(4) == ')' ) {
117       ac1 = 1;       // start of area code
118       xch0 = 5;      // position before exchange
119     }
120     else {    
121       ac1 = 0;       // start of area code
122       xch0 = 3;      // position before exchange
123     }
124     loc1 = xch0+5;   // start of local number
125     xt0  = loc1 + 4; // position before optional extension
126 
127     this.areaCode = parseAreaCode( number, ac1 );
128     this.exchange = parseExchange( number, xch0 );
129     this.local = parseLocal( number, loc1 );
130 
131     this.extension = parseExtension( number, xt0 );
132     if ( this.extension != null && this.extension.trim().length() == 0 ) {
133       this.extension = null;
134     }
135 
136     validateComponents();
137     if ( this.extension == null && number.length() > xt0 ) {
138       String msg = "unable to parse extension from '" + number + "'";
139       throw new IllegalArgumentException( msg );
140     }
141 
142   } // ctor(String)
143 
144   private void validateComponents() {
145 
146     if ( !isValidAreaCode(this.areaCode) ) {
147       throw new IllegalArgumentException( "null or invalid area code" );
148     }
149 
150     if ( !isValidExchange(this.exchange) ) {
151       throw new IllegalArgumentException( "null or invalid exchange" );
152     }
153 
154     if ( !isValidLocal(this.local) ) {
155       throw new IllegalArgumentException( "null or invalid local number" );
156     }
157 
158   } // validateComponents()
159 
160   /** Creates a valid telephone number or returns null */
161   public static Telephone createTelephone( String areaCode,
162     String exchange, String local, String extension ) {
163     Telephone retVal = null;
164     if ( isValidAreaCode(areaCode)
165          && isValidExchange(exchange) && isValidLocal(local) ) {
166       retVal = new Telephone(areaCode,exchange,local,extension);
167     }
168     return retVal;
169   } // createTelephone(String,String,String,String)
170 
171   public String getAreaCode()  { return this.areaCode;  }
172   public String getExchange()  { return this.exchange;  }
173   public String getLocal()     { return this.local;     }
174   public String getExtension() { return this.extension; }
175 
176   /** @return a 3-digit number starting at index 'ac1', or null on error */
177   private static String parseAreaCode( String number, int ac1 ) {
178     String retVal = null;
179     if ( Character.isDigit( number.charAt(ac1) )
180            && Character.isDigit( number.charAt(ac1+1) )
181            && Character.isDigit( number.charAt(ac1+2) ) ) {
182         retVal = number.substring( ac1, ac1+3 );
183     }
184 
185     return retVal;
186   } // parseAreaCode(String)
187 
188   /** @return a 3-digit number, or null on error */
189   private static String parseExchange( String number, int xch0 ) {
190     String retVal = null;
191     if ( (number.charAt(xch0) == ' ' && number.charAt(xch0+4) == '-')
192         || (number.charAt(xch0) == '-' && number.charAt(xch0+4) == '-') ) {
193       if ( Character.isDigit( number.charAt(xch0+1) ) 
194            && Character.isDigit( number.charAt(xch0+2) )
195            && Character.isDigit( number.charAt(xch0+3) ) ) {
196         retVal = number.substring( xch0+1, xch0+4 );
197       }
198     }
199 
200     return retVal;
201   } // parseExchange(String)
202 
203   /** @return a 4-digit number, or null on error */
204   private static String parseLocal( String number, int loc1 ) {
205     String retVal = null;
206     if ( Character.isDigit( number.charAt(loc1) )
207          && Character.isDigit( number.charAt(loc1+1) )
208          && Character.isDigit( number.charAt(loc1+2) )
209          && Character.isDigit( number.charAt(loc1+3) ) ) {
210       retVal = number.substring( loc1, loc1+4 );
211     }
212 
213     return retVal;
214   } // parseLocal(String)
215 
216   /** @return a numerical extension or null */
217   private static String parseExtension( String number, int xt0 ) {
218     String retVal = null;
219     
220     // Optional extension is " Ext. " plus at least one digit
221     if ( number.length() > xt0+6 ) {
222       String nxt = number.substring(xt0, xt0+5);
223       if ( nxt.compareTo(" ext.") == 0 || nxt.compareTo(" Ext.") == 0
224         || nxt.compareTo(" EXT.") == 0 ) {
225         try {
226           int test = Integer.parseInt( number.substring(xt0+6) );
227           retVal = number.substring(xt0+6);
228         }
229         catch( NumberFormatException ignored ) {}
230       }
231     }
232 
233     return retVal;
234   } // parseExtension(String)
235 
236   public String toString() {
237     StringBuffer sb = new StringBuffer(25);
238     sb.append( "(" );
239     sb.append( this.areaCode );
240     sb.append( ") " );
241     sb.append( this.exchange );
242     sb.append( "-" );
243     sb.append( this.local );
244     if ( this.extension != null && this.extension.trim().length() > 0 ) {
245       sb.append( " Ext. " );
246       sb.append( this.extension.trim() );
247     }
248     String retVal = new String( sb );
249 
250     return retVal;
251   } // toString()
252 
253   public boolean equals( Object o ) {
254     boolean retVal;
255     if ( o == null ) {
256       retVal = false;
257     }
258     else if ( o instanceof Telephone ) {
259       Telephone that = (Telephone) o;
260       retVal = this.areaCode.equals(that.areaCode);
261       retVal = retVal && this.exchange.equals(that.exchange);
262       retVal = retVal && this.local.equals(that.local);
263       if ( this.extension != null ) {
264         retVal = retVal && this.extension.equals(that.extension);
265       }
266       else {
267         retVal = retVal && that.extension == null;
268       }
269     }
270     else if ( o instanceof String ) {
271       retVal = false;
272       try {
273         Telephone other = new Telephone( (String)o );
274         retVal = this.equals(other);
275       } catch( Exception x ) {
276         // don't care
277       }
278     }
279     else {
280       retVal = false;
281     }
282 
283     return retVal;
284   } // equals(Object)
285 
286   public int hashCode() {
287     int retVal = this.local.hashCode(); // good enough
288     return retVal;
289   }
290 
291 } // Telephone
292 
293 /*
294  * $Log: Telephone.java,v $
295  * Revision 1.13  2003/02/26 03:38:45  rphall
296  * Added copyright and GPL license
297  *
298  * Revision 1.12  2003/02/21 15:08:33  rphall
299  * More fixes to blank extension bug
300  *
301  * Revision 1.11  2003/02/21 14:30:37  rphall
302  * Fixed bug with blank extensions
303  *
304  * Revision 1.10  2003/02/19 22:26:39  rphall
305  * Removed gratuitous use of CLRA acronym
306  *
307  * Revision 1.9  2003/02/19 03:16:56  rphall
308  * Added validation for extension
309  *
310  * Revision 1.8  2003/02/18 04:21:34  rphall
311  * Added validation methods
312  *
313  * Revision 1.7  2003/02/15 04:31:42  rphall
314  * Changes connected to major revision of MemberBean
315  *
316  * Revision 1.6  2003/02/10 05:10:51  rphall
317  * Added parsing for '-' between area code and exchange
318  *
319  */
320