diff --git a/.classpath b/.classpath index 8c43cc2b..9a59b4ce 100755 --- a/.classpath +++ b/.classpath @@ -15,7 +15,6 @@ - @@ -63,7 +62,7 @@ - + diff --git a/README.md b/README.md index c873a53d..632f84bd 100644 --- a/README.md +++ b/README.md @@ -9,13 +9,19 @@ Over the last years it turned out that people want more lightweight and mobile-f So briefly what is Requirement Bazaar? It is a web application that provides a user-friendly, yet developer usable way, how end-users and developers can share ideas/requirement/problems about a certain app. +We also provide a modern webcomponent frontend for this service which you can find also on **[Github](https://github.com/rwth-acis/RequirementsBazaar-WebFrontend)**. + +The service is under development. You can participate by creating pull requests or by discussing ideas and requirements inside **[Requirements-Bazaar](https://requirements-bazaar.org/projects/2/categories/143)**. + +More information about our microservice ecosystem is explained in our **[Requirements-Bazaar wiki on Github](https://github.com/rwth-acis/RequirementsBazaar/wiki)**. + ---------- Service Documentation ------------------- We use **[Swagger](http://swagger.io/specification/)** for documenting this microservice. You can use **[Swagger UI](http://swagger.io/swagger-ui/)** to inspect the API. -In the future we want to deploy our own Swagger UI instance which you can use to check and use the API. Until then please use the **[Swagger petstore instance](http://petstore.swagger.io/)**. -Open the Swagger UI petstore demo, enter the APi endpoint you want to inspect and press explore. Of course the microservice instance you want to inspect needs to run. At the moment you can not authorize yourself, but we are working on this feature. +Please use our deployed **[Swagger UI instance](https://requirements-bazaar.org/docs)** to inspect our API. You can authorize yourself via Oauth 2.0 by clicking at the `Authorize` button at the top. After you are authorized you can try out all the API calls directly from Swagger UI. +To try out one API call open one method, fill the parameters and click `Try it out!`. The Swagger UI instance is connected to our development environment where we test nex features. So feel free to play around. API documentation endpoints: @@ -27,9 +33,7 @@ Technology ------------------- Requirements bazaar itself is a web application, which is separated to a client-only side and a back-end side. This GitHub repo holds the codebase of the back-end side only. If you are looking for the front-end, take a look at this GitHub project: **[Requirement Bazaar Web Frontend](https://github.com/rwth-acis/RequirementsBazaar-WebFrontend)** -The backend is built on Java technologies. As a service framework we use our in-house developed **[las2peer](https://github.com/rwth-acis/LAS2peer)** project. For persisting our data we use MySQL database and jOOQ to access it. User input validation is done using Jodd Vtor library and for serializing our data into JSON format, we use GSON library. - ----------- +The backend is built on Java technologies. As a service framework we use our in-house developed **[las2peer](https://github.com/rwth-acis/LAS2peer)** project. For persisting our data we use MySQL database and jOOQ to access it. User input validation is done using Jodd Vtor library and for serializing our data into JSON format, we use the Jackson library. Dependencies ------------------- @@ -42,15 +46,15 @@ In order to be able to run this service project the following components should How to set up the database ------------------- 1. `git clone` this repo - 2. create a new database called `reqbaz`, possibly with UTF-8 collation - 3. Run the SQL commands in the file `\etc\ReqBaz_create.sql` - This will create the tables and relations between them. - 4. If you need sample data run the file `\etc\ReqBaz_demo_data_FULL.sql` if not run: `\etc\ReqBaz_demo_data.sql` - 5. To configure your database access look at the [Configuration](#configuration) section + 2. To configure your database access look at the [Configuration](#configuration) section + 3. Compile the project with `ant` + 4. Create a new database called `reqbaz`, possibly with UTF-8 collation + 5. Run `ant migrate-db` to create your db schema or migrate to a newer version while updating your service + 6. If you need sample data run the file `\etc\add_reqbaz_demo_data.sql` or `\etc\add_reqbaz_demo_data_full.sql` Configuration ------------------- -You need to configure this service to work with your own specific environment. Here are the list of configuration files and their short description: +You need to configure this service to work with your own specific environment. Here is the list of configuration variables: `\etc\de.rwth.dbis.acis.bazaar.service.BazaarService.properties`: - `dbUserName`: A database user's name, which will be used to access the database @@ -59,10 +63,11 @@ You need to configure this service to work with your own specific environment. H - `land`: Default language setting - `country`: Default country setting - `baseURL`: Base URL this service runs on - - `frontendBaseURL` Base URL for the frontend which uses Requirements-Bazaar service - - `activityTrackerService` p2p microservice name of the las2peer activity tracker. Leave this field empty if no las2peer activity tracker is used. (example: `de.rwth.dbis.acis.activitytracker.service.ActivityTrackerService@0.2`) - - `smtpServer` SMTP server to send email notifications to users. Leave this field empty if no email notification is used. - - `emailFromAddress` Email from address which is used for email notifications to users. Leave this field empty if no email notification is used. + - `frontendBaseURL`: Base URL for the frontend which uses Requirements-Bazaar service + - `activityTrackerService`: p2p microservice name of the las2peer activity tracker. Leave this field empty if no las2peer activity tracker is used. (example: `de.rwth.dbis.acis.activitytracker.service.ActivityTrackerService@0.2`) + - `smtpServer`: SMTP server to send email notifications to users. Leave this field empty if no email notification is used. + - `emailFromAddress`: Email from address which is used for email notifications to users. Leave this field empty if no email notification is used. + - `monitor`: Boolean value for logging calls to MobSOS data processing For other configuration settings, check the **[las2peer](https://github.com/rwth-acis/LAS2peer)** project. @@ -70,7 +75,11 @@ Build ------------------- For build management we use Ant. To build the cloned code, please using a console/terminal navigate to the home directory, where the build.xml file is located and run the following commands: - 1. `ant` + - `ant` + +You can also generate a bundled jar with all the dependencies with the command + + - `ant jar-big` How to run ------------------- @@ -87,3 +96,12 @@ How to run 1. `git clone` this repo 2. `docker build -t rwthacis/reqbaz-service` 3. `docker run -i -t --rm -v "pwd":/build rwthacis/reqbaz-service` + +---------- + +Troubleshooting & FAQ +------------------- + - I get Java encryption errors: Did you install Java Cryptography Extension? + - I can not run the start script: Check if you have OS permission to run the file. + - The service does not start: Check if all jars in the lib and service folder are readable. + - The start script seems broken: Check if the start script has the correct encoding. If you ran the service on Unix use `dos2unix` to change the encoding. \ No newline at end of file diff --git a/build.xml b/build.xml index 9484d616..0a1bafa2 100755 --- a/build.xml +++ b/build.xml @@ -1,8 +1,11 @@ - + + + @@ -16,6 +19,7 @@ + @@ -68,6 +72,7 @@ + @@ -80,6 +85,7 @@ + @@ -142,7 +148,7 @@ # it starts a LAS2peer node providing the service '${service.name}.${service.class}' of this project # pls execute it from the root folder of your deployment, e. g. ./bin/start_network.sh - java -cp "lib/*" i5.las2peer.tools.L2pNodeLauncher -p 9011 uploadStartupDirectory startService\(\'${service.name}.${service.class}@${service.version}\',\'${service.passphrase}\'\) startWebConnector interactive + java -cp "lib/*" i5.las2peer.tools.L2pNodeLauncher -p 9011 uploadStartupDirectory startService\(\'${service.name}.${service.class}@${service.version}\',\'${service.passphrase}\'\) startWebConnector interactive :: this script is autogenerated by 'ant startscripts' @@ -155,7 +161,7 @@ set BASE=%CD% set CLASSPATH="%BASE%/lib/*;" - java -cp %CLASSPATH% i5.las2peer.tools.L2pNodeLauncher -p 9011 uploadStartupDirectory startService('${service.name}.${service.class}@${service.version}','${service.passphrase}') startWebConnector interactive + java -cp %CLASSPATH% i5.las2peer.tools.L2pNodeLauncher -p 9011 uploadStartupDirectory startService('${service.name}.${service.class}@${service.version}','${service.passphrase}') startWebConnector interactive pause @@ -177,6 +183,18 @@ + + + + + + + + + + + + @@ -258,6 +276,24 @@ + + + + + + + + + + + + + + + + + + - + diff --git a/etc/ant_configuration/service.properties b/etc/ant_configuration/service.properties index 746109ef..1ca94066 100755 --- a/etc/ant_configuration/service.properties +++ b/etc/ant_configuration/service.properties @@ -1,6 +1,6 @@ -service.version=0.6 +service.version=0.7 service.name=de.rwth.dbis.acis.bazaar.service service.path=de/rwth/dbis/acis/bazaar/service service.class=BazaarService service.passphrase=Passphrase -service.dependencies=commons-codec;version="1.9",commons-dbcp2;version="2.0",commons-io;version="2.4",commons-logging;version="1.2",commons-pool2;version="2.2",emoji-java;version="3.1.3",gson;version="2.3",httpclient;version="4.5.1",httpcore;version="4.4.3",jodd-bean;version="3.6.1",jodd-core;version="3.6.1",jodd-vtor;version="3.6.1",jooq;version="3.9.1",jooq-codegen;version="3.9.1",jooq-meta;version="3.9.1",json;version="20140107",mysql-connector-java;version="5.1.6" +service.dependencies=commons-codec;version="1.9",commons-dbcp2;version="2.0",commons-io;version="2.4",commons-logging;version="1.2",commons-pool2;version="2.2",emoji-java;version="3.1.3",gson;version="2.3",httpclient;version="4.5.1",httpcore;version="4.4.3",jodd-bean;version="3.6.1",jodd-core;version="3.6.1",jodd-vtor;version="3.6.1",jooq;version="3.9.1",jooq-codegen;version="3.9.1",jooq-meta;version="3.9.1",json;version="20140107",mysql-connector-java;version="6.0.5" diff --git a/etc/de.rwth.dbis.acis.bazaar.service.BazaarService.properties b/etc/de.rwth.dbis.acis.bazaar.service.BazaarService.properties index 8858c057..4d623ebf 100644 --- a/etc/de.rwth.dbis.acis.bazaar.service.BazaarService.properties +++ b/etc/de.rwth.dbis.acis.bazaar.service.BazaarService.properties @@ -5,7 +5,8 @@ lang=eng country=us baseURL=http://localhost:8080/bazaar/ frontendBaseURL=http://localhost:5000/ -activityTrackerService=de.rwth.dbis.acis.activitytracker.service.ActivityTrackerService@0.3 +activityTrackerService=de.rwth.dbis.acis.activitytracker.service.ActivityTrackerService@0.4 activityOrigin=https://requirements-bazaar.org smtpServer= -emailFromAddress= \ No newline at end of file +emailFromAddress= +monitor= \ No newline at end of file diff --git a/etc/i5.las2peer.webConnector.WebConnector.properties b/etc/i5.las2peer.webConnector.WebConnector.properties index f03ec045..8c815727 100755 --- a/etc/i5.las2peer.webConnector.WebConnector.properties +++ b/etc/i5.las2peer.webConnector.WebConnector.properties @@ -11,5 +11,4 @@ preferLocalServices = TRUE xmlPath = defaultLoginUser=anonymous defaultLoginPassword=anonymous -oidcProviders = https://api.learning-layers.eu/o/oauth2,https://accounts.google.com -monitor = false \ No newline at end of file +oidcProviders = https://api.learning-layers.eu/o/oauth2,https://accounts.google.com \ No newline at end of file diff --git a/etc/ivy/ivy.xml b/etc/ivy/ivy.xml index b9dc72e4..ac46de77 100755 --- a/etc/ivy/ivy.xml +++ b/etc/ivy/ivy.xml @@ -14,7 +14,9 @@ - + + + diff --git a/etc/ReqBaz_create.sql b/etc/migrations/V1__create_reqbaz_schema.sql similarity index 83% rename from etc/ReqBaz_create.sql rename to etc/migrations/V1__create_reqbaz_schema.sql index 5ca31869..296fb54f 100644 --- a/etc/ReqBaz_create.sql +++ b/etc/migrations/V1__create_reqbaz_schema.sql @@ -1,13 +1,5 @@ SET FOREIGN_KEY_CHECKS = 0; -CREATE DATABASE IF NOT EXISTS reqbaz; - -DROP TABLE IF EXISTS reqbaz.attachment, reqbaz.comment, reqbaz.category, -reqbaz.requirement_developer_map, reqbaz.requirement_follower_map, reqbaz.category_follower_map, -reqbaz.project_follower_map, reqbaz.privilege, reqbaz.project, reqbaz.requirement, -reqbaz.requirement_category_map, reqbaz.role_privilege_map, reqbaz.role_role_map, -reqbaz.role, reqbaz.user_role_map, reqbaz.vote; - -- tables -- Table attachment CREATE TABLE IF NOT EXISTS reqbaz.attachment ( @@ -232,4 +224,95 @@ CREATE TABLE IF NOT EXISTS reqbaz.vote ( CONSTRAINT vote_user FOREIGN KEY vote_user (user_id) REFERENCES user (id) ); +-- Fill roles and privileges +REPLACE INTO reqbaz.role +(id, name) +VALUES + (1, 'Anonymous'), + (2, 'LoggedInUser'), + (3, 'ProjectAdmin'), + (4, 'SystemAdmin'); + +REPLACE INTO reqbaz.privilege +(id, name) +VALUES + (1, 'Create_PROJECT'), + (2, 'Read_PROJECT'), + (3, 'Read_PUBLIC_PROJECT'), + (4, 'Modify_PROJECT'), + (5, 'Create_CATEGORY'), + (6, 'Read_CATEGORY'), + (7, 'Read_PUBLIC_CATEGORY'), + (8, 'Modify_CATEGORY'), + (9, 'Create_REQUIREMENT'), + (10, 'Read_REQUIREMENT'), + (11, 'Read_PUBLIC_REQUIREMENT'), + (12, 'Modify_REQUIREMENT'), + (13, 'Create_COMMENT'), + (14, 'Read_COMMENT'), + (15, 'Read_PUBLIC_COMMENT'), + (16, 'Modify_COMMENT'), + (17, 'Create_ATTACHMENT'), + (18, 'Read_ATTACHMENT'), + (19, 'Read_PUBLIC_ATTACHMENT'), + (20, 'Modify_ATTACHMENT'), + (21, 'Create_VOTE'), + (22, 'Delete_VOTE'), + (23, 'Create_FOLLOW'), + (24, 'Delete_FOLLOW'), + (25, 'Create_DEVELOP'), + (26, 'Delete_DEVELOP'); + +REPLACE INTO reqbaz.role_privilege_map +(id, role_id, privilege_id) +VALUES + (1, 1, 3), + (2, 1, 7), + (3, 1, 11), + (4, 1, 15), + (5, 1, 19), + (6, 4, 1), + (7, 4, 2), + (8, 4, 8), + (9, 4, 7), + (10, 4, 6), + (11, 4, 5), + (12, 4, 3), + (13, 4, 4), + (14, 4, 9), + (15, 4, 10), + (16, 4, 11), + (17, 4, 12), + (18, 4, 13), + (19, 4, 14), + (20, 4, 16), + (21, 4, 17), + (22, 4, 18), + (23, 4, 19), + (24, 4, 20), + (25, 4, 21), + (26, 4, 22), + (27, 4, 23), + (28, 4, 24), + (29, 4, 25), + (30, 4, 26); + +REPLACE INTO reqbaz.role_role_map +(id, child_id, parent_id) +VALUES + (1, 2, 1), + (2, 3, 2), + (3, 4, 3); + +REPLACE INTO reqbaz.user_role_map +(id, role_id, user_id) +VALUES + (1, 1, 1); + +REPLACE INTO reqbaz.user +(id, first_name, last_name, email, admin, las2peer_id, user_name, profile_image, email_lead_subscription, email_follow_subscription) +VALUES + (1, NULL, NULL, 'anonymous@requirements-bazaar.org', 0, '-1722613621014065292', 'anonymous', + 'https://api.learning-layers.eu/profile.png', 0, 0); + SET FOREIGN_KEY_CHECKS = 1; \ No newline at end of file diff --git a/etc/ReqBaz_demo_data.sql b/etc/migrations/add_reqbaz_demo_data.sql similarity index 98% rename from etc/ReqBaz_demo_data.sql rename to etc/migrations/add_reqbaz_demo_data.sql index d2d5f701..0a518b29 100644 --- a/etc/ReqBaz_demo_data.sql +++ b/etc/migrations/add_reqbaz_demo_data.sql @@ -134,6 +134,7 @@ VALUES (4, 1, 3, 4), (5, 1, 4, 4); +-- roles and privilege schema is already set up with V1__create_reqbaz_schema REPLACE INTO reqbaz.role (id, name) VALUES diff --git a/etc/ReqBaz_demo_data_FULL.sql b/etc/migrations/add_reqbaz_demo_data_full.sql similarity index 99% rename from etc/ReqBaz_demo_data_FULL.sql rename to etc/migrations/add_reqbaz_demo_data_full.sql index 3d86a355..520d886e 100644 --- a/etc/ReqBaz_demo_data_FULL.sql +++ b/etc/migrations/add_reqbaz_demo_data_full.sql @@ -620,6 +620,8 @@ VALUES (20, 1, 15, 6), (21, 1, 16, 7); + -- roles and privilege schema is already set up with V1__create_reqbaz_schema + REPLACE INTO reqbaz.role (id, name) VALUES diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/AttachmentsResource.java b/src/main/de/rwth/dbis/acis/bazaar/service/AttachmentsResource.java index e7ba79a0..89649f9c 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/AttachmentsResource.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/AttachmentsResource.java @@ -1,6 +1,5 @@ package de.rwth.dbis.acis.bazaar.service; -import com.google.gson.Gson; import de.rwth.dbis.acis.bazaar.service.dal.DALFacade; import de.rwth.dbis.acis.bazaar.service.dal.entities.*; import de.rwth.dbis.acis.bazaar.service.dal.helpers.PageInfo; @@ -47,9 +46,8 @@ @Path("/attachments") public class AttachmentsResource { - private BazaarService bazaarService; - private final L2pLogger logger = L2pLogger.getInstance(AttachmentsResource.class.getName()); + private BazaarService bazaarService; public AttachmentsResource() throws Exception { bazaarService = (BazaarService) Context.getCurrent().getService(); @@ -81,8 +79,8 @@ public Response getAttachmentsForRequirement(int requirementId, int page, int pe Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); Requirement requirement = dalFacade.getRequirementById(requirementId, internalUserId); Project project = dalFacade.getProjectById(requirement.getProjectId(), internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_44, Context.getCurrent().getMainAgent(), "Get attachments for requirement " + requirementId); - + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE_CHILD, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_44, + requirement.getId(), Activity.DataType.REQUIREMENT, internalUserId); if (dalFacade.isRequirementPublic(requirementId)) { boolean authorized = new AuthorizationManager().isAuthorized(internalUserId, PrivilegeEnum.Read_PUBLIC_COMMENT, String.valueOf(project.getId()), dalFacade); if (!authorized) { @@ -95,7 +93,6 @@ public Response getAttachmentsForRequirement(int requirementId, int page, int pe } } PaginationResult attachmentsResult = dalFacade.listAttachmentsByRequirementId(requirementId, pageInfo); - Gson gson = new Gson(); Map> parameter = new HashMap<>(); parameter.put("page", new ArrayList() {{ @@ -106,7 +103,7 @@ public Response getAttachmentsForRequirement(int requirementId, int page, int pe }}); Response.ResponseBuilder responseBuilder = Response.ok(); - responseBuilder = responseBuilder.entity(gson.toJson(attachmentsResult.getElements())); + responseBuilder = responseBuilder.entity(attachmentsResult.toJSON()); responseBuilder = bazaarService.paginationLinks(responseBuilder, attachmentsResult, "requirements/" + String.valueOf(requirementId) + "/attachments", parameter); responseBuilder = bazaarService.xHeaderFields(responseBuilder, attachmentsResult); Response response = responseBuilder.build(); @@ -161,7 +158,8 @@ public Response getAttachment(@PathParam("attachmentId") int attachmentId) { Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); Attachment attachment = dalFacade.getAttachmentById(attachmentId); Requirement requirement = dalFacade.getRequirementById(attachment.getRequirementId(), internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_49, Context.getCurrent().getMainAgent(), "Get attachment " + attachmentId); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_49, + attachment.getId(), Activity.DataType.ATTACHMENT, internalUserId); if (dalFacade.isProjectPublic(requirement.getProjectId())) { boolean authorized = new AuthorizationManager().isAuthorized(internalUserId, PrivilegeEnum.Read_PUBLIC_ATTACHMENT, String.valueOf(requirement.getProjectId()), dalFacade); if (!authorized) { @@ -173,8 +171,7 @@ public Response getAttachment(@PathParam("attachmentId") int attachmentId) { ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.AUTHORIZATION, Localization.getInstance().getResourceBundle().getString("error.authorization.attachment.read")); } } - Gson gson = new Gson(); - return Response.ok(gson.toJson(attachment)).build(); + return Response.ok(attachment.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -220,7 +217,6 @@ public Response createAttachment(@ApiParam(value = "Attachment entity as JSON", if (registrarErrors != null) { ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, registrarErrors); } - Gson gson = new Gson(); Vtor vtor = bazaarService.getValidators(); vtor.useProfiles("create"); vtor.validate(attachmentToCreate); @@ -236,10 +232,9 @@ public Response createAttachment(@ApiParam(value = "Attachment entity as JSON", } attachmentToCreate.setCreator(dalFacade.getUserById(internalUserId)); Attachment createdAttachment = dalFacade.createAttachment(attachmentToCreate); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_50, Context.getCurrent().getMainAgent(), "Create attachment " + createdAttachment.getId()); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, attachmentToCreate.getCreationDate(), Activity.ActivityAction.CREATE, attachmentToCreate.getId(), - Activity.DataType.ATTACHMENT, attachmentToCreate.getRequirementId(), Activity.DataType.REQUIREMENT, internalUserId); - return Response.status(Response.Status.CREATED).entity(gson.toJson(createdAttachment)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(createdAttachment.getCreationDate(), Activity.ActivityAction.CREATE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_50, + createdAttachment.getId(), Activity.DataType.ATTACHMENT, internalUserId); + return Response.status(Response.Status.CREATED).entity(createdAttachment.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -291,9 +286,9 @@ public Response deleteAttachment(@PathParam("attachmentId") int attachmentId) { ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.AUTHORIZATION, Localization.getInstance().getResourceBundle().getString("error.authorization.attachment.modify")); } Attachment deletedAttachment = dalFacade.deleteAttachmentById(attachmentId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_52, Context.getCurrent().getMainAgent(), "Delete attachment " + attachmentId); - Gson gson = new Gson(); - return Response.ok(gson.toJson(deletedAttachment)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.DELETE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_52, + deletedAttachment.getId(), Activity.DataType.ATTACHMENT, internalUserId); + return Response.ok(deletedAttachment.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/BazaarService.java b/src/main/de/rwth/dbis/acis/bazaar/service/BazaarService.java index dde4f834..5ccad894 100755 --- a/src/main/de/rwth/dbis/acis/bazaar/service/BazaarService.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/BazaarService.java @@ -20,13 +20,12 @@ package de.rwth.dbis.acis.bazaar.service; -import com.google.gson.Gson; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.JsonPrimitive; -import com.mysql.jdbc.exceptions.jdbc4.CommunicationsException; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import de.rwth.dbis.acis.bazaar.service.dal.DALFacade; import de.rwth.dbis.acis.bazaar.service.dal.DALFacadeImpl; +import de.rwth.dbis.acis.bazaar.service.dal.entities.Activity; import de.rwth.dbis.acis.bazaar.service.dal.entities.Statistic; import de.rwth.dbis.acis.bazaar.service.dal.entities.User; import de.rwth.dbis.acis.bazaar.service.dal.helpers.PaginationResult; @@ -95,6 +94,7 @@ public class BazaarService extends RESTService { private DataSource dataSource; private final L2pLogger logger = L2pLogger.getInstance(BazaarService.class.getName()); + private static ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL); @Override protected void initResources() { @@ -125,10 +125,10 @@ public void registerFunction(EnumSet functions) throws BazaarExc try { dalFacade = getDBConnection(); AuthorizationManager.SyncPrivileges(dalFacade); - } catch (CommunicationsException commEx) { - ExceptionHandler.getInstance().convertAndThrowException(commEx, ExceptionLocation.BAZAARSERVICE, ErrorCode.DB_COMM, Localization.getInstance().getResourceBundle().getString("error.db_comm")); - } catch (Exception ex) { + } catch (BazaarException ex) { ExceptionHandler.getInstance().convertAndThrowException(ex, ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, Localization.getInstance().getResourceBundle().getString("error.privilege_sync")); + } catch (Exception e) { + ExceptionHandler.getInstance().convertAndThrowException(e, ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, Localization.getInstance().getResourceBundle().getString("error.privilege_sync")); } finally { closeDBConnection(dalFacade); } @@ -162,13 +162,14 @@ public void registerFunction(EnumSet functions) throws Exception props.put("mail.smtp.host", smtpServer); notificationDispatcher.setEmailDispatcher(new EmailDispatcher(this, smtpServer, emailFromAddress, frontendBaseURL)); } + notificationDispatcher.setBazaarService(this); } @Api(value = "/", description = "Bazaar service") @SwaggerDefinition( info = @Info( title = "Requirements Bazaar", - version = "0.6", + version = "0.7", description = "Requirements Bazaar project", termsOfService = "http://requirements-bazaar.org", contact = @Contact( @@ -208,15 +209,19 @@ public Response getStatistics( @ApiParam(value = "Since timestamp", required = false) @QueryParam("since") String since) { DALFacade dalFacade = null; try { + String registrarErrors = bazaarService.notifyRegistrars(EnumSet.of(BazaarFunction.VALIDATION, BazaarFunction.USER_FIRST_LOGIN_HANDLING)); + if (registrarErrors != null) { + ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, registrarErrors); + } UserAgent agent = (UserAgent) Context.getCurrent().getMainAgent(); long userId = agent.getId(); dalFacade = bazaarService.getDBConnection(); Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); Calendar sinceCal = since == null ? null : DatatypeConverter.parseDateTime(since); - Statistic statisticsResult = dalFacade.getStatisticsForAllProjects(internalUserId, sinceCal); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_2, Context.getCurrent().getMainAgent(), "Get statistics"); - Gson gson = new Gson(); - return Response.ok(gson.toJson(statisticsResult)).build(); + Statistic platformStatistics = dalFacade.getStatisticsForAllProjects(internalUserId, sinceCal); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_2, + 0, Activity.DataType.STATISTIC, internalUserId); + return Response.ok(platformStatistics.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -277,21 +282,21 @@ private void registerUserAtFirstLogin() throws Exception { if (agent.getLoginName().equals("anonymous")) { agent.setEmail("anonymous@requirements-bazaar.org"); } else if (agent.getUserData() != null) { - JsonObject userDataJson = new JsonParser().parse(agent.getUserData().toString()).getAsJsonObject(); - JsonPrimitive pictureJson = userDataJson.getAsJsonPrimitive("picture"); + JsonNode userDataJson = mapper.readTree(agent.getUserData().toString()); + JsonNode pictureJson = userDataJson.get("picture"); String agentPicture; if (pictureJson == null) agentPicture = profileImage; else - agentPicture = pictureJson.getAsString(); + agentPicture = pictureJson.textValue(); if (agentPicture != null && !agentPicture.isEmpty()) profileImage = agentPicture; - String givenNameData = userDataJson.getAsJsonPrimitive("given_name").getAsString(); + String givenNameData = userDataJson.get("given_name").textValue(); if (givenNameData != null && !givenNameData.isEmpty()) givenName = givenNameData; - String familyNameData = userDataJson.getAsJsonPrimitive("family_name").getAsString(); + String familyNameData = userDataJson.get("family_name").textValue(); if (familyNameData != null && !familyNameData.isEmpty()) familyName = familyNameData; } @@ -310,7 +315,8 @@ private void registerUserAtFirstLogin() throws Exception { User user = userBuilder.admin(false).las2peerId(agent.getId()).userName(agent.getLoginName()).profileImage(profileImage) .emailLeadSubscription(true).emailFollowSubscription(true).build(); int userId = dalFacade.createUser(user).getId(); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_55, Context.getCurrent().getMainAgent(), "Create user " + userId); + this.getNotificationDispatcher().dispatchNotification(user.getCreationDate(), Activity.ActivityAction.CREATE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_55, + userId, Activity.DataType.USER, userId); dalFacade.addUserToRole(userId, "SystemAdmin", null); } else { // update lastLoginDate @@ -327,7 +333,7 @@ private void registerUserAtFirstLogin() throws Exception { public static DataSource setupDataSource(String dbUrl, String dbUserName, String dbPassword) { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); - dataSource.setUrl(dbUrl); + dataSource.setUrl(dbUrl + "?useSSL=false&serverTimezone=UTC"); dataSource.setUsername(dbUserName); dataSource.setPassword(dbPassword); dataSource.setValidationQuery("SELECT 1;"); diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/CategoryResource.java b/src/main/de/rwth/dbis/acis/bazaar/service/CategoryResource.java index 942ef9b0..4a53fbf3 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/CategoryResource.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/CategoryResource.java @@ -1,6 +1,5 @@ package de.rwth.dbis.acis.bazaar.service; -import com.google.gson.Gson; import de.rwth.dbis.acis.bazaar.service.dal.DALFacade; import de.rwth.dbis.acis.bazaar.service.dal.entities.*; import de.rwth.dbis.acis.bazaar.service.dal.helpers.PageInfo; @@ -77,7 +76,6 @@ public Response getCategoriesForProject(int projectId, int page, int perPage, St if (registrarErrors != null) { ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, registrarErrors); } - Gson gson = new Gson(); List sortList = new ArrayList<>(); for (String sortOption : sort) { Pageable.SortDirection direction = Pageable.SortDirection.DEFAULT; @@ -115,8 +113,8 @@ public Response getCategoriesForProject(int projectId, int page, int perPage, St } } PaginationResult categoriesResult = dalFacade.listCategoriesByProjectId(projectId, pageInfo, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_13, Context.getCurrent().getMainAgent(), "Get categories for project " + projectId); - + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE_CHILD, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_13, + projectId, Activity.DataType.PROJECT, internalUserId); Map> parameter = new HashMap<>(); parameter.put("page", new ArrayList() {{ add(String.valueOf(page)); @@ -132,7 +130,7 @@ public Response getCategoriesForProject(int projectId, int page, int perPage, St parameter.put("sort", sort); Response.ResponseBuilder responseBuilder = Response.ok(); - responseBuilder = responseBuilder.entity(gson.toJson(categoriesResult.getElements())); + responseBuilder = responseBuilder.entity(categoriesResult.toJSON()); responseBuilder = bazaarService.paginationLinks(responseBuilder, categoriesResult, "projects/" + String.valueOf(projectId) + "/categories", parameter); responseBuilder = bazaarService.xHeaderFields(responseBuilder, categoriesResult); Response response = responseBuilder.build(); @@ -186,7 +184,8 @@ public Response getCategory(@PathParam("categoryId") int categoryId) { dalFacade = bazaarService.getDBConnection(); Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); Category categoryToReturn = dalFacade.getCategoryById(categoryId, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_15, Context.getCurrent().getMainAgent(), "Get category " + categoryId); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_15, + categoryId, Activity.DataType.CATEGORY, internalUserId); if (dalFacade.isCategoryPublic(categoryId)) { boolean authorized = new AuthorizationManager().isAuthorized(internalUserId, PrivilegeEnum.Read_PUBLIC_CATEGORY, String.valueOf(categoryId), dalFacade); if (!authorized) { @@ -198,8 +197,7 @@ public Response getCategory(@PathParam("categoryId") int categoryId) { ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.AUTHORIZATION, Localization.getInstance().getResourceBundle().getString("error.authorization.category.read")); } } - Gson gson = new Gson(); - return Response.ok(gson.toJson(categoryToReturn)).build(); + return Response.ok(categoryToReturn.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -247,7 +245,6 @@ public Response createCategory(@ApiParam(value = "Category entity", required = t if (registrarErrors != null) { ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, registrarErrors); } - Gson gson = new Gson(); Vtor vtor = bazaarService.getValidators(); vtor.useProfiles("create"); vtor.validate(categoryToCreate); @@ -262,10 +259,9 @@ public Response createCategory(@ApiParam(value = "Category entity", required = t } categoryToCreate.setLeader(dalFacade.getUserById(internalUserId)); Category createdCategory = dalFacade.createCategory(categoryToCreate, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_16, Context.getCurrent().getMainAgent(), "Create category " + createdCategory.getId()); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, createdCategory.getCreationDate(), Activity.ActivityAction.CREATE, createdCategory.getId(), - Activity.DataType.CATEGORY, createdCategory.getProjectId(), Activity.DataType.PROJECT, internalUserId); - return Response.status(Response.Status.CREATED).entity(gson.toJson(createdCategory)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(createdCategory.getCreationDate(), Activity.ActivityAction.CREATE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_16, + createdCategory.getId(), Activity.DataType.CATEGORY, internalUserId); + return Response.status(Response.Status.CREATED).entity(createdCategory.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -313,7 +309,6 @@ public Response updateCategory(@PathParam("categoryId") int categoryId, } UserAgent agent = (UserAgent) Context.getCurrent().getMainAgent(); long userId = agent.getId(); - Gson gson = new Gson(); Vtor vtor = bazaarService.getValidators(); vtor.validate(categoryToUpdate); if (vtor.hasViolations()) { @@ -329,10 +324,9 @@ public Response updateCategory(@PathParam("categoryId") int categoryId, ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, "Id does not match"); } Category updatedCategory = dalFacade.modifyCategory(categoryToUpdate); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_17, Context.getCurrent().getMainAgent(), "Update category " + categoryId); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, updatedCategory.getLastUpdatedDate(), Activity.ActivityAction.UPDATE, updatedCategory.getId(), - Activity.DataType.CATEGORY, updatedCategory.getProjectId(), Activity.DataType.PROJECT, internalUserId); - return Response.ok(gson.toJson(updatedCategory)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(updatedCategory.getLastUpdatedDate(), Activity.ActivityAction.UPDATE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_17, + updatedCategory.getId(), Activity.DataType.CATEGORY, internalUserId); + return Response.ok(updatedCategory.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -381,7 +375,6 @@ public Response deleteCategory(@PathParam("categoryId") int categoryId) { dalFacade = bazaarService.getDBConnection(); Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); Category categoryToDelete = dalFacade.getCategoryById(categoryId, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_18, Context.getCurrent().getMainAgent(), "Delete category " + categoryId); Project project = dalFacade.getProjectById(categoryToDelete.getProjectId(), internalUserId); boolean authorized = new AuthorizationManager().isAuthorized(internalUserId, PrivilegeEnum.Modify_CATEGORY, String.valueOf(project.getId()), dalFacade); if (!authorized) { @@ -395,11 +388,10 @@ public Response deleteCategory(@PathParam("categoryId") int categoryId) { MessageFormat.format(Localization.getInstance().getResourceBundle().getString("error.authorization.category.delete"), categoryId) ); } - Gson gson = new Gson(); Category deletedCategory = dalFacade.deleteCategoryById(categoryId, internalUserId); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, deletedCategory.getLastUpdatedDate(), Activity.ActivityAction.DELETE, deletedCategory.getId(), - Activity.DataType.CATEGORY, deletedCategory.getProjectId(), Activity.DataType.PROJECT, internalUserId); - return Response.ok(gson.toJson(deletedCategory)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(deletedCategory.getLastUpdatedDate(), Activity.ActivityAction.DELETE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_18, + deletedCategory.getId(), Activity.DataType.CATEGORY, internalUserId); + return Response.ok(deletedCategory.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -452,12 +444,10 @@ public Response followCategory(@PathParam("categoryId") int categoryId) { ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.AUTHORIZATION, Localization.getInstance().getResourceBundle().getString("error.authorization.follow.create")); } dalFacade.followCategory(internalUserId, categoryId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_19, Context.getCurrent().getMainAgent(), "Follow category " + categoryId); Category category = dalFacade.getCategoryById(categoryId, internalUserId); - Gson gson = new Gson(); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, new Date(), Activity.ActivityAction.FOLLOW, category.getId(), - Activity.DataType.CATEGORY, category.getProjectId(), Activity.DataType.PROJECT, internalUserId); - return Response.status(Response.Status.CREATED).entity(gson.toJson(category)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.FOLLOW, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_19, + category.getId(), Activity.DataType.CATEGORY, internalUserId); + return Response.status(Response.Status.CREATED).entity(category.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -510,12 +500,10 @@ public Response unfollowCategory(@PathParam("categoryId") int categoryId) { ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.AUTHORIZATION, Localization.getInstance().getResourceBundle().getString("error.authorization.follow.delete")); } dalFacade.unFollowCategory(internalUserId, categoryId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_20, Context.getCurrent().getMainAgent(), "Unfollow category " + categoryId); Category category = dalFacade.getCategoryById(categoryId, internalUserId); - Gson gson = new Gson(); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, new Date(), Activity.ActivityAction.UNFOLLOW, category.getId(), - Activity.DataType.CATEGORY, category.getProjectId(), Activity.DataType.PROJECT, internalUserId); - return Response.ok(gson.toJson(category)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.UNFOLLOW, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_20, + category.getId(), Activity.DataType.CATEGORY, internalUserId); + return Response.ok(category.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -558,15 +546,20 @@ public Response getStatisticsForCategory( @ApiParam(value = "Since timestamp", required = false) @QueryParam("since") String since) { DALFacade dalFacade = null; try { + String registrarErrors = bazaarService.notifyRegistrars(EnumSet.of(BazaarFunction.VALIDATION, BazaarFunction.USER_FIRST_LOGIN_HANDLING)); + if (registrarErrors != null) { + ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, registrarErrors); + } UserAgent agent = (UserAgent) Context.getCurrent().getMainAgent(); long userId = agent.getId(); + Calendar sinceCal = since == null ? null : DatatypeConverter.parseDateTime(since); dalFacade = bazaarService.getDBConnection(); Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); - Calendar sinceCal = since == null ? null : DatatypeConverter.parseDateTime(since); - Statistic statisticsResult = dalFacade.getStatisticsForCategory(internalUserId, categoryId, sinceCal); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_21, Context.getCurrent().getMainAgent(), "Get statistics for category " + categoryId); - Gson gson = new Gson(); - return Response.ok(gson.toJson(statisticsResult)).build(); + Category category = dalFacade.getCategoryById(categoryId, internalUserId); + Statistic categoryStatistics = dalFacade.getStatisticsForCategory(internalUserId, categoryId, sinceCal); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE_CHILD, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_21, + categoryId, Activity.DataType.CATEGORY, internalUserId); + return Response.ok(categoryStatistics.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -587,6 +580,58 @@ public Response getStatisticsForCategory( } } + /** + * This method returns the list of contributors for a specific category. + * + * @param categoryId id of the category + * @return Response with category contributors + */ + @GET + @Path("/{categoryId}/contributors") + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "This method returns the list of contributors for a specific category.") + @ApiResponses(value = { + @ApiResponse(code = HttpURLConnection.HTTP_OK, message = "Returns a list of contributors for a given category", response = CategoryContributors.class), + @ApiResponse(code = HttpURLConnection.HTTP_UNAUTHORIZED, message = "Unauthorized"), + @ApiResponse(code = HttpURLConnection.HTTP_NOT_FOUND, message = "Not found"), + @ApiResponse(code = HttpURLConnection.HTTP_INTERNAL_ERROR, message = "Internal server problems") + }) + public Response getContributorsForCategory(@PathParam("categoryId") int categoryId) throws Exception { + DALFacade dalFacade = null; + try { + UserAgent agent = (UserAgent) Context.getCurrent().getMainAgent(); + long userId = agent.getId(); + String registrarErrors = bazaarService.notifyRegistrars(EnumSet.of(BazaarFunction.VALIDATION, BazaarFunction.USER_FIRST_LOGIN_HANDLING)); + if (registrarErrors != null) { + ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, registrarErrors); + } + dalFacade = bazaarService.getDBConnection(); + Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); + Category category = dalFacade.getCategoryById(categoryId, internalUserId); + CategoryContributors categoryContributors = dalFacade.listContributorsForCategory(categoryId); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE_CHILD, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_22, + categoryId, Activity.DataType.CATEGORY, internalUserId); + return Response.ok(categoryContributors.toJSON()).build(); + } catch (BazaarException bex) { + if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { + return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); + } else if (bex.getErrorCode() == ErrorCode.NOT_FOUND) { + return Response.status(Response.Status.NOT_FOUND).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); + } else { + logger.warning(bex.getMessage()); + L2pLogger.logEvent(NodeObserver.Event.SERVICE_ERROR, Context.getCurrent().getMainAgent(), "Get contributors for category " + categoryId); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); + } + } catch (Exception ex) { + BazaarException bex = ExceptionHandler.getInstance().convert(ex, ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, ex.getMessage()); + logger.warning(bex.getMessage()); + L2pLogger.logEvent(NodeObserver.Event.SERVICE_ERROR, Context.getCurrent().getMainAgent(), "Get contributors for category " + categoryId); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); + } finally { + bazaarService.closeDBConnection(dalFacade); + } + } + /** * This method returns the list of followers for a specific category. * @@ -623,9 +668,11 @@ public Response getFollowersForCategory(@PathParam("categoryId") int categoryId, ExceptionHandler.getInstance().handleViolations(vtor.getViolations()); } dalFacade = bazaarService.getDBConnection(); - PaginationResult requirementsResult = dalFacade.listFollowersForCategory(categoryId, pageInfo); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_23, Context.getCurrent().getMainAgent(), "Get followers for category " + categoryId); - + Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); + Category category = dalFacade.getCategoryById(categoryId, internalUserId); + PaginationResult categoryFollowers = dalFacade.listFollowersForCategory(categoryId, pageInfo); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE_CHILD, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_23, + categoryId, Activity.DataType.CATEGORY, internalUserId); Map> parameter = new HashMap<>(); parameter.put("page", new ArrayList() {{ add(String.valueOf(page)); @@ -634,11 +681,10 @@ public Response getFollowersForCategory(@PathParam("categoryId") int categoryId, add(String.valueOf(perPage)); }}); - Gson gson = new Gson(); Response.ResponseBuilder responseBuilder = Response.ok(); - responseBuilder = responseBuilder.entity(gson.toJson(requirementsResult.getElements())); - responseBuilder = bazaarService.paginationLinks(responseBuilder, requirementsResult, "categories/" + String.valueOf(categoryId) + "/followers", parameter); - responseBuilder = bazaarService.xHeaderFields(responseBuilder, requirementsResult); + responseBuilder = responseBuilder.entity(categoryFollowers.toJSON()); + responseBuilder = bazaarService.paginationLinks(responseBuilder, categoryFollowers, "categories/" + String.valueOf(categoryId) + "/followers", parameter); + responseBuilder = bazaarService.xHeaderFields(responseBuilder, categoryFollowers); Response response = responseBuilder.build(); return response; diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/CommentsResource.java b/src/main/de/rwth/dbis/acis/bazaar/service/CommentsResource.java index e0ebe840..c8626188 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/CommentsResource.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/CommentsResource.java @@ -1,6 +1,5 @@ package de.rwth.dbis.acis.bazaar.service; -import com.google.gson.Gson; import de.rwth.dbis.acis.bazaar.service.dal.DALFacade; import de.rwth.dbis.acis.bazaar.service.dal.entities.*; import de.rwth.dbis.acis.bazaar.service.dal.helpers.PageInfo; @@ -93,8 +92,8 @@ public Response getCommentsForRequirement(int requirementId, int page, int perPa } } PaginationResult commentsResult = dalFacade.listCommentsByRequirementId(requirementId, pageInfo); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_43, Context.getCurrent().getMainAgent(), "Get comments for requirement " + requirementId); - + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE_CHILD, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_43, + requirementId, Activity.DataType.REQUIREMENT, internalUserId); Map> parameter = new HashMap<>(); parameter.put("page", new ArrayList() {{ add(String.valueOf(page)); @@ -103,9 +102,8 @@ public Response getCommentsForRequirement(int requirementId, int page, int perPa add(String.valueOf(perPage)); }}); - Gson gson = new Gson(); Response.ResponseBuilder responseBuilder = Response.ok(); - responseBuilder = responseBuilder.entity(gson.toJson(commentsResult.getElements())); + responseBuilder = responseBuilder.entity(commentsResult.toJSON()); responseBuilder = bazaarService.paginationLinks(responseBuilder, commentsResult, "requirements/" + String.valueOf(requirementId) + "/comments", parameter); responseBuilder = bazaarService.xHeaderFields(responseBuilder, commentsResult); Response response = responseBuilder.build(); @@ -160,7 +158,8 @@ public Response getComment(@PathParam("commentId") int commentId) { Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); Comment comment = dalFacade.getCommentById(commentId); Requirement requirement = dalFacade.getRequirementById(comment.getRequirementId(), internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_45, Context.getCurrent().getMainAgent(), "Get comment " + commentId); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_45, + commentId, Activity.DataType.COMMENT, internalUserId); if (dalFacade.isProjectPublic(requirement.getProjectId())) { boolean authorized = new AuthorizationManager().isAuthorized(internalUserId, PrivilegeEnum.Read_PUBLIC_COMMENT, String.valueOf(requirement.getProjectId()), dalFacade); if (!authorized) { @@ -172,8 +171,7 @@ public Response getComment(@PathParam("commentId") int commentId) { ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.AUTHORIZATION, Localization.getInstance().getResourceBundle().getString("error.authorization.comment.read")); } } - Gson gson = new Gson(); - return Response.ok(gson.toJson(comment)).build(); + return Response.ok(comment.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -222,7 +220,6 @@ public Response createComment(@ApiParam(value = "Comment entity", required = tru if (registrarErrors != null) { ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, registrarErrors); } - Gson gson = new Gson(); dalFacade = bazaarService.getDBConnection(); Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); Requirement requirement = dalFacade.getRequirementById(commentToCreate.getRequirementId(), internalUserId); @@ -239,10 +236,9 @@ public Response createComment(@ApiParam(value = "Comment entity", required = tru } dalFacade.followRequirement(internalUserId, requirement.getId()); Comment createdComment = dalFacade.createComment(commentToCreate); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_46, Context.getCurrent().getMainAgent(), "Create comment " + commentToCreate.getId()); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, createdComment.getCreationDate(), Activity.ActivityAction.CREATE, createdComment.getId(), - Activity.DataType.COMMENT, createdComment.getRequirementId(), Activity.DataType.REQUIREMENT, internalUserId); - return Response.status(Response.Status.CREATED).entity(gson.toJson(createdComment)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(createdComment.getCreationDate(), Activity.ActivityAction.CREATE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_46, + createdComment.getId(), Activity.DataType.COMMENT, internalUserId); + return Response.status(Response.Status.CREATED).entity(createdComment.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -295,12 +291,10 @@ public Response deleteComment(@PathParam("commentId") int commentId) { if (!authorized) { ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.AUTHORIZATION, Localization.getInstance().getResourceBundle().getString("error.authorization.comment.modify")); } - Gson gson = new Gson(); Comment deletedComment = dalFacade.deleteCommentById(commentId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_48, Context.getCurrent().getMainAgent(), "Delete comment " + commentId); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, deletedComment.getCreationDate(), Activity.ActivityAction.DELETE, deletedComment.getId(), - Activity.DataType.COMMENT, commentToDelete.getRequirementId(), Activity.DataType.REQUIREMENT, internalUserId); - return Response.ok(gson.toJson(deletedComment)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(deletedComment.getCreationDate(), Activity.ActivityAction.DELETE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_48, + deletedComment.getId(), Activity.DataType.COMMENT, internalUserId); + return Response.ok(deletedComment.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/ProjectsResource.java b/src/main/de/rwth/dbis/acis/bazaar/service/ProjectsResource.java index 4649ff9c..508a7f63 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/ProjectsResource.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/ProjectsResource.java @@ -1,6 +1,5 @@ package de.rwth.dbis.acis.bazaar.service; -import com.google.gson.Gson; import de.rwth.dbis.acis.bazaar.service.dal.DALFacade; import de.rwth.dbis.acis.bazaar.service.dal.entities.*; import de.rwth.dbis.acis.bazaar.service.dal.helpers.PageInfo; @@ -88,7 +87,6 @@ public Response getProjects( } UserAgent agent = (UserAgent) Context.getCurrent().getMainAgent(); long userId = agent.getId(); - Gson gson = new Gson(); List sortList = new ArrayList<>(); for (String sortOption : sort) { Pageable.SortDirection direction = Pageable.SortDirection.DEFAULT; @@ -110,16 +108,17 @@ public Response getProjects( ExceptionHandler.getInstance().handleViolations(vtor.getViolations()); } dalFacade = bazaarService.getDBConnection(); + Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); PaginationResult projectsResult; if (agent.getLoginName().equals("anonymous")) { // return only public projects projectsResult = dalFacade.listPublicProjects(pageInfo, 0); } else { // return public projects and the ones the user belongs to - Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); projectsResult = dalFacade.listPublicAndAuthorizedProjects(pageInfo, internalUserId); } - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_3, Context.getCurrent().getMainAgent(), "Get projects"); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_3, + 0, Activity.DataType.PROJECT, internalUserId); Map> parameter = new HashMap<>(); parameter.put("page", new ArrayList() {{ @@ -136,7 +135,7 @@ public Response getProjects( parameter.put("sort", sort); Response.ResponseBuilder responseBuilder = Response.ok(); - responseBuilder = responseBuilder.entity(gson.toJson(projectsResult.getElements())); + responseBuilder = responseBuilder.entity(projectsResult.toJSON()); responseBuilder = bazaarService.paginationLinks(responseBuilder, projectsResult, "projects", parameter); responseBuilder = bazaarService.xHeaderFields(responseBuilder, projectsResult); Response response = responseBuilder.build(); @@ -195,9 +194,9 @@ public Response getProject(@PathParam("projectId") int projectId) { } } Project projectToReturn = dalFacade.getProjectById(projectId, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_4, Context.getCurrent().getMainAgent(), "Get project " + projectId); - Gson gson = new Gson(); - return Response.ok(gson.toJson(projectToReturn)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_4, + projectId, Activity.DataType.PROJECT, internalUserId); + return Response.ok(projectToReturn.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -243,7 +242,6 @@ public Response createProject(@ApiParam(value = "Project entity", required = tru } UserAgent agent = (UserAgent) Context.getCurrent().getMainAgent(); long userId = agent.getId(); - Gson gson = new Gson(); Vtor vtor = bazaarService.getValidators(); vtor.useProfiles("create"); vtor.validate(projectToCreate); @@ -256,10 +254,9 @@ public Response createProject(@ApiParam(value = "Project entity", required = tru } projectToCreate.setLeader(dalFacade.getUserById(internalUserId)); Project createdProject = dalFacade.createProject(projectToCreate, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_5, Context.getCurrent().getMainAgent(), "Create project " + createdProject.getId()); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, createdProject.getCreationDate(), Activity.ActivityAction.CREATE, createdProject.getId(), - Activity.DataType.PROJECT, 0, null, internalUserId); - return Response.status(Response.Status.CREATED).entity(gson.toJson(createdProject)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.CREATE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_5, + createdProject.getId(), Activity.DataType.PROJECT, internalUserId); + return Response.status(Response.Status.CREATED).entity(createdProject.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -306,7 +303,6 @@ public Response updateProject(@PathParam("projectId") int projectId, } UserAgent agent = (UserAgent) Context.getCurrent().getMainAgent(); long userId = agent.getId(); - Gson gson = new Gson(); Vtor vtor = bazaarService.getValidators(); vtor.validate(projectToUpdate); if (vtor.hasViolations()) { @@ -322,10 +318,9 @@ public Response updateProject(@PathParam("projectId") int projectId, ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, "Id does not match"); } Project updatedProject = dalFacade.modifyProject(projectToUpdate); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_6, Context.getCurrent().getMainAgent(), "Update project " + projectId); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, updatedProject.getLastUpdatedDate(), Activity.ActivityAction.UPDATE, updatedProject.getId(), - Activity.DataType.PROJECT, 0, null, internalUserId); - return Response.ok(gson.toJson(updatedProject)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.UPDATE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_6, + updatedProject.getId(), Activity.DataType.PROJECT, internalUserId); + return Response.ok(updatedProject.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -378,12 +373,10 @@ public Response followProject(@PathParam("projectId") int projectId) { ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.AUTHORIZATION, Localization.getInstance().getResourceBundle().getString("error.authorization.follow.create")); } dalFacade.followProject(internalUserId, projectId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_8, Context.getCurrent().getMainAgent(), "Follow project " + projectId); Project project = dalFacade.getProjectById(projectId, internalUserId); - Gson gson = new Gson(); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, new Date(), Activity.ActivityAction.FOLLOW, project.getId(), - Activity.DataType.PROJECT, 0, null, internalUserId); - return Response.status(Response.Status.CREATED).entity(gson.toJson(project)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.FOLLOW, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_8, + projectId, Activity.DataType.PROJECT, internalUserId); + return Response.status(Response.Status.CREATED).entity(project.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -437,11 +430,9 @@ public Response unfollowProject(@PathParam("projectId") int projectId) { } dalFacade.unFollowProject(internalUserId, projectId); Project project = dalFacade.getProjectById(projectId, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_9, Context.getCurrent().getMainAgent(), "Unfollow project " + projectId); - Gson gson = new Gson(); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, new Date(), Activity.ActivityAction.UNFOLLOW, project.getId(), - Activity.DataType.PROJECT, 0, null, internalUserId); - return Response.ok(gson.toJson(project)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.UNFOLLOW, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_9, + projectId, Activity.DataType.PROJECT, internalUserId); + return Response.ok(project.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -484,15 +475,19 @@ public Response getStatisticsForProject( @ApiParam(value = "Since timestamp", required = false) @QueryParam("since") String since) { DALFacade dalFacade = null; try { + String registrarErrors = bazaarService.notifyRegistrars(EnumSet.of(BazaarFunction.VALIDATION, BazaarFunction.USER_FIRST_LOGIN_HANDLING)); + if (registrarErrors != null) { + ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, registrarErrors); + } UserAgent agent = (UserAgent) Context.getCurrent().getMainAgent(); long userId = agent.getId(); dalFacade = bazaarService.getDBConnection(); Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); Calendar sinceCal = since == null ? null : DatatypeConverter.parseDateTime(since); - Statistic statisticsResult = dalFacade.getStatisticsForProject(internalUserId, projectId, sinceCal); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_10, Context.getCurrent().getMainAgent(), "Get statistics for project " + projectId); - Gson gson = new Gson(); - return Response.ok(gson.toJson(statisticsResult)).build(); + Statistic projectStatistics = dalFacade.getStatisticsForProject(internalUserId, projectId, sinceCal); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE_CHILD, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_10, + projectId, Activity.DataType.PROJECT, internalUserId); + return Response.ok(projectStatistics.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -513,6 +508,57 @@ public Response getStatisticsForProject( } } + /** + * This method returns the list of contributors for a specific project. + * + * @param projectId id of the project + * @return Response with project contributors + */ + @GET + @Path("/{projectId}/contributors") + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "This method returns the list of contributors for a specific project.") + @ApiResponses(value = { + @ApiResponse(code = HttpURLConnection.HTTP_OK, message = "Returns a list of contributors for a given project", response = ProjectContributors.class), + @ApiResponse(code = HttpURLConnection.HTTP_UNAUTHORIZED, message = "Unauthorized"), + @ApiResponse(code = HttpURLConnection.HTTP_NOT_FOUND, message = "Not found"), + @ApiResponse(code = HttpURLConnection.HTTP_INTERNAL_ERROR, message = "Internal server problems") + }) + public Response getContributorsForProject(@PathParam("projectId") int projectId) throws Exception { + DALFacade dalFacade = null; + try { + UserAgent agent = (UserAgent) Context.getCurrent().getMainAgent(); + long userId = agent.getId(); + String registrarErrors = bazaarService.notifyRegistrars(EnumSet.of(BazaarFunction.VALIDATION, BazaarFunction.USER_FIRST_LOGIN_HANDLING)); + if (registrarErrors != null) { + ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, registrarErrors); + } + dalFacade = bazaarService.getDBConnection(); + Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); + ProjectContributors projectContributors = dalFacade.listContributorsForProject(projectId); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE_CHILD, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_11, + projectId, Activity.DataType.PROJECT, internalUserId); + return Response.ok(projectContributors.toJSON()).build(); + } catch (BazaarException bex) { + if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { + return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); + } else if (bex.getErrorCode() == ErrorCode.NOT_FOUND) { + return Response.status(Response.Status.NOT_FOUND).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); + } else { + logger.warning(bex.getMessage()); + L2pLogger.logEvent(NodeObserver.Event.SERVICE_ERROR, Context.getCurrent().getMainAgent(), "Get contributors for project " + projectId); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); + } + } catch (Exception ex) { + BazaarException bex = ExceptionHandler.getInstance().convert(ex, ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, ex.getMessage()); + logger.warning(bex.getMessage()); + L2pLogger.logEvent(NodeObserver.Event.SERVICE_ERROR, Context.getCurrent().getMainAgent(), "Get contributors for project " + projectId); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); + } finally { + bazaarService.closeDBConnection(dalFacade); + } + } + /** * This method returns the list of followers for a specific project. * @@ -549,8 +595,10 @@ public Response getFollowersForProject(@PathParam("projectId") int projectId, ExceptionHandler.getInstance().handleViolations(vtor.getViolations()); } dalFacade = bazaarService.getDBConnection(); - PaginationResult requirementsResult = dalFacade.listFollowersForProject(projectId, pageInfo); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_12, Context.getCurrent().getMainAgent(), "Get followers for project " + projectId); + Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); + PaginationResult projectFollowers = dalFacade.listFollowersForProject(projectId, pageInfo); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE_CHILD, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_12, + projectId, Activity.DataType.PROJECT, internalUserId); Map> parameter = new HashMap<>(); parameter.put("page", new ArrayList() {{ @@ -560,11 +608,10 @@ public Response getFollowersForProject(@PathParam("projectId") int projectId, add(String.valueOf(perPage)); }}); - Gson gson = new Gson(); Response.ResponseBuilder responseBuilder = Response.ok(); - responseBuilder = responseBuilder.entity(gson.toJson(requirementsResult.getElements())); - responseBuilder = bazaarService.paginationLinks(responseBuilder, requirementsResult, "projects/" + String.valueOf(projectId) + "/followers", parameter); - responseBuilder = bazaarService.xHeaderFields(responseBuilder, requirementsResult); + responseBuilder = responseBuilder.entity(projectFollowers.toJSON()); + responseBuilder = bazaarService.paginationLinks(responseBuilder, projectFollowers, "projects/" + String.valueOf(projectId) + "/followers", parameter); + responseBuilder = bazaarService.xHeaderFields(responseBuilder, projectFollowers); Response response = responseBuilder.build(); return response; diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/RequirementsResource.java b/src/main/de/rwth/dbis/acis/bazaar/service/RequirementsResource.java index 2b07448f..804dec33 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/RequirementsResource.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/RequirementsResource.java @@ -1,6 +1,5 @@ package de.rwth.dbis.acis.bazaar.service; -import com.google.gson.Gson; import de.rwth.dbis.acis.bazaar.service.dal.DALFacade; import de.rwth.dbis.acis.bazaar.service.dal.entities.*; import de.rwth.dbis.acis.bazaar.service.dal.helpers.PageInfo; @@ -27,7 +26,6 @@ import java.net.HttpURLConnection; import java.util.*; - @Api(value = "requirements", description = "Requirements resource") @SwaggerDefinition( info = @Info( @@ -78,7 +76,6 @@ public Response getRequirementsForProject(int projectId, int page, int perPage, if (registrarErrors != null) { ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, registrarErrors); } - Gson gson = new Gson(); HashMap filters = new HashMap<>(); if (stateFilter != "all") { filters.put("realized", stateFilter); @@ -120,7 +117,8 @@ public Response getRequirementsForProject(int projectId, int page, int perPage, } } PaginationResult requirementsResult = dalFacade.listRequirementsByProject(projectId, pageInfo, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_14, Context.getCurrent().getMainAgent(), "Get requirements for project " + projectId); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE_CHILD, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_14, + projectId, Activity.DataType.PROJECT, internalUserId); Map> parameter = new HashMap<>(); parameter.put("page", new ArrayList() {{ @@ -140,7 +138,7 @@ public Response getRequirementsForProject(int projectId, int page, int perPage, parameter.put("sort", sort); Response.ResponseBuilder responseBuilder = Response.ok(); - responseBuilder = responseBuilder.entity(gson.toJson(requirementsResult.getElements())); + responseBuilder = responseBuilder.entity(requirementsResult.toJSON()); responseBuilder = bazaarService.paginationLinks(responseBuilder, requirementsResult, "projects/" + String.valueOf(projectId) + "/requirements", parameter); responseBuilder = bazaarService.xHeaderFields(responseBuilder, requirementsResult); Response response = responseBuilder.build(); @@ -186,7 +184,6 @@ public Response getRequirementsForCategory(int categoryId, int page, int perPage if (registrarErrors != null) { ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, registrarErrors); } - Gson gson = new Gson(); HashMap filters = new HashMap<>(); if (stateFilter != "all") { filters.put("realized", stateFilter); @@ -230,7 +227,8 @@ public Response getRequirementsForCategory(int categoryId, int page, int perPage } } PaginationResult requirementsResult = dalFacade.listRequirementsByCategory(categoryId, pageInfo, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_24, Context.getCurrent().getMainAgent(), "Get requirements for category " + categoryId); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE_CHILD, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_24, + categoryId, Activity.DataType.CATEGORY, internalUserId); Map> parameter = new HashMap<>(); parameter.put("page", new ArrayList() {{ @@ -250,7 +248,7 @@ public Response getRequirementsForCategory(int categoryId, int page, int perPage parameter.put("sort", sort); Response.ResponseBuilder responseBuilder = Response.ok(); - responseBuilder = responseBuilder.entity(gson.toJson(requirementsResult.getElements())); + responseBuilder = responseBuilder.entity(requirementsResult.toJSON()); responseBuilder = bazaarService.paginationLinks(responseBuilder, requirementsResult, "categories/" + String.valueOf(categoryId) + "/requirements", parameter); responseBuilder = bazaarService.xHeaderFields(responseBuilder, requirementsResult); Response response = responseBuilder.build(); @@ -304,7 +302,8 @@ public Response getRequirement(@PathParam("requirementId") int requirementId) { dalFacade = bazaarService.getDBConnection(); Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); Requirement requirement = dalFacade.getRequirementById(requirementId, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_25, Context.getCurrent().getMainAgent(), "Get requirement " + requirementId); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_25, + requirementId, Activity.DataType.REQUIREMENT, internalUserId); if (dalFacade.isRequirementPublic(requirementId)) { boolean authorized = new AuthorizationManager().isAuthorized(internalUserId, PrivilegeEnum.Read_PUBLIC_REQUIREMENT, String.valueOf(requirement.getProjectId()), dalFacade); if (!authorized) { @@ -316,8 +315,7 @@ public Response getRequirement(@PathParam("requirementId") int requirementId) { ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.AUTHORIZATION, Localization.getInstance().getResourceBundle().getString("error.authorization.category.read")); } } - Gson gson = new Gson(); - return Response.ok(gson.toJson(requirement)).build(); + return Response.ok(requirement.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -365,7 +363,7 @@ public Response createRequirement(@ApiParam(value = "Requirement entity", requir } // TODO: check whether the current user may create a new requirement dalFacade = bazaarService.getDBConnection(); - Gson gson = new Gson(); + Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); requirementToCreate.setCreator(dalFacade.getUserById(internalUserId)); Vtor vtor = bazaarService.getValidators(); @@ -388,7 +386,6 @@ public Response createRequirement(@ApiParam(value = "Requirement entity", requir ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.AUTHORIZATION, Localization.getInstance().getResourceBundle().getString("error.authorization.requirement.create")); } Requirement createdRequirement = dalFacade.createRequirement(requirementToCreate, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_26, Context.getCurrent().getMainAgent(), "Create requirement " + createdRequirement.getId()); // check if attachments are given if (requirementToCreate.getAttachments() != null && !requirementToCreate.getAttachments().isEmpty()) { @@ -403,11 +400,10 @@ public Response createRequirement(@ApiParam(value = "Requirement entity", requir dalFacade.createAttachment(attachment); } } - createdRequirement = dalFacade.getRequirementById(createdRequirement.getId(), internalUserId); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, createdRequirement.getCreationDate(), Activity.ActivityAction.CREATE, createdRequirement.getId(), - Activity.DataType.REQUIREMENT, createdRequirement.getCategories().get(0).getId(), Activity.DataType.CATEGORY, internalUserId); - return Response.status(Response.Status.CREATED).entity(gson.toJson(createdRequirement)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.CREATE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_26, + createdRequirement.getId(), Activity.DataType.REQUIREMENT, internalUserId); + return Response.status(Response.Status.CREATED).entity(createdRequirement.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -454,7 +450,6 @@ public Response updateRequirement(@PathParam("requirementId") int requirementId, } UserAgent agent = (UserAgent) Context.getCurrent().getMainAgent(); long userId = agent.getId(); - Gson gson = new Gson(); Vtor vtor = bazaarService.getValidators(); vtor.validate(requirementToUpdate); if (vtor.hasViolations()) { @@ -471,10 +466,9 @@ public Response updateRequirement(@PathParam("requirementId") int requirementId, } dalFacade.followRequirement(internalUserId, requirementToUpdate.getId()); Requirement updatedRequirement = dalFacade.modifyRequirement(requirementToUpdate, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_27, Context.getCurrent().getMainAgent(), "Update requirement " + requirementId); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, updatedRequirement.getLastUpdatedDate(), Activity.ActivityAction.UPDATE, updatedRequirement.getId(), - Activity.DataType.REQUIREMENT, updatedRequirement.getCategories().get(0).getId(), Activity.DataType.CATEGORY, internalUserId); - return Response.ok(gson.toJson(updatedRequirement)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.UPDATE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_27, + requirementId, Activity.DataType.REQUIREMENT, internalUserId); + return Response.ok(updatedRequirement.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -528,12 +522,10 @@ public Response deleteRequirement(@PathParam("requirementId") int requirementId) if (!authorized) { ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.AUTHORIZATION, Localization.getInstance().getResourceBundle().getString("error.authorization.requirement.delete")); } - Gson gson = new Gson(); Requirement deletedRequirement = dalFacade.deleteRequirementById(requirementId, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_28, Context.getCurrent().getMainAgent(), "Delete requirement " + requirementId); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, deletedRequirement.getLastUpdatedDate(), Activity.ActivityAction.DELETE, deletedRequirement.getId(), - Activity.DataType.REQUIREMENT, deletedRequirement.getCategories().get(0).getId(), Activity.DataType.CATEGORY, internalUserId); - return Response.ok(gson.toJson(deletedRequirement)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.DELETE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_28, + requirementId, Activity.DataType.REQUIREMENT, internalUserId); + return Response.ok(deletedRequirement.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -586,11 +578,9 @@ public Response leaddevelopRequirement(@PathParam("requirementId") int requireme ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.AUTHORIZATION, Localization.getInstance().getResourceBundle().getString("error.authorization.vote.create")); } Requirement requirement = dalFacade.setUserAsLeadDeveloper(requirementId, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_29, Context.getCurrent().getMainAgent(), "Leaddevelop requirement " + requirementId); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, new Date(), Activity.ActivityAction.LEADDEVELOP, requirement.getId(), - Activity.DataType.REQUIREMENT, requirement.getCategories().get(0).getId(), Activity.DataType.CATEGORY, internalUserId); - Gson gson = new Gson(); - return Response.status(Response.Status.CREATED).entity(gson.toJson(requirement)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.LEADDEVELOP, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_29, + requirementId, Activity.DataType.REQUIREMENT, internalUserId); + return Response.status(Response.Status.CREATED).entity(requirement.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -647,11 +637,9 @@ public Response unleaddevelopRequirement(@PathParam("requirementId") int require ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.AUTHORIZATION, "You are not lead developer."); } requirement = dalFacade.deleteUserAsLeadDeveloper(requirementId, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_30, Context.getCurrent().getMainAgent(), "Unleaddevelop requirement " + requirementId); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, new Date(), Activity.ActivityAction.UNLEADDEVELOP, requirement.getId(), - Activity.DataType.REQUIREMENT, requirement.getCategories().get(0).getId(), Activity.DataType.CATEGORY, internalUserId); - Gson gson = new Gson(); - return Response.ok(gson.toJson(requirement)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.UNLEADDEVELOP, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_30, + requirementId, Activity.DataType.REQUIREMENT, internalUserId); + return Response.ok(requirement.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -706,11 +694,9 @@ public Response developRequirement(@PathParam("requirementId") int requirementId dalFacade.wantToDevelop(internalUserId, requirementId); dalFacade.followRequirement(internalUserId, requirementId); Requirement requirement = dalFacade.getRequirementById(requirementId, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_31, Context.getCurrent().getMainAgent(), "Develop requirement " + requirementId); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, new Date(), Activity.ActivityAction.DEVELOP, requirement.getId(), - Activity.DataType.REQUIREMENT, requirement.getCategories().get(0).getId(), Activity.DataType.CATEGORY, internalUserId); - Gson gson = new Gson(); - return Response.status(Response.Status.CREATED).entity(gson.toJson(requirement)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.DEVELOP, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_31, + requirementId, Activity.DataType.REQUIREMENT, internalUserId); + return Response.status(Response.Status.CREATED).entity(requirement.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -764,11 +750,9 @@ public Response undevelopRequirement(@PathParam("requirementId") int requirement } dalFacade.notWantToDevelop(internalUserId, requirementId); Requirement requirement = dalFacade.getRequirementById(requirementId, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_32, Context.getCurrent().getMainAgent(), "Undevelop requirement " + requirementId); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, new Date(), Activity.ActivityAction.UNDEVELOP, requirement.getId(), - Activity.DataType.REQUIREMENT, requirement.getCategories().get(0).getId(), Activity.DataType.CATEGORY, internalUserId); - Gson gson = new Gson(); - return Response.ok(gson.toJson(requirement)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.UNDEVELOP, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_32, + requirementId, Activity.DataType.REQUIREMENT, internalUserId); + return Response.ok(requirement.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -822,11 +806,9 @@ public Response followRequirement(@PathParam("requirementId") int requirementId) } dalFacade.followRequirement(internalUserId, requirementId); Requirement requirement = dalFacade.getRequirementById(requirementId, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_33, Context.getCurrent().getMainAgent(), "Follow requirement " + requirementId); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, new Date(), Activity.ActivityAction.FOLLOW, requirement.getId(), - Activity.DataType.REQUIREMENT, requirement.getCategories().get(0).getId(), Activity.DataType.CATEGORY, internalUserId); - Gson gson = new Gson(); - return Response.status(Response.Status.CREATED).entity(gson.toJson(requirement)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.FOLLOW, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_33, + requirementId, Activity.DataType.REQUIREMENT, internalUserId); + return Response.status(Response.Status.CREATED).entity(requirement.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -880,11 +862,9 @@ public Response unfollowRequirement(@PathParam("requirementId") int requirementI } dalFacade.unFollowRequirement(internalUserId, requirementId); Requirement requirement = dalFacade.getRequirementById(requirementId, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_34, Context.getCurrent().getMainAgent(), "Unfollow requirement " + requirementId); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, new Date(), Activity.ActivityAction.UNFOLLOW, requirement.getId(), - Activity.DataType.REQUIREMENT, requirement.getCategories().get(0).getId(), Activity.DataType.CATEGORY, internalUserId); - Gson gson = new Gson(); - return Response.ok(gson.toJson(requirement)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.UNFOLLOW, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_34, + requirementId, Activity.DataType.REQUIREMENT, internalUserId); + return Response.ok(requirement.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -948,11 +928,9 @@ public Response vote(@PathParam("requirementId") int requirementId, dalFacade.followRequirement(internalUserId, requirementId); } Requirement requirement = dalFacade.getRequirementById(requirementId, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_35, Context.getCurrent().getMainAgent(), "Vote requirement " + requirementId); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, new Date(), Activity.ActivityAction.VOTE, requirement.getId(), - Activity.DataType.REQUIREMENT, requirement.getCategories().get(0).getId(), Activity.DataType.CATEGORY, internalUserId); - Gson gson = new Gson(); - return Response.status(Response.Status.CREATED).entity(gson.toJson(requirement)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.VOTE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_35, + requirementId, Activity.DataType.REQUIREMENT, internalUserId); + return Response.status(Response.Status.CREATED).entity(requirement.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -1006,11 +984,9 @@ public Response unvote(@PathParam("requirementId") int requirementId) { } dalFacade.unVote(internalUserId, requirementId); Requirement requirement = dalFacade.getRequirementById(requirementId, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_36, Context.getCurrent().getMainAgent(), "Unvote requirement " + requirementId); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, new Date(), Activity.ActivityAction.UNVOTE, requirement.getId(), - Activity.DataType.REQUIREMENT, requirement.getCategories().get(0).getId(), Activity.DataType.CATEGORY, internalUserId); - Gson gson = new Gson(); - return Response.ok(gson.toJson(requirement)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.UNVOTE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_36, + requirementId, Activity.DataType.REQUIREMENT, internalUserId); + return Response.ok(requirement.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -1063,11 +1039,9 @@ public Response realize(@PathParam("requirementId") int requirementId) { ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.AUTHORIZATION, Localization.getInstance().getResourceBundle().getString("error.authorization.vote.create")); } Requirement requirement = dalFacade.setRequirementToRealized(requirementId, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_37, Context.getCurrent().getMainAgent(), "Realize requirement " + requirementId); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, new Date(), Activity.ActivityAction.REALIZE, requirement.getId(), - Activity.DataType.REQUIREMENT, requirement.getCategories().get(0).getId(), Activity.DataType.CATEGORY, internalUserId); - Gson gson = new Gson(); - return Response.status(Response.Status.CREATED).entity(gson.toJson(requirement)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.REALIZE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_37, + requirementId, Activity.DataType.REQUIREMENT, internalUserId); + return Response.status(Response.Status.CREATED).entity(requirement.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -1120,11 +1094,9 @@ public Response unrealize(@PathParam("requirementId") int requirementId) { ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.AUTHORIZATION, Localization.getInstance().getResourceBundle().getString("error.authorization.vote.delete")); } Requirement requirement = dalFacade.setRequirementToUnRealized(requirementId, internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_38, Context.getCurrent().getMainAgent(), "Unrealize requirement " + requirementId); - bazaarService.getNotificationDispatcher().dispatchNotification(bazaarService, new Date(), Activity.ActivityAction.UNREALIZE, requirement.getId(), - Activity.DataType.REQUIREMENT, requirement.getCategories().get(0).getId(), Activity.DataType.CATEGORY, internalUserId); - Gson gson = new Gson(); - return Response.ok(gson.toJson(requirement)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.UNREALIZE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_38, + requirementId, Activity.DataType.REQUIREMENT, internalUserId); + return Response.ok(requirement.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -1167,15 +1139,19 @@ public Response getStatisticsForRequirement( @ApiParam(value = "Since timestamp", required = false) @QueryParam("since") String since) { DALFacade dalFacade = null; try { + String registrarErrors = bazaarService.notifyRegistrars(EnumSet.of(BazaarFunction.VALIDATION, BazaarFunction.USER_FIRST_LOGIN_HANDLING)); + if (registrarErrors != null) { + ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, registrarErrors); + } UserAgent agent = (UserAgent) Context.getCurrent().getMainAgent(); long userId = agent.getId(); dalFacade = bazaarService.getDBConnection(); Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); Calendar sinceCal = since == null ? null : DatatypeConverter.parseDateTime(since); - Statistic statisticsResult = dalFacade.getStatisticsForRequirement(internalUserId, requirementId, sinceCal); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_39, Context.getCurrent().getMainAgent(), "Get statistics for requirement " + requirementId); - Gson gson = new Gson(); - return Response.ok(gson.toJson(statisticsResult)).build(); + Statistic requirementStatistics = dalFacade.getStatisticsForRequirement(internalUserId, requirementId, sinceCal); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE_CHILD, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_39, + requirementId, Activity.DataType.REQUIREMENT, internalUserId); + return Response.ok(requirementStatistics.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -1232,8 +1208,10 @@ public Response getDevelopersForRequirement(@PathParam("requirementId") int requ ExceptionHandler.getInstance().handleViolations(vtor.getViolations()); } dalFacade = bazaarService.getDBConnection(); - PaginationResult requirementsResult = dalFacade.listDevelopersForRequirement(requirementId, pageInfo); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_40, Context.getCurrent().getMainAgent(), "Get developers for requirement " + requirementId); + Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); + PaginationResult requirementDevelopers = dalFacade.listDevelopersForRequirement(requirementId, pageInfo); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE_CHILD, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_40, + requirementId, Activity.DataType.REQUIREMENT, internalUserId); Map> parameter = new HashMap<>(); parameter.put("page", new ArrayList() {{ @@ -1243,11 +1221,10 @@ public Response getDevelopersForRequirement(@PathParam("requirementId") int requ add(String.valueOf(perPage)); }}); - Gson gson = new Gson(); Response.ResponseBuilder responseBuilder = Response.ok(); - responseBuilder = responseBuilder.entity(gson.toJson(requirementsResult.getElements())); - responseBuilder = bazaarService.paginationLinks(responseBuilder, requirementsResult, "requirements/" + String.valueOf(requirementId) + "/developers", parameter); - responseBuilder = bazaarService.xHeaderFields(responseBuilder, requirementsResult); + responseBuilder = responseBuilder.entity(requirementDevelopers.toJSON()); + responseBuilder = bazaarService.paginationLinks(responseBuilder, requirementDevelopers, "requirements/" + String.valueOf(requirementId) + "/developers", parameter); + responseBuilder = bazaarService.xHeaderFields(responseBuilder, requirementDevelopers); Response response = responseBuilder.build(); return response; @@ -1275,23 +1252,19 @@ public Response getDevelopersForRequirement(@PathParam("requirementId") int requ * This method returns the list of contributors for a specific requirement. * * @param requirementId id of the requirement - * @param page page number - * @param perPage number of projects by page - * @return Response with contributors as a JSON array. + * @return Response with requirement contributors */ @GET @Path("/{requirementId}/contributors") @Produces(MediaType.APPLICATION_JSON) @ApiOperation(value = "This method returns the list of contributors for a specific requirement.") @ApiResponses(value = { - @ApiResponse(code = HttpURLConnection.HTTP_OK, message = "Returns a list of contributors for a given requirement", response = User.class, responseContainer = "List"), + @ApiResponse(code = HttpURLConnection.HTTP_OK, message = "Returns a list of contributors for a given requirement", response = RequirementContributors.class), @ApiResponse(code = HttpURLConnection.HTTP_UNAUTHORIZED, message = "Unauthorized"), @ApiResponse(code = HttpURLConnection.HTTP_NOT_FOUND, message = "Not found"), @ApiResponse(code = HttpURLConnection.HTTP_INTERNAL_ERROR, message = "Internal server problems") }) - public Response getContributorsForRequirement(@PathParam("requirementId") int requirementId, - @ApiParam(value = "Page number", required = false) @DefaultValue("0") @QueryParam("page") int page, - @ApiParam(value = "Elements of comments by page", required = false) @DefaultValue("10") @QueryParam("per_page") int perPage) throws Exception { + public Response getContributorsForRequirement(@PathParam("requirementId") int requirementId) throws Exception { DALFacade dalFacade = null; try { UserAgent agent = (UserAgent) Context.getCurrent().getMainAgent(); @@ -1300,32 +1273,12 @@ public Response getContributorsForRequirement(@PathParam("requirementId") int re if (registrarErrors != null) { ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, registrarErrors); } - PageInfo pageInfo = new PageInfo(page, perPage); - Vtor vtor = bazaarService.getValidators(); - vtor.validate(pageInfo); - if (vtor.hasViolations()) { - ExceptionHandler.getInstance().handleViolations(vtor.getViolations()); - } dalFacade = bazaarService.getDBConnection(); - PaginationResult requirementsResult = dalFacade.listContributorsForRequirement(requirementId, pageInfo); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_41, Context.getCurrent().getMainAgent(), "Get contributors for requirement " + requirementId); - - Map> parameter = new HashMap<>(); - parameter.put("page", new ArrayList() {{ - add(String.valueOf(page)); - }}); - parameter.put("per_page", new ArrayList() {{ - add(String.valueOf(perPage)); - }}); - - Gson gson = new Gson(); - Response.ResponseBuilder responseBuilder = Response.ok(); - responseBuilder = responseBuilder.entity(gson.toJson(requirementsResult.getElements())); - responseBuilder = bazaarService.paginationLinks(responseBuilder, requirementsResult, "requirements/" + String.valueOf(requirementId) + "/contributors", parameter); - responseBuilder = bazaarService.xHeaderFields(responseBuilder, requirementsResult); - Response response = responseBuilder.build(); - - return response; + Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); + RequirementContributors requirementContributors = dalFacade.listContributorsForRequirement(requirementId); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE_CHILD, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_41, + requirementId, Activity.DataType.REQUIREMENT, internalUserId); + return Response.ok(requirementContributors.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -1382,8 +1335,10 @@ public Response getFollowersForRequirement(@PathParam("requirementId") int requi ExceptionHandler.getInstance().handleViolations(vtor.getViolations()); } dalFacade = bazaarService.getDBConnection(); - PaginationResult requirementsResult = dalFacade.listFollowersForRequirement(requirementId, pageInfo); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_42, Context.getCurrent().getMainAgent(), "Get followers for requirement " + requirementId); + Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); + PaginationResult requirementFollowers = dalFacade.listFollowersForRequirement(requirementId, pageInfo); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE_CHILD, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_42, + requirementId, Activity.DataType.REQUIREMENT, internalUserId); Map> parameter = new HashMap<>(); parameter.put("page", new ArrayList() {{ @@ -1392,12 +1347,11 @@ public Response getFollowersForRequirement(@PathParam("requirementId") int requi parameter.put("per_page", new ArrayList() {{ add(String.valueOf(perPage)); }}); - - Gson gson = new Gson(); + Response.ResponseBuilder responseBuilder = Response.ok(); - responseBuilder = responseBuilder.entity(gson.toJson(requirementsResult.getElements())); - responseBuilder = bazaarService.paginationLinks(responseBuilder, requirementsResult, "requirements/" + String.valueOf(requirementId) + "/followers", parameter); - responseBuilder = bazaarService.xHeaderFields(responseBuilder, requirementsResult); + responseBuilder = responseBuilder.entity(requirementFollowers.toJSON()); + responseBuilder = bazaarService.paginationLinks(responseBuilder, requirementFollowers, "requirements/" + String.valueOf(requirementId) + "/followers", parameter); + responseBuilder = bazaarService.xHeaderFields(responseBuilder, requirementFollowers); Response response = responseBuilder.build(); return response; diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/UsersResource.java b/src/main/de/rwth/dbis/acis/bazaar/service/UsersResource.java index b16391d0..530b1c00 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/UsersResource.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/UsersResource.java @@ -1,7 +1,7 @@ package de.rwth.dbis.acis.bazaar.service; -import com.google.gson.Gson; import de.rwth.dbis.acis.bazaar.service.dal.DALFacade; +import de.rwth.dbis.acis.bazaar.service.dal.entities.Activity; import de.rwth.dbis.acis.bazaar.service.dal.entities.User; import de.rwth.dbis.acis.bazaar.service.exception.BazaarException; import de.rwth.dbis.acis.bazaar.service.exception.ErrorCode; @@ -18,6 +18,7 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.net.HttpURLConnection; +import java.util.Date; import java.util.EnumSet; @@ -77,9 +78,10 @@ public Response getUser(@PathParam("userId") int userId) { } dalFacade = bazaarService.getDBConnection(); User user = dalFacade.getUserById(userId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_53, Context.getCurrent().getMainAgent(), "Get user " + userId); - Gson gson = new Gson(); - return Response.ok(gson.toJson(user)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_53, + userId, Activity.DataType.USER, userId); + + return Response.ok(user.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -127,9 +129,10 @@ public Response getActiveUser() { dalFacade = bazaarService.getDBConnection(); Integer internalUserId = dalFacade.getUserIdByLAS2PeerId(userId); User user = dalFacade.getUserById(internalUserId); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_54, Context.getCurrent().getMainAgent(), "Get active user " + internalUserId); - Gson gson = new Gson(); - return Response.ok(gson.toJson(user)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.RETRIEVE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_54, + internalUserId, Activity.DataType.USER, internalUserId); + + return Response.ok(user.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); @@ -177,7 +180,7 @@ public Response updateUser(@PathParam("userId") int userId, ExceptionHandler.getInstance().throwException(ExceptionLocation.BAZAARSERVICE, ErrorCode.UNKNOWN, registrarErrors); } UserAgent agent = (UserAgent) Context.getCurrent().getMainAgent(); - Gson gson = new Gson(); + Vtor vtor = bazaarService.getValidators(); vtor.validate(userToUpdate); if (vtor.hasViolations()) { @@ -190,8 +193,9 @@ public Response updateUser(@PathParam("userId") int userId, "UserId is not identical with user sending this request."); } User updatedUser = dalFacade.modifyUser(userToUpdate); - L2pLogger.logEvent(NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_56, Context.getCurrent().getMainAgent(), "Update user " + userId); - return Response.ok(gson.toJson(updatedUser)).build(); + bazaarService.getNotificationDispatcher().dispatchNotification(new Date(), Activity.ActivityAction.UPDATE, NodeObserver.Event.SERVICE_CUSTOM_MESSAGE_56, + userId, Activity.DataType.USER, internalUserId); + return Response.ok(updatedUser.toJSON()).build(); } catch (BazaarException bex) { if (bex.getErrorCode() == ErrorCode.AUTHORIZATION) { return Response.status(Response.Status.UNAUTHORIZED).entity(ExceptionHandler.getInstance().toJSON(bex)).build(); diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/dal/DALFacade.java b/src/main/de/rwth/dbis/acis/bazaar/service/dal/DALFacade.java index cbc14f75..6a13f804 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/dal/DALFacade.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/dal/DALFacade.java @@ -75,11 +75,28 @@ public interface DALFacade { * Get all contributors for a requirement * * @param requirementId - * @param pageable * @return * @throws BazaarException */ - PaginationResult listContributorsForRequirement(int requirementId, Pageable pageable) throws BazaarException; + RequirementContributors listContributorsForRequirement(int requirementId) throws BazaarException; + + /** + * Get all contributors for a category + * + * @param categoryId + * @return + * @throws BazaarException + */ + CategoryContributors listContributorsForCategory(int categoryId) throws BazaarException; + + /** + * Get all contributors for a project + * + * @param projectId + * @return + * @throws BazaarException + */ + ProjectContributors listContributorsForProject(int projectId) throws BazaarException; /** * Get all developers for a requirement diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/dal/DALFacadeImpl.java b/src/main/de/rwth/dbis/acis/bazaar/service/dal/DALFacadeImpl.java index 1979c807..70ea9b5c 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/dal/DALFacadeImpl.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/dal/DALFacadeImpl.java @@ -118,9 +118,21 @@ public Integer getUserIdByLAS2PeerId(long las2PeerId) throws Exception { } @Override - public PaginationResult listContributorsForRequirement(int requirementId, Pageable pageable) throws BazaarException { + public RequirementContributors listContributorsForRequirement(int requirementId) throws BazaarException { userRepository = (userRepository != null) ? userRepository : new UserRepositoryImpl(dslContext); - return userRepository.findAllByContribution(requirementId, pageable); + return userRepository.findRequirementContributors(requirementId); + } + + @Override + public CategoryContributors listContributorsForCategory(int categoryId) throws BazaarException { + userRepository = (userRepository != null) ? userRepository : new UserRepositoryImpl(dslContext); + return userRepository.findCategoryContributors(categoryId); + } + + @Override + public ProjectContributors listContributorsForProject(int projectId) throws BazaarException { + userRepository = (userRepository != null) ? userRepository : new UserRepositoryImpl(dslContext); + return userRepository.findProjectContributors(projectId); } @Override diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Activity.java b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Activity.java index 3f17717b..baa24372 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Activity.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Activity.java @@ -1,10 +1,18 @@ package de.rwth.dbis.acis.bazaar.service.dal.entities; +import com.fasterxml.jackson.annotation.JsonFilter; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.databind.JsonNode; + import java.util.Date; public class Activity extends EntityBase { - private final int id; + private final transient int id; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ") private final Date creationDate; private final ActivityAction activityAction; private final String dataUrl; @@ -15,7 +23,28 @@ public class Activity extends EntityBase { private final String userUrl; private final String origin; + private AdditionalObject additionalObject; + + protected Activity(Builder builder) { + this.id = builder.id; + this.creationDate = builder.creationDate; + this.activityAction = builder.activityAction; + this.dataUrl = builder.dataUrl; + this.dataType = builder.dataType; + this.dataFrontendUrl = builder.dataFrontendUrl; + this.parentDataUrl = builder.parentDataUrl; + this.parentDataType = builder.parentDataType; + this.userUrl = builder.userUrl; + this.origin = builder.origin; + this.additionalObject = builder.additionalObject; + } + + public static Builder getBuilder() { + return new Builder(); + } + @Override + @JsonIgnore public int getId() { return id; } @@ -52,23 +81,40 @@ public String getUserUrl() { return userUrl; } - public String getOrigin() { return origin; } + public String getOrigin() { + return origin; + } - protected Activity(Builder builder) { - this.id = builder.id; - this.creationDate = builder.creationDate; - this.activityAction = builder.activityAction; - this.dataUrl = builder.dataUrl; - this.dataType = builder.dataType; - this.dataFrontendUrl = builder.dataFrontendUrl; - this.parentDataUrl = builder.parentDataUrl; - this.parentDataType = builder.parentDataType; - this.userUrl = builder.userUrl; - this.origin = builder.origin; + public AdditionalObject getAdditionalObject() { + return additionalObject; } - public static Builder getBuilder() { - return new Builder(); + public enum DataType { + STATISTIC, + PROJECT, + CATEGORY, + REQUIREMENT, + COMMENT, + ATTACHMENT, + USER + } + + public enum ActivityAction { + RETRIEVE, + RETRIEVE_CHILD, + CREATE, + UPDATE, + DELETE, + REALIZE, + UNREALIZE, + VOTE, + UNVOTE, + DEVELOP, + UNDEVELOP, + FOLLOW, + UNFOLLOW, + LEADDEVELOP, + UNLEADDEVELOP } public static class Builder { @@ -83,6 +129,7 @@ public static class Builder { protected DataType parentDataType; protected String userUrl; protected String origin; + protected AdditionalObject additionalObject; public Builder creationDate(Date creationDate) { this.creationDate = creationDate; @@ -129,33 +176,51 @@ public Builder origin(String origin) { return this; } + public Builder addititionalObject(AdditionalObject additionalObject) { + this.additionalObject = additionalObject; + return this; + } + public Activity build() { Activity created = new Activity(this); return created; } } - public enum DataType { - PROJECT, - CATEGORY, - REQUIREMENT, - COMMENT, - ATTACHMENT - } + public static class AdditionalObject { + @JsonFilter("ActivityFilter") + private Project project; - public enum ActivityAction { - CREATE, - UPDATE, - DELETE, - REALIZE, - UNREALIZE, - VOTE, - UNVOTE, - DEVELOP, - UNDEVELOP, - FOLLOW, - UNFOLLOW, - LEADDEVELOP, - UNLEADDEVELOP + @JsonFilter("ActivityFilter") + private Category category; + + @JsonFilter("ActivityFilter") + private Requirement requirement; + + @JsonFilter("ActivityFilter") + private User user; + + public Project getProject() { + return project; + } + + public Category getCategory() { + return category; + } + + public Requirement getRequirement() { + return requirement; + } + + public User getUser() { + return user; + } + + public AdditionalObject(Project project, Category category, Requirement requirement, User user) { + this.project = project; + this.category = category; + this.requirement = requirement; + this.user = user; + } } } diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Attachment.java b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Attachment.java index 36e975e1..0449245f 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Attachment.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Attachment.java @@ -20,6 +20,7 @@ package de.rwth.dbis.acis.bazaar.service.dal.entities; +import com.fasterxml.jackson.annotation.JsonFormat; import jodd.vtor.constraint.MaxLength; import jodd.vtor.constraint.Min; import jodd.vtor.constraint.NotBlank; @@ -58,8 +59,10 @@ public class Attachment extends EntityBase { private User creator; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ") private Date creationDate; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ") private Date lastUpdatedDate; public Attachment() { diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Category.java b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Category.java index e86af23d..be9e44b3 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Category.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Category.java @@ -21,13 +21,14 @@ package de.rwth.dbis.acis.bazaar.service.dal.entities; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; import jodd.vtor.constraint.MaxLength; import jodd.vtor.constraint.Min; import jodd.vtor.constraint.NotBlank; import jodd.vtor.constraint.NotNull; import java.util.Date; -import java.util.List; /** * @author Adam Gavronek @@ -51,23 +52,53 @@ public class Category extends EntityBase { private User leader; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ") private Date creationDate; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ") private Date lastUpdatedDate; private Integer numberOfRequirements; private Integer numberOfFollowers; private Boolean isFollower; + public Category() { + } - public int getProjectId() { - return projectId; + /** + * Private constructor, should be called from its builder only. + * + * @param builder + */ + private Category(Builder builder) { + this.id = builder.id; + this.name = builder.name; + this.description = builder.description; + this.projectId = builder.projectId; + this.leader = builder.leader; + this.creationDate = builder.creationDate; + this.lastUpdatedDate = builder.lastUpdatedDate; + this.isFollower = builder.isFollower; + } + + /** + * Builder to easily build Category objects + * + * @param name Name field will be initialized using the passed value + * @return a builder with name returned + */ + public static Builder getBuilder(String name) { + return new Builder(name); } public int getId() { return id; } + public int getProjectId() { + return projectId; + } + public Date getCreationDate() { return creationDate; } @@ -104,46 +135,30 @@ public void setFollower(Boolean follower) { isFollower = follower; } - public void setNumberOfRequirements(Integer numberOfRequirements) { - this.numberOfRequirements = numberOfRequirements; + public Integer getNumberOfRequirements() { + return numberOfRequirements; } - public void setNumberOfFollowers(Integer numberOfFollowers) { - this.numberOfFollowers = numberOfFollowers; + public void setNumberOfRequirements(Integer numberOfRequirements) { + this.numberOfRequirements = numberOfRequirements; } - public Category() { + public Integer getNumberOfFollowers() { + return numberOfFollowers; } - /** - * Private constructor, should be called from its builder only. - * - * @param builder - */ - private Category(Builder builder) { - this.id = builder.id; - this.name = builder.name; - this.description = builder.description; - this.projectId = builder.projectId; - this.leader = builder.leader; - this.creationDate = builder.creationDate; - this.lastUpdatedDate = builder.lastUpdatedDate; - this.isFollower = builder.isFollower; + public void setNumberOfFollowers(Integer numberOfFollowers) { + this.numberOfFollowers = numberOfFollowers; } - - /** - * Builder to easily build Category objects - * - * @param name Name field will be initialized using the passed value - * @return a builder with name returned - */ - public static Builder getBuilder(String name) { - return new Builder(name); + @JsonProperty("isFollower") + public Boolean isFollower() { + return isFollower; } public static class Builder { + public User leader; private int id; private String description; private String name; @@ -151,7 +166,6 @@ public static class Builder { private Date lastUpdatedDate; private int projectId; private Boolean isFollower; - public User leader; public Builder(String name) { this.name = name; diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/CategoryContributors.java b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/CategoryContributors.java new file mode 100644 index 00000000..a1295a21 --- /dev/null +++ b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/CategoryContributors.java @@ -0,0 +1,110 @@ +package de.rwth.dbis.acis.bazaar.service.dal.entities; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +import java.util.List; + +/** + * Created by Martin on 15.06.2017. + */ +public class CategoryContributors extends EntityBase { + + private final int id; + + private User leader; + private List requirementCreator; + private List leadDeveloper; + private List developers; + private List commentCreator; + private List attachmentCreator; + + protected CategoryContributors(Builder builder) { + this.id = builder.id; + this.leader = builder.leader; + this.requirementCreator = builder.requirementCreator; + this.leadDeveloper = builder.leadDeveloper; + this.developers = builder.developers; + this.commentCreator = builder.commentCreator; + this.attachmentCreator = builder.attachmentCreator; + } + + public static Builder getBuilder() { + return new Builder(); + } + + @Override + @JsonIgnore + public int getId() { + return id; + } + + public User getLeader() { + return leader; + } + + public List getRequirementCreator() { + return requirementCreator; + } + + public List getLeadDeveloper() { + return leadDeveloper; + } + + public List getDevelopers() { + return developers; + } + + public List getCommentCreator() { + return commentCreator; + } + + public List getAttachmentCreator() { + return attachmentCreator; + } + + public static class Builder { + + private int id; + private User leader; + private List requirementCreator; + private List leadDeveloper; + private List developers; + private List commentCreator; + private List attachmentCreator; + + public Builder leader(User leader) { + this.leader = leader; + return this; + } + + public Builder requirementCreator(List requirementCreator) { + this.requirementCreator = requirementCreator; + return this; + } + + public Builder leadDeveloper(List leadDeveloper) { + this.leadDeveloper = leadDeveloper; + return this; + } + + public Builder developers(List developers) { + this.developers = developers; + return this; + } + + public Builder commentCreator(List commentCreator) { + this.commentCreator = commentCreator; + return this; + } + + public Builder attachmentCreator(List attachmentCreator) { + this.attachmentCreator = attachmentCreator; + return this; + } + + public CategoryContributors build() { + CategoryContributors created = new CategoryContributors(this); + return created; + } + } +} diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Comment.java b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Comment.java index 1261e1c7..7a6639a1 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Comment.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Comment.java @@ -21,6 +21,7 @@ package de.rwth.dbis.acis.bazaar.service.dal.entities; +import com.fasterxml.jackson.annotation.JsonFormat; import jodd.vtor.constraint.Min; import jodd.vtor.constraint.NotBlank; import jodd.vtor.constraint.NotNull; @@ -46,8 +47,10 @@ public class Comment extends EntityBase { private User creator; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ") private Date creationDate; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ") private Date lastUpdatedDate; public Comment() { diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/EntityBase.java b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/EntityBase.java index d833e958..f7027257 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/EntityBase.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/EntityBase.java @@ -20,7 +20,9 @@ package de.rwth.dbis.acis.bazaar.service.dal.entities; -import com.google.gson.Gson; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; /** * @author Adam Gavronek @@ -28,7 +30,7 @@ */ public abstract class EntityBase implements IdentifiedById { - public String toJSON() { - return new Gson().toJson(this); + public String toJSON() throws JsonProcessingException { + return new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL).writeValueAsString(this); } } diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Project.java b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Project.java index 0a0d0fc7..a792942b 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Project.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Project.java @@ -20,12 +20,13 @@ package de.rwth.dbis.acis.bazaar.service.dal.entities; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; import jodd.vtor.constraint.MaxLength; import jodd.vtor.constraint.NotBlank; import jodd.vtor.constraint.NotNull; import java.util.Date; -import java.util.List; /** * @author Adam Gavronek @@ -37,7 +38,7 @@ public class Project extends EntityBase { @NotBlank(profiles = {"*"}) @NotNull(profiles = {"create"}) - @MaxLength(value= 50, profiles = {"*"}) + @MaxLength(value = 50, profiles = {"*"}) private String name; @NotBlank(profiles = {"*"}) @@ -50,8 +51,10 @@ public class Project extends EntityBase { private User leader; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ") private Date creationDate; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ") private Date lastUpdatedDate; private Integer numberOfCategories; @@ -59,30 +62,6 @@ public class Project extends EntityBase { private Integer numberOfFollowers; private Boolean isFollower; - public Boolean getVisibility() { - return visibility; - } - - public void setLeader(User leader) { - this.leader = leader; - } - - public void setFollower(Boolean follower) { - isFollower = follower; - } - - public void setNumberOfCategories(Integer numberOfCategories) { - this.numberOfCategories = numberOfCategories; - } - - public void setNumberOfRequirements(Integer numberOfRequirements) { - this.numberOfRequirements = numberOfRequirements; - } - - public void setNumberOfFollowers(Integer numberOfFollowers) { - this.numberOfFollowers = numberOfFollowers; - } - public Project() { } @@ -113,7 +92,6 @@ public static Builder getBuilder(String name) { return new Builder(name); } - @Override public int getId() { return id; } @@ -146,6 +124,10 @@ public User getLeader() { return leader; } + public void setLeader(User leader) { + this.leader = leader; + } + public Integer getDefaultCategoryId() { return defaultCategoryId; } @@ -154,6 +136,43 @@ public void setDefaultCategoryId(Integer defaultCategoryId) { this.defaultCategoryId = defaultCategoryId; } + public Boolean getVisibility() { + return visibility; + } + + public Integer getNumberOfCategories() { + return numberOfCategories; + } + + public void setNumberOfCategories(Integer numberOfCategories) { + this.numberOfCategories = numberOfCategories; + } + + public Integer getNumberOfRequirements() { + return numberOfRequirements; + } + + public void setNumberOfRequirements(Integer numberOfRequirements) { + this.numberOfRequirements = numberOfRequirements; + } + + public Integer getNumberOfFollowers() { + return numberOfFollowers; + } + + public void setNumberOfFollowers(Integer numberOfFollowers) { + this.numberOfFollowers = numberOfFollowers; + } + + public void setFollower(Boolean isFollower) { + this.isFollower = isFollower; + } + + @JsonProperty("isFollower") + public Boolean isFollower() { + return isFollower; + } + public static class Builder { private int id; diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/ProjectContributors.java b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/ProjectContributors.java new file mode 100644 index 00000000..e66cc5d8 --- /dev/null +++ b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/ProjectContributors.java @@ -0,0 +1,122 @@ +package de.rwth.dbis.acis.bazaar.service.dal.entities; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +import java.util.List; + +/** + * Created by Martin on 15.06.2017. + */ +public class ProjectContributors extends EntityBase { + + private final int id; + + private User leader; + private List categoryLeader; + private List requirementCreator; + private List leadDeveloper; + private List developers; + private List commentCreator; + private List attachmentCreator; + + protected ProjectContributors(Builder builder) { + this.id = builder.id; + this.leader = builder.leader; + this.categoryLeader = builder.categoryLeader; + this.requirementCreator = builder.requirementCreator; + this.leadDeveloper = builder.leadDeveloper; + this.developers = builder.developers; + this.commentCreator = builder.commentCreator; + this.attachmentCreator = builder.attachmentCreator; + } + + public static Builder getBuilder() { + return new Builder(); + } + + @Override + @JsonIgnore + public int getId() { + return id; + } + + public User getLeader() { + return leader; + } + + public List getCategoryLeader() { + return categoryLeader; + } + + public List getRequirementCreator() { + return requirementCreator; + } + + public List getLeadDeveloper() { + return leadDeveloper; + } + + public List getDevelopers() { + return developers; + } + + public List getCommentCreator() { + return commentCreator; + } + + public List getAttachmentCreator() { + return attachmentCreator; + } + + public static class Builder { + + private int id; + private User leader; + private List categoryLeader; + private List requirementCreator; + private List leadDeveloper; + private List developers; + private List commentCreator; + private List attachmentCreator; + + public Builder leader(User leader) { + this.leader = leader; + return this; + } + + public Builder categoryLeader(List categoryLeader) { + this.categoryLeader = categoryLeader; + return this; + } + + public Builder requirementCreator(List requirementCreator) { + this.requirementCreator = requirementCreator; + return this; + } + + public Builder leadDeveloper(List leadDeveloper) { + this.leadDeveloper = leadDeveloper; + return this; + } + + public Builder developers(List developers) { + this.developers = developers; + return this; + } + + public Builder commentCreator(List commentCreator) { + this.commentCreator = commentCreator; + return this; + } + + public Builder attachmentCreator(List attachmentCreator) { + this.attachmentCreator = attachmentCreator; + return this; + } + + public ProjectContributors build() { + ProjectContributors created = new ProjectContributors(this); + return created; + } + } +} diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Requirement.java b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Requirement.java index 151705d9..c0b64fe0 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Requirement.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Requirement.java @@ -1,6 +1,8 @@ package de.rwth.dbis.acis.bazaar.service.dal.entities; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; import de.rwth.dbis.acis.bazaar.service.dal.helpers.UserVote; import jodd.vtor.constraint.*; @@ -23,6 +25,7 @@ public class Requirement extends EntityBase { @NotNull(profiles = {"create"}) private String description; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ") private Date realized; @Min(value = 0, profiles = {"create"}) @@ -39,8 +42,10 @@ public class Requirement extends EntityBase { // But the API still allows to create a requirement with attachments at the same time. private List attachments; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ") private Date creationDate; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ") private Date lastUpdatedDate; private Integer numberOfComments; @@ -55,6 +60,37 @@ public class Requirement extends EntityBase { private Boolean isDeveloper; private Boolean isContributor; + public Requirement() { + } + + protected Requirement(Builder builder) { + this.id = builder.id; + this.name = builder.name; + this.description = builder.description; + this.realized = builder.realized; + this.projectId = builder.projectId; + this.creator = builder.creator; + this.leadDeveloper = builder.leadDeveloper; + this.creationDate = builder.creationDate; + this.lastUpdatedDate = builder.lastUpdatedDate; + this.upVotes = builder.upVotes; + this.downVotes = builder.downVotes; + this.userVoted = builder.userVoted; + this.isFollower = builder.isFollower; + this.isDeveloper = builder.isDeveloper; + this.isContributor = builder.isContributor; + } + + /** + * Builder to easily build Requirement objects + * + * @param name Name field will be initialized using the passed value + * @return a builder with name returned + */ + public static Builder getBuilder(String name) { + return new Builder(name); + } + public Date getRealized() { return realized; } @@ -119,59 +155,67 @@ public User getLeadDeveloper() { return leadDeveloper; } + public void setFollower(Boolean follower) { + isFollower = follower; + } + + public void setDeveloper(Boolean developer) { + isDeveloper = developer; + } + + public void setContributor(Boolean contributor) { + isContributor = contributor; + } + + public Integer getNumberOfComments() { + return numberOfComments; + } + public void setNumberOfComments(Integer numberOfComments) { this.numberOfComments = numberOfComments; } + public Integer getNumberOfAttachments() { + return numberOfAttachments; + } + public void setNumberOfAttachments(Integer numberOfAttachments) { this.numberOfAttachments = numberOfAttachments; } + public Integer getNumberOfFollowers() { + return numberOfFollowers; + } + public void setNumberOfFollowers(Integer numberOfFollowers) { this.numberOfFollowers = numberOfFollowers; } - public void setFollower(Boolean follower) { - isFollower = follower; + public int getUpVotes() { + return upVotes; } - public void setDeveloper(Boolean developer) { - isDeveloper = developer; + public int getDownVotes() { + return downVotes; } - public void setContributor(Boolean contributor) { - isContributor = contributor; + public UserVote getUserVoted() { + return userVoted; } - public Requirement() { + @JsonProperty("isFollower") + public Boolean isFollower() { + return isFollower; } - protected Requirement(Builder builder) { - this.id = builder.id; - this.name = builder.name; - this.description = builder.description; - this.realized = builder.realized; - this.projectId = builder.projectId; - this.creator = builder.creator; - this.leadDeveloper = builder.leadDeveloper; - this.creationDate = builder.creationDate; - this.lastUpdatedDate = builder.lastUpdatedDate; - this.upVotes = builder.upVotes; - this.downVotes = builder.downVotes; - this.userVoted = builder.userVoted; - this.isFollower = builder.isFollower; - this.isDeveloper = builder.isDeveloper; - this.isContributor = builder.isContributor; + @JsonProperty("isDeveloper") + public Boolean isDeveloper() { + return isDeveloper; } - /** - * Builder to easily build Requirement objects - * - * @param name Name field will be initialized using the passed value - * @return a builder with name returned - */ - public static Builder getBuilder(String name) { - return new Builder(name); + @JsonProperty("isContributor") + public Boolean isContributor() { + return isContributor; } public static class Builder { diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/RequirementContributors.java b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/RequirementContributors.java new file mode 100644 index 00000000..e1c4145a --- /dev/null +++ b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/RequirementContributors.java @@ -0,0 +1,102 @@ +package de.rwth.dbis.acis.bazaar.service.dal.entities; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +// import javax.ws.rs.core.Link; +import java.util.List; + +/** + * Created by Martin on 12.06.2017. + */ +public class RequirementContributors extends EntityBase { + + private final int id; + + private User creator; + private User leadDeveloper; + private List developers; + //private Link developersLink; // TODO: Skip after 10 elements and add HATEOAS link + private List commentCreator; + //private Link commentCreatorLink; + private List attachmentCreator; + //private Link attachmentCreatorLink; + + protected RequirementContributors(Builder builder) { + this.id = builder.id; + this.creator = builder.creator; + this.leadDeveloper = builder.leadDeveloper; + this.developers = builder.developers; + this.commentCreator = builder.commentCreator; + this.attachmentCreator = builder.attachmentCreator; + } + + public static Builder getBuilder() { + return new Builder(); + } + + @Override + @JsonIgnore + public int getId() { + return id; + } + + public User getCreator() { + return creator; + } + + public User getLeadDeveloper() { + return leadDeveloper; + } + + public List getDevelopers() { + return developers; + } + + public List getCommentCreator() { + return commentCreator; + } + + public List getAttachmentCreator() { + return attachmentCreator; + } + + public static class Builder { + + private int id; + private User creator; + private User leadDeveloper; + private List developers; + private List commentCreator; + private List attachmentCreator; + + public Builder creator(User creator) { + this.creator = creator; + return this; + } + + public Builder leadDeveloper(User leadDeveloper) { + this.leadDeveloper = leadDeveloper; + return this; + } + + public Builder developers(List developers) { + this.developers = developers; + return this; + } + + public Builder commentCreator(List commentCreator) { + this.commentCreator = commentCreator; + return this; + } + + public Builder attachmentCreator(List attachmentCreator) { + this.attachmentCreator = attachmentCreator; + return this; + } + + public RequirementContributors build() { + RequirementContributors created = new RequirementContributors(this); + return created; + } + } +} diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Statistic.java b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Statistic.java index f08e04c9..89b1bb39 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Statistic.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/Statistic.java @@ -1,5 +1,9 @@ package de.rwth.dbis.acis.bazaar.service.dal.entities; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + /** * Created by hugif on 26.12.2016. */ @@ -22,6 +26,58 @@ protected Statistic(Builder builder) { this.numberOfVotes = builder.numberOfVotes; } + public int getNumberOfProjects() { + return numberOfProjects; + } + + public void setNumberOfProjects(int numberOfProjects) { + this.numberOfProjects = numberOfProjects; + } + + public int getNumberOfCategories() { + return numberOfCategories; + } + + public void setNumberOfCategories(int numberOfCategories) { + this.numberOfCategories = numberOfCategories; + } + + public int getNumberOfRequirements() { + return numberOfRequirements; + } + + public void setNumberOfRequirements(int numberOfRequirements) { + this.numberOfRequirements = numberOfRequirements; + } + + public int getNumberOfComments() { + return numberOfComments; + } + + public void setNumberOfComments(int numberOfComments) { + this.numberOfComments = numberOfComments; + } + + public int getNumberOfAttachments() { + return numberOfAttachments; + } + + public void setNumberOfAttachments(int numberOfAttachments) { + this.numberOfAttachments = numberOfAttachments; + } + + public int getNumberOfVotes() { + return numberOfVotes; + } + + public void setNumberOfVotes(int numberOfVotes) { + this.numberOfVotes = numberOfVotes; + } + + public String toJSON() throws JsonProcessingException { + return new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL).writeValueAsString(this); + } + public static Builder getBuilder() { return new Builder(); } @@ -69,7 +125,6 @@ public Statistic build() { Statistic created = new Statistic(this); return created; } - } } diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/User.java b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/User.java index a7aee9dc..970613f4 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/User.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/dal/entities/User.java @@ -21,6 +21,8 @@ package de.rwth.dbis.acis.bazaar.service.dal.entities; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; import jodd.vtor.constraint.MaxLength; import jodd.vtor.constraint.Min; import jodd.vtor.constraint.NotBlank; @@ -59,10 +61,13 @@ public class User extends EntityBase { private Boolean emailFollowSubscription; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ") private Date creationDate; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ") private Date lastUpdatedDate; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ") private Date lastLoginDate; public User() { @@ -96,6 +101,7 @@ public String getLastName() { return lastName; } + @JsonIgnore public String getEMail() { return eMail; } diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/dal/helpers/PaginationResult.java b/src/main/de/rwth/dbis/acis/bazaar/service/dal/helpers/PaginationResult.java index ce390569..7d0d26ac 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/dal/helpers/PaginationResult.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/dal/helpers/PaginationResult.java @@ -1,6 +1,10 @@ package de.rwth.dbis.acis.bazaar.service.dal.helpers; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + import java.util.List; public class PaginationResult { @@ -46,4 +50,8 @@ public int getNextPage() { return -1; } } + + public String toJSON() throws JsonProcessingException { + return new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL).writeValueAsString(this.getElements()); + } } diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/dal/repositories/UserRepository.java b/src/main/de/rwth/dbis/acis/bazaar/service/dal/repositories/UserRepository.java index e951d682..c103f949 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/dal/repositories/UserRepository.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/dal/repositories/UserRepository.java @@ -20,6 +20,9 @@ package de.rwth.dbis.acis.bazaar.service.dal.repositories; +import de.rwth.dbis.acis.bazaar.service.dal.entities.CategoryContributors; +import de.rwth.dbis.acis.bazaar.service.dal.entities.ProjectContributors; +import de.rwth.dbis.acis.bazaar.service.dal.entities.RequirementContributors; import de.rwth.dbis.acis.bazaar.service.dal.entities.User; import de.rwth.dbis.acis.bazaar.service.dal.helpers.Pageable; import de.rwth.dbis.acis.bazaar.service.dal.helpers.PaginationResult; @@ -39,7 +42,11 @@ public interface UserRepository extends Repository { PaginationResult findAllByDeveloping(int requirementId, Pageable pageable) throws BazaarException; - PaginationResult findAllByContribution(int requirementId, Pageable pageable) throws BazaarException; + RequirementContributors findRequirementContributors(int requirementId) throws BazaarException; + + CategoryContributors findCategoryContributors(int categoryId) throws BazaarException; + + ProjectContributors findProjectContributors(int projectId) throws BazaarException; PaginationResult findAllByFollowing(int projectId, int categoryId, int requirementId, Pageable pageable) throws BazaarException; diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/dal/repositories/UserRepositoryImpl.java b/src/main/de/rwth/dbis/acis/bazaar/service/dal/repositories/UserRepositoryImpl.java index 178b4670..88d41244 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/dal/repositories/UserRepositoryImpl.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/dal/repositories/UserRepositoryImpl.java @@ -20,6 +20,9 @@ package de.rwth.dbis.acis.bazaar.service.dal.repositories; +import de.rwth.dbis.acis.bazaar.service.dal.entities.CategoryContributors; +import de.rwth.dbis.acis.bazaar.service.dal.entities.ProjectContributors; +import de.rwth.dbis.acis.bazaar.service.dal.entities.RequirementContributors; import de.rwth.dbis.acis.bazaar.service.dal.entities.User; import de.rwth.dbis.acis.bazaar.service.dal.helpers.Pageable; import de.rwth.dbis.acis.bazaar.service.dal.helpers.PaginationResult; @@ -32,10 +35,12 @@ import org.jooq.DSLContext; import org.jooq.Field; import org.jooq.Record; +import org.jooq.Result; import java.util.ArrayList; import java.util.Calendar; import java.util.List; +import java.util.Map; import static de.rwth.dbis.acis.bazaar.service.dal.jooq.Tables.*; @@ -44,6 +49,8 @@ * @since 6/23/2014 */ public class UserRepositoryImpl extends RepositoryImpl implements UserRepository { + final byte ONE = 1; + /** * @param jooq DSLContext for JOOQ connection */ @@ -51,8 +58,6 @@ public UserRepositoryImpl(DSLContext jooq) { super(jooq, new UserTransformer()); } - final byte ONE = 1; - @Override public Integer getIdByLas2PeerId(long las2PeerId) throws BazaarException { Integer id = null; @@ -76,93 +81,313 @@ public void updateLastLoginDate(int userId) throws Exception { } @Override - public PaginationResult findAllByContribution(int requirementId, Pageable pageable) throws BazaarException { - PaginationResult result = null; - List users; + public RequirementContributors findRequirementContributors(int requirementId) throws BazaarException { + RequirementContributors contributors = null; try { - users = new ArrayList<>(); + de.rwth.dbis.acis.bazaar.service.dal.jooq.tables.User creator = USER.as("creator"); + de.rwth.dbis.acis.bazaar.service.dal.jooq.tables.User leadDeveloper = USER.as("leadDeveloper"); + de.rwth.dbis.acis.bazaar.service.dal.jooq.tables.User developer = USER.as("developer"); + de.rwth.dbis.acis.bazaar.service.dal.jooq.tables.User commentCreator = USER.as("commentCreator"); + de.rwth.dbis.acis.bazaar.service.dal.jooq.tables.User attachmentCreator = USER.as("attachmentCreator"); + + Result queryResult = jooq.select(REQUIREMENT.fields()) + .select(creator.fields()) + .select(leadDeveloper.fields()) + .select(developer.fields()) + .select(commentCreator.fields()) + .select(attachmentCreator.fields()) + .from(REQUIREMENT) + .leftOuterJoin(creator).on(creator.ID.equal(REQUIREMENT.CREATOR_ID)) + .leftOuterJoin(leadDeveloper).on(leadDeveloper.ID.equal(REQUIREMENT.LEAD_DEVELOPER_ID)) + .leftOuterJoin(REQUIREMENT_DEVELOPER_MAP).on(REQUIREMENT_DEVELOPER_MAP.REQUIREMENT_ID.eq(REQUIREMENT.ID)) + .leftOuterJoin(developer).on(developer.ID.eq(REQUIREMENT_DEVELOPER_MAP.USER_ID)) + .leftOuterJoin(COMMENT).on(COMMENT.REQUIREMENT_ID.eq(REQUIREMENT.ID)) + .leftOuterJoin(commentCreator).on(commentCreator.ID.eq(COMMENT.USER_ID)) + .leftOuterJoin(ATTACHMENT).on(ATTACHMENT.REQUIREMENT_ID.eq(REQUIREMENT.ID)) + .leftOuterJoin(attachmentCreator).on(attachmentCreator.ID.eq(ATTACHMENT.USER_ID)) + .where(REQUIREMENT.ID.equal(requirementId)) + .fetch(); - Field idCount = jooq.selectCount().from( - jooq.select(USER.fields()) - .from(USER) - .leftOuterJoin(REQUIREMENT).on(REQUIREMENT.CREATOR_ID.equal(USER.ID)) - .where(REQUIREMENT.ID.equal(requirementId)) - .union( - jooq.select(USER.fields()) - .from(USER) - .leftOuterJoin(REQUIREMENT).on(REQUIREMENT.LEAD_DEVELOPER_ID.equal(USER.ID)) - .where(REQUIREMENT.ID.equal(requirementId)) - ) - .union( - jooq.select(USER.fields()) - .from(USER) - .leftOuterJoin(REQUIREMENT_DEVELOPER_MAP).on(REQUIREMENT_DEVELOPER_MAP.USER_ID.equal(USER.ID)) - .where(REQUIREMENT_DEVELOPER_MAP.REQUIREMENT_ID.equal(requirementId)) - ) - .union( - jooq.select(USER.fields()) - .from(USER) - .leftOuterJoin(COMMENT).on(COMMENT.USER_ID.equal(USER.ID)) - .where(COMMENT.REQUIREMENT_ID.equal(requirementId)) - ) - .union( - jooq.select(USER.fields()) - .from(USER) - .leftOuterJoin(ATTACHMENT).on(ATTACHMENT.USER_ID.equal(USER.ID)) - .where(ATTACHMENT.REQUIREMENT_ID.equal(requirementId)) - ) - ) - .asField("idCount"); + if (queryResult == null || queryResult.size() == 0) { + ExceptionHandler.getInstance().convertAndThrowException( + new Exception("No requirement found with id: " + requirementId), + ExceptionLocation.REPOSITORY, ErrorCode.NOT_FOUND); + } - List queryResults = - jooq.select(USER.fields()) - .select(idCount) - .from(USER) - .leftOuterJoin(REQUIREMENT).on(REQUIREMENT.CREATOR_ID.equal(USER.ID)) - .where(REQUIREMENT.ID.equal(requirementId)) - .union( - jooq.select(USER.fields()) - .select(idCount) - .from(USER) - .leftOuterJoin(REQUIREMENT).on(REQUIREMENT.LEAD_DEVELOPER_ID.equal(USER.ID)) - .where(REQUIREMENT.ID.equal(requirementId)) - ) - .union( - jooq.select(USER.fields()) - .select(idCount) - .from(USER) - .leftOuterJoin(REQUIREMENT_DEVELOPER_MAP).on(REQUIREMENT_DEVELOPER_MAP.USER_ID.equal(USER.ID)) - .where(REQUIREMENT_DEVELOPER_MAP.REQUIREMENT_ID.equal(requirementId)) - ) - .union( - jooq.select(USER.fields()) - .select(idCount) - .from(USER) - .leftOuterJoin(COMMENT).on(COMMENT.USER_ID.equal(USER.ID)) - .where(COMMENT.REQUIREMENT_ID.equal(requirementId)) - ) - .union( - jooq.select(USER.fields()) - .select(idCount) - .from(USER) - .leftOuterJoin(ATTACHMENT).on(ATTACHMENT.USER_ID.equal(USER.ID)) - .where(ATTACHMENT.REQUIREMENT_ID.equal(requirementId)) - ) - .limit(pageable.getPageSize()) - .offset(pageable.getOffset()) - .fetch(); + UserTransformer userTransformer = new UserTransformer(); + RequirementContributors.Builder builder = new RequirementContributors.Builder(); - for (Record queryResult : queryResults) { - UserRecord userRecord = queryResult.into(UserRecord.class); - users.add(transformer.getEntityFromTableRecord(userRecord)); + builder.creator( + userTransformer.getEntityFromQueryResult(creator, queryResult) + ); + if (queryResult.getValues(leadDeveloper.ID).get(0) != null) { + builder.leadDeveloper( + userTransformer.getEntityFromQueryResult(leadDeveloper, queryResult) + ); + } + List developers = new ArrayList<>(); + for (Map.Entry> entry : queryResult.intoGroups(developer.ID).entrySet()) { + if (entry.getKey() == null) continue; + Result records = entry.getValue(); + developers.add( + userTransformer.getEntityFromQueryResult(developer, records) + ); } + builder.developers(developers); + + List commentCreators = new ArrayList<>(); + for (Map.Entry> entry : queryResult.intoGroups(commentCreator.ID).entrySet()) { + if (entry.getKey() == null) continue; + Result records = entry.getValue(); + commentCreators.add( + userTransformer.getEntityFromQueryResult(commentCreator, records) + ); + } + builder.commentCreator(commentCreators); + + List attachmentCreators = new ArrayList<>(); + for (Map.Entry> entry : queryResult.intoGroups(attachmentCreator.ID).entrySet()) { + if (entry.getKey() == null) continue; + Result records = entry.getValue(); + attachmentCreators.add( + userTransformer.getEntityFromQueryResult(attachmentCreator, records) + ); + } + builder.attachmentCreator(attachmentCreators); + + contributors = builder.build(); - int total = queryResults.isEmpty() ? 0 : ((Integer) queryResults.get(0).get("idCount")); - result = new PaginationResult<>(total, pageable, users); } catch (Exception e) { ExceptionHandler.getInstance().convertAndThrowException(e, ExceptionLocation.REPOSITORY, ErrorCode.UNKNOWN); } - return result; + return contributors; + } + + @Override + public CategoryContributors findCategoryContributors(int categoryId) throws BazaarException { + CategoryContributors contributors = null; + try { + de.rwth.dbis.acis.bazaar.service.dal.jooq.tables.User leader = USER.as("leader"); + de.rwth.dbis.acis.bazaar.service.dal.jooq.tables.User requirementCreator = USER.as("requirementCreator"); + de.rwth.dbis.acis.bazaar.service.dal.jooq.tables.User leadDeveloper = USER.as("leadDeveloper"); + de.rwth.dbis.acis.bazaar.service.dal.jooq.tables.User developer = USER.as("developer"); + de.rwth.dbis.acis.bazaar.service.dal.jooq.tables.User commentCreator = USER.as("commentCreator"); + de.rwth.dbis.acis.bazaar.service.dal.jooq.tables.User attachmentCreator = USER.as("attachmentCreator"); + + Result queryResult = jooq.select(CATEGORY.fields()) + .select(leader.fields()) + .select(requirementCreator.fields()) + .select(leadDeveloper.fields()) + .select(developer.fields()) + .select(commentCreator.fields()) + .select(attachmentCreator.fields()) + .from(CATEGORY) + .leftOuterJoin(leader).on(leader.ID.equal(CATEGORY.LEADER_ID)) + .leftOuterJoin(REQUIREMENT_CATEGORY_MAP).on(REQUIREMENT_CATEGORY_MAP.CATEGORY_ID.eq(CATEGORY.ID)) + .leftOuterJoin(REQUIREMENT).on(REQUIREMENT.ID.eq(REQUIREMENT_CATEGORY_MAP.REQUIREMENT_ID)) + .leftOuterJoin(requirementCreator).on(requirementCreator.ID.equal(REQUIREMENT.CREATOR_ID)) + .leftOuterJoin(leadDeveloper).on(leadDeveloper.ID.equal(REQUIREMENT.LEAD_DEVELOPER_ID)) + .leftOuterJoin(REQUIREMENT_DEVELOPER_MAP).on(REQUIREMENT_DEVELOPER_MAP.REQUIREMENT_ID.eq(REQUIREMENT.ID)) + .leftOuterJoin(developer).on(developer.ID.eq(REQUIREMENT_DEVELOPER_MAP.USER_ID)) + .leftOuterJoin(COMMENT).on(COMMENT.REQUIREMENT_ID.eq(REQUIREMENT.ID)) + .leftOuterJoin(commentCreator).on(commentCreator.ID.eq(COMMENT.USER_ID)) + .leftOuterJoin(ATTACHMENT).on(ATTACHMENT.REQUIREMENT_ID.eq(REQUIREMENT.ID)) + .leftOuterJoin(attachmentCreator).on(attachmentCreator.ID.eq(ATTACHMENT.USER_ID)) + + .where(CATEGORY.ID.equal(categoryId)) + .fetch(); + + if (queryResult == null || queryResult.size() == 0) { + ExceptionHandler.getInstance().convertAndThrowException( + new Exception("No category found with id: " + categoryId), + ExceptionLocation.REPOSITORY, ErrorCode.NOT_FOUND); + } + + UserTransformer userTransformer = new UserTransformer(); + CategoryContributors.Builder builder = new CategoryContributors.Builder(); + + builder.leader( + userTransformer.getEntityFromQueryResult(leader, queryResult) + ); + + List requirementCreators = new ArrayList<>(); + for (Map.Entry> entry : queryResult.intoGroups(requirementCreator.ID).entrySet()) { + if (entry.getKey() == null) continue; + Result records = entry.getValue(); + requirementCreators.add( + userTransformer.getEntityFromQueryResult(requirementCreator, records) + ); + } + builder.requirementCreator(requirementCreators); + + List leadDevelopers = new ArrayList<>(); + for (Map.Entry> entry : queryResult.intoGroups(leadDeveloper.ID).entrySet()) { + if (entry.getKey() == null) continue; + Result records = entry.getValue(); + leadDevelopers.add( + userTransformer.getEntityFromQueryResult(leadDeveloper, records) + ); + } + builder.leadDeveloper(leadDevelopers); + + List developers = new ArrayList<>(); + for (Map.Entry> entry : queryResult.intoGroups(developer.ID).entrySet()) { + if (entry.getKey() == null) continue; + Result records = entry.getValue(); + developers.add( + userTransformer.getEntityFromQueryResult(developer, records) + ); + } + builder.developers(developers); + + List commentCreators = new ArrayList<>(); + for (Map.Entry> entry : queryResult.intoGroups(commentCreator.ID).entrySet()) { + if (entry.getKey() == null) continue; + Result records = entry.getValue(); + commentCreators.add( + userTransformer.getEntityFromQueryResult(commentCreator, records) + ); + } + builder.commentCreator(commentCreators); + + List attachmentCreators = new ArrayList<>(); + for (Map.Entry> entry : queryResult.intoGroups(attachmentCreator.ID).entrySet()) { + if (entry.getKey() == null) continue; + Result records = entry.getValue(); + attachmentCreators.add( + userTransformer.getEntityFromQueryResult(attachmentCreator, records) + ); + } + builder.attachmentCreator(attachmentCreators); + + contributors = builder.build(); + + } catch (Exception e) { + ExceptionHandler.getInstance().convertAndThrowException(e, ExceptionLocation.REPOSITORY, ErrorCode.UNKNOWN); + } + return contributors; + } + + @Override + public ProjectContributors findProjectContributors(int projectId) throws BazaarException { + ProjectContributors contributors = null; + try { + de.rwth.dbis.acis.bazaar.service.dal.jooq.tables.User leader = USER.as("leader"); + de.rwth.dbis.acis.bazaar.service.dal.jooq.tables.User categoryLeader = USER.as("categoryLeader"); + de.rwth.dbis.acis.bazaar.service.dal.jooq.tables.User requirementCreator = USER.as("requirementCreator"); + de.rwth.dbis.acis.bazaar.service.dal.jooq.tables.User leadDeveloper = USER.as("leadDeveloper"); + de.rwth.dbis.acis.bazaar.service.dal.jooq.tables.User developer = USER.as("developer"); + de.rwth.dbis.acis.bazaar.service.dal.jooq.tables.User commentCreator = USER.as("commentCreator"); + de.rwth.dbis.acis.bazaar.service.dal.jooq.tables.User attachmentCreator = USER.as("attachmentCreator"); + + Result queryResult = jooq.select(PROJECT.fields()) + .select(leader.fields()) + .select(categoryLeader.fields()) + .select(requirementCreator.fields()) + .select(leadDeveloper.fields()) + .select(developer.fields()) + .select(commentCreator.fields()) + .select(attachmentCreator.fields()) + .from(PROJECT) + + .leftOuterJoin(leader).on(leader.ID.equal(PROJECT.LEADER_ID)) + + .leftOuterJoin(CATEGORY).on(CATEGORY.PROJECT_ID.eq(PROJECT.ID)) + .leftOuterJoin(categoryLeader).on(categoryLeader.ID.equal(CATEGORY.LEADER_ID)) + + .leftOuterJoin(REQUIREMENT_CATEGORY_MAP).on(REQUIREMENT_CATEGORY_MAP.CATEGORY_ID.eq(CATEGORY.ID)) + .leftOuterJoin(REQUIREMENT).on(REQUIREMENT.ID.eq(REQUIREMENT_CATEGORY_MAP.REQUIREMENT_ID)) + .leftOuterJoin(requirementCreator).on(requirementCreator.ID.equal(REQUIREMENT.CREATOR_ID)) + .leftOuterJoin(leadDeveloper).on(leadDeveloper.ID.equal(REQUIREMENT.LEAD_DEVELOPER_ID)) + .leftOuterJoin(REQUIREMENT_DEVELOPER_MAP).on(REQUIREMENT_DEVELOPER_MAP.REQUIREMENT_ID.eq(REQUIREMENT.ID)) + .leftOuterJoin(developer).on(developer.ID.eq(REQUIREMENT_DEVELOPER_MAP.USER_ID)) + .leftOuterJoin(COMMENT).on(COMMENT.REQUIREMENT_ID.eq(REQUIREMENT.ID)) + .leftOuterJoin(commentCreator).on(commentCreator.ID.eq(COMMENT.USER_ID)) + .leftOuterJoin(ATTACHMENT).on(ATTACHMENT.REQUIREMENT_ID.eq(REQUIREMENT.ID)) + .leftOuterJoin(attachmentCreator).on(attachmentCreator.ID.eq(ATTACHMENT.USER_ID)) + + .where(PROJECT.ID.equal(projectId)) + .fetch(); + + if (queryResult == null || queryResult.size() == 0) { + ExceptionHandler.getInstance().convertAndThrowException( + new Exception("No project found with id: " + projectId), + ExceptionLocation.REPOSITORY, ErrorCode.NOT_FOUND); + } + + UserTransformer userTransformer = new UserTransformer(); + ProjectContributors.Builder builder = new ProjectContributors.Builder(); + + builder.leader( + userTransformer.getEntityFromQueryResult(leader, queryResult) + ); + + List categoriesLeaders = new ArrayList<>(); + for (Map.Entry> entry : queryResult.intoGroups(categoryLeader.ID).entrySet()) { + if (entry.getKey() == null) continue; + Result records = entry.getValue(); + categoriesLeaders.add( + userTransformer.getEntityFromQueryResult(categoryLeader, records) + ); + } + builder.requirementCreator(categoriesLeaders); + + List requirementCreators = new ArrayList<>(); + for (Map.Entry> entry : queryResult.intoGroups(requirementCreator.ID).entrySet()) { + if (entry.getKey() == null) continue; + Result records = entry.getValue(); + requirementCreators.add( + userTransformer.getEntityFromQueryResult(requirementCreator, records) + ); + } + builder.requirementCreator(requirementCreators); + + List leadDevelopers = new ArrayList<>(); + for (Map.Entry> entry : queryResult.intoGroups(leadDeveloper.ID).entrySet()) { + if (entry.getKey() == null) continue; + Result records = entry.getValue(); + leadDevelopers.add( + userTransformer.getEntityFromQueryResult(leadDeveloper, records) + ); + } + builder.leadDeveloper(leadDevelopers); + + List developers = new ArrayList<>(); + for (Map.Entry> entry : queryResult.intoGroups(developer.ID).entrySet()) { + if (entry.getKey() == null) continue; + Result records = entry.getValue(); + developers.add( + userTransformer.getEntityFromQueryResult(developer, records) + ); + } + builder.developers(developers); + + List commentCreators = new ArrayList<>(); + for (Map.Entry> entry : queryResult.intoGroups(commentCreator.ID).entrySet()) { + if (entry.getKey() == null) continue; + Result records = entry.getValue(); + commentCreators.add( + userTransformer.getEntityFromQueryResult(commentCreator, records) + ); + } + builder.commentCreator(commentCreators); + + List attachmentCreators = new ArrayList<>(); + for (Map.Entry> entry : queryResult.intoGroups(attachmentCreator.ID).entrySet()) { + if (entry.getKey() == null) continue; + Result records = entry.getValue(); + attachmentCreators.add( + userTransformer.getEntityFromQueryResult(attachmentCreator, records) + ); + } + builder.attachmentCreator(attachmentCreators); + + contributors = builder.build(); + + } catch (Exception e) { + ExceptionHandler.getInstance().convertAndThrowException(e, ExceptionLocation.REPOSITORY, ErrorCode.UNKNOWN); + } + return contributors; } @Override diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/exception/BazaarException.java b/src/main/de/rwth/dbis/acis/bazaar/service/exception/BazaarException.java index a61c9fac..ab491776 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/exception/BazaarException.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/exception/BazaarException.java @@ -20,7 +20,6 @@ package de.rwth.dbis.acis.bazaar.service.exception; -import com.google.gson.annotations.Expose; import de.rwth.dbis.acis.bazaar.service.internalization.Localization; /** @@ -28,11 +27,11 @@ * @since 10/6/2014 */ public class BazaarException extends Exception { - @Expose + private String message; - @Expose + private ErrorCode errorCode; - @Expose + private final ExceptionLocation location; protected BazaarException(ExceptionLocation location) { diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/exception/ExceptionHandler.java b/src/main/de/rwth/dbis/acis/bazaar/service/exception/ExceptionHandler.java index 8ac5c09c..57a88444 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/exception/ExceptionHandler.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/exception/ExceptionHandler.java @@ -20,8 +20,10 @@ package de.rwth.dbis.acis.bazaar.service.exception; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import de.rwth.dbis.acis.bazaar.service.internalization.Localization; import jodd.vtor.Violation; @@ -39,6 +41,8 @@ public static ExceptionHandler getInstance() { return INSTANCE; } + ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL); + public BazaarException convert(Exception ex, ExceptionLocation location, ErrorCode errorCode, String message) { BazaarException bazaarException = new BazaarException(location); bazaarException.setErrorCode(errorCode); @@ -59,10 +63,12 @@ public void convertAndThrowException(BazaarException bazaarEx) throws BazaarExce } public String toJSON(BazaarException exception) { - GsonBuilder builder = new GsonBuilder(); - builder.excludeFieldsWithoutExposeAnnotation(); - final Gson gson = builder.create(); - return gson.toJson(exception); + try { + return mapper.writeValueAsString(exception); + } catch (JsonProcessingException e) { + // no important error + } + return null; } public void handleViolations(List violations) throws BazaarException { diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/notification/ActivityDispatcher.java b/src/main/de/rwth/dbis/acis/bazaar/service/notification/ActivityDispatcher.java index e195da2f..16640aae 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/notification/ActivityDispatcher.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/notification/ActivityDispatcher.java @@ -1,16 +1,19 @@ package de.rwth.dbis.acis.bazaar.service.notification; -import com.google.gson.Gson; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ser.FilterProvider; +import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; +import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; import de.rwth.dbis.acis.bazaar.service.BazaarService; import de.rwth.dbis.acis.bazaar.service.dal.DALFacade; -import de.rwth.dbis.acis.bazaar.service.dal.entities.Activity; -import de.rwth.dbis.acis.bazaar.service.dal.entities.Comment; -import de.rwth.dbis.acis.bazaar.service.dal.entities.Category; -import de.rwth.dbis.acis.bazaar.service.dal.entities.Requirement; +import de.rwth.dbis.acis.bazaar.service.dal.entities.*; import de.rwth.dbis.acis.bazaar.service.exception.ErrorCode; import de.rwth.dbis.acis.bazaar.service.exception.ExceptionHandler; import de.rwth.dbis.acis.bazaar.service.exception.ExceptionLocation; import i5.las2peer.api.Service; +import i5.las2peer.logging.L2pLogger; + import javax.ws.rs.core.Response; import java.io.Serializable; @@ -21,11 +24,12 @@ */ public class ActivityDispatcher { - private BazaarService bazaarService; + private final L2pLogger logger = L2pLogger.getInstance(ActivityDispatcher.class.getName()); private final String activityTrackerService; private final String activityOrigin; private final String baseURL; private final String frontendBaseURL; + private BazaarService bazaarService; public ActivityDispatcher(BazaarService bazaarService, String activityTrackerService, String activityOrigin, String baseURL, String frontendBaseURL) { this.bazaarService = bazaarService; @@ -35,14 +39,12 @@ public ActivityDispatcher(BazaarService bazaarService, String activityTrackerSer this.frontendBaseURL = frontendBaseURL; } - public void sendActivityOverRMI(Service service, Date creationDate, Activity.ActivityAction activityAction, - int dataId, Activity.DataType dataType, int parentDataId, - Activity.DataType parentDataTyp, int userId) { + public void sendActivityOverRMI(Date creationDate, Activity.ActivityAction activityAction, + int dataId, Activity.DataType dataType, int userId, Activity.AdditionalObject additionalObject) { DALFacade dalFacade; try { dalFacade = bazaarService.getDBConnection(); - Gson gson = new Gson(); Activity.Builder activityBuilder = Activity.getBuilder(); activityBuilder = activityBuilder.creationDate(creationDate); activityBuilder = activityBuilder.activityAction(activityAction); @@ -50,6 +52,9 @@ public void sendActivityOverRMI(Service service, Date creationDate, Activity.Act String resourcePath = new String(); String parentResourcePath = null; String frontendResourcePath = new String(); + int parentDataId = 0; + Activity.DataType parentDataTyp = null; + if (dataType.equals(Activity.DataType.PROJECT)) { resourcePath = "projects"; frontendResourcePath = "projects" + "/" + String.valueOf(dataId); @@ -58,12 +63,16 @@ public void sendActivityOverRMI(Service service, Date creationDate, Activity.Act parentResourcePath = "projects"; Category category = dalFacade.getCategoryById(dataId, userId); frontendResourcePath = "projects" + "/" + category.getProjectId() + "/" + "categories" + "/" + String.valueOf(dataId); + parentDataId = category.getProjectId(); + parentDataTyp = Activity.DataType.PROJECT; } else if (dataType.equals(Activity.DataType.REQUIREMENT)) { resourcePath = "requirements"; parentResourcePath = "categories"; Requirement requirement = dalFacade.getRequirementById(dataId, userId); frontendResourcePath = "projects" + "/" + requirement.getProjectId() + "/" + "categories" + "/" + requirement.getCategories().get(0).getId() + "/" + "requirements" + "/" + String.valueOf(dataId); + parentDataId = requirement.getCategories().get(0).getId(); + parentDataTyp = Activity.DataType.CATEGORY; } else if (dataType.equals(Activity.DataType.COMMENT)) { resourcePath = "comments"; parentResourcePath = "requirements"; @@ -71,6 +80,17 @@ public void sendActivityOverRMI(Service service, Date creationDate, Activity.Act Requirement requirement = dalFacade.getRequirementById(comment.getRequirementId(), userId); frontendResourcePath = "projects" + "/" + requirement.getProjectId() + "/" + "categories" + "/" + requirement.getCategories().get(0).getId() + "/" + "requirements" + "/" + String.valueOf(requirement.getId()); + parentDataId = requirement.getId(); + parentDataTyp = Activity.DataType.REQUIREMENT; + } else if (dataType.equals(Activity.DataType.ATTACHMENT)) { + resourcePath = "attachments"; + parentResourcePath = "requirements"; + Attachment attachment = dalFacade.getAttachmentById(dataId); + Requirement requirement = dalFacade.getRequirementById(attachment.getRequirementId(), userId); + frontendResourcePath = "projects" + "/" + requirement.getProjectId() + "/" + "categories" + "/" + + requirement.getCategories().get(0).getId() + "/" + "requirements" + "/" + String.valueOf(requirement.getId()); + parentDataId = requirement.getId(); + parentDataTyp = Activity.DataType.REQUIREMENT; } resourcePath = resourcePath + "/" + String.valueOf(dataId); if (parentResourcePath != null) { @@ -89,15 +109,24 @@ public void sendActivityOverRMI(Service service, Date creationDate, Activity.Act } activityBuilder = activityBuilder.userUrl(baseURL + "users" + "/" + String.valueOf(userId)); activityBuilder = activityBuilder.origin(activityOrigin); + activityBuilder = activityBuilder.addititionalObject(additionalObject); Activity activity = activityBuilder.build(); - Object result = service.getContext().invoke(activityTrackerService, "createActivity", new Serializable[]{gson.toJson(activity)}); + FilterProvider filters = + new SimpleFilterProvider().addFilter( + "ActivityFilter", + SimpleBeanPropertyFilter.filterOutAllExcept("id", "name")); + + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.setFilters(filters); + + Object result = bazaarService.getContext().invoke(activityTrackerService, "createActivity", new Serializable[]{mapper.writeValueAsString(activity)}); if (!(result).equals(new Integer(Response.Status.CREATED.getStatusCode()).toString())) { ExceptionHandler.getInstance().throwException(ExceptionLocation.NETWORK, ErrorCode.RMI_ERROR, "ActivityTracker RMI call failed"); } } catch (Exception ex) { - //TODO log - System.out.println(ex.getMessage()); + logger.warning(ex.getMessage()); } } } diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/notification/EmailDispatcher.java b/src/main/de/rwth/dbis/acis/bazaar/service/notification/EmailDispatcher.java index a2ee0703..d192d96a 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/notification/EmailDispatcher.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/notification/EmailDispatcher.java @@ -34,19 +34,22 @@ public void sendEmailNotification(Date creationDate, Activity.ActivityAction act dalFacade = bazaarService.getDBConnection(); List recipients = new ArrayList<>(); - if (dataType.equals(Activity.DataType.REQUIREMENT)) { + if (dataType.equals(Activity.DataType.PROJECT)) { + recipients = dalFacade.getRecipientListForProject(dataId); + } else if (dataType.equals(Activity.DataType.CATEGORY)) { + recipients = dalFacade.getRecipientListForCategory(dataId); + } else if (dataType.equals(Activity.DataType.REQUIREMENT)) { recipients = dalFacade.getRecipientListForRequirement(dataId); } else if (dataType.equals(Activity.DataType.COMMENT)) { int requirementId = dalFacade.getCommentById(dataId).getRequirementId(); recipients = dalFacade.getRecipientListForRequirement(requirementId); - } else if (dataType.equals(Activity.DataType.CATEGORY)) { - recipients = dalFacade.getRecipientListForCategory(dataId); - } else if (dataType.equals(Activity.DataType.PROJECT)) { - recipients = dalFacade.getRecipientListForProject(dataId); + } else if (dataType.equals(Activity.DataType.ATTACHMENT)) { + int requirementId = dalFacade.getAttachmentById(dataId).getRequirementId(); + recipients = dalFacade.getRecipientListForRequirement(requirementId); } // delete the user who created the activity Iterator recipientsIterator = recipients.iterator(); - while(recipientsIterator.hasNext()) { + while (recipientsIterator.hasNext()) { User recipient = recipientsIterator.next(); if (recipient.getId() == userId) { recipientsIterator.remove(); diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/notification/NotificationDispatcher.java b/src/main/de/rwth/dbis/acis/bazaar/service/notification/NotificationDispatcher.java index daa5b61d..5ebda189 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/notification/NotificationDispatcher.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/notification/NotificationDispatcher.java @@ -1,7 +1,8 @@ package de.rwth.dbis.acis.bazaar.service.notification; +import de.rwth.dbis.acis.bazaar.service.BazaarService; import de.rwth.dbis.acis.bazaar.service.dal.entities.Activity; -import i5.las2peer.api.Service; +import i5.las2peer.logging.NodeObserver; import java.util.Date; @@ -9,8 +10,10 @@ * Created by martin on 15.02.2016. */ public interface NotificationDispatcher { - void dispatchNotification(Service service, Date creationDate, Activity.ActivityAction activityAction, - int dataId, Activity.DataType dataType, int parentDataId, Activity.DataType parentDataType, int userId); + void dispatchNotification(Date creationDate, Activity.ActivityAction activityAction, final NodeObserver.Event mobSOSEvent, + int dataId, Activity.DataType dataType, int userId); + + void setBazaarService(BazaarService service); void setActivityDispatcher(ActivityDispatcher activityDispatcher); diff --git a/src/main/de/rwth/dbis/acis/bazaar/service/notification/NotificationDispatcherImp.java b/src/main/de/rwth/dbis/acis/bazaar/service/notification/NotificationDispatcherImp.java index 157e3888..b80a8777 100644 --- a/src/main/de/rwth/dbis/acis/bazaar/service/notification/NotificationDispatcherImp.java +++ b/src/main/de/rwth/dbis/acis/bazaar/service/notification/NotificationDispatcherImp.java @@ -1,7 +1,17 @@ package de.rwth.dbis.acis.bazaar.service.notification; -import de.rwth.dbis.acis.bazaar.service.dal.entities.Activity; -import i5.las2peer.api.Service; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ser.FilterProvider; +import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; +import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; +import de.rwth.dbis.acis.bazaar.service.BazaarService; +import de.rwth.dbis.acis.bazaar.service.dal.DALFacade; +import de.rwth.dbis.acis.bazaar.service.dal.entities.*; +import i5.las2peer.api.Context; +import i5.las2peer.logging.L2pLogger; +import i5.las2peer.logging.NodeObserver; import java.util.Date; import java.util.concurrent.ExecutorService; @@ -12,9 +22,16 @@ */ public class NotificationDispatcherImp implements NotificationDispatcher { + private L2pLogger logger = L2pLogger.getInstance(NotificationDispatcherImp.class.getName()); + private ExecutorService executorService = Executors.newCachedThreadPool(); private ActivityDispatcher activityDispatcher; private EmailDispatcher emailDispatcher; - ExecutorService executorService = Executors.newCachedThreadPool(); + private BazaarService bazaarService; + private ObjectMapper mapper; + + public void setBazaarService(BazaarService service) { + this.bazaarService = service; + } public void setActivityDispatcher(ActivityDispatcher activityDispatcher) { this.activityDispatcher = activityDispatcher; @@ -25,28 +42,85 @@ public void setEmailDispatcher(EmailDispatcher emailDispatcher) { } @Override - public void dispatchNotification(final Service service, final Date creationDate, final Activity.ActivityAction activityAction, - final int dataId, final Activity.DataType dataType, final int parentDataId, - final Activity.DataType parentDataType, final int userId) { -// executorService.execute(new Runnable() { + public void dispatchNotification(final Date creationDate, final Activity.ActivityAction activityAction, final NodeObserver.Event mobSOSEvent, + final int dataId, final Activity.DataType dataType, final int userId) { +// executorService.execute(new Runnable() { //TODO: try to run sendActivityOverRMI inside Runnable when las2peer allows this // public void run() { // if (activityDispatcher != null) { // activityDispatcher.sendActivityOverRMI(service, creationDate, activityAction, dataId, dataType, userId); // } // } // }); - executorService.execute(new Runnable() { - public void run() { - if (emailDispatcher != null && (activityAction == Activity.ActivityAction.CREATE || activityAction == Activity.ActivityAction.UPDATE || - activityAction == Activity.ActivityAction.REALIZE)) { - emailDispatcher.sendEmailNotification(creationDate, activityAction, dataId, dataType, userId); + + FilterProvider filters = + new SimpleFilterProvider().addFilter( + "ActivityFilter", + SimpleBeanPropertyFilter.filterOutAllExcept("id", "name")); + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.setFilters(filters); + + try { + executorService.execute(new Runnable() { + public void run() { + if (emailDispatcher != null && (activityAction == Activity.ActivityAction.CREATE || activityAction == Activity.ActivityAction.UPDATE || + activityAction == Activity.ActivityAction.REALIZE)) { + emailDispatcher.sendEmailNotification(creationDate, activityAction, dataId, dataType, userId); + } } + }); + Activity.AdditionalObject additionalObject = generateAdditionalObject(dataType, dataId, userId); + if (activityDispatcher != null && (activityAction == Activity.ActivityAction.CREATE || activityAction == Activity.ActivityAction.UPDATE || + activityAction == Activity.ActivityAction.REALIZE || activityAction == Activity.ActivityAction.DEVELOP || + activityAction == Activity.ActivityAction.LEADDEVELOP || activityAction == Activity.ActivityAction.FOLLOW || + activityAction == Activity.ActivityAction.VOTE)) { + activityDispatcher.sendActivityOverRMI(creationDate, activityAction, dataId, dataType, userId, additionalObject); + } + if (mobSOSEvent != null) { + L2pLogger.logEvent(mobSOSEvent, Context.getCurrent().getMainAgent(), mapper.writeValueAsString(additionalObject)); } - }); - if (activityDispatcher != null) { - activityDispatcher.sendActivityOverRMI(service, creationDate, activityAction, dataId, dataType, parentDataId, - parentDataType, userId); + } catch (JsonProcessingException e) { + logger.warning(e.getMessage()); } } + private Activity.AdditionalObject generateAdditionalObject(Activity.DataType dataType, int dataId, int userId) { + DALFacade dalFacade; + Activity.AdditionalObject additionalObject = null; + try { + dalFacade = bazaarService.getDBConnection(); + + User user = dalFacade.getUserById(userId); + if (dataType.equals(Activity.DataType.PROJECT) && dataId != 0) { + Project project = dalFacade.getProjectById(dataId, userId); + additionalObject = new Activity.AdditionalObject(project, null, null, user); + } else if (dataType.equals(Activity.DataType.CATEGORY)) { + Category category = dalFacade.getCategoryById(dataId, userId); + Project project = dalFacade.getProjectById(category.getProjectId(), userId); + additionalObject = new Activity.AdditionalObject(project, category, null, user); + } else if (dataType.equals(Activity.DataType.REQUIREMENT)) { + Requirement requirement = dalFacade.getRequirementById(dataId, userId); + Category category = dalFacade.getCategoryById(requirement.getCategories().get(0).getId(), userId); + Project project = dalFacade.getProjectById(requirement.getProjectId(), userId); + additionalObject = new Activity.AdditionalObject(project, category, requirement, user); + } else if (dataType.equals(Activity.DataType.COMMENT)) { + Comment comment = dalFacade.getCommentById(dataId); + Requirement requirement = dalFacade.getRequirementById(comment.getRequirementId(), userId); + Category category = dalFacade.getCategoryById(requirement.getCategories().get(0).getId(), userId); + Project project = dalFacade.getProjectById(requirement.getProjectId(), userId); + additionalObject = new Activity.AdditionalObject(project, category, requirement, user); + } else if (dataType.equals(Activity.DataType.ATTACHMENT)) { + Attachment attachment = dalFacade.getAttachmentById(dataId); + Requirement requirement = dalFacade.getRequirementById(attachment.getRequirementId(), userId); + Category category = dalFacade.getCategoryById(requirement.getCategories().get(0).getId(), userId); + Project project = dalFacade.getProjectById(requirement.getProjectId(), userId); + additionalObject = new Activity.AdditionalObject(project, category, requirement, user); + } else { + additionalObject = new Activity.AdditionalObject(null, null, null, user); + } + } catch (Exception e) { + logger.warning(e.getMessage()); + } + return additionalObject; + } }