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