2 * Copyright (C) 2016 Roland Haeder
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License as
6 * published by the Free Software Foundation, either version 3 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Affero General Public License for more details.
14 * You should have received a copy of the GNU Affero General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 package org.mxchange.addressbook.beans.user;
19 import java.text.MessageFormat;
20 import java.util.Collections;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Objects;
24 import javax.annotation.PostConstruct;
25 import javax.enterprise.context.SessionScoped;
26 import javax.enterprise.event.Event;
27 import javax.enterprise.event.Observes;
28 import javax.enterprise.inject.Any;
29 import javax.faces.context.FacesContext;
30 import javax.faces.view.facelets.FaceletException;
31 import javax.inject.Inject;
32 import javax.inject.Named;
33 import javax.naming.Context;
34 import javax.naming.InitialContext;
35 import javax.naming.NamingException;
36 import org.mxchange.addressbook.beans.BaseAddressbookController;
37 import org.mxchange.addressbook.beans.contact.AddressbookContactWebSessionController;
38 import org.mxchange.addressbook.beans.login.AddressbookUserLoginWebSessionController;
39 import org.mxchange.addressbook.beans.register.AddressbookUserRegisterWebSessionController;
40 import org.mxchange.jcontacts.contact.Contact;
41 import org.mxchange.jcontacts.contact.ContactSessionBeanRemote;
42 import org.mxchange.jcontacts.events.contact.add.AdminAddedContactEvent;
43 import org.mxchange.jusercore.events.login.UserLoggedInEvent;
44 import org.mxchange.jusercore.events.registration.UserRegisteredEvent;
45 import org.mxchange.jusercore.events.user.add.AdminAddedUserEvent;
46 import org.mxchange.jusercore.events.user.update.AdminUpdatedUserDataEvent;
47 import org.mxchange.jusercore.events.user.update.UpdatedUserPersonalDataEvent;
48 import org.mxchange.jusercore.events.user.update.UserUpdatedPersonalDataEvent;
49 import org.mxchange.jusercore.exceptions.UserNotFoundException;
50 import org.mxchange.jusercore.exceptions.UserPasswordMismatchException;
51 import org.mxchange.jusercore.model.user.LoginUser;
52 import org.mxchange.jusercore.model.user.User;
53 import org.mxchange.jusercore.model.user.UserSessionBeanRemote;
54 import org.mxchange.jusercore.model.user.UserUtils;
55 import org.mxchange.jusercore.model.user.profilemodes.ProfileMode;
58 * A user bean (controller)
60 * @author Roland Haeder<roland@mxchange.org>
62 @Named ("userController")
64 public class AddressbookUserWebSessionBean extends BaseAddressbookController implements AddressbookUserWebSessionController {
69 private static final long serialVersionUID = 542_145_347_916L;
74 private ContactSessionBeanRemote contactBean;
77 * General contact controller
80 private AddressbookContactWebSessionController contactController;
83 * Login bean (controller)
86 private AddressbookUserLoginWebSessionController loginController;
89 * Registration controller
92 private AddressbookUserRegisterWebSessionController registerController;
95 * A list of all selectable contacts
97 private List<Contact> selectableContacts;
100 * Event being fired when user updated personal data
104 private Event<UpdatedUserPersonalDataEvent> updatedPersonalDataEvent;
109 private final UserSessionBeanRemote userBean;
117 * A list of all user profiles
119 private List<User> userList;
122 * Login bean (controller)
125 private AddressbookUserLoginWebSessionController userLoginController;
130 private String userName;
135 private List<String> userNameList;
138 * User password (unencrypted from web form)
140 private String userPassword;
143 * User password repeated (unencrypted from web form)
145 private String userPasswordRepeat;
148 * Whether the user wants a public profile
150 private ProfileMode userProfileMode;
153 * A list of all public user profiles
155 private List<User> visibleUserList;
158 * Default constructor
160 public AddressbookUserWebSessionBean () {
163 // Get initial context
164 Context context = new InitialContext();
167 this.userBean = (UserSessionBeanRemote) context.lookup("java:global/addressbook-ejb/user!org.mxchange.jusercore.model.user.UserSessionBeanRemote"); //NOI18N
170 this.contactBean = (ContactSessionBeanRemote) context.lookup("java:global/addressbook-ejb/contact!org.mxchange.jcontacts.contact.ContactSessionBeanRemote"); //NOI18N
171 } catch (final NamingException e) {
173 throw new FaceletException(e);
178 public void afterAdminAddedContact (@Observes final AdminAddedContactEvent event) {
179 // The event must be valid
182 throw new NullPointerException("event is null"); //NOI18N
183 } else if (event.getAddedContact() == null) {
185 throw new NullPointerException("event.addedContact is null"); //NOI18N
186 } else if (event.getAddedContact().getContactId() == null) {
188 throw new NullPointerException("event.addedContact.customerId is null"); //NOI18N
189 } else if (event.getAddedContact().getContactId() < 1) {
191 throw new IllegalArgumentException(MessageFormat.format("event.addedContact.customerId={0} is not valid", event.getAddedContact().getContactId())); //NOI18N //NOI18N
195 this.selectableContacts.add(event.getAddedContact());
199 public void afterAdminAddedUserEvent (@Observes final AdminAddedUserEvent event) {
201 //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("UserWebBean:afterAdminAddedUserEvent: event={0} - CALLED!", event)); //NOI18N
203 // event should not be null
206 throw new NullPointerException("event is null"); //NOI18N
207 } else if (event.getAddedUser() == null) {
209 throw new NullPointerException("event.addedUser is null"); //NOI18N
210 } else if (event.getAddedUser().getUserId() == null) {
212 throw new NullPointerException("event.addedUser.userId is null"); //NOI18N
213 } else if (event.getAddedUser().getUserId() < 1) {
215 throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getAddedUser(), event.getAddedUser().getUserId())); //NOI18N
218 // Add user to local list
219 this.userList.add(event.getAddedUser());
225 this.setUserId(event.getAddedUser().getUserId());
228 //* NOISY-DEBUG: */ System.out.println("UserWebBean:afterAdminAddedUserEvent: EXIT!"); //NOI18N
232 public void afterAdminUpdatedUserDataEvent (@Observes final AdminUpdatedUserDataEvent event) {
234 //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("UserWebBean:afterAdminUpdatedUserEvent: event={0} - CALLED!", event)); //NOI18N
236 // event should not be null
239 throw new NullPointerException("event is null"); //NOI18N
240 } else if (event.getUpdatedUser() == null) {
242 throw new NullPointerException("event.updatedUser is null"); //NOI18N
243 } else if (event.getUpdatedUser().getUserId() == null) {
245 throw new NullPointerException("event.updatedUser.userId is null"); //NOI18N
246 } else if (event.getUpdatedUser().getUserId() < 1) {
248 throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getUpdatedUser(), event.getUpdatedUser().getUserId())); //NOI18N
252 this.updateList(event.getUpdatedUser());
258 //* NOISY-DEBUG: */ System.out.println("UserWebBean:afterAdminUpdatedUserEvent: EXIT!"); //NOI18N
262 public void afterRegistrationEvent (@Observes final UserRegisteredEvent event) {
264 //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("UserWebBean:afterRegistration: event={0} - CALLED!", event)); //NOI18N
266 // event should not be null
269 throw new NullPointerException("event is null"); //NOI18N
270 } else if (event.getRegisteredUser() == null) {
272 throw new NullPointerException("event.registeredUser is null"); //NOI18N
273 } else if (event.getRegisteredUser().getUserId() == null) {
275 throw new NullPointerException("event.registeredUser.userId is null"); //NOI18N
276 } else if (event.getRegisteredUser().getUserId() < 1) {
278 throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getRegisteredUser(), event.getRegisteredUser().getUserId())); //NOI18N
282 User registeredUser = event.getRegisteredUser();
285 //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("UserWebBean:afterRegistration: registeredUser={0}", registeredUser)); //NOI18N
287 // Copy all data from registered->user
288 this.copyUser(registeredUser);
293 // Add user to local list
294 this.userList.add(registeredUser);
297 this.addUserName(registeredUser);
299 // Is the account public?
300 if (Objects.equals(registeredUser.getUserProfileMode(), ProfileMode.PUBLIC)) {
301 // Also add it to this list
302 this.visibleUserList.add(registeredUser);
306 this.setUserId(registeredUser.getUserId());
309 //* NOISY-DEBUG: */ System.out.println("UserWebBean:afterRegistration: EXIT!"); //NOI18N
313 public void afterUserLogin (final @Observes UserLoggedInEvent event) {
315 //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("UserWebBean:afterUserLogin: event={0} - CALLED!", event)); //NOI18N
317 // event should not be null
320 throw new NullPointerException("event is null"); //NOI18N
321 } else if (event.getLoggedInUser() == null) {
323 throw new NullPointerException("event.registeredUser is null"); //NOI18N
324 } else if (event.getLoggedInUser().getUserId() == null) {
326 throw new NullPointerException("event.registeredUser.userId is null"); //NOI18N
327 } else if (event.getLoggedInUser().getUserId() < 1) {
329 throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getLoggedInUser(), event.getLoggedInUser().getUserId())); //NOI18N
332 // Copy all data to this bean
333 this.copyUser(event.getLoggedInUser());
335 // Re-initialize list
336 this.visibleUserList = this.userBean.allMemberPublicVisibleUsers();
342 public void afterUserUpdatedPersonalData (@Observes final UpdatedUserPersonalDataEvent event) {
346 throw new NullPointerException("event is null"); //NOI18N
347 } else if (event.getUpdatedUser() == null) {
349 throw new NullPointerException("event.updatedUser is null"); //NOI18N
350 } else if (event.getUpdatedUser().getUserId() == null) {
352 throw new NullPointerException("event.updatedUser.userId is null"); //NOI18N
353 } else if (event.getUpdatedUser().getUserId() < 1) {
355 throw new IllegalArgumentException(MessageFormat.format("event.updatedUser.userId={0} is in valid", event.getUpdatedUser().getUserId())); //NOI18N
358 // All fine, so update list
359 this.updateList(event.getUpdatedUser());
363 public List<User> allUsers () {
365 return Collections.unmodifiableList(this.userList);
369 public List<User> allVisibleUsers () {
371 return Collections.unmodifiableList(this.visibleUserList);
375 public User createUserInstance () {
377 //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("{0}.createUserInstance: CALLED!", this.getClass().getSimpleName()));
379 // Required personal data must be set
380 assert (this.isRequiredPersonalDataSet()) : "not all personal data is set"; //NOI18N
382 // Create new user instance
383 User user = new LoginUser();
385 // Is user name required?
386 if (!this.isUserNameRequired()) {
387 // Generate pseudo-random user name
388 String randomName = this.userBean.generateRandomUserName();
390 // Set it and inivisible profile
391 this.setUserName(randomName);
392 this.setUserProfileMode(ProfileMode.INVISIBLE);
394 // Generate random password
395 String randomPassword = UserUtils.createRandomPassword(AddressbookUserWebSessionController.MINIMUM_PASSWORD_LENGTH);
397 // Set random password
398 this.setUserPassword(randomPassword);
399 this.setUserPasswordRepeat(randomPassword);
402 // Set user name and mode
403 user.setUserName(this.getUserName());
404 user.setUserProfileMode(this.getUserProfileMode());
406 // Is multiple registration page
407 if (!this.registerController.isMultiplePageEnabled()) {
408 // Create contact instance
409 Contact contact = this.contactController.createContactInstance();
412 //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("{0}.createUserInstance: contact={1}", this.getClass().getSimpleName(), contact));
414 // Set contact in user
415 user.setUserContact(contact);
419 //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("{0}.createUserInstance: user={1} - EXIT!", this.getClass().getSimpleName(), user));
426 public User createUserLogin () {
428 //* NOISY-DEBUG */ System.out.println(MessageFormat.format("{0}.createUserLogin: CALLED!", this.getClass().getSimpleName()));
431 if (this.getUserName() == null) {
433 throw new NullPointerException("recruiterName is null"); //NOI18N
434 } else if (this.getUserName().isEmpty()) {
436 throw new IllegalStateException("recruiterName is empty."); //NOI18N
439 // Create new recruiter instance
440 User recruiter = new LoginUser();
442 // Update all data ...
443 recruiter.setUserName(this.getUserName());
446 //* NOISY-DEBUG */ System.out.println(MessageFormat.format("{0}.createUserLogin: recruiter={1} - EXIT!", this.getClass().getSimpleName(), recruiter));
448 // Return the new instance
453 public String doChangePersonalData () {
454 // This method shall only be called if the user is logged-in
455 if (!this.loginController.isUserLoggedIn()) {
457 throw new IllegalStateException("User is not logged-in"); //NOI18N
458 } else if (!this.isRequiredChangePersonalDataSet()) {
459 // Not all required fields are set
460 throw new FaceletException("Not all required fields are set."); //NOI18N
461 } else if (!this.loginController.ifCurrentPasswordMatches()) {
462 // Password not matching
463 throw new FaceletException(new UserPasswordMismatchException(this.loginController.getLoggedInUser()));
467 User user = this.loginController.getLoggedInUser();
469 // Copy contact data to contact instance
470 this.contactController.updateContactDataFromController(user.getUserContact());
472 // It should be there, so run some tests on it
473 assert (user instanceof User) : "Instance loginController.loggedInUser is null";
474 assert (user.getUserId() instanceof Long) : "Instance loginController.loggedInUser.userId is null";
475 assert (user.getUserId() > 0) : MessageFormat.format("loginController.loggedInUser.userId={0} is invalid", user.getUserId());
476 assert (user.getUserContact() instanceof Contact) : "Instance loginController.loggedInUser.userContact is null";
477 assert (user.getUserContact().getContactId() instanceof Long) : "Instance loginController.userContact.contactId is null";
478 assert (user.getUserContact().getContactId() > 0) : MessageFormat.format("Instance loginController.userContact.contactId={0} is invalid", user.getUserContact().getContactId());
481 user.setUserProfileMode(this.getUserProfileMode());
483 // Send it to the EJB
484 User updatedUser = this.userBean.updateUserPersonalData(user);
487 this.updatedPersonalDataEvent.fire(new UserUpdatedPersonalDataEvent(updatedUser));
490 return "user_data_saved"; //NOI18N
494 public Long getUserId () {
499 public void setUserId (final Long userId) {
500 this.userId = userId;
504 public String getUserName () {
505 return this.userName;
509 public void setUserName (final String userName) {
510 this.userName = userName;
514 public String getUserPassword () {
515 return this.userPassword;
519 public void setUserPassword (final String userPassword) {
520 this.userPassword = userPassword;
524 public String getUserPasswordRepeat () {
525 return this.userPasswordRepeat;
529 public void setUserPasswordRepeat (final String userPasswordRepeat) {
530 this.userPasswordRepeat = userPasswordRepeat;
534 public ProfileMode getUserProfileMode () {
535 return this.userProfileMode;
539 public void setUserProfileMode (final ProfileMode userProfileMode) {
540 this.userProfileMode = userProfileMode;
544 public boolean hasUsers () {
545 return (!this.allUsers().isEmpty());
549 * Post-initialization of this class
552 public void init () {
553 // Initialize user list
554 this.userList = this.userBean.allUsers();
556 // Get full user name list for reducing EJB calls
557 this.userNameList = this.userBean.getUserNameList();
559 // Is the user logged-in?
560 if (this.userLoginController.isUserLoggedIn()) {
561 // Is logged-in, so load also users visible to memebers
562 this.visibleUserList = this.userBean.allMemberPublicVisibleUsers();
564 // Initialize user list
565 this.visibleUserList = this.userBean.allPublicUsers();
569 List<User> allUsers = this.allUsers();
572 List<Contact> allContacts = this.contactBean.getAllContacts();
575 Iterator<Contact> iterator = allContacts.iterator();
578 while (iterator.hasNext()) {
580 Contact next = iterator.next();
583 Iterator<User> userIterator = allUsers.iterator();
585 // Loop through all users
586 while (userIterator.hasNext()) {
588 User nextUser = userIterator.next();
591 if (Objects.equals(next, nextUser.getUserContact())) {
600 this.selectableContacts = allContacts;
604 public boolean isContactFound (final Contact contact) {
605 // The contact must be valid
606 if (null == contact) {
608 throw new NullPointerException("contact is null"); //NOI18N
609 } else if (contact.getContactId() == null) {
611 throw new NullPointerException("contact.contactId is null"); //NOI18N
612 } else if (contact.getContactId() < 1) {
614 throw new IllegalArgumentException(MessageFormat.format("contact.contactId={0} is not valid", contact.getContactId())); //NOI18N
617 // Default is not found
618 boolean isFound = false;
621 Iterator<User> iterator = this.allUsers().iterator();
623 // Loop through all entries
624 while (iterator.hasNext()) {
626 User next = iterator.next();
628 // Compare both objects
629 if (Objects.equals(contact, next.getUserContact())) {
641 public boolean isPublicUserProfileEnabled () {
642 // Get context parameter
643 String contextParameter = FacesContext.getCurrentInstance().getExternalContext().getInitParameter("is_public_profile_enabled"); //NOI18N
646 boolean isEnabled = ((contextParameter instanceof String) && (contextParameter.toLowerCase().equals("true"))); //NOI18N
648 // This requires user names being enabled, too.
649 if ((isEnabled) && (!this.isUserNameRequired())) {
650 // Not valid state, users must be able to modify their profile, especially when it is public
651 throw new IllegalStateException("Public user profiles are enabled but user name requirement is disabled, this is not possible."); //NOI18N
659 public boolean isRequiredChangePersonalDataSet () {
660 return ((this.getUserProfileMode() != null) &&
661 (this.getUserName() != null) && (!this.getUserName().isEmpty()) &&
662 (this.contactController.isRequiredChangePersonalDataSet()));
666 public boolean isRequiredPersonalDataSet () {
667 if (this.registerController.isMultiplePageEnabled()) {
668 // Multiple registration page
669 return this.contactController.isRequiredPersonalDataSet();
671 // Single registration page
672 return (((this.getUserName() != null) || (!this.isUserNameRequired())) &&
673 (this.getUserProfileMode() != null) &&
674 (this.contactController.isRequiredPersonalDataSet()) &&
675 (this.getUserPassword() != null) &&
676 (this.getUserPasswordRepeat() != null));
681 public boolean isSamePasswordEntered () {
682 return ((!this.getUserPassword().isEmpty()) && (Objects.equals(this.getUserPassword(), this.getUserPasswordRepeat())));
686 public boolean isUserIdEmpty () {
687 return ((this.getUserId() == null) || (this.getUserId() == 0));
691 public boolean isUserNameRegistered (final User user) {
692 return ((this.userNameList instanceof List) && (this.userNameList.contains(user.getUserName())));
696 public boolean isUserNameRequired () {
697 // Get context parameter
698 String contextParameter = FacesContext.getCurrentInstance().getExternalContext().getInitParameter("is_user_name_required"); //NOI18N
701 boolean isRequired = ((contextParameter instanceof String) && (contextParameter.toLowerCase().equals("true"))); //NOI18N
708 public boolean isVisibleUserFound () {
709 return ((this.visibleUserList instanceof List) && (this.visibleUserList.size() > 0));
713 public User lookupUserById (final Long userId) throws UserNotFoundException {
714 // Parameter must be valid
715 if (null == userId) {
717 throw new NullPointerException("userId is null"); //NOI18N
718 } else if (userId < 1) {
720 throw new IllegalArgumentException(MessageFormat.format("userId={0} is not valid.", userId)); //NOI18N
726 // Try to lookup it in visible user list
727 for (final Iterator<User> iterator = this.userList.iterator(); iterator.hasNext();) {
729 User next = iterator.next();
731 // Is the user id found?
732 if (Objects.equals(next.getUserId(), userId)) {
733 // Copy to other variable
741 // Not visible for the current user
742 throw new UserNotFoundException(userId);
750 public List<Contact> selectableContacts () {
751 return Collections.unmodifiableList(this.selectableContacts);
755 * Adds user's name to bean's internal list. It also updates the public user
756 * list if the user has decided to have a public account,
758 * @param user User instance
760 private void addUserName (final User user) {
761 // Make sure the entry is not added yet
762 if (this.userNameList.contains(user.getUserName())) {
764 throw new IllegalArgumentException(MessageFormat.format("User name {0} already added.", user.getUserName())); //NOI18N
765 } else if (this.contactController.isEmailAddressRegistered(user.getUserContact())) {
767 throw new IllegalArgumentException(MessageFormat.format("Email address {0} already added.", user.getUserContact().getContactEmailAddress())); //NOI18N
771 this.userNameList.add(user.getUserName());
777 private void clear () {
780 this.setUserId(null);
781 this.setUserProfileMode(null);
784 this.setUserName(null);
785 this.setUserPassword(null);
786 this.setUserPasswordRepeat(null);
790 * Copies given user into the controller
792 * @param user User instance
794 private void copyUser (final User user) {
795 // Make sure the instance is valid
798 throw new NullPointerException("user is null"); //NOI18N
799 } else if (user.getUserContact() == null) {
801 throw new NullPointerException("user.userContact is null"); //NOI18N
806 this.setUserId(user.getUserId());
807 this.setUserProfileMode(user.getUserProfileMode());
811 * Updates list with given user instance
813 * @param user User instance
815 private void updateList (final User user) {
816 // The user should be valid
819 throw new NullPointerException("user is null"); //NOI18N
820 } else if (user.getUserId() == null) {
822 throw new NullPointerException("user.userId is null"); //NOI18N
823 } else if (user.getUserId() < 1) {
825 throw new IllegalArgumentException(MessageFormat.format("user.userId={0} is invalid", user.getUserId())); //NOI18N
829 Iterator<User> iterator = this.userList.iterator();
832 while (iterator.hasNext()) {
834 User next = iterator.next();
836 // Is the same user id?
837 if (Objects.equals(user.getUserId(), next.getUserId())) {
838 // Found it, so remove it
839 this.userList.remove(next);
845 this.userList.add(user);