]> 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 - 2020 Free Software Foundation
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"); //NOI18N
387                 } else if (event.getLocale() == null) {
388                         // Throw NPE again
389                         throw new NullPointerException("event.locale is null"); //NOI18N
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"); //NOI18N
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"); //NOI18N
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                         // @TODO Refacture this to avoid EJB call
613                         final String randomName = this.userBean.generateRandomUserName();
614
615                         // Set it and inivisible profile
616                         this.setUserName(randomName);
617                         this.setUserProfileMode(ProfileMode.INVISIBLE);
618
619                         // Generate random password
620                         final String randomPassword = UserLoginUtils.createRandomPassword(JobsUserWebRequestController.MINIMUM_PASSWORD_LENGTH);
621
622                         // Set random password
623                         this.setUserPassword(randomPassword);
624                         this.setUserPasswordRepeat(randomPassword);
625                 }
626
627                 // Set user name profile mode and locale
628                 user.setUserName(this.getUserName());
629                 user.setUserProfileMode(this.getUserProfileMode());
630                 user.setUserLocale(this.getLocale());
631
632                 // Is multiple registration page
633                 if ((createContactData) || (!this.featureController.isFeatureEnabled("user_register_multiple_page"))) { //NOI18N
634                         // Create contact instance
635                         final Contact contact = this.contactController.createContactInstance();
636
637                         // Set contact in user
638                         user.setUserContact(contact);
639                 }
640
641                 // Return it
642                 return user;
643         }
644
645         @Override
646         public User createUserLogin () {
647                 // Is all data set?
648                 if (this.getUserName() == null) {
649                         // Throw NPE
650                         throw new NullPointerException("userName is null"); //NOI18N
651                 } else if (this.getUserName().isEmpty()) {
652                         // Is empty
653                         throw new IllegalStateException("userName is empty."); //NOI18N
654                 }
655
656                 // Create new user instance
657                 final User user = new LoginUser();
658
659                 // Update all data ...
660                 user.setUserName(this.getUserName());
661
662                 // Return the new instance
663                 return user;
664         }
665
666         @Override
667         public String doChangePersonalData () {
668                 // This method shall only be called if the user is logged-in
669                 if (!this.userLoginController.isUserLoggedIn()) {
670                         // Not logged-in
671                         throw new IllegalStateException("User is not logged-in"); //NOI18N
672                 } else if (!this.isRequiredChangePersonalDataSet()) {
673                         // Not all required fields are set
674                         throw new FaceletException("Not all required fields are set."); //NOI18N
675                 } else if (!this.userLoginController.ifCurrentPasswordMatches()) {
676                         // Password not matching
677                         throw new FaceletException(new UserPasswordMismatchException(this.userLoginController.getLoggedInUser()));
678                 } else if (!this.featureController.isFeatureEnabled("change_user_personal_data")) { //NOI18N
679                         // Editing is not allowed
680                         throw new IllegalStateException("User tried to edit personal data."); //NOI18N
681                 }
682
683                 // Get user instance
684                 final User user = this.userLoginController.getLoggedInUser();
685
686                 // Copy contact data to contact instance
687                 this.contactController.updateContactDataFromController(user.getUserContact());
688
689                 // It should be there, so run some tests on it
690                 assert (user instanceof User) : "Instance userLoginController.loggedInUser is null"; //NOI18N
691                 assert (user.getUserId() instanceof Long) : "Instance userLoginController.loggedInUser.userId is null"; //NOI18N
692                 assert (user.getUserId() > 0) : MessageFormat.format("userLoginController.loggedInUser.userId={0} is invalid", user.getUserId()); //NOI18N
693                 assert (user.getUserContact() instanceof Contact) : "Instance userLoginController.loggedInUser.userContact is null"; //NOI18N
694                 assert (user.getUserContact().getContactId() instanceof Long) : "Instance userLoginController.userContact.contactId is null"; //NOI18N
695                 assert (user.getUserContact().getContactId() > 0) : MessageFormat.format("Instance userLoginController.userContact.contactId={0} is invalid", user.getUserContact().getContactId()); //NOI18N
696
697                 // Update all fields
698                 user.setUserProfileMode(this.getUserProfileMode());
699
700                 // Send it to the EJB
701                 final User updatedUser = this.userBean.updateUserPersonalData(user);
702
703                 // Fire event
704                 this.updatedPersonalDataEvent.fire(new UpdatedUserPersonalDataEvent(updatedUser));
705
706                 // All fine
707                 return "user_contact_data_saved"; //NOI18N
708         }
709
710         @Override
711         public User findUserById (final Long userId) throws UserNotFoundException {
712                 // Validate parameter
713                 if (null == userId) {
714                         // Throw NPE
715                         throw new NullPointerException("userId is null"); //NOI18N
716                 } else if (userId < 1) {
717                         // Throw IAE
718                         throw new IllegalArgumentException("userId=" + userId + " is invalid."); //NOI18N
719                 } else if (!this.userCache.containsKey(userId)) {
720                         // Not found
721                         throw new UserNotFoundException(userId);
722                 }
723
724                 // Get it from cache
725                 final User user = this.userCache.get(userId);
726
727                 // Return it
728                 return user;
729         }
730
731         /**
732          * Getter for filtered users list
733          * <p>
734          * @return Filtered users list
735          */
736         @SuppressWarnings ("ReturnOfCollectionOrArrayField")
737         public List<User> getFilteredUsers () {
738                 return this.filteredUsers;
739         }
740
741         /**
742          * Setter for filtered users list
743          * <p>
744          * @param filteredUsers Filtered users list
745          */
746         @SuppressWarnings ("AssignmentToCollectionOrArrayFieldFromParameter")
747         public void setFilteredUsers (final List<User> filteredUsers) {
748                 this.filteredUsers = filteredUsers;
749         }
750
751         /**
752          * Getter for user id
753          * <p>
754          * @return User id
755          */
756         public Long getUserId () {
757                 return this.userId;
758         }
759
760         /**
761          * Setter for user id
762          * <p>
763          * @param userId User id
764          */
765         public void setUserId (final Long userId) {
766                 this.userId = userId;
767         }
768
769         /**
770          * Getter for user name
771          * <p>
772          * @return User name
773          */
774         public String getUserName () {
775                 return this.userName;
776         }
777
778         /**
779          * Setter for user name
780          * <p>
781          * @param userName User name
782          */
783         public void setUserName (final String userName) {
784                 this.userName = userName;
785         }
786
787         @Override
788         public String getUserPassword () {
789                 return this.userPassword;
790         }
791
792         /**
793          * Setter for clear-text user password
794          * <p>
795          * @param userPassword Clear-text user password
796          */
797         public void setUserPassword (final String userPassword) {
798                 this.userPassword = userPassword;
799         }
800
801         /**
802          * Getter for clear-text user password repeated
803          * <p>
804          * @return Clear-text user password repeated
805          */
806         public String getUserPasswordRepeat () {
807                 return this.userPasswordRepeat;
808         }
809
810         /**
811          * Setter for clear-text user password repeated
812          * <p>
813          * @param userPasswordRepeat Clear-text user password repeated
814          */
815         public void setUserPasswordRepeat (final String userPasswordRepeat) {
816                 this.userPasswordRepeat = userPasswordRepeat;
817         }
818
819         /**
820          * Getter for user profile mode
821          * <p>
822          * @return User profile mode
823          */
824         public ProfileMode getUserProfileMode () {
825                 return this.userProfileMode;
826         }
827
828         /**
829          * Setter for user profile mode
830          * <p>
831          * @param userProfileMode User profile mode
832          */
833         public void setUserProfileMode (final ProfileMode userProfileMode) {
834                 this.userProfileMode = userProfileMode;
835         }
836
837         @Override
838         public boolean ifBothPasswordsEmptyAllowed () {
839                 // Check feature first
840                 return ((this.featureController.isFeatureEnabled("allow_user_registration_empty_password")) && //NOI18N
841                                 ((this.getUserPassword() == null) || (this.getUserPassword().isEmpty())) &&
842                                 ((this.getUserPasswordRepeat() == null) || (this.getUserPasswordRepeat().isEmpty())));
843         }
844
845         @Override
846         public boolean ifUserIdExists (final Long userId) {
847                 // Validate parameter
848                 if (null == userId) {
849                         // Throw NPE
850                         throw new NullPointerException("userId is null"); //NOI18N
851                 } else if (userId < 1) {
852                         // Throw IAE
853                         throw new IllegalArgumentException("userId=" + userId + " is invalid."); //NOI18N
854                 }
855
856                 // Check if key is there
857                 boolean isFound = this.userCache.containsKey(userId);
858
859                 // Return flag
860                 return isFound;
861         }
862
863         /**
864          * Post-initialization of this class
865          */
866         @PostConstruct
867         public void init () {
868                 // Is cache there?
869                 if (!this.userCache.iterator().hasNext()) {
870                         // Get whole list from EJB
871                         final List<User> users = this.userBean.allUsers();
872
873                         // Add all
874                         for (final User user : users) {
875                                 // Add it to cache
876                                 this.userCache.put(user.getUserId(), user);
877                                 this.userNameCache.put(user.getUserId(), user.getUserName());
878                         }
879                 }
880
881                 // Is cache filled and list is empty
882                 if ((this.userCache.iterator().hasNext()) && (this.allUsers.isEmpty())) {
883                         // Get iterator
884                         final Iterator<Cache.Entry<Long, User>> iterator = this.userCache.iterator();
885
886                         // Build up list
887                         while (iterator.hasNext()) {
888                                 // GEt next element
889                                 final Cache.Entry<Long, User> next = iterator.next();
890
891                                 // Add to list
892                                 this.allUsers.add(next.getValue());
893                         }
894
895                         // Sort list
896                         this.allUsers.sort(new Comparator<User>() {
897                                 @Override
898                                 public int compare (final User o1, final User o2) {
899                                         return o1.getUserId() > o2.getUserId() ? 1 : o1.getUserId() < o2.getUserId() ? -1 : 0;
900                                 }
901                         });
902                 }
903         }
904
905         @Override
906         public boolean isContactFound (final Contact contact) {
907                 // The contact must be valid
908                 if (null == contact) {
909                         // Throw NPE
910                         throw new NullPointerException("contact is null"); //NOI18N
911                 } else if (contact.getContactId() == null) {
912                         // Throw again ...
913                         throw new NullPointerException("contact.contactId is null"); //NOI18N
914                 } else if (contact.getContactId() < 1) {
915                         // Not valid
916                         throw new IllegalArgumentException(MessageFormat.format("contact.contactId={0} is not valid", contact.getContactId())); //NOI18N
917                 }
918
919                 // Default is not found
920                 boolean isFound = false;
921
922                 // Get iterator
923                 final Iterator<User> iterator = this.allUsers().iterator();
924
925                 // Loop through all entries
926                 while (iterator.hasNext()) {
927                         // Get user
928                         final User next = iterator.next();
929
930                         // Compare both objects
931                         if (Objects.equals(contact, next.getUserContact())) {
932                                 // Found it
933                                 isFound = true;
934                                 break;
935                         }
936                 }
937
938                 // Return status
939                 return isFound;
940         }
941
942         @Override
943         public boolean isRequiredChangePersonalDataSet () {
944                 return ((this.getUserProfileMode() != null) &&
945                                 (this.getUserName() != null) && (!this.getUserName().isEmpty()) &&
946                                 (this.contactController.isRequiredChangePersonalDataSet()));
947         }
948
949         @Override
950         public boolean isRequiredPersonalDataSet () {
951                 if (this.featureController.isFeatureEnabled("user_register_multiple_page")) { //NOI18N
952                         // Multiple registration page
953                         return this.contactController.isRequiredPersonalDataSet();
954                 } else {
955                         // Single registration page
956                         return (((this.getUserName() != null) || (!this.isUserNameRequired())) &&
957                                         (this.getUserProfileMode() != null) &&
958                                         (this.contactController.isRequiredPersonalDataSet()) &&
959                                         (this.getUserPassword() != null) &&
960                                         (this.getUserPasswordRepeat() != null));
961                 }
962         }
963
964         @Override
965         public boolean isSamePasswordEntered () {
966                 return ((!this.getUserPassword().isEmpty()) && (Objects.equals(this.getUserPassword(), this.getUserPasswordRepeat())));
967         }
968
969         @Override
970         public boolean isUserIdEmpty () {
971                 return ((this.getUserId() == null) || (this.getUserId() == 0));
972         }
973
974         @Override
975         public boolean isUserNameRegistered (final User user) {
976                 return ((this.userNameCache instanceof List) && (this.userNameCache.containsKey(user.getUserId())));
977         }
978
979         @Override
980         public boolean isUserNameRequired () {
981                 // Get context parameter
982                 final String contextParameter = FacesContext.getCurrentInstance().getExternalContext().getInitParameter("is_user_login_require_user_name"); //NOI18N
983
984                 // Is it set?
985                 final boolean isRequired = ((contextParameter instanceof String) && (contextParameter.toLowerCase().equals("true"))); //NOI18N
986
987                 // Return value
988                 return isRequired;
989         }
990
991         @Override
992         public User lookupUserByEmailAddress (final String emailAddress) throws UserEmailAddressNotFoundException {
993                 // Parameter must be valid
994                 if (null == emailAddress) {
995                         // Throw NPE
996                         throw new NullPointerException("emailAddress is null"); //NOI18N
997                 } else if (emailAddress.isEmpty()) {
998                         // Not valid
999                         throw new IllegalArgumentException("emailAddress is empty"); //NOI18N
1000                 }
1001
1002                 // Init variable
1003                 User user = null;
1004
1005                 // Try to lookup it in visible user list
1006                 for (final Iterator<Cache.Entry<Long, User>> iterator = this.userCache.iterator(); iterator.hasNext();) {
1007                         // Get next user
1008                         final Cache.Entry<Long, User> next = iterator.next();
1009
1010                         // Contact should be set
1011                         if (next.getValue().getUserContact() == null) {
1012                                 // Contact is null
1013                                 throw new NullPointerException(MessageFormat.format("next.userContact is null for user id {0}", next.getKey())); //NOI18N
1014                         } else if (next.getValue().getUserContact().getContactEmailAddress() == null) {
1015                                 // Email address should be set
1016                                 throw new NullPointerException(MessageFormat.format("next.userContact.contactEmailAddress is null for user id {0}", next.getKey())); //NOI18N
1017                         }
1018
1019                         // Is the email address found?
1020                         if (Objects.equals(next.getValue().getUserContact().getContactEmailAddress(), emailAddress)) {
1021                                 // Copy to other variable
1022                                 user = next.getValue();
1023                                 break;
1024                         }
1025                 }
1026
1027                 // Is it still null?
1028                 if (null == user) {
1029                         // Not visible for the current user
1030                         throw new UserEmailAddressNotFoundException(emailAddress);
1031                 }
1032
1033                 // Return it
1034                 return user;
1035         }
1036
1037         @Override
1038         public User lookupUserById (final Long userId) throws UserNotFoundException {
1039                 // Parameter must be valid
1040                 if (null == userId) {
1041                         // Throw NPE
1042                         throw new NullPointerException("userId is null"); //NOI18N
1043                 } else if (userId < 1) {
1044                         // Not valid
1045                         throw new IllegalArgumentException(MessageFormat.format("userId={0} is not valid.", userId)); //NOI18N
1046                 }
1047
1048                 // Init variable
1049                 User user = null;
1050
1051                 // Try to lookup it in visible user list
1052                 for (final Iterator<Cache.Entry<Long, User>> iterator = this.userCache.iterator(); iterator.hasNext();) {
1053                         // Get next user
1054                         final Cache.Entry<Long, User> next = iterator.next();
1055
1056                         // Is the user id found?
1057                         if (Objects.equals(next.getKey(), userId)) {
1058                                 // Copy to other variable
1059                                 user = next.getValue();
1060                                 break;
1061                         }
1062                 }
1063
1064                 // Is it still null?
1065                 if (null == user) {
1066                         // Not visible for the current user
1067                         throw new UserNotFoundException(userId);
1068                 }
1069
1070                 // Return it
1071                 return user;
1072         }
1073
1074         /**
1075          * Adds user's name to bean's internal list. It also updates the public user
1076          * list if the user has decided to have a public account,
1077          * <p>
1078          * @param user User instance
1079          */
1080         private void addUserName (final User user) {
1081                 // Make sure the entry is not added yet
1082                 if (this.userNameCache.containsKey(user.getUserId())) {
1083                         // Abort here
1084                         throw new IllegalArgumentException(MessageFormat.format("User name {0} already added.", user.getUserName())); //NOI18N
1085                 }
1086
1087                 // Add user name
1088                 this.userNameCache.put(user.getUserId(), user.getUserName());
1089         }
1090
1091         /**
1092          * Clears this bean
1093          */
1094         private void clear () {
1095                 // Clear all data
1096                 // - personal data
1097                 this.setUserId(null);
1098                 this.setUserProfileMode(null);
1099
1100                 // - other data
1101                 this.clearUserName();
1102                 this.clearUserPasswords();
1103                 this.setLocale(null);
1104         }
1105
1106         /**
1107          * Clears user name
1108          */
1109         private void clearUserName () {
1110                 // Clear it
1111                 this.setUserName(null);
1112         }
1113
1114         /**
1115          * Clears both user passwords
1116          */
1117         private void clearUserPasswords () {
1118                 // Clear both
1119                 this.setUserPassword(null);
1120                 this.setUserPasswordRepeat(null);
1121         }
1122
1123         /**
1124          * Copies given user into the controller
1125          * <p>
1126          * @param user User instance
1127          */
1128         private void copyUser (final User user) {
1129                 // Make sure the instance is valid
1130                 if (null == user) {
1131                         // Throw NPE
1132                         throw new NullPointerException("user is null"); //NOI18N
1133                 } else if (user.getUserContact() == null) {
1134                         // Throw again ...
1135                         throw new NullPointerException("user.userContact is null"); //NOI18N
1136                 }
1137
1138                 // Copy all fields:
1139                 // - base data
1140                 this.setUserId(user.getUserId());
1141                 this.setUserProfileMode(user.getUserProfileMode());
1142         }
1143
1144         /**
1145          * Getter for locale instance
1146          * <p>
1147          * @return Locale instance
1148          */
1149         private Locale getLocale () {
1150                 return this.locale;
1151         }
1152
1153         /**
1154          * Setter for locale instance
1155          * <p>
1156          * @param locale Locale instance
1157          */
1158         private void setLocale (final Locale locale) {
1159                 this.locale = locale;
1160         }
1161
1162         /**
1163          * Removes user from all lists
1164          * <p>
1165          * @param user User to remove
1166          */
1167         private void removeFromList (final User user) {
1168                 // The user should be valid
1169                 if (null == user) {
1170                         // Throw NPE
1171                         throw new NullPointerException("user is null"); //NOI18N
1172                 } else if (user.getUserId() == null) {
1173                         // ... again NPE
1174                         throw new NullPointerException("user.userId is null"); //NOI18N
1175                 } else if (user.getUserId() < 1) {
1176                         // Invalid id
1177                         throw new IllegalArgumentException(MessageFormat.format("user.userId={0} is invalid", user.getUserId())); //NOI18N
1178                 }
1179
1180                 // Remove it from lists
1181                 this.userCache.remove(user.getUserId());
1182                 this.allUsers.remove(user);
1183
1184                 // Remove name from list
1185                 this.userNameCache.remove(user.getUserId());
1186         }
1187
1188         /**
1189          * Updates list with given user instance
1190          * <p>
1191          * @param user User instance
1192          */
1193         private void updateList (final User user) {
1194                 // The user should be valid
1195                 if (null == user) {
1196                         // Throw NPE
1197                         throw new NullPointerException("user is null"); //NOI18N
1198                 } else if (user.getUserId() == null) {
1199                         // ... again NPE
1200                         throw new NullPointerException("user.userId is null"); //NOI18N
1201                 } else if (user.getUserId() < 1) {
1202                         // Invalid id
1203                         throw new IllegalArgumentException(MessageFormat.format("user.userId={0} is invalid", user.getUserId())); //NOI18N
1204                 } else if (user.getUserContact() == null) {
1205                         // Throw again ...
1206                         throw new NullPointerException("user.userContact is null"); //NOI18N
1207                 } else if (user.getUserContact().getContactId() == null) {
1208                         // Throw again ...
1209                         throw new NullPointerException("user.userContact.contactId is null"); //NOI18N
1210                 } else if (user.getUserContact().getContactId() < 1) {
1211                         // Throw again ...
1212                         throw new NullPointerException(MessageFormat.format("user.userContact.contactId={0} is invalid.", user.getUserContact().getContactId())); //NOI18N
1213                 }
1214
1215                 // Add/update user
1216                 this.userCache.put(user.getUserId(), user);
1217                 this.allUsers.add(user);
1218         }
1219
1220 }