From a436b3dc19312734cc7908482c3279d04a30995b Mon Sep 17 00:00:00 2001 From: Ian Hlavats Date: Wed, 5 Jun 2013 15:28:23 +0200 Subject: [PATCH] First commit! This is the initial commit for the source code for my book PrimeFaces Start by Packt Publishing. --- primefaces-webapp/.classpath | 42 ++ primefaces-webapp/.euml2 | 7 + primefaces-webapp/.factorypath | 5 + primefaces-webapp/.gitignore | 1 + .../main/webapp/WEB-INF/faces-config.pageflow | 8 + primefaces-webapp/.project | 42 ++ primefaces-webapp/.settings/.jsdtscope | 12 + .../.settings/org.eclipse.jdt.apt.core.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 13 + .../.settings/org.eclipse.jpt.core.prefs | 3 + .../.settings/org.eclipse.m2e.core.prefs | 4 + .../org.eclipse.wst.common.component | 14 + ...se.wst.common.project.facet.core.prefs.xml | 17 + ....eclipse.wst.common.project.facet.core.xml | 10 + ...rg.eclipse.wst.jsdt.ui.superType.container | 1 + .../org.eclipse.wst.jsdt.ui.superType.name | 1 + primefaces-webapp/.umlproject | 7 + primefaces-webapp/pom.xml | 270 ++++++++++ .../controller/AbstractController.java | 105 ++++ .../mycompany/controller/ChartController.java | 175 ++++++ .../mycompany/controller/ChatController.java | 94 ++++ .../controller/ContactsController.java | 158 ++++++ .../controller/ContentController.java | 122 +++++ .../controller/DashboardController.java | 91 ++++ .../mycompany/controller/EventController.java | 326 +++++++++++ .../mycompany/controller/LoginController.java | 132 +++++ .../controller/MindMapController.java | 126 +++++ .../controller/SearchController.java | 308 +++++++++++ .../controller/SignupController.java | 146 +++++ .../mycompany/controller/UserController.java | 131 +++++ .../mycompany/controller/VenueController.java | 138 +++++ .../com/mycompany/convert/CityConverter.java | 64 +++ .../mycompany/convert/CountryConverter.java | 64 +++ .../convert/EditableStateConverter.java | 77 +++ .../com/mycompany/convert/StateConverter.java | 63 +++ .../com/mycompany/convert/UserConverter.java | 64 +++ .../com/mycompany/convert/VenueConverter.java | 64 +++ .../ConversationExceptionFilter.java | 111 ++++ .../com/mycompany/lifecycle/Destroyed.java | 42 ++ .../com/mycompany/lifecycle/Initialized.java | 42 ++ .../lifecycle/SecurityPhaseListener.java | 88 +++ .../ServletContextLifecycleNotifier.java | 58 ++ .../com/mycompany/model/AbstractEntity.java | 88 +++ .../com/mycompany/model/AbstractEntity_.java | 14 + .../java/com/mycompany/model/ActiveUsers.java | 48 ++ .../main/java/com/mycompany/model/City.java | 91 ++++ .../main/java/com/mycompany/model/City_.java | 15 + .../java/com/mycompany/model/Content.java | 101 ++++ .../java/com/mycompany/model/Content_.java | 16 + .../java/com/mycompany/model/Country.java | 103 ++++ .../java/com/mycompany/model/Country_.java | 16 + .../java/com/mycompany/model/Credentials.java | 58 ++ .../main/java/com/mycompany/model/Event.java | 162 ++++++ .../com/mycompany/model/EventAttendance.java | 100 ++++ .../com/mycompany/model/EventAttendance_.java | 15 + .../java/com/mycompany/model/EventType.java | 47 ++ .../main/java/com/mycompany/model/Event_.java | 22 + .../main/java/com/mycompany/model/Gender.java | 47 ++ .../main/java/com/mycompany/model/Idea.java | 119 ++++ .../main/java/com/mycompany/model/Idea_.java | 18 + .../com/mycompany/model/ProvinceState.java | 94 ++++ .../com/mycompany/model/ProvinceState_.java | 16 + .../com/mycompany/model/RelationshipType.java | 47 ++ .../main/java/com/mycompany/model/User.java | 243 +++++++++ .../com/mycompany/model/UserRelationship.java | 83 +++ .../mycompany/model/UserRelationship_.java | 14 + .../main/java/com/mycompany/model/User_.java | 29 + .../main/java/com/mycompany/model/Venue.java | 180 +++++++ .../main/java/com/mycompany/model/Venue_.java | 20 + .../com/mycompany/service/ChartService.java | 50 ++ .../com/mycompany/service/ContentService.java | 55 ++ .../com/mycompany/service/CountryService.java | 150 ++++++ .../com/mycompany/service/EventService.java | 131 +++++ .../com/mycompany/service/IdeaService.java | 76 +++ .../com/mycompany/service/UserService.java | 130 +++++ .../com/mycompany/service/VenueService.java | 72 +++ .../service/impl/AbstractService.java | 39 ++ .../service/impl/ChartServiceImpl.java | 48 ++ .../service/impl/ContentServiceImpl.java | 65 +++ .../service/impl/CountryServiceImpl.java | 226 ++++++++ .../service/impl/EventServiceImpl.java | 153 ++++++ .../service/impl/IdeaServiceImpl.java | 91 ++++ .../service/impl/UserServiceImpl.java | 133 +++++ .../service/impl/VenueServiceImpl.java | 72 +++ .../java/com/mycompany/util/FacesUtils.java | 60 +++ .../main/java/com/mycompany/util/Queries.java | 101 ++++ .../java/com/mycompany/util/UserSession.java | 86 +++ .../mycompany/websocket/DefaultPushRule.java | 78 +++ .../src/main/resources/META-INF/auth.conf | 4 + .../main/resources/META-INF/persistence.xml | 17 + .../src/main/resources/cities.txt | 14 + .../src/main/resources/countries.txt | 244 +++++++++ .../src/main/webapp/WEB-INF/beans.xml | 1 + .../WEB-INF/dialogs/addShowDialog.xhtml | 56 ++ .../webapp/WEB-INF/dialogs/chatDialog.xhtml | 59 ++ .../WEB-INF/dialogs/newContactDialog.xhtml | 44 ++ .../WEB-INF/dialogs/validationDialog.xhtml | 18 + .../src/main/webapp/WEB-INF/faces-config.xml | 29 + .../webapp/WEB-INF/glassfish-resources.xml | 33 ++ .../main/webapp/WEB-INF/mycompany.taglib.xml | 15 + .../main/webapp/WEB-INF/templates/main.xhtml | 57 ++ .../src/main/webapp/WEB-INF/web.xml | 210 ++++++++ primefaces-webapp/src/main/webapp/about.xhtml | 40 ++ primefaces-webapp/src/main/webapp/error.xhtml | 16 + primefaces-webapp/src/main/webapp/ideas.xhtml | 64 +++ primefaces-webapp/src/main/webapp/index.xhtml | 53 ++ .../src/main/webapp/mobile/index.xhtml | 510 ++++++++++++++++++ .../webapp/protected/members/contacts.xhtml | 39 ++ .../webapp/protected/members/dashboard.xhtml | 103 ++++ .../main/webapp/protected/members/index.xhtml | 38 ++ .../webapp/protected/members/reviews.xhtml | 54 ++ .../main/webapp/protected/members/shows.xhtml | 36 ++ .../webapp/protected/members/venues.xhtml | 98 ++++ .../src/main/webapp/resources/css/main.css | 129 +++++ .../main/webapp/resources/images/about.png | Bin 0 -> 6335 bytes .../webapp/resources/images/add-user-icon.png | Bin 0 -> 10401 bytes .../src/main/webapp/resources/images/home.png | Bin 0 -> 6809 bytes .../main/webapp/resources/images/members.png | Bin 0 -> 6131 bytes .../resources/images/offline-user-icon.png | Bin 0 -> 8886 bytes .../main/webapp/resources/images/privacy.png | Bin 0 -> 5039 bytes .../webapp/resources/images/showtime_logo.png | Bin 0 -> 13406 bytes .../webapp/resources/images/showtimes.png | Bin 0 -> 5912 bytes .../main/webapp/resources/images/status.gif | Bin 0 -> 9427 bytes .../webapp/resources/images/user-icon.png | Bin 0 -> 9123 bytes .../src/main/webapp/resources/images/user.png | Bin 0 -> 4683 bytes .../src/main/webapp/resources/js/main.js | 19 + .../resources/mycompany/contactList.xhtml | 69 +++ .../src/main/webapp/showtimes.xhtml | 121 +++++ .../src/main/webapp/signup.xhtml | 81 +++ primefaces-webapp/src/test/java/.gitignore | 4 + .../src/test/resources/.gitignore | 4 + 131 files changed, 9151 insertions(+) create mode 100644 primefaces-webapp/.classpath create mode 100644 primefaces-webapp/.euml2 create mode 100644 primefaces-webapp/.factorypath create mode 100644 primefaces-webapp/.gitignore create mode 100644 primefaces-webapp/.metadata/src/main/webapp/WEB-INF/faces-config.pageflow create mode 100644 primefaces-webapp/.project create mode 100644 primefaces-webapp/.settings/.jsdtscope create mode 100644 primefaces-webapp/.settings/org.eclipse.jdt.apt.core.prefs create mode 100644 primefaces-webapp/.settings/org.eclipse.jdt.core.prefs create mode 100644 primefaces-webapp/.settings/org.eclipse.jpt.core.prefs create mode 100644 primefaces-webapp/.settings/org.eclipse.m2e.core.prefs create mode 100644 primefaces-webapp/.settings/org.eclipse.wst.common.component create mode 100644 primefaces-webapp/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml create mode 100644 primefaces-webapp/.settings/org.eclipse.wst.common.project.facet.core.xml create mode 100644 primefaces-webapp/.settings/org.eclipse.wst.jsdt.ui.superType.container create mode 100644 primefaces-webapp/.settings/org.eclipse.wst.jsdt.ui.superType.name create mode 100644 primefaces-webapp/.umlproject create mode 100644 primefaces-webapp/pom.xml create mode 100644 primefaces-webapp/src/main/java/com/mycompany/controller/AbstractController.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/controller/ChartController.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/controller/ChatController.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/controller/ContactsController.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/controller/ContentController.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/controller/DashboardController.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/controller/EventController.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/controller/LoginController.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/controller/MindMapController.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/controller/SearchController.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/controller/SignupController.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/controller/UserController.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/controller/VenueController.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/convert/CityConverter.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/convert/CountryConverter.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/convert/EditableStateConverter.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/convert/StateConverter.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/convert/UserConverter.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/convert/VenueConverter.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/lifecycle/ConversationExceptionFilter.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/lifecycle/Destroyed.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/lifecycle/Initialized.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/lifecycle/SecurityPhaseListener.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/lifecycle/ServletContextLifecycleNotifier.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/AbstractEntity.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/AbstractEntity_.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/ActiveUsers.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/City.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/City_.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/Content.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/Content_.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/Country.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/Country_.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/Credentials.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/Event.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/EventAttendance.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/EventAttendance_.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/EventType.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/Event_.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/Gender.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/Idea.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/Idea_.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/ProvinceState.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/ProvinceState_.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/RelationshipType.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/User.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/UserRelationship.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/UserRelationship_.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/User_.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/Venue.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/model/Venue_.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/service/ChartService.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/service/ContentService.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/service/CountryService.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/service/EventService.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/service/IdeaService.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/service/UserService.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/service/VenueService.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/service/impl/AbstractService.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/service/impl/ChartServiceImpl.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/service/impl/ContentServiceImpl.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/service/impl/CountryServiceImpl.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/service/impl/EventServiceImpl.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/service/impl/IdeaServiceImpl.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/service/impl/UserServiceImpl.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/service/impl/VenueServiceImpl.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/util/FacesUtils.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/util/Queries.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/util/UserSession.java create mode 100644 primefaces-webapp/src/main/java/com/mycompany/websocket/DefaultPushRule.java create mode 100644 primefaces-webapp/src/main/resources/META-INF/auth.conf create mode 100644 primefaces-webapp/src/main/resources/META-INF/persistence.xml create mode 100644 primefaces-webapp/src/main/resources/cities.txt create mode 100644 primefaces-webapp/src/main/resources/countries.txt create mode 100644 primefaces-webapp/src/main/webapp/WEB-INF/beans.xml create mode 100644 primefaces-webapp/src/main/webapp/WEB-INF/dialogs/addShowDialog.xhtml create mode 100644 primefaces-webapp/src/main/webapp/WEB-INF/dialogs/chatDialog.xhtml create mode 100644 primefaces-webapp/src/main/webapp/WEB-INF/dialogs/newContactDialog.xhtml create mode 100644 primefaces-webapp/src/main/webapp/WEB-INF/dialogs/validationDialog.xhtml create mode 100644 primefaces-webapp/src/main/webapp/WEB-INF/faces-config.xml create mode 100644 primefaces-webapp/src/main/webapp/WEB-INF/glassfish-resources.xml create mode 100644 primefaces-webapp/src/main/webapp/WEB-INF/mycompany.taglib.xml create mode 100644 primefaces-webapp/src/main/webapp/WEB-INF/templates/main.xhtml create mode 100644 primefaces-webapp/src/main/webapp/WEB-INF/web.xml create mode 100644 primefaces-webapp/src/main/webapp/about.xhtml create mode 100644 primefaces-webapp/src/main/webapp/error.xhtml create mode 100644 primefaces-webapp/src/main/webapp/ideas.xhtml create mode 100644 primefaces-webapp/src/main/webapp/index.xhtml create mode 100644 primefaces-webapp/src/main/webapp/mobile/index.xhtml create mode 100644 primefaces-webapp/src/main/webapp/protected/members/contacts.xhtml create mode 100644 primefaces-webapp/src/main/webapp/protected/members/dashboard.xhtml create mode 100644 primefaces-webapp/src/main/webapp/protected/members/index.xhtml create mode 100644 primefaces-webapp/src/main/webapp/protected/members/reviews.xhtml create mode 100644 primefaces-webapp/src/main/webapp/protected/members/shows.xhtml create mode 100644 primefaces-webapp/src/main/webapp/protected/members/venues.xhtml create mode 100644 primefaces-webapp/src/main/webapp/resources/css/main.css create mode 100755 primefaces-webapp/src/main/webapp/resources/images/about.png create mode 100644 primefaces-webapp/src/main/webapp/resources/images/add-user-icon.png create mode 100755 primefaces-webapp/src/main/webapp/resources/images/home.png create mode 100755 primefaces-webapp/src/main/webapp/resources/images/members.png create mode 100644 primefaces-webapp/src/main/webapp/resources/images/offline-user-icon.png create mode 100755 primefaces-webapp/src/main/webapp/resources/images/privacy.png create mode 100644 primefaces-webapp/src/main/webapp/resources/images/showtime_logo.png create mode 100755 primefaces-webapp/src/main/webapp/resources/images/showtimes.png create mode 100644 primefaces-webapp/src/main/webapp/resources/images/status.gif create mode 100644 primefaces-webapp/src/main/webapp/resources/images/user-icon.png create mode 100644 primefaces-webapp/src/main/webapp/resources/images/user.png create mode 100644 primefaces-webapp/src/main/webapp/resources/js/main.js create mode 100644 primefaces-webapp/src/main/webapp/resources/mycompany/contactList.xhtml create mode 100644 primefaces-webapp/src/main/webapp/showtimes.xhtml create mode 100644 primefaces-webapp/src/main/webapp/signup.xhtml create mode 100644 primefaces-webapp/src/test/java/.gitignore create mode 100644 primefaces-webapp/src/test/resources/.gitignore diff --git a/primefaces-webapp/.classpath b/primefaces-webapp/.classpath new file mode 100644 index 0000000..0d6bd5f --- /dev/null +++ b/primefaces-webapp/.classpath @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/primefaces-webapp/.euml2 b/primefaces-webapp/.euml2 new file mode 100644 index 0000000..e348ac9 --- /dev/null +++ b/primefaces-webapp/.euml2 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/primefaces-webapp/.factorypath b/primefaces-webapp/.factorypath new file mode 100644 index 0000000..2ddac7b --- /dev/null +++ b/primefaces-webapp/.factorypath @@ -0,0 +1,5 @@ + + + + + + + + + + + + diff --git a/primefaces-webapp/.project b/primefaces-webapp/.project new file mode 100644 index 0000000..cfa0d1f --- /dev/null +++ b/primefaces-webapp/.project @@ -0,0 +1,42 @@ + + + primefaces-webapp + + + + + + org.eclipse.wst.jsdt.core.javascriptValidator + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/primefaces-webapp/.settings/.jsdtscope b/primefaces-webapp/.settings/.jsdtscope new file mode 100644 index 0000000..b46b920 --- /dev/null +++ b/primefaces-webapp/.settings/.jsdtscope @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/primefaces-webapp/.settings/org.eclipse.jdt.apt.core.prefs b/primefaces-webapp/.settings/org.eclipse.jdt.apt.core.prefs new file mode 100644 index 0000000..7d52ece --- /dev/null +++ b/primefaces-webapp/.settings/org.eclipse.jdt.apt.core.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.apt.aptEnabled=true +org.eclipse.jdt.apt.genSrcDir=.apt_generated +org.eclipse.jdt.apt.reconcileEnabled=true diff --git a/primefaces-webapp/.settings/org.eclipse.jdt.core.prefs b/primefaces-webapp/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..66c3cd6 --- /dev/null +++ b/primefaces-webapp/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,13 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.processAnnotations=enabled +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/primefaces-webapp/.settings/org.eclipse.jpt.core.prefs b/primefaces-webapp/.settings/org.eclipse.jpt.core.prefs new file mode 100644 index 0000000..7f6edff --- /dev/null +++ b/primefaces-webapp/.settings/org.eclipse.jpt.core.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +org.eclipse.jpt.core.platform=generic2_0 +org.eclipse.jpt.jpa.core.discoverAnnotatedClasses=true diff --git a/primefaces-webapp/.settings/org.eclipse.m2e.core.prefs b/primefaces-webapp/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/primefaces-webapp/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/primefaces-webapp/.settings/org.eclipse.wst.common.component b/primefaces-webapp/.settings/org.eclipse.wst.common.component new file mode 100644 index 0000000..4dd5c78 --- /dev/null +++ b/primefaces-webapp/.settings/org.eclipse.wst.common.component @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/primefaces-webapp/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml b/primefaces-webapp/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml new file mode 100644 index 0000000..d564e65 --- /dev/null +++ b/primefaces-webapp/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/primefaces-webapp/.settings/org.eclipse.wst.common.project.facet.core.xml b/primefaces-webapp/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 0000000..d125834 --- /dev/null +++ b/primefaces-webapp/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/primefaces-webapp/.settings/org.eclipse.wst.jsdt.ui.superType.container b/primefaces-webapp/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100644 index 0000000..3bd5d0a --- /dev/null +++ b/primefaces-webapp/.settings/org.eclipse.wst.jsdt.ui.superType.container @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/primefaces-webapp/.settings/org.eclipse.wst.jsdt.ui.superType.name b/primefaces-webapp/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100644 index 0000000..05bd71b --- /dev/null +++ b/primefaces-webapp/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Window \ No newline at end of file diff --git a/primefaces-webapp/.umlproject b/primefaces-webapp/.umlproject new file mode 100644 index 0000000..e348ac9 --- /dev/null +++ b/primefaces-webapp/.umlproject @@ -0,0 +1,7 @@ + + + + + + + diff --git a/primefaces-webapp/pom.xml b/primefaces-webapp/pom.xml new file mode 100644 index 0000000..4812a4b --- /dev/null +++ b/primefaces-webapp/pom.xml @@ -0,0 +1,270 @@ + + 4.0.0 + com.mycompany + primefaces-webapp + 0.0.1-SNAPSHOT + war + + + prime-repo + PrimeFaces Maven Repository + http://repository.primefaces.org + default + + + codehaus-snapshots + http://snapshots.repository.codehaus.org + + + jboss-public-repository-group + JBoss Public Maven Repository Group + https://repository.jboss.org/nexus/content/groups/public-jboss/ + default + + + + + + + org.primefaces + primefaces + 3.5 + + + org.primefaces + primefaces-mobile + 1.0.0-SNAPSHOT + + + org.glassfish + javax.faces + 2.1.10 + + + + + + org.atmosphere + atmosphere-runtime + 1.0.10 + + + slf4j-api + org.slf4j + + + + + + + rome + rome + 1.0 + + + + + commons-fileupload + commons-fileupload + 1.2.1 + + + + + + + org.primefaces.themes + all-themes + 1.0.9 + + + + + org.hibernate + hibernate-jpamodelgen + 1.0.0.Final + provided + + + org.hibernate + hibernate-entitymanager + 3.5.1-Final + + + org.slf4j + slf4j-simple + 1.5.8 + + + javax.validation + validation-api + 1.0.0.GA + + + org.hibernate + hibernate-validator + 4.0.2.GA + + + slf4j-api + org.slf4j + + + + + + + org.jboss.spec + jboss-javaee-6.0 + 1.0.0.Final + pom + provided + + + + + commons-lang + commons-lang + 2.6 + + + + + org.codehaus.jackson + jackson-mapper-asl + 1.9.11 + + + + mysql + mysql-connector-java + 5.1.22 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + true + lines,vars,source + -proc:none + + + + + run-annotation-processors-only + generate-sources + + -proc:only + + **/model/*.java + + + + **/model/*_.java + **/model/Abstract*.java + + + + compile + + + + + + org.bsc.maven + maven-processor-plugin + 2.1.1 + + + process + + process + + generate-sources + + UTF-8 + + src/main/java + + + + + + maven-clean-plugin + 2.4.1 + + + + ../${project.artifactId}/src/main/java + + **/*_.java + + + + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.codehaus.mojo + build-helper-maven-plugin + [1.3,) + + add-source + + + + + + + + + org.bsc.maven + maven-processor-plugin + [2.1.0,) + + process + + + + + + + + + + + + + + \ No newline at end of file diff --git a/primefaces-webapp/src/main/java/com/mycompany/controller/AbstractController.java b/primefaces-webapp/src/main/java/com/mycompany/controller/AbstractController.java new file mode 100644 index 0000000..0ef330e --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/controller/AbstractController.java @@ -0,0 +1,105 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.controller; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; + +import javax.faces.application.FacesMessage; +import javax.faces.bean.ManagedProperty; +import javax.faces.context.FacesContext; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.mycompany.model.User; +import com.mycompany.util.UserSession; + +/** + * Base class for controller objects. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +/** + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +public abstract class AbstractController implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -4862069600034765532L; + + protected transient Logger logger = LoggerFactory.getLogger(getClass()); + + @ManagedProperty(value = "#{userSession}") + protected UserSession userSession; + + /** + * Adds a global error message to the response. + * + * @param summary + * The message summary. + */ + protected void addErrorMessage(String summary) { + FacesMessage msg = new FacesMessage(summary); + msg.setSeverity(FacesMessage.SEVERITY_ERROR); + FacesContext.getCurrentInstance().addMessage(null, msg); + } + + /** + * Convenience method to return the logged in user. + * + * @return A {@link User} object. + */ + protected User getLoggedInUser() { + User user = null; + if (userSession != null) { + user = userSession.getUser(); + } + return user; + } + + /** + * Handle deserialization from passivated session and restore transient + * fields. + * + * @param ois + * The ObjectInputStream object. + * @throws IOException + * @throws ClassNotFoundException + */ + private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + ois.defaultReadObject(); + logger = LoggerFactory.getLogger(getClass()); + } + + public void setUserSession(UserSession userSession) { + this.userSession = userSession; + } +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/controller/ChartController.java b/primefaces-webapp/src/main/java/com/mycompany/controller/ChartController.java new file mode 100644 index 0000000..826c7e6 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/controller/ChartController.java @@ -0,0 +1,175 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.controller; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.faces.application.FacesMessage; +import javax.faces.bean.ManagedBean; +import javax.faces.bean.ManagedProperty; +import javax.faces.bean.ViewScoped; +import javax.faces.context.FacesContext; +import javax.faces.event.ComponentSystemEvent; +import javax.persistence.EntityManager; + +import org.primefaces.event.ItemSelectEvent; +import org.primefaces.model.chart.CartesianChartModel; +import org.primefaces.model.chart.ChartSeries; +import org.primefaces.model.chart.PieChartModel; + +import com.mycompany.model.Gender; +import com.mycompany.model.User; +import com.mycompany.service.ChartService; +import com.mycompany.service.UserService; + +/** + * Controller class for charts. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@ManagedBean +@ViewScoped +public class ChartController extends AbstractController { + + /** + * + */ + private static final long serialVersionUID = -1999623701433215717L; + + private CartesianChartModel barChartModel; + + @ManagedProperty(value = "#{chartService}") + private ChartService chartService; + + @ManagedProperty(value = "#{userService}") + private UserService userService; + + private PieChartModel pieChartModel; + + private ChartSeries buildChartSeries(List results, String label) { + ChartSeries series = new ChartSeries(); + series.setLabel(label); + // calculate monthly totals + SimpleDateFormat sdf = new SimpleDateFormat("MMM/yy"); + List months = new ArrayList(); + Map monthTotals = new HashMap(); + for (Object[] result : results) { + Date date = (Date) result[0]; + Long count = (Long) result[1]; + String month = sdf.format(date); + if (!months.contains(month)) { + months.add(month); + } + Long total = monthTotals.get(month); + if (total == null) { + total = 0L; + } + monthTotals.put(month, count + total); + } + // add the data to the chart series + for (String month : months) { + series.set(month, monthTotals.get(month).intValue()); + } + return series; + } + + private void createBarChartModel() { + List maleResults = chartService.findEventAttendanceByGender(Gender.MALE); + List femaleResults = chartService.findEventAttendanceByGender(Gender.FEMALE); + if (maleResults.isEmpty() && femaleResults.isEmpty()) { + return; + } + barChartModel = new CartesianChartModel(); + ChartSeries males = buildChartSeries(maleResults, "Male"); + ChartSeries females = buildChartSeries(femaleResults, "Female"); + barChartModel.addSeries(males); + barChartModel.addSeries(females); + } + + private void createPieModel() { + pieChartModel = new PieChartModel(); + List users = userService.findUsers(); + for (User user : users) { + Integer count = user.getClickCount(); + if (count == null) { + count = 0; + } + String username = user.getUsername(); + pieChartModel.getData().put(username, count); + } + } + + public CartesianChartModel getBarChartModel() { + return barChartModel; + } + + /** + * This method builds a {@link PieChartModel} of active user click counts. + * + * @return A PieChartModel. + */ + public PieChartModel getLivePieModel() { + return pieChartModel; + } + + public PieChartModel getPieChartModel() { + return pieChartModel; + } + + /** + * Initializes the pie chart and bar chart models from data in our database. + * We can't do this in the constructor because the {@link EntityManager} is + * injected after the object is constructed, so this method handles the + * initialization during the pre-render view event. + * + * @param event + * The view event. + */ + public void init(ComponentSystemEvent event) { + createBarChartModel(); + createPieModel(); + } + + public void itemSelect(ItemSelectEvent event) { + FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Item selected", + "Item Index: " + event.getItemIndex() + ", Series Index:" + event.getSeriesIndex()); + + FacesContext.getCurrentInstance().addMessage(null, msg); + } + + public void setChartService(ChartService chartService) { + this.chartService = chartService; + } + + public void setUserService(UserService userService) { + this.userService = userService; + } +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/controller/ChatController.java b/primefaces-webapp/src/main/java/com/mycompany/controller/ChatController.java new file mode 100644 index 0000000..7e7a7a9 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/controller/ChatController.java @@ -0,0 +1,94 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.controller; + +import javax.faces.bean.ManagedBean; +import javax.faces.bean.ViewScoped; +import javax.inject.Inject; + +import org.primefaces.context.RequestContext; +import org.primefaces.push.PushContext; +import org.primefaces.push.PushContextFactory; + +import com.mycompany.model.ActiveUsers; +import com.mycompany.model.User; + +/** + * Controller class for chat functionality. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@ManagedBean +@ViewScoped +public class ChatController extends AbstractController { + + /** + * + */ + private static final long serialVersionUID = -2706002474535643832L; + + private String globalMessage; + + private static final String CHANNEL = "/chat/"; + + @Inject + private ActiveUsers activeUsers; + + private final PushContext pushContext = PushContextFactory.getDefault().getPushContext(); + + public String getGlobalMessage() { + return globalMessage; + } + + public void beginChat() { + User user = getLoggedInUser(); + RequestContext requestContext = RequestContext.getCurrentInstance(); + requestContext.execute("socketWidget.cfg.request.trackMessageLength = true;"); + requestContext.execute("socketWidget.connect('/" + user.getUsername() + "')"); + pushContext.push(CHANNEL + "*", user.getUsername() + " joined the channel."); + } + + public void endChat() { + // remove user and update ui + User user = getLoggedInUser(); + RequestContext.getCurrentInstance().update("chatForm:users"); + // disconnect websocket + RequestContext requestContext = RequestContext.getCurrentInstance(); + requestContext.execute("socketWidget.disconnect('/" + user.getUsername() + "')"); + // push leave information + pushContext.push(CHANNEL + "*", user.getUsername() + " left the channel."); + } + + public void sendGlobal() { + String username = getLoggedInUser().getUsername(); + pushContext.push(CHANNEL + "*", username + ": " + globalMessage); + } + + public void setGlobalMessage(String globalMessage) { + this.globalMessage = globalMessage; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/controller/ContactsController.java b/primefaces-webapp/src/main/java/com/mycompany/controller/ContactsController.java new file mode 100644 index 0000000..9446df5 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/controller/ContactsController.java @@ -0,0 +1,158 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.controller; + +import java.util.List; + +import javax.faces.bean.ManagedBean; +import javax.faces.bean.ManagedProperty; +import javax.faces.bean.ViewScoped; +import javax.faces.event.ActionEvent; +import javax.faces.event.ComponentSystemEvent; + +import org.primefaces.event.SelectEvent; + +import com.mycompany.model.RelationshipType; +import com.mycompany.model.User; +import com.mycompany.model.UserRelationship; +import com.mycompany.service.UserService; + +/** + * Controller class for contacts related functionality. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@ManagedBean +@ViewScoped +public class ContactsController extends AbstractController { + + /** + * + */ + private static final long serialVersionUID = -1709154434943491658L; + + private List colleagues; + + @ManagedProperty(value = "#{userService}") + private UserService userService; + + private List family; + + private List friends; + + private UserRelationship relationship; + + private RelationshipType relationshipType; + + public List findUsersByName(String suggest) { + if (suggest == null) { + return null; + } + List users = userService.findUsersByName(suggest); + // remove current user from list + users.remove(getLoggedInUser()); + logger.info("Found {} users for '{}'", users.size(), suggest); + return users; + } + + public List getColleagues() { + if (colleagues == null) { + colleagues = userService.findUsersByType(RelationshipType.COLLEAGUE, getLoggedInUser()); + } + return colleagues; + } + + public List getFamily() { + if (family == null) { + family = userService.findUsersByType(RelationshipType.FAMILY, getLoggedInUser()); + } + return family; + } + + public List getFriends() { + if (friends == null) { + friends = userService.findUsersByType(RelationshipType.FRIEND, getLoggedInUser()); + } + return friends; + } + + public UserRelationship getRelationship() { + return relationship; + } + + public RelationshipType getRelationshipType() { + return relationshipType; + } + + public RelationshipType[] getRelationshipTypes() { + return RelationshipType.values(); + } + + public RelationshipType[] getUserTypes() { + return RelationshipType.values(); + } + + public void init(ComponentSystemEvent event) { + if (relationship == null) { + relationship = new UserRelationship(); + relationship.setFromUser(getLoggedInUser()); + } + } + + public void newRelationship(ActionEvent event) { + relationship = new UserRelationship(); + } + + public String saveRelationship() { + if (relationship.getToUser().equals(getLoggedInUser())) { + // throw new + // IllegalArgumentException("Unable to create relationship to self"); + addErrorMessage("Unable to create relationship to self"); + return null; + } + userService.saveRelationship(relationship); + relationship = null; + family = null; + friends = null; + colleagues = null; + return null; + } + + public void setUserService(UserService userService) { + this.userService = userService; + } + + public void setRelationship(UserRelationship relationship) { + this.relationship = relationship; + } + + public void userSelected(SelectEvent event) { + // load an existing relationship so it can be edited + relationship = userService.findRelationshipToUser(getLoggedInUser(), + relationship.getToUser()); + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/controller/ContentController.java b/primefaces-webapp/src/main/java/com/mycompany/controller/ContentController.java new file mode 100644 index 0000000..6c56127 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/controller/ContentController.java @@ -0,0 +1,122 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.controller; + +import java.util.Date; + +import javax.enterprise.context.Conversation; +import javax.faces.bean.ManagedBean; +import javax.faces.bean.ManagedProperty; +import javax.faces.bean.ViewScoped; +import javax.faces.context.FacesContext; +import javax.faces.event.ActionEvent; +import javax.faces.event.ComponentSystemEvent; +import javax.faces.event.ValueChangeEvent; +import javax.inject.Inject; + +import com.mycompany.model.Content; +import com.mycompany.service.ContentService; + +/** + * Controller class for content editing. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@ManagedBean +@ViewScoped +public class ContentController extends AbstractController { + + /** + * + */ + private static final long serialVersionUID = -5256865616437754501L; + + private Content content; + + @ManagedProperty(value = "#{contentService}") + private ContentService contentService; + + @Inject + private Conversation conversation; + + private boolean editing; + + public void contentChanged(ValueChangeEvent event) { + saveContentAndStopEditing(); + } + + public Content getContent() { + return content; + } + + public void init(ComponentSystemEvent event) { + String viewId = FacesContext.getCurrentInstance().getViewRoot().getViewId(); + if (content == null || !viewId.equals(content.getViewId())) { + content = contentService.findContentByName(viewId); + } + if (content == null) { + content = new Content(); + content.setViewId(viewId); + content.setCreatedBy(getLoggedInUser()); + content.setCreatedDate(new Date()); + } + if (conversation.isTransient()) { + conversation.begin(); + } + } + + public boolean isEditing() { + return editing; + } + + public void saveContent(ActionEvent event) { + saveContentAndStopEditing(); + } + + private void saveContentAndStopEditing() { + contentService.saveContent(content); + content = null; + editing = false; + conversation.end(); + } + + public void setContent(Content content) { + this.content = content; + } + + public void setContentService(ContentService contentService) { + this.contentService = contentService; + } + + public void setEditing(boolean editing) { + this.editing = editing; + } + + public void toggleEditing(ActionEvent event) { + editing = !editing; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/controller/DashboardController.java b/primefaces-webapp/src/main/java/com/mycompany/controller/DashboardController.java new file mode 100644 index 0000000..588a8d2 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/controller/DashboardController.java @@ -0,0 +1,91 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.controller; + +import javax.faces.application.FacesMessage; +import javax.faces.bean.ManagedBean; +import javax.faces.bean.ViewScoped; +import javax.faces.context.FacesContext; + +import org.primefaces.event.DashboardReorderEvent; +import org.primefaces.model.DashboardColumn; +import org.primefaces.model.DashboardModel; +import org.primefaces.model.DefaultDashboardColumn; +import org.primefaces.model.DefaultDashboardModel; + +/** + * Controller class for dashboard screen. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@ManagedBean +@ViewScoped +public class DashboardController extends AbstractController { + + /** + * + */ + private static final long serialVersionUID = -291033332986147359L; + + private DashboardModel model; + + public DashboardController() { + model = new DefaultDashboardModel(); + DashboardColumn column1 = new DefaultDashboardColumn(); + DashboardColumn column2 = new DefaultDashboardColumn(); + DashboardColumn column3 = new DefaultDashboardColumn(); + + column1.addWidget("sports"); + column1.addWidget("events"); + + column2.addWidget("weather"); + column2.addWidget("clicks"); + + column3.addWidget("politics"); + column3.addWidget("entertainment"); + + model.addColumn(column1); + model.addColumn(column2); + model.addColumn(column3); + } + + public void handleReorder(DashboardReorderEvent event) { + FacesMessage message = new FacesMessage(); + message.setSeverity(FacesMessage.SEVERITY_INFO); + message.setSummary("Reordered: " + event.getWidgetId()); + message.setDetail("Item index: " + event.getItemIndex() + ", Column index: " + + event.getColumnIndex() + ", Sender index: " + event.getSenderColumnIndex()); + addMessage(message); + } + + private void addMessage(FacesMessage message) { + FacesContext.getCurrentInstance().addMessage(null, message); + } + + public DashboardModel getModel() { + return model; + } +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/controller/EventController.java b/primefaces-webapp/src/main/java/com/mycompany/controller/EventController.java new file mode 100644 index 0000000..3bcf72f --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/controller/EventController.java @@ -0,0 +1,326 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.controller; + +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +import javax.faces.bean.ManagedBean; +import javax.faces.bean.ManagedProperty; +import javax.faces.bean.ViewScoped; +import javax.faces.event.ActionEvent; +import javax.faces.event.ComponentSystemEvent; +import javax.persistence.EntityManager; + +import org.primefaces.event.ScheduleEntryMoveEvent; +import org.primefaces.event.ScheduleEntryResizeEvent; +import org.primefaces.event.SelectEvent; +import org.primefaces.model.DefaultScheduleEvent; +import org.primefaces.model.LazyScheduleModel; +import org.primefaces.model.ScheduleEvent; +import org.primefaces.model.ScheduleModel; + +import com.mycompany.model.Event; +import com.mycompany.model.EventAttendance; +import com.mycompany.model.EventType; +import com.mycompany.model.User; +import com.mycompany.service.EventService; + +/** + * This class implements controller behavior for a number of screens in the + * application. It supports the member dashboard, shows, and reviews screens. + * This class is responsible for handling any calendar event related data and + * functionality for the application. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@ManagedBean +@ViewScoped +public class EventController extends AbstractController { + + /** + * + */ + private static final long serialVersionUID = 1256165484728132802L; + + private List allEvents; + + private List allEventsAttendance; + + private Event event; + + @ManagedProperty(value = "#{eventService}") + private EventService eventService; + + private ScheduleModel userScheduleModel; + + /** + * This method is called when the user clicks on a date in the calendar. It + * sets the start and end date of the calendar {@link Event} object. + * + * @param evt + * The {@link SelectEvent} object. + */ + public void dateSelected(SelectEvent evt) { + event.setStartDate((Date) evt.getObject()); + Calendar cal = Calendar.getInstance(); + cal.setTime((Date) evt.getObject()); + cal.roll(Calendar.HOUR_OF_DAY, 1); + event.setEndDate(cal.getTime()); + } + + /** + * This method is called when the user moves a calendar {@link Event} from + * one date/time to another date/time. It updates the object and saves the + * changes to the database. + * + * @param evt + * The {@link ScheduleEntryMoveEvent} object. + */ + public void eventMoved(ScheduleEntryMoveEvent evt) { + ScheduleEvent scheduleEvent = evt.getScheduleEvent(); + Event event = (Event) scheduleEvent.getData(); + event = eventService.findEventById(event.getId()); + event.setStartDate(scheduleEvent.getStartDate()); + event.setEndDate(scheduleEvent.getEndDate()); + eventService.saveEvent(event); + } + + /** + * This method is called when the user resizes an event. It handles changing + * the start and/or end dates of the {@link Event} object and updates the + * database. + * + * @param evt + * The {@link ScheduleEntryResizeEvent} object. + */ + public void eventResized(ScheduleEntryResizeEvent evt) { + ScheduleEvent scheduleEvent = evt.getScheduleEvent(); + Event event = (Event) scheduleEvent.getData(); + event = eventService.findEventById(event.getId()); + event.setStartDate(scheduleEvent.getStartDate()); + event.setEndDate(scheduleEvent.getEndDate()); + eventService.saveEvent(event); + } + + /** + * This method is called when the user clicks on an existing event in the + * schedule. It assigns the selected event to an instance variable so it can + * be used for editing. + * + * @param evt + * The {@link SelectEvent} object. + */ + public void eventSelected(SelectEvent evt) { + ScheduleEvent scheduleEvent = (ScheduleEvent) evt.getObject(); + event = (Event) scheduleEvent.getData(); + } + + /** + * This method returns all {@link Event} objects in the database. + * + * @return A List of all objects. + */ + public List getAllEvents() { + if (allEvents == null) { + allEvents = eventService.findAllEvents(); + } + return allEvents; + } + + /** + * This method returns a list of {@link EventAttendance} objects + * encapsulating information about a user's attendance for a particular + * event. + * + * @return A List of EventAttendance objects. + */ + public List getAllEventsAttendance() { + if (allEventsAttendance == null) { + allEventsAttendance = eventService.findAllEventsAttendanceByUser(getLoggedInUser()); + } + return allEventsAttendance; + } + + /** + * This method returns the currently selected {@link Event}. + * + * @return An object. + */ + public Event getEvent() { + return event; + } + + /** + * This method returns an array of {@link EventType} enum objects. + * + * @return An array of EventType objects. + */ + public EventType[] getEventTypes() { + return EventType.values(); + } + + /** + * This method provides a {@link LazyScheduleModel} for the PrimeFaces + * schedule component. It loads all events for the current user that have a + * start date between two dates. The overridden + * {@link LazyScheduleModel#loadEvents(Date, Date)} method is called by + * PrimeFaces when data is needed for a particular date range. + * + * @return A {@link ScheduleModel} object. + */ + public ScheduleModel getUserScheduleModel() { + if (userScheduleModel == null) { + userScheduleModel = new LazyScheduleModel() { + + private static final long serialVersionUID = 1L; + + @Override + public void loadEvents(Date start, Date end) { + clear(); + User user = getLoggedInUser(); + List events = eventService.findUserEvents(start, end, user); + for (Event event : events) { + String title = event.getTitle(); + Date startDate = event.getStartDate(); + Date endDate = event.getEndDate(); + addEvent(new DefaultScheduleEvent(title, startDate, endDate, event)); + } + } + }; + } + return userScheduleModel; + } + + /** + * This method is called by JSF when the view is first loaded. It loads all + * the {@link Event} objects from the database so they can be displayed in + * the UI, and prepares the {@link EventAttendance} model for the current + * user. + * + * @param evt + * The JSF {@link ComponentSystemEvent} object. + */ + public void init(ComponentSystemEvent evt) { + if (event == null) { + event = new Event(); + userScheduleModel = null; + } + if (allEvents == null) { + // initialize user attendance model + User user = getLoggedInUser(); + List events = getAllEvents(); + for (Event event : events) { + EventAttendance attendance = eventService.findEventAttendance(event, user); + if (attendance == null) { + attendance = new EventAttendance(); + attendance.setEvent(event); + attendance.setUser(user); + eventService.saveAttendance(attendance); + } + } + } + } + + /** + * This method is called when the user clicks on the "New Event" button in + * the mobile web application. It simply creates a new {@link Event} object + * and assigns it to the {@link #event} instance variable. + * + * @param evt + * The JSF {@link ActionEvent} object. + */ + public void newEvent(ActionEvent evt) { + event = new Event(); + } + + /** + * This method is called from the reviews screen to refresh the + * {@link EventAttendance} data. When the user reloads the dashboard, the + * {@link #getAllEventsAttendance()} method will see that this instance + * variable is null, and reload the data to update the graph. + * + * @param event + * The JSF {@link ActionEvent} object. + */ + public void refreshAttendance(ActionEvent event) { + allEventsAttendance = null; + } + + /** + * This method is called when the user clicks the "Save" button in the new + * event dialog. It saves the {@link Event} object to the database. + * + * @param evt + * The JSF {@link ActionEvent} object. + */ + public void saveEvent(ActionEvent evt) { + event.setCreatedBy(getLoggedInUser()); + eventService.saveEvent(event); + event = null; + allEvents = null; + allEventsAttendance = null; + userScheduleModel = null; + } + + /** + * Sets the {@link Event}. + * + * @param event + * The Event object. + */ + public void setEvent(Event event) { + this.event = event; + } + + public void setEventService(EventService eventService) { + this.eventService = eventService; + } + + /** + *

+ * This method updates the current user's EventAttendance object for a + * particular event. It uses the JPA {@link EntityManager#merge(Object)} + * method to save the object's changes to the database, and then replaces + * this object in the {@link #allEventsAttendance} list to ensure the latest + * object is loaded in the UI. + *

+ *

+ * Note: this method is called directly from the UI since it takes advantage + * of the Expression Language (EL) 2.2 feature that allows method argument + * passing from JSF. + *

+ * + * @param attendance + * The {@link EventAttendance} object. + */ + public void updateAttendance(EventAttendance attendance) { + EventAttendance updated = eventService.saveAttendance(attendance); + allEventsAttendance.set(allEventsAttendance.indexOf(attendance), updated); + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/controller/LoginController.java b/primefaces-webapp/src/main/java/com/mycompany/controller/LoginController.java new file mode 100644 index 0000000..9da76c6 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/controller/LoginController.java @@ -0,0 +1,132 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.controller; + +import java.io.IOException; + +import javax.faces.application.NavigationHandler; +import javax.faces.bean.ManagedBean; +import javax.faces.bean.ManagedProperty; +import javax.faces.bean.ViewScoped; +import javax.faces.context.ExternalContext; +import javax.faces.context.FacesContext; +import javax.faces.event.ComponentSystemEvent; + +import com.mycompany.model.ActiveUsers; +import com.mycompany.model.Credentials; +import com.mycompany.model.User; +import com.mycompany.service.UserService; + +/** + * Controller class for desktop and mobile login functionality. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * @uml.dependency supplier="com.mycompany.controller.AbstractController" + */ +@ManagedBean +@ViewScoped +public class LoginController extends AbstractController { + + /** + * + */ + private static final long serialVersionUID = -6710063228036238737L; + + @ManagedProperty(value = "#{activeUsers}") + private ActiveUsers activeUsers; + + @ManagedProperty(value = "#{credentials}") + private Credentials credentials; + + @ManagedProperty(value = "#{userService}") + private UserService userService; + + public void checkPermission(ComponentSystemEvent event) throws IOException { + if (!isLoggedIn()) { + FacesContext ctx = FacesContext.getCurrentInstance(); + ExternalContext external = ctx.getExternalContext(); + if (!external.isResponseCommitted()) { + NavigationHandler handler = ctx.getApplication().getNavigationHandler(); + handler.handleNavigation(ctx, null, "login"); + } + } + } + + public boolean isLoggedIn() { + return getLoggedInUser() != null; + } + + public String login() { + String outcome = null; + try { + String username = credentials.getUsername(); + String password = credentials.getPassword(); + User user = userService.findUser(username, password); + if (user == null) { + addErrorMessage("Invalid login"); + userSession.setUser(null); + } else { + userSession.setUser(user); + if (!activeUsers.contains(user)) { + activeUsers.add(user); + } + outcome = "members"; + } + } catch (Exception e) { + logger.error("Unable to login:", e); + } + return outcome; + } + + public String loginMobile() { + login(); + if (isLoggedIn()) { + return "pm:members"; + } + return null; + } + + public String logout() { + FacesContext.getCurrentInstance().getExternalContext().invalidateSession(); + return "login"; + } + + public String logoutMobile() { + FacesContext.getCurrentInstance().getExternalContext().invalidateSession(); + return "pm:main?reverse=true"; + } + + public void setActiveUsers(ActiveUsers activeUsers) { + this.activeUsers = activeUsers; + } + + public void setCredentials(Credentials credentials) { + this.credentials = credentials; + } + + public void setUserService(UserService userService) { + this.userService = userService; + } +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/controller/MindMapController.java b/primefaces-webapp/src/main/java/com/mycompany/controller/MindMapController.java new file mode 100644 index 0000000..2ac5fc1 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/controller/MindMapController.java @@ -0,0 +1,126 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.controller; + +import java.util.List; + +import javax.faces.bean.ManagedBean; +import javax.faces.bean.ManagedProperty; +import javax.faces.bean.ViewScoped; +import javax.faces.event.ActionEvent; +import javax.faces.event.ComponentSystemEvent; + +import org.primefaces.event.SelectEvent; +import org.primefaces.model.mindmap.DefaultMindmapNode; +import org.primefaces.model.mindmap.MindmapNode; + +import com.mycompany.model.Idea; +import com.mycompany.service.IdeaService; + +/** + * Controller class for mind map feature. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@ManagedBean +@ViewScoped +public class MindMapController extends AbstractController { + + /** + * + */ + private static final long serialVersionUID = 4810848975079411459L; + + @ManagedProperty(value = "#{ideaService}") + private IdeaService ideaService; + + private Idea newIdea; + + private MindmapNode root; + + private Idea selectedIdea; + + private MindmapNode selectedNode; + + public Idea getNewIdea() { + return newIdea; + } + + public MindmapNode getRoot() { + return root; + } + + public MindmapNode getSelectedNode() { + return selectedNode; + } + + public void init(ComponentSystemEvent event) { + if (newIdea == null) { + newIdea = new Idea(); + loadIdeas(); + } + } + + private void loadIdeas() { + List ideas = ideaService.findIdeas(); + if (!ideas.isEmpty()) { + Idea rootIdea = ideas.get(0); + String label = rootIdea.getName(); + root = new DefaultMindmapNode(label, rootIdea, "FFCC00", true); + ideaService.buildMindMap(rootIdea, root); + } + } + + public void onNodeDblselect(SelectEvent event) { + this.selectedNode = (MindmapNode) event.getObject(); + this.selectedIdea = (Idea) this.selectedNode.getData(); + } + + public void onNodeSelect(SelectEvent event) { + } + + public void saveIdea(ActionEvent event) { + if (selectedIdea != null) { + newIdea.setParent(selectedIdea); + } + newIdea.setAuthor(getLoggedInUser()); + ideaService.saveIdea(newIdea); + root = null; + newIdea = null; + } + + public void setIdeaService(IdeaService ideaService) { + this.ideaService = ideaService; + } + + public void setNewIdea(Idea newIdea) { + this.newIdea = newIdea; + } + + public void setSelectedNode(MindmapNode selectedNode) { + this.selectedNode = selectedNode; + } +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/controller/SearchController.java b/primefaces-webapp/src/main/java/com/mycompany/controller/SearchController.java new file mode 100644 index 0000000..3d49708 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/controller/SearchController.java @@ -0,0 +1,308 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.controller; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLEncoder; +import java.util.List; + +import javax.ejb.TransactionAttribute; +import javax.ejb.TransactionAttributeType; +import javax.faces.bean.ManagedBean; +import javax.faces.bean.ManagedProperty; +import javax.faces.bean.ViewScoped; +import javax.faces.event.ActionEvent; +import javax.faces.event.ComponentSystemEvent; + +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.ObjectMapper; +import org.primefaces.event.map.OverlaySelectEvent; +import org.primefaces.model.map.DefaultMapModel; +import org.primefaces.model.map.LatLng; +import org.primefaces.model.map.MapModel; +import org.primefaces.model.map.Marker; +import org.primefaces.model.map.Overlay; + +import com.mycompany.model.City; +import com.mycompany.model.Event; +import com.mycompany.model.EventType; +import com.mycompany.model.ProvinceState; +import com.mycompany.model.Venue; +import com.mycompany.service.CountryService; +import com.mycompany.service.EventService; + +/** + * Controller class for searching for shows and events. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@ManagedBean +@ViewScoped +public class SearchController extends AbstractController { + + /** + * + */ + private static final long serialVersionUID = 3648708195333963881L; + + private boolean alcoholPermitted; + + private City city; + + @ManagedProperty(value = "#{countryService}") + private CountryService countryService; + + @ManagedProperty(value = "#{eventService}") + private EventService eventService; + + private EventType eventType; + + private String keyword; + + private String mapCenter; + + private Integer mapZoom; + + private int maxResults; + + private boolean noCoverCharge; + + private boolean outdoorVenue; + + private ProvinceState provinceState; + + private MapModel searchResultsModel; + + private Event selectedEvent; + + public SearchController() { + searchResultsModel = new DefaultMapModel(); + } + + public void eventSelected(OverlaySelectEvent evt) { + Overlay overlay = evt.getOverlay(); + this.selectedEvent = (Event) overlay.getData(); + } + + public List getCitiesForState() { + if (provinceState == null) { + return null; + } + return countryService.findCitiesByState(provinceState); + } + + public City getCity() { + return city; + } + + private LatLng getCoordinates(Venue venue) { + LatLng coords = null; + try { + if (venue.getLatitude() == null || venue.getLongitude() == null) { + // lookup address coordinates using Google Geocoding API + String address = URLEncoder.encode(venue.getCompleteAddress(), "UTF-8"); + String uri = "http://maps.googleapis.com/maps/api/geocode/json?sensor=true&address=" + + address; + ObjectMapper mapper = new ObjectMapper(); + JsonNode root = mapper.readTree(new URL(uri)); + logger.info("{}", root); + JsonNode geometry = root.findValue("geometry"); + if (geometry.isMissingNode()) { + return null; + } + JsonNode location = geometry.path("location"); + JsonNode latitude = location.path("lat"); + JsonNode longitude = location.path("lng"); + City city = venue.getCity(); + if (city.getLatitude() == null || city.getLongitude() == null) { + city.setLatitude(latitude.asDouble()); + city.setLongitude(longitude.asDouble()); + // Google Geocoding license does not permit storing in DB + } + venue.setLatitude(latitude.asDouble()); + venue.setLongitude(longitude.asDouble()); + } + coords = new LatLng(venue.getLatitude(), venue.getLongitude()); + } catch (UnsupportedEncodingException e) { + logger.error("Exception: {}", e); + } catch (MalformedURLException e) { + logger.error("Exception: {}", e); + } catch (IOException e) { + logger.error("Exception: {}", e); + } + return coords; + } + + public EventType getEventType() { + return eventType; + } + + public String getKeyword() { + return keyword; + } + + public String getMapCenter() { + if (mapCenter == null) { + if (city == null) { + // center on USA + mapCenter = "38.889722,-77.008889"; + } else { + mapCenter = city.getLatitude() + "," + city.getLongitude(); + } + } + return mapCenter; + } + + public Integer getMapZoom() { + if (mapZoom == null) { + mapZoom = 2; + } + return mapZoom; + } + + public int getMaxResults() { + return maxResults; + } + + public ProvinceState getProvinceState() { + return provinceState; + } + + public List getProvinceStates() { + return countryService.getProvinceStates(); + } + + public MapModel getSearchResultsModel() { + return searchResultsModel; + } + + public Event getSelectedEvent() { + return selectedEvent; + } + + public void init(ComponentSystemEvent event) { + } + + public boolean isAlcoholPermitted() { + return alcoholPermitted; + } + + public boolean isNoCoverCharge() { + return noCoverCharge; + } + + public boolean isOutdoorVenue() { + return outdoorVenue; + } + + /** + * This method searches the database for events. + * + * @param evt + */ + @TransactionAttribute(TransactionAttributeType.SUPPORTS) + public void search(ActionEvent evt) { + + // Get the list of shows from our database + List events = eventService.findEvents(city, provinceState, eventType, keyword); + if (events.isEmpty()) { + // zoom out to show world + mapZoom = 2; + return; + } + + // reset center + mapCenter = null; + + // zoom in to show city + mapZoom = 12; + + // Build a model for the Google map + for (Event event : events) { + LatLng coords = getCoordinates(event.getVenue()); + if (coords == null) { + logger.warn("Warning - no coordinates for location: " + + event.getVenue().getCompleteAddress()); + continue; + } + searchResultsModel.addOverlay(new Marker(coords, event.getTitle(), event)); + + // center map on city of first event + if (mapCenter == null) { + City eventCity = event.getVenue().getCity(); + mapCenter = eventCity.getLatitude() + "," + eventCity.getLongitude(); + } + } + } + + public void setAlcoholPermitted(boolean alcoholPermitted) { + this.alcoholPermitted = alcoholPermitted; + } + + public void setCity(City city) { + this.city = city; + } + + public void setCountryService(CountryService countryService) { + this.countryService = countryService; + } + + public void setEventService(EventService eventService) { + this.eventService = eventService; + } + + public void setEventType(EventType eventType) { + this.eventType = eventType; + } + + public void setKeyword(String keyword) { + this.keyword = keyword; + } + + public void setMaxResults(int maxResults) { + this.maxResults = maxResults; + } + + public void setNoCoverCharge(boolean noCoverCharge) { + this.noCoverCharge = noCoverCharge; + } + + public void setOutdoorVenue(boolean outdoorVenue) { + this.outdoorVenue = outdoorVenue; + } + + public void setProvinceState(ProvinceState state) { + this.provinceState = state; + } + + public void setSelectedEvent(Event selectedEvent) { + this.selectedEvent = selectedEvent; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/controller/SignupController.java b/primefaces-webapp/src/main/java/com/mycompany/controller/SignupController.java new file mode 100644 index 0000000..5b278c7 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/controller/SignupController.java @@ -0,0 +1,146 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.controller; + +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +import javax.faces.application.FacesMessage; +import javax.faces.bean.ManagedBean; +import javax.faces.bean.ManagedProperty; +import javax.faces.bean.ViewScoped; +import javax.faces.context.FacesContext; +import javax.faces.event.ActionEvent; + +import com.mycompany.model.Country; +import com.mycompany.model.Gender; +import com.mycompany.model.User; +import com.mycompany.service.CountryService; +import com.mycompany.service.UserService; + +/** + * Controller class for new user signup. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * @uml.dependency supplier="com.mycompany.model.Country" + */ +@ManagedBean +@ViewScoped +public class SignupController extends AbstractController { + + /** + * + */ + private static final long serialVersionUID = -3479887222411577225L; + + @ManagedProperty(value = "#{countryService}") + private CountryService countryService; + + private User user; + + @ManagedProperty(value = "#{userService}") + private UserService userService; + + public SignupController() { + user = new User(); + } + + public void createUser(ActionEvent event) { + user = new User(); + } + + public List getCountries() { + return countryService.getCountries(); + } + + public Gender[] getGenders() { + return Gender.values(); + } + + /** + * Return a date 100 years ago. + * + * @return + */ + public Date getMinDate() { + Calendar cal = Calendar.getInstance(); + cal.roll(Calendar.YEAR, -100); + return cal.getTime(); + } + + public User getUser() { + return user; + } + + /** + * This method checks to see if the username already exists. + * + * @return A boolean value. + */ + private boolean isValidUser() { + boolean valid = false; + String username = user.getUsername(); + if (username != null) { + if (userService.findUserByUsername(username) == null) { + valid = true; + } else { + FacesMessage msg = new FacesMessage(); + msg.setDetail("The username you have entered is already in use."); + msg.setSeverity(FacesMessage.SEVERITY_ERROR); + FacesContext.getCurrentInstance().addMessage(null, msg); + } + } + return valid; + } + + public void setCountryService(CountryService countryService) { + this.countryService = countryService; + } + + public void setUser(User user) { + this.user = user; + } + + public void setUserService(UserService userService) { + this.userService = userService; + } + + public String signup() { + if (isValidUser()) { + userService.saveUser(user); + return "login"; + } + return null; + } + + public String signupMobile() { + String outcome = signup(); + if (outcome != null) { + return "pm:main"; + } + return null; + } +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/controller/UserController.java b/primefaces-webapp/src/main/java/com/mycompany/controller/UserController.java new file mode 100644 index 0000000..8f79396 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/controller/UserController.java @@ -0,0 +1,131 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.controller; + +import java.util.ArrayList; +import java.util.List; + +import javax.faces.bean.ManagedBean; +import javax.faces.bean.ManagedProperty; +import javax.faces.bean.ViewScoped; +import javax.faces.event.ActionEvent; +import javax.faces.event.AjaxBehaviorEvent; + +import com.mycompany.model.ActiveUsers; +import com.mycompany.model.User; +import com.mycompany.service.UserService; + +/** + * Controller class for user-related functionality. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * @uml.dependency supplier="com.mycompany.util.UserSession" + */ +@ManagedBean +@ViewScoped +public class UserController extends AbstractController { + + /** + * + */ + private static final long serialVersionUID = 1140838618640961470L; + + @ManagedProperty(value = "#{activeUsers}") + private ActiveUsers activeUsers; + + private List themes; + + @ManagedProperty(value = "#{userService}") + private UserService userService; + + public User findUser(String username, String password) { + return userService.findUser(username, password); + } + + public List getThemes() { + if (themes == null) { + themes = new ArrayList(); + themes.add("aristo"); + themes.add("cupertino"); + themes.add("redmond"); + } + return themes; + } + + /** + * Returns the currently logged in user. + * + * @return A {@link User} object. + */ + public User getUser() { + return getLoggedInUser(); + } + + public String getUserTheme() { + String theme = null; + User user = getUser(); + if (user != null) { + theme = user.getTheme(); + } + if (theme == null) { + // use the default theme + theme = "aristo"; + } + return theme; + } + + public void handleClick(ActionEvent event) { + User user = getUser(); + if (user != null) { + Integer count = user.getClickCount(); + if (count == null) { + count = 0; + } + user.setClickCount(count + 1); + user = userService.saveUser(user); + userSession.setUser(user); + } + } + + public boolean isUserPresent(User user) { + return activeUsers.contains(user); + } + + public void setActiveUsers(ActiveUsers activeUsers) { + this.activeUsers = activeUsers; + } + + public void setUserService(UserService userService) { + this.userService = userService; + } + + public void updateUserTheme(AjaxBehaviorEvent event) { + User user = getUser(); + if (user != null) { + user = userService.saveUser(user); + } + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/controller/VenueController.java b/primefaces-webapp/src/main/java/com/mycompany/controller/VenueController.java new file mode 100644 index 0000000..0f05286 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/controller/VenueController.java @@ -0,0 +1,138 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.controller; + +import java.util.List; + +import javax.faces.application.FacesMessage; +import javax.faces.bean.ManagedBean; +import javax.faces.bean.ManagedProperty; +import javax.faces.bean.ViewScoped; +import javax.faces.context.FacesContext; +import javax.faces.event.ActionEvent; +import javax.faces.event.ComponentSystemEvent; +import javax.faces.event.ValueChangeEvent; + +import com.mycompany.model.City; +import com.mycompany.model.Country; +import com.mycompany.model.ProvinceState; +import com.mycompany.model.Venue; +import com.mycompany.service.CountryService; +import com.mycompany.service.VenueService; + +/** + * Controller class for venue-related functionality. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@ManagedBean +@ViewScoped +public class VenueController extends AbstractController { + + /** + * + */ + private static final long serialVersionUID = 1127963225862339644L; + + @ManagedProperty(value = "#{countryService}") + private CountryService countryService; + + private Venue venue; + + @ManagedProperty(value = "#{venueService}") + private VenueService venueService; + + public void deleteVenue(ActionEvent evt) { + venueService.deleteVenue(venue); + this.venue = null; + } + + public List findProvinceStatesByCountry(Country country) { + return countryService.findProvinceStatesByCountry(country); + } + + public List getCountries() { + return countryService.getCountries(); + } + + public Venue getVenue() { + return venue; + } + + public List getVenues() { + return venueService.findVenues(); + } + + public void init(ComponentSystemEvent evt) { + if (venue == null) { + venue = new Venue(); + venue.setCity(new City()); + } + } + + public void newVenue(ActionEvent event) { + this.venue = new Venue(); + this.venue.setCity(new City()); + } + + public void saveVenue(ActionEvent evt) { + try { + // lookup existing city + City city = countryService.findCity(venue.getCity().getName(), venue.getProvinceState()); + if (city == null) { + venue.getCity().setProvinceState(venue.getProvinceState()); + } else { + venue.setCity(city); + } + venueService.saveVenue(venue); + FacesMessage msg = new FacesMessage(); + msg.setDetail("The venue has been saved!"); + msg.setSeverity(FacesMessage.SEVERITY_INFO); + String id = evt.getComponent().getClientId(); + FacesContext.getCurrentInstance().addMessage(id, msg); + } catch (Exception e) { + FacesMessage msg = new FacesMessage(); + msg.setDetail("Failed to save venue: " + e.getMessage()); + msg.setSeverity(FacesMessage.SEVERITY_ERROR); + FacesContext.getCurrentInstance().addMessage(null, msg); + } + } + + public void setCountryService(CountryService countryService) { + this.countryService = countryService; + } + + public void setVenue(Venue venue) { + this.venue = venue; + } + + public void setVenueService(VenueService venueService) { + this.venueService = venueService; + } + + public void venueSelected(ValueChangeEvent evt) { + } +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/convert/CityConverter.java b/primefaces-webapp/src/main/java/com/mycompany/convert/CityConverter.java new file mode 100644 index 0000000..9d4378a --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/convert/CityConverter.java @@ -0,0 +1,64 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.convert; + +import javax.faces.component.UIComponent; +import javax.faces.context.FacesContext; +import javax.faces.convert.Converter; +import javax.faces.convert.FacesConverter; + +import com.mycompany.model.City; +import com.mycompany.service.CountryService; +import com.mycompany.util.FacesUtils; + +/** + * Converter for {@link City} objects. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@FacesConverter(forClass = City.class) +public class CityConverter implements Converter { + + @Override + public Object getAsObject(FacesContext context, UIComponent component, String value) { + if (value == null) { + return null; + } + CountryService service = (CountryService) FacesUtils.getManagedBean("countryService"); + return service.findCityById(Integer.valueOf(value)); + } + + @Override + public String getAsString(FacesContext context, UIComponent component, Object value) { + if (value instanceof City) { + return String.valueOf(((City) value).getId()); + } else if (value instanceof String) { + return ((String) value); + } + return null; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/convert/CountryConverter.java b/primefaces-webapp/src/main/java/com/mycompany/convert/CountryConverter.java new file mode 100644 index 0000000..8f1a674 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/convert/CountryConverter.java @@ -0,0 +1,64 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.convert; + +import javax.faces.component.UIComponent; +import javax.faces.context.FacesContext; +import javax.faces.convert.Converter; +import javax.faces.convert.FacesConverter; + +import com.mycompany.model.Country; +import com.mycompany.service.CountryService; +import com.mycompany.util.FacesUtils; + +/** + * Converter class for {@link Country} objects. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@FacesConverter(forClass = Country.class) +public class CountryConverter implements Converter { + + @Override + public Object getAsObject(FacesContext context, UIComponent component, String value) { + if (value == null) { + return null; + } + CountryService service = (CountryService) FacesUtils.getManagedBean("countryService"); + return service.findCountryById(Integer.valueOf(value)); + } + + @Override + public String getAsString(FacesContext context, UIComponent component, Object value) { + if (value instanceof Country) { + return String.valueOf(((Country) value).getId()); + } else if (value instanceof String) { + return ((String) value); + } + return null; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/convert/EditableStateConverter.java b/primefaces-webapp/src/main/java/com/mycompany/convert/EditableStateConverter.java new file mode 100644 index 0000000..0d5f2bd --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/convert/EditableStateConverter.java @@ -0,0 +1,77 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.convert; + +import javax.faces.component.UIComponent; +import javax.faces.component.UIParameter; +import javax.faces.context.FacesContext; +import javax.faces.convert.Converter; +import javax.faces.convert.FacesConverter; + +import com.mycompany.model.Country; +import com.mycompany.model.ProvinceState; +import com.mycompany.service.CountryService; +import com.mycompany.util.FacesUtils; + +/** + * Converter object for editable {@link ProvinceState} objects. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@FacesConverter(forClass = ProvinceState.class, + value = "mycompany.EditableStateConverter") +public class EditableStateConverter implements Converter { + + @Override + public Object getAsObject(FacesContext context, UIComponent component, String value) { + if (value == null) { + return null; + } + ProvinceState state = null; + UIParameter param = (UIParameter) component.findComponent("countryParam"); + if (param != null) { + // lookup existing state by country and name + Country country = (Country) param.getValue(); + CountryService service = (CountryService) FacesUtils.getManagedBean("countryService"); + state = service.findStateByName(country, value); + if (state == null) { + // create new state if it does not exist + state = service.createProvinceState(country, value); + } + } + return state; + } + + @Override + public String getAsString(FacesContext context, UIComponent component, Object value) { + if (value instanceof ProvinceState) { + return ((ProvinceState) value).getName(); + } else if (value instanceof String) { + return ((String) value); + } + return null; + } +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/convert/StateConverter.java b/primefaces-webapp/src/main/java/com/mycompany/convert/StateConverter.java new file mode 100644 index 0000000..365eed7 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/convert/StateConverter.java @@ -0,0 +1,63 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.convert; + +import javax.faces.component.UIComponent; +import javax.faces.context.FacesContext; +import javax.faces.convert.Converter; +import javax.faces.convert.FacesConverter; + +import com.mycompany.model.ProvinceState; +import com.mycompany.service.CountryService; +import com.mycompany.util.FacesUtils; + +/** + * Converter class for {@link ProvinceState} objects. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@FacesConverter(forClass = ProvinceState.class) +public class StateConverter implements Converter { + + @Override + public Object getAsObject(FacesContext context, UIComponent component, String value) { + if (value == null) { + return null; + } + CountryService service = (CountryService) FacesUtils.getManagedBean("countryService"); + return service.findStateById(Integer.valueOf(value)); + } + + @Override + public String getAsString(FacesContext context, UIComponent component, Object value) { + if (value instanceof ProvinceState) { + return String.valueOf(((ProvinceState) value).getId()); + } else if (value instanceof String) { + return ((String) value); + } + return null; + } +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/convert/UserConverter.java b/primefaces-webapp/src/main/java/com/mycompany/convert/UserConverter.java new file mode 100644 index 0000000..2b483b4 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/convert/UserConverter.java @@ -0,0 +1,64 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.convert; + +import javax.faces.component.UIComponent; +import javax.faces.context.FacesContext; +import javax.faces.convert.Converter; +import javax.faces.convert.FacesConverter; + +import com.mycompany.model.User; +import com.mycompany.service.UserService; +import com.mycompany.util.FacesUtils; + +/** + * Converter class for {@link User} objects. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@FacesConverter(forClass = User.class) +public class UserConverter implements Converter { + + @Override + public Object getAsObject(FacesContext context, UIComponent component, String value) { + if (value == null) { + return null; + } + UserService service = (UserService) FacesUtils.getManagedBean("userService"); + return service.findUserById(Integer.valueOf(value)); + } + + @Override + public String getAsString(FacesContext context, UIComponent component, Object value) { + if (value instanceof User) { + return String.valueOf(((User) value).getId()); + } else if (value instanceof String) { + return ((String) value); + } + return null; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/convert/VenueConverter.java b/primefaces-webapp/src/main/java/com/mycompany/convert/VenueConverter.java new file mode 100644 index 0000000..9e0b5c2 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/convert/VenueConverter.java @@ -0,0 +1,64 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.convert; + +import javax.faces.component.UIComponent; +import javax.faces.context.FacesContext; +import javax.faces.convert.Converter; +import javax.faces.convert.FacesConverter; + +import com.mycompany.model.Venue; +import com.mycompany.service.VenueService; +import com.mycompany.util.FacesUtils; + +/** + * Converter class for {@link Venue} objects. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@FacesConverter(forClass = Venue.class) +public class VenueConverter implements Converter { + + @Override + public Object getAsObject(FacesContext context, UIComponent component, String value) { + if (value == null) { + return null; + } + VenueService service = (VenueService) FacesUtils.getManagedBean("venueService"); + return service.findVenueById(Integer.valueOf(value)); + } + + @Override + public String getAsString(FacesContext context, UIComponent component, Object value) { + if (value instanceof Venue) { + return String.valueOf(((Venue) value).getId()); + } else if (value instanceof String) { + return ((String) value); + } + return null; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/lifecycle/ConversationExceptionFilter.java b/primefaces-webapp/src/main/java/com/mycompany/lifecycle/ConversationExceptionFilter.java new file mode 100644 index 0000000..f728bb5 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/lifecycle/ConversationExceptionFilter.java @@ -0,0 +1,111 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.lifecycle; + +import java.io.IOException; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Map; + +import javax.enterprise.context.NonexistentConversationException; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import javax.servlet.http.HttpServletResponse; + +/** + * + * This filter handles the {@link NonexistentConversationException) propagating + * from CDI for requests containing an invalid conversation ID (cid parameter). + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@WebFilter("/*") +public class ConversationExceptionFilter implements Filter { + + private class ConversationAwareRequestWrapper extends HttpServletRequestWrapper { + + public ConversationAwareRequestWrapper(HttpServletRequest request) { + super(request); + } + + @Override + public String getParameter(String name) { + if ("cid".equals(name)) { + return null; + } + return super.getParameter(name); + } + + @Override + public Map getParameterMap() { + Map map = super.getParameterMap(); + map.remove("cid"); + return map; + } + + @Override + public Enumeration getParameterNames() { + return Collections.enumeration(getParameterMap().keySet()); + } + + } + + @Override + public void destroy() { + } + + @Override + public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) + throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest) req; + HttpServletResponse response = (HttpServletResponse) res; + try { + chain.doFilter(request, response); + } catch (ServletException e) { + if (e.getCause() instanceof NonexistentConversationException) { + HttpServletRequestWrapper wrapper = new ConversationAwareRequestWrapper(request); + String context = request.getContextPath(); + String viewId = request.getRequestURI(); + String path = viewId.replaceFirst(context, ""); + request.getRequestDispatcher(path).forward(wrapper, res); + } else { + throw e; + } + } + } + + @Override + public void init(FilterConfig arg0) throws ServletException { + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/lifecycle/Destroyed.java b/primefaces-webapp/src/main/java/com/mycompany/lifecycle/Destroyed.java new file mode 100644 index 0000000..cc7325b --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/lifecycle/Destroyed.java @@ -0,0 +1,42 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.lifecycle; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.inject.Qualifier; + +/** + * Thanks to Dan Allen for this useful code: https://gist.github.com/637959 + * + */ +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.FIELD, ElementType.PARAMETER }) +public @interface Destroyed { +} \ No newline at end of file diff --git a/primefaces-webapp/src/main/java/com/mycompany/lifecycle/Initialized.java b/primefaces-webapp/src/main/java/com/mycompany/lifecycle/Initialized.java new file mode 100644 index 0000000..86226d3 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/lifecycle/Initialized.java @@ -0,0 +1,42 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.lifecycle; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.inject.Qualifier; + +/** + * Thanks to Dan Allen for this useful code: https://gist.github.com/637959 + * + */ +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.FIELD, ElementType.PARAMETER }) +public @interface Initialized { +} \ No newline at end of file diff --git a/primefaces-webapp/src/main/java/com/mycompany/lifecycle/SecurityPhaseListener.java b/primefaces-webapp/src/main/java/com/mycompany/lifecycle/SecurityPhaseListener.java new file mode 100644 index 0000000..99b1a13 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/lifecycle/SecurityPhaseListener.java @@ -0,0 +1,88 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.lifecycle; + +import javax.faces.component.UIViewRoot; +import javax.faces.context.FacesContext; +import javax.faces.event.PhaseEvent; +import javax.faces.event.PhaseId; +import javax.faces.event.PhaseListener; + +import com.mycompany.controller.LoginController; + +/** + * PhaseListener class that handles authorization for protected views. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +public class SecurityPhaseListener implements PhaseListener { + + /** + * + */ + private static final long serialVersionUID = -1013239137374622294L; + + @Override + public void afterPhase(PhaseEvent event) { + + // eagerly create session due to JAVASERVERFACES-2215 + FacesContext context = FacesContext.getCurrentInstance(); + context.getExternalContext().getSession(true); + + // check if view is protected + UIViewRoot view = context.getViewRoot(); + if (view != null) { + String viewId = view.getViewId(); + boolean authenticationRequired = viewId.contains("/protected/"); + boolean loggedIn = isLoggedIn(); + if (authenticationRequired && !loggedIn) { + // send user to login page if not logged in + context.getApplication() + .getNavigationHandler() + .handleNavigation(context, null, "login"); + } + } + } + + @Override + public void beforePhase(PhaseEvent event) { + } + + @Override + public PhaseId getPhaseId() { + return PhaseId.RESTORE_VIEW; + } + + private boolean isLoggedIn() { + boolean loggedIn = false; + FacesContext ctx = FacesContext.getCurrentInstance(); + LoginController controller = (LoginController) ctx.getApplication().evaluateExpressionGet( + ctx, "#{loginController}", Object.class); + loggedIn = controller.isLoggedIn(); + return loggedIn; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/lifecycle/ServletContextLifecycleNotifier.java b/primefaces-webapp/src/main/java/com/mycompany/lifecycle/ServletContextLifecycleNotifier.java new file mode 100644 index 0000000..1b36259 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/lifecycle/ServletContextLifecycleNotifier.java @@ -0,0 +1,58 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.lifecycle; + +import javax.enterprise.event.Event; +import javax.enterprise.inject.Any; +import javax.enterprise.util.AnnotationLiteral; +import javax.inject.Inject; +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; + +/** + * Thanks to Dan Allen for this useful code: https://gist.github.com/637959 + * + */ +@WebListener +public class ServletContextLifecycleNotifier implements ServletContextListener { + + @Inject + @Any + private Event servletContextEvent; + + @Override + public void contextInitialized(ServletContextEvent sce) { + servletContextEvent.select(new AnnotationLiteral() { + }).fire(sce.getServletContext()); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + servletContextEvent.select(new AnnotationLiteral() { + }).fire(sce.getServletContext()); + } +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/AbstractEntity.java b/primefaces-webapp/src/main/java/com/mycompany/model/AbstractEntity.java new file mode 100644 index 0000000..94a9803 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/AbstractEntity.java @@ -0,0 +1,88 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.model; + +import java.io.Serializable; + +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.MappedSuperclass; +import javax.persistence.Version; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * Abstract class for JPA entities. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@MappedSuperclass +@Inheritance(strategy = InheritanceType.JOINED) +public abstract class AbstractEntity implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -489637051819304520L; + + private Integer id; + + private Integer version; + + @Override + public boolean equals(Object object) { + return EqualsBuilder.reflectionEquals(this, object); + } + + @Id + @GeneratedValue(strategy = GenerationType.TABLE) + public Integer getId() { + return id; + } + + @Version + public Integer getVersion() { + return version; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + public void setId(Integer id) { + this.id = id; + } + + public void setVersion(Integer version) { + this.version = version; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/AbstractEntity_.java b/primefaces-webapp/src/main/java/com/mycompany/model/AbstractEntity_.java new file mode 100644 index 0000000..f706cdf --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/AbstractEntity_.java @@ -0,0 +1,14 @@ +package com.mycompany.model; + +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.StaticMetamodel; + +@StaticMetamodel(AbstractEntity.class) +public abstract class AbstractEntity_ { + + public static volatile SingularAttribute id; + public static volatile SingularAttribute hashCode; + public static volatile SingularAttribute version; + +} + diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/ActiveUsers.java b/primefaces-webapp/src/main/java/com/mycompany/model/ActiveUsers.java new file mode 100644 index 0000000..2bc520c --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/ActiveUsers.java @@ -0,0 +1,48 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.model; + +import java.util.ArrayList; + +import javax.faces.bean.ApplicationScoped; +import javax.faces.bean.ManagedBean; + +/** + * Application-scoped JSF managed bean storing {@link User} objects for presence + * purposes. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@ManagedBean +@ApplicationScoped +public class ActiveUsers extends ArrayList { + + /** + * + */ + private static final long serialVersionUID = -3068333669859836249L; + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/City.java b/primefaces-webapp/src/main/java/com/mycompany/model/City.java new file mode 100644 index 0000000..31471ce --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/City.java @@ -0,0 +1,91 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.model; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.ManyToOne; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; + +import com.mycompany.util.Queries; + +/** + * JPA entity class for city data. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@Entity +@NamedQueries(@NamedQuery( name = Queries.CITY_FIND_BY_NAME_AND_PROVINCE_STATE, + query = "select c from City c where c.name = ?1 and c.provinceState = ?2")) +public class City extends AbstractEntity { + + /** + * + */ + private static final long serialVersionUID = -1124357744815785459L; + + private Double latitude; + + private Double longitude; + + private String name; + + private ProvinceState provinceState; + + public Double getLatitude() { + return latitude; + } + + public Double getLongitude() { + return longitude; + } + + public String getName() { + return name; + } + + @ManyToOne(fetch = FetchType.EAGER) + public ProvinceState getProvinceState() { + return provinceState; + } + + public void setLatitude(Double latitude) { + this.latitude = latitude; + } + + public void setLongitude(Double longitude) { + this.longitude = longitude; + } + + public void setName(String name) { + this.name = name; + } + + public void setProvinceState(ProvinceState state) { + this.provinceState = state; + } +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/City_.java b/primefaces-webapp/src/main/java/com/mycompany/model/City_.java new file mode 100644 index 0000000..506dc06 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/City_.java @@ -0,0 +1,15 @@ +package com.mycompany.model; + +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.StaticMetamodel; + +@StaticMetamodel(City.class) +public abstract class City_ extends com.mycompany.model.AbstractEntity_ { + + public static volatile SingularAttribute provinceState; + public static volatile SingularAttribute name; + public static volatile SingularAttribute longitude; + public static volatile SingularAttribute latitude; + +} + diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/Content.java b/primefaces-webapp/src/main/java/com/mycompany/model/Content.java new file mode 100644 index 0000000..d8d580b --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/Content.java @@ -0,0 +1,101 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.model; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.ManyToOne; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.persistence.UniqueConstraint; + +import com.mycompany.util.Queries; + +/** + * JPA entity for content data. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@Entity +@Table(uniqueConstraints = @UniqueConstraint(columnNames = "viewid")) +@NamedQueries(@NamedQuery( name = Queries.CONTENT_FIND_BY_NAME, + query = "select c from Content c where c.viewId=?1")) +public class Content extends AbstractEntity { + + /** + * + */ + private static final long serialVersionUID = 5714237132670562107L; + + private User createdBy; + + private Date createdDate; + + private String viewId; + + private String value; + + @ManyToOne + public User getCreatedBy() { + return createdBy; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getCreatedDate() { + return createdDate; + } + + public String getViewId() { + return viewId; + } + + @Column(columnDefinition = "TEXT") + public String getValue() { + return value; + } + + public void setCreatedBy(User createdBy) { + this.createdBy = createdBy; + } + + public void setCreatedDate(Date createdDate) { + this.createdDate = createdDate; + } + + public void setViewId(String name) { + this.viewId = name; + } + + public void setValue(String value) { + this.value = value; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/Content_.java b/primefaces-webapp/src/main/java/com/mycompany/model/Content_.java new file mode 100644 index 0000000..a8a845a --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/Content_.java @@ -0,0 +1,16 @@ +package com.mycompany.model; + +import java.util.Date; +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.StaticMetamodel; + +@StaticMetamodel(Content.class) +public abstract class Content_ extends com.mycompany.model.AbstractEntity_ { + + public static volatile SingularAttribute createdBy; + public static volatile SingularAttribute value; + public static volatile SingularAttribute createdDate; + public static volatile SingularAttribute viewId; + +} + diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/Country.java b/primefaces-webapp/src/main/java/com/mycompany/model/Country.java new file mode 100644 index 0000000..bd43e96 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/Country.java @@ -0,0 +1,103 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.model; + +import java.util.HashSet; +import java.util.Set; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.OneToMany; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +import com.mycompany.util.Queries; + +/** + * JPA entity for country data. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@Entity +@NamedQueries({ @NamedQuery(name = Queries.COUNTRY_FIND_BY_CODE, + query = "select c from Country c where c.code = ?1"), + @NamedQuery(name = Queries.COUNTRY_FIND_ALL, + query = "select c from Country c order by c.name") }) +public class Country extends AbstractEntity { + + private static final String[] excludeFields = new String[] { "provinceStates" }; + + /** + * + */ + private static final long serialVersionUID = -4925972235656394450L; + + private String code; + + private String name; + + private Set provinceStates = new HashSet(); + + @Override + public boolean equals(Object object) { + return EqualsBuilder.reflectionEquals(this, object, excludeFields); + } + + public String getCode() { + return code; + } + + public String getName() { + return name; + } + + @OneToMany( mappedBy = "country", + fetch = FetchType.EAGER) + public Set getProvinceStates() { + return provinceStates; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this, excludeFields); + } + + public void setCode(String code) { + this.code = code; + } + + public void setName(String name) { + this.name = name; + } + + public void setProvinceStates(Set states) { + this.provinceStates = states; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/Country_.java b/primefaces-webapp/src/main/java/com/mycompany/model/Country_.java new file mode 100644 index 0000000..596c0de --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/Country_.java @@ -0,0 +1,16 @@ +package com.mycompany.model; + +import javax.persistence.metamodel.SetAttribute; +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.StaticMetamodel; + +@StaticMetamodel(Country.class) +public abstract class Country_ extends com.mycompany.model.AbstractEntity_ { + + public static volatile SetAttribute provinceStates; + public static volatile SingularAttribute name; + public static volatile SingularAttribute hashCode; + public static volatile SingularAttribute code; + +} + diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/Credentials.java b/primefaces-webapp/src/main/java/com/mycompany/model/Credentials.java new file mode 100644 index 0000000..030907f --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/Credentials.java @@ -0,0 +1,58 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.model; + +import javax.enterprise.inject.Model; + +/** + * CDI-managed bean in request scope for user credentials. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@Model +public class Credentials { + + private String password; + + private String username; + + public String getPassword() { + return password; + } + + public String getUsername() { + return username; + } + + public void setPassword(String password) { + this.password = password; + } + + public void setUsername(String username) { + this.username = username; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/Event.java b/primefaces-webapp/src/main/java/com/mycompany/model/Event.java new file mode 100644 index 0000000..c3274fc --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/Event.java @@ -0,0 +1,162 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.model; + +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.ManyToOne; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.OneToMany; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +import com.mycompany.util.Queries; + +/** + * JPA entity for event data. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@Entity +@NamedQueries(@NamedQuery( name = Queries.EVENT_FIND_ALL, + query = "select e from Event e order by e.startDate desc")) +public class Event extends AbstractEntity { + + private static final String[] excludedFields = new String[] { "attendance" }; + + /** + * + */ + private static final long serialVersionUID = 1853185041344918956L; + + private Set attendance = new HashSet(); + + private User createdBy; + + private String description; + + private Date endDate; + + private EventType eventType; + + private Date startDate; + + private String title; + + private Venue venue; + + @Override + public boolean equals(Object object) { + return EqualsBuilder.reflectionEquals(this, object, excludedFields); + } + + @OneToMany( cascade = CascadeType.REMOVE, + mappedBy = "event") + public Set getAttendance() { + return attendance; + } + + @ManyToOne + public User getCreatedBy() { + return createdBy; + } + + public String getDescription() { + return description; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getEndDate() { + return endDate; + } + + @Enumerated(EnumType.STRING) + public EventType getEventType() { + return eventType; + } + + @Temporal(TemporalType.TIMESTAMP) + public Date getStartDate() { + return startDate; + } + + public String getTitle() { + return title; + } + + @ManyToOne + public Venue getVenue() { + return venue; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this, excludedFields); + } + + public void setAttendance(Set usersAttended) { + this.attendance = usersAttended; + } + + public void setCreatedBy(User createdBy) { + this.createdBy = createdBy; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setEndDate(Date endDate) { + this.endDate = endDate; + } + + public void setEventType(EventType eventType) { + this.eventType = eventType; + } + + public void setStartDate(Date startDate) { + this.startDate = startDate; + } + + public void setTitle(String title) { + this.title = title; + } + + public void setVenue(Venue venue) { + this.venue = venue; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/EventAttendance.java b/primefaces-webapp/src/main/java/com/mycompany/model/EventAttendance.java new file mode 100644 index 0000000..0b9304b --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/EventAttendance.java @@ -0,0 +1,100 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.model; + +import javax.persistence.Entity; +import javax.persistence.ManyToOne; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.Table; +import javax.persistence.UniqueConstraint; + +import com.mycompany.util.Queries; + +/** + * JPA entity for user event attendance data. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@Entity +@Table(uniqueConstraints = @UniqueConstraint(columnNames = { "event", "user" })) +@NamedQueries({ + @NamedQuery(name = Queries.EVENT_ATTENDANCE_FIND_BY_USER_AND_EVENT, + query = "select e from EventAttendance e where e.user = ?1 and e.event = ?2"), + @NamedQuery(name = Queries.EVENT_ATTENDANCE_FIND_BY_USER, + query = "select e from EventAttendance e where e.user = ?1 order by e.event.startDate desc"), + @NamedQuery(name = Queries.EVENT_ATTENDANCE_FIND_GENDER_COUNT_BY_EVENT, + query = "select e.event.startDate, count(e.user.gender) from EventAttendance e where e.user.gender = ?1 and e.confirmed is true group by e.event order by e.event.startDate ") }) +public class EventAttendance extends AbstractEntity { + + /** + * + */ + private static final long serialVersionUID = -4351135973935030713L; + + private boolean confirmed; + + private Event event; + + private int rating; + + private User user; + + @ManyToOne + public Event getEvent() { + return event; + } + + public int getRating() { + return rating; + } + + @ManyToOne + public User getUser() { + return user; + } + + public boolean isConfirmed() { + return confirmed; + } + + public void setConfirmed(boolean attended) { + this.confirmed = attended; + } + + public void setEvent(Event event) { + this.event = event; + } + + public void setRating(int rating) { + this.rating = rating; + } + + public void setUser(User user) { + this.user = user; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/EventAttendance_.java b/primefaces-webapp/src/main/java/com/mycompany/model/EventAttendance_.java new file mode 100644 index 0000000..b3cbbc6 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/EventAttendance_.java @@ -0,0 +1,15 @@ +package com.mycompany.model; + +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.StaticMetamodel; + +@StaticMetamodel(EventAttendance.class) +public abstract class EventAttendance_ extends com.mycompany.model.AbstractEntity_ { + + public static volatile SingularAttribute confirmed; + public static volatile SingularAttribute event; + public static volatile SingularAttribute rating; + public static volatile SingularAttribute user; + +} + diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/EventType.java b/primefaces-webapp/src/main/java/com/mycompany/model/EventType.java new file mode 100644 index 0000000..9ad4a29 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/EventType.java @@ -0,0 +1,47 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.model; + +/** + * Represents an event type. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +public enum EventType { + + CONCERT("Concert"), MOVIE("Movie"), OTHER("Other"); + + private String label; + + private EventType(String label) { + this.label = label; + } + + public String getLabel() { + return label; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/Event_.java b/primefaces-webapp/src/main/java/com/mycompany/model/Event_.java new file mode 100644 index 0000000..387da14 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/Event_.java @@ -0,0 +1,22 @@ +package com.mycompany.model; + +import java.util.Date; +import javax.persistence.metamodel.SetAttribute; +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.StaticMetamodel; + +@StaticMetamodel(Event.class) +public abstract class Event_ extends com.mycompany.model.AbstractEntity_ { + + public static volatile SingularAttribute startDate; + public static volatile SingularAttribute title; + public static volatile SingularAttribute createdBy; + public static volatile SingularAttribute description; + public static volatile SetAttribute attendance; + public static volatile SingularAttribute hashCode; + public static volatile SingularAttribute endDate; + public static volatile SingularAttribute eventType; + public static volatile SingularAttribute venue; + +} + diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/Gender.java b/primefaces-webapp/src/main/java/com/mycompany/model/Gender.java new file mode 100644 index 0000000..10560e5 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/Gender.java @@ -0,0 +1,47 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.model; + +/** + * Represents a gender. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +public enum Gender { + + FEMALE("Female"), MALE("Male"); + + private String label; + + private Gender(String label) { + this.label = label; + } + + public String getLabel() { + return label; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/Idea.java b/primefaces-webapp/src/main/java/com/mycompany/model/Idea.java new file mode 100644 index 0000000..68a1140 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/Idea.java @@ -0,0 +1,119 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.model; + +import java.util.HashSet; +import java.util.Set; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * JPA entity for mind map data. This class is self-referencing and has a + * hierarchical parent-child relationship so an idea can have any number of + * sub-ideas. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@Entity +public class Idea extends AbstractEntity { + + private static final String[] excludeFields = new String[] { "parent", "children" }; + + /** + * + */ + private static final long serialVersionUID = -5778367117092282684L; + + private User author; + + private Set children = new HashSet(); + + private String description; + + private String name; + + private Idea parent; + + @Override + public boolean equals(Object object) { + return EqualsBuilder.reflectionEquals(this, object, excludeFields); + } + + @ManyToOne + public User getAuthor() { + return author; + } + + @OneToMany( mappedBy = "parent", + fetch = FetchType.LAZY) + public Set getChildren() { + return children; + } + + public String getDescription() { + return description; + } + + public String getName() { + return name; + } + + @ManyToOne + public Idea getParent() { + return parent; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this, excludeFields); + } + + public void setAuthor(User author) { + this.author = author; + } + + public void setChildren(Set children) { + this.children = children; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setName(String name) { + this.name = name; + } + + public void setParent(Idea parent) { + this.parent = parent; + } +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/Idea_.java b/primefaces-webapp/src/main/java/com/mycompany/model/Idea_.java new file mode 100644 index 0000000..a86f4f7 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/Idea_.java @@ -0,0 +1,18 @@ +package com.mycompany.model; + +import javax.persistence.metamodel.SetAttribute; +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.StaticMetamodel; + +@StaticMetamodel(Idea.class) +public abstract class Idea_ extends com.mycompany.model.AbstractEntity_ { + + public static volatile SingularAttribute author; + public static volatile SingularAttribute description; + public static volatile SingularAttribute name; + public static volatile SingularAttribute hashCode; + public static volatile SingularAttribute parent; + public static volatile SetAttribute children; + +} + diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/ProvinceState.java b/primefaces-webapp/src/main/java/com/mycompany/model/ProvinceState.java new file mode 100644 index 0000000..24b008a --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/ProvinceState.java @@ -0,0 +1,94 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.model; + +import java.util.HashSet; +import java.util.Set; + +import javax.persistence.Entity; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * JPA entity for province/state data. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@Entity +public class ProvinceState extends AbstractEntity { + + private static final String[] excludeFields = new String[] { "cities" }; + + /** + * + */ + private static final long serialVersionUID = 5984616633801173028L; + + private Set cities = new HashSet(); + + private Country country; + + private String name; + + @Override + public boolean equals(Object object) { + return EqualsBuilder.reflectionEquals(this, object, excludeFields); + } + + @OneToMany(mappedBy = "provinceState") + public Set getCities() { + return cities; + } + + @ManyToOne + public Country getCountry() { + return country; + } + + public String getName() { + return name; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this, excludeFields); + } + + public void setCities(Set cities) { + this.cities = cities; + } + + public void setCountry(Country country) { + this.country = country; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/ProvinceState_.java b/primefaces-webapp/src/main/java/com/mycompany/model/ProvinceState_.java new file mode 100644 index 0000000..223ab66 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/ProvinceState_.java @@ -0,0 +1,16 @@ +package com.mycompany.model; + +import javax.persistence.metamodel.SetAttribute; +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.StaticMetamodel; + +@StaticMetamodel(ProvinceState.class) +public abstract class ProvinceState_ extends com.mycompany.model.AbstractEntity_ { + + public static volatile SetAttribute cities; + public static volatile SingularAttribute name; + public static volatile SingularAttribute hashCode; + public static volatile SingularAttribute country; + +} + diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/RelationshipType.java b/primefaces-webapp/src/main/java/com/mycompany/model/RelationshipType.java new file mode 100644 index 0000000..b1ed719 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/RelationshipType.java @@ -0,0 +1,47 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.model; + +/** + * Represents a relationship type. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +public enum RelationshipType { + + FAMILY("Family"), FRIEND("Friend"), COLLEAGUE("Colleague"); + + private String label; + + private RelationshipType(String label) { + this.label = label; + } + + public String getLabel() { + return label; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/User.java b/primefaces-webapp/src/main/java/com/mycompany/model/User.java new file mode 100644 index 0000000..3fcc998 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/User.java @@ -0,0 +1,243 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.model; + +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.ManyToOne; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.persistence.UniqueConstraint; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +import com.mycompany.util.Queries; + +/** + * JPA entity for user data. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@Entity +@Table( name = "USERS", + uniqueConstraints = { @UniqueConstraint(columnNames = "username"), + @UniqueConstraint(columnNames = "emailaddress") }) +@NamedQueries({ + @NamedQuery(name = Queries.USER_FIND_BY_USERNAME_PASSWORD, + query = "select u from User u where u.username=?1 and u.password=?2"), + @NamedQuery(name = Queries.USER_FIND_BY_RELATIONSHIP_TYPE, + query = "select r.toUser from UserRelationship r where r.relationshipType = ?1 and r.fromUser = ?2 order by r.toUser.lastName, r.toUser.firstName"), + @NamedQuery(name = Queries.USER_FIND_BY_PARTIAL_NAME, + query = "select u from User u where u.firstName like :name or u.lastName like :name order by u.firstName, u.lastName") }) +public class User extends AbstractEntity { + + private static final String[] excludedFields = new String[] { "fromRelationships", + "toRelationships", "eventsAttended" }; + + /** + * + */ + private static final long serialVersionUID = 8009394076089033693L; + + private boolean acceptedTerms; + + private Date birthdate; + + private Integer clickCount; + + private Country country; + + private String emailAddress; + + private Set eventsAttended = new HashSet(); + + private String firstName; + + private Set fromRelationships = new HashSet(); + + private Gender gender; + + private String lastName; + + private String password; + + private String phoneNumber; + + private String theme; + + private Set toRelationships = new HashSet(); + + private String username; + + @Override + public boolean equals(Object object) { + return EqualsBuilder.reflectionEquals(this, object, excludedFields); + } + + @Temporal(TemporalType.DATE) + public Date getBirthdate() { + return birthdate; + } + + public Integer getClickCount() { + return clickCount; + } + + @ManyToOne + public Country getCountry() { + return country; + } + + public String getEmailAddress() { + return emailAddress; + } + + @OneToMany(mappedBy = "user") + public Set getEventsAttended() { + return eventsAttended; + } + + public String getFirstName() { + return firstName; + } + + @OneToMany(mappedBy = "fromUser") + public Set getFromRelationships() { + return fromRelationships; + } + + @Enumerated(EnumType.STRING) + public Gender getGender() { + return gender; + } + + public String getLastName() { + return lastName; + } + + public String getPassword() { + return password; + } + + public String getPhoneNumber() { + return phoneNumber; + } + + public String getTheme() { + return theme; + } + + @OneToMany(mappedBy = "toUser") + public Set getToRelationships() { + return toRelationships; + } + + public String getUsername() { + return username; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this, excludedFields); + } + + @Column(columnDefinition = "smallint not null default 0") + public boolean isAcceptedTerms() { + return acceptedTerms; + } + + public void setAcceptedTerms(boolean acceptedTerms) { + this.acceptedTerms = acceptedTerms; + } + + public void setBirthdate(Date birthdate) { + this.birthdate = birthdate; + } + + public void setClickCount(Integer clicks) { + this.clickCount = clicks; + } + + public void setCountry(Country country) { + this.country = country; + } + + public void setEmailAddress(String emailAddress) { + this.emailAddress = emailAddress; + } + + public void setEventsAttended(Set eventsAttended) { + this.eventsAttended = eventsAttended; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public void setFromRelationships(Set fromRelationships) { + this.fromRelationships = fromRelationships; + } + + public void setGender(Gender gender) { + this.gender = gender; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public void setPassword(String password) { + this.password = password; + } + + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } + + public void setTheme(String theme) { + this.theme = theme; + } + + public void setToRelationships(Set toRelationships) { + this.toRelationships = toRelationships; + } + + public void setUsername(String username) { + this.username = username; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/UserRelationship.java b/primefaces-webapp/src/main/java/com/mycompany/model/UserRelationship.java new file mode 100644 index 0000000..adcd9fc --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/UserRelationship.java @@ -0,0 +1,83 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.model; + +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import javax.persistence.UniqueConstraint; + +/** + * JPA entity for a relationship between two users. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@Entity +@Table(uniqueConstraints = @UniqueConstraint(columnNames = { "from_user", "to_user", + "relationshipType" })) +public class UserRelationship extends AbstractEntity { + + /** + * + */ + private static final long serialVersionUID = -5157091586647676960L; + + private RelationshipType relationshipType; + + private User fromUser; + + private User toUser; + + @Enumerated(EnumType.STRING) + public RelationshipType getRelationshipType() { + return relationshipType; + } + + @ManyToOne + public User getFromUser() { + return fromUser; + } + + @ManyToOne + public User getToUser() { + return toUser; + } + + public void setRelationshipType(RelationshipType contactType) { + this.relationshipType = contactType; + } + + public void setFromUser(User firstUser) { + this.fromUser = firstUser; + } + + public void setToUser(User secondUser) { + this.toUser = secondUser; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/UserRelationship_.java b/primefaces-webapp/src/main/java/com/mycompany/model/UserRelationship_.java new file mode 100644 index 0000000..9780702 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/UserRelationship_.java @@ -0,0 +1,14 @@ +package com.mycompany.model; + +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.StaticMetamodel; + +@StaticMetamodel(UserRelationship.class) +public abstract class UserRelationship_ extends com.mycompany.model.AbstractEntity_ { + + public static volatile SingularAttribute relationshipType; + public static volatile SingularAttribute toUser; + public static volatile SingularAttribute fromUser; + +} + diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/User_.java b/primefaces-webapp/src/main/java/com/mycompany/model/User_.java new file mode 100644 index 0000000..bd4eeb9 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/User_.java @@ -0,0 +1,29 @@ +package com.mycompany.model; + +import java.util.Date; +import javax.persistence.metamodel.SetAttribute; +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.StaticMetamodel; + +@StaticMetamodel(User.class) +public abstract class User_ extends com.mycompany.model.AbstractEntity_ { + + public static volatile SingularAttribute acceptedTerms; + public static volatile SingularAttribute lastName; + public static volatile SingularAttribute clickCount; + public static volatile SetAttribute fromRelationships; + public static volatile SingularAttribute theme; + public static volatile SingularAttribute hashCode; + public static volatile SingularAttribute emailAddress; + public static volatile SetAttribute toRelationships; + public static volatile SingularAttribute password; + public static volatile SingularAttribute country; + public static volatile SingularAttribute username; + public static volatile SetAttribute eventsAttended; + public static volatile SingularAttribute phoneNumber; + public static volatile SingularAttribute birthdate; + public static volatile SingularAttribute gender; + public static volatile SingularAttribute firstName; + +} + diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/Venue.java b/primefaces-webapp/src/main/java/com/mycompany/model/Venue.java new file mode 100644 index 0000000..6bbd4ad --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/Venue.java @@ -0,0 +1,180 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.model; + +import java.util.HashSet; +import java.util.Set; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Transient; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * JPA entity for venue data. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@Entity +public class Venue extends AbstractEntity { + + private static final String[] excludedFields = new String[] { "events" }; + + /** + * + */ + private static final long serialVersionUID = 5049478213946349124L; + + private City city; + + private Country country; + + private Set events = new HashSet(); + + private Double latitude; + + private Double longitude; + + private String name; + + private String phoneNumber; + + private ProvinceState provinceState; + + private String streetAddress; + + @Override + public boolean equals(Object object) { + return EqualsBuilder.reflectionEquals(this, object, excludedFields); + } + + @ManyToOne(cascade = CascadeType.PERSIST) + public City getCity() { + return city; + } + + /** + * This method returns the complete address of the venue. + * + * @return A string. + */ + @Transient + public String getCompleteAddress() { + StringBuilder sb = new StringBuilder(); + sb.append(streetAddress); + sb.append(", "); + sb.append(city.getName()); + sb.append(", "); + sb.append(provinceState.getName()); + sb.append(", "); + sb.append(country.getName()); + return sb.toString(); + } + + @ManyToOne + public Country getCountry() { + return country; + } + + @OneToMany( cascade = CascadeType.REMOVE, + mappedBy = "venue") + public Set getEvents() { + return events; + } + + @Transient + public Double getLatitude() { + return latitude; + } + + @Transient + public Double getLongitude() { + return longitude; + } + + public String getName() { + return name; + } + + public String getPhoneNumber() { + return phoneNumber; + } + + @ManyToOne + public ProvinceState getProvinceState() { + return provinceState; + } + + public String getStreetAddress() { + return streetAddress; + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this, excludedFields); + } + + public void setCity(City city) { + this.city = city; + } + + public void setCountry(Country country) { + this.country = country; + } + + public void setEvents(Set events) { + this.events = events; + } + + public void setLatitude(Double latitude) { + this.latitude = latitude; + } + + public void setLongitude(Double longitude) { + this.longitude = longitude; + } + + public void setName(String name) { + this.name = name; + } + + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } + + public void setProvinceState(ProvinceState state) { + this.provinceState = state; + } + + public void setStreetAddress(String streetAddress) { + this.streetAddress = streetAddress; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/model/Venue_.java b/primefaces-webapp/src/main/java/com/mycompany/model/Venue_.java new file mode 100644 index 0000000..7ae5977 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/model/Venue_.java @@ -0,0 +1,20 @@ +package com.mycompany.model; + +import javax.persistence.metamodel.SetAttribute; +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.StaticMetamodel; + +@StaticMetamodel(Venue.class) +public abstract class Venue_ extends com.mycompany.model.AbstractEntity_ { + + public static volatile SingularAttribute streetAddress; + public static volatile SingularAttribute provinceState; + public static volatile SingularAttribute phoneNumber; + public static volatile SetAttribute events; + public static volatile SingularAttribute name; + public static volatile SingularAttribute hashCode; + public static volatile SingularAttribute country; + public static volatile SingularAttribute city; + +} + diff --git a/primefaces-webapp/src/main/java/com/mycompany/service/ChartService.java b/primefaces-webapp/src/main/java/com/mycompany/service/ChartService.java new file mode 100644 index 0000000..c257c9c --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/service/ChartService.java @@ -0,0 +1,50 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.service; + +import java.util.List; + +import com.mycompany.model.Gender; + +/** + * Interface for a chart service. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +public interface ChartService { + + /** + * Finds all event attendance data by gender. + * + * @param gender + * The {@link Gender} enum. + * @return A List of Object arrays. First element is the event date, second + * element is the number of people by gender who attended this + * event. + */ + List findEventAttendanceByGender(Gender gender); + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/service/ContentService.java b/primefaces-webapp/src/main/java/com/mycompany/service/ContentService.java new file mode 100644 index 0000000..1694619 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/service/ContentService.java @@ -0,0 +1,55 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.service; + +import com.mycompany.model.Content; + +/** + * Interface for a content service. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +public interface ContentService { + + /** + * Finds a {@link Content} object by name. + * + * @param name + * The name to find. + * @return A Content object. + */ + Content findContentByName(String name); + + /** + * Saves a {@link Content} object. + * + * @param content + * The object to save. + * @return The saved object. + */ + Content saveContent(Content content); + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/service/CountryService.java b/primefaces-webapp/src/main/java/com/mycompany/service/CountryService.java new file mode 100644 index 0000000..d6b90b5 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/service/CountryService.java @@ -0,0 +1,150 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.service; + +import java.util.List; + +import javax.enterprise.event.Observes; +import javax.servlet.ServletContext; + +import com.mycompany.lifecycle.Initialized; +import com.mycompany.model.City; +import com.mycompany.model.Country; +import com.mycompany.model.ProvinceState; + +/** + * Service class for country-related operations. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +public interface CountryService { + + /** + * Creates a {@link ProvinceState} object for a particular {@link Country}. + * + * @param country + * The Country in which the ProvinceState is located. + * @param value + * The name of the ProvinceState. + * @return The newly created ProvinceState object. + */ + ProvinceState createProvinceState(Country country, String value); + + /** + * Finds a list of {@link City} objects for the given {@link ProvinceState}. + * + * @param provinceState + * The ProvinceState object for which to find cities. + * @return A List of City objects. + */ + List findCitiesByState(ProvinceState provinceState); + + /** + * Finds a {@link City} by name in the {@link ProvinceState}. + * + * @param name + * The name of the city. + * @param provinceState + * The province/state in which to find the city. + * @return A City object. + */ + City findCity(String name, ProvinceState provinceState); + + /** + * Finds a {@link City} object by ID. + * + * @param id + * The ID of the city. + * @return A City object. + */ + City findCityById(Integer id); + + /** + * Finds a {@link Country} object by ID. + * + * @param id + * The ID of the country. + * @return A Country object. + */ + Country findCountryById(Integer id); + + /** + * Finds a {@link List} of {@link ProvinceState} objects for a particular + * {@link Country}. + * + * @param country + * The Country object. + * @return A List of ProvinceState objects. + */ + List findProvinceStatesByCountry(Country country); + + /** + * Finds a {@link ProvinceState} object by ID. + * + * @param id + * The ID of the ProvinceState object. + * @return A ProvinceState object. + */ + ProvinceState findStateById(Integer id); + + /** + * Finds a {@link ProvinceState} object by name within a particular + * {@link Country}. + * + * @param country + * The Country object. + * @param name + * The name of the ProvinceState to find. + * @return A ProvinceState object. + */ + ProvinceState findStateByName(Country country, String name); + + /** + * Returns all {@link Country} objects. + * + * @return A List of Country objects. + */ + List getCountries(); + + /** + * Returns all {@link ProvinceState} objects. + * + * @return A List of ProvinceState objects. + */ + List getProvinceStates(); + + /** + * Invoked during the {@link ServletContext} initialization to populate the + * database with sample data. + * + * @param context + * The {@link ServletContext} object. + * @throws Exception + * If something goes wrong. + */ + void init(@Observes @Initialized ServletContext context) throws Exception; + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/service/EventService.java b/primefaces-webapp/src/main/java/com/mycompany/service/EventService.java new file mode 100644 index 0000000..0fe35ed --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/service/EventService.java @@ -0,0 +1,131 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.service; + +import java.util.Date; +import java.util.List; + +import com.mycompany.model.City; +import com.mycompany.model.Event; +import com.mycompany.model.EventAttendance; +import com.mycompany.model.EventType; +import com.mycompany.model.ProvinceState; +import com.mycompany.model.User; + +/** + * Interfaces for an event service. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +public interface EventService { + + /** + * Finds all {@link Event} objects. + * + * @return A List of Event objects. + */ + List findAllEvents(); + + /** + * Finds all {@link EventAttendance} objects for a particular {@link User}. + * + * @param user + * The User object. + * @return A List of EventAttendance objects. + */ + List findAllEventsAttendanceByUser(User user); + + /** + * Finds the {@link EventAttendance} object for a particular {@link Event} + * and {@link User}. + * + * @param event + * The Event object. + * @param user + * The User object. + * @return An EventAttendance object. + */ + EventAttendance findEventAttendance(Event event, User user); + + /** + * Finds an {@link Event} by ID. + * + * @param id + * The Event ID. + * @return An Event object. + */ + Event findEventById(Integer id); + + /** + * Finds a List of {@link Event} objects in a {@link City} and + * {@link ProvinceState} for a particular {@link EventType} and keyword. + * + * @param city + * The City object. + * @param provinceState + * The ProvinceState object. + * @param eventType + * The EventType object. + * @param keyword + * A keyword. + * @return A List of Event objects. + */ + List findEvents(City city, ProvinceState provinceState, EventType eventType, + String keyword); + + /** + * Finds a List of {@link Event} objects between a start and end date + * created by a particular {@link User}. + * + * @param start + * The start date. + * @param end + * The end date. + * @param user + * The User object. + * @return A List of Event objects. + */ + List findUserEvents(Date start, Date end, User user); + + /** + * Saves an {@link EventAttendance} object. + * + * @param attendance + * The EventAttendance object. + * @return The saved object. + */ + EventAttendance saveAttendance(EventAttendance attendance); + + /** + * Saves an {@link Event}. + * + * @param event + * The Event object. + * @return The saved object. + */ + Event saveEvent(Event event); + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/service/IdeaService.java b/primefaces-webapp/src/main/java/com/mycompany/service/IdeaService.java new file mode 100644 index 0000000..1e1d817 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/service/IdeaService.java @@ -0,0 +1,76 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.service; + +import java.util.List; + +import org.primefaces.model.mindmap.MindmapNode; + +import com.mycompany.model.Idea; + +/** + * Interface for an idea service. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +public interface IdeaService { + + /** + * Populates a mind map data structure from an {@link Idea} using the + * {@link MindmapNode} interface. + * + * @param idea + * The {@link Idea} object. + * @param root + * The root of the mind map tree. + */ + void buildMindMap(Idea idea, MindmapNode root); + + /** + * Finds an {@link Idea} by ID. + * + * @param id + * The Idea object's ID. + * @return An Idea object. + */ + Idea findIdea(Integer id); + + /** + * Finds a list of {@link Idea} objects. + * + * @return + */ + List findIdeas(); + + /** + * Saves an {@link Idea} object. + * + * @param newIdea + * The Idea to save. + * @return The saved Idea. + */ + Idea saveIdea(Idea newIdea); +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/service/UserService.java b/primefaces-webapp/src/main/java/com/mycompany/service/UserService.java new file mode 100644 index 0000000..34cde9f --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/service/UserService.java @@ -0,0 +1,130 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.service; + +import java.util.List; + +import com.mycompany.model.RelationshipType; +import com.mycompany.model.User; +import com.mycompany.model.UserRelationship; + +/** + * Interface for user service. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +public interface UserService { + + /** + * Finds a {@link UserRelationship} object representing a relationship + * between two {@link User} objects. + * + * @param user1 + * The first user. + * @param user2 + * The second user. + * @return A UserRelationship object. + */ + UserRelationship findRelationshipToUser(User user1, User user2); + + /** + * Finds a {@link User} with the given username and password. Used for + * authentication. + * + * @param username + * The username. + * @param password + * The password. + * @return A User object if found. + */ + User findUser(String username, String password); + + /** + * Finds a {@link User} by ID. + * + * @param id + * The user's ID. + * @return A User object. + */ + User findUserById(Integer id); + + /** + * Finds a {@link User} by username. + * + * @param username + * The username. + * @return A User object. + */ + User findUserByUsername(String username); + + /** + * Finds a List of all {@link User} objects. + * + * @return A List of User objects. + */ + List findUsers(); + + /** + * Finds a List of {@link User} objects that have a first name or last name + * that partially matches the suggestion string. + * + * @param suggest + * The partial string. + * @return A List of User objects. + */ + List findUsersByName(String suggest); + + /** + * Finds a List of {@link User} objects that are related to the {@link User} + * according to the specified {@link RelationshipType}. + * + * @param type + * The {@link RelationshipType} object. + * @param user + * The {@link User} object. + * @return A List of {@link User} objects. + */ + List findUsersByType(RelationshipType type, User user); + + /** + * Saves a {@link UserRelationship} object. + * + * @param relationship + * The UserRelationship to save. + * @return The saved object. + */ + UserRelationship saveRelationship(UserRelationship relationship); + + /** + * Saves a {@link User} object. + * + * @param user + * The user to save. + * @return The saved object. + */ + User saveUser(User user); + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/service/VenueService.java b/primefaces-webapp/src/main/java/com/mycompany/service/VenueService.java new file mode 100644 index 0000000..8ebe3e5 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/service/VenueService.java @@ -0,0 +1,72 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.service; + +import java.util.List; + +import com.mycompany.model.Venue; + +/** + * Interface for a venue service. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +public interface VenueService { + + /** + * Deletes a {@link Venue} object. + * + * @param venue + * The Venue to delete. + */ + void deleteVenue(Venue venue); + + /** + * Finds a {@link Venue} object by ID. + * + * @param id + * The ID of the Venue. + * @return The Venue object. + */ + Venue findVenueById(Integer id); + + /** + * Finds a {@link List} of all {@link Venue} objects. + * + * @return A List of Venue objects. + */ + List findVenues(); + + /** + * Saves a {@link Venue} object. + * + * @param venue + * The Venue to save. + * @return The saved object. + */ + Venue saveVenue(Venue venue); + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/service/impl/AbstractService.java b/primefaces-webapp/src/main/java/com/mycompany/service/impl/AbstractService.java new file mode 100644 index 0000000..4d42834 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/service/impl/AbstractService.java @@ -0,0 +1,39 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.service.impl; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class AbstractService { + + @PersistenceContext + protected EntityManager em; + + protected Logger logger = LoggerFactory.getLogger(getClass()); +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/service/impl/ChartServiceImpl.java b/primefaces-webapp/src/main/java/com/mycompany/service/impl/ChartServiceImpl.java new file mode 100644 index 0000000..d5c5b17 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/service/impl/ChartServiceImpl.java @@ -0,0 +1,48 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.service.impl; + +import java.util.List; + +import javax.ejb.Stateless; +import javax.inject.Named; +import javax.persistence.Query; + +import com.mycompany.model.Gender; +import com.mycompany.service.ChartService; +import com.mycompany.util.Queries; + +@Named("chartService") +@Stateless +public class ChartServiceImpl extends AbstractService implements ChartService { + + @Override + @SuppressWarnings("unchecked") + public List findEventAttendanceByGender(Gender gender) { + Query query = em.createNamedQuery(Queries.EVENT_ATTENDANCE_FIND_GENDER_COUNT_BY_EVENT); + List genderResults = query.setParameter(1, gender).getResultList(); + return genderResults; + } +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/service/impl/ContentServiceImpl.java b/primefaces-webapp/src/main/java/com/mycompany/service/impl/ContentServiceImpl.java new file mode 100644 index 0000000..5d420fa --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/service/impl/ContentServiceImpl.java @@ -0,0 +1,65 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.service.impl; + +import javax.ejb.Stateless; +import javax.inject.Named; +import javax.persistence.NoResultException; +import javax.persistence.TypedQuery; + +import com.mycompany.model.Content; +import com.mycompany.service.ContentService; +import com.mycompany.util.Queries; + +@Named("contentService") +@Stateless +public class ContentServiceImpl extends AbstractService implements ContentService { + + @Override + public Content findContentByName(String name) { + Content found = null; + try { + TypedQuery query = em.createNamedQuery(Queries.CONTENT_FIND_BY_NAME, + Content.class); + query.setParameter(1, name); + found = query.getSingleResult(); + } catch (NoResultException e) { + logger.info("No content found: {}", name); + } + return found; + } + + @Override + public Content saveContent(Content content) { + Content saved = content; + if (content.getVersion() == null) { + em.persist(content); + } else { + saved = em.merge(content); + } + return saved; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/service/impl/CountryServiceImpl.java b/primefaces-webapp/src/main/java/com/mycompany/service/impl/CountryServiceImpl.java new file mode 100644 index 0000000..3761d44 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/service/impl/CountryServiceImpl.java @@ -0,0 +1,226 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.service.impl; + +import java.io.InputStream; +import java.util.List; +import java.util.Scanner; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.ejb.Stateless; +import javax.enterprise.event.Observes; +import javax.inject.Named; +import javax.persistence.NoResultException; +import javax.persistence.TypedQuery; +import javax.servlet.ServletContext; +import javax.transaction.UserTransaction; + +import com.mycompany.lifecycle.Initialized; +import com.mycompany.lifecycle.ServletContextLifecycleNotifier; +import com.mycompany.model.City; +import com.mycompany.model.Country; +import com.mycompany.model.ProvinceState; +import com.mycompany.service.CountryService; +import com.mycompany.util.Queries; + +/** + *

+ * Controller class for countries. Since this class holds application-wide + * state, namely a list of {@link Country} objects, we annotate it as an + * application-scoped CDI bean. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@Named("countryService") +@Stateless +public class CountryServiceImpl extends AbstractService implements CountryService { + + public ProvinceState createProvinceState(Country country, String name) { + ProvinceState state = null; + try { + // tx.begin(); + state = new ProvinceState(); + state.setName(name); + state.setCountry(country); + country.getProvinceStates().add(state); + em.persist(state); + // tx.commit(); + } catch (Exception e) { + logger.error("Unable to create province/state object:", e); + } + return state; + } + + public List findCitiesByState(ProvinceState state) { + String jql = "select c from City c where c.provinceState = ?1 order by c.name"; + TypedQuery query = em.createQuery(jql, City.class); + query.setParameter(1, state); + return query.getResultList(); + } + + public City findCity(String name, ProvinceState provinceState) { + City city = null; + try { + TypedQuery query = em.createNamedQuery( + Queries.CITY_FIND_BY_NAME_AND_PROVINCE_STATE, City.class); + query.setParameter(1, name); + query.setParameter(2, provinceState); + city = query.getSingleResult(); + } catch (NoResultException e) { + } + return city; + } + + public City findCityById(Integer id) { + return em.find(City.class, id); + } + + private Country findCountryByCode(String countryCode) { + return (Country) em.createNamedQuery(Queries.COUNTRY_FIND_BY_CODE) + .setParameter(1, countryCode) + .getSingleResult(); + } + + public Country findCountryById(Integer id) { + return em.find(Country.class, id); + } + + @Override + public List findProvinceStatesByCountry(Country country) { + String jql = "select p from ProvinceState p where p.country = ?1 order by p.name"; + TypedQuery query = em.createQuery(jql, ProvinceState.class); + query.setParameter(1, country); + return query.getResultList(); + } + + public ProvinceState findStateById(Integer id) { + return em.find(ProvinceState.class, id); + } + + public ProvinceState findStateByName(Country country, String stateName) { + if (country == null) { + return null; + } + for (ProvinceState state : country.getProvinceStates()) { + if (state.getName().equals(stateName)) { + return state; + } + } + return null; + } + + @Override + @SuppressWarnings("unchecked") + public List getCountries() { + return em.createNamedQuery(Queries.COUNTRY_FIND_ALL).getResultList(); + } + + @Override + public List getProvinceStates() { + String jql = "select p from ProvinceState p where p.country.code = 'US' order by p.name"; + TypedQuery query = em.createQuery(jql, ProvinceState.class); + return query.getResultList(); + } + + private void importCities() { + InputStream in = getClass().getResourceAsStream("/cities.txt"); + Scanner scanner = new Scanner(in); + Pattern pattern = Pattern.compile("([^:]+):([^:]+):([^:]+):(.*)"); + Matcher matcher = null; + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + matcher = pattern.matcher(line); + if (matcher.find()) { + String countryCode = matcher.group(1); + String stateName = matcher.group(2); + String cityName = matcher.group(3); + String coords = matcher.group(4); + String[] array = coords.split(","); + Double latitude = Double.parseDouble(array[0]); + Double longitude = Double.parseDouble(array[1]); + Country country = findCountryByCode(countryCode); + ProvinceState state = findStateByName(country, stateName); + if (state == null) { + state = new ProvinceState(); + state.setName(stateName); + state.setCountry(country); + country.getProvinceStates().add(state); + em.persist(state); + } + City city = new City(); + city.setName(cityName); + city.setProvinceState(state); + city.setLatitude(latitude); + city.setLongitude(longitude); + state.getCities().add(city); + em.persist(city); + } + } + } + + private void importCountries() { + InputStream in = getClass().getResourceAsStream("/countries.txt"); + Scanner scanner = new Scanner(in); + Pattern pattern = Pattern.compile("([A-Z]+):(.*)"); + Matcher matcher = null; + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + matcher = pattern.matcher(line); + if (matcher.find()) { + String isoCode = matcher.group(1); + String countryName = matcher.group(2); + Country country = new Country(); + country.setCode(isoCode); + country.setName(countryName); + em.persist(country); + } + } + } + + /** + * This method is responsible for initializing a List of Country objects + * when the web application is started. We use the CDI event handling system + * combined with the custom {@link Initialized} event to ensure this method + * is called at startup time. Note: since this class is not an EJB, to + * insert data we have to use bean-managed transactions with the + * {@link UserTransaction}. + * + * @param context + * @throws Exception + * @see ServletContextLifecycleNotifier + */ + @Override + public void init(@Observes @Initialized ServletContext context) throws Exception { + List countries = getCountries(); + if (countries == null || countries.isEmpty()) { + logger.info("Importing country and city data..."); + importCountries(); + importCities(); + } + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/service/impl/EventServiceImpl.java b/primefaces-webapp/src/main/java/com/mycompany/service/impl/EventServiceImpl.java new file mode 100644 index 0000000..cd8e753 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/service/impl/EventServiceImpl.java @@ -0,0 +1,153 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.service.impl; + +import java.util.Date; +import java.util.List; + +import javax.ejb.Stateless; +import javax.inject.Named; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Join; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +import com.mycompany.model.City; +import com.mycompany.model.City_; +import com.mycompany.model.Event; +import com.mycompany.model.EventAttendance; +import com.mycompany.model.EventType; +import com.mycompany.model.Event_; +import com.mycompany.model.ProvinceState; +import com.mycompany.model.User; +import com.mycompany.model.Venue; +import com.mycompany.model.Venue_; +import com.mycompany.service.EventService; +import com.mycompany.util.Queries; + +@Named("eventService") +@Stateless +public class EventServiceImpl extends AbstractService implements EventService { + + @Override + public List findAllEvents() { + return em.createNamedQuery(Queries.EVENT_FIND_ALL, Event.class).getResultList(); + } + + @Override + public List findAllEventsAttendanceByUser(User user) { + TypedQuery query = em.createNamedQuery( + Queries.EVENT_ATTENDANCE_FIND_BY_USER, EventAttendance.class); + query.setParameter(1, user); + return query.getResultList(); + } + + @Override + public EventAttendance findEventAttendance(Event event, User user) { + TypedQuery query = em.createNamedQuery( + Queries.EVENT_ATTENDANCE_FIND_BY_USER_AND_EVENT, EventAttendance.class); + query.setParameter(1, user); + query.setParameter(2, event); + List resultList = query.getResultList(); + if (!resultList.isEmpty()) { + return resultList.get(0); + } + return null; + } + + @Override + public Event findEventById(Integer id) { + return em.find(Event.class, id); + } + + @Override + public List findUserEvents(Date start, Date end, User user) { + String jql = "select evt from Event evt where evt.createdBy = ?1 and evt.startDate between ?2 and ?3"; + TypedQuery query = em.createQuery(jql, Event.class); + query.setParameter(1, user); + query.setParameter(2, start); + query.setParameter(3, end); + List events = query.getResultList(); + return events; + } + + @Override + public EventAttendance saveAttendance(EventAttendance attendance) { + EventAttendance saved = attendance; + if (attendance.getVersion() == null) { + em.persist(attendance); + } else { + saved = em.merge(attendance); + } + return saved; + } + + @Override + public Event saveEvent(Event event) { + Event saved = event; + if (event.getVersion() == null) { + em.persist(event); + } else { + saved = em.merge(event); + } + return saved; + } + + @Override + public List findEvents(City city, ProvinceState provinceState, EventType eventType, + String keyword) { + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaQuery criteria = cb.createQuery(Event.class); + Root event = criteria.from(Event.class); + criteria.select(event); + Predicate andClause = cb.conjunction(); + if (city != null) { + Join joinedVenue = event.join(Event_.venue); + Join joinedCity = joinedVenue.join(Venue_.city); + Predicate cityClause = cb.equal(joinedCity.get(City_.name), city.getName()); + andClause = cb.and(andClause, cityClause); + } + if (provinceState != null) { + Join joinedVenue = event.join(Event_.venue); + Predicate provinceStateClause = cb.equal(joinedVenue.get(Venue_.provinceState), + provinceState); + andClause = cb.and(andClause, provinceStateClause); + } + if (eventType != null) { + Predicate eventTypeClause = cb.equal(event.get(Event_.eventType), eventType); + andClause = cb.and(andClause, eventTypeClause); + } + if (keyword != null) { + Predicate keywordClause = cb.like(event.get(Event_.title), "%" + keyword + "%"); + andClause = cb.and(andClause, keywordClause); + } + criteria.where(andClause); + TypedQuery query = em.createQuery(criteria); + return query.getResultList(); + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/service/impl/IdeaServiceImpl.java b/primefaces-webapp/src/main/java/com/mycompany/service/impl/IdeaServiceImpl.java new file mode 100644 index 0000000..63bffcf --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/service/impl/IdeaServiceImpl.java @@ -0,0 +1,91 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.service.impl; + +import java.util.List; + +import javax.ejb.Stateless; +import javax.inject.Named; +import javax.persistence.TypedQuery; + +import org.primefaces.model.mindmap.DefaultMindmapNode; +import org.primefaces.model.mindmap.MindmapNode; + +import com.mycompany.model.Idea; +import com.mycompany.service.IdeaService; + +@Named("ideaService") +@Stateless +public class IdeaServiceImpl extends AbstractService implements IdeaService { + + /** + * This method uses recursion to build the mind map data structure. + * + * @param parentIdea + * The parent {@link Idea}. + * @param parentNode + * The parent {@link MindmapNode}. + */ + public void buildMindMap(Idea parentIdea, MindmapNode parentNode) { + Idea idea = parentIdea; + if (!em.contains(idea)) { + idea = em.find(Idea.class, idea.getId()); + } + if (idea.getChildren().isEmpty()) { + return; + } + for (Idea childIdea : idea.getChildren()) { + String label = childIdea.getName(); + MindmapNode childNode = new DefaultMindmapNode(label, childIdea, "6e9ebf", true); + parentNode.addNode(childNode); + buildMindMap(childIdea, childNode); + } + } + + @Override + public Idea findIdea(Integer id) { + return em.find(Idea.class, id); + } + + @Override + public List findIdeas() { + String jql = "select idea from Idea idea where idea.parent is null"; + TypedQuery query = em.createQuery(jql, Idea.class); + List ideas = query.getResultList(); + return ideas; + } + + @Override + public Idea saveIdea(Idea idea) { + Idea saved = idea; + if (idea.getVersion() == null) { + em.persist(idea); + } else { + saved = em.merge(idea); + } + return saved; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/service/impl/UserServiceImpl.java b/primefaces-webapp/src/main/java/com/mycompany/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..c25a38f --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/service/impl/UserServiceImpl.java @@ -0,0 +1,133 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.service.impl; + +import java.util.List; + +import javax.ejb.Stateless; +import javax.inject.Named; +import javax.persistence.NoResultException; +import javax.persistence.TypedQuery; + +import com.mycompany.model.RelationshipType; +import com.mycompany.model.User; +import com.mycompany.model.UserRelationship; +import com.mycompany.service.UserService; +import com.mycompany.util.Queries; + +/** + * @uml.dependency supplier="javax.persistence.EntityManager" + */ +@Named("userService") +@Stateless +public class UserServiceImpl extends AbstractService implements UserService { + + public UserRelationship findRelationshipToUser(User user1, User user2) { + UserRelationship found = null; + try { + String jql = "select r from UserRelationship r where r.fromUser = ?1 and r.toUser = ?2"; + TypedQuery query = em.createQuery(jql, UserRelationship.class); + query.setParameter(1, user1); + query.setParameter(2, user2); + found = query.getSingleResult(); + } catch (NoResultException e) { + } + return found; + } + + @Override + public User findUser(String username, String password) { + TypedQuery query = em.createNamedQuery(Queries.USER_FIND_BY_USERNAME_PASSWORD, User.class); + query.setParameter(1, username); + query.setParameter(2, password); + List users = query.getResultList(); + if (!users.isEmpty()) { + return users.get(0); + } + return null; + } + + @Override + public User findUserById(Integer id) { + return em.find(User.class, id); + } + + @Override + public User findUserByUsername(String username) { + String jql = "select u from User u where u.username = ?1"; + TypedQuery query = em.createQuery(jql, User.class); + query.setParameter(1, username); + List users = query.getResultList(); + if (!users.isEmpty()) { + return users.get(0); + } + return null; + } + + @Override + public List findUsers() { + String jql = "select u from User u order by u.username"; + List users = em.createQuery(jql, User.class).getResultList(); + return users; + } + + @Override + public List findUsersByName(String suggest) { + TypedQuery query = em.createNamedQuery(Queries.USER_FIND_BY_PARTIAL_NAME, User.class); + query.setParameter("name", "%" + suggest.trim() + "%"); + List users = query.getResultList(); + return users; + } + + @Override + public List findUsersByType(RelationshipType type, User user) { + TypedQuery query = em.createNamedQuery(Queries.USER_FIND_BY_RELATIONSHIP_TYPE, User.class); + query.setParameter(1, type); + query.setParameter(2, user); + return query.getResultList(); + } + + @Override + public UserRelationship saveRelationship(UserRelationship relationship) { + UserRelationship saved = relationship; + if (relationship.getVersion() == null) { + em.persist(relationship); + } else { + saved = em.merge(relationship); + } + return saved; + } + + @Override + public User saveUser(User user) { + User saved = user; + if (user.getVersion() == null) { + em.persist(user); + } else { + saved = em.merge(user); + } + return saved; + } +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/service/impl/VenueServiceImpl.java b/primefaces-webapp/src/main/java/com/mycompany/service/impl/VenueServiceImpl.java new file mode 100644 index 0000000..8796261 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/service/impl/VenueServiceImpl.java @@ -0,0 +1,72 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.service.impl; + +import java.util.List; + +import javax.ejb.Stateless; +import javax.inject.Named; +import javax.persistence.TypedQuery; + +import com.mycompany.model.Venue; +import com.mycompany.service.VenueService; + +@Named("venueService") +@Stateless +public class VenueServiceImpl extends AbstractService implements VenueService { + + @Override + public void deleteVenue(Venue venue) { + Venue found = em.find(Venue.class, venue.getId()); + if (found != null) { + em.remove(found); + } + } + + @Override + public Venue findVenueById(Integer id) { + return em.find(Venue.class, id); + } + + @Override + public List findVenues() { + String jql = "select v from Venue v order by v.name"; + TypedQuery query = em.createQuery(jql, Venue.class); + List venues = query.getResultList(); + return venues; + } + + @Override + public Venue saveVenue(Venue venue) { + Venue saved = venue; + if (venue.getVersion() == null) { + em.persist(venue); + } else { + saved = em.merge(venue); + } + return saved; + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/util/FacesUtils.java b/primefaces-webapp/src/main/java/com/mycompany/util/FacesUtils.java new file mode 100644 index 0000000..a253bd2 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/util/FacesUtils.java @@ -0,0 +1,60 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.util; + +import javax.faces.application.FacesMessage; +import javax.faces.context.FacesContext; + +/** + * Utility class for common JSF API uses. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +public class FacesUtils { + + /** + * Utility method to lookup a managed bean. + * + * @param name + * The managed bean name. + * @return A managed bean object. + */ + public static Object getManagedBean(String name) { + FacesContext ctx = FacesContext.getCurrentInstance(); + return ctx.getApplication().evaluateExpressionGet(ctx, "#{" + name + "}", Object.class); + } + + /** + * Adds a {@link FacesMessage} to the {@link FacesContext}. + * + * @param message + * The FacesMessage + */ + public static void addMessage(FacesMessage message) { + FacesContext.getCurrentInstance().addMessage(null, message); + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/util/Queries.java b/primefaces-webapp/src/main/java/com/mycompany/util/Queries.java new file mode 100644 index 0000000..52aa5c1 --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/util/Queries.java @@ -0,0 +1,101 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.util; + +import com.mycompany.model.Content; +import com.mycompany.model.Country; +import com.mycompany.model.Event; +import com.mycompany.model.EventAttendance; +import com.mycompany.model.Gender; +import com.mycompany.model.ProvinceState; +import com.mycompany.model.RelationshipType; +import com.mycompany.model.User; + +/** + * Constant interface for named JPA queries. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +public interface Queries { + + /** + * Finds a {@link City} by name and {@link ProvinceState}. + */ + public static final String CITY_FIND_BY_NAME_AND_PROVINCE_STATE = "City.findByNameAndProvinceState"; + + /** + * Finds a {@link Content} by name. + */ + public static final String CONTENT_FIND_BY_NAME = "Content.findByName"; + + /** + * Finds all {@link Country} objects. + */ + public static final String COUNTRY_FIND_ALL = "Country.findAll"; + + /** + * Finds a {@link Country} by code. + */ + public static final String COUNTRY_FIND_BY_CODE = "Country.findByCode"; + + /** + * Finds all {@link EventAttendance} for a particular {@link User}. + */ + public static final String EVENT_ATTENDANCE_FIND_BY_USER = "EventAttendance.findByUser"; + + /** + * Finds a List of {@link EventAttendance} for a particular {@link User} and + * {@link Event}. + */ + public static final String EVENT_ATTENDANCE_FIND_BY_USER_AND_EVENT = "EventAttendance.findByUserAndEvent"; + + /** + * Find a count of all {@link EventAttendance} objects by {@link Gender}. + */ + public static final String EVENT_ATTENDANCE_FIND_GENDER_COUNT_BY_EVENT = "EventAttendance.findGenderCountByEvent"; + + /** + * Find all {@link Event} objects. + */ + public static final String EVENT_FIND_ALL = "Event.findAll"; + + /** + * Finds a {@link User} by partial name. + */ + public static final String USER_FIND_BY_PARTIAL_NAME = "User.findByPartialName"; + + /** + * Finds a List of {@link User} objects by {@link RelationshipType} to + * another {@link User}. + */ + public static final String USER_FIND_BY_RELATIONSHIP_TYPE = "User.findByRelationshipType"; + + /** + * Finds a {@link User} by username and password. + */ + public static final String USER_FIND_BY_USERNAME_PASSWORD = "User.findByUsernamePassword"; + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/util/UserSession.java b/primefaces-webapp/src/main/java/com/mycompany/util/UserSession.java new file mode 100644 index 0000000..2634f7f --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/util/UserSession.java @@ -0,0 +1,86 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.util; + +import java.io.Serializable; + +import javax.annotation.PreDestroy; +import javax.enterprise.context.SessionScoped; +import javax.inject.Inject; +import javax.inject.Named; + +import com.mycompany.model.ActiveUsers; +import com.mycompany.model.User; + +/** + * Session-scoped CDI managed bean to store a {@link User} object. + * + * @author Ian Hlavats (ian@tarantulaconsulting.com) + * + */ +@Named("userSession") +@SessionScoped +public class UserSession implements Serializable { + + @Inject + private ActiveUsers activeUsers; + + /** + * + */ + private static final long serialVersionUID = 8195784747974150341L; + + private User user; + + /** + * Returns the current {@link User}. + * + * @return A User object. + */ + public User getUser() { + return user; + } + + /** + * Sets the {@link User}. + * + * @param user + * The User object. + */ + public void setUser(User user) { + this.user = user; + } + + /** + * CDI calls this method before the bean is destroyed. Since this class is + * session-scoped, it will get called if the user session expires, allowing + * us to remove the user from the active user list. + */ + @PreDestroy + public void release() { + activeUsers.remove(user); + } + +} diff --git a/primefaces-webapp/src/main/java/com/mycompany/websocket/DefaultPushRule.java b/primefaces-webapp/src/main/java/com/mycompany/websocket/DefaultPushRule.java new file mode 100644 index 0000000..449017a --- /dev/null +++ b/primefaces-webapp/src/main/java/com/mycompany/websocket/DefaultPushRule.java @@ -0,0 +1,78 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2013 Ian Hlavats. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.mycompany.websocket; + +import static org.atmosphere.cpr.BroadcasterLifeCyclePolicy.EMPTY_DESTROY; + +import org.atmosphere.cpr.AtmosphereRequest; +import org.atmosphere.cpr.AtmosphereResource; +import org.atmosphere.cpr.Broadcaster; +import org.atmosphere.cpr.BroadcasterFactory; +import org.atmosphere.cpr.BroadcasterLifeCyclePolicyListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utility class for GlassFish WebSocket support with PrimeFaces. + */ +public class DefaultPushRule extends org.primefaces.push.DefaultPushRule { + + public boolean apply(AtmosphereResource resource) { + AtmosphereRequest req = resource.getRequest(); + String pathInfo = req.getPathInfo(); + if (pathInfo == null) { + String servletPath = req.getServletPath(); + String contextPath = req.getContextPath(); + pathInfo = req.getRequestURI() + .replaceFirst(contextPath, "") + .replaceFirst(servletPath, ""); + } + if (pathInfo == null || pathInfo == "") { + resource.setBroadcaster(BroadcasterFactory.getDefault().lookup("/*")); + return true; + } + final Broadcaster b = BroadcasterFactory.getDefault().lookup(pathInfo, true); + b.setBroadcasterLifeCyclePolicy(EMPTY_DESTROY); + b.addBroadcasterLifeCyclePolicyListener(new BroadcasterLifeCyclePolicyListener() { + + private final Logger logger = LoggerFactory.getLogger(BroadcasterLifeCyclePolicyListener.class); + + public void onEmpty() { + logger.trace("onEmpty {}", b.getID()); + } + + public void onIdle() { + logger.trace("onIdle {}", b.getID()); + } + + public void onDestroy() { + logger.trace("onDestroy {}", b.getID()); + } + }); + resource.setBroadcaster(b); + + return true; + } +} diff --git a/primefaces-webapp/src/main/resources/META-INF/auth.conf b/primefaces-webapp/src/main/resources/META-INF/auth.conf new file mode 100644 index 0000000..24d75d0 --- /dev/null +++ b/primefaces-webapp/src/main/resources/META-INF/auth.conf @@ -0,0 +1,4 @@ +AppLogin +{ + com.mycompany.util.AppLoginModule required +}; \ No newline at end of file diff --git a/primefaces-webapp/src/main/resources/META-INF/persistence.xml b/primefaces-webapp/src/main/resources/META-INF/persistence.xml new file mode 100644 index 0000000..7abeea5 --- /dev/null +++ b/primefaces-webapp/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,17 @@ + + + + + org.hibernate.ejb.HibernatePersistence + java:app/jdbc/mycompanyDataSource + + + + + + + \ No newline at end of file diff --git a/primefaces-webapp/src/main/resources/cities.txt b/primefaces-webapp/src/main/resources/cities.txt new file mode 100644 index 0000000..989cc37 --- /dev/null +++ b/primefaces-webapp/src/main/resources/cities.txt @@ -0,0 +1,14 @@ +US:California:San Francisco:37.7810,-122.418 +US:California:Los Angeles:34.112,-118.246 +US:California:San Diego:32.776,-117.158 +US:New York:New York:40.739,-74.009 +US:New York:Buffalo:42.898,-78.878 +US:New York:Rochester:43.173,-77.609 +US:Illinois:Chicago:41.900,-87.627 +US:Texas:Dallas:32.843,-96.770 +CA:Ontario:Toronto:43.677,-79.386 +CA:Quebec:Montreal:45.527,-73.559 +CA:British Columbia:Vancouver:49.2660,-123.115 +CA:Nova Scotia:Halifax:44.6533,-63.577 + + diff --git a/primefaces-webapp/src/main/resources/countries.txt b/primefaces-webapp/src/main/resources/countries.txt new file mode 100644 index 0000000..962d6e8 --- /dev/null +++ b/primefaces-webapp/src/main/resources/countries.txt @@ -0,0 +1,244 @@ +AF:Afghanistan +AX:land Islands +AL:Albania +DZ:Algeria +AS:American Samoa +AD:Andorra +AO:Angola +AI:Anguilla +AQ:Antarctica +AG:Antigua and Barbuda +AR:Argentina +AM:Armenia +AW:Aruba +AU:Australia +AT:Austria +AZ:Azerbaijan +BS:Bahamas +BH:Bahrain +BD:Bangladesh +BB:Barbados +BY:Belarus +BE:Belgium +BZ:Belize +BJ:Benin +BM:Bermuda +BT:Bhutan +BO:Bolivia +BA:Bosnia and Herzegovina +BW:Botswana +BV:Bouvet Island +BR:Brazil +IO:British Indian Ocean Territory +BN:Brunei Darussalam +BG:Bulgaria +BF:Burkina Faso +BI:Burundi +KH:Cambodia +CM:Cameroon +CA:Canada +CV:Cape Verde +KY:Cayman Islands +CF:Central African Republic +TD:Chad +CL:Chile +CN:China +CX:Christmas Island +CC:Cocos (Keeling) Islands +CO:Colombia +KM:Comoros +CG:Congo +CD:Congo, The Democratic Republic of The +CK:Cook Islands +CR:Costa Rica +CI:Cote D'ivoire +HR:Croatia +CU:Cuba +CY:Cyprus +CZ:Czech Republic +DK:Denmark +DJ:Djibouti +DM:Dominica +DO:Dominican Republic +EC:Ecuador +EG:Egypt +SV:El Salvador +GQ:Equatorial Guinea +ER:Eritrea +EE:Estonia +ET:Ethiopia +FK:Falkland Islands (Malvinas) +FO:Faroe Islands +FJ:Fiji +FI:Finland +FR:France +GF:French Guiana +PF:French Polynesia +TF:French Southern Territories +GA:Gabon +GM:Gambia +GE:Georgia +DE:Germany +GH:Ghana +GI:Gibraltar +GR:Greece +GL:Greenland +GD:Grenada +GP:Guadeloupe +GU:Guam +GT:Guatemala +GG:Guernsey +GN:Guinea +GW:Guinea-bissau +GY:Guyana +HT:Haiti +HM:Heard Island and Mcdonald Islands +VA:Holy See (Vatican City State) +HN:Honduras +HK:Hong Kong +HU:Hungary +IS:Iceland +IN:India +ID:Indonesia +IR:Iran, Islamic Republic of +IQ:Iraq +IE:Ireland +IM:Isle of Man +IL:Israel +IT:Italy +JM:Jamaica +JP:Japan +JE:Jersey +JO:Jordan +KZ:Kazakhstan +KE:Kenya +KI:Kiribati +KP:Korea, Democratic People's Republic of +KR:Korea, Republic of +KW:Kuwait +KG:Kyrgyzstan +LA:Lao People's Democratic Republic +LV:Latvia +LB:Lebanon +LS:Lesotho +LR:Liberia +LY:Libyan Arab Jamahiriya +LI:Liechtenstein +LT:Lithuania +LU:Luxembourg +MO:Macao +MK:Macedonia, The Former Yugoslav Republic of +MG:Madagascar +MW:Malawi +MY:Malaysia +MV:Maldives +ML:Mali +MT:Malta +MH:Marshall Islands +MQ:Martinique +MR:Mauritania +MU:Mauritius +YT:Mayotte +MX:Mexico +FM:Micronesia, Federated States of +MD:Moldova, Republic of +MC:Monaco +MN:Mongolia +ME:Montenegro +MS:Montserrat +MA:Morocco +MZ:Mozambique +MM:Myanmar +NA:Namibia +NR:Nauru +NP:Nepal +NL:Netherlands +AN:Netherlands Antilles +NC:New Caledonia +NZ:New Zealand +NI:Nicaragua +NE:Niger +NG:Nigeria +NU:Niue +NF:Norfolk Island +MP:Northern Mariana Islands +NO:Norway +OM:Oman +PK:Pakistan +PW:Palau +PS:Palestinian Territory, Occupied +PA:Panama +PG:Papua New Guinea +PY:Paraguay +PE:Peru +PH:Philippines +PN:Pitcairn +PL:Poland +PT:Portugal +PR:Puerto Rico +QA:Qatar +RE:Reunion +RO:Romania +RU:Russian Federation +RW:Rwanda +SH:Saint Helena +KN:Saint Kitts and Nevis +LC:Saint Lucia +PM:Saint Pierre and Miquelon +VC:Saint Vincent and The Grenadines +WS:Samoa +SM:San Marino +ST:Sao Tome and Principe +SA:Saudi Arabia +SN:Senegal +RS:Serbia +SC:Seychelles +SL:Sierra Leone +SG:Singapore +SK:Slovakia +SI:Slovenia +SB:Solomon Islands +SO:Somalia +ZA:South Africa +GS:South Georgia and The South Sandwich Islands +ES:Spain +LK:Sri Lanka +SD:Sudan +SR:Suriname +SJ:Svalbard and Jan Mayen +SZ:Swaziland +SE:Sweden +CH:Switzerland +SY:Syrian Arab Republic +TW:Taiwan, Province of China +TJ:Tajikistan +TZ:Tanzania, United Republic of +TH:Thailand +TL:Timor-leste +TG:Togo +TK:Tokelau +TO:Tonga +TT:Trinidad and Tobago +TN:Tunisia +TR:Turkey +TM:Turkmenistan +TC:Turks and Caicos Islands +TV:Tuvalu +UG:Uganda +UA:Ukraine +AE:United Arab Emirates +GB:United Kingdom +US:United States +UM:United States Minor Outlying Islands +UY:Uruguay +UZ:Uzbekistan +VU:Vanuatu +VE:Venezuela +VN:Viet Nam +VG:Virgin Islands, British +VI:Virgin Islands, U.S. +WF:Wallis and Futuna +EH:Western Sahara +YE:Yemen +ZM:Zambia +ZW:Zimbabwe \ No newline at end of file diff --git a/primefaces-webapp/src/main/webapp/WEB-INF/beans.xml b/primefaces-webapp/src/main/webapp/WEB-INF/beans.xml new file mode 100644 index 0000000..a3257e5 --- /dev/null +++ b/primefaces-webapp/src/main/webapp/WEB-INF/beans.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/primefaces-webapp/src/main/webapp/WEB-INF/dialogs/addShowDialog.xhtml b/primefaces-webapp/src/main/webapp/WEB-INF/dialogs/addShowDialog.xhtml new file mode 100644 index 0000000..46c1089 --- /dev/null +++ b/primefaces-webapp/src/main/webapp/WEB-INF/dialogs/addShowDialog.xhtml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ +
+ + + + + + + diff --git a/primefaces-webapp/src/main/webapp/WEB-INF/dialogs/chatDialog.xhtml b/primefaces-webapp/src/main/webapp/WEB-INF/dialogs/chatDialog.xhtml new file mode 100644 index 0000000..de8c79d --- /dev/null +++ b/primefaces-webapp/src/main/webapp/WEB-INF/dialogs/chatDialog.xhtml @@ -0,0 +1,59 @@ + + + + + + + + + + + + Users + + #{user.username} + + + +
+ + + +
+
+ +
+
+
+ + +
+ + diff --git a/primefaces-webapp/src/main/webapp/WEB-INF/dialogs/newContactDialog.xhtml b/primefaces-webapp/src/main/webapp/WEB-INF/dialogs/newContactDialog.xhtml new file mode 100644 index 0000000..04f58e2 --- /dev/null +++ b/primefaces-webapp/src/main/webapp/WEB-INF/dialogs/newContactDialog.xhtml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/primefaces-webapp/src/main/webapp/WEB-INF/dialogs/validationDialog.xhtml b/primefaces-webapp/src/main/webapp/WEB-INF/dialogs/validationDialog.xhtml new file mode 100644 index 0000000..e9ead0f --- /dev/null +++ b/primefaces-webapp/src/main/webapp/WEB-INF/dialogs/validationDialog.xhtml @@ -0,0 +1,18 @@ + + + + + + + + + + + diff --git a/primefaces-webapp/src/main/webapp/WEB-INF/faces-config.xml b/primefaces-webapp/src/main/webapp/WEB-INF/faces-config.xml new file mode 100644 index 0000000..2176baf --- /dev/null +++ b/primefaces-webapp/src/main/webapp/WEB-INF/faces-config.xml @@ -0,0 +1,29 @@ + + + + * + + members + /protected/members/index.xhtml + + + + + * + + login + /index.xhtml + + + + + com.mycompany.lifecycle.SecurityPhaseListener + + + + mycompany.EditableStateConverter + com.mycompany.convert.EditableStateConverter + + + + diff --git a/primefaces-webapp/src/main/webapp/WEB-INF/glassfish-resources.xml b/primefaces-webapp/src/main/webapp/WEB-INF/glassfish-resources.xml new file mode 100644 index 0000000..50866a0 --- /dev/null +++ b/primefaces-webapp/src/main/webapp/WEB-INF/glassfish-resources.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/primefaces-webapp/src/main/webapp/WEB-INF/mycompany.taglib.xml b/primefaces-webapp/src/main/webapp/WEB-INF/mycompany.taglib.xml new file mode 100644 index 0000000..3321028 --- /dev/null +++ b/primefaces-webapp/src/main/webapp/WEB-INF/mycompany.taglib.xml @@ -0,0 +1,15 @@ + + + My Company Custom Facelets Tag Library + My Company Tag Library + http://www.showtimeguru.com/taglib + + editableStateConverter + + mycompany.EditableStateConverter + + + \ No newline at end of file diff --git a/primefaces-webapp/src/main/webapp/WEB-INF/templates/main.xhtml b/primefaces-webapp/src/main/webapp/WEB-INF/templates/main.xhtml new file mode 100644 index 0000000..de25851 --- /dev/null +++ b/primefaces-webapp/src/main/webapp/WEB-INF/templates/main.xhtml @@ -0,0 +1,57 @@ + + + + + <ui:insert name="title" /> + + + + + + + + +
+ +
+
+ + + + + +
+ +
+
+ diff --git a/primefaces-webapp/src/main/webapp/WEB-INF/web.xml b/primefaces-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..2f99b9a --- /dev/null +++ b/primefaces-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,210 @@ + + + primefaces-webapp + + javax.faces.DEFAULT_SUFFIX + .xhtml + + + javax.faces.FACELETS_LIBRARIES + /WEB-INF/mycompany.taglib.xml + + + javax.faces.STATE_SAVING_METHOD + server + + + javax.faces.PROJECT_STAGE + Production + + + javax.faces.FACELETS_REFRESH_PERIOD + 1 + + + javax.faces.FACELETS_SKIP_COMMENTS + false + + + javax.faces.validator.DISABLE_DEFAULT_BEAN_VALIDATOR + false + + + javax.faces.FACELETS_VIEW_MAPPINGS + *.jsf;*.xhtml;/faces/* + + + com.sun.faces.enableMissingResourceLibraryDetection + false + + + com.sun.faces.clientStateTimeout + 1200000 + + + com.sun.faces.responseBufferSize + 500000 + + + com.sun.faces.numberOfViewsInSession + 5 + + + com.sun.faces.numberOfLogicalViews + 5 + + + com.sun.faces.validateXml + false + + + com.sun.faces.verifyObjects + false + + + facelets.DEVELOPMENT + false + + + facelets.RECREATE_VALUE_EXPRESSION_ON_BUILD_BEFORE_RESTORE + false + + + facelets.BUILD_BEFORE_RESTORE + false + + + primefaces.PUBLIC_CAPTCHA_KEY + [YOUR RECAPTCHA PUBLIC KEY HERE] + + + primefaces.PRIVATE_CAPTCHA_KEY + [YOUR RECAPTCHA PRIVATE KEY HERE] + + + primefaces.THEME + #{userController.userTheme} + + + + + + primefaces.PUSH_SERVER_URL + http://localhost:8080 + + + + com.sun.faces.config.ConfigureListener + + + com.mycompany.lifecycle.ServletContextLifecycleNotifier + + + + Faces Servlet + javax.faces.webapp.FacesServlet + 1 + + + Faces Servlet + /faces/* + + + + PushServlet + org.primefaces.push.PushServlet + + + org.atmosphere.cpr.AtmosphereInterceptor + org.atmosphere.client.TrackMessageSizeInterceptor + + + + org.atmosphere.cpr.sessionSupport + true + + + org.atmosphere.cpr.broadcasterCacheClass + org.atmosphere.cache.SessionBroadcasterCache + + + + org.atmosphere.disableOnStateEvent + true + + + + org.primefaces.push.rules + com.mycompany.websocket.DefaultPushRule + + 1 + true + + + PushServlet + /primepush/* + + + + + + PrimeFaces FileUpload Filter + org.primefaces.webapp.filter.FileUploadFilter + + + PrimeFaces FileUpload Filter + Faces Servlet + + + + txt + text/plain + + + html + text/html + + + css + text/css + + + xhtml + text/html + + + gif + image/gif + + + jpeg + image/jpeg + + + jpg + image/jpeg + + + png + image/png + + + diff --git a/primefaces-webapp/src/main/webapp/about.xhtml b/primefaces-webapp/src/main/webapp/about.xhtml new file mode 100644 index 0000000..62e9ac7 --- /dev/null +++ b/primefaces-webapp/src/main/webapp/about.xhtml @@ -0,0 +1,40 @@ + + + + + + + About Us + + + + + + +
+
+ + +
+
+ + +
+
+
+
+
+ + diff --git a/primefaces-webapp/src/main/webapp/error.xhtml b/primefaces-webapp/src/main/webapp/error.xhtml new file mode 100644 index 0000000..bbc927d --- /dev/null +++ b/primefaces-webapp/src/main/webapp/error.xhtml @@ -0,0 +1,16 @@ + + + + + + Error Page + + There was an error processing your request. Please try again later. + + + + diff --git a/primefaces-webapp/src/main/webapp/ideas.xhtml b/primefaces-webapp/src/main/webapp/ideas.xhtml new file mode 100644 index 0000000..4d863ef --- /dev/null +++ b/primefaces-webapp/src/main/webapp/ideas.xhtml @@ -0,0 +1,64 @@ + + + + + + + Ideas + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+ + diff --git a/primefaces-webapp/src/main/webapp/index.xhtml b/primefaces-webapp/src/main/webapp/index.xhtml new file mode 100644 index 0000000..ef897fe --- /dev/null +++ b/primefaces-webapp/src/main/webapp/index.xhtml @@ -0,0 +1,53 @@ + + + + + + + Welcome to our site + + + + + + + + + + + + + + + + + + + + +
    +
  • + Find out what's happening +
  • +
  • + Rate and review shows +
  • +
  • + Invite your friends +
  • +
  • + Join today! +
  • +
+
+
+
+
+ + diff --git a/primefaces-webapp/src/main/webapp/mobile/index.xhtml b/primefaces-webapp/src/main/webapp/mobile/index.xhtml new file mode 100644 index 0000000..35fcf7a --- /dev/null +++ b/primefaces-webapp/src/main/webapp/mobile/index.xhtml @@ -0,0 +1,510 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
  • + Find out what's happening +
  • +
  • + Rate and review shows +
  • +
  • + +
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dashboard + + + Venues + + + Shows + + + Reviews + + + Contacts + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + diff --git a/primefaces-webapp/src/main/webapp/protected/members/contacts.xhtml b/primefaces-webapp/src/main/webapp/protected/members/contacts.xhtml new file mode 100644 index 0000000..a34fa1b --- /dev/null +++ b/primefaces-webapp/src/main/webapp/protected/members/contacts.xhtml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/primefaces-webapp/src/main/webapp/protected/members/dashboard.xhtml b/primefaces-webapp/src/main/webapp/protected/members/dashboard.xhtml new file mode 100644 index 0000000..dd58019 --- /dev/null +++ b/primefaces-webapp/src/main/webapp/protected/members/dashboard.xhtml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/primefaces-webapp/src/main/webapp/protected/members/index.xhtml b/primefaces-webapp/src/main/webapp/protected/members/index.xhtml new file mode 100644 index 0000000..c298e14 --- /dev/null +++ b/primefaces-webapp/src/main/webapp/protected/members/index.xhtml @@ -0,0 +1,38 @@ + + + + + + + Members + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/primefaces-webapp/src/main/webapp/protected/members/reviews.xhtml b/primefaces-webapp/src/main/webapp/protected/members/reviews.xhtml new file mode 100644 index 0000000..eb06d63 --- /dev/null +++ b/primefaces-webapp/src/main/webapp/protected/members/reviews.xhtml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/primefaces-webapp/src/main/webapp/protected/members/shows.xhtml b/primefaces-webapp/src/main/webapp/protected/members/shows.xhtml new file mode 100644 index 0000000..b21a093 --- /dev/null +++ b/primefaces-webapp/src/main/webapp/protected/members/shows.xhtml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/primefaces-webapp/src/main/webapp/protected/members/venues.xhtml b/primefaces-webapp/src/main/webapp/protected/members/venues.xhtml new file mode 100644 index 0000000..0c7ea6e --- /dev/null +++ b/primefaces-webapp/src/main/webapp/protected/members/venues.xhtml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ +
+ + +
+
+ + +
+
+ + diff --git a/primefaces-webapp/src/main/webapp/resources/css/main.css b/primefaces-webapp/src/main/webapp/resources/css/main.css new file mode 100644 index 0000000..8e3fea7 --- /dev/null +++ b/primefaces-webapp/src/main/webapp/resources/css/main.css @@ -0,0 +1,129 @@ +body, ul { + font-family:Arial, Helvetica, sans-serif; + font-size:1.1em; + color:#4F4F4F; +} +div.header { + text-align:center; + margin-bottom:25px; +} +div.content table { + margin:0 auto; + text-align:center; +} +div.content table td { + text-align:left; +} +div.footer { + text-align:center; + margin-top:20px; + margin-bottom:20px; +} +div.footer a { + margin-right:15px; +} +ul li { + margin-bottom:15px; +} +.input-form input.ui-inputfield { + width:445px; +} +.input-form input.ui-inputfield.hasDatepicker { + width:394px; +} +button.ui-datepicker-trigger { + vertical-align:middle; + height:35px; + margin-left:5px; +} +.centered { + text-align:center; +} +.ui-tabs-hide { + position:absolute; + left:-10000px; +} +.ui-overlay-hidden { + position:absolute; + left:-10000px; +} +.ui-datepicker .ui-datepicker-title select { + font-size:0.7em; +} +.top { + vertical-align:top; +} +.left { + text-align:left; +} +.content-box { + width:50%; + margin:0 auto; +} +.person-item { + height:140px; + text-align:center; + width:200px; +} +.mobile-person-item { + height:130px; + text-align:center; + vertical-align:middle; + width:100%; + font-size:0.9em; +} +div.content .person-item table td { + text-align:center; +} +.chatlogs { + height:235px; + width:450px; + overflow:auto; + padding:0.5em 1em 0.5em 0.5em; +} +.ui-dashboard .ui-panel { + margin:10px; + width:265px; + font-size:0.9em; +} +.ui-dashboard .ui-panel .ui-widget-content { + height:200px; + overflow-y:auto; + font-size:0.8em; +} +.ui-dashboard .ui-panel .ui-widget-content img { + padding-right:10px; + padding-bottom:5px; +} +.align-left { + text-align:left; +} +.align-right { + text-align:right; +} +.content-controls { + text-align:center; +} +.content-box div.ui-editor { + text-align:center; + margin:0 auto; +} +.chat-users-column { + width:25%; +} +.chat-text-column { + width:75%; +} +.centervh { + text-align:center; + vertical-align:middle; +} +.no-border { + border:none; +} +.ui-panelgrid td.no-border { + border:none; +} +table.no-border .ui-widget-content { + border:none; +} \ No newline at end of file diff --git a/primefaces-webapp/src/main/webapp/resources/images/about.png b/primefaces-webapp/src/main/webapp/resources/images/about.png new file mode 100755 index 0000000000000000000000000000000000000000..7d45c0da98627fc197212a21b4cefb377c8a2c87 GIT binary patch literal 6335 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 literal 0 HcmV?d00001 diff --git a/primefaces-webapp/src/main/webapp/resources/images/members.png b/primefaces-webapp/src/main/webapp/resources/images/members.png new file mode 100755 index 0000000000000000000000000000000000000000..3c3fe32b25f949ec7d730e23780eea54317c9044 GIT binary patch literal 6131 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 Ef`Z)=Y5)KL literal 0 HcmV?d00001 diff --git a/primefaces-webapp/src/main/webapp/resources/images/privacy.png b/primefaces-webapp/src/main/webapp/resources/images/privacy.png new file mode 100755 index 0000000000000000000000000000000000000000..6ac92a4bf137867bd5d721c85b61ae79ac9cba5b GIT binary patch literal 5039 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 literal 0 HcmV?d00001 diff --git a/primefaces-webapp/src/main/webapp/resources/images/showtimes.png b/primefaces-webapp/src/main/webapp/resources/images/showtimes.png new file mode 100755 index 0000000000000000000000000000000000000000..3a5d44e15d2b7d4a509b117c5df06d7b126959ee GIT binary patch literal 5912 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 K{Rzy>&;J0Pu;>i{ literal 0 HcmV?d00001 diff --git a/primefaces-webapp/src/main/webapp/resources/images/user-icon.png b/primefaces-webapp/src/main/webapp/resources/images/user-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4475c83e4a205491af67056d849737d7e8682b5a GIT binary patch literal 9123 zcmV;UBV62xP)e92c_Z&SN+-6PIylh|!`+H8|arn{4!Y!f%#PBOFE zxaoG288^<+By}=T64yEH_>yHimUT;%M2Vz$lK=^VxQP4M|NlKa;KSnsNXY;Jiu})f zd=KwEfbaW$zyI;wGT4xHEwXaIz=o7pHVClJWrG0gTs8=>&gGUSz?Uzi%y>AAX&0t@ zFtw*sJ{e7?bC}L!dgHS@WTWNIM=9l&BLITlj)y4jU747Usc5ctD*_!Oo;R4V|w%{=gJRm*2KmHs0TB9%Uw z2?C7!04DrAF;HH>^fe^H8|BV#v1H8?APxK%FdeQ(z`Lpud`mWCGA5UK36KUnCG|N? z3?ji5H-Iz9-FgGl-`@&EShEE9()lFnxa=933_fbt1MIW`5CJlol8Hzlm0L0JQrAS5 zfe3KH1uz@rK7R-Qe)@mxlzYlu9ycp%k^uj3CULJ^F8irk4(5IJGEU>!%*aF<&sqT~ zNio5|5_gd2Gg*Xprc)42f+v|wJ@$8d6t9=NTy93z6aiYkn~?qGc6eG2@cEW18Qjq% z1M>Hh8ZSkHw4@-fF(~W~M4zJxB*9b)CjBW$0(|jbFT&FkA5n;7%ZipYLjVH*sjaDR z%VqG9y$y2ctCcO)bO~RdOyx%VavA@ejCo$r@Dy_tOCif}Wj+O`9ZC9M-+k_q>|<+* z1Z#o-1pbqK$?s?s@aK0lE1fN;)!R^WG(^6dZPzQz#29ZJD(ugB>oYi&-&6i793>HMz4P>lA+9D)V{6i{? zJ1F+ZxDLpk^CXB73I6Tht|~uP=_IIF0ucC5bjLo8TKAPZT9wdKtH^m_0yBXn?vL{3 zJ_mHjC4h{v0vYo!&OHMrnSRa%q?jX1h7|7-^h*AB#c{#7HwkZy#_0Y2_TPt8&r~uA zDv|&M{^RY@Jz6E4+*z-LT@A`5Wc;RzC_W`if0u&-ZGW`XE zinj;=xt8R-BMuiZp=H{4bX0w&Qb|y81fYNq56VC5jGSsP$#?u-k0uv1{Ns-R1fsdX zOPTx}D*#KipQ!}!N0BQ?irhg`A~v9-PQ_aT@o&657y(BhIW`xP?|WrN<*LNmK}8WD z4Zh;>w(!$>mF#nmY|(;IBg?!f0Z1J-p;&(4#U@`aGW%=*C~h0baRZ`YkUJ)GEdomd z4HBSQooh`3kre!VAdK&u`p2VV+NbeSqS8oEX#`L_+!*dMsZ#IlYE)P6YExwf5CnuxekI8y}J*^!^0wl^^ z&a6}n0m$#;L2;xx`0Z+~{KJp$(C26>1$(ZbH0U>C{(-RutcctG1&bhd1NlfGJZIMM zL=b+Hp84s;Ab7*cAN*`m|0G_DS5iDs5d;uS|9y3#ZnHXh<<3qm^jKAy7o;ZF2_GNG z2?3sz6%g0^#nHd;du$s(jvHVadXlN^QHlUk7Jws0lJAtt1csP~=3?;nXc*iPdEXmz zxYmY*>88td;%MAMY||UXBWN%$u(2$+K0wyuizs5&)QECKeFALq_WX zBx?iWz)&h45XeC9*=WcTjh_F>`2cvrsc-yZ#_(zU7^@U3P<8?cQ9ma2BlZ5N-ObwS zT`ignNX|uog>Zh;zg&x-;P*5BU!s#ps(oK777$kl*&2b^B~UC-tIPi8Wk(d=8w+_~ zbeNj)3f5ydS5S5731CJXN$?rYBrwU9OIrm~Q)R94VF31Y0s2_64kgwr~ zHUHwKVDVUhj5}aV{*rb9$ZrWKwO8{^$9#<-2|qdOgT;jWKfmTO9>q)1O0WWDB>PxkR^j~kH#QU zJRn$<-&_j7q&NPfmt9qV0Tp5e%1r>y_hZsMRO`8Tuv6c>wLzQF{>$^I@sR8LWfF0K z6ag|;Ae~FL3K&i<&A3*+GzK8a2?m$xFk%BiffQY4WO%yY;L=POPK*R6Uz#^>$15SI zfLNg11fZhPY&R@!Y1G6{J-VwJYK?sOOo5*#oWH)G*Zf2FoJfS07vfm>u@wI~QypY; z&zOD{UQ@~Wqejl3OEwIxFd(E@pvjc(C|XRwi|4#B9Z~JQxM;Y7mm=kE7bqJ681t_? zX!8ECNtyiSlXuo;H1@26FSI3~3)ke*;1k$b&Ja%UokdauK*Uu+l6(z86mw{ilLiG( ziY2vy0zn}q`Zs;n>~DYP?RoIW<$v+6zxv0(TY<8=fpQXn3;rQS>fs&L z9559154mrk(FcENF^+*&oY!(ODWr~4Qm|VX&z1N+6H?ZoTtUkqWGw>)gF-X$uP=IG zY$5TrxBTWW;zt@|T-IQ)oCM&^KPKZ{M)wc4G-w{UyVu0s8(!es{AE(wFVC&=1yR$z zv8AJba^eAywgRk(TLN>Uf5-)xtU|SlCqh08K-UuKqeTnQR?VLuzvhPlN92{`ftnBF z;{hnM8z?6MIP;Imbf;ndg?;V%eY@KY96;xsOFMkT79fh~EJS&ezmj->tpViA^pfV_ zl(fkg049rILCw}E3bYKSco!nLfwNMn!SYe90(x+;^o4jECfjVe=hpR zRCP$_`suz7{oZ|@Mow#vkLPN-;Pd6_IvZ&`nftsQK~UHQ02Gb^gwJg7x1{+Ovgf9B zPoPW$JWGasjXYsajs)P;NbuA!u(&yyg-6E}L-9y05k@fOV}A_7Fp6$qA_0MzSa z*{hoU;l578?z_58a0#RT5l^l^r$BEZnm;C3b_CEe;0q!Z2xhb&3P=8IA`<9D0b)xP zz!oIITZ4Xd1B+)*#p?bHe};yR3xVLeB7jf>ps?S(N9lZiUx#t`-J49%KhG0@dpUeN zZx$(uqYn?lY@0|6n~zFhzp17NakkB`6k z!0tNeu<79!Bd8X!WnR2c-CsDaFaQ)}rGa2RE09l`u=;nP0bt4%gjdha!bN54-FO+J zo%J09WU7IfY`w9`Z)|GNZ~ISstnk(Zz;*u$Gf<%J&yN0)3IHW702BP>3k1d0!sS|U zcBB9A!u0wD7Yxn>`>(2+{|a&mu4(^O=&I2XHen04!}7x)IrH1*k@6=U7;T-D4AR?21qR>!OZ~9 z3iN zaE+QeJ`TL;rzBJXBkOKF00|QaX5s)!){yfNW7PlgM-F#@QlezpOqZ04V&+ytNoA)z`b)CMS7tlse_jSzX@wmqHDZdP%cMI<115UW5E5cmh` zc<`q%W*K#d;cEXF1Z0|5T-B}L0v_~v$c_G^>vmoM2|G6c(j7y<6M)=7b)9SQA8aON zb4zbK?6)hp!liWrPE;5Ps?>bMPgBBa-J%oD1k4SMg3BMDoVE7+9q@pY*(dOY4xqBn z2_Pve0Z14tK*PfXD?kJ=?^MtK&Fs|NA+yB@oxQCY^Gbz$-kn_}s+>}f)ZJCf&mf|~ zD<{#w&kT)&XCVNsE!K(tsO9O!q+%Mf1Ryd9;{eOPT1X`jfNBFmEWnKrs#3(;cItfp zVo*cJrg{~;@YXaaO(y8+ZH7a2d|^{8(2u$_QN}9bcC=TW>HP=@{I{K0WgVV`q~8yp z{Jj=9JspE7Z+vkyqWk1%RR10@-M>&FD}|Ju03@sxuqh)gn>B$S>eR65(R~)MRw?1^ zzykd1OOsG#vq10WX1K%7lYqp5p7dgR0Lf|zjsD$H!w&@~A@Gkokc>l<;G0{3Pe0rY z4{Wv2;!yCtQ(hQ$Mg87{>c5{0RnxTaiqU?ON+AGe1v*rV_06i_uWVJytq<)ngGr|V zBi^y1eRu`c{n^*1A*Inm`{s5y+^om|5KA{0QQtu+V*{EAw8ae2X3Sn2!&v@=BLP#_ zMnM({BlsC>dF1)oTD?5}YOP7N z^A8Txf?A2-qf@XcmpQ+U}j{B1N}=M>IS1mQSdj9A_-292fgu>?EVvxx-;dj0g#lP z0A&6TsvWOuRr0$(h~Og$@`5i&0CnfNHy!Zui5butbkNY%4809TK(`AP&C=&dTZshJ zxfDy!DP&!RLCGZ5QZflb^?M3DC+7k%gTY>CF$DJ?Xn?2gs)y>r*k|PE84pJSv;_CR z7qyq21m$iAkndMH{s}Gp-yFHq#(}TH5A|y4=V_#^Glp87?iZMGh2WQOPQu8fAB<)b z)VDQ2ClaBjIW{L2z)TabL}WlA)R zKlsh#^Dym=U06&i@9$4o=htOZFoC~U;W#3frH;$XNCro0_Aj^L%_x*88a;O~$-JJpal z)zfUKCIXN&BS>lq^ye|48;>miyQ4^iGgszeV0Zz-kpyQI%r-OVkrXD2iE|J1`^NO# zenDsmI=KmMkqNXe{slkyQOoH_+O9?4zPZZ+d$!a;g*rA6&Wa;Yi`} z^XyS;HK5V*ra*7fgF>lEUY3{Aef2-P_v zgkvrUGnm2={s+lj2tsC^M5|FkgG~?hm~IqsDWQ0#M^~5xUw_pB)1K(@bF$|9p$vTk zt4#oTN77}hg3#5z_NwarThpdrv()sDq5pNSp+O+|gd>3=KM6*$p8D-$vk(W_f9aPu zQLo{ut|Po^1Q2@uw#6r((W+#hcoM`|LP^KYt5=F9@v{(4)^!f)`HB z!@1Fb*DKTZjwx(&tLX|>g#d!z?}|IRb*bo;J9b*3tJ%m+;Aqw6M*Rf*cyP6{zj{K8 zN_Fa`?@`t8pME_F!D#ABmsKrafK_w_t3?2=t$#~o{97iy;=@PoYvHbQfghv&A&i3u z0;};x<&g$-b@h1~nT}odz#Eqqygs>p^Q6i~!^T#nYFKgt2-@Ekb!^fn!6umUA_1*<^-ZWhp{(CBkU zo$`rC?{DRv7tA7w*MNlQJhcmkKE+I4w^qm zYY5Tuu)bI>@WmE^4Af#N>=H(V;dT^dt}Q2AJYZaUJseHKSN~%KYXtI7T-Ud)O1E*T z3BYN8$Ku#$w93>!{=t3iT%!*yonlQl&C*UFSABd-+)9L=Ux@Kw`{Shp`~8SO6g`nc zo+d}SS%DUyrd>z7O?-=_Ae4V1@=K?jaD5`sKWywc2>g=rCA9)2BLKS>K&Nl`az{&5 z%l=(9f>i$>g8zx4X-d$OF4I-lmy_kzr{QJRg+fn@rUp4>$rOjT7KPq z()s~+uJ(rz@aa%-hjUfB^r988i>!dx7lBva9D$(9v}fMfFaRYSL|Q5WaHD){0@IuI zk-(Yz?rw+bYAsjyZ%z-Hqus!q>Byf*FdOE5{CX1_fwWt~3jE?X*C3RTeZgVrdIqw? z$ct_TicSC~_|w|whd-lLB%l8MhkNhXI&LhS;(n{uyty1FTj)%Ao*|R@pkXf^`7bn`~`BlPPioKYy_w;ws(87pxt$!Bk1s5-2JG*hL?z z=SM%FiY)%<_aE8L-6PGfQS+NYUYIIjNv=_8uEE-XXe9IR-o6elPxPPN_D#YDQ$=4* zq}T)ymVYyt9aleZHYh)N=RG~#J!QH{bc7~UcuH83YgDTB0G)NY*Uq1tfXPYUs|$@= zgbk*OzM^Qc36R+bpnCesH|lMMBYXC@=R7myz?_7OUw~^}sLx<~Ywoqdt4Jv7YDta7HYyxB!d#IYc^g?%!ZC`h9ZYB597~i3@AxmX*Gn!APgJ^Vk4hH&X{Jyqr z)FMdh3KYFnuxJEe>i^uLPsXwS-*#`R>+NC)5XCzGwTY6KKY3eXGbJy_H7hm?p9FEc0&x1BL0IhA zNr6;JHkc|V0dm&;(_cR~wCB(!urLI0d#Ss#mckk|l674Qh zOakO=0-+u}du8uETfkVI9Sc1>i#b@~J^<@cbXai1qHF)--_t zMcr$-*aQ&P`>Rn5oW9t%zZ+`nvrf&qL4bln1h6v%a89`3+PTp{qIb_B$X#8$q6xsQ z`zyP8_GgXlwyw@?+18C&BtT??0C`1&rB}xgVDRj9a5{YNq`G&|7Bdt+3l^YgjX@Jmz ztzAFC+gN{EJGB5|2avj?Z(&Pfbnq+Nwl(Q@?redHAlfnHa&V(DXo*-`05;kA`47im zJ`bT_d_dW^`*XlAFE8vdQ1l+bVz&e2>;;IaHa2qYPm&(@69?|v4BNYEV0sbY+5q~v zbu{vKIcdR?>gfbdK~BFr1g;5JNY%ONbMh+l5ajMKQuHn6iro^(uKI0FCrfnT!Y5?0 z$nA&j+Xh=24dAEs_6GQ|f$Lc`Xfrq01JtAT4`Z2}{@ozVPt1a{sqOzL?TsfvdXIsk z4h}7LXOOTH7{vj?<`3i!szT>a{=FPh&AaZ|4trV+pum`5Vgg_kvlw1y)_?}b&>+xe zGoIV{H4!epHwf+tCw{K~p1QU3Rgm6epyfS7Hr4gELGz|&*lbWj6U75e zHi-l?K0a0Y>>(QY+)%}*deMTS^Jw8NU|R47z|lVpi!KkSEwwKhHuwD!Z&Nr-Ak%;k z50iwg<>>yJni?k52m}(4B_I+I8K`K;I#8^j3Jeb18=ZGOB$vx|_U+x!&|VLlQA^tB zS44n&(K1YB@!kms$hF!bV|VYr zE32xheox?%?V}tK;AHXz%@0C}x0fm9>|nA2+$0gmlAt=B=rb8cB7r&)4jUFnh7L#P z=O0q(wP5LN0c&eLbgGoli!?Iic}oxK%tDAia_2#Q&4E$~&EB!#8=H0fJU#;6EWI}b zKlKe^8^v>PA`Gs95e|5nQt8$;HvNabwf!94B3mbbPnz$8ECB@YX}TWDPAOYPYq9|itk2N$kc_6ajzKbk^vB3uBt`?{_7@-S)sg>6A*DU|P zXVV={PNw6@xx!8;yJ_ip-SX>0a|2!{5WZoA)QLG>T$lszxB~)?IUe{r`%A{I9@;#T zG?_ppaLMcw&;-0ceGEVre9j@R$t7Y)7!nAUfJi{Vn;`27hy_b3bY8uz}U$C zh|6_XDju&KEHn6L;(135dY%>r*J>`CuSfp z=i8QyMjPq3$vWt2 zE!AB4UPQ_=*cvY0`O$gS@2olS$|L8S+xx$R(r8%L9+#GKw#@d zNteFP1&F|tfF%M)hD11|56(EcV*!6-Y;mzG8HqHel1VNsQ|fh~)M-IMN3M6icdMxz@woSJ4+kPEt??PA~~kPY^P zfKNCVfM>P-*4{8ekhDu+-GX2dSTe9A&_I?1tZQJcLJk?2yorx1k(9)dO{|F*d_3#t z1>nO>5{Gba-08b3OVDecK z2-jJSUsYe9Pby*GKq(@yWMGqqIbVrIkTbu{5}}Y30-iPVLW+t~MBl*Lbm13;|dX1&acZEFtnG z_PKm9LZN(%gS!MsgU_1&I4lJ_2XrW-k6%tIk^q7*Rv{lDSdf*Xdxc_xd?Gge0tr|v z!217$=z4f h2(Zp&g8=JX{y&U>Q-J*$G|~V7002ovPDHLkV1o2sBAWmJ literal 0 HcmV?d00001 diff --git a/primefaces-webapp/src/main/webapp/resources/images/user.png b/primefaces-webapp/src/main/webapp/resources/images/user.png new file mode 100644 index 0000000000000000000000000000000000000000..63e9bb97f2338650b6060a5ee6bc6bd8c99c9923 GIT binary patch literal 4683 zcmV-R6144!P)4Tx05}naRo`#hR1`jmZ&IWdKOk5~hl<6oRa0BJ z8yc;~21%2p?MfD<>DVeH9(p*dx19w`~g7O0}n_%Aq@s%d)fBDv`JHk zDym6Hd+5XuAtvnwRpGmKVkc9?T=n|PIo~X-eVh__(Z?q}P9Z-Dj?gOW6|D%o20XmjW-qs4 zUjrD(li^iv8@eK9k+ZFmVRFymFOPAzG5-%Pn|1W;U4vNroTa&AxDScmEA~{ri9gr1 z^c?U@uwSpaNnw8l_>cP1d;)kMQS_;jeRSUEM_*s96y65j1$)tOrwdK{YIQMt92l|D z^(E_=$Rjw{b!QT@q!)niR`|5oW9X5n$Wv+HVc@|^eX5yXnsHX8PF3UX~a6)MwxDE0HaPjyrlI!;jX{6Kvu zh*8ej?;85ekN$?5uuCiSBTvvVG+XTxAO{m@bvM#Jr)z6J><&E22D|vq?Y?Vkbo_Di zjopiF$2PET#mZ8eu=y$(ArYkv7@Ex z`GL?QCc!_*KFrd&;n1r7qW-CFs9&fT)ZaU5gc&=gBz-DaCw(vdOp0__x+47~ zU6sC(E(JNe@4cTT*n6*EVH4eoU1-&7pEV~_PRe`a7v+@vy!^5}8?Y3)UmlaER00009a7bBm000XS000XS z0e@s)kpKVP)*c^PMyAnLTgv?3ta*nfJW!?|Z+?IWyBYGBPr$s@B)nHyhsD zb_0hwGQ#txaogt)!csULmcSf11#;WNjV-VN{+Y3nt@}OXzS#DJ^;PXyNa8Fae-*5S z3t=(LfPT;p!G2H(o8eJ-1kQo;VG!oRiJ)MPX9szLiGLb?1wVsfc&!(NP#FP`c$0h$ zd=ZwzcoS%A6_Y)lg!8nfrnt7ly>Kf$4*RMsgh~j2FNy z2O>Dtst@4>K=Lo+pl*jD=(Gj58lU4m|23X)58MQH5tZu}LJNT8+t=R#^C7C)E!+<` z!edaWE+MP{Nd8+1=H1}vKDs%^_%+-B>*x+%jqY&n-wFARNL!M>2!C#aDkR^~*)?4W z*TE9}pTf2h7E%C2?sKrJ5)nM&q_O-cTn!5lL6pJj5f2;O3MT*pcPW0_lA;ax8ieov z?wZa$ir_qO+8W+M2_P$-*Aumw;Um}F!LxYia#+mqOm6|S!03o>mRznqAf1Xi& zUjyfYtCpcHngBjev?@_LkCW9ic>E$5h+YN42!KF&GRD%`3)as;I1X3_jtjzC7y%HW zcf;(kk!syB1+WrkBJQwVS_lDT0lK2~7>9nvJiI#{T*b5^gtQO>ATkEYHUF?JrH$-) zES|q`QEO@&uP@~#Q3P-*M;m#)zujbb4ZHirYU0=TXbvbseP zz$FAIiZ8g5%q;z`1xUz6p{@s=(x?xE(2Hi$o!&~w6GUAX0D&<`jsbenEc=#!yMkH( zO)~6RGh0ZnngXc1fMaCW3J|h&9K+{U9#R0V2KGms2}I}uTqNm*_5Ws~@YqgvyaZPVBV+ikFfLT*g^y0W^sBe(u}Z;Qn5@ z%a&hPfMaCybspPtjK{0~ke7^yZ2bl{LKomisy69NkJ>97mmeNc2;nS(01VFa;Ubg9 zA(JkC!dSwIpz8w2K3V%h#Ngmlr)I+al#o?Up@*}s3m}WgFk4$lui0J>$S5)G=VAQmwdtVA_gh3l&H(T$h5&Q~ zdkOqbfZxGZ=moO^So*`xa6(i7GffpRNZ)~Pz++H#v(a=3P2EAHCxOt!BKP-P2oDL5xcUmLJljfuBfzQVx9o9 z|KA3+00=_6W+3l?u+yj}2lg!YE8Ki4*yL&5zdLLN$U@^n%AK&G`=J`Q2TuF!|MhuK zHl7*xi_3muXaQuwTSrj74PjT){wHZ(0Fn#9ZD^3Zk3S*MEU$HSGfQ zJ+y@vKvo3|=FJfOvax6I(ZS!-urqr3$H!2ogY~DO5lGAb18^He?Ft;IJ_26htN_B7 ze|)Tl0CW^Hptr&w{3oC}=hsKaEG`2_6)LVBvG83$?kZKl7Pb*?2Nzl*EwAd^@4>_m z!|p1SfBdXe1<+qx)x|K|e*&576<+^u@)be&!5==3T4gFg?l9XofuFYR8*^VbZ#wdy z2X6)kfR*~?u&N1QIssk|k<5>O&x92)t!e@|g`=3!@JPCUr{Y`)`lu)> zVO0}=gRQ8eYr7;x;P|8;Dq&RJH&$LA}1>itX{Moq4 zRTv96ny!)!;B4eB;3E7x58ekqf}bM-mxQDGJSpr?#}d3zBY>7ur+%M;tHCK(^sdWA zDwFPK9KHqjfr~><8ADlU0g(JNh}IY2gD?xC%>8j?+~&CDZny=!+wVRMAB zK^Os$e5X%eg3o~S>0Y&c9N1m(HCT@bx_Z%Q2mz4%vk1m_;WDUtx#tj$Yjz2KA;yg` zj0hA(SFGy-Ao;5~@*lt;OoZffn4{(x;9j^1{svw707=&bK;ljIHDJr13lq_-1P%(X zhjml}uP83nx;dZz07vQ-J`*+hCfY`@2K>?NA=<=AY)iG$1z^j^Z22bNA5)s>W)40C zpMcYdO{pi6N*4eJ>1y8h!PBO-{Wk(r*jx+mfq96aw7it|Mjj^zb|xE_M(gAokfY6u zO0I)TptOrhN)rIdU(A8s35%e%#t~S--5-bLP|A3q6ai%Y+SfU#bD_585pYnr7TyH| z#I5k_3Q7?G2lEm5FqHLvyj5k*OWr;PHkKKPpwP9E!V`l3OE{1(!(^y!d=c--I%2x=RD1Z?$o18;#jMOJ}A1%UHcf`ghu%NYCbMRU;Xxe=>?)5Joo zFae-iOTJ5-Qw#CD_jhWeSqp5C))-F;pP}K&{ho z__I*R{@L$DvbS-tE}*$kl-!C+&=q*<0H*HyJ5QO5Lrw|j(y)@R3nUjn=H#_FT-d;+ z^O#m@500T$frG*1$k6Z ze`*I)9&E+;HHiPGLedjN$pnC7Ud#V>sHc7ep#ZacT>!Ho*`iQN0a&7(uGCgc1Wfuo z@MCky#sMh>VCzrj82hU2=m=O@?E(})vh{$J0&wN8wqhgTEWq;uQ?oHw$M2Rz0662? zzb7qfD>edNM(+i+R)8d9tt0}#8Rw`DP--hS0yZ?Kfs!P5Np^xW4gl-^pCA-$3c%K{ z0FtZ-rV@ao|0E8vpW2#7z!)n4r`$>6ok{>_<4}@5iT%{pJOakpN^2!ZvKG*>02lzO z$YoGlIT0{tilF1%>28XhxH9D$b#3KD!2aKBEmGtz$xi%ucl{~fa+2@6*bR8OeHa0_ zGNmeOD=z{`lCQfdcI1aWlMG18i(lp6$tvJtV8;XR6asK*vSUXopOSJ9z^|4`VkrdR z8LHaKi$I=yzEWr;zuoq`rw~Bh|F<3fwqCfOS0($F(G&uxD?nR$Z2Ltf-yfw)B7zhG zsIUKTJC`lL(2{QjcpbVgfNT_63!vpZw*7)VS@K_Dd!X&TjCo;46(AdgOyuwR8xzXH zZyw|w?t|U%5?BQ~wvGglz5D%aRbjR?FrVHPX_g|HUh30}We3xOcCU?zSSJOEo@1K9GP@PCq@ zr1Z0|QA;8K_cUfkVA7YtrLYFx0rg@LK^TYaqXQ_V@cEZar3?|>iZ->HuXezk?aCX!X!U^0^ z2!5p54>b6_0juClP!x_ECTjO!nYX;#x;KFXJ^z0Oo`Qda{k}gUkz~P#eKoYg1dzX5 zRuQ~}$t#EEgH^!U!Vs*4vq3RTfnF7a2{*}>c3Zc}b|7bxO|~t418jxeP};AD6fOV` zX4EnvIAgFXIAFAkPz(ye!Q(<0gk>-QCqh-tR_ofxMzDpOa98p6fk}5B{~Y+3eZ5In zAO~piilsCwO#ow$Xp9&f9Qxh3bHJo80=o+2WGZrlWbyb z;F#69LTve>-5dXO}49c-u6DLLB0>4 zf3WP9&U-ert_xtSSD6^R%dWy?+FeLqDHMQ-cRV4AMSR@n=K}CG4nj4>l~<0@JC5-u zPozn*jN7`sFTdX;` + + + +Untitled Document + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/primefaces-webapp/src/main/webapp/showtimes.xhtml b/primefaces-webapp/src/main/webapp/showtimes.xhtml new file mode 100644 index 0000000..8e26ba4 --- /dev/null +++ b/primefaces-webapp/src/main/webapp/showtimes.xhtml @@ -0,0 +1,121 @@ + + + + + + + Show Times + + +