Source code: com/clra/member/remote/MemberBean.java
1 /*
2 * Copyright (c) Carnegie Lake Rowing Association 2002. All rights reserved.
3 * Distributed under the GPL license. See doc/COPYING.
4 * $RCSfile: MemberBean.java,v $
5 * $Date: 2003/02/26 03:38:45 $
6 * $Revision: 1.11 $
7 */
8
9 package com.clra.member.remote;
10
11 import com.clra.member.Configuration;
12 import com.clra.util.DBConfiguration;
13 import com.clra.util.ISerializableComparator;
14 import com.clra.util.ErrorUtils;
15 import com.clra.member.AccountType;
16 import com.clra.member.Address;
17 import com.clra.member.Email;
18 import com.clra.member.MemberDBRead;
19 import com.clra.member.MemberException;
20 import com.clra.member.MemberName;
21 import com.clra.member.MemberRole;
22 import com.clra.member.MemberSnapshot;
23 import com.clra.member.Telephone;
24 import java.rmi.RemoteException;
25 import java.sql.Connection;
26 import java.sql.PreparedStatement;
27 import java.sql.ResultSet;
28 import java.sql.SQLException;
29 import java.sql.Types;
30 import java.util.ArrayList;
31 import java.util.Calendar;
32 import java.util.Collection;
33 import java.util.Date;
34 import java.util.HashMap;
35 import java.util.HashSet;
36 import java.util.Iterator;
37 import java.util.Map;
38 import java.util.Set;
39 import java.text.SimpleDateFormat;
40 import javax.ejb.CreateException;
41 import javax.ejb.EJBException;
42 import javax.ejb.EntityBean;
43 import javax.ejb.EntityContext;
44 import javax.ejb.FinderException;
45 import javax.ejb.NoSuchEntityException;
46 import javax.ejb.ObjectNotFoundException;
47 import javax.ejb.RemoveException;
48 import org.apache.log4j.Category;
49
50 /**
51 * @author <a href="mailto:donaldzhu@sympatico.ca">Angela Yue</a>
52 * @author <a href="mailto:rphall@pluto.njcc.com">Rick Hall</a>
53 * @version $Revision: 1.11 $ $Date: 2003/02/26 03:38:45 $
54 */
55
56 public class MemberBean implements EntityBean {
57
58 private final static String base = MemberBean.class.getName();
59 private final static Category theLog = Category.getInstance( base );
60
61 private transient boolean isDirty = false;
62
63 private EntityContext context = null;
64
65 private Integer m_memberId = null;
66 private String m_accountName = null;
67 private String m_accountPassword = null;
68 private AccountType m_accountType = null;
69 private MemberName m_memberName = null;
70 private Email m_email = null;
71 private Telephone m_eveningPhone = null;
72 private Telephone m_dayPhone = null;
73 private Telephone m_otherPhone = null;
74 private Address m_address = null;
75 private Date m_accountYear = null;
76 private Date m_birthDate = null;
77 private Set m_roles = null;
78
79 public final static SimpleDateFormat dateFormat =
80 new SimpleDateFormat( Configuration.SQL_DATE_FORMAT );
81
82 /** Set the context (and primary key) of this instance */
83 public void setEntityContext(EntityContext ctx) {
84
85 this.context = ctx;
86 if ( theLog.isDebugEnabled() ) {
87 theLog.debug( "setEntityContext: context set" );
88 theLog.debug( "setEntityContext: id == " + this.m_memberId );
89 }
90
91 return;
92 } // setEntityContext(EntityContext)
93
94 /** Unset the context (and primary key) of this instance */
95 public void unsetEntityContext() {
96
97 this.context = null;
98 if ( theLog.isDebugEnabled() ) {
99 theLog.debug( "unsetEntityContext: id nulled" );
100 theLog.debug( "unsetEntityContext: context nulled" );
101 }
102
103 return;
104 } // unsetEntityContext()
105
106 /**
107 * Sets all properties of a member except the member id. The member id
108 * of the specified snapshot must match the member id of this bean.
109 */
110 public void setData(MemberSnapshot data) {
111 _setData(data);
112 }
113
114 /**
115 * A private method outside the watchful eye of the EJB container. Used
116 * to implement both <code>setData</code> and <code>loadRows()</code>.
117 */
118 private void _setData( MemberSnapshot data ) {
119
120 if ( !m_memberId.equals(data.getId()) ) {
121 String msg = "memberId == '" +m_memberId+ "' != '" +data.getId()+ "'";
122 throw new IllegalArgumentException( msg );
123 }
124
125 setAccountName( data.getAccountName() );
126 setAccountPassword( data.getAccountPassword() );
127 setAccountType( data.getAccountType() );
128 setMemberName( data.getMemberName() );
129 setEmail( data.getEmail() );
130
131 Map phones = data.getTelephoneNumbers();
132 Telephone evening = (Telephone) phones.get( Telephone.EVENING );
133 setEveningTelephone( evening );
134
135 Telephone day = (Telephone) phones.get( Telephone.DAY );
136 setDayTelephone( day );
137
138 Telephone other = (Telephone) phones.get( Telephone.OTHER );
139 setOtherTelephone( other );
140
141 setAddress( data.getAddress() );
142 setAccountYear( data.getAccountDate() );
143 setBirthDate( data.getBirthDate() );
144 setMemberRoles( data.getMemberRoles() );
145
146 return;
147 } // setData( MemberSnapshot )
148
149 public void setAccountName(String accountName) {
150 if ( accountName == null || accountName.trim().length() == 0 ) {
151 String msg = "invalid account name == '" +accountName+ "'";
152 throw new IllegalArgumentException( msg );
153 }
154 if ( m_accountName == null || !m_accountName.equals(accountName) ) {
155 this.isDirty = true;
156 m_accountName = accountName;
157 }
158 return;
159 } // setAccountName(String)
160
161 public void setAccountPassword(String password) {
162 if ( password == null || password.trim().length() == 0 ) {
163 String msg = "invalid password == '" +password+ "'";
164 throw new IllegalArgumentException( msg );
165 }
166 if ( m_accountPassword == null || !m_accountPassword.equals(password) ) {
167 this.isDirty = true;
168 m_accountPassword = password;
169 }
170 return;
171 } // setAccountPassword(String)
172
173 public void setAccountType(AccountType type ) {
174 if ( type == null ) {
175 throw new IllegalArgumentException( "null account type" );
176 }
177 if ( m_accountType == null || !m_accountType.equals(type) ) {
178 this.isDirty = true;
179 m_accountType = type;
180 }
181 return;
182 } // setAccountType(AccountType)
183
184 public void setMemberName(MemberName name) {
185 if ( name == null ) {
186 throw new IllegalArgumentException( "null member name" );
187 }
188 if ( m_memberName == null || !m_memberName.equals(name) ) {
189 this.isDirty = true;
190 m_memberName = name;
191 }
192 return;
193 } // setMemberName(MemberName)
194
195 public void setEmail(Email email) {
196 if ( m_email != null && !m_email.equals(email) ) {
197 this.isDirty = true;
198 m_email = email;
199 }
200 else if ( m_email == null && email != null ) {
201 this.isDirty = true;
202 m_email = email;
203 }
204 return;
205 } // setEmail(Email)
206
207 public void setTelephones( Map telephones ) {
208
209 if ( telephones == null ) {
210 throw new IllegalArgumentException( "null telephone map" );
211 }
212
213 Telephone phone = (Telephone) telephones.get( Telephone.EVENING );
214 if ( phone == null ) {
215 String msg = "null evening phone";
216 theLog.error( msg );
217 throw new IllegalArgumentException( msg );
218 }
219 if ( m_eveningPhone == null || !m_eveningPhone.equals(phone) ) {
220 this.isDirty = true;
221 m_eveningPhone = phone;
222 }
223
224 phone = (Telephone) telephones.get( Telephone.DAY );
225 if ( m_dayPhone != null && !m_dayPhone.equals(phone) ) {
226 this.isDirty = true;
227 m_dayPhone = phone;
228 }
229 else if ( m_dayPhone == null && phone != null ) {
230 this.isDirty = true;
231 m_dayPhone = phone;
232 }
233
234 phone = (Telephone) telephones.get( Telephone.OTHER );
235 if ( m_otherPhone != null && !m_otherPhone.equals(phone) ) {
236 this.isDirty = true;
237 m_otherPhone = phone;
238 }
239 else if ( m_otherPhone == null && phone != null ) {
240 this.isDirty = true;
241 m_otherPhone = phone;
242 }
243
244 return;
245 } // setTelephones(Map)
246
247 public void setEveningTelephone(Telephone phone) {
248 if ( phone == null ) {
249 throw new IllegalArgumentException( "null evening phone" );
250 }
251 if ( m_eveningPhone == null || !m_eveningPhone.equals(phone) ) {
252 this.isDirty = true;
253 m_eveningPhone = phone;
254 }
255 return;
256 } // setEveningTelephone(Telephone)
257
258 public void setDayTelephone(Telephone phone) {
259 if ( m_dayPhone != null && !m_dayPhone.equals(phone) ) {
260 this.isDirty = true;
261 m_dayPhone = phone;
262 }
263 else if ( m_dayPhone == null && phone != null ) {
264 this.isDirty = true;
265 m_dayPhone = phone;
266 }
267 return;
268 } // setDayTelephone(Telephone)
269
270 public void setOtherTelephone(Telephone phone) {
271 if ( m_otherPhone != null && !m_otherPhone.equals(phone) ) {
272 this.isDirty = true;
273 m_otherPhone = phone;
274 }
275 else if ( m_otherPhone == null && phone != null ) {
276 this.isDirty = true;
277 m_otherPhone = phone;
278 }
279 return;
280 } // setOtherTelephone(Telephone)
281
282 public void setAddress(Address address) {
283 if ( address == null ) {
284 throw new IllegalArgumentException( "null mailing address" );
285 }
286 if ( m_address == null || !m_address.equals( address ) ) {
287 this.isDirty = true;
288 m_address = address;
289 }
290 return;
291 } // setAddress(Address)
292
293 public void setAccountYear(Date year) {
294 if ( year == null ) {
295 throw new IllegalArgumentException( "null year" );
296 }
297 if ( m_accountYear == null || !m_accountYear.equals( year ) ) {
298 this.isDirty = true;
299 m_accountYear = year;
300 }
301 return;
302 } // setAccountYear(Date)
303
304 public void setBirthDate(Date date) {
305 if ( m_birthDate != null && !m_birthDate.equals(date) ) {
306 this.isDirty = true;
307 m_birthDate = date;
308 }
309 else if ( date != null ) {
310 this.isDirty = true;
311 m_birthDate = date;
312 }
313 return;
314 } // setBirthDate(Date)
315
316 public void setMemberRoles( MemberRole[] roles ) {
317 if ( roles == null ) {
318 throw new IllegalArgumentException( "null roles" );
319 }
320 boolean isOutOfDate = false;
321 if ( m_roles == null ) {
322 isOutOfDate = true;
323 }
324 else if ( m_roles.size() != roles.length ) {
325 isOutOfDate = true;
326 }
327 else {
328 for ( int i=0; i<roles.length; i++ ) {
329 if ( roles[i] != null && !m_roles.contains(roles[i]) ) {
330 isOutOfDate = true;
331 break;
332 }
333 else if ( roles[i] == null ) {
334 isOutOfDate = true;
335 break;
336 }
337 } // for
338 }
339
340 if ( isOutOfDate ) {
341 this.isDirty = true;
342 m_roles = new HashSet( roles.length );
343 for ( int i=0; i<roles.length; i++ ) {
344 if ( roles[i] != null ) {
345 m_roles.add( roles[i] );
346 }
347 } // for
348 }
349
350 return;
351 } // setMemberRoles(MemberRole[])
352
353 public Integer getId() {
354 return m_memberId;
355 }
356
357 public MemberSnapshot getData() {
358
359 Map phones = new HashMap();
360 phones.put( Telephone.EVENING, m_eveningPhone );
361 if ( m_dayPhone != null ) {
362 phones.put( Telephone.DAY, m_dayPhone );
363 }
364 if ( m_otherPhone != null ) {
365 phones.put( Telephone.OTHER, m_otherPhone );
366 }
367
368 MemberRole[] roles = (MemberRole[]) m_roles.toArray( new MemberRole[0] );
369
370 MemberSnapshot retVal = new MemberSnapshot( m_memberId,
371 m_accountName, m_accountPassword, m_accountType, m_memberName,
372 m_email, phones, m_address, m_accountYear, m_birthDate, roles );
373
374 return retVal;
375 } // getData()
376
377 public String getAccountName() {
378 return m_accountName;
379 }
380
381 public String getAccountPassword() {
382 return m_accountPassword;
383 }
384
385 public AccountType getAccountType() {
386 return m_accountType;
387 }
388
389 public MemberName getMemberName() {
390 return m_memberName;
391 }
392
393 public Email getEmail() {
394 return m_email;
395 }
396
397 public Map getTelephones() {
398
399 if ( m_eveningPhone == null ) {
400 throw new IllegalStateException( "null evening phone" );
401 }
402
403 Map retVal = new HashMap();
404 retVal.put( Telephone.EVENING, m_eveningPhone );
405 if ( m_dayPhone != null ) {
406 retVal.put( Telephone.DAY, m_dayPhone );
407 }
408 if ( m_otherPhone != null ) {
409 retVal.put( Telephone.OTHER, m_otherPhone );
410 }
411
412 return retVal;
413 } // getTelephones()
414
415 public Telephone getEveningTelephone() {
416 return m_eveningPhone;
417 }
418
419 public Telephone getDayTelephone() {
420 return m_dayPhone;
421 }
422
423 public Telephone getOtherTelephone() {
424 return m_otherPhone;
425 }
426
427 public Address getAddress() {
428 return m_address;
429 }
430
431 public Date getAccountYear() {
432 return m_accountYear;
433 }
434
435 public Date getBirthDate() {
436 return m_birthDate;
437 }
438
439 public MemberRole[] getMemberRoles() {
440 MemberRole[] retVal = (MemberRole[]) m_roles.toArray( new MemberRole[0] );
441 return retVal;
442 }
443
444 public Integer ejbCreate(
445 String accountName,
446 String accountPassword,
447 AccountType accountType,
448 MemberName memberName,
449 Email email,
450 Telephone evening,
451 Telephone day,
452 Telephone other,
453 Address address,
454 Date accountYear,
455 Date birthDate,
456 MemberRole[] roles
457 ) throws CreateException {
458
459 try {
460
461 m_memberId = nextId();
462
463 setAccountName( accountName );
464 setAccountPassword( accountPassword );
465 setAccountType( accountType );
466 setMemberName( memberName );
467 setEmail( email );
468 setEveningTelephone( evening );
469 setDayTelephone( day );
470 setOtherTelephone( other );
471 setAddress( address );
472 setAccountYear( accountYear );
473 setBirthDate( birthDate );
474 setMemberRoles( roles );
475
476 insertRows();
477
478 // FIXME shouldn't isDirty be set false here?
479 //this.isDirty = false;
480 // ENDFIXME
481
482 if ( theLog.isDebugEnabled() ) {
483 String msg = "ejbCreate: " + m_memberId + ", '" + accountName
484 + "', '" + memberName.getLastName()
485 + "', '" + memberName.getFirstName() + "'";
486 theLog.debug( msg );
487 }
488
489 }
490 catch (Exception ex) {
491 theLog.error( "ejbCreate", ex );
492 throw new EJBException( "ejbCreate: " + ex.getMessage() );
493 }
494
495 return m_memberId;
496 } // ejbCreate
497
498 public void ejbPostCreate( String accountName, String accountPassword,
499 AccountType accountType, MemberName memberName, Email email,
500 Telephone evening, Telephone day, Telephone other, Address address,
501 Date accountYear, Date birthDate, MemberRole[] roles ) {
502 }
503
504 public Integer ejbFindByPrimaryKey(final Integer primaryKey)
505 throws FinderException {
506
507 // Precondition
508 if ( primaryKey == null ) {
509 throw new FinderException( "null primaryKey" );
510 }
511
512 Connection conn = null;
513 PreparedStatement stmt = null;
514 ResultSet rs = null;
515 boolean hasRow = false;
516 try {
517 conn = DBConfiguration.getConnection();
518 stmt = conn.prepareStatement(Configuration.SQL_08,
519 ResultSet.TYPE_FORWARD_ONLY,
520 ResultSet.CONCUR_READ_ONLY);
521
522 stmt.setInt( 1, primaryKey.intValue() );
523
524 rs = stmt.executeQuery();
525 hasRow = rs.next();
526 if ( theLog.isDebugEnabled() ) {
527 theLog.debug( "selectByPrimaryKey: hasRow == " + hasRow );
528 }
529
530 } catch (Exception ex) {
531 theLog.debug("Exception in ejbFindByPrimaryKey: " + ex.getMessage());
532 }
533 finally {
534 DBConfiguration.closeSQLResultSet( rs );
535 DBConfiguration.closeSQLStatement( stmt );
536 DBConfiguration.closeSQLConnection( conn );
537 rs = null;
538 stmt = null;
539 conn = null;
540 }
541
542 if (!hasRow) {
543 String msg = "Row for primaryKey '" + primaryKey + "' not found.";
544 throw new ObjectNotFoundException( msg );
545 }
546
547 return primaryKey;
548 } // ejbFindByPrimaryKey(Integer)
549
550 public Integer ejbFindByAccountName(String name)
551 throws FinderException {
552
553 Connection conn = null;
554 PreparedStatement stmt = null;
555 ResultSet rs = null;
556 boolean retVal = false;
557 Integer primaryKey = null;
558
559 try {
560 conn = DBConfiguration.getConnection();
561 stmt = conn.prepareStatement(Configuration.SQL_081,
562 ResultSet.TYPE_FORWARD_ONLY,
563 ResultSet.CONCUR_READ_ONLY);
564
565 stmt.setString( 1, name );
566
567 rs = stmt.executeQuery();
568 retVal = rs.next();
569 primaryKey = new Integer(rs.getInt(1));
570
571 if ( theLog.isDebugEnabled() ) {
572 theLog.debug( "selectByPrimaryKey: retVal == " + retVal );
573 }
574
575 } catch (Exception ex) {
576 theLog.debug("Exception in ejbFindByPrimaryKey: " + ex);
577 }
578 finally {
579 DBConfiguration.closeSQLResultSet( rs );
580 DBConfiguration.closeSQLStatement( stmt );
581 DBConfiguration.closeSQLConnection( conn );
582 rs = null;
583 stmt = null;
584 conn = null;
585 }
586
587 if (!retVal) {
588 String msg = "Row for primary '" + primaryKey + "' not found.";
589 throw new ObjectNotFoundException( msg );
590 }
591
592 m_memberId = primaryKey;
593 theLog.info("findByAccountName m_memberId = " + m_memberId );
594
595 return primaryKey;
596 } // ejbFindByAccountName(String)
597
598 public Collection ejbFindAll()
599 throws FinderException {
600
601 Connection conn = null;
602 PreparedStatement stmt = null;
603 ResultSet rs = null;
604 Collection retVal = new ArrayList();
605 try {
606 conn = DBConfiguration.getConnection();
607 stmt = conn.prepareStatement(Configuration.SQL_09,
608 ResultSet.TYPE_FORWARD_ONLY,
609 ResultSet.CONCUR_READ_ONLY);
610
611 rs = stmt.executeQuery();
612
613 int rowCount = 0;
614 while ( rs.next() ) {
615 Integer m_memberId = new Integer( rs.getInt(1) );
616 retVal.add(m_memberId);
617 ++rowCount;
618 }
619
620 if ( theLog.isDebugEnabled() ) {
621 String msg = "selectAll: rowCount == " + rowCount;
622 theLog.debug( msg );
623 }
624
625 } catch (Exception ex) {
626 theLog.debug("Exception in ejbFindAll: " + ex);
627 }
628
629 finally {
630 DBConfiguration.closeSQLResultSet( rs );
631 DBConfiguration.closeSQLStatement( stmt );
632 DBConfiguration.closeSQLConnection( conn );
633 rs = null;
634 stmt = null;
635 conn = null;
636 }
637
638 return retVal;
639 } // ejbFindAll()
640
641 /** @see delete() */
642 public void ejbRemove() {
643
644 Connection conn = null;
645 PreparedStatement stmt = null;
646 ResultSet rs = null;
647
648 try {
649 conn = DBConfiguration.getConnection();
650 stmt = conn.prepareStatement(Configuration.SQL_10,
651 ResultSet.TYPE_FORWARD_ONLY,
652 ResultSet.CONCUR_READ_ONLY);
653
654 stmt.setInt( 1, m_memberId.intValue());
655
656 rs = stmt.executeQuery();
657
658 deleteRoles(); // delete old roles
659
660 if ( theLog.isDebugEnabled() ) {
661 theLog.debug( "deleteRow: row " + m_memberId );
662 }
663
664 } catch (Exception ex) {
665 theLog.debug("Exception in ejbRemove: " + ex);
666 }
667
668 finally {
669 DBConfiguration.closeSQLResultSet( rs );
670 DBConfiguration.closeSQLStatement( stmt );
671 DBConfiguration.closeSQLConnection( conn );
672 rs = null;
673 stmt = null;
674 conn = null;
675 }
676
677 return;
678 } // ejbRemove()
679
680 public void ejbActivate() {
681 this.m_memberId = (Integer) this.context.getPrimaryKey();
682 if ( theLog.isDebugEnabled() ) {
683 theLog.debug( "ejbActivate: m_memberId == " + m_memberId );
684 }
685 }
686
687 public void ejbPassivate() {
688 this.m_memberId = null;
689 if ( theLog.isDebugEnabled() ) {
690 theLog.debug( "MemberBean.ejbPassivate: m_memberId == " + m_memberId );
691 }
692 }
693
694 public void ejbLoad() {
695
696 this.m_memberId = (Integer) this.context.getPrimaryKey();
697 if ( theLog.isDebugEnabled() ) {
698 theLog.debug( "ejbLoad: m_memberId == " + m_memberId );
699 }
700
701 try {
702 loadRows();
703 if ( theLog.isDebugEnabled() ) {
704 theLog.debug( "ejbLoad: row loaded" );
705 }
706 isDirty = false;
707 }
708 catch (Exception ex) {
709 theLog.error( "ejbLoad", ex );
710 throw new EJBException("ejbLoad: " + ex.getMessage());
711 }
712
713 } // ejbLoad()
714
715 public void ejbStore() {
716
717 try {
718 if ( isDirty ) {
719 storeRows();
720 if ( theLog.isDebugEnabled() ) {
721 theLog.debug( "ejbStore: row stored for #" + m_memberId );
722 }
723 isDirty = false;
724 }
725 else {
726 if ( theLog.isDebugEnabled() ) {
727 theLog.debug( "ejbStore: row skipped" );
728 }
729 }
730 }
731 catch (Exception ex) {
732 String msg = ErrorUtils.createDbgMsg( "ejbStore", ex );
733 theLog.error( msg, ex );
734 throw new EJBException(msg);
735 }
736
737 } // ejbStore()
738
739 /** Inserts a single Member row, and possibly multiple MemberRole rows */
740 private void insertRows() throws SQLException, CreateException {
741
742 Connection conn = null;
743 PreparedStatement stmt = null;
744 int rowCount = 0;
745 try {
746
747 conn = DBConfiguration.getConnection();
748 stmt = conn.prepareStatement(Configuration.SQL_12);
749
750 stmt.setInt(1, m_memberId.intValue() );
751 stmt.setString(2, m_accountName );
752 stmt.setString(3, m_accountPassword );
753 stmt.setString(4, m_accountType.toString() );
754 stmt.setString(5, m_memberName.getLastName() );
755 stmt.setString(6, m_memberName.getFirstName() );
756
757 int paramInd = 7;
758 final String nmiddle = m_memberName.getMiddleName();
759 if ( nmiddle != null && nmiddle.length() > 0 ) {
760 stmt.setString(paramInd, nmiddle);
761 } else {
762 stmt.setNull(paramInd, Types.VARCHAR);
763 }
764 paramInd++;
765
766 final String nsuffix = m_memberName.getSuffix();
767 if ( nsuffix != null && nsuffix .length() > 0 ) {
768 stmt.setString(paramInd, nsuffix );
769 } else {
770 stmt.setNull(paramInd, Types.VARCHAR);
771 }
772 paramInd++;
773
774 final String email = m_email == null ? null : m_email.toString();
775 if ( email != null && email .length() > 0 ) {
776 stmt.setString(paramInd, email );
777 } else {
778 stmt.setNull(paramInd, Types.VARCHAR);
779 }
780 paramInd++;
781
782 final String tel_evening = toDataString(m_eveningPhone);
783 stmt.setString(paramInd, tel_evening );
784 paramInd++;
785
786 final String tel_day =
787 m_dayPhone == null ? null : toDataString(m_dayPhone);
788 if ( tel_day != null ) {
789 stmt.setString(paramInd, tel_day );
790 } else {
791 stmt.setNull(paramInd, Types.VARCHAR);
792 }
793 paramInd++;
794
795 final String tel_other =
796 m_otherPhone == null ? null : toDataString(m_otherPhone);
797 if ( tel_other != null ) {
798 stmt.setString(paramInd, tel_other );
799 } else {
800 stmt.setNull(paramInd, Types.VARCHAR);
801 }
802 paramInd++;
803
804 final String addr_str1 = m_address.getStreet1();
805 stmt.setString(paramInd, addr_str1 );
806 paramInd++;
807
808 final String addr_str2 = m_address.getStreet2();
809 if ( addr_str2 != null && addr_str2 .length() > 0 ) {
810 stmt.setString(paramInd, addr_str2 );
811 } else {
812 stmt.setNull(paramInd, Types.VARCHAR);
813 }
814 paramInd++;
815
816 final String addr_city = m_address.getCity();
817 stmt.setString(paramInd, addr_city );
818 paramInd++;
819
820 final String addr_state = m_address.getState();
821 stmt.setString(paramInd, addr_state );
822 paramInd++;
823
824 final String addr_zip = m_address.getZip();
825 stmt.setString(paramInd, addr_zip );
826 paramInd++;
827
828 final int year = m_accountYear.getYear() + 1900;
829 stmt.setInt(paramInd, year);
830 paramInd++;
831
832 if ( m_birthDate != null ) {
833 String s = dateFormat.format( m_birthDate );
834 stmt.setString(paramInd, s );
835 } else {
836 stmt.setNull(paramInd, Types.VARCHAR);
837 }
838
839 rowCount = stmt.executeUpdate();
840
841 if ( theLog.isDebugEnabled() ) {
842 theLog.debug("insertRow count: " + rowCount);
843 theLog.debug("insertRow memberId: " + m_memberId);
844 theLog.debug("insertRow accountName: " + m_accountName);
845 theLog.debug("insertRow accountPassword: " + m_accountPassword);
846 theLog.debug("insertRow status: " + m_accountType.toString());
847 theLog.debug("insertRow lname: '" +m_memberName.getLastName()+ "'");
848 theLog.debug("insertRow fname: '" +m_memberName.getFirstName()+ "'");
849 theLog.debug("insertRow tel_evening: " + tel_evening);
850 theLog.debug("insertRow addr_str1: " + addr_str1);
851 theLog.debug("insertRow addr_city: " + addr_city);
852 theLog.debug("insertRow addr_state: " + addr_state);
853 theLog.debug("insertRow addr_zip: " + addr_zip);
854 theLog.debug("insertRow year: " + year);
855 }
856
857 deleteRoles(); // delete old roles
858 insertRoles(); // insert current roles
859
860 }
861 finally {
862 DBConfiguration.closeSQLStatement( stmt );
863 stmt = null;
864 DBConfiguration.closeSQLConnection( conn );
865 conn = null;
866 }
867
868 if ( rowCount != 1 ) {
869 String msg = "failed to insert member == " + m_memberId;
870 theLog.error( msg );
871 throw new CreateException( msg );
872 }
873
874 return;
875 } // insertRows
876
877 /** Load a single Member row, and possibly multiple MemberRole rows */
878 private void loadRows() throws MemberException, SQLException {
879
880 /*
881 * Implementation note: the translation from DB row to snapshot
882 * to bean looks inefficient, but it is not the bottleneck in
883 * loading bean. The bottleneck is the EJB algorithm for finding
884 * an id, then loading a row, then storing the result back to
885 * the DB. That means at least two DB calls (assuming the storage
886 * step is skipped by checking an isDirty flag). The DB calls
887 * completely dominate performance.
888 *
889 * On the other hand, returning a row as a snapshot allows the
890 * MemberDBRead code to be reused directly elsewhere. Where
891 * speed is critical, and where it is unlikely that a MemberBean
892 * is already in memory, it is best to use the MemberDBRead code to
893 * directly load a (read-only) snapshot from the database.
894 */
895
896 MemberSnapshot data = MemberDBRead.loadMember( m_memberId );
897 _setData( data );
898
899 return;
900 } // loadRows()
901
902 /** Stores a single Member row, and possibly multiple MemberRole rows */
903 private void storeRows() throws SQLException {
904
905 Connection conn = null;
906 PreparedStatement stmt = null;
907 int rowCount = 0;
908 try {
909
910 conn = DBConfiguration.getConnection();
911 stmt = conn.prepareStatement(Configuration.SQL_11);
912
913 stmt.setInt( 19, m_memberId.intValue() );
914 stmt.setString( 17, m_accountName );
915 stmt.setString( 1, m_accountPassword );
916 stmt.setString( 18, m_accountType.toString() );
917 stmt.setString( 2, m_memberName.getLastName() );
918 stmt.setString( 3, m_memberName.getFirstName() );
919
920 final String nmiddle = m_memberName.getMiddleName();
921 if (nmiddle != null && nmiddle.length() > 0 ) {
922 stmt.setString( 4, nmiddle);
923 } else {
924 stmt.setNull( 4, Types.VARCHAR);
925 }
926
927 final String nsuffix = m_memberName.getSuffix();
928 if ( nsuffix != null && nsuffix .length() > 0 ) {
929 stmt.setString( 5, nsuffix );
930 } else {
931 stmt.setNull( 5, Types.VARCHAR);
932 }
933
934 final String email = m_email == null ? null : m_email.toString();
935 if ( email != null && email .length() > 0 ) {
936 stmt.setString( 6, email );
937 } else {
938 stmt.setNull( 6, Types.VARCHAR);
939 }
940
941 stmt.setString( 7, toDataString(m_eveningPhone) );
942
943 if ( m_dayPhone != null ) {
944 stmt.setString( 8, toDataString(m_dayPhone) );
945 }
946 else {
947 stmt.setNull( 8, Types.VARCHAR );
948 }
949
950 if ( m_otherPhone != null ) {
951 stmt.setString( 9, toDataString(m_otherPhone) );
952 }
953 else {
954 stmt.setNull( 9, Types.VARCHAR );
955 }
956
957 stmt.setString(10, m_address.getStreet1() );
958
959 String addrstr2 = m_address.getStreet2();
960 if ( addrstr2 != null && addrstr2.trim().length() > 0) {
961 stmt.setString( 11, addrstr2 );
962 }
963 else {
964 stmt.setNull( 11, Types.VARCHAR );
965 }
966
967 stmt.setString( 12, m_address.getCity() );
968 stmt.setString( 13, m_address.getState() );
969 stmt.setString( 14, m_address.getZip() );
970 stmt.setInt( 15, 1900 + m_accountYear.getYear() );
971
972 if ( m_birthDate != null ) {
973 String s = dateFormat.format( m_birthDate );
974 stmt.setString( 16, s );
975 }
976 else {
977 stmt.setNull( 16, Types.VARCHAR );
978 }
979
980 rowCount = stmt.executeUpdate();
981
982 if ( theLog.isDebugEnabled() ) {
983 theLog.debug( "storeRows: rowCount == " + m_memberId );
984 theLog.debug( "storeRows: memberId: " + m_memberId);
985 theLog.debug( "storeRows: accountName: " + m_accountName);
986 theLog.debug( "storeRows: accountPassword: " + m_accountPassword);
987 theLog.debug( "storeRows: status: " + m_accountType.toString());
988 theLog.debug( "storeRows: lname: '" +m_memberName.getLastName()+ "'");
989 theLog.debug( "storeRows: fname: '" +m_memberName.getFirstName()+ "'");
990 theLog.debug( "storeRows: tel_evening: " + m_eveningPhone.toString());
991 theLog.debug( "storeRows: addr_str1: '" + m_address.getStreet1() + "'");
992 theLog.debug( "storeRows: addr_city: '" + m_address.getCity() + "'");
993 theLog.debug( "storeRows: addr_state: '" + m_address.getState() + "'");
994 theLog.debug( "storeRows: addr_zip: '" + m_address.getZip() + "'");
995 theLog.debug( "storeRows: year: " + (1900 + m_accountYear.getYear()) );
996 }
997
998 deleteRoles(); // delete old roles
999 insertRoles(); // insert current roles
1000
1001 }
1002 finally {
1003 DBConfiguration.closeSQLStatement( stmt );
1004 stmt = null;
1005 DBConfiguration.closeSQLConnection( conn );
1006 conn = null;
1007 }
1008
1009 if ( rowCount != 1 ) {
1010 String msg = "failed to store member == " + m_memberId;
1011 theLog.error( msg );
1012 throw new EJBException( msg );
1013 }
1014
1015 return;
1016 } // storeRows()
1017
1018 /** Inserts (possibly multiple) MemberRole rows */
1019 private void insertRoles() throws SQLException {
1020
1021 Connection conn = null;
1022 PreparedStatement stmt = null;
1023 ResultSet rs = null;
1024
1025 try {
1026 conn = DBConfiguration.getConnection();
1027 stmt = conn.prepareStatement(Configuration.SQL_16);
1028
1029 MemberRole[] roles = this.getMemberRoles();
1030 for ( int i=0; i<roles.length; i++ ) {
1031
1032 stmt.setInt( 1, m_memberId.intValue() );
1033 stmt.setString( 2, roles[i].getRole() );
1034 stmt.setString( 3, roles[i].getRoleGroup() );
1035
1036 int count = stmt.executeUpdate();
1037
1038 if ( theLog.isDebugEnabled() ) {
1039 theLog.debug("insertRole count: " + count);
1040 theLog.debug("insertRole member_id: " + m_memberId);
1041 theLog.debug("insertRole role: " + roles[i].getRole() );
1042 theLog.debug("insertRole roleGroup: " + roles[i].getRoleGroup() );
1043 }
1044
1045 } // for
1046
1047 }
1048 finally {
1049 DBConfiguration.closeSQLResultSet( rs );
1050 rs = null;
1051 DBConfiguration.closeSQLStatement( stmt );
1052 stmt = null;
1053 DBConfiguration.closeSQLConnection( conn );
1054 conn = null;
1055 }
1056
1057 return;
1058 } // insertRoles()
1059
1060 /** Deletes (possibly multiple) MemberRole rows */
1061 private void deleteRoles() throws SQLException {
1062
1063 Connection conn = null;
1064 PreparedStatement stmt = null;
1065 ResultSet rs = null;
1066
1067 try {
1068 conn = DBConfiguration.getConnection();
1069 stmt = conn.prepareStatement(Configuration.SQL_17);
1070
1071 stmt.setInt( 1, m_memberId.intValue() );
1072
1073 rs = stmt.executeQuery();
1074
1075 if ( theLog.isDebugEnabled() ) {
1076 theLog.debug("deleteRole member_id: " + m_memberId);
1077 }
1078
1079 }
1080 finally {
1081 DBConfiguration.closeSQLResultSet( rs );
1082 rs = null;
1083 DBConfiguration.closeSQLStatement( stmt );
1084 stmt = null;
1085 DBConfiguration.closeSQLConnection( conn );
1086 conn = null;
1087 }
1088
1089 return;
1090 } // deleteRoles()
1091
1092 /** A utility that gets (and reserves) the next id for a member */
1093 public static Integer nextId() throws SQLException, CreateException {
1094
1095 Connection conn = null;
1096 PreparedStatement stmt = null;
1097 ResultSet rs = null;
1098 Integer retVal = null;
1099 try {
1100 conn = DBConfiguration.getConnection();
1101 stmt = conn.prepareStatement(
1102 Configuration.SQL_15,
1103 ResultSet.TYPE_FORWARD_ONLY,
1104 ResultSet.CONCUR_READ_ONLY);
1105
1106 if ( theLog.isDebugEnabled() ) {
1107 String msg =
1108 "nextId update: SQL == " + Configuration.SQL_15;
1109 theLog.debug( msg );
1110 }
1111
1112 if ( !DBConfiguration.isOracle() ) {
1113
1114 /*
1115 * There is a problem in this block of code because it is not
1116 * locked in a transaction. If two different threads execute
1117 * this block simultaneously, the MySQL sequence value will
1118 * have been incremented twice, and both threads will use the
1119 * same value in the code section that follows this block.
1120 *
1121 * As a practical matter, during normal operation, rowing
1122 * sessions are created infrequently, and this block of code
1123 * is executed by one thread at a time. This code works because
1124 * this is a low-load application.
1125 */
1126
1127 boolean moreResults = stmt.execute();
1128
1129 stmt = conn.prepareStatement(
1130 Configuration.SQL_15A,
1131 ResultSet.TYPE_FORWARD_ONLY,
1132 ResultSet.CONCUR_READ_ONLY);
1133
1134 if ( theLog.isDebugEnabled() ) {
1135 String msg =
1136 "nextId select: SQL == " + Configuration.SQL_15A;
1137 theLog.debug( msg );
1138 }
1139
1140 } // if !isOracle
1141
1142 rs = stmt.executeQuery();
1143
1144 int rowCount = 0;
1145 while ( rs.next() ) {
1146 retVal = new Integer( rs.getInt(1) );
1147 ++rowCount;
1148 }
1149 if ( rowCount != 1 ) {
1150 String msg = "unable to get next id: rowCount == " + rowCount;
1151 throw new CreateException( msg );
1152 }
1153
1154 if ( theLog.isDebugEnabled() ) {
1155 String msg = "nextId: retVal == " + retVal.intValue();
1156 theLog.debug( msg );
1157 }
1158
1159 }
1160 finally {
1161 DBConfiguration.closeSQLResultSet( rs );
1162 DBConfiguration.closeSQLStatement( stmt );
1163 DBConfiguration.closeSQLConnection( conn );
1164 rs = null;
1165 stmt = null;
1166 conn = null;
1167 }
1168
1169 return retVal;
1170 } // nextId()
1171
1172 private static String toDataString( Telephone phone ) {
1173
1174 if ( phone == null ) {
1175 throw new IllegalArgumentException( "null phone" );
1176 }
1177
1178 StringBuffer sb = new StringBuffer();
1179 sb.append( phone.getAreaCode() );
1180 sb.append( " " );
1181 sb.append( phone.getExchange() );
1182 sb.append( "-" );
1183 sb.append( phone.getLocal() );
1184 String ext = phone.getExtension();
1185 if ( ext != null && ext.trim().length() > 0 ) {
1186 sb.append( " ext. " );
1187 sb.append( ext.trim() );
1188 }
1189 String retVal = new String(sb);
1190
1191 return retVal;
1192 } // toDataString(Telephone)
1193
1194} // MemberBean
1195
1196/*
1197 * $Log: MemberBean.java,v $
1198 * Revision 1.11 2003/02/26 03:38:45 rphall
1199 * Added copyright and GPL license
1200 *
1201 * Revision 1.10 2003/02/21 14:30:55 rphall
1202 * Fixed bug with blank extensions
1203 *
1204 * Revision 1.9 2003/02/21 05:02:33 rphall
1205 * Fixed bug where accountType, accountName weren't stored
1206 *
1207 * Revision 1.8 2003/02/20 04:58:03 rphall
1208 * Added insert/deleteRoles
1209 *
1210 */
1211