]> git.mxchange.org Git - jjobs-war.git/blob - src/java/org/mxchange/jjobs/beans/user/JobsUserWebRequestBean.java
Please cherry-pick:
[jjobs-war.git] / src / java / org / mxchange / jjobs / beans / user / JobsUserWebRequestBean.java
1 /*
2  * Copyright (C) 2016, 2017 Roland Häder
3  *
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.
8  *
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.
13  *
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/>.
16  */
17 package org.mxchange.jjobs.beans.user;
18
19 import fish.payara.cdi.jsr107.impl.NamedCache;
20 import java.text.MessageFormat;
21 import java.util.Comparator;
22 import java.util.Iterator;
23 import java.util.LinkedList;
24 import java.util.List;
25 import java.util.Locale;
26 import java.util.Objects;
27 import javax.annotation.PostConstruct;
28 import javax.cache.Cache;
29 import javax.ejb.EJB;
30 import javax.enterprise.context.RequestScoped;
31 import javax.enterprise.event.Event;
32 import javax.enterprise.event.Observes;
33 import javax.enterprise.inject.Any;
34 import javax.faces.context.FacesContext;
35 import javax.faces.view.facelets.FaceletException;
36 import javax.inject.Inject;
37 import javax.inject.Named;
38 import org.mxchange.jcontacts.model.contact.Contact;
39 import org.mxchange.jcoreee.events.locale.ObservableLocaleChangeEvent;
40 import org.mxchange.jjobs.beans.BaseJobsBean;
41 import org.mxchange.jjobs.beans.contact.JobsContactWebRequestController;
42 import org.mxchange.jjobs.beans.features.JobsFeaturesWebApplicationController;
43 import org.mxchange.jjobs.beans.user.login.JobsUserLoginWebSessionController;
44 import org.mxchange.jusercore.events.user.add.ObservableAdminAddedUserEvent;
45 import org.mxchange.jusercore.events.user.clear.password.ObservableClearUserPasswordEvent;
46 import org.mxchange.jusercore.events.user.clear.username.ObservableClearUserNameEvent;
47 import org.mxchange.jusercore.events.user.created.ObservableCreatedUserEvent;
48 import org.mxchange.jusercore.events.user.delete.ObservableAdminDeletedUserEvent;
49 import org.mxchange.jusercore.events.user.linked.ObservableAdminLinkedUserEvent;
50 import org.mxchange.jusercore.events.user.locked.ObservableAdminLockedUserEvent;
51 import org.mxchange.jusercore.events.user.unlocked.ObservableAdminUnlockedUserEvent;
52 import org.mxchange.jusercore.events.user.update.ObservableAdminUpdatedUserDataEvent;
53 import org.mxchange.jusercore.events.user.update.ObservableUpdatedUserPersonalDataEvent;
54 import org.mxchange.jusercore.events.user.update.UpdatedUserPersonalDataEvent;
55 import org.mxchange.jusercore.exceptions.UserEmailAddressNotFoundException;
56 import org.mxchange.jusercore.exceptions.UserNotFoundException;
57 import org.mxchange.jusercore.model.user.LoginUser;
58 import org.mxchange.jusercore.model.user.User;
59 import org.mxchange.jusercore.model.user.UserSessionBeanRemote;
60 import org.mxchange.jusercore.model.user.profilemodes.ProfileMode;
61 import org.mxchange.juserlogincore.events.confirmation.ObservableUserConfirmedAccountEvent;
62 import org.mxchange.juserlogincore.events.login.ObservableUserLoggedInEvent;
63 import org.mxchange.juserlogincore.events.registration.ObservableUserRegisteredEvent;
64 import org.mxchange.juserlogincore.events.user.password_change.ObservableUpdatedUserPasswordEvent;
65 import org.mxchange.juserlogincore.exceptions.UserPasswordMismatchException;
66 import org.mxchange.juserlogincore.login.UserLoginUtils;
67
68 /**
69  * A user controller (bean)
70  * <p>
71  * @author Roland Häder<roland@mxchange.org>
72  */
73 @Named ("userController")
74 @RequestScoped
75 public class JobsUserWebRequestBean extends BaseJobsBean implements JobsUserWebRequestController {
76
77         /**
78          * Serial number
79          */
80         private static final long serialVersionUID = 542_145_347_916L;
81
82         /**
83          * List of all users
84          */
85         private final List<User> allUsers;
86
87         /**
88          * General contact controller
89          */
90         @Inject
91         private JobsContactWebRequestController contactController;
92
93         /**
94          * Features controller
95          */
96         @Inject
97         private JobsFeaturesWebApplicationController featureController;
98
99         /**
100          * List of filtered users
101          */
102         private List<User> filteredUsers;
103
104         /**
105          * Locale instance
106          */
107         private Locale locale;
108
109         /**
110          * Event being fired when user updated personal data
111          */
112         @Inject
113         @Any
114         private Event<ObservableUpdatedUserPersonalDataEvent> updatedPersonalDataEvent;
115
116         /**
117          * Remote user bean
118          */
119         @EJB (lookup = "java:global/jjobs-ejb/user!org.mxchange.jusercore.model.user.UserSessionBeanRemote")
120         private UserSessionBeanRemote userBean;
121
122         /**
123          * A list of all user profiles
124          */
125         @Inject
126         @NamedCache (cacheName = "userCache")
127         private Cache<Long, User> userCache;
128
129         /**
130          * User id
131          */
132         private Long userId;
133
134         /**
135          * Login controller (bean)
136          */
137         @Inject
138         private JobsUserLoginWebSessionController userLoginController;
139
140         /**
141          * User name
142          */
143         private String userName;
144
145         /**
146          * User name list
147          */
148         @Inject
149         @NamedCache (cacheName = "userNameCache")
150         private Cache<Long, String> userNameCache;
151
152         /**
153          * User password (clear-text from web form)
154          */
155         private String userPassword;
156
157         /**
158          * User password repeated (clear-text from web form)
159          */
160         private String userPasswordRepeat;
161
162         /**
163          * Whether the user wants a public profile
164          */
165         private ProfileMode userProfileMode;
166
167         /**
168          * Default constructor
169          */
170         public JobsUserWebRequestBean () {
171                 // Call super constructor
172                 super();
173
174                 // Init list
175                 this.allUsers = new LinkedList<>();
176         }
177
178         /**
179          * Event observer for newly added users by administrator
180          * <p>
181          * @param event Event being fired
182          */
183         public void afterAdminAddedUserEvent (@Observes final ObservableAdminAddedUserEvent event) {
184                 // event should not be null
185                 if (null == event) {
186                         // Throw NPE
187                         throw new NullPointerException("event is null"); //NOI18N
188                 } else if (event.getAddedUser() == null) {
189                         // Throw NPE again
190                         throw new NullPointerException("event.addedUser is null"); //NOI18N
191                 } else if (event.getAddedUser().getUserId() == null) {
192                         // userId is null
193                         throw new NullPointerException("event.addedUser.userId is null"); //NOI18N
194                 } else if (event.getAddedUser().getUserId() < 1) {
195                         // Not avalid id
196                         throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getAddedUser(), event.getAddedUser().getUserId())); //NOI18N
197                 }
198
199                 // Update user list
200                 this.updateList(event.getAddedUser());
201
202                 // Clear all data
203                 this.clear();
204
205                 // Set user id again
206                 this.setUserId(event.getAddedUser().getUserId());
207         }
208
209         /**
210          * Event observer for deleted user accounts (by administrator)
211          * <p>
212          * @param event Event being fired
213          */
214         public void afterAdminDeletedUserEvent (@Observes final ObservableAdminDeletedUserEvent event) {
215                 // event should not be null
216                 if (null == event) {
217                         // Throw NPE
218                         throw new NullPointerException("event is null"); //NOI18N
219                 } else if (event.getDeletedUser() == null) {
220                         // Throw NPE again
221                         throw new NullPointerException("event.deletedUser is null"); //NOI18N
222                 } else if (event.getDeletedUser().getUserId() == null) {
223                         // userId is null
224                         throw new NullPointerException("event.deletedUser.userId is null"); //NOI18N
225                 } else if (event.getDeletedUser().getUserId() < 1) {
226                         // Not avalid id
227                         throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getDeletedUser(), event.getDeletedUser().getUserId())); //NOI18N
228                 }
229
230                 // Update user list
231                 this.removeFromList(event.getDeletedUser());
232
233                 // Clear all data
234                 this.clear();
235         }
236
237         /**
238          * Event observer for linked users with existing contact data
239          * <p>
240          * @param event Event being fired
241          */
242         public void afterAdminLinkedUserEvent (@Observes final ObservableAdminLinkedUserEvent event) {
243                 // event should not be null
244                 if (null == event) {
245                         // Throw NPE
246                         throw new NullPointerException("event is null"); //NOI18N
247                 } else if (event.getLinkedUser() == null) {
248                         // Throw NPE again
249                         throw new NullPointerException("event.linkedUser is null"); //NOI18N
250                 } else if (event.getLinkedUser().getUserId() == null) {
251                         // userId is null
252                         throw new NullPointerException("event.linkedUser.userId is null"); //NOI18N
253                 } else if (event.getLinkedUser().getUserId() < 1) {
254                         // Not avalid id
255                         throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getLinkedUser(), event.getLinkedUser().getUserId())); //NOI18N
256                 }
257
258                 // Update user list
259                 this.updateList(event.getLinkedUser());
260
261                 // Clear all data
262                 this.clear();
263
264                 // Set user id again
265                 this.setUserId(event.getLinkedUser().getUserId());
266         }
267
268         /**
269          * Event observer for locked users
270          * <p>
271          * @param event Event being fired
272          */
273         public void afterAdminLockedUserEvent (@Observes final ObservableAdminLockedUserEvent event) {
274                 // event should not be null
275                 if (null == event) {
276                         // Throw NPE
277                         throw new NullPointerException("event is null"); //NOI18N
278                 } else if (event.getLockedUser() == null) {
279                         // Throw NPE again
280                         throw new NullPointerException("event.lockedUser is null"); //NOI18N
281                 } else if (event.getLockedUser().getUserId() == null) {
282                         // userId is null
283                         throw new NullPointerException("event.lockedUser.userId is null"); //NOI18N
284                 } else if (event.getLockedUser().getUserId() < 1) {
285                         // Not avalid id
286                         throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getLockedUser(), event.getLockedUser().getUserId())); //NOI18N
287                 }
288
289                 // Update user list
290                 this.updateList(event.getLockedUser());
291         }
292
293         /**
294          * Event observer for unlocked users
295          * <p>
296          * @param event Event being fired
297          */
298         public void afterAdminUnlockedUserEvent (@Observes final ObservableAdminUnlockedUserEvent event) {
299                 // event should not be null
300                 if (null == event) {
301                         // Throw NPE
302                         throw new NullPointerException("event is null"); //NOI18N
303                 } else if (event.getUnlockedUser() == null) {
304                         // Throw NPE again
305                         throw new NullPointerException("event.unlockedUser is null"); //NOI18N
306                 } else if (event.getUnlockedUser().getUserId() == null) {
307                         // userId is null
308                         throw new NullPointerException("event.unlockedUser.userId is null"); //NOI18N
309                 } else if (event.getUnlockedUser().getUserId() < 1) {
310                         // Not avalid id
311                         throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getUnlockedUser(), event.getUnlockedUser().getUserId())); //NOI18N
312                 }
313
314                 // Update user list
315                 this.updateList(event.getUnlockedUser());
316         }
317
318         /**
319          * Event observer for updated user data by administrator
320          * <p>
321          * @param event Event being updated
322          */
323         public void afterAdminUpdatedUserDataEvent (@Observes final ObservableAdminUpdatedUserDataEvent event) {
324                 // event should not be null
325                 if (null == event) {
326                         // Throw NPE
327                         throw new NullPointerException("event is null"); //NOI18N
328                 } else if (event.getUpdatedUser() == null) {
329                         // Throw NPE again
330                         throw new NullPointerException("event.updatedUser is null"); //NOI18N
331                 } else if (event.getUpdatedUser().getUserId() == null) {
332                         // userId is null
333                         throw new NullPointerException("event.updatedUser.userId is null"); //NOI18N
334                 } else if (event.getUpdatedUser().getUserId() < 1) {
335                         // Not avalid id
336                         throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getUpdatedUser(), event.getUpdatedUser().getUserId())); //NOI18N
337                 }
338
339                 // Update user list
340                 this.updateList(event.getUpdatedUser());
341
342                 // Clear all data
343                 this.clear();
344         }
345
346         /**
347          * Event observer for when a bean helper has successfully created a user
348          * instance, means the user exists. If the user does not exist, this event
349          * should not fire but instead a proper exception must be thrown.
350          * <p>
351          * @param event User created event
352          */
353         public void afterCreatedUserEvent (@Observes final ObservableCreatedUserEvent event) {
354                 // Is the instance valid?
355                 if (null == event) {
356                         // Throw NPE
357                         throw new NullPointerException("event is null"); //NOI18N
358                 } else if (event.getCreatedUser() == null) {
359                         // Throw NPE again
360                         throw new NullPointerException("event.createdUser is null"); //NOI18N
361                 } else if (event.getCreatedUser().getUserId() == null) {
362                         // Throw NPE again
363                         throw new NullPointerException("event.createdUser.userId is null"); //NOI18N
364                 } else if (event.getCreatedUser().getUserId() < 1) {
365                         // Throw NPE again
366                         throw new NullPointerException(MessageFormat.format("event.createdUser.userId={0} is not valid", event.getCreatedUser().getUserId())); //NOI18N
367                 }
368
369                 // Get user instance
370                 final User user = event.getCreatedUser();
371
372                 // Set all fields here
373                 this.copyUser(user);
374         }
375
376         /**
377          * Observer method for events being fired when the application's locale has
378          * been changed.
379          * <p>
380          * @param event Event being fired
381          */
382         public void afterLocaleChangeEvent (@Observes final ObservableLocaleChangeEvent event) {
383                 // Is the parameter valid?
384                 if (null == event) {
385                         // Throw NPE
386                         throw new NullPointerException("event is null");
387                 } else if (event.getLocale() == null) {
388                         // Throw NPE again
389                         throw new NullPointerException("event.locale is null");
390                 }
391
392                 // Set it here
393                 this.setLocale(event.getLocale());
394         }
395
396         /**
397          * Event observer when user confirmed account.
398          * <p>
399          * @param event Event being fired
400          */
401         public void afterUserConfirmedAccountEvent (@Observes final ObservableUserConfirmedAccountEvent event) {
402                 // event should not be null
403                 if (null == event) {
404                         // Throw NPE
405                         throw new NullPointerException("event is null"); //NOI18N
406                 } else if (event.getConfirmedUser() == null) {
407                         // Throw NPE again
408                         throw new NullPointerException("event.confirmedUser is null"); //NOI18N
409                 } else if (event.getConfirmedUser().getUserId() == null) {
410                         // userId is null
411                         throw new NullPointerException("event.confirmedUser.userId is null"); //NOI18N
412                 } else if (event.getConfirmedUser().getUserId() < 1) {
413                         // Not avalid id
414                         throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getConfirmedUser(), event.getConfirmedUser().getUserId())); //NOI18N
415                 }
416
417                 // Update user list
418                 this.updateList(event.getConfirmedUser());
419         }
420
421         /**
422          * Event observer for logged-in user
423          * <p>
424          * @param event Event instance
425          */
426         public void afterUserLoginEvent (@Observes final ObservableUserLoggedInEvent event) {
427                 // event should not be null
428                 if (null == event) {
429                         // Throw NPE
430                         throw new NullPointerException("event is null"); //NOI18N
431                 } else if (event.getLoggedInUser() == null) {
432                         // Throw NPE again
433                         throw new NullPointerException("event.registeredUser is null"); //NOI18N
434                 } else if (event.getLoggedInUser().getUserId() == null) {
435                         // userId is null
436                         throw new NullPointerException("event.registeredUser.userId is null"); //NOI18N
437                 } else if (event.getLoggedInUser().getUserId() < 1) {
438                         // Not avalid id
439                         throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getLoggedInUser(), event.getLoggedInUser().getUserId())); //NOI18N
440                 }
441
442                 // "Cache" user instance
443                 final User loggedInUser = event.getLoggedInUser();
444
445                 // Copy all data to this bean
446                 this.copyUser(loggedInUser);
447         }
448
449         /**
450          * Event observer for user password changes
451          * <p>
452          * @param event Event being fired
453          */
454         public void afterUserPasswordChangedEvent (@Observes final ObservableUpdatedUserPasswordEvent event) {
455                 // Is it valid?
456                 if (null == event) {
457                         // Throw NPE
458                         throw new NullPointerException("event is null"); //NOI18N
459                 } else if (event.getUserPassword() == null) {
460                         // Throw NPE
461                         throw new NullPointerException("event.userPassword is null"); //NOI18N
462                 } else if (event.getUserPassword().isEmpty()) {
463                         // Throw NPE
464                         throw new IllegalArgumentException("event.userPassword is empty"); //NOI18N
465                 }
466
467                 // Set it here
468                 this.setUserPassword(event.getUserPassword());
469                 this.setUserPasswordRepeat(event.getUserPassword());
470         }
471
472         /**
473          * Event observer for new user registrations
474          * <p>
475          * @param event User registration event
476          */
477         public void afterUserRegistrationEvent (@Observes final ObservableUserRegisteredEvent event) {
478                 // event should not be null
479                 if (null == event) {
480                         // Throw NPE
481                         throw new NullPointerException("event is null"); //NOI18N
482                 } else if (event.getRegisteredUser() == null) {
483                         // Throw NPE again
484                         throw new NullPointerException("event.registeredUser is null"); //NOI18N
485                 } else if (event.getRegisteredUser().getUserId() == null) {
486                         // userId is null
487                         throw new NullPointerException("event.registeredUser.userId is null"); //NOI18N
488                 } else if (event.getRegisteredUser().getUserId() < 1) {
489                         // Not avalid id
490                         throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getRegisteredUser(), event.getRegisteredUser().getUserId())); //NOI18N
491                 }
492
493                 // Get user instance
494                 final User registeredUser = event.getRegisteredUser();
495
496                 // Copy all data from registered->user
497                 this.copyUser(registeredUser);
498
499                 // Clear all data
500                 this.clear();
501
502                 // Update user list
503                 this.updateList(registeredUser);
504
505                 // Add user name
506                 this.addUserName(registeredUser);
507
508                 // Set user id again
509                 this.setUserId(registeredUser.getUserId());
510         }
511
512         /**
513          * Method being call after user's password has been updated (and history
514          * entry has been created).
515          * <p>
516          * @param event Event being observed
517          */
518         public void afterUserUpdatedPasswordEvent (@Observes final ObservableUpdatedUserPasswordEvent event) {
519                 // Check parameter
520                 if (null == event) {
521                         // Throw NPE
522                         throw new NullPointerException("event is null"); //NOI18N
523                 } else if (event.getPasswordHistory() == null) {
524                         // Throw NPE again
525                         throw new NullPointerException("event.passwordHistory is null"); //NOI18N
526                 } else if (event.getPasswordHistory().getUserPasswordHistoryId() == null) {
527                         // ... and again
528                         throw new NullPointerException("event.passwordHistory.userPasswordHistoryId is null"); //NOI18N
529                 } else if (event.getPasswordHistory().getUserPasswordHistoryId() < 1) {
530                         // Invalid value
531                         throw new IllegalArgumentException(MessageFormat.format("event.passwordHistory.userPasswordHistoryId={0} is in valid", event.getPasswordHistory().getUserPasswordHistoryId())); //NOI18N
532                 }
533
534                 // Update user list
535                 this.updateList(event.getPasswordHistory().getUserPasswordHistoryUser());
536         }
537
538         /**
539          * Listens to fired event when user updated personal data
540          * <p>
541          * @param event Event being fired
542          */
543         public void afterUserUpdatedPersonalDataEvent (@Observes final ObservableUpdatedUserPersonalDataEvent event) {
544                 // Check parameter
545                 if (null == event) {
546                         // Throw NPE
547                         throw new NullPointerException("event is null"); //NOI18N
548                 } else if (event.getUpdatedUser() == null) {
549                         // Throw NPE again
550                         throw new NullPointerException("event.updatedUser is null"); //NOI18N
551                 } else if (event.getUpdatedUser().getUserId() == null) {
552                         // ... and again
553                         throw new NullPointerException("event.updatedUser.userId is null"); //NOI18N
554                 } else if (event.getUpdatedUser().getUserId() < 1) {
555                         // Invalid value
556                         throw new IllegalArgumentException(MessageFormat.format("event.updatedUser.userId={0} is in valid", event.getUpdatedUser().getUserId())); //NOI18N
557                 }
558
559                 // Update user list
560                 this.updateList(event.getUpdatedUser());
561         }
562
563         @Override
564         @SuppressWarnings ("ReturnOfCollectionOrArrayField")
565         public List<User> allUsers () {
566                 return this.allUsers;
567         }
568
569         /**
570          * Event observer for when a user name should be cleared
571          * <p>
572          * @param event Event being fired
573          */
574         public void clearUserNameEvent (@Observes final ObservableClearUserNameEvent event) {
575                 // Is it valid?
576                 if (null == event) {
577                         // Throw NPE
578                         throw new NullPointerException("event is null");
579                 }
580
581                 // Clear it
582                 this.clearUserName();
583         }
584
585         /**
586          * Event observer for when both user passwords should be cleared
587          * <p>
588          * @param event Event being fired
589          */
590         public void clearUserPasswordEvent (@Observes final ObservableClearUserPasswordEvent event) {
591                 // Is it valid?
592                 if (null == event) {
593                         // Throw NPE
594                         throw new NullPointerException("event is null");
595                 }
596
597                 // Clear it
598                 this.clearUserPasswords();
599         }
600
601         @Override
602         public User createUserInstance (final boolean createContactData) {
603                 // Required personal data must be set
604                 assert (this.isRequiredPersonalDataSet()) : "not all personal data is set"; //NOI18N
605
606                 // Create new user instance
607                 final User user = new LoginUser();
608
609                 // Is user name required?
610                 if (!this.isUserNameRequired()) {
611                         // Generate pseudo-random user name
612                         String randomName = this.userBean.generateRandomUserName();
613
614                         // Set it and inivisible profile
615                         this.setUserName(randomName);
616                         this.setUserProfileMode(ProfileMode.INVISIBLE);
617
618                         // Generate random password
619                         String randomPassword = UserLoginUtils.createRandomPassword(JobsUserWebRequestController.MINIMUM_PASSWORD_LENGTH);
620
621                         // Set random password
622                         this.setUserPassword(randomPassword);
623                         this.setUserPasswordRepeat(randomPassword);
624                 }
625
626                 // Set user name profile mode and locale
627                 user.setUserName(this.getUserName());
628                 user.setUserProfileMode(this.getUserProfileMode());
629                 user.setUserLocale(this.getLocale());
630
631                 // Is multiple registration page
632                 if ((createContactData) || (!this.featureController.isFeatureEnabled("user_register_multiple_page"))) { //NOI18N
633                         // Create contact instance
634                         final Contact contact = this.contactController.createContactInstance();
635
636                         // Set contact in user
637                         user.setUserContact(contact);
638                 }
639
640                 // Return it
641                 return user;
642         }
643
644         @Override
645         public User createUserLogin () {
646                 // Is all data set?
647                 if (this.getUserName() == null) {
648                         // Throw NPE
649                         throw new NullPointerException("userName is null"); //NOI18N
650                 } else if (this.getUserName().isEmpty()) {
651                         // Is empty
652                         throw new IllegalStateException("userName is empty."); //NOI18N
653                 }
654
655                 // Create new user instance
656                 final User user = new LoginUser();
657
658                 // Update all data ...
659                 user.setUserName(this.getUserName());
660
661                 // Return the new instance
662                 return user;
663         }
664
665         @Override
666         public String doChangePersonalData () {
667                 // This method shall only be called if the user is logged-in
668                 if (!this.userLoginController.isUserLoggedIn()) {
669                         // Not logged-in
670                         throw new IllegalStateException("User is not logged-in"); //NOI18N
671                 } else if (!this.isRequiredChangePersonalDataSet()) {
672                         // Not all required fields are set
673                         throw new FaceletException("Not all required fields are set."); //NOI18N
674                 } else if (!this.userLoginController.ifCurrentPasswordMatches()) {
675                         // Password not matching
676                         throw new FaceletException(new UserPasswordMismatchException(this.userLoginController.getLoggedInUser()));
677                 } else if (!this.featureController.isFeatureEnabled("change_user_personal_data")) { //NOI18N
678                         // Editing is not allowed
679                         throw new IllegalStateException("User tried to edit personal data."); //NOI18N
680                 }
681
682                 // Get user instance
683                 final User user = this.userLoginController.getLoggedInUser();
684
685                 // Copy contact data to contact instance
686                 this.contactController.updateContactDataFromController(user.getUserContact());
687
688                 // It should be there, so run some tests on it
689                 assert (user instanceof User) : "Instance userLoginController.loggedInUser is null"; //NOI18N
690                 assert (user.getUserId() instanceof Long) : "Instance userLoginController.loggedInUser.userId is null"; //NOI18N
691                 assert (user.getUserId() > 0) : MessageFormat.format("userLoginController.loggedInUser.userId={0} is invalid", user.getUserId()); //NOI18N
692                 assert (user.getUserContact() instanceof Contact) : "Instance userLoginController.loggedInUser.userContact is null"; //NOI18N
693                 assert (user.getUserContact().getContactId() instanceof Long) : "Instance userLoginController.userContact.contactId is null"; //NOI18N
694                 assert (user.getUserContact().getContactId() > 0) : MessageFormat.format("Instance userLoginController.userContact.contactId={0} is invalid", user.getUserContact().getContactId()); //NOI18N
695
696                 // Update all fields
697                 user.setUserProfileMode(this.getUserProfileMode());
698
699                 // Send it to the EJB
700                 final User updatedUser = this.userBean.updateUserPersonalData(user);
701
702                 // Fire event
703                 this.updatedPersonalDataEvent.fire(new UpdatedUserPersonalDataEvent(updatedUser));
704
705                 // All fine
706                 return "user_contact_data_saved"; //NOI18N
707         }
708
709         /**
710          * Getter for filtered users list
711          * <p>
712          * @return Filtered users list
713          */
714         @SuppressWarnings ("ReturnOfCollectionOrArrayField")
715         public List<User> getFilteredUsers () {
716                 return this.filteredUsers;
717         }
718
719         /**
720          * Setter for filtered users list
721          * <p>
722          * @param filteredUsers Filtered users list
723          */
724         @SuppressWarnings ("AssignmentToCollectionOrArrayFieldFromParameter")
725         public void setFilteredUsers (final List<User> filteredUsers) {
726                 this.filteredUsers = filteredUsers;
727         }
728
729         /**
730          * Getter for user id
731          * <p>
732          * @return User id
733          */
734         public Long getUserId () {
735                 return this.userId;
736         }
737
738         /**
739          * Setter for user id
740          * <p>
741          * @param userId User id
742          */
743         public void setUserId (final Long userId) {
744                 this.userId = userId;
745         }
746
747         /**
748          * Getter for user name
749          * <p>
750          * @return User name
751          */
752         public String getUserName () {
753                 return this.userName;
754         }
755
756         /**
757          * Setter for user name
758          * <p>
759          * @param userName User name
760          */
761         public void setUserName (final String userName) {
762                 this.userName = userName;
763         }
764
765         @Override
766         public String getUserPassword () {
767                 return this.userPassword;
768         }
769
770         /**
771          * Setter for clear-text user password
772          * <p>
773          * @param userPassword Clear-text user password
774          */
775         public void setUserPassword (final String userPassword) {
776                 this.userPassword = userPassword;
777         }
778
779         /**
780          * Getter for clear-text user password repeated
781          * <p>
782          * @return Clear-text user password repeated
783          */
784         public String getUserPasswordRepeat () {
785                 return this.userPasswordRepeat;
786         }
787
788         /**
789          * Setter for clear-text user password repeated
790          * <p>
791          * @param userPasswordRepeat Clear-text user password repeated
792          */
793         public void setUserPasswordRepeat (final String userPasswordRepeat) {
794                 this.userPasswordRepeat = userPasswordRepeat;
795         }
796
797         /**
798          * Getter for user profile mode
799          * <p>
800          * @return User profile mode
801          */
802         public ProfileMode getUserProfileMode () {
803                 return this.userProfileMode;
804         }
805
806         /**
807          * Setter for user profile mode
808          * <p>
809          * @param userProfileMode User profile mode
810          */
811         public void setUserProfileMode (final ProfileMode userProfileMode) {
812                 this.userProfileMode = userProfileMode;
813         }
814
815         @Override
816         public boolean ifBothPasswordsEmptyAllowed () {
817                 // Check feature first
818                 return ((this.featureController.isFeatureEnabled("allow_user_registration_empty_password")) && //NOI18N
819                                 ((this.getUserPassword() == null) || (this.getUserPassword().isEmpty())) &&
820                                 ((this.getUserPasswordRepeat() == null) || (this.getUserPasswordRepeat().isEmpty())));
821         }
822
823         /**
824          * Post-initialization of this class
825          */
826         @PostConstruct
827         public void init () {
828                 // Is cache there?
829                 if (!this.userCache.iterator().hasNext()) {
830                         // Get whole list
831                         final List<User> users = this.userBean.allUsers();
832
833                         // Add all
834                         for (final User user : users) {
835                                 // Add it to cache
836                                 this.userCache.put(user.getUserId(), user);
837                                 this.userNameCache.put(user.getUserId(), user.getUserName());
838                         }
839                 }
840
841                 // Is cache filled and list is empty
842                 if ((this.userCache.iterator().hasNext()) && (this.allUsers.isEmpty())) {
843                         // Get iterator
844                         final Iterator<Cache.Entry<Long, User>> iterator = this.userCache.iterator();
845
846                         // Build up list
847                         while (iterator.hasNext()) {
848                                 // GEt next element
849                                 final Cache.Entry<Long, User> next = iterator.next();
850
851                                 // Add to list
852                                 this.allUsers.add(next.getValue());
853                         }
854
855                         // Sort list
856                         this.allUsers.sort(new Comparator<User>() {
857                                 @Override
858                                 public int compare (final User o1, final User o2) {
859                                         return o1.getUserId() > o2.getUserId() ? 1 : o1.getUserId() < o2.getUserId() ? -1 : 0;
860                                 }
861                         });
862                 }
863         }
864
865         @Override
866         public boolean isContactFound (final Contact contact) {
867                 // The contact must be valid
868                 if (null == contact) {
869                         // Throw NPE
870                         throw new NullPointerException("contact is null"); //NOI18N
871                 } else if (contact.getContactId() == null) {
872                         // Throw again ...
873                         throw new NullPointerException("contact.contactId is null"); //NOI18N
874                 } else if (contact.getContactId() < 1) {
875                         // Not valid
876                         throw new IllegalArgumentException(MessageFormat.format("contact.contactId={0} is not valid", contact.getContactId())); //NOI18N
877                 }
878
879                 // Default is not found
880                 boolean isFound = false;
881
882                 // Get iterator
883                 final Iterator<User> iterator = this.allUsers().iterator();
884
885                 // Loop through all entries
886                 while (iterator.hasNext()) {
887                         // Get user
888                         final User next = iterator.next();
889
890                         // Compare both objects
891                         if (Objects.equals(contact, next.getUserContact())) {
892                                 // Found it
893                                 isFound = true;
894                                 break;
895                         }
896                 }
897
898                 // Return status
899                 return isFound;
900         }
901
902         @Override
903         public boolean isPublicUserProfileEnabled () {
904                 // Get context parameter
905                 final String contextParameter = FacesContext.getCurrentInstance().getExternalContext().getInitParameter("is_public_profile_enabled"); //NOI18N
906
907                 // Is it set?
908                 final boolean isEnabled = ((contextParameter instanceof String) && (contextParameter.toLowerCase().equals("true"))); //NOI18N
909
910                 // This requires user names being enabled, too.
911                 if ((isEnabled) && (!this.isUserNameRequired())) {
912                         // Not valid state, users must be able to modify their profile, especially when it is public
913                         throw new IllegalStateException("Public user profiles are enabled but user name requirement is disabled, this is not possible."); //NOI18N
914                 }
915
916                 // Return value
917                 return isEnabled;
918         }
919
920         @Override
921         public boolean isRequiredChangePersonalDataSet () {
922                 return ((this.getUserProfileMode() != null) &&
923                                 (this.getUserName() != null) && (!this.getUserName().isEmpty()) &&
924                                 (this.contactController.isRequiredChangePersonalDataSet()));
925         }
926
927         @Override
928         public boolean isRequiredPersonalDataSet () {
929                 if (this.featureController.isFeatureEnabled("user_register_multiple_page")) { //NOI18N
930                         // Multiple registration page
931                         return this.contactController.isRequiredPersonalDataSet();
932                 } else {
933                         // Single registration page
934                         return (((this.getUserName() != null) || (!this.isUserNameRequired())) &&
935                                         (this.getUserProfileMode() != null) &&
936                                         (this.contactController.isRequiredPersonalDataSet()) &&
937                                         (this.getUserPassword() != null) &&
938                                         (this.getUserPasswordRepeat() != null));
939                 }
940         }
941
942         @Override
943         public boolean isSamePasswordEntered () {
944                 return ((!this.getUserPassword().isEmpty()) && (Objects.equals(this.getUserPassword(), this.getUserPasswordRepeat())));
945         }
946
947         @Override
948         public boolean isUserIdEmpty () {
949                 return ((this.getUserId() == null) || (this.getUserId() == 0));
950         }
951
952         @Override
953         public boolean isUserNameRegistered (final User user) {
954                 return ((this.userNameCache instanceof List) && (this.userNameCache.containsKey(user.getUserId())));
955         }
956
957         @Override
958         public boolean isUserNameRequired () {
959                 // Get context parameter
960                 final String contextParameter = FacesContext.getCurrentInstance().getExternalContext().getInitParameter("is_user_login_require_user_name"); //NOI18N
961
962                 // Is it set?
963                 final boolean isRequired = ((contextParameter instanceof String) && (contextParameter.toLowerCase().equals("true"))); //NOI18N
964
965                 // Return value
966                 return isRequired;
967         }
968
969         @Override
970         public User lookupUserByEmailAddress (final String emailAddress) throws UserEmailAddressNotFoundException {
971                 // Parameter must be valid
972                 if (null == emailAddress) {
973                         // Throw NPE
974                         throw new NullPointerException("emailAddress is null"); //NOI18N
975                 } else if (emailAddress.isEmpty()) {
976                         // Not valid
977                         throw new IllegalArgumentException("emailAddress is empty"); //NOI18N
978                 }
979
980                 // Init variable
981                 User user = null;
982
983                 // Try to lookup it in visible user list
984                 for (final Iterator<Cache.Entry<Long, User>> iterator = this.userCache.iterator(); iterator.hasNext();) {
985                         // Get next user
986                         final Cache.Entry<Long, User> next = iterator.next();
987
988                         // Contact should be set
989                         if (next.getValue().getUserContact() == null) {
990                                 // Contact is null
991                                 throw new NullPointerException(MessageFormat.format("next.userContact is null for user id {0}", next.getKey())); //NOI18N
992                         } else if (next.getValue().getUserContact().getContactEmailAddress() == null) {
993                                 // Email address should be set
994                                 throw new NullPointerException(MessageFormat.format("next.userContact.contactEmailAddress is null for user id {0}", next.getKey())); //NOI18N
995                         }
996
997                         // Is the email address found?
998                         if (Objects.equals(next.getValue().getUserContact().getContactEmailAddress(), emailAddress)) {
999                                 // Copy to other variable
1000                                 user = next.getValue();
1001                                 break;
1002                         }
1003                 }
1004
1005                 // Is it still null?
1006                 if (null == user) {
1007                         // Not visible for the current user
1008                         throw new UserEmailAddressNotFoundException(emailAddress);
1009                 }
1010
1011                 // Return it
1012                 return user;
1013         }
1014
1015         @Override
1016         public User lookupUserById (final Long userId) throws UserNotFoundException {
1017                 // Parameter must be valid
1018                 if (null == userId) {
1019                         // Throw NPE
1020                         throw new NullPointerException("userId is null"); //NOI18N
1021                 } else if (userId < 1) {
1022                         // Not valid
1023                         throw new IllegalArgumentException(MessageFormat.format("userId={0} is not valid.", userId)); //NOI18N
1024                 }
1025
1026                 // Init variable
1027                 User user = null;
1028
1029                 // Try to lookup it in visible user list
1030                 for (final Iterator<Cache.Entry<Long, User>> iterator = this.userCache.iterator(); iterator.hasNext();) {
1031                         // Get next user
1032                         final Cache.Entry<Long, User> next = iterator.next();
1033
1034                         // Is the user id found?
1035                         if (Objects.equals(next.getKey(), userId)) {
1036                                 // Copy to other variable
1037                                 user = next.getValue();
1038                                 break;
1039                         }
1040                 }
1041
1042                 // Is it still null?
1043                 if (null == user) {
1044                         // Not visible for the current user
1045                         throw new UserNotFoundException(userId);
1046                 }
1047
1048                 // Return it
1049                 return user;
1050         }
1051
1052         /**
1053          * Adds user's name to bean's internal list. It also updates the public user
1054          * list if the user has decided to have a public account,
1055          * <p>
1056          * @param user User instance
1057          */
1058         private void addUserName (final User user) {
1059                 // Make sure the entry is not added yet
1060                 if (this.userNameCache.containsKey(user.getUserId())) {
1061                         // Abort here
1062                         throw new IllegalArgumentException(MessageFormat.format("User name {0} already added.", user.getUserName())); //NOI18N
1063                 }
1064
1065                 // Add user name
1066                 this.userNameCache.put(user.getUserId(), user.getUserName());
1067         }
1068
1069         /**
1070          * Clears this bean
1071          */
1072         private void clear () {
1073                 // Clear all data
1074                 // - personal data
1075                 this.setUserId(null);
1076                 this.setUserProfileMode(null);
1077
1078                 // - other data
1079                 this.clearUserName();
1080                 this.clearUserPasswords();
1081                 this.setLocale(null);
1082         }
1083
1084         /**
1085          * Clears user name
1086          */
1087         private void clearUserName () {
1088                 // Clear it
1089                 this.setUserName(null);
1090         }
1091
1092         /**
1093          * Clears both user passwords
1094          */
1095         private void clearUserPasswords () {
1096                 // Clear both
1097                 this.setUserPassword(null);
1098                 this.setUserPasswordRepeat(null);
1099         }
1100
1101         /**
1102          * Copies given user into the controller
1103          * <p>
1104          * @param user User instance
1105          */
1106         private void copyUser (final User user) {
1107                 // Make sure the instance is valid
1108                 if (null == user) {
1109                         // Throw NPE
1110                         throw new NullPointerException("user is null"); //NOI18N
1111                 } else if (user.getUserContact() == null) {
1112                         // Throw again ...
1113                         throw new NullPointerException("user.userContact is null"); //NOI18N
1114                 }
1115
1116                 // Copy all fields:
1117                 // - base data
1118                 this.setUserId(user.getUserId());
1119                 this.setUserProfileMode(user.getUserProfileMode());
1120         }
1121
1122         /**
1123          * Getter for locale instance
1124          * <p>
1125          * @return Locale instance
1126          */
1127         private Locale getLocale () {
1128                 return this.locale;
1129         }
1130
1131         /**
1132          * Setter for locale instance
1133          * <p>
1134          * @param locale Locale instance
1135          */
1136         private void setLocale (final Locale locale) {
1137                 this.locale = locale;
1138         }
1139
1140         /**
1141          * Removes user from all lists
1142          * <p>
1143          * @param user User to remove
1144          */
1145         private void removeFromList (final User user) {
1146                 // The user should be valid
1147                 if (null == user) {
1148                         // Throw NPE
1149                         throw new NullPointerException("user is null"); //NOI18N
1150                 } else if (user.getUserId() == null) {
1151                         // ... again NPE
1152                         throw new NullPointerException("user.userId is null"); //NOI18N
1153                 } else if (user.getUserId() < 1) {
1154                         // Invalid id
1155                         throw new IllegalArgumentException(MessageFormat.format("user.userId={0} is invalid", user.getUserId())); //NOI18N
1156                 }
1157
1158                 // Remove it from lists
1159                 this.userCache.remove(user.getUserId());
1160                 this.allUsers.remove(user);
1161
1162                 // Remove name from list
1163                 this.userNameCache.remove(user.getUserId());
1164         }
1165
1166         /**
1167          * Updates list with given user instance
1168          * <p>
1169          * @param user User instance
1170          */
1171         private void updateList (final User user) {
1172                 // The user should be valid
1173                 if (null == user) {
1174                         // Throw NPE
1175                         throw new NullPointerException("user is null"); //NOI18N
1176                 } else if (user.getUserId() == null) {
1177                         // ... again NPE
1178                         throw new NullPointerException("user.userId is null"); //NOI18N
1179                 } else if (user.getUserId() < 1) {
1180                         // Invalid id
1181                         throw new IllegalArgumentException(MessageFormat.format("user.userId={0} is invalid", user.getUserId())); //NOI18N
1182                 } else if (user.getUserContact() == null) {
1183                         // Throw again ...
1184                         throw new NullPointerException("user.userContact is null"); //NOI18N
1185                 } else if (user.getUserContact().getContactId() == null) {
1186                         // Throw again ...
1187                         throw new NullPointerException("user.userContact.contactId is null"); //NOI18N
1188                 } else if (user.getUserContact().getContactId() < 1) {
1189                         // Throw again ...
1190                         throw new NullPointerException(MessageFormat.format("user.userContact.contactId={0} is invalid.", user.getUserContact().getContactId())); //NOI18N
1191                 }
1192
1193                 // Add/update user
1194                 this.userCache.put(user.getUserId(), user);
1195                 this.allUsers.add(user);
1196         }
1197
1198 }