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 localUser = 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 localUser.setUserName(this.getUserName());
404 localUser.setUserProfileMode(this.getUserProfileMode());
406 // Create contact instance
407 Contact contact = this.contactController.createContactInstance();
410 //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("{0}.createUserInstance: contact={1}", this.getClass().getSimpleName(), contact));
412 // Set contact in user
413 localUser.setUserContact(contact);
416 //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("{0}.createUserInstance: user={1} - EXIT!", this.getClass().getSimpleName(), user));
423 public User createUserLogin () {
425 //* NOISY-DEBUG */ System.out.println(MessageFormat.format("{0}.createUserLogin: CALLED!", this.getClass().getSimpleName()));
428 if (this.getUserName() == null) {
430 throw new NullPointerException("recruiterName is null"); //NOI18N
431 } else if (this.getUserName().isEmpty()) {
433 throw new IllegalStateException("recruiterName is empty."); //NOI18N
436 // Create new recruiter instance
437 User recruiter = new LoginUser();
439 // Update all data ...
440 recruiter.setUserName(this.getUserName());
443 //* NOISY-DEBUG */ System.out.println(MessageFormat.format("{0}.createUserLogin: recruiter={1} - EXIT!", this.getClass().getSimpleName(), recruiter));
445 // Return the new instance
450 public String doChangePersonalData () {
451 // This method shall only be called if the user is logged-in
452 if (!this.loginController.isUserLoggedIn()) {
454 throw new IllegalStateException("User is not logged-in"); //NOI18N
455 } else if (!this.isRequiredChangePersonalDataSet()) {
456 // Not all required fields are set
457 throw new FaceletException("Not all required fields are set."); //NOI18N
458 } else if (!this.loginController.ifCurrentPasswordMatches()) {
459 // Password not matching
460 throw new FaceletException(new UserPasswordMismatchException(this.loginController.getLoggedInUser()));
464 User user = this.loginController.getLoggedInUser();
466 // Copy contact data to contact instance
467 this.contactController.updateContactDataFromController(user.getUserContact());
469 // It should be there, so run some tests on it
470 assert (user instanceof User) : "Instance loginController.loggedInUser is null";
471 assert (user.getUserId() instanceof Long) : "Instance loginController.loggedInUser.userId is null";
472 assert (user.getUserId() > 0) : MessageFormat.format("loginController.loggedInUser.userId={0} is invalid", user.getUserId());
473 assert (user.getUserContact() instanceof Contact) : "Instance loginController.loggedInUser.userContact is null";
474 assert (user.getUserContact().getContactId() instanceof Long) : "Instance loginController.userContact.contactId is null";
475 assert (user.getUserContact().getContactId() > 0) : MessageFormat.format("Instance loginController.userContact.contactId={0} is invalid", user.getUserContact().getContactId());
478 user.setUserProfileMode(this.getUserProfileMode());
480 // Send it to the EJB
481 User updatedUser = this.userBean.updateUserPersonalData(user);
484 this.updatedPersonalDataEvent.fire(new UserUpdatedPersonalDataEvent(updatedUser));
487 return "user_data_saved"; //NOI18N
491 public Long getUserId () {
496 public void setUserId (final Long userId) {
497 this.userId = userId;
501 public String getUserName () {
502 return this.userName;
506 public void setUserName (final String userName) {
507 this.userName = userName;
511 public String getUserPassword () {
512 return this.userPassword;
516 public void setUserPassword (final String userPassword) {
517 this.userPassword = userPassword;
521 public String getUserPasswordRepeat () {
522 return this.userPasswordRepeat;
526 public void setUserPasswordRepeat (final String userPasswordRepeat) {
527 this.userPasswordRepeat = userPasswordRepeat;
531 public ProfileMode getUserProfileMode () {
532 return this.userProfileMode;
536 public void setUserProfileMode (final ProfileMode userProfileMode) {
537 this.userProfileMode = userProfileMode;
541 public boolean hasUsers () {
542 return (!this.allUsers().isEmpty());
546 * Post-initialization of this class
549 public void init () {
550 // Initialize user list
551 this.userList = this.userBean.allUsers();
553 // Get full user name list for reducing EJB calls
554 this.userNameList = this.userBean.getUserNameList();
556 // Is the user logged-in?
557 if (this.userLoginController.isUserLoggedIn()) {
558 // Is logged-in, so load also users visible to memebers
559 this.visibleUserList = this.userBean.allMemberPublicVisibleUsers();
561 // Initialize user list
562 this.visibleUserList = this.userBean.allPublicUsers();
566 List<User> allUsers = this.allUsers();
569 List<Contact> allContacts = this.contactBean.getAllContacts();
572 Iterator<Contact> iterator = allContacts.iterator();
575 while (iterator.hasNext()) {
577 Contact next = iterator.next();
580 Iterator<User> userIterator = allUsers.iterator();
582 // Loop through all users
583 while (userIterator.hasNext()) {
585 User nextUser = userIterator.next();
588 if (Objects.equals(next, nextUser.getUserContact())) {
597 this.selectableContacts = allContacts;
601 public boolean isContactFound (final Contact contact) {
602 // The contact must be valid
603 if (null == contact) {
605 throw new NullPointerException("contact is null"); //NOI18N
606 } else if (contact.getContactId() == null) {
608 throw new NullPointerException("contact.contactId is null"); //NOI18N
609 } else if (contact.getContactId() < 1) {
611 throw new IllegalArgumentException(MessageFormat.format("contact.contactId={0} is not valid", contact.getContactId())); //NOI18N
614 // Default is not found
615 boolean isFound = false;
618 Iterator<User> iterator = this.allUsers().iterator();
620 // Loop through all entries
621 while (iterator.hasNext()) {
623 User next = iterator.next();
625 // Compare both objects
626 if (Objects.equals(contact, next.getUserContact())) {
638 public boolean isPublicUserProfileEnabled () {
639 // Get context parameter
640 String contextParameter = FacesContext.getCurrentInstance().getExternalContext().getInitParameter("is_public_profile_enabled"); //NOI18N
643 boolean isPublicUserProfileEnabled = ((contextParameter instanceof String) && (contextParameter.toLowerCase().equals("true"))); //NOI18N
645 // This requires user names being enabled, too.
646 if ((isPublicUserProfileEnabled) && (!this.isUserNameRequired())) {
647 // Not valid state, users must be able to modify their profile, especially when it is public
648 throw new IllegalStateException("Public user profiles are enabled but user name requirement is disabled, this is not possible."); //NOI18N
652 return isPublicUserProfileEnabled;
656 public boolean isRequiredChangePersonalDataSet () {
657 return ((this.getUserProfileMode() != null) &&
658 (this.getUserName() != null) && (!this.getUserName().isEmpty()) &&
659 (this.contactController.isRequiredChangePersonalDataSet()));
663 public boolean isRequiredPersonalDataSet () {
664 if (this.registerController.isMultiplePageEnabled()) {
665 // Multiple registration page
666 return this.contactController.isRequiredPersonalDataSet();
668 // Single registration page
669 return (((this.getUserName() != null) || (!this.isUserNameRequired())) &&
670 (this.getUserProfileMode() != null) &&
671 (this.contactController.isRequiredPersonalDataSet()) &&
672 (this.getUserPassword() != null) &&
673 (this.getUserPasswordRepeat() != null));
678 public boolean isSamePasswordEntered () {
679 return ((!this.getUserPassword().isEmpty()) && (Objects.equals(this.getUserPassword(), this.getUserPasswordRepeat())));
683 public boolean isUserIdEmpty () {
684 return ((this.getUserId() == null) || (this.getUserId() == 0));
688 public boolean isUserNameRegistered (final User user) {
689 return ((this.userNameList instanceof List) && (this.userNameList.contains(user.getUserName())));
693 public boolean isUserNameRequired () {
694 // Get context parameter
695 String contextParameter = FacesContext.getCurrentInstance().getExternalContext().getInitParameter("is_user_name_required"); //NOI18N
698 boolean isUserNameRequired = ((contextParameter instanceof String) && (contextParameter.toLowerCase().equals("true"))); //NOI18N
701 return isUserNameRequired;
705 public boolean isVisibleUserFound () {
706 return ((this.visibleUserList instanceof List) && (this.visibleUserList.size() > 0));
710 public User lookupUserById (final Long userId) throws UserNotFoundException {
711 // Parameter must be valid
712 if (null == userId) {
714 throw new NullPointerException("userId is null"); //NOI18N
715 } else if (userId < 1) {
717 throw new IllegalArgumentException(MessageFormat.format("userId={0} is not valid.", userId)); //NOI18N
723 // Try to lookup it in visible user list
724 for (final Iterator<User> iterator = this.userList.iterator(); iterator.hasNext();) {
726 User next = iterator.next();
728 // Is the user id found?
729 if (Objects.equals(next.getUserId(), userId)) {
730 // Copy to other variable
738 // Not visible for the current user
739 throw new UserNotFoundException(userId);
747 public List<Contact> selectableContacts () {
748 return Collections.unmodifiableList(this.selectableContacts);
752 * Adds user's name to bean's internal list. It also updates the public user
753 * list if the user has decided to have a public account,
755 * @param user User instance
757 private void addUserName (final User user) {
758 // Make sure the entry is not added yet
759 if (this.userNameList.contains(user.getUserName())) {
761 throw new IllegalArgumentException(MessageFormat.format("User name {0} already added.", user.getUserName())); //NOI18N
762 } else if (this.contactController.isEmailAddressRegistered(user.getUserContact())) {
764 throw new IllegalArgumentException(MessageFormat.format("Email address {0} already added.", user.getUserContact().getContactEmailAddress())); //NOI18N
768 this.userNameList.add(user.getUserName());
774 private void clear () {
777 this.setUserId(null);
778 this.setUserProfileMode(null);
781 this.setUserName(null);
782 this.setUserPassword(null);
783 this.setUserPasswordRepeat(null);
787 * Copies given user into the controller
789 * @param user User instance
791 private void copyUser (final User user) {
792 // Make sure the instance is valid
795 throw new NullPointerException("user is null"); //NOI18N
796 } else if (user.getUserContact() == null) {
798 throw new NullPointerException("user.userContact is null"); //NOI18N
803 this.setUserId(user.getUserId());
804 this.setUserProfileMode(user.getUserProfileMode());
808 * Updates list with given user instance
810 * @param user User instance
812 private void updateList (final User user) {
813 // The user should be valid
816 throw new NullPointerException("user is null"); //NOI18N
817 } else if (user.getUserId() == null) {
819 throw new NullPointerException("user.userId is null"); //NOI18N
820 } else if (user.getUserId() < 1) {
822 throw new IllegalArgumentException(MessageFormat.format("user.userId={0} is invalid", user.getUserId())); //NOI18N
826 Iterator<User> iterator = this.userList.iterator();
829 while (iterator.hasNext()) {
831 User next = iterator.next();
833 // Is the same user id?
834 if (Objects.equals(user.getUserId(), next.getUserId())) {
835 // Found it, so remove it
836 this.userList.remove(next);
842 this.userList.add(user);