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.jjobs.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.jcontacts.contact.Contact;
37 import org.mxchange.jcontacts.contact.ContactSessionBeanRemote;
38 import org.mxchange.jcontacts.events.contact.add.AdminAddedContactEvent;
39 import org.mxchange.jjobs.beans.BaseJobsController;
40 import org.mxchange.jjobs.beans.contact.JobsContactWebSessionController;
41 import org.mxchange.jjobs.beans.login.JobsUserLoginWebSessionController;
42 import org.mxchange.jjobs.beans.register.JobsUserRegisterWebSessionController;
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.UserEmailAddressNotFoundException;
50 import org.mxchange.jusercore.exceptions.UserNotFoundException;
51 import org.mxchange.jusercore.exceptions.UserPasswordMismatchException;
52 import org.mxchange.jusercore.model.user.LoginUser;
53 import org.mxchange.jusercore.model.user.User;
54 import org.mxchange.jusercore.model.user.UserSessionBeanRemote;
55 import org.mxchange.jusercore.model.user.UserUtils;
56 import org.mxchange.jusercore.model.user.profilemodes.ProfileMode;
59 * A user bean (controller)
61 * @author Roland Haeder<roland@mxchange.org>
63 @Named ("userController")
65 public class JobsUserWebSessionBean extends BaseJobsController implements JobsUserWebSessionController {
70 private static final long serialVersionUID = 542_145_347_916L;
75 private ContactSessionBeanRemote contactBean;
78 * General contact controller
81 private JobsContactWebSessionController contactController;
84 * Registration controller
87 private JobsUserRegisterWebSessionController registerController;
90 * A list of all selectable contacts
92 private List<Contact> selectableContacts;
95 * Event being fired when user updated personal data
99 private Event<UpdatedUserPersonalDataEvent> updatedPersonalDataEvent;
104 private final UserSessionBeanRemote userBean;
112 * A list of all user profiles
114 private List<User> userList;
117 * Login bean (controller)
120 private JobsUserLoginWebSessionController userLoginController;
125 private String userName;
130 private List<String> userNameList;
133 * User password (unencrypted from web form)
135 private String userPassword;
138 * User password repeated (unencrypted from web form)
140 private String userPasswordRepeat;
143 * Whether the user wants a public profile
145 private ProfileMode userProfileMode;
148 * A list of all public user profiles
150 private List<User> visibleUserList;
153 * Default constructor
155 public JobsUserWebSessionBean () {
158 // Get initial context
159 Context context = new InitialContext();
162 this.userBean = (UserSessionBeanRemote) context.lookup("java:global/jjobs-ejb/user!org.mxchange.jusercore.model.user.UserSessionBeanRemote"); //NOI18N
165 this.contactBean = (ContactSessionBeanRemote) context.lookup("java:global/jjobs-ejb/contact!org.mxchange.jcontacts.contact.ContactSessionBeanRemote"); //NOI18N
166 } catch (final NamingException e) {
168 throw new FaceletException(e);
173 public void afterAdminAddedContact (@Observes final AdminAddedContactEvent event) {
174 // The event must be valid
177 throw new NullPointerException("event is null"); //NOI18N
178 } else if (event.getAddedContact() == null) {
180 throw new NullPointerException("event.addedContact is null"); //NOI18N
181 } else if (event.getAddedContact().getContactId() == null) {
183 throw new NullPointerException("event.addedContact.customerId is null"); //NOI18N
184 } else if (event.getAddedContact().getContactId() < 1) {
186 throw new IllegalArgumentException(MessageFormat.format("event.addedContact.customerId={0} is not valid", event.getAddedContact().getContactId())); //NOI18N //NOI18N
190 this.selectableContacts.add(event.getAddedContact());
194 public void afterAdminAddedUserEvent (@Observes final AdminAddedUserEvent event) {
196 //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("UserWebBean:afterAdminAddedUserEvent: event={0} - CALLED!", event)); //NOI18N
198 // event should not be null
201 throw new NullPointerException("event is null"); //NOI18N
202 } else if (event.getAddedUser() == null) {
204 throw new NullPointerException("event.addedUser is null"); //NOI18N
205 } else if (event.getAddedUser().getUserId() == null) {
207 throw new NullPointerException("event.addedUser.userId is null"); //NOI18N
208 } else if (event.getAddedUser().getUserId() < 1) {
210 throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getAddedUser(), event.getAddedUser().getUserId())); //NOI18N
213 // Add user to local list
214 this.userList.add(event.getAddedUser());
220 this.setUserId(event.getAddedUser().getUserId());
223 //* NOISY-DEBUG: */ System.out.println("UserWebBean:afterAdminAddedUserEvent: EXIT!"); //NOI18N
227 public void afterAdminUpdatedUserDataEvent (@Observes final AdminUpdatedUserDataEvent event) {
229 //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("UserWebBean:afterAdminUpdatedUserEvent: event={0} - CALLED!", event)); //NOI18N
231 // event should not be null
234 throw new NullPointerException("event is null"); //NOI18N
235 } else if (event.getUpdatedUser() == null) {
237 throw new NullPointerException("event.updatedUser is null"); //NOI18N
238 } else if (event.getUpdatedUser().getUserId() == null) {
240 throw new NullPointerException("event.updatedUser.userId is null"); //NOI18N
241 } else if (event.getUpdatedUser().getUserId() < 1) {
243 throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getUpdatedUser(), event.getUpdatedUser().getUserId())); //NOI18N
247 this.updateList(event.getUpdatedUser());
253 //* NOISY-DEBUG: */ System.out.println("UserWebBean:afterAdminUpdatedUserEvent: EXIT!"); //NOI18N
257 public void afterRegistrationEvent (@Observes final UserRegisteredEvent event) {
259 //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("UserWebBean:afterRegistration: event={0} - CALLED!", event)); //NOI18N
261 // event should not be null
264 throw new NullPointerException("event is null"); //NOI18N
265 } else if (event.getRegisteredUser() == null) {
267 throw new NullPointerException("event.registeredUser is null"); //NOI18N
268 } else if (event.getRegisteredUser().getUserId() == null) {
270 throw new NullPointerException("event.registeredUser.userId is null"); //NOI18N
271 } else if (event.getRegisteredUser().getUserId() < 1) {
273 throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getRegisteredUser(), event.getRegisteredUser().getUserId())); //NOI18N
277 User registeredUser = event.getRegisteredUser();
280 //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("UserWebBean:afterRegistration: registeredUser={0}", registeredUser)); //NOI18N
282 // Copy all data from registered->user
283 this.copyUser(registeredUser);
288 // Add user to local list
289 this.userList.add(registeredUser);
292 this.addUserName(registeredUser);
294 // Is the account public?
295 if (Objects.equals(registeredUser.getUserProfileMode(), ProfileMode.PUBLIC)) {
296 // Also add it to this list
297 this.visibleUserList.add(registeredUser);
301 this.setUserId(registeredUser.getUserId());
304 //* NOISY-DEBUG: */ System.out.println("UserWebBean:afterRegistration: EXIT!"); //NOI18N
308 public void afterUserLogin (@Observes final UserLoggedInEvent event) {
310 //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("UserWebBean:afterUserLogin: event={0} - CALLED!", event)); //NOI18N
312 // event should not be null
315 throw new NullPointerException("event is null"); //NOI18N
316 } else if (event.getLoggedInUser() == null) {
318 throw new NullPointerException("event.registeredUser is null"); //NOI18N
319 } else if (event.getLoggedInUser().getUserId() == null) {
321 throw new NullPointerException("event.registeredUser.userId is null"); //NOI18N
322 } else if (event.getLoggedInUser().getUserId() < 1) {
324 throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getLoggedInUser(), event.getLoggedInUser().getUserId())); //NOI18N
327 // Copy all data to this bean
328 this.copyUser(event.getLoggedInUser());
330 // Re-initialize list
331 this.visibleUserList = this.userBean.allMemberPublicVisibleUsers();
334 //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("UserWebBean:afterUserLogin: this.visibleUserList.size()={0} - EXIT!", this.visibleUserList.size())); //NOI18N
338 public void afterUserUpdatedPersonalData (@Observes final UpdatedUserPersonalDataEvent event) {
342 throw new NullPointerException("event is null"); //NOI18N
343 } else if (event.getUpdatedUser() == null) {
345 throw new NullPointerException("event.updatedUser is null"); //NOI18N
346 } else if (event.getUpdatedUser().getUserId() == null) {
348 throw new NullPointerException("event.updatedUser.userId is null"); //NOI18N
349 } else if (event.getUpdatedUser().getUserId() < 1) {
351 throw new IllegalArgumentException(MessageFormat.format("event.updatedUser.userId={0} is in valid", event.getUpdatedUser().getUserId())); //NOI18N
354 // All fine, so update list
355 this.updateList(event.getUpdatedUser());
359 public List<User> allUsers () {
361 return Collections.unmodifiableList(this.userList);
365 public List<User> allVisibleUsers () {
367 return Collections.unmodifiableList(this.visibleUserList);
371 public User createUserInstance () {
373 //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("{0}.createUserInstance: CALLED!", this.getClass().getSimpleName()));
375 // Required personal data must be set
376 assert (this.isRequiredPersonalDataSet()) : "not all personal data is set"; //NOI18N
378 // Create new user instance
379 User user = new LoginUser();
381 // Is user name required?
382 if (!this.isUserNameRequired()) {
383 // Generate pseudo-random user name
384 String randomName = this.userBean.generateRandomUserName();
386 // Set it and inivisible profile
387 this.setUserName(randomName);
388 this.setUserProfileMode(ProfileMode.INVISIBLE);
390 // Generate random password
391 String randomPassword = UserUtils.createRandomPassword(JobsUserWebSessionController.MINIMUM_PASSWORD_LENGTH);
393 // Set random password
394 this.setUserPassword(randomPassword);
395 this.setUserPasswordRepeat(randomPassword);
398 // Set user name and mode
399 user.setUserName(this.getUserName());
400 user.setUserProfileMode(this.getUserProfileMode());
402 // Is multiple registration page
403 if (!this.registerController.isMultiplePageEnabled()) {
404 // Create contact instance
405 Contact contact = this.contactController.createContactInstance();
408 //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("{0}.createUserInstance: contact={1}", this.getClass().getSimpleName(), contact));
410 // Set contact in user
411 user.setUserContact(contact);
415 //* NOISY-DEBUG: */ System.out.println(MessageFormat.format("{0}.createUserInstance: user={1} - EXIT!", this.getClass().getSimpleName(), user));
422 public User createUserLogin () {
424 //* NOISY-DEBUG */ System.out.println(MessageFormat.format("{0}.createUserLogin: CALLED!", this.getClass().getSimpleName()));
427 if (this.getUserName() == null) {
429 throw new NullPointerException("recruiterName is null"); //NOI18N
430 } else if (this.getUserName().isEmpty()) {
432 throw new IllegalStateException("recruiterName is empty."); //NOI18N
435 // Create new recruiter instance
436 User recruiter = new LoginUser();
438 // Update all data ...
439 recruiter.setUserName(this.getUserName());
442 //* NOISY-DEBUG */ System.out.println(MessageFormat.format("{0}.createUserLogin: recruiter={1} - EXIT!", this.getClass().getSimpleName(), recruiter));
444 // Return the new instance
449 public String doChangePersonalData () {
450 // This method shall only be called if the user is logged-in
451 if (!this.userLoginController.isUserLoggedIn()) {
453 throw new IllegalStateException("User is not logged-in"); //NOI18N
454 } else if (!this.isRequiredChangePersonalDataSet()) {
455 // Not all required fields are set
456 throw new FaceletException("Not all required fields are set."); //NOI18N
457 } else if (!this.userLoginController.ifCurrentPasswordMatches()) {
458 // Password not matching
459 throw new FaceletException(new UserPasswordMismatchException(this.userLoginController.getLoggedInUser()));
463 User user = this.userLoginController.getLoggedInUser();
465 // Copy contact data to contact instance
466 this.contactController.updateContactDataFromController(user.getUserContact());
468 // It should be there, so run some tests on it
469 assert (user instanceof User) : "Instance userLoginController.loggedInUser is null"; //NOI18N
470 assert (user.getUserId() instanceof Long) : "Instance userLoginController.loggedInUser.userId is null"; //NOI18N
471 assert (user.getUserId() > 0) : MessageFormat.format("userLoginController.loggedInUser.userId={0} is invalid", user.getUserId()); //NOI18N
472 assert (user.getUserContact() instanceof Contact) : "Instance userLoginController.loggedInUser.userContact is null"; //NOI18N
473 assert (user.getUserContact().getContactId() instanceof Long) : "Instance userLoginController.userContact.contactId is null"; //NOI18N
474 assert (user.getUserContact().getContactId() > 0) : MessageFormat.format("Instance userLoginController.userContact.contactId={0} is invalid", user.getUserContact().getContactId()); //NOI18N
477 user.setUserProfileMode(this.getUserProfileMode());
479 // Send it to the EJB
480 User updatedUser = this.userBean.updateUserPersonalData(user);
483 this.updatedPersonalDataEvent.fire(new UserUpdatedPersonalDataEvent(updatedUser));
486 return "user_data_saved"; //NOI18N
490 public Long getUserId () {
495 public void setUserId (final Long userId) {
496 this.userId = userId;
500 public String getUserName () {
501 return this.userName;
505 public void setUserName (final String userName) {
506 this.userName = userName;
510 public String getUserPassword () {
511 return this.userPassword;
515 public void setUserPassword (final String userPassword) {
516 this.userPassword = userPassword;
520 public String getUserPasswordRepeat () {
521 return this.userPasswordRepeat;
525 public void setUserPasswordRepeat (final String userPasswordRepeat) {
526 this.userPasswordRepeat = userPasswordRepeat;
530 public ProfileMode getUserProfileMode () {
531 return this.userProfileMode;
535 public void setUserProfileMode (final ProfileMode userProfileMode) {
536 this.userProfileMode = userProfileMode;
540 public boolean hasUsers () {
541 return (!this.allUsers().isEmpty());
545 * Post-initialization of this class
548 public void init () {
549 // Initialize user list
550 this.userList = this.userBean.allUsers();
552 // Get full user name list for reducing EJB calls
553 this.userNameList = this.userBean.getUserNameList();
555 // Is the user logged-in?
556 if (this.userLoginController.isUserLoggedIn()) {
557 // Is logged-in, so load also users visible to memebers
558 this.visibleUserList = this.userBean.allMemberPublicVisibleUsers();
560 // Initialize user list
561 this.visibleUserList = this.userBean.allPublicUsers();
565 List<User> allUsers = this.allUsers();
568 List<Contact> allContacts = this.contactBean.getAllContacts();
571 Iterator<Contact> iterator = allContacts.iterator();
574 while (iterator.hasNext()) {
576 Contact next = iterator.next();
579 Iterator<User> userIterator = allUsers.iterator();
581 // Loop through all users
582 while (userIterator.hasNext()) {
584 User nextUser = userIterator.next();
587 if (Objects.equals(next, nextUser.getUserContact())) {
596 this.selectableContacts = allContacts;
600 public boolean isContactFound (final Contact contact) {
601 // The contact must be valid
602 if (null == contact) {
604 throw new NullPointerException("contact is null"); //NOI18N
605 } else if (contact.getContactId() == null) {
607 throw new NullPointerException("contact.contactId is null"); //NOI18N
608 } else if (contact.getContactId() < 1) {
610 throw new IllegalArgumentException(MessageFormat.format("contact.contactId={0} is not valid", contact.getContactId())); //NOI18N
613 // Default is not found
614 boolean isFound = false;
617 Iterator<User> iterator = this.allUsers().iterator();
619 // Loop through all entries
620 while (iterator.hasNext()) {
622 User next = iterator.next();
624 // Compare both objects
625 if (Objects.equals(contact, next.getUserContact())) {
637 public boolean isPublicUserProfileEnabled () {
638 // Get context parameter
639 String contextParameter = FacesContext.getCurrentInstance().getExternalContext().getInitParameter("is_public_profile_enabled"); //NOI18N
642 boolean isEnabled = ((contextParameter instanceof String) && (contextParameter.toLowerCase().equals("true"))); //NOI18N
644 // This requires user names being enabled, too.
645 if ((isEnabled) && (!this.isUserNameRequired())) {
646 // Not valid state, users must be able to modify their profile, especially when it is public
647 throw new IllegalStateException("Public user profiles are enabled but user name requirement is disabled, this is not possible."); //NOI18N
655 public boolean isRequiredChangePersonalDataSet () {
656 return ((this.getUserProfileMode() != null) &&
657 (this.getUserName() != null) && (!this.getUserName().isEmpty()) &&
658 (this.contactController.isRequiredChangePersonalDataSet()));
662 public boolean isRequiredPersonalDataSet () {
663 if (this.registerController.isMultiplePageEnabled()) {
664 // Multiple registration page
665 return this.contactController.isRequiredPersonalDataSet();
667 // Single registration page
668 return (((this.getUserName() != null) || (!this.isUserNameRequired())) &&
669 (this.getUserProfileMode() != null) &&
670 (this.contactController.isRequiredPersonalDataSet()) &&
671 (this.getUserPassword() != null) &&
672 (this.getUserPasswordRepeat() != null));
677 public boolean isSamePasswordEntered () {
678 return ((!this.getUserPassword().isEmpty()) && (Objects.equals(this.getUserPassword(), this.getUserPasswordRepeat())));
682 public boolean isUserIdEmpty () {
683 return ((this.getUserId() == null) || (this.getUserId() == 0));
687 public boolean isUserNameRegistered (final User user) {
688 return ((this.userNameList instanceof List) && (this.userNameList.contains(user.getUserName())));
692 public boolean isUserNameRequired () {
693 // Get context parameter
694 String contextParameter = FacesContext.getCurrentInstance().getExternalContext().getInitParameter("is_user_name_required"); //NOI18N
697 boolean isRequired = ((contextParameter instanceof String) && (contextParameter.toLowerCase().equals("true"))); //NOI18N
704 public boolean isVisibleUserFound () {
705 return ((this.visibleUserList instanceof List) && (this.visibleUserList.size() > 0));
709 public User lookupUserById (final Long userId) throws UserNotFoundException {
710 // Parameter must be valid
711 if (null == userId) {
713 throw new NullPointerException("userId is null"); //NOI18N
714 } else if (userId < 1) {
716 throw new IllegalArgumentException(MessageFormat.format("userId={0} is not valid.", userId)); //NOI18N
722 // Try to lookup it in visible user list
723 for (final Iterator<User> iterator = this.userList.iterator(); iterator.hasNext();) {
725 User next = iterator.next();
727 // Is the user id found?
728 if (Objects.equals(next.getUserId(), userId)) {
729 // Copy to other variable
737 // Not visible for the current user
738 throw new UserNotFoundException(userId);
746 public User lookupUserByEmailAddress (final String emailAddress) throws UserEmailAddressNotFoundException {
747 // Parameter must be valid
748 if (null == emailAddress) {
750 throw new NullPointerException("emailAddress is null"); //NOI18N
751 } else if (emailAddress.isEmpty()) {
753 throw new IllegalArgumentException("emailAddress is empty"); //NOI18N
759 // Try to lookup it in visible user list
760 for (final Iterator<User> iterator = this.userList.iterator(); iterator.hasNext();) {
762 User next = iterator.next();
764 // Contact should be set
765 if (next.getUserContact() == null) {
767 throw new NullPointerException(MessageFormat.format("next.userContact is null for user id {0}", next.getUserId())); //NOI18N
768 } else if (next.getUserContact().getContactEmailAddress() == null) {
769 // Email address should be set
770 throw new NullPointerException(MessageFormat.format("next.userContact.contactEmailAddress is null for user id {0}", next.getUserId())); //NOI18N //NOI18N
773 // Is the email address found?
774 if (Objects.equals(next.getUserContact().getContactEmailAddress(), emailAddress)) {
775 // Copy to other variable
783 // Not visible for the current user
784 throw new UserEmailAddressNotFoundException(emailAddress);
792 public List<Contact> selectableContacts () {
793 return Collections.unmodifiableList(this.selectableContacts);
797 * Adds user's name to bean's internal list. It also updates the public user
798 * list if the user has decided to have a public account,
800 * @param user User instance
802 private void addUserName (final User user) {
803 // Make sure the entry is not added yet
804 if (this.userNameList.contains(user.getUserName())) {
806 throw new IllegalArgumentException(MessageFormat.format("User name {0} already added.", user.getUserName())); //NOI18N
807 } else if (this.contactController.isEmailAddressRegistered(user.getUserContact())) {
809 throw new IllegalArgumentException(MessageFormat.format("Email address {0} already added.", user.getUserContact().getContactEmailAddress())); //NOI18N
813 this.userNameList.add(user.getUserName());
819 private void clear () {
822 this.setUserId(null);
823 this.setUserProfileMode(null);
826 this.setUserName(null);
827 this.setUserPassword(null);
828 this.setUserPasswordRepeat(null);
832 * Copies given user into the controller
834 * @param user User instance
836 private void copyUser (final User user) {
837 // Make sure the instance is valid
840 throw new NullPointerException("user is null"); //NOI18N
841 } else if (user.getUserContact() == null) {
843 throw new NullPointerException("user.userContact is null"); //NOI18N
848 this.setUserId(user.getUserId());
849 this.setUserProfileMode(user.getUserProfileMode());
853 * Updates list with given user instance
855 * @param user User instance
857 private void updateList (final User user) {
858 // The user should be valid
861 throw new NullPointerException("user is null"); //NOI18N
862 } else if (user.getUserId() == null) {
864 throw new NullPointerException("user.userId is null"); //NOI18N
865 } else if (user.getUserId() < 1) {
867 throw new IllegalArgumentException(MessageFormat.format("user.userId={0} is invalid", user.getUserId())); //NOI18N
871 Iterator<User> iterator = this.userList.iterator();
874 while (iterator.hasNext()) {
876 User next = iterator.next();
878 // Is the same user id?
879 if (Objects.equals(user.getUserId(), next.getUserId())) {
880 // Found it, so remove it
881 this.userList.remove(next);
887 this.userList.add(user);