diff --git a/services/contest_service_facade/src/java/main/com/topcoder/service/facade/contest/ejb/ContestServiceFacadeBean.java b/services/contest_service_facade/src/java/main/com/topcoder/service/facade/contest/ejb/ContestServiceFacadeBean.java index a37d42c85..a955bcd94 100644 --- a/services/contest_service_facade/src/java/main/com/topcoder/service/facade/contest/ejb/ContestServiceFacadeBean.java +++ b/services/contest_service_facade/src/java/main/com/topcoder/service/facade/contest/ejb/ContestServiceFacadeBean.java @@ -215,49 +215,58 @@ /** *
- * This is an implementation of Contest Service Facade web service in form of stateless session EJB. It
- * holds a reference to {@link StudioService} which is delegated the fulfillment of requests.
+ * This is an implementation of Contest Service Facade web service
+ * in form of stateless session EJB. It holds a reference to
+ * {@link StudioService} which is delegated the fulfillment of requests.
*
- * Module Cockpit Contest Service Enhancement Assembly change: Several new methods related to the permission and - * permission type are added. + * Module Cockpit Contest Service Enhancement Assembly change: Several new + * methods related to the permission and permission type are added. *
*- * Module Cockpit Share Submission Integration Assembly change: Added method to retrieve all permissions by projectId. - * Version 1.0.1 (Cockpit Release Assembly 5 v1.0) Change Notes: - Added method to retrieve contest fees by given - * billing project id.
Version 1.0.2 (Spec Reviews Finishing Touches v1.0) Change Notes: - Made the - * getSpecReviews method return instance of SpecReview rather than a list. - Added the methods to mark ready for review, - * review done and resubmit for review. + * Module Cockpit Share Submission Integration Assembly change: Added method to + * retrieve all permissions by projectId. Version 1.0.1 (Cockpit Release + * Assembly 5 v1.0) Change Notes: - Added method to retrieve contest fees by + * given billing project id. + * + * + * Version 1.0.2 (Spec Reviews Finishing Touches v1.0) Change Notes: - Made the + * getSpecReviews method return instance of SpecReview rather than a list. - + * Added the methods to mark ready for review, review done and resubmit for + * review. + * *- * Version 1.0.3 (Cockpit Software Contest Payments v1.0) Change notes: - For software contest, payment is made for the - * sum of various costs. - While doing so, only the increased amount is paid (if earlier payments were made). - + * Version 1.0.3 (Cockpit Software Contest Payments v1.0) Change notes: - For + * software contest, payment is made for the sum of various costs. - While doing + * so, only the increased amount is paid (if earlier payments were made). - * Introduced constants for new cost types *
** Version 1.0.4 - Add 'Applications'/'Components' to resource for project *
- * -----------------------changed in the version 1.1----------------- - * Four methods are added + * -----------------------changed in the version 1.1----------------- Four + * methods are added * setSubmissionCheckpointPrize(submissionId:long,checkpointPrizeId:long):void * getUserContests(userName:String):List- * Changes in v1.2 (Studio Multi-Rounds Assembly - Launch Contest): Added default checkpoint date when contest is - * created. + * Changes in v1.2 (Studio Multi-Rounds Assembly - Launch Contest): Added + * default checkpoint date when contest is created. *
** Changes in v1.2.1 updated to set creator user as Observer created. *
*- * Changes in v1.2.2 - Cockpit Release Assembly 11 Add method getDesignComponents to get design components. + * Changes in v1.2.2 - Cockpit Release Assembly 11 Add method + * getDesignComponents to get design components. *
*- * Changes in v1.3 (Prototype Conversion Studio Multi-Rounds Assembly - Submission Viewer UI): - Added a flag to - * updateSubmissionUserRank method to support ranking checkpoint submissions. - Added support for checkpoint - * prizes payment. + * Changes in v1.3 (Prototype Conversion Studio Multi-Rounds Assembly - + * Submission Viewer UI): - Added a flag to updateSubmissionUserRank method to + * support ranking checkpoint submissions. - Added support for checkpoint prizes + * payment. *
** Changes in v1.3.1 Added elegibility services. @@ -269,669 +278,816 @@ * Changes in v1.3.3 Added permission check. *
*- * Changes in v1.4 (Cockpit Spec Review Backend Service Update v1.0): - * - Added method to create specification review project for an existing project. - * - Added method to get scorecard and review information for a specific project. - * - Added method to upload a mock submission / final fixes to the associated specification review of a - * project to make it ready for review. - Added method to add comments to an existing review. + * Changes in v1.4 (Cockpit Spec Review Backend Service Update v1.0): - Added + * method to create specification review project for an existing project. - + * Added method to get scorecard and review information for a specific project. + * - Added method to upload a mock submission / final fixes to the associated + * specification review of a project to make it ready for review. - Added method + * to add comments to an existing review. *
*- * Change in v1.4.1 (Cockpit Spec Review -stage 2 v1.0) - * - Add spec review project id - * - After activiation of contests, create spec review project + * Change in v1.4.1 (Cockpit Spec Review -stage 2 v1.0) - Add spec review + * project id - After activiation of contests, create spec review project *
*- * Changes in v1.5 (Cockpit Release Assembly - Contest Repost and New Version v1.0): - * - Added method to re open failed software contest. - * - Added method to create new version for development or design contest. - * - Refactor the create/update-software-contest methods + * Changes in v1.5 (Cockpit Release Assembly - Contest Repost and New Version + * v1.0): - Added method to re open failed software contest. - Added method to + * create new version for development or design contest. - Refactor the + * create/update-software-contest methods *
*- * Changes in v1.5.1(Cockpit Security Facade V1.0): - * - It is not a web-service any more. - * - All the methods accepts a parameter TCSubject which contains all the security info for current user. - * The implementation EJB should use TCSubject and now get these info from the sessionContext. - * - Please use the new ContestServiceFacadeWebService as the facade now. That interface will delegates all the methods - * to it. - * - UserService is used to get the user-name for the given user-id. + * Changes in v1.5.1(Cockpit Security Facade V1.0): - It is not a web-service + * any more. - All the methods accepts a parameter TCSubject which contains all + * the security info for current user. The implementation EJB should use + * TCSubject and now get these info from the sessionContext. - Please use the + * new ContestServiceFacadeWebService as the facade now. That interface will + * delegates all the methods to it. - UserService is used to get the user-name + * for the given user-id. *
*- * Changes in v1.6(Direct Search Assembly v1.0): Adds getProjectData method to return project data with aggregate contest - * information in different status. Change getCommonProjectContestData method to add payment information. + * Changes in v1.6(Direct Search Assembly v1.0): Adds getProjectData method to + * return project data with aggregate contest information in different status. + * Change getCommonProjectContestData method to add payment information. *
*
- * Changes in v1.6.1, two public methods are added (BUGR - 3706):
- * - List
- * Version 1.6.2 (Direct Permissions Setting Back-end and Integration Assembly 1.0) Change notes: - *
* Version 1.6.3 (Direct Submission Viewer Release 4 Assembly 1.0) Change notes: - *
- * Version 1.6.4 (TC Direct - Launch Copilot Selection Contest assembly 1.0) Change notes: - *
* Version 1.6.5 (Manage Copilot Postings Assembly 1.0) Change notes: - *
* Version 1.6.6 (TC Direct Replatforming Release 1) Change notes: *
- * Version 1.6.7 (TC Direct - Permission Updates) Change notes: - *
+ * Version 1.6.7 (TC Direct - Permission Updates) Change notes: + *
- * Version 1.6.8 (TC Direct Replatforming Release 2) Change notes: - *
+ * Version 1.6.8 (TC Direct Replatforming Release 2) Change notes: + *
- * Version 1.6.8 (TC Direct - Software Contest Creation Update) Change notes: - *
createContestResources to create copilot resource and set form permission/watch if exists.updateContestResources to update copilots and update forum permission/watch+ * Version 1.6.8 (TC Direct - Software Contest Creation Update) Change + * notes: + *
createContestResources to create
+ * copilot resource and set form permission/watch if exists.updateContestResources to update
+ * copilots and update forum permission/watch- * Version 1.6.9 (BUGR-4582) Change notes: - *
- * Version 1.7.0 Release Assembly - Direct Improvements Assembly Release 3 Change notes: - *
+ * Version 1.6.9 (BUGR-4582) Change notes: + *
+ * Version 1.7.0 Release Assembly - Direct Improvements Assembly + * Release 3 Change notes: + *
- * Version 1.6.9 (TC Direct Replatforming Release 3) Change notes: - *
+ * Version 1.6.9 (TC Direct Replatforming Release 3) Change notes: + *
- * Version 1.6.10 (TC Direct Replatforming Release 5) Change notes: - *
getCheckpointSubmissions to {@link #getSoftwareActiveSubmissions(long, int)}. The new method
- * support searching the active submissions for a specified submission type.+ * Version 1.6.10 (TC Direct Replatforming Release 5) Change notes: + *
getCheckpointSubmissions
+ * to {@link #getSoftwareActiveSubmissions(long, int)}. The new method
+ * support searching the active submissions for a specified submission
+ * type.- * Version 1.6.11 (TCCC-3153) Change notes: - *
+ * Version 1.6.11 (TCCC-3153) Change notes: + *
- * Version 1.7.1 Release Assembly - TopCoder Cockpit Project Status Management Change notes: - *
+ * Version 1.7.1 Release Assembly - TopCoder Cockpit Project Status + * Management Change notes: + *
- * Version 1.7.2 (TopCoder Cockpit Project Overview R2 Project Forum Backend Assembly 1.0) Change notes: - *
+ * Version 1.7.2 (TopCoder Cockpit Project Overview R2 Project Forum + * Backend Assembly 1.0) Change notes: + *
- * Version 1.7.3 (TCCC-3658) Change notes: - *
+ * Version 1.7.3 (TCCC-3658) Change notes: + *
- * Version 1.7.4 (Add Reporting Contest Type) Change notes: - *
+ * Version 1.7.4 (Add Reporting Contest Type) Change notes: + *
- * Version 1.7.5 (Release Assembly - TopCoder Cockpit DataTables Filter Panel and Search Bar) Change notes: - *
+ * Version 1.7.5 (Release Assembly - TopCoder Cockpit DataTables Filter + * Panel and Search Bar) Change notes: + *
- * Version 1.8.0 (Release Assembly - TC Cockpit Create Project Refactoring Assembly Part One) Change notes: - *
+ * Version 1.8.0 (Release Assembly - TC Cockpit Create Project + * Refactoring Assembly Part One) Change notes: + *
- * Version 1.8.2 (Release Assembly - TC Direct Cockpit Release Two version 1.0) Change notes: - *
+ * Version 1.8.2 (Release Assembly - TC Direct Cockpit Release Two + * version 1.0) Change notes: + *
- * Version 1.8.3 (Release Assembly - TopCoder Bug Hunt Assembly Integration 2) change notes: - *
- * Version 1.8.4 (System Assembly - TopCoder Security Groups Frontend - Permission Propagation Integration) Change notes: - *
- * Version 1.8.4 (Release Assembly - TC Direct Cockpit Release Three version 1.0) - *
- * Version 1.8.5 (Release Assembly - TC Direct Cockpit Release Four version 1.0) - *
+ * Version 1.8.3 (Release Assembly - TopCoder Bug Hunt Assembly + * Integration 2) change notes: + *
+ * Version 1.8.4 (System Assembly - TopCoder Security Groups Frontend - + * Permission Propagation Integration) Change notes: + *
+ * Version 1.8.4 (Release Assembly - TC Direct Cockpit Release Three + * version 1.0) + *
+ * Version 1.8.5 (Release Assembly - TC Direct Cockpit Release Four + * version 1.0) + *
- * Version 1.8.6 (Release Assembly - TC Direct Issue Tracking Tab Update Assembly 2 v1.0) change notes: - *
+ * Version 1.8.6 (Release Assembly - TC Direct Issue Tracking Tab + * Update Assembly 2 v1.0) change notes: + *
- * Version 1.8.6 (Release Assembly - TopCoder Cockpit Project Dashboard Project Type and Permission Notifications Integration) - *
userId argument when update forum notification.
- * - * Version 1.8.7 (Release Assembly - TopCoder Cockpit Software Checkpoint Management) change notes: - *
+ *
+ * Version 1.8.6 (Release Assembly - TopCoder Cockpit Project Dashboard + * Project Type and Permission Notifications Integration) + *
userId argument when update forum notification.+ * Version 1.8.7 (Release Assembly - TopCoder Cockpit Software + * Checkpoint Management) change notes: + *
* - *
- * Version 1.9.0 (Module Assembly - TC Cockpit Project Contests Batch Edit) changes: - *
+ * Version 1.9.0 (Module Assembly - TC Cockpit Project Contests Batch + * Edit) changes: + *
- * Version 1.9.1 (Release Assembly - TopCoder Cockpit Post Software Checkpoint Feedback to Forum v1.0) changes: - *
+ * Version 1.9.1 (Release Assembly - TopCoder Cockpit Post Software + * Checkpoint Feedback to Forum v1.0) changes: + *
- * Version 1.9.2 (Release Assembly - TopCoder Security Groups Release 5 v1.0) changes: - *
+ * Version 1.9.2 (Release Assembly - TopCoder Security Groups Release 5 + * v1.0) changes: + *
- * Version 1.9.3 (Release Assembly - TC Direct Cockpit Release Ten) - *
+ * Version 1.9.3 (Release Assembly - TC Direct Cockpit Release Ten) + *
- * Version 1.9.4 (Release Assembly - TC Cockpit Operations Dashboard Improvements 2) changes: - *
+ * Version 1.9.4 (Release Assembly - TC Cockpit Operations Dashboard + * Improvements 2) changes: + *
- * Version 1.9.5 (BUGR-7954) updates - *
+ * Version 1.9.5 (BUGR-7954) updates + *
- * Version 1.9.6 (Release Assembly - TopCoder Cockpit Copilot Selection Update and Other Fixes Assembly) - *
+ * Version 1.9.6 (Release Assembly - TopCoder Cockpit Copilot Selection + * Update and Other Fixes Assembly) + *
- * Version 1.9.8 (Module Assembly - TC Cockpit - Studio - Final Fixes Integration Part One Assembly) Change notes: - *
+ * Version 1.9.8 (Module Assembly - TC Cockpit - Studio - Final Fixes + * Integration Part One Assembly) Change notes: + *
- * Version 1.9.9 (Module Assembly - TC Cockpit Contest Milestone Association 1) change notes: - *
+ * Version 1.9.9 (Module Assembly - TC Cockpit Contest Milestone + * Association 1) change notes: + *
- * Version 2.0.0 (Module Assembly - TC Cockpit Launch Code contest) - *
+ * Version 2.0.0 (Module Assembly - TC Cockpit Launch Code contest) + *
- * Version 2.0.1 (Module Assembly - TC Cockpit Launch F2F contest) - *
+ * Version 2.0.1 (Module Assembly - TC Cockpit Launch F2F contest) + *
- * Version 2.0.2 (Release Assembly - Publish Event on Contest Creation in TopCoder Cockpit) change notes: - *
+ * Version 2.0.2 (Release Assembly - Publish Event on Contest Creation + * in TopCoder Cockpit) change notes: + *
- * Version 2.1 (Release Assembly - TC Cockpit Private Challenge Update) - *
+ * Version 2.1 (Release Assembly - TC Cockpit Private Challenge Update) + *
- * Version 2.2 (TC Cockpit Auto Assign Reviewer for First2Finish challenge) - *
+ * Version 2.2 (TC Cockpit Auto Assign Reviewer for First2Finish + * challenge) + *
- * Version 2.3 (TC Cockpit CMC Task Update Events Push) - *
+ * Version 2.3 (TC Cockpit CMC Task Update Events Push) + *
- * Version 2.4 (Release Assembly - TC Cockpit New Challenge types Integration Bug Fixes) - *
+ * Version 2.4 (Release Assembly - TC Cockpit New Challenge types + * Integration Bug Fixes) + *
- * Version 2.5 (First2Finish - TC Cockpit Auto Assign Reviewer Update) - *
+ * Version 2.5 (First2Finish - TC Cockpit Auto Assign Reviewer Update) + *
- * Version 2.6 (TC Cockpit Push Amazon SNS event for challenge update) - *
+ * Version 2.6 (TC Cockpit Push Amazon SNS event for challenge update) + *
- * Version 2.7 (F2F - TC Cockpit Create Challenge Auto Add Manager) - *
+ * Version 2.7 (F2F - TC Cockpit Create Challenge Auto Add Manager) + *
- * Version 2.8 (F2F - TC Cockpit Update Bug Hunt type) - *
+ * Version 2.8 (F2F - TC Cockpit Update Bug Hunt type) + *
- * Version 2.9 (F2F - TC Direct - Locate Activate Contest Issue) - *
+ * Version 2.9 (F2F - TC Direct - Locate Activate Contest Issue) + *
- * Version 3.0 (Module Assembly - TC Direct Studio Design First2Finish Challenge Type) - *
+ * Version 3.0 (Module Assembly - TC Direct Studio Design First2Finish + * Challenge Type) + *
- * Version 3.1 (Release Assembly - Port Design Challenge Forum to use Dev Forum) - *
+ * Version 3.1 (Release Assembly - Port Design Challenge Forum to use + * Dev Forum) + *
- * Version 3.2 (TopCoder Direct - Add Appirio Manager) - *
+ * Version 3.2 (TopCoder Direct - Add Appirio Manager) + *
+ * A ContestEligibilityValidationManager providing access to
+ * available Contest Eligibility Validation EJB.
+ *
+ * A ContestEligibilityManager providing access to available
+ * Contest Eligibility Persistence EJB.
+ *
+ * A CatalogService providing access to available
+ * Category Services EJB. This bean is delegated to process the
+ * calls to the methods inherited from Category Services component.
+ *
+ * A ProjectServices providing access to available
+ * Project Services EJB. This bean is delegated to process the
+ * calls to the methods inherited from Project Services component.
+ *
+ * A PermissionService providing access to available
+ * Permission Service EJB. This bean is delegated to process the
+ * calls for CRUD on permissions.
+ *
+ * A UserService providing access to available
+ * User Service EJB.
+ *
+ * A SpecReviewService providing access to available
+ * Spec Review Service. This bean is delegated to process the calls
+ * for CRUD spec reviews.
+ *
+ * A ProjectDAO providing access to available billing project
+ * related methods like retrieving contest fee for given billing project.
+ *
+ * A ProjectService providing access to project service.
+ *
+ * A PermissionServiceFacade providing access to permission related
+ * methods.
+ *
+ * A SpecificationReviewService providing access to contest
+ * specification review related methods.
+ *
+ * A PaymentProcessor instance of payment processor implementing
+ * class. All payment requests are processed through this instance.
+ *
+ * A UploadExternalServices instance of Online Review Upload
+ * Services to expose its methods.
+ *
+ * Represents the sessionContext of the ejb. + *
+ */ + @Resource + private SessionContext sessionContext; + + /** + * Document manager config file location. + * + * @since Cockpit Release Assembly for Receipts + */ + @Resource(name = "documentManagerConfigFile") + private String documentManagerConfigFile; + + /** + * Email template file path for Activate Contest Receipt. + * + * @since Cockpit Release Assembly for Receipts + */ + @Resource(name = "activateContestReceiptEmailTemplatePath") + private String activateContestReceiptEmailTemplatePath; + + /** + * BCC Address for Activate Contest Receipt Email + * + * @since Cockpit Release Assembly for Receipts + */ + @Resource(name = "activateContestReceiptEmailBCCAddr") + private String activateContestReceiptEmailBCCAddr; + + /** + * From Address for Activate Contest Receipt Email + * + * @since Cockpit Release Assembly for Receipts + */ + @Resource(name = "activateContestReceiptEmailFromAddr") + private String activateContestReceiptEmailFromAddr; + + /** + * Subject line for Activate Contest Receipt Email + * + * @since Cockpit Release Assembly for Receipts + */ + @Resource(name = "activateContestReceiptEmailSubject") + private String activateContestReceiptEmailSubject; + + /** + * Email template file path for copilot winner email. + * + * @since 1.8.5 + */ + @Resource(name = "copilotWinnerEmailTemplatePath") + private String copilotWinnerEmailTemplatePath; + + /** + * BCC Address for copilot winner email. + * + * @since 1.8.5 + */ + @Resource(name = "copilotWinnerEmailBCCAddr") + private String copilotWinnerEmailBCCAddr; + + /** + * From Address for copilot winner email. + * + * @since 1.8.5 + */ + @Resource(name = "copilotWinnerEmailFromAddr") + private String copilotWinnerEmailFromAddr; + + /** + * Subject line for copilot winner email. + * + * @since 1.8.5 + */ + @Resource(name = "copilotWinnerEmailSubject") + private String copilotWinnerEmailSubject; + + /** + * Contains all the contest type ids need custom contest activation email + * template, the ids are separated with ';' and configured in ejb-jar.xml. + * + * @since 1.8.4 + */ + @Resource(name = "customActivateContestReceiptContestTypeIds") + private String customActivateContestReceiptContestTypeIds; + + /** + * Contains all the custom contest activation email template paths, map to the + * ids configured incustomActivateContestReceiptContestTypeIds.
+ * The paths are separated with ';' and configured in ejb-jar.xml
+ *
+ * @since 1.8.4
+ */
+ @Resource(name = "customActivateContestReceiptEmailTemplatePaths")
+ private String customActivateContestReceiptEmailTemplatePaths;
+
+ /**
+ * Email template file path for Spec Review Notification Email
+ *
+ * @since 1.0.2
+ */
+ @Resource(name = "specReviewNotificationEmailTemplatePath")
+ private String specReviewNotificationEmailTemplatePath;
+
+ /**
+ * BCC Address for Spec Review Notification Email
+ *
+ * @since 1.0.2
+ */
+ @Resource(name = "specReviewNotificationEmailBCCAddr")
+ private String specReviewNotificationEmailBCCAddr;
+
+ /**
+ * From Address for Spec Review Notification Email
+ *
+ * @since 1.0.2
+ */
+ @Resource(name = "specReviewNotificationEmailFromAddr")
+ private String specReviewNotificationEmailFromAddr;
+
+ /**
+ * Subject line for Spec Review Notification Email
+ *
+ * @since 1.0.2
+ */
+ @Resource(name = "specReviewNotificationEmailSubject")
+ private String specReviewNotificationEmailSubject;
+
+ /**
+ * The default prize for spec reviews
+ *
+ * @since 1.4
+ */
+ @Resource(name = "specReviewPrize")
+ private Double specReviewPrize;
+
+ /**
+ * The mock file path to use for submissions
+ *
+ * @since 1.4
+ */
+ private String mockSubmissionFilePath;
+
+ /**
+ * The mock file name to use for submissions
+ *
+ * @since 1.4
+ */
+ @Resource(name = "mockSubmissionFileName")
+ private String mockSubmissionFileName;
+
+ /**
+ * Document generator that stores email templates.
+ *
+ * @since Cockpit Release Assembly for Receipts
+ */
+ private DocumentGenerator documentGenerator;
+
+ /**
+ * Email generator that generates email message from given template.
+ *
+ * @since Cockpit Release Assembly for Receipts
+ */
+ private EmailMessageGenerator emailMessageGenerator;
+
+ /**
+ * UploadManager instance which is used to get submission information.
+ *
+ * @since BUGR-3738
+ */
+ private UploadManager uploadManager;
+
+ /**
+ * Project Manager instance which is used to perform level contest related
+ * operations.
+ *
+ * @since 1.9.2
+ */
+ private ProjectManager projectManager;
+
+ /**
+ * user id for Applications
+ *
+ * @since 1.0.4
+ */
+ private long applications_user_id;
+
+ /**
+ * user id for Components
+ *
+ * @since 1.0.4
+ */
+ private long components_user_id;
+
+ /**
+ * The logger instance for logging the information in ContestServiceFacadeBean.
+ *
+ * @since 1.1
+ */
+ private Logger logger = Logger.getLogger(this.getClass());
+
+ /**
+ * + * The lookup DAO. + *
+ */ + private LookupDAO lookupDAO; + + /** + *+ * The copilot project DAO. + *
+ */ + private CopilotProjectDAO copilotProjectDAO; + + private CopilotProfileDAO copilotProfileDAO; + + /** + * The helper map stores the mapping of contest type id to custom contset + * activation email template path. It's initialized in the init() method. + * + * @since 1.8.4 + */ + private Map
+ * Constructs new ContestServiceFacadeBean instance. This
+ * implementation instantiates new instance of payment processor. Current
+ * implementation just support processing through PayPalCreditCard. When
+ * multiple processors are desired the implementation should use factory design
+ * pattern to get the right instance of the payment processor.
+ *
+ * This initializes the API Profile to the CallerServices. The API
+ * profile are the merchant's (in this case TopCoder) PayPal API details.
+ *
+ * TopCoder Service Layer Integration 3 Assembly change: new instance of the + * DefaultUploadServices for exposing its methods. + *
+ * + *+ * Updated for Cockpit Release Assembly for Receipts - documentGenerator and + * emailMessageGenerator instance created. + *
+ * + *+ * Updated in version 1.8.4: - Add the codes to load custom contest type id - + * custom contest acativation email template path mapping from the ejb + * configuration. + *
+ * + * @throws IllegalStateException it throws this exception on any issues during + * caller services initialization. Issues can be: + * wrong authentication information, invalid + * information etc. + */ + @PostConstruct + public void init() { + if (logger == null) { + logger = Logger.getLogger(this.getClass()); + } + + logger.debug("Initializing PayflowProPaymentProcessor"); + + ConfigManager configManager = ConfigManager.getInstance(); + + try { + Property payflowProPaymentProcessorProp = configManager.getPropertyObject(DEFAULT_NAMESAPCE, + "PayflowProPaymentProcessor"); + String payFlowHostAddress = payflowProPaymentProcessorProp.getValue("payFlowHostAddress"); + String payFlowUser = payflowProPaymentProcessorProp.getValue("payFlowUser"); + String payFlowPartner = payflowProPaymentProcessorProp.getValue("payFlowPartner"); + String payFlowVendor = payflowProPaymentProcessorProp.getValue("payFlowVendor"); + String payFlowPassword = payflowProPaymentProcessorProp.getValue("payFlowPassword"); + paymentProcessor = new PayflowProPaymentProcessor(payFlowHostAddress, payFlowUser, payFlowPartner, payFlowVendor, + payFlowPassword); + } catch (ConfigManagerException e) { + throw new IllegalStateException("Failed to create the PayflowProPaymentProcessor instance.", e); + } + + try { + String createForumProp = configManager.getString(DEFAULT_NAMESAPCE, "createForum"); + + createForum = Boolean.parseBoolean(createForumProp); + + softwareForumBeanProviderUrl = configManager.getString(DEFAULT_NAMESAPCE, "forumBeanProviderUrl"); + + studioForumBeanProviderUrl = configManager.getString(DEFAULT_NAMESAPCE, "studioForumBeanProviderUrl"); + + userBeanProviderUrl = configManager.getString(DEFAULT_NAMESAPCE, "userBeanProviderUrl"); + + projectBeanProviderUrl = configManager.getString(DEFAULT_NAMESAPCE, "projectBeanProviderUrl"); + + mockSubmissionFilePath = configManager.getString(DEFAULT_NAMESAPCE, "mockSubmissionFilePath"); + + studioForumRootCategoryId = Long + .parseLong(configManager.getString(DEFAULT_NAMESAPCE, "studioForumRootCategoryId")); + + } catch (ConfigManagerException e) { + throw new IllegalStateException("Unable to read property from config file", e); + } + + // TopCoder Service Layer Integration 3 Assembly + try { + uploadExternalServices = new DefaultUploadExternalServices(); + } catch (ConfigurationException e) { + throw new IllegalStateException("Failed to create the DefaultUploadExternalServices instance.", e); + } + + try { + documentGenerator = getDocumentGenerator(); + } catch (ConfigurationException e) { + throw new IllegalStateException("Failed to create the documentGenerator instance.", e); + } + + // the default email message generator. + emailMessageGenerator = new DefaultEmailMessageGenerator(); + + try { + components_user_id = userService.getUserId(RESOURCE_INFO_HANDLE_COMPONENTS); - /** - * Private contest specifying the notification type of Contest Timeline Notification. - */ - private static final long TIMELINE_NOTIFICATION_TYPE = 1; - - /** - * Private constant specifying active & public status id. - * - * @since Module Contest Service Software Contest Sales Assembly - */ - private static final long CONTEST_SALE_STATUS_PAID = 1; - - /** - * Private constant specifying active & public status id. - * - * @since Module Contest Service Software Contest Sales Assembly - */ - private static final long SALE_TYPE_PAYPAL_PAYFLOW = 1; - - /** - * Private constant specifying active & public status id. - * - * @since Module Contest Service Software Contest Sales Assembly - */ - private static final long SALE_TYPE_TC_PURCHASE_ORDER = 2; + applications_user_id = userService.getUserId(RESOURCE_INFO_HANDLE_APPLICATIONS); + } catch (UserServiceException e) { + throw new IllegalStateException("Failed to get components/applications user id.", e); + } - /** - * Private constant specifying resource ext ref id - * - * @since Flex Cockpit Launch Contest - Integrate Software Contests v1.0 - */ - private static final String RESOURCE_INFO_EXTERNAL_REFERENCE_ID = "External Reference ID"; + // BUGR-3738 : initialize an UploadManager instance through Object Factory + try { + ObjectFactory objectFactory = new ObjectFactory( + new ConfigManagerSpecificationFactory(this.objectFactoryConfigManagerSpecName)); + this.uploadManager = (UploadManager) objectFactory.createObject(this.uploadManagerOFKey); - /** - * Private constant specifying resource handle - * - * @since Flex Cockpit Launch Contest - Integrate Software Contests v1.0 - */ - private static final String RESOURCE_INFO_HANDLE = "Handle"; + } catch (Exception ex) { + throw new IllegalStateException("Failed to initialize UploadManager through Object Factory.", ex); + } - /** - * Private constant specifying resource handle - * - * @since Flex Cockpit Launch Contest - Integrate Software Contests v1.0 - */ - private static final String RESOURCE_INFO_HANDLE_APPLICATIONS = "Applications"; + try { + // initialize the project manager instance + ObjectFactory objectFactory = new ObjectFactory( + new ConfigManagerSpecificationFactory(this.objectFactoryConfigManagerSpecName)); - /** - * Private constant specifying resource handle - * - * @since 1.0.4 - */ - private static final String RESOURCE_INFO_HANDLE_COMPONENTS = "Components"; + this.projectManager = (ProjectManager) objectFactory.createObject(this.projectManagerOFKey); + } catch (Exception ex) { + throw new IllegalStateException("Failed to initialize ProjectManager through Object Factory.", ex); + } - /** - * Private constant specifying resource payment anout. - * @since 1.8.3 - */ - private static final String RESOURCE_INFO_PAYMENT = "Payment"; + Configuration configuration = new AnnotationConfiguration().configure("/META-INF/hibernate.cfg.xml"); - /** - * Private constant specifying resource pay - * - * @since Flex Cockpit Launch Contest - Integrate Software Contests v1.0 - */ - private static final String RESOURCE_INFO_PAYMENT_STATUS = "Payment Status"; + LookupDAOImpl ldao = new LookupDAOImpl(); + ldao.setLoggerName("copilotBaseDAO"); + ldao.setSessionFactory(configuration.buildSessionFactory()); + lookupDAO = ldao; - /** - * Private constant specifying registration date - * - */ - private static final String RESOURCE_INFO_REGISTRATION_DATE = "Registration Date"; + CopilotProjectDAOImpl c = new CopilotProjectDAOImpl(); + c.setLoggerName("copilotBaseDAO"); + c.setSessionFactory(configuration.buildSessionFactory()); + copilotProjectDAO = c; - /** - * Private constant specifying resource pay - * - * @since Flex Cockpit Launch Contest - Integrate Software Contests v1.0 - */ - private static final String RESOURCE_INFO_PAYMENT_STATUS_NA = "N/A"; + CopilotProfileDAOImpl cp = new CopilotProfileDAOImpl(); + cp.setLoggerName("copilotBaseDAO"); + cp.setSessionFactory(configuration.buildSessionFactory()); + copilotProfileDAO = cp; - /** - * Private contest specifiy the N/A payment - * @since 1.8.3 - */ - private static final String RESOURCE_INFO_PAYMENT_NA = "N/A"; + // intialize the custom activate email template path map + this.customContestActivationEmailTempaltes = new HashMap+ * Checks if the login user is of given role + *
+ * + * @param tcSubject TCSubject instance for login user + * @return true if it is given role + */ + private static boolean isRole(TCSubject tcSubject, String roleName) { + Set+ * Get the user-name for current login user represented by tcSubject. + *
+ * + * @param tcSubject TCSubject instance for login user + * @return user name + * @throws ContestServiceException fail to retrieve user-name + */ + private String getUserName(TCSubject tcSubject) throws ContestServiceException { + try { + return this.userService.getUserHandle(tcSubject.getUserId()); + } catch (Exception e) { + throw new ContestServiceException("Fail to get the user-name by user-id" + tcSubject.getUserId(), e); + } + } + + /** + *
+ * Converts specified XMLGregorianCalendar instance into
+ * Date instance.
+ *
XMLGregorianCalendar representing the date to
+ * be converted.
+ * @return a Date providing the converted value of specified
+ * calendar or null if specified calendar is
+ * null.
+ */
+ private Date getDate(XMLGregorianCalendar calendar) {
+ if (calendar == null) {
+ return null;
+ }
+
+ return calendar.toGregorianCalendar().getTime();
+ }
+
+ /**
+ *
+ * Converts specified Date instance into
+ * XMLGregorianCalendar instance.
+ *
Date representing the date to be converted.
+ * @return a XMLGregorianCalendar providing the converted value of
+ * specified date or null if specified date is
+ * null or if it can't be converted to calendar.
+ */
+ private XMLGregorianCalendar getXMLGregorianCalendar(Date date) {
+ if (date == null) {
+ return null;
+ }
+
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.setTime(date);
+
+ try {
+ return DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);
+ } catch (DatatypeConfigurationException ex) {
+ return null;
+ }
+ }
+
+ /**
+ * + * Processes the contest sale. + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for + * the current user + * @param competition data that recognizes a contest. + * @param paymentData payment information (credit card/po details) that need to + * be processed. + * @return aSoftwareContestPaymentResult result of the payment
+ * processing.
+ * @throws ContestServiceException if an error occurs when interacting with the
+ * service layer.
+ * @since Module Contest Service Software Contest Sales Assembly
+ * @since BUGR-1682 changed return value
+ */
+ public SoftwareContestPaymentResult processContestCreditCardSale(TCSubject tcSubject, SoftwareCompetition competition,
+ CreditCardPaymentData paymentData) throws ContestServiceException, PermissionServiceException {
+ logger.debug("processContestCreditCardSale");
+
+ return processContestSaleInternal(tcSubject, competition, paymentData, null, null, null);
+ }
+
+ /**
+ * + * Processes the contest sale. + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info + * for the current user + * @param competition data that recognizes a contest. + * @param paymentData payment information (credit card/po details) that + * need to be processed. + * @param multiRoundEndDate the end date for the multiround phase. No multiround + * if it's null. + * @param endDate the end date for submission phase. Can be null if to + * use default. + * @return aSoftwareContestPaymentResult result of the payment
+ * processing.
+ * @throws ContestServiceException if an error occurs when interacting with the
+ * service layer.
+ * @since Module Contest Service Software Contest Sales Assembly
+ * @since 1.6.6
+ */
+ public SoftwareContestPaymentResult processContestCreditCardSale(TCSubject tcSubject, SoftwareCompetition competition,
+ CreditCardPaymentData paymentData, Date multiRoundEndDate, Date endDate)
+ throws ContestServiceException, PermissionServiceException {
+ logger.debug("processContestCreditCardSale");
+
+ return processContestSaleInternal(tcSubject, competition, paymentData, null, multiRoundEndDate, endDate);
+ }
+
+ /**
+ * + * Processes the contest sale. + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for + * the current user + * @param competition data that recognizes a contest. + * @param paymentData payment information (credit card/po details) that need to + * be processed. + * @return aSoftwareContestPaymentResult result of the payment
+ * processing.
+ * @throws ContestServiceException if an error occurs when interacting with the
+ * service layer.
+ * @since Module Contest Service Software Contest Sales Assembly
+ * @since BUGR-1682 changed return value
+ */
+ public SoftwareContestPaymentResult processContestPurchaseOrderSale(TCSubject tcSubject,
+ SoftwareCompetition competition, TCPurhcaseOrderPaymentData paymentData)
+ throws ContestServiceException, PermissionServiceException {
+ logger.debug("processPurchaseOrderSale");
+
+ return processContestSaleInternal(tcSubject, competition, paymentData, null, null, null);
+ }
+
+ /**
+ * + * Processes the contest sale. + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info + * for the current user + * @param competition data that recognizes a contest. + * @param paymentData payment information (credit card/po details) that + * need to be processed. + * @param multiRoundEndDate the end date for the multiround phase. No multiround + * if it's null. + * @param endDate the end date for submission phase. Can be null if to + * use default. + * @return aSoftwareContestPaymentResult result of the payment
+ * processing.
+ * @throws ContestServiceException if an error occurs when interacting with the
+ * service layer.
+ * @since Module Contest Service Software Contest Sales Assembly
+ * @since 1.6.6
+ */
+ public SoftwareContestPaymentResult processContestPurchaseOrderSale(TCSubject tcSubject,
+ SoftwareCompetition competition, TCPurhcaseOrderPaymentData paymentData, Date multiRoundEndDate, Date endDate)
+ throws ContestServiceException, PermissionServiceException {
+ logger.debug("processPurchaseOrderSale");
+
+ return processContestSaleInternal(tcSubject, competition, paymentData, null, multiRoundEndDate, endDate);
+ }
+
+ /**
+ * + * Processes the contest sale. + *
+ * + * @param tcSubject TCSubject instance contains the login security info + * for the current user + * @param competition data that recognizes a contest. + * @param paymentData payment information (credit card/po details) that + * need to be processed. + * @param multiRoundEndDate the end date for registration phase. + * @param multiRoundEndDate the end date for the multiround phase. No multiround + * if it's null. + * @param endDate the end date for submission phase. Can be null if to + * use default. + * @return aSoftwareContestPaymentResult result of the payment
+ * processing.
+ * @throws ContestServiceException if an error occurs when interacting with the
+ * service layer.
+ * @since Module Contest Service Software Contest Sales Assembly
+ * @since 3.10
+ */
+ public SoftwareContestPaymentResult processContestPurchaseOrderSale(TCSubject tcSubject,
+ SoftwareCompetition competition, TCPurhcaseOrderPaymentData paymentData, Date regEndDate, Date multiRoundEndDate,
+ Date endDate) throws ContestServiceException, PermissionServiceException {
+ logger.debug("processPurchaseOrderSale");
+
+ return processContestSaleInternal(tcSubject, competition, paymentData, regEndDate, multiRoundEndDate, endDate);
+ }
+
+ /**
+ * + * Processes the contest sale, activate the contest and start the specification + * review of the contest. + *
+ * + * @param tcSubject TCSubject instance contains the login security info + * for the current user + * @param competition data that recognizes a contest. + * @param paymentData payment information (TCSubject tcSubject,credit + * card/po details) that need to be processed. + * @param multiRoundEndDate the end date for the multiround phase. No + * multiround if it's null. + * @param endDate the end date for submission phase. Can be null if + * to use default. + * @param startSpecReviewNow the flag whether to start spec review now. + * @return aPaymentResult result of the payment processing.
+ * @throws ContestServiceException if an error occurs when
+ * interacting with the service
+ * layer.
+ * @throws PermissionServiceException if there is error when assigning
+ * permission to user.
+ * @throws SpecificationReviewServiceException if fail to start the spec review
+ * of the contest.
+ * @since 1.8.5
+ */
+ public SoftwareContestPaymentResult purchaseActivateContestAndStartSpecReview(TCSubject tcSubject,
+ SoftwareCompetition competition, TCPurhcaseOrderPaymentData paymentData, Date multiRoundEndDate, Date endDate,
+ boolean startSpecReviewNow)
+ throws ContestServiceException, PermissionServiceException, SpecificationReviewServiceException {
+ return purchaseActivateContestAndStartSpecReview(tcSubject, competition, paymentData, null, multiRoundEndDate,
+ endDate, startSpecReviewNow);
+ }
+
+ /**
+ * + * Processes the contest sale, activate the contest and start the specification + * review of the contest. + *
+ * + * @param tcSubject TCSubject instance contains the login security info + * for the current user + * @param competition data that recognizes a contest. + * @param paymentData payment information (TCSubject tcSubject,credit + * card/po details) that need to be processed. + * @param regEndDate the end date for registration phase. + * @param multiRoundEndDate the end date for the multiround phase. No + * multiround if it's null. + * @param endDate the end date for submission phase. Can be null if + * to use default. + * @param startSpecReviewNow the flag whether to start spec review now. + * @return aPaymentResult result of the payment processing.
+ * @throws ContestServiceException if an error occurs when
+ * interacting with the service
+ * layer.
+ * @throws PermissionServiceException if there is error when assigning
+ * permission to user.
+ * @throws SpecificationReviewServiceException if fail to start the spec review
+ * of the contest.
+ * @since 3.10
+ */
+ public SoftwareContestPaymentResult purchaseActivateContestAndStartSpecReview(TCSubject tcSubject,
+ SoftwareCompetition competition, TCPurhcaseOrderPaymentData paymentData, Date regEndDate, Date multiRoundEndDate,
+ Date endDate, boolean startSpecReviewNow)
+ throws ContestServiceException, PermissionServiceException, SpecificationReviewServiceException {
+
+ // purchase the contest and activate it
+ final SoftwareContestPaymentResult softwareContestPaymentResult = processContestSaleInternal(tcSubject, competition,
+ paymentData, regEndDate, multiRoundEndDate, endDate);
+
+ // check if the contest has specification review phase
+ final Set+ * Processes the contest sale. + *
+ *+ * Updated for Cockpit Release Assembly for Receipts - Added code snippet to + * send email receipts on successful purchase. + *
+ *+ * Updated for Version 1.0.3 - For software contest, payment is made for the sum + * of various costs. - While doing so, only the increased amount is paid (if + * earlier payments were made). + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + *+ * Updates in 1.8.4: - Check the DR flag before adding DR points to the total + * cost - Fix the total member cost and total cost, they should be different. + * Total cost = total member cost + admin fee - Add the logics to dynamic load + * activation email tempalte according to the contest type + *
+ * + * + * @param tcSubject TCSubject instance contains the login security info + * for the current user + * @param competition data that recognizes a contest. + * @param paymentData payment information (credit card/po details) that + * need to be processed. + * @param regEndDate the end date for registration phase. + * @param multiRoundEndDate the end date for the multiround phase. No multiround + * if it's null. + * @param endDate the end date for submission phase. Can be null if to + * use default. + * @return aSoftwareContestPaymentResult result of the payment
+ * processing.
+ * @throws ContestServiceException if an error occurs when interacting with the
+ * service layer.
+ * @since Module Contest Service Software Contest Sales Assembly
+ * @since BUGR-1682 changed return value
+ */
+ private SoftwareContestPaymentResult processContestSaleInternal(TCSubject tcSubject, SoftwareCompetition competition,
+ PaymentData paymentData, Date regEndDate, Date multiRoundEndDate, Date endDate)
+ throws ContestServiceException, PermissionServiceException {
+ logger.info("SoftwareCompetition: " + competition);
+ logger.info("PaymentData: " + paymentData);
+ logger.info("tcSubject: " + tcSubject.getUserId());
+ logger.info("multiRoundEndDate: " + multiRoundEndDate);
+
+ SoftwareContestPaymentResult softwareContestPaymentResult = null;
+
+ PaymentResult result = null;
+
+ try {
+ long contestId = competition.getProjectHeader().getId();
+ double pastPayment = 0;
+ boolean hasContestSaleData = false;
+ long contestSaleId = 0L;
+
+ SoftwareCompetition tobeUpdatedCompetition = null;
+
+ if (contestId > 0) { // BUGR-1682
+ tobeUpdatedCompetition = this.getSoftwareContestByProjectId(tcSubject, contestId); // BUGR-1682
+
+ // calculate the past payment to calculate the differential cost.
+ List
+ * Returns a list containing all active Categories.
+ *
+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @return a list containing all activeCategories. It can be empty
+ * if no objects found.
+ * @throws ContestServiceException if an error occurs when interacting with the
+ * service layer.
+ * @since TopCoder Service Layer Integration 3 Assembly
+ */
+ public List
+ * Returns a list containing all active Technologies.
+ *
+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @return a list containing all activeCategories. It can be empty
+ * if no objects found.
+ * @throws ContestServiceException if an error occurs when interacting with the
+ * service layer.
+ * @since TopCoder Service Layer Integration 3 Assembly
+ */
+ public List
+ * Returns a list containing all Phases.
+ *
+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @return a list containing all activeCategories. It can be empty
+ * if no objects found.
+ * @throws ContestServiceException if an error occurs when interacting with the
+ * service layer.
+ * @since TopCoder Service Layer Integration 3 Assembly
+ */
+ public List
+ * Assigns a specified user to a specified assetDTO.
+ *
+ * If the user already assigned to the asset, this method simply does nothing. + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @param userId the id of the user + * @param assetId the id of the assetDTO + * @throws ContestServiceException if an error occurs when interacting with the + * service layer. + * @since TopCoder Service Layer Integration 3 Assembly + */ + public void assignUserToAsset(TCSubject tcSubject, long userId, long assetId) throws ContestServiceException { + logger.debug("assignUserToAsset"); + + try { + catalogService.assignUserToAsset(userId, assetId); + logger.debug("Exit assignUserToAsset"); + } catch (EntityNotFoundException e) { + logger.error("Operation failed in the catalogService.", e); + throw new ContestServiceException("Operation failed in the catalogService.", e); + } catch (com.topcoder.catalog.service.PersistenceException e) { + logger.error("Operation failed in the catalogService.", e); + throw new ContestServiceException("Operation failed in the catalogService.", e); + } + } + + /** + *
+ * Removes a specified user from a specified assetDTO.
+ *
+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @param userId the id of the user + * @param assetId the id of the asset + * @throws ContestServiceException if an error occurs when interacting with the + * service layer. + * @since TopCoder Service Layer Integration 3 Assembly + */ + public void removeUserFromAsset(TCSubject tcSubject, long userId, long assetId) throws ContestServiceException { + logger.debug("removeUserFromAsset"); + + try { + catalogService.removeUserFromAsset(userId, assetId); + logger.debug("Exit removeUserFromAsset"); + } catch (EntityNotFoundException e) { + logger.error("Operation failed in the catalogService.", e); + throw new ContestServiceException("Operation failed in the catalogService.", e); + } catch (com.topcoder.catalog.service.PersistenceException e) { + logger.error("Operation failed in the catalogService.", e); + throw new ContestServiceException("Operation failed in the catalogService.", e); + } + } + + /** + *+ * This method finds all tc direct projects. Returns empty array if no projects + * found. + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @return Project array with project info, or empty array if none found + * @throws ContestServiceException if an error occurs when interacting with the + * service layer. + * @since TopCoder Service Layer Integration 3 Assembly + */ + public SoftwareCompetition[] findAllTcDirectProjects(TCSubject tcSubject) throws ContestServiceException { + logger.debug("findAllTcDirectProjects"); + + try { + Project[] projects = projectServices.findAllTcDirectProjects(tcSubject); + + SoftwareCompetition[] ret = new SoftwareCompetition[projects.length]; + + for (int i = 0; i < projects.length; i++) { + FullProjectData projectData = new FullProjectData(); + projectData.setProjectHeader(projects[i]); + + ret[i] = new SoftwareCompetition(); + ret[i].setProjectData(projectData); + ret[i].setType(CompetionType.SOFTWARE); + ret[i].setId(projectData.getProjectHeader().getId()); + } + + logger.debug("Exit findAllTcDirectProjects"); + + return ret; + } catch (ProjectServicesException e) { + logger.error("Operation failed in the projectServices.", e); + throw new ContestServiceException("Operation failed in the projectServices.", e); + } + } + + /** + *+ * This method finds all given user tc direct projects . Returns empty array if + * no projects found. + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @param operator The user to search for projects + * @return Project array with project info, or empty array if none found + * @throws ContestServiceException if an error occurs when interacting with the + * service layer. + * @since TopCoder Service Layer Integration 3 Assembly + */ + public SoftwareCompetition[] findAllTcDirectProjectsForUser(TCSubject tcSubject, String operator) + throws ContestServiceException { + logger.debug("findAllTcDirectProjectsForUser"); + + try { + Project[] projects = projectServices.findAllTcDirectProjectsForUser(tcSubject, operator); + + SoftwareCompetition[] ret = new SoftwareCompetition[projects.length]; + + for (int i = 0; i < projects.length; i++) { + FullProjectData projectData = new FullProjectData(); + projectData.setProjectHeader(projects[i]); + + ret[i] = new SoftwareCompetition(); + ret[i].setProjectData(projectData); + ret[i].setType(CompetionType.SOFTWARE); + ret[i].setId(projectData.getProjectHeader().getId()); + } + + logger.debug("Exit findAllTcDirectProjectsForUser"); + + return ret; + } catch (ProjectServicesException e) { + logger.error("Operation failed in the projectServices.", e); + throw new ContestServiceException("Operation failed in the projectServices.", e); + } + } + + /** + *+ * This method retrieves the project along with all known associated + * information. Returns null if not found. + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @param projectId The ID of the project to retrieve + * @return the project along with all known associated information + * @throws IllegalArgumentException If projectId is negative + * @throws ContestServiceException if an error occurs when interacting with the + * service layer. + * @since TopCoder Service Layer Integration 3 Assembly + */ + public SoftwareCompetition getFullProjectData(TCSubject tcSubject, long projectId) + throws ContestServiceException, PermissionServiceException { + logger.debug("getFullProjectData"); + + try { + FullProjectData projectData = projectServices.getFullProjectData(projectId); + + if (projectData == null) { + return null; + } + + com.topcoder.project.phases.Phase[] allPhases = projectData.getAllPhases(); + + for (int i = 0; i < allPhases.length; i++) { + allPhases[i].setProject(null); + } + + SoftwareCompetition contest = new SoftwareCompetition(); + contest.setProjectData(projectData); + contest.setType(CompetionType.SOFTWARE); + contest.setId(projectData.getProjectHeader().getId()); + logger.debug("Exit getFullProjectData"); + + return contest; + } catch (ProjectServicesException e) { + logger.error("Operation failed in the projectServices.", e); + throw new ContestServiceException("Operation failed in the projectServices.", e); + } + } + + /** + * Checks the permission for the given tc-direct-project-id for the current + * caller. + * + * @param tcSubject the current caller + * @param tcDirectProjectId the project id + * @param readOnly true to check READ permission, false to check WRITE + * permission + * @throws PermissionServiceException if user(not admin) does not have the + * permission + */ + private void checkSoftwareProjectPermission(TCSubject tcSubject, long tcDirectProjectId, boolean readOnly) + throws PermissionServiceException { + if (!isRole(tcSubject, ADMIN_ROLE) && !isRole(tcSubject, TC_STAFF_ROLE)) { + if (!projectServices.checkProjectPermission(tcDirectProjectId, readOnly, tcSubject.getUserId())) { + // check group permission + checkGroupPermissionForProject(tcSubject, tcDirectProjectId, readOnly); + } + } + } + + /** + * Checks the permission for the given contestId for the current caller. + * + * @param tcSubject the current caller + * @param contestId the contest id + * @param readOnly true to check READ permission, false to check WRITE + * permission + * @throws PermissionServiceException if user(not admin) does not have the + * permission + */ + private void checkSoftwareContestPermission(TCSubject tcSubject, long contestId, boolean readOnly) + throws PermissionServiceException { + if (!isRole(tcSubject, ADMIN_ROLE) && !isRole(tcSubject, TC_STAFF_ROLE)) { + if (!projectServices.checkContestPermission(contestId, readOnly, tcSubject.getUserId())) { + // check group permission for project + checkGroupPermissionForProject(tcSubject, projectServices.getTcDirectProject(contestId), readOnly); + } + } + } + + /** + * Checks the group permission for the given tc-direct-project-id for the + * current caller. + * + * @param tcSubject the current caller + * @param tcDirectProjectId the project id + * @param readOnly true to check READ permission, false to check WRITE + * permission + * @throws PermissionServiceException if user(not admin) does not have the group + * permission + * @since 1.8.4 + */ + private void checkGroupPermissionForProject(TCSubject tcSubject, long tcDirectProjectId, boolean readOnly) + throws PermissionServiceException { + try { + // Check if user is administrator for client account + Long clientId = null; + + // get client id + DataAccess dataAccess = new DataAccess(DBMS.TCS_DW_DATASOURCE_NAME); + Request request = new Request(); + request.setContentHandle("non_admin_client_billing_accounts"); + request.setProperty("tdpis", String.valueOf(tcDirectProjectId)); + ResultSetContainer resultContainer = dataAccess.getData(request).get("non_admin_client_billing_accounts"); + if (resultContainer != null && resultContainer.size() > 0) { + clientId = resultContainer.getLongItem(0, "client_id"); + } + long userId = tcSubject.getUserId(); + boolean isCustomerAdministrator = false; + if (clientId != null) { + isCustomerAdministrator = authorizationService.isCustomerAdministrator(userId, clientId); + } + if (isCustomerAdministrator) { + return; + } else { + // If not then check if user is granted desired permission to access the project + // based on + // security groups which user is member of + GroupPermissionType groupPermissionType = authorizationService.checkAuthorization(userId, tcDirectProjectId, + ResourceType.PROJECT); + if (groupPermissionType != null) { + if (readOnly && groupPermissionType != GroupPermissionType.REPORT) { + return; + } + if (!readOnly && (groupPermissionType == GroupPermissionType.WRITE + || groupPermissionType == GroupPermissionType.FULL)) { + return; + } + } + } + } catch (Exception e) { + throw new PermissionServiceException("Failed to authorize user against security groups", e); + } + + throw new PermissionServiceException("No " + (readOnly ? "read" : "write") + " permission on project"); + } + + /** + * Checks the billing project permission of the given contest for the current + * caller. + * + * @param contest the contest to check + * @return billing project id, if it is -1, then no billing project + * @throws ContestServiceException if user(not admin) does not have the + * permission + */ + private void checkBillingProjectPermission(TCSubject tcSubject, SoftwareCompetition contest) + throws PermissionServiceException, DAOException, ContestServiceException { + if (!isRole(tcSubject, ADMIN_ROLE) && !isRole(tcSubject, TC_STAFF_ROLE)) { + String billingProject = contest.getProjectHeader() + .getProperty(ProjectPropertyType.BILLING_PROJECT_PROJECT_PROPERTY_KEY); + + Project cur = projectServices.getProject(contest.getProjectHeader().getId()); + String curBilling = cur.getProperty(ProjectPropertyType.BILLING_PROJECT_PROJECT_PROPERTY_KEY); + + if (billingProject != null && !billingProject.equals("") && !billingProject.equals("0")) { + + // if billing not changed, no need to check + if (curBilling != null && !billingProject.equals("") && !billingProject.equals("0")) { + if (billingProject.equals(billingProject)) { + return; + } + } + long clientProjectId = Long.parseLong(billingProject); + if (!billingProjectDAO.checkClientProjectPermission(getUserName(tcSubject), clientProjectId)) { + throw new PermissionServiceException("No permission on billing project " + clientProjectId); + } + } + } + } + + /** + * get billing project id + * + * @param contest the contest to check + * @return billing project id, if it is 0, then no billing project + */ + private long getBillingProjectId(SoftwareCompetition contest) { + + String billingProject = contest.getProjectHeader() + .getProperty(ProjectPropertyType.BILLING_PROJECT_PROJECT_PROPERTY_KEY); + + if (billingProject != null && !billingProject.equals("") && !billingProject.equals("0")) { + long clientProjectId = Long.parseLong(billingProject); + return clientProjectId; + } + return 0; + + } + + /** + * Checks if the contest is development contest. + * + * @param contest the contest + * @return true if yes + */ + private boolean isDevContest(SoftwareCompetition contest) { + return contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.DEVELOPMENT.getId(); + } + + /** + * Checks if the contest is of type Code + * + * @param contest the contest to check + * @return true if yes, false otherwise + * @since 2.0.0 + */ + private boolean isCodeContest(SoftwareCompetition contest) { + return contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.CODE.getId(); + } + + /** + * Checks if the contest is of type First2Finish + * + * @param contest the contest to check + * @return true if yes, false otherwise + * @since 2.0.1 + */ + private boolean isF2FContest(SoftwareCompetition contest) { + return contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.FIRST2FINISH.getId(); + } + + /** + * Checks if the contest is of type Design First2Finish + * + * @param contest the contest tocheck + * @return true if yes, false otherwise + * @since 3.0 + */ + private boolean isDesignF2FContest(SoftwareCompetition contest) { + return contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.DESIGN_FIRST2FINISH.getId(); + } + + /** + * Checks if the contest is copilot contest. + * + * @param contest the contest + * @return true if yes + * @since 1.6.4 + */ + private boolean isCopilotContest(SoftwareCompetition contest) { + return contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.COPILOT_POSTING.getId(); + } + + /** + * Checks if the contest is studio contest. + * + * @param contest the conetst to check + * @return true if the contest is studio contest, false otherwise + * @since 1.6.6 + */ + private boolean isStudio(SoftwareCompetition contest) { + return contest.getProjectHeader().getProjectCategory().getProjectType().getId() == ProjectType.STUDIO.getId(); + } + + /** + * Checks if the contest is of type Marathon Match. + * + * @param contest the contest + * @return true if yes + * @since 3.14 + */ + private boolean isMMContest(SoftwareCompetition contest) { + return contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.MARATHON_MATCH.getId(); + } + + /** + *
+ * Creates a new SoftwareCompetition in the persistence.
+ *
+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info + * for the current user + * @param contest theSoftwareCompetition to create as a
+ * contest
+ * @param tcDirectProjectId the TC direct project id. a long
+ * providing the ID of a client the new competition
+ * belongs to.
+ * @return the created SoftwareCompetition as a contest
+ * @throws IllegalArgumentException if the input argument is invalid.
+ * @throws ContestServiceException if an error occurs when interacting with the
+ * service layer.
+ * @since TopCoder Service Layer Integration 3 Assembly
+ */
+ public SoftwareCompetition createSoftwareContest(TCSubject tcSubject, SoftwareCompetition contest,
+ long tcDirectProjectId) throws ContestServiceException, PermissionServiceException {
+ return createSoftwareContest(tcSubject, contest, tcDirectProjectId, null, null, null);
+ }
+
+ /**
+ * Checks whether the given billing account is associated with the given direct
+ * project.
+ *
+ * @deprecated
+ * @param billingAccountId the id of the billing account
+ * @param directProjectId the id of the direct project
+ * @throws PersistenceFault if there is any error with projectService
+ * @throws ContestServiceException if the billing account is not assciated with
+ * the direct project
+ * @since 1.9.3
+ */
+ private void checkContestBillingAccount(long billingAccountId, long directProjectId)
+ throws PersistenceFault, ContestServiceException {
+ if (billingAccountId <= 0) {
+ return;
+ }
+
+ final List
+ * Creates a new SoftwareCompetition in the persistence.
+ *
+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + *+ * Update in v1.8.3: Add handling of auto creation of bug hunt for assembly + * competition. If the assembly contest has bugHuntProjectHeader set and the + * properties not empty in bugHuntProjectHeader. A bug hunt contest is + * automatically created. The bug hunt contest will - have copilot inserted as + * reviewer (if exists) - use the start date of approval date as the start date + * and producation date of bug hunt contest. - add a "Bug Race For" link between + * the bug race contest and assembly contest + *
+ * + * @param tcSubject TCSubject instance contains the login security info + * for the current user + * @param contest theSoftwareCompetition to create as a
+ * contest
+ * @param tcDirectProjectId the TC direct project id. a long
+ * providing the ID of a client the new competition
+ * belongs to.
+ * @param multiRoundEndDate the end date for the multiround phase. No multiround
+ * if it's null.
+ * @param endDate the end date for submission phase. Can be null if to
+ * use default.
+ * @return the created SoftwareCompetition as a contest
+ * @throws IllegalArgumentException if the input argument is invalid.
+ * @throws ContestServiceException if an error occurs when interacting with the
+ * service layer.
+ * @since 1.6.6
+ */
+ public SoftwareCompetition createSoftwareContest(TCSubject tcSubject, SoftwareCompetition contest,
+ long tcDirectProjectId, Date multiRoundEndDate, Date endDate)
+ throws ContestServiceException, PermissionServiceException {
+ return createSoftwareContest(tcSubject, contest, tcDirectProjectId, null, null, null);
+ }
+
+ /**
+ *
+ * Creates a new SoftwareCompetition in the persistence.
+ *
SoftwareCompetition to create as a
+ * contest
+ * @param tcDirectProjectId the TC direct project id. a long
+ * providing the ID of a client the new competition
+ * belongs to.
+ * @param regEndDate the registration end date
+ * @param multiRoundEndDate the end date for the multiround phase. No multiround
+ * if it's null.
+ * @param endDate the end date for submission phase. Can be null if to
+ * use default.
+ * @return the created SoftwareCompetition as a contest
+ * @throws IllegalArgumentException if the input argument is invalid.
+ * @throws ContestServiceException if an error occurs when interacting with the
+ * service layer.
+ */
+ public SoftwareCompetition createSoftwareContest(TCSubject tcSubject, SoftwareCompetition contest,
+ long tcDirectProjectId, Date regEndDate, Date multiRoundEndDate, Date endDate)
+ throws ContestServiceException, PermissionServiceException {
+ logger.debug("createSoftwareContest with information : [tcSubject = " + tcSubject.getUserId()
+ + ", tcDirectProjectId =" + tcDirectProjectId + ", multiRoundEndDate = " + multiRoundEndDate + "]");
+
+ try {
+ ExceptionUtils.checkNull(contest, null, null, "The contest to create is null.");
+ ExceptionUtils.checkNull(contest.getProjectHeader(), null, null, "The contest#ProjectHeader to create is null.");
+
+ // check the permission
+ // TODO liquid creaet project, and assign permission, check fails here
+ // checkSoftwareProjectPermission(tcSubject, tcDirectProjectId, true);
+ // check the billing project permission
+ long billingProjectId = getBillingProjectId(contest);
+
+ // check if billing project id is one of the billing accounts for the direct
+ // project
+ if (billingProjectId > 0) {
+ // do the checking
+ checkContestBillingAccount(billingProjectId, contest.getProjectHeader().getTcDirectProjectId());
+ }
+
+ // check whether we need to auto-create-development contest for design
+ boolean creatingDevContest = shouldAutoCreateDevContest(contest);
+
+ // check whether we need to auto create bug hunt contest for the bug hunt
+ boolean creatingBugHunt = shouldAutoCreateBugHuntContest(contest);
+
+ // copy the data from design to development if it is going to do
+ // auto-dev-creating
+ SoftwareCompetition devContest = null;
+ if (creatingDevContest) {
+ devContest = (SoftwareCompetition) contest.clone();
+ }
+
+ SoftwareCompetition bugHuntContest = null;
+
+ if (creatingBugHunt) {
+ // copy the data from assembly to bug hunt if creatingBugHunt is true
+ bugHuntContest = (SoftwareCompetition) contest.clone();
+ }
+
+ boolean requireApproval = true;
+
+ if (isStudio(contest)
+ || contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.BUG_HUNT.getId()
+ || contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.COPILOT_POSTING.getId()) {
+ // do not add approver for bug hunt and copilot posting
+ requireApproval = false;
+ }
+
+ checkBillingProjectCCA(contest);
+
+ // update the AssetDTO and update corresponding properties
+ createUpdateAssetDTO(tcSubject, contest);
+
+ com.topcoder.management.resource.Resource[] contestResources = createContestResources(tcSubject, contest,
+ billingProjectId, requireApproval);
+
+ // create contest resources
+ contest.setProjectResources(contestResources);
+
+ // set the tc-direct-project-id
+ contest.getProjectHeader().setTcDirectProjectId(tcDirectProjectId);
+
+ // set status to draft
+ contest.getProjectHeader().setProjectStatus(ProjectStatus.DRAFT);
+
+ // create project now
+ FullProjectData projectData = projectServices.createProjectWithTemplate(contest.getProjectHeader(),
+ contest.getProjectPhases(), contest.getProjectResources(), regEndDate, multiRoundEndDate, endDate,
+ String.valueOf(tcSubject.getUserId()));
+
+ // create mm entry
+ if (contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.MARATHON_MATCH.getId()) {
+ Date mStartDate = null;
+ Date mRegEndDate = null;
+ Date mEndDate = null;
+ for (com.topcoder.project.phases.Phase p : projectData.getAllPhases()) {
+ if (p.getPhaseType().getId() == PhaseType.REGISTRATION_PHASE.getId()) {
+ mStartDate = p.getScheduledStartDate();
+ mRegEndDate = p.getScheduledEndDate();
+ } else if (p.getPhaseType().getId() == PhaseType.SUBMISSION_PHASE.getId()) {
+ mEndDate = p.getScheduledEndDate();
+ }
+ }
+ projectManager.createOrUpdateMarathonMatch(projectData.getProjectHeader(), mStartDate, mRegEndDate, mEndDate,
+ true, String.valueOf(tcSubject.getUserId()));
+ }
+
+ if (contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.DEVELOPMENT.getId()) {
+ projectServices.linkDevelopmentToDesignContest(projectData.getProjectHeader().getId());
+ }
+
+ if (contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.BUG_HUNT.getId()
+ && contest.getProjectHeader().isAutoCreationBugHunt()) {
+ // link the bug hunt to the parent contest if it's of type bug hunt and it's an
+ // auto created one
+ projectServices.linkBugHuntToOtherContest(projectData.getProjectHeader().getId());
+
+ // add copilot as reviewer
+ for (com.topcoder.management.resource.Resource r : contestResources) {
+ if (r.getResourceRole().getId() == ResourceRole.RESOURCE_ROLE_COPILOT_ID) {
+ addReviewer(tcSubject, projectData.getProjectHeader().getId(),
+ Long.parseLong(r.getProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID)));
+ }
+ }
+ }
+
+ if (contest.getProjectHeader().getAutoAssignReviewerId() > 0) {
+ if (contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.CODE.getId()) {
+ // no review payment for the contest
+ addReviewer(tcSubject, projectData.getProjectHeader().getId(),
+ contest.getProjectHeader().getAutoAssignReviewerId());
+ }
+ }
+
+ // set copilot forum permission
+ long forumId = 0;
+
+ // COMMENTED OUT FOR TIME BEING
+ // if (createForum) {
+ // forumId = contest.getAssetDTO().getForum().getJiveCategoryId();
+ // }
+
+ // String adminRole = getEligibilityAdminRole(tcSubject,
+ // billingProjectId).trim();
+
+ for (com.topcoder.management.resource.Resource r : contest.getProjectResources()) {
+ long roleId = r.getResourceRole().getId();
+ long uid = Long.parseLong(r.getProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID));
- /**
- * Active status list.
- *
- * @since 1.6
- */
- private final static List
- * A ContestEligibilityValidationManager providing access to available
- * Contest Eligibility Validation EJB.
- *
- * A ContestEligibilityManager providing access to available
- * Contest Eligibility Persistence EJB.
- *
- * A CatalogService providing access to available
- * Category Services EJB. This bean is delegated to process the
- * calls to the methods inherited from Category Services
- * component.
- *
- * A ProjectServices providing access to available
- * Project Services EJB. This bean is delegated to process the
- * calls to the methods inherited from Project Services
- * component.
- *
- * A PermissionService providing access to available
- * Permission Service EJB. This bean is delegated to process
- * the calls for CRUD on permissions.
- *
- * A UserService providing access to available
- * User Service EJB.
- *
A SpecReviewService providing access to available Spec Review Service. This bean is
- * delegated to process the calls for CRUD spec reviews.
A ProjectDAO providing access to available billing project related methods like retrieving
- * contest fee for given billing project.
A ProjectService providing access to project service.
A PermissionServiceFacade providing access to permission related methods.
A SpecificationReviewService providing access to contest specification review related methods.
- * A PaymentProcessor instance of payment processor
- * implementing class. All payment requests are processed through this
- * instance.
- *
- * A UploadExternalServices instance of Online Review Upload
- * Services to expose its methods.
- *
- * Represents the sessionContext of the ejb. - *
- */ - @Resource - private SessionContext sessionContext; + if (creatingDevContest) { + autoCreateDevContest(tcSubject, contest, tcDirectProjectId, devContest); + contest.setDevelopmentProjectHeader(devContest.getProjectHeader()); + contest.setDevId(devContest.getProjectHeader().getId()); + } - /** - * Document manager config file location. - * - * @since Cockpit Release Assembly for Receipts - */ - @Resource(name = "documentManagerConfigFile") - private String documentManagerConfigFile; + if (creatingBugHunt) { + // get the approval phase start time of assembly contest + Date apprvalPhaseStartDate = null; - /** - * Email template file path for Activate Contest Receipt. - * - * @since Cockpit Release Assembly for Receipts - */ - @Resource(name = "activateContestReceiptEmailTemplatePath") - private String activateContestReceiptEmailTemplatePath; + for (com.topcoder.project.phases.Phase p : contest.getProjectPhases().getPhases()) { + if (p.getPhaseType().getId() == PhaseType.APPROVAL_PHASE.getId()) { + apprvalPhaseStartDate = p.getScheduledStartDate(); + break; + } + } - /** - * BCC Address for Activate Contest Receipt Email - * - * @since Cockpit Release Assembly for Receipts - */ - @Resource(name = "activateContestReceiptEmailBCCAddr") - private String activateContestReceiptEmailBCCAddr; + // auto create the bug hunt contest + autoCreateBugHuntContest(tcSubject, contest, tcDirectProjectId, bugHuntContest, apprvalPhaseStartDate); - /** - * From Address for Activate Contest Receipt Email - * - * @since Cockpit Release Assembly for Receipts - */ - @Resource(name = "activateContestReceiptEmailFromAddr") - private String activateContestReceiptEmailFromAddr; + // set updated bug hunt project header for the parent assembly contest + contest.setBugHuntProjectHeader(bugHuntContest.getProjectHeader()); + } - /** - * Subject line for Activate Contest Receipt Email - * - * @since Cockpit Release Assembly for Receipts - */ - @Resource(name = "activateContestReceiptEmailSubject") - private String activateContestReceiptEmailSubject; + addReviewAuction(contest); - /** - * Email template file path for copilot winner email. - * @since 1.8.5 - */ - @Resource(name = "copilotWinnerEmailTemplatePath") - private String copilotWinnerEmailTemplatePath; + // create direct project milestone xref if needed + if (contest.getDirectProjectMilestoneId() > 0) { + projectServices.createProjectMilestoneRelation(contest.getProjectHeader().getId(), + contest.getDirectProjectMilestoneId(), String.valueOf(tcSubject.getUserId())); + } - /** - * BCC Address for copilot winner email. - * @since 1.8.5 - */ - @Resource(name = "copilotWinnerEmailBCCAddr") - private String copilotWinnerEmailBCCAddr; + // publish event to AWS SNS if needed + try { + String cmcTaskId = contest.getProjectHeader() + .getProperty(ProjectPropertyType.CLOUDSPOKES_CMC_TASK_PROPERTY_KEY); + String apiURL = ""; - /** - * From Address for copilot winner email. - * - * @since 1.8.5 - */ - @Resource(name = "copilotWinnerEmailFromAddr") - private String copilotWinnerEmailFromAddr; + if (isStudio(contest)) { + apiURL = "http://api.topcoder.com/v2/design/challenges/" + String.valueOf(contest.getProjectHeader().getId()); + } else { + apiURL = "http://api.topcoder.com/v2/develop/challenges/" + + String.valueOf(contest.getProjectHeader().getId()); + } + + if (StringUtils.isNotEmpty(cmcTaskId)) { + String contestCreationMessage = contestCreationMessageTemplate + .replace("%CHALLENGE_ID%", String.valueOf(contest.getProjectHeader().getId())) + .replace("%CMC_TASK_ID%", cmcTaskId).replace("%API_URL%", apiURL); + + String subject = contestCreationSubject.replace("%CMC_TASK_ID%", cmcTaskId); + + PublishRequest request = new PublishRequest().withSubject(subject).withMessage(contestCreationMessage) + .withTopicArn(contestCreationArn); + + PublishResult result = amazonSNSClient.publish(request); + logger.debug("Publish amazon SNS successfully, the published message id is " + result.getMessageId()); + } + } catch (Exception e) { + // we will only log publish error here, won't rollback contest creation. + logger.error("Operation failed in publish amazon SNS.", e); + } + + return contest; + } catch (Exception e) { + sessionContext.setRollbackOnly(); + logger.error("Operation failed in the contest service facade.", e); + throw new ContestServiceException("Operation failed in the contest service facade.", e); + } finally { + logger.debug("Exit createSoftwareContest, the newly create contest id = " + contest.getId()); + } + } + + /** + *+ * Detects whether the auto creating development contest is on. + *
+ * + * @param contest the contest + * @return true if yes + */ + private boolean shouldAutoCreateDevContest(SoftwareCompetition contest) { + return contest.getDevelopmentProjectHeader() != null + && contest.getDevelopmentProjectHeader().getProperties() != null + && contest.getDevelopmentProjectHeader().getProperties().size() != 0; + } + + /** + *+ * Detects whether need to auto create the bug hunt contest. + *
+ * + * @param contest the contest + * @return true if yes, false otherwise + * @since 1.8.3 + */ + private boolean shouldAutoCreateBugHuntContest(SoftwareCompetition contest) { + return contest.getBugHuntProjectHeader() != null && contest.getBugHuntProjectHeader().getProperties() != null + && contest.getBugHuntProjectHeader().getProperties().size() != 0; + } + + /** + * Create or updating the AssetDTO for the contest. If the AssetDTO already + * exists for development contest, we need to create dev-component. Also, + * creating forum if necessary. + *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ *+ * Update in v1.6.4: set digital run flag to 'Off' and rated to 'No' if it's + * copilot selection contest. + *
+ * + *+ * Update in 1.8.3: - Reuse the same assetDTO as the parent contest for auto + * creation bug hunt contest. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @param contest the contest + * @throws EntityNotFoundException if any error occurs + * @throws com.topcoder.catalog.service.PersistenceException if any error occurs + */ + private void createUpdateAssetDTO(TCSubject tcSubject, SoftwareCompetition contest) throws EntityNotFoundException, + com.topcoder.catalog.service.PersistenceException, DAOException, ConfigManagerException { + // check if it is going to create development contest + boolean isDevContest = isDevContest(contest); + XMLGregorianCalendar productionDate = null; + if (contest.getAssetDTO() != null) { + AssetDTO assetDTO = contest.getAssetDTO(); + boolean useExistingAsset = false; + if (isDevContest && assetDTO.getVersionNumber() != null && assetDTO.getVersionNumber().longValue() != 1) { + useExistingAsset = true; + productionDate = assetDTO.getProductionDate(); + assetDTO = catalogService.getAssetByVersionId(assetDTO.getVersionNumber()); + // for dev, we need to insert a row in comp version dates + catalogService.createDevComponent(assetDTO); + // set dev only flag + } else if (contest.getProjectHeader().isAutoCreationBugHunt()) { + // use the asset belong to the parent contest + useExistingAsset = true; + productionDate = assetDTO.getProductionDate() == null ? nextDay() : assetDTO.getProductionDate(); + } + // dev only + else if (isDevContest) { + contest.getProjectHeader().setDevOnly(true); + } + + if (!useExistingAsset) { + productionDate = assetDTO.getProductionDate() == null ? nextDay() : assetDTO.getProductionDate(); + assetDTO.setProductionDate(null); + if (contest.getProjectHeader() != null) { + // comp development, set phase to dev, otherwise to design + assetDTO.setPhase(isDevContest ? "Development" : "Design"); + } + assetDTO = this.catalogService.createAsset(assetDTO); + contest.setAssetDTO(assetDTO); + } + long forumId = 0; + // create forum + if (createForum) { + if (useExistingAsset && assetDTO.getForum() != null) { + forumId = assetDTO.getForum().getJiveCategoryId(); + } else { + if (!isStudio(contest)) { + // software contest + forumId = createForum(tcSubject, assetDTO, tcSubject.getUserId(), + contest.getProjectHeader().getProjectCategory().getId()); + } else { + // studio contest + forumId = createStudioForum(assetDTO.getName(), tcSubject.getUserId()); + } + } + } + + // if forum created + if (forumId > 0 && (!useExistingAsset || assetDTO.getForum() == null)) { + // create a comp forum + CompForum compForum = new CompForum(); + compForum.setJiveCategoryId(forumId); + assetDTO.setForum(compForum); + assetDTO = this.catalogService.updateAsset(assetDTO); + // avoid cycle + assetDTO.getForum().setCompVersion(null); + } + contest.setAssetDTO(assetDTO); + + contest.getProjectHeader().setProperty(ProjectPropertyType.EXTERNAL_REFERENCE_ID_PROJECT_PROPERTY_KEY, + assetDTO.getCompVersionId().toString()); + contest.getProjectHeader().setProperty(ProjectPropertyType.COMPONENT_ID_PROJECT_PROPERTY_KEY, + assetDTO.getId().toString()); + contest.getProjectHeader().setProperty(ProjectPropertyType.ROOT_CATALOG_ID_PROJECT_PROPERTY_KEY, + assetDTO.getRootCategory().getId().toString()); + contest.getProjectHeader().setProperty(ProjectPropertyType.SVN_MODULE_PROJECT_PROPERTY_KEY, ""); + contest.getProjectHeader().setProperty(ProjectPropertyType.NOTES_PROJECT_PROPERTY_KEY, ""); + contest.getProjectHeader().setProperty(ProjectPropertyType.PROJECT_VERSION_PROJECT_PROPERTY_KEY, "1.0"); + contest.getProjectHeader().setProperty(ProjectPropertyType.VERSION_ID_PROJECT_PROPERTY_KEY, "1"); + contest.getProjectHeader().setProperty(ProjectPropertyType.AUTOPILOT_OPTION_PROJECT_PROPERTY_KEY, "Off"); + contest.getProjectHeader().setProperty(ProjectPropertyType.STATUS_NOTIFICATION_PROJECT_PROPERTY_KEY, "On"); + contest.getProjectHeader().setProperty(ProjectPropertyType.TIMELINE_NOTIFICATION_PROJECT_PROPERTY_KEY, "On"); + contest.getProjectHeader().setProperty(ProjectPropertyType.PUBLIC_PROJECT_PROPERTY_KEY, "Yes"); + contest.getProjectHeader().setProperty(ProjectPropertyType.RATED_PROJECT_PROPERTY_KEY, "Yes"); + contest.getProjectHeader().setProperty(ProjectPropertyType.ELIGIBILITY_PROJECT_PROPERTY_KEY, "Open"); + + // set the forum type + if (!isStudio(contest)) { + // software contest + contest.getProjectHeader().setProperty(ProjectPropertyType.FORUM_TYPE, "Development"); + } else { + // studio contest + contest.getProjectHeader().setProperty(ProjectPropertyType.FORUM_TYPE, "Design"); + } + + if (contest.getProjectHeader().getProperty(ProjectPropertyType.DIGITAL_RRUN_FLAG_PROJECT_PROPERTY_KEY) == null) { + contest.getProjectHeader().setProperty(ProjectPropertyType.DIGITAL_RRUN_FLAG_PROJECT_PROPERTY_KEY, "On"); + } + + if (isF2FContest(contest) || isDesignF2FContest(contest) || isMMContest(contest)) { + contest.getProjectHeader().setProperty(ProjectPropertyType.ALLOW_MULTIPLE_SUBMISSIONS_PROPERTY_KEY, "true"); + } + + boolean hasEligibility = false; + + long billingProjectId = getBillingProjectId(contest); + + // if creating contest, eligiblity is not commited, so above will not get back + // result + if (billingProjectId != 0 && contest.getProjectHeader().getSecurityGroupId() > 0) { + hasEligibility = true; + } + + if (hasEligibility) { + contest.getProjectHeader().setProperty(ProjectPropertyType.SEND_WINNDER_EMAILS_PROJECT_PROPERTY_KEY, "false"); + } else { + contest.getProjectHeader().setProperty(ProjectPropertyType.SEND_WINNDER_EMAILS_PROJECT_PROPERTY_KEY, "true"); + } + + if (isDevContest && !hasEligibility && billingProjectId > 0) { + String codename = billingProjectDAO.getProjectById(billingProjectId).getClient().getCodeName(); + String compname = contest.getAssetDTO().getName(); + if (codename != null && !codename.equals("")) { + + codename = CodeNameUtil.decodeCodeName(codename, "users"); + compname = compname.toLowerCase().replaceAll(" ", "_").replaceAll("/", "_").replaceAll("&", "_"); + codename = codename.toLowerCase().replaceAll(" ", ""); + contest.getProjectHeader().setProperty(ProjectPropertyType.SVN_MODULE_PROJECT_PROPERTY_KEY, + "https://coder.topcoder.com/tcs/clients/" + codename + "/components/" + compname + "/trunk"); + } + } + + contest.getProjectHeader().setProperty(ProjectPropertyType.TRACK_LATE_DELIVERABLES_PROJECT_PROPERTY_KEY, "true"); + + if (isCopilotContest(contest)) { + contest.getProjectHeader().setProperty(ProjectPropertyType.DIGITAL_RRUN_FLAG_PROJECT_PROPERTY_KEY, "Off"); + contest.getProjectHeader().setProperty(ProjectPropertyType.DR_POINTS_PROJECT_PROPERTY_KEY, "0"); + contest.getProjectHeader().setProperty(ProjectPropertyType.RATED_PROJECT_PROPERTY_KEY, "No"); + contest.getProjectHeader().setProperty(ProjectPropertyType.RELIABILITY_BONUS_ELIGIBLE_PROJECT_PROPERTY_KEY, + "false"); + contest.getProjectHeader().setProperty(ProjectPropertyType.CONFIDENTIALITY_TYPE_PROJECT_PROPERTY_KEY, + "standard_cca"); + contest.getProjectHeader().setProperty(ProjectPropertyType.TRACK_LATE_DELIVERABLES_PROJECT_PROPERTY_KEY, + "false"); + } + + if (contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.BUG_HUNT.getId()) { + contest.getProjectHeader().setProperty(ProjectPropertyType.RELIABILITY_BONUS_ELIGIBLE_PROJECT_PROPERTY_KEY, + "false"); + } + + if (isStudio(contest)) { + contest.getProjectHeader().setProperty(ProjectPropertyType.RATED_PROJECT_PROPERTY_KEY, "No"); + contest.getProjectHeader().setProperty(ProjectPropertyType.TRACK_LATE_DELIVERABLES_PROJECT_PROPERTY_KEY, + "false"); + } + + if (isF2FContest(contest) || isDesignF2FContest(contest)) { + // no rated for F2F || Design F2F + contest.getProjectHeader().setProperty(ProjectPropertyType.RATED_PROJECT_PROPERTY_KEY, "No"); + + // no Reliability for Code || F2F || Design F2F + contest.getProjectHeader().setProperty(ProjectPropertyType.RELIABILITY_BONUS_ELIGIBLE_PROJECT_PROPERTY_KEY, + "false"); + contest.getProjectHeader().setProperty(ProjectPropertyType.RELIABILITY_BONUS_COST_PROJECT_PROPERTY_KEY, "0"); + + // no Approval Required for Code || F2F || Design F2F + contest.getProjectHeader().setProperty(ProjectPropertyType.APPROVAL_REQUIRED_PROJECT_PROPERTY_KEY, "false"); + } + + if (isF2FContest(contest) || isCodeContest(contest)) { + // no Digital Run for F2F/Code + contest.getProjectHeader().setProperty(ProjectPropertyType.DIGITAL_RRUN_FLAG_PROJECT_PROPERTY_KEY, "Off"); + contest.getProjectHeader().setProperty(ProjectPropertyType.DR_POINTS_PROJECT_PROPERTY_KEY, "0"); + } + + if (!isStudio(contest) && !isCopilotContest(contest) + && contest.getProjectHeader().getProjectCategory().getId() != ProjectCategory.BUG_HUNT.getId() + && !isCodeContest(contest) && !isF2FContest(contest)) { + contest.getProjectHeader().setProperty(ProjectPropertyType.REVIEW_FEEDBACK_FLAG_PROJECT_PROPERTY_KEY, "true"); + } else { + contest.getProjectHeader().setProperty(ProjectPropertyType.REVIEW_FEEDBACK_FLAG_PROJECT_PROPERTY_KEY, "false"); + } + + if (contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.REPORTING.getId() + || contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.BUG_HUNT.getId() + || isDesignF2FContest(contest)) { + contest.getProjectHeader().setProperty(ProjectPropertyType.DIGITAL_RRUN_FLAG_PROJECT_PROPERTY_KEY, "Off"); + contest.getProjectHeader().setProperty(ProjectPropertyType.DR_POINTS_PROJECT_PROPERTY_KEY, "0"); + contest.getProjectHeader().setProperty(ProjectPropertyType.RATED_PROJECT_PROPERTY_KEY, "No"); + } + + if (isPrivateProject(contest)) { + // not rate for private + contest.getProjectHeader().setProperty(ProjectPropertyType.RATED_PROJECT_PROPERTY_KEY, "No"); + } + + // if (contest.getProjectHeader().getProjectCategory().getId() == + // ProjectCategory.CONTENT_CREATION.getId()) + // { + // contest.getProjectHeader().setProperty(ProjectPropertyType.DIGITAL_RRUN_FLAG_PROJECT_PROPERTY_KEY, + // "Off"); + // contest.getProjectHeader().setProperty(ProjectPropertyType.DR_POINTS_PROJECT_PROPERTY_KEY, + // "0"); + // } + + if (forumId > 0) { + contest.getProjectHeader().setProperty(ProjectPropertyType.DEVELOPER_FORUM_ID_PROJECT_PROPERTY_KEY, + String.valueOf(forumId)); + } + + contest.getProjectPhases().setStartDate(getDate(productionDate)); + } + } + + /** + *+ * If the auto creating development contest is switch on, we need to prepare the + * contest here. + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info + * for the current user + * @param designContest the design contest + * @param tcDirectProjectId tc-direct-project-id + * @param devContest the development contest to create + * @throws DatatypeConfigurationException if any error occurs + * @throws ContestServiceException if any error occurs + */ + private void autoCreateDevContest(TCSubject tcSubject, SoftwareCompetition designContest, long tcDirectProjectId, + SoftwareCompetition devContest) + throws DatatypeConfigurationException, ContestServiceException, PermissionServiceException { + devContest.setAssetDTO(designContest.getAssetDTO()); + devContest.getProjectHeader().getProperties().putAll(designContest.getDevelopmentProjectHeader().getProperties()); + devContest.setDevelopmentProjectHeader(null); + devContest.getProjectHeader().getProjectCategory().setId(ProjectCategory.DEVELOPMENT.getId()); + devContest.getAssetDTO().setProductionDate(nextDevProdDay(devContest.getAssetDTO().getProductionDate())); + devContest.setProjectHeaderReason("Create corresponding development contest"); + createSoftwareContest(tcSubject, devContest, tcDirectProjectId); + } + + /** + *+ * Auto creates the bug hunt contest for the parent contest if auto create bug + * hunt is on. This method prepares the bug hunt contest before inserting into + * the persistence. + *
+ * + * @param tcSubject instance contains the login security info for the + * current user + * @param assemblyContest the parent assembly contest + * @param tcDirectProjectId the if of the direct project + * @param bugHuntContest the bug hunt contest + * @param bugHuntStartTime the scheduled start time of the bug hunt contest + * @throws ContestServiceException if any error occurs realted to Contest + * Service facade + * @throws PermissionServiceException if any error occurs to Permission service + * facade + * @since 1.8.3 + */ + private void autoCreateBugHuntContest(TCSubject tcSubject, SoftwareCompetition assemblyContest, + long tcDirectProjectId, SoftwareCompetition bugHuntContest, Date bugHuntStartTime) + throws ContestServiceException, PermissionServiceException { + // preCreationAssetDTO.setName("Bug Hunt For " + preCreationAssetDTO); + bugHuntContest.setAssetDTO(assemblyContest.getAssetDTO()); + bugHuntContest.getProjectHeader().getProperties().putAll(assemblyContest.getBugHuntProjectHeader().getProperties()); + + final Map+ * Persists the GroupContestEligibility for the contest and client. If the + * eligiblity is not null, then the information will be copied from it. + *
+ * + * @param projectHeader the contest header data + * @param eligiblity, the existing ContestEligibility, could be null + * @param isStudio true for studio + * @throws ContestEligibilityPersistenceException if any error occurs + */ + private void persistContestEligility(Project projectHeader, List+ * Adding the contest resources when creating contest. manager or observer or + * client-manager will be added. + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ *+ * Update in v1.6.8: gets the copilot resource from getResources() of + * SoftwareCompetition. + *
+ * + *+ * Update in v1.8.3: For auto created bug hunt contest, insert the copilot as + * reviewer of the bug hunt contest if the copilot exists. + *
+ * + * @param tcSubject TCSubject instance contains the login security info + * for the current user + * @param contest the contest to create + * @param billingProjectId the billing project id + * @param requireApproval the flag of whether it's required + * @return resource array + * @throws ContestServiceException fail to retrieve user-handle + */ + private com.topcoder.management.resource.Resource[] createContestResources(TCSubject tcSubject, + SoftwareCompetition contest, long billingProjectId, boolean requireApproval) + throws ContestServiceException, UserServiceException, PermissionServiceException { + + // check if contest contains copilot resource + com.topcoder.management.resource.Resource[] contestResources = contest.getResources(); + com.topcoder.management.resource.Resource copilot = null; + com.topcoder.management.resource.Resource appirioManager = null; + + // flag indicates whether current user is set as the copilot + boolean isCopilotCurrentUser = false; + boolean isAppirioManagerCurrentUser = false; + + if (contestResources.length > 1) { + for (int i = 1; i < contestResources.length; ++i) { + + if (contestResources[i].getResourceRole().getId() == ResourceRole.RESOURCE_ROLE_COPILOT_ID) { + // contains copilot resource + copilot = contestResources[1]; + + if (copilot.getProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID).equals(String.valueOf(tcSubject.getUserId()))) { + isCopilotCurrentUser = true; + } + } else if (contestResources[i].getResourceRole().getId() == ResourceRole.RESOURCE_ROLE_MANAGER_ID) { + appirioManager = contestResources[i]; + if (appirioManager.getProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID) + .equals(String.valueOf(tcSubject.getUserId()))) { + isAppirioManagerCurrentUser = true; + } + } + } + } + + // create an array to store the resources, if copilot exists and copilot is not + // current user, we create + // an array of length 3, otherwise of length 2 + com.topcoder.management.resource.Resource[] resources = new com.topcoder.management.resource.Resource[2]; + + resources[0] = new com.topcoder.management.resource.Resource(); + resources[0].setId(com.topcoder.management.resource.Resource.UNSET_ID); + + // manager role + ResourceRole managerRole = new ResourceRole(); + managerRole.setId(ResourceRole.RESOURCE_ROLE_MANAGER_ID); + managerRole.setName(ResourceRole.RESOURCE_ROLE_MANAGER_NAME); + managerRole.setDescription(ResourceRole.RESOURCE_ROLE_MANAGER_DESC); + + // observer role + ResourceRole observerRole = new ResourceRole(); + observerRole.setId(ResourceRole.RESOURCE_ROLE_OBSERVER_ID); + observerRole.setName(ResourceRole.RESOURCE_ROLE_OBSERVER_NAME); + observerRole.setDescription(ResourceRole.RESOURCE_ROLE_OBSERVER_DESC); + + // client manager role + ResourceRole clientManagerRole = new ResourceRole(); + clientManagerRole.setId(ResourceRole.RESOURCE_ROLE_CLIENT_MANAGER_ID); + clientManagerRole.setName(ResourceRole.RESOURCE_ROLE_CLIENT_MANAGER_NAME); + clientManagerRole.setDescription(ResourceRole.RESOURCE_ROLE_CLIENT_MANAGER_DESC); + + // copilot role + ResourceRole copilotRole = new ResourceRole(); + copilotRole.setId(ResourceRole.RESOURCE_ROLE_COPILOT_ID); + + // is current user TC staff role + boolean tcstaff = isRole(tcSubject, TC_STAFF_ROLE); + boolean isObserverCopilot = false; + + if (appirioManager != null) { + resources[0] = appirioManager; + } else if (tcstaff) { + resources[0].setResourceRole(managerRole); + } else if (contest.getProjectHeader().getSecurityGroupId() > 0) { + resources[0].setResourceRole(managerRole); + } else { + if (isCopilotCurrentUser) { + // if copilot is current user, then set as copilot + resources[0] = copilot; + isObserverCopilot = true; + } else { + resources[0].setResourceRole(managerRole); + } + } + + if (!isObserverCopilot && appirioManager == null) { + // we don't override the copilot properties if the observer is the copilot + resources[0].setProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID, String.valueOf(tcSubject.getUserId())); + resources[0].setProperty(RESOURCE_INFO_HANDLE, getUserName(tcSubject)); + resources[0].setProperty(RESOURCE_INFO_PAYMENT_STATUS, RESOURCE_INFO_PAYMENT_STATUS_NA); + resources[0].setUserId(tcSubject.getUserId()); + } + + resources[0].setProperty(RESOURCE_INFO_REGISTRATION_DATE, DATE_FORMAT.format(new Date())); + + // for private, check if admin role is set, and use that if so + /** + * if (getEligibilityName(tcSubject, billingProjectId).trim().length() > 0) { + * + * String adminRole = getEligibilityAdminRole(tcSubject, + * billingProjectId).trim(); + * + * if (adminRole.length() > 0) { long roleId = userService.getUserId(adminRole); + * resources[1] = new com.topcoder.management.resource.Resource(); + * resources[1].setId(com.topcoder.management.resource.Resource.UNSET_ID); + * resources[1].setResourceRole(managerRole); + * resources[1].setProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID, + * Long.toString(roleId)); resources[1].setProperty(RESOURCE_INFO_HANDLE, + * adminRole); resources[1].setProperty(RESOURCE_INFO_PAYMENT_STATUS, + * RESOURCE_INFO_PAYMENT_STATUS_NA); + * resources[1].setProperty(RESOURCE_INFO_REGISTRATION_DATE, + * DATE_FORMAT.format(new Date())); } } + **/ + // design/dev, add Components + if (contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.DEVELOPMENT.getId() + || contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.DESIGN.getId()) { + + resources[1] = new com.topcoder.management.resource.Resource(); + resources[1].setId(com.topcoder.management.resource.Resource.UNSET_ID); + resources[1].setResourceRole(managerRole); + resources[1].setProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID, Long.toString(components_user_id)); + resources[1].setUserId(components_user_id); + resources[1].setProperty(RESOURCE_INFO_HANDLE, RESOURCE_INFO_HANDLE_COMPONENTS); + resources[1].setProperty(RESOURCE_INFO_PAYMENT_STATUS, RESOURCE_INFO_PAYMENT_STATUS_NA); + resources[1].setProperty(RESOURCE_INFO_REGISTRATION_DATE, DATE_FORMAT.format(new Date())); + } + // else add Applications + else { + resources[1] = new com.topcoder.management.resource.Resource(); + resources[1].setId(com.topcoder.management.resource.Resource.UNSET_ID); + resources[1].setResourceRole(managerRole); + resources[1].setProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID, Long.toString(applications_user_id)); + resources[1].setUserId(applications_user_id); + resources[1].setProperty(RESOURCE_INFO_HANDLE, RESOURCE_INFO_HANDLE_APPLICATIONS); + resources[1].setProperty(RESOURCE_INFO_PAYMENT_STATUS, RESOURCE_INFO_PAYMENT_STATUS_NA); + resources[1].setProperty(RESOURCE_INFO_REGISTRATION_DATE, DATE_FORMAT.format(new Date())); + } + + if (copilot != null && (!isCopilotCurrentUser || appirioManager != null)) { + com.topcoder.management.resource.Resource[] _resources = resources; + resources = new com.topcoder.management.resource.Resource[3]; + resources[0] = _resources[0]; + resources[1] = _resources[1]; + // when copilot exists and copilot is not current user, we store resource in + // another array element + resources[2] = copilot; + + // and set the registration date with current date + resources[2].setProperty(RESOURCE_INFO_REGISTRATION_DATE, DATE_FORMAT.format(new Date())); + } + + // add users has permission on cockpit project as observers + ListSoftwareCompetition in one
+ * trasaction. If there is SoftwareCompetition not in draft status,
+ * it won't be updated.
+ *
+ * @param tcSubject the tcSubject instance.
+ * @param tcDirectProjectId the id of the tc direct project.
+ * @param draftContests a list of SoftwareCompetition to
+ * update.
+ * @return the list of updated SoftwareCompetition
+ * @throws ContestServiceException if any error related to contest service
+ * facade.
+ * @throws PermissionServiceException if any error related to permission service
+ * facade.
+ * @since 1.9
+ */
+ public List
+ * Updates a SoftwareCompetition in the persistence.
+ *
+ * Update in version 1.5, reduce the code redundancy in permission checking. + *
+ *
+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info + * for the current user + * @param contest theSoftwareCompetition to update as a
+ * contest
+ * @param tcDirectProjectId the TC direct project id.
+ * @throws IllegalArgumentException if the input argument is invalid.
+ * @throws ContestServiceException if an error occurs when interacting with the
+ * service layer.
+ * @since TopCoder Service Layer Integration 3 Assembly
+ */
+ public SoftwareCompetition updateSoftwareContest(TCSubject tcSubject, SoftwareCompetition contest,
+ long tcDirectProjectId) throws ContestServiceException, PermissionServiceException {
+ return updateSoftwareContest(tcSubject, contest, tcDirectProjectId, null, null, null);
+ }
+
+ /**
+ *
+ * Updates a SoftwareCompetition in the persistence.
+ *
+ * Update in version 1.5, reduce the code redundancy in permission checking. + *
+ *
+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + *+ * Update in 1.9.2: Update to support add copilot as the approver of the contest + * when updating the contest. + *
+ * + * @param tcSubject TCSubject instance contains the login security info + * for the current user + * @param contest theSoftwareCompetition to update as a
+ * contest
+ * @param tcDirectProjectId the TC direct project id.
+ * @param multiRoundEndDate the end date for the multiround phase. No multiround
+ * if it's null.
+ * @param endDate the end date for submission phase. Can be null if to
+ * use default.
+ * @throws IllegalArgumentException if the input argument is invalid.
+ * @throws ContestServiceException if an error occurs when interacting with the
+ * service layer.
+ * @since 1.6.6
+ */
+ public SoftwareCompetition updateSoftwareContest(TCSubject tcSubject, SoftwareCompetition contest,
+ long tcDirectProjectId, Date multiRoundEndDate, Date endDate)
+ throws ContestServiceException, PermissionServiceException {
+
+ return updateSoftwareContest(tcSubject, contest, tcDirectProjectId, null, multiRoundEndDate, endDate);
+ }
+
+ /**
+ *
+ * Updates a SoftwareCompetition in the persistence.
+ *
SoftwareCompetition to update as a
+ * contest
+ * @param tcDirectProjectId the TC direct project id.
+ * @param regEndDate the registration end date
+ * @param multiRoundEndDate the end date for the multiround phase. No multiround
+ * if it's null.
+ * @param endDate the end date for submission phase. Can be null if to
+ * use default.
+ * @throws IllegalArgumentException if the input argument is invalid.
+ * @throws ContestServiceException if an error occurs when interacting with the
+ * service layer.
+ */
+ public SoftwareCompetition updateSoftwareContest(TCSubject tcSubject, SoftwareCompetition contest,
+ long tcDirectProjectId, Date regEndDate, Date multiRoundEndDate, Date endDate)
+ throws ContestServiceException, PermissionServiceException {
+ logger.debug("updateSoftwareContest");
+
+ try {
+ XMLGregorianCalendar productionDate = null;
+
+ if (contest.getAssetDTO() != null) {
+ // product date is used to pass the project start date
+ // bcoz we need to use XMLGregorianCalendar and project start
+ // date
+ // is Date and since it is not DTO and hard to change, we use
+ // product date for now, but we need to set it null so it will
+ // not
+ // saved in catalog
+ productionDate = contest.getAssetDTO().getProductionDate();
+ contest.getAssetDTO().setProductionDate(null);
+
+ // TODO: for some reason, versionid is not passed
+ contest.getAssetDTO().setCompVersionId(contest.getAssetDTO().getVersionNumber());
+ contest.setAssetDTO(this.catalogService.updateAsset(contest.getAssetDTO()));
+ }
+
+ String oldCMCTaskId = null;
+ String cmcTaskId = null;
+ Date oldStartDate = null;
+ Date oldCheckpointEndDate = null;
+ Date oldEndDate = null;
+
+ if (contest.getProjectHeader() != null) {
+
+ cmcTaskId = contest.getProjectHeader().getProperty(ProjectPropertyType.CLOUDSPOKES_CMC_TASK_PROPERTY_KEY);
+
+ FullProjectData oldProjectData = projectServices.getFullProjectData(contest.getProjectHeader().getId());
+
+ Project oldProject = oldProjectData.getProjectHeader();
+
+ if (StringUtils.isNotEmpty(cmcTaskId)) {
+
+ oldStartDate = oldProjectData.getStartDate();
+
+ com.topcoder.project.phases.Phase[] oldPhases = oldProjectData.getAllPhases();
+
+ for (com.topcoder.project.phases.Phase oldP : oldPhases) {
+ if (oldP.getPhaseType().getId() == PhaseType.REGISTRATION_PHASE.getId()) {
+ oldStartDate = oldP.getScheduledStartDate();
+ }
+ if (oldP.getPhaseType().getId() == PhaseType.CHECKPOINT_SUBMISSION_PHASE.getId()) {
+ oldCheckpointEndDate = oldP.getScheduledEndDate();
+ }
+ if (oldP.getPhaseType().getId() == PhaseType.SUBMISSION_PHASE.getId()) {
+ oldEndDate = oldP.getScheduledEndDate();
+ }
+ }
+
+ // get the old cmcTaskID
+ oldCMCTaskId = oldProject.getProperty(ProjectPropertyType.CLOUDSPOKES_CMC_TASK_PROPERTY_KEY);
+ }
+
+ // check the contest status - we do not accept change a active contet back to
+ // draft by the direct front end
+ if (oldProject.getProjectStatus().getId() == ProjectStatus.ACTIVE.getId()
+ && contest.getProjectHeader().getProjectStatus().getId() == ProjectStatus.DRAFT.getId()) {
+ // old is active, the new value is draft, not allow, set back to active
+ contest.getProjectHeader().setProjectStatus(ProjectStatus.ACTIVE);
+
+ // keep the auto pilot property
+ contest.getProjectHeader().setProperty(ProjectPropertyType.AUTOPILOT_OPTION_PROJECT_PROPERTY_KEY,
+ oldProject.getProperty(ProjectPropertyType.AUTOPILOT_OPTION_PROJECT_PROPERTY_KEY));
+ }
- /**
- * Subject line for copilot winner email.
- *
- * @since 1.8.5
- */
- @Resource(name = "copilotWinnerEmailSubject")
- private String copilotWinnerEmailSubject;
+ // check the permissions
+ checkSoftwareContestPermission(tcSubject, contest.getProjectHeader().getId(), false);
+ // checkBillingProjectPermission(tcSubject, contest);
+ // check billing cca
+ checkBillingProjectCCA(contest);
- /**
- * Contains all the contest type ids need custom contest activation email template, the ids are
- * separated with ';' and configured in ejb-jar.xml.
- *
- * @since 1.8.4
- */
- @Resource(name = "customActivateContestReceiptContestTypeIds")
- private String customActivateContestReceiptContestTypeIds;
+ SetcustomActivateContestReceiptContestTypeIds. The paths are separated with
- * ';' and configured in ejb-jar.xml
- *
- * @since 1.8.4
- */
- @Resource(name = "customActivateContestReceiptEmailTemplatePaths")
- private String customActivateContestReceiptEmailTemplatePaths;
+ // add back project on phase
+ for (int i = 0; i < phases.length; i++) {
+ phases[i].setProject(contest.getProjectPhases());
+ }
- /**
- * Email template file path for Spec Review Notification Email
- *
- * @since 1.0.2
- */
- @Resource(name = "specReviewNotificationEmailTemplatePath")
- private String specReviewNotificationEmailTemplatePath;
+ contest.getProjectPhases().setStartDate(getDate(productionDate));
- /**
- * BCC Address for Spec Review Notification Email
- *
- * @since 1.0.2
- */
- @Resource(name = "specReviewNotificationEmailBCCAddr")
- private String specReviewNotificationEmailBCCAddr;
+ contest.getProjectHeader().setTcDirectProjectId(tcDirectProjectId);
- /**
- * From Address for Spec Review Notification Email
- *
- * @since 1.0.2
- */
- @Resource(name = "specReviewNotificationEmailFromAddr")
- private String specReviewNotificationEmailFromAddr;
+ // update name in project info in case name is changed.
+ contest.getProjectHeader().setProperty(ProjectPropertyType.PROJECT_NAME_PROJECT_PROPERTY_KEY,
+ contest.getAssetDTO().getName());
- /**
- * Subject line for Spec Review Notification Email
- *
- * @since 1.0.2
- */
- @Resource(name = "specReviewNotificationEmailSubject")
- private String specReviewNotificationEmailSubject;
+ long billingProjectId = getBillingProjectId(contest);
- /**
- * The default prize for spec reviews
- *
- * @since 1.4
- */
- @Resource(name = "specReviewPrize")
- private Double specReviewPrize;
+ /*
+ * if (billingProjectId > 0) { // check billing account
+ * checkContestBillingAccount(billingProjectId,
+ * contest.getProjectHeader().getTcDirectProjectId()); }
+ */
- /**
- * The mock file path to use for submissions
- *
- * @since 1.4
- */
- private String mockSubmissionFilePath;
+ // dont send wiiner email for private
+ if (contest.getProjectHeader().getSecurityGroupId() > 0) {
+ contest.getProjectHeader().setProperty(ProjectPropertyType.SEND_WINNDER_EMAILS_PROJECT_PROPERTY_KEY, "false");
+ contest.getProjectHeader().setProperty(ProjectPropertyType.SVN_MODULE_PROJECT_PROPERTY_KEY, "");
- /**
- * The mock file name to use for submissions
- *
- * @since 1.4
- */
- @Resource(name = "mockSubmissionFileName")
- private String mockSubmissionFileName;
+ } else {
+ contest.getProjectHeader().setProperty(ProjectPropertyType.SEND_WINNDER_EMAILS_PROJECT_PROPERTY_KEY, "true");
+ boolean isDevContest = isDevContest(contest);
+
+ if (isDevContest && billingProjectId > 0) {
+
+ String codename = billingProjectDAO.getProjectById(billingProjectId).getClient().getCodeName();
+ String compname = contest.getAssetDTO().getName();
+ if (codename != null && !codename.equals("")) {
+ codename = CodeNameUtil.decodeCodeName(codename, "users");
+ compname = compname.toLowerCase().replaceAll(" ", "_").replaceAll("/", "_").replaceAll("&", "_");
+ codename = codename.toLowerCase().replaceAll(" ", "");
+ contest.getProjectHeader().setProperty(ProjectPropertyType.SVN_MODULE_PROJECT_PROPERTY_KEY,
+ "https://coder.topcoder.com/tcs/clients/" + codename + "/components/" + compname + "/trunk");
+ } else {
+ contest.getProjectHeader().setProperty(ProjectPropertyType.SVN_MODULE_PROJECT_PROPERTY_KEY, "");
+ }
+ }
+ }
- /**
- * Document generator that stores email templates.
- *
- * @since Cockpit Release Assembly for Receipts
- */
- private DocumentGenerator documentGenerator;
+ if (isCopilotContest(contest)) {
+ contest.getProjectHeader().setProperty(ProjectPropertyType.DIGITAL_RRUN_FLAG_PROJECT_PROPERTY_KEY, "Off");
+ contest.getProjectHeader().setProperty(ProjectPropertyType.DR_POINTS_PROJECT_PROPERTY_KEY, "0");
+ contest.getProjectHeader().setProperty(ProjectPropertyType.RATED_PROJECT_PROPERTY_KEY, "No");
+ contest.getProjectHeader().setProperty(ProjectPropertyType.CONFIDENTIALITY_TYPE_PROJECT_PROPERTY_KEY,
+ "standard_cca");
+ contest.getProjectHeader().setProperty(ProjectPropertyType.RELIABILITY_BONUS_ELIGIBLE_PROJECT_PROPERTY_KEY,
+ "false");
+ contest.getProjectHeader().setProperty(ProjectPropertyType.TRACK_LATE_DELIVERABLES_PROJECT_PROPERTY_KEY,
+ "false");
+ }
- /**
- * Email generator that generates email message from given template.
- *
- * @since Cockpit Release Assembly for Receipts
- */
- private EmailMessageGenerator emailMessageGenerator;
+ if (contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.BUG_HUNT.getId()) {
+ contest.getProjectHeader().setProperty(ProjectPropertyType.RELIABILITY_BONUS_ELIGIBLE_PROJECT_PROPERTY_KEY,
+ "false");
+ }
- /**
- * UploadManager instance which is used to get submission information.
- *
- * @since BUGR-3738
- */
- private UploadManager uploadManager;
+ if (isStudio(contest)) {
+ contest.getProjectHeader().setProperty(ProjectPropertyType.RATED_PROJECT_PROPERTY_KEY, "No");
+ contest.getProjectHeader().setProperty(ProjectPropertyType.TRACK_LATE_DELIVERABLES_PROJECT_PROPERTY_KEY,
+ "false");
+ }
+ if (contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.REPORTING.getId()
+ || contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.BUG_HUNT.getId()) {
+ contest.getProjectHeader().setProperty(ProjectPropertyType.DIGITAL_RRUN_FLAG_PROJECT_PROPERTY_KEY, "Off");
+ contest.getProjectHeader().setProperty(ProjectPropertyType.DR_POINTS_PROJECT_PROPERTY_KEY, "0");
+ contest.getProjectHeader().setProperty(ProjectPropertyType.RATED_PROJECT_PROPERTY_KEY, "No");
+ }
- /**
- * Project Manager instance which is used to perform level contest related operations.
- *
- * @since 1.9.2
- */
- private ProjectManager projectManager;
+ if (isPrivateProject(contest)) {
+ contest.getProjectHeader().setProperty(ProjectPropertyType.RATED_PROJECT_PROPERTY_KEY, "No");
+ }
+ // if (contest.getProjectHeader().getProjectCategory().getId() ==
+ // ProjectCategory.CONTENT_CREATION.getId())
+ // {
+ // contest.getProjectHeader().setProperty(ProjectPropertyType.DIGITAL_RRUN_FLAG_PROJECT_PROPERTY_KEY,
+ // "Off");
+ // contest.getProjectHeader().setProperty(ProjectPropertyType.DR_POINTS_PROJECT_PROPERTY_KEY,
+ // "0");
+ // }
- /**
- * user id for Applications
- *
- * @since 1.0.4
- */
- private long applications_user_id;
+ // preserve the information before update
+ boolean isTcDirectProjectChanged = (contest.getProjectHeader().getTcDirectProjectId() != this.projectServices
+ .getTcDirectProject(contest.getId()));
+ // get old copilots before update
+ com.topcoder.management.resource.Resource[] oldCopilots = projectServices
+ .searchResources(contest.getProjectHeader().getId(), ResourceRole.RESOURCE_ROLE_COPILOT_ID);
- /**
- * user id for Components
- *
- * @since 1.0.4
- */
- private long components_user_id;
+ // get old approvers before update
+ com.topcoder.management.resource.Resource[] oldApprovers = projectServices
+ .searchResources(contest.getProjectHeader().getId(), ResourceRole.RESOURCE_ROLE_APPROVER_ID);
- /**
- * The logger instance for logging the information in
- * ContestServiceFacadeBean.
- *
- * @since 1.1
- */
- private Logger logger = Logger.getLogger(this.getClass());
+ ListThe lookup DAO.
- */ - private LookupDAO lookupDAO; + ListThe copilot project DAO.
- */ - private CopilotProjectDAO copilotProjectDAO; + // we need to do remove task before projectServices delete the resources + for (Long r : oldCopilotManualPayments) { + removeManualCopilotPaymentByResourceId(contest.getId(), r); + } - private CopilotProfileDAO copilotProfileDAO; + for (com.topcoder.management.resource.Resource r : contest.getProjectResources()) { + if (r.getResourceRole().getId() == ResourceRole.RESOURCE_ROLE_COPILOT_ID) { + // check if current copilot has corresponding approver resource created + boolean hasApproverAdded = false; + for (com.topcoder.management.resource.Resource oldApprover : oldApprovers) { + if (oldApprover.getProperties().get(RESOURCE_INFO_EXTERNAL_REFERENCE_ID) + .equals(r.getProperties().get(RESOURCE_INFO_EXTERNAL_REFERENCE_ID))) { + hasApproverAdded = true; + } + } + if (!hasApproverAdded) { + // no added as approver, add it now + updatedResources.add(createApproverResourceFromCopilot(r, r.getProject())); + } + } + + if (r.getResourceRole().getId() == ResourceRole.RESOURCE_ROLE_APPROVER_ID) { + // check if the old approver needs to be removed + boolean needApproverRemoved = false; + for (com.topcoder.management.resource.Resource oldCopilot : oldCopilots) { + if (oldCopilot.getProperties().get(RESOURCE_INFO_EXTERNAL_REFERENCE_ID) + .equals(r.getProperties().get(RESOURCE_INFO_EXTERNAL_REFERENCE_ID))) { + needApproverRemoved = true; + } + } + // check if the old copilot is not in the new copilot list + if (needApproverRemoved + && !updatedCopilots.contains(r.getProperties().get(RESOURCE_INFO_EXTERNAL_REFERENCE_ID))) { + continue; + } + } + // if (r.getResourceRole().getId() != ResourceRole.RESOURCE_ROLE_SUBMITTER) { + updatedResources.add(r); + // } + } + + if (isF2FContest(contest)) { + // check if need to auto create reviewer for F2F contest + com.topcoder.management.resource.Resource[] oldReviewers = projectServices + .searchResources(contest.getProjectHeader().getId(), ResourceRole.RESOURCE_ROLE_ITERATIVE_REVIEWER_ID); + + if (oldReviewers != null && oldReviewers.length == 0 + && contest.getProjectHeader().getAutoAssignReviewerId() > 0) { + // no reviewers added and has auto reviewer id > 0 set, auto add iterative + // reviewer + + // 1) found out the iterative review phase + com.topcoder.project.phases.Phase iterativeReviewPhase = null; + for (com.topcoder.project.phases.Phase p : contest.getProjectPhases().getAllPhases()) { + if (p.getPhaseType().getId() == PhaseType.ITERATIVE_REVIEW_PHASE.getId()) { + iterativeReviewPhase = p; + break; + } + } - /** - * The helper map stores the mapping of contest type id to custom contset activation email template path. It's - * initialized in the init() method. - * - * @since 1.8.4 - */ - private Map
- * Constructs new ContestServiceFacadeBean instance. This
- * implementation instantiates new instance of payment processor. Current
- * implementation just support processing through PayPalCreditCard. When
- * multiple processors are desired the implementation should use factory
- * design pattern to get the right instance of the payment processor.
- *
- * This initializes the API Profile to the CallerServices. The
- * API profile are the merchant's (in this case TopCoder) PayPal API
- * details.
- *
- * TopCoder Service Layer Integration 3 Assembly change: new instance of the - * DefaultUploadServices for exposing its methods. - *
- * - *- * Updated for Cockpit Release Assembly for Receipts - documentGenerator and - * emailMessageGenerator instance created. - *
- * - *- * Updated in version 1.8.4: - * - Add the codes to load custom contest type id - custom contest acativation email template path mapping from - * the ejb configuration. - *
- * - * @throws IllegalStateException - * it throws this exception on any issues during caller services - * initialization. Issues can be: wrong authentication - * information, invalid information etc. - */ - @PostConstruct - public void init() { - if (logger == null) { - logger = Logger.getLogger(this.getClass()); } - logger.debug("Initializing PayflowProPaymentProcessor"); + com.topcoder.project.phases.Phase[] allPhases = projectData.getAllPhases(); + + // this is to avoid cycle + for (int i = 0; i < allPhases.length; i++) { + allPhases[i].setProject(null); + allPhases[i].clearDependencies(); + } + + // NOTE. comment out because now all challenges can set its groups, regards of + // its billing id status + // keep as reference + // + // // billing projct can change, set or unset + // // so for now easy way is removing current, and add if any + // List+ * Updates contest observer resources from direct project if the direct project + * associated is changed. + *
+ * + * @param tcSubject the current user + * @param contest the contest to be updated + * @throws Exception if any error occurs + */ + private void updateContestObserversFromDirectProject(TCSubject tcSubject, SoftwareCompetition contest) + throws Exception { + long forumId = projectServices.getForumId(contest.getId()); + + // Remove all current observers + for (com.topcoder.management.resource.Resource resource : this.projectServices.searchResources(contest.getId(), + ResourceRole.RESOURCE_ROLE_OBSERVER_ID)) { + deleteForumWatchAndRoleForResource(forumId, resource, contest, hasForumType(contest.getProjectHeader())); + this.projectServices.removeResource(resource, String.valueOf(tcSubject.getUserId())); + + } + + // Add observers + // add users has permission on cockpit project as observers + List+ * Deletes forum and role for the resource. + *
+ * + * @param forumId the forum id + * @param r the resource + * @param contest the contest data + * @param isNewForum whether the forum is ported from studio to software + */ + private void deleteForumWatchAndRoleForResource(long forumId, com.topcoder.management.resource.Resource r, + SoftwareCompetition contest, boolean isNewForum) { + if (forumId <= 0 || !createForum) { + return; + } + + long userId = Long.parseLong(r.getProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID)); + if (!isStudio(contest)) { + deleteSoftwareForumWatchAndRole(forumId, userId); + } else { + deleteStudioForumWatchAndRole(forumId, userId, isNewForum); + } + } + + /** + *+ * Add forum and role for the resource and also notification day. + *
+ * + * @param forumId the forum id + * @param r the resource + * @param contest the contest data + * @param isNewForum whether the forum is ported from studio to software + */ + private void addForumWatchAndRoleForResource(long forumId, com.topcoder.management.resource.Resource r, + SoftwareCompetition contest, TCSubject tcSubject, boolean isNewForum) throws Exception { + if (forumId <= 0 || !createForum) { + return; + } + + long userId = Long.parseLong(r.getProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID)); + long roleId = r.getResourceRole().getId(); + boolean addNotification; + boolean addForumWatch; + + List+ * Adds a new submission for an user in a particular project. + *
+ *+ * If the project allows multiple submissions for users, it will add the new + * submission and return. If multiple submission are not allowed for the + * project, firstly it will add the new submission, secondly mark previous + * submissions as deleted and then return. + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @param projectId the project's id + * @param filename the file name to use + * @param submission the submission file data + * @return the id of the new submission + * @throws IllegalArgumentException if any id is < 0, if any argument is + *null or trim to empty
+ * @throws ContestServiceException if an error occurs when interacting with the
+ * service layer.
+ * @since TopCoder Service Layer Integration 3 Assembly
+ */
+ public long uploadSubmission(TCSubject tcSubject, long projectId, String filename, DataHandler submission)
+ throws ContestServiceException {
+ return uploadSubmission(tcSubject.getUserId(), projectId, filename, submission);
+ }
+
+ /**
+ * + * Adds a new submission for an user in a particular project. + *
+ *+ * If the project allows multiple submissions for users, it will add the new + * submission and return. If multiple submission are not allowed for the + * project, firstly it will add the new submission, secondly mark previous + * submissions as deleted and then return. + *
+ * + * @param userId user Id + * @param projectId project Id + * @param filename filename + * @param submission submission data + * @return + * @throws ContestServiceException + * @since 3.5 + */ + public long uploadSubmission(long userId, long projectId, String filename, DataHandler submission) + throws ContestServiceException { + logger.debug("uploadSubmission"); + + try { + logger.debug("Exit updateSoftwareContest"); + + return uploadExternalServices.uploadSubmission(projectId, userId, filename, submission); + } catch (UploadServicesException e) { + logger.error("Operation failed in the uploadExternalServices.", e); + throw new ContestServiceException("Operation failed in the uploadExternalServices.", e); + } catch (RemoteException e) { + logger.error("Operation failed in the uploadExternalServices.", e); + throw new ContestServiceException("Operation failed in the uploadExternalServices.", e); + } + } + + /** + *+ * Adds a new final fix upload for an user in a particular project. This + * submission always overwrite the previous ones. + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @param projectId the project's id + * @param filename the file name to use + * @param finalFix the final fix file data + * @return the id of the created final fix submission + * @throws IllegalArgumentException if any id is < 0, if any argument is + *null or trim to empty
+ * @throws ContestServiceException if an error occurs when interacting with the
+ * service layer.
+ * @since TopCoder Service Layer Integration 3 Assembly
+ */
+ public long uploadFinalFix(TCSubject tcSubject, long projectId, String filename, DataHandler finalFix)
+ throws ContestServiceException {
+ logger.debug("uploadFinalFix");
+
+ try {
+ logger.debug("Exit uploadFinalFix");
+
+ return uploadExternalServices.uploadFinalFix(projectId, tcSubject.getUserId(), filename, finalFix);
+ } catch (UploadServicesException e) {
+ logger.error("Operation failed in the uploadExternalServices.", e);
+ throw new ContestServiceException("Operation failed in the uploadExternalServices.", e);
+ } catch (RemoteException e) {
+ logger.error("Operation failed in the uploadExternalServices.", e);
+ throw new ContestServiceException("Operation failed in the uploadExternalServices.", e);
+ }
+ }
+
+ /**
+ * + * Adds a new test case upload for an user in a particular project. This + * submission always overwrite the previous ones. + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @param projectId the project's id + * @param filename the file name to use + * @param testCases the test cases data + * @return the id of the created test cases submission + * @throws IllegalArgumentException if any id is < 0, if any argument is + *null or trim to empty
+ * @throws ContestServiceException if an error occurs when interacting with the
+ * service layer.
+ * @since TopCoder Service Layer Integration 3 Assembly
+ */
+ public long uploadTestCases(TCSubject tcSubject, long projectId, String filename, DataHandler testCases)
+ throws ContestServiceException {
+ logger.debug("uploadTestCases");
+
+ try {
+ logger.debug("Exit uploadTestCases");
+
+ return uploadExternalServices.uploadTestCases(projectId, tcSubject.getUserId(), filename, testCases);
+ } catch (UploadServicesException e) {
+ logger.error("Operation failed in the uploadExternalServices.", e);
+ throw new ContestServiceException("Operation failed in the uploadExternalServices.", e);
+ } catch (RemoteException e) {
+ logger.error("Operation failed in the uploadExternalServices.", e);
+ throw new ContestServiceException("Operation failed in the uploadExternalServices.", e);
+ }
+ }
+
+ /**
+ * + * Sets the status of a existing submission. + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info + * for the current user + * @param submissionId the submission's id + * @param submissionStatusId the submission status id + * @param operator the operator which execute the operation + * @throws IllegalArgumentException if any id is < 0 or if operator is null + * or trim to empty + * @throws ContestServiceException if an error occurs when interacting with the + * service layer. + * @since TopCoder Service Layer Integration 3 Assembly + */ + public void setSubmissionStatus(TCSubject tcSubject, long submissionId, long submissionStatusId, String operator) + throws ContestServiceException { + logger.debug("setSubmissionStatus"); + + try { + uploadExternalServices.setSubmissionStatus(submissionId, submissionStatusId, operator); + logger.debug("Exit setSubmissionStatus"); + } catch (UploadServicesException e) { + logger.error("Operation failed in the uploadExternalServices.", e); + throw new ContestServiceException("Operation failed in the uploadExternalServices.", e); + } catch (RemoteException e) { + logger.error("Operation failed in the uploadExternalServices.", e); + throw new ContestServiceException("Operation failed in the uploadExternalServices.", e); + } + } + + /** + * Adds the given user as a new submitter to the given project id. + *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @param projectId the project to which the user needs to be added + * @param userId the user to be added + * @return the added resource id + * @throws IllegalArgumentException if any id is < 0 + * @throws ContestServiceException if an error occurs when interacting with the + * service layer. + * @since TopCoder Service Layer Integration 3 Assembly + */ + public long addSubmitter(TCSubject tcSubject, long projectId, long userId) throws ContestServiceException { + logger.debug("AddSubmitter (tcSubject = " + tcSubject.getUserId() + ", " + projectId + "," + userId + ")"); + + try { + return uploadExternalServices.addSubmitter(projectId, userId); + } catch (UploadServicesException e) { + logger.error("Operation failed in the uploadExternalServices.", e); + throw new ContestServiceException("Operation failed in the uploadExternalServices.", e); + } catch (RemoteException e) { + logger.error("Operation failed in the uploadExternalServices.", e); + throw new ContestServiceException("Operation failed in the uploadExternalServices.", e); + } + } + + /** + * Get the EJB handler for Forum EJB service. + * + * @param url the EJB bean url + * @return the forum EJB service handler. + * @throws NamingException if a naming exception is encountered. + * @throws RemoteException if remote error occurs. + * @throws CreateException if error occurs when creating EJB handler + * + * @since 1.6.6 + */ + private Forums getForumsEJBFromJNDI(String url) throws NamingException, CreateException, RemoteException { + Properties p = new Properties(); + p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); + p.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces"); + + p.put(Context.PROVIDER_URL, url); + + Context c = new InitialContext(p); + ForumsHome forumsHome = (ForumsHome) c.lookup(ForumsHome.EJB_REF_NAME); + + return forumsHome.create(); + } + + /** + * Get the Software Forum EJB service for Software competitions. + * + * @return the forums EJB service handler. + * @throws NamingException if a naming exception is encountered. + * @throws RemoteException if remote error occurs. + * @throws CreateException if error occurs when creating EJB handler + * + * @since 1.6.11 + */ + private Forums getSoftwareForums() throws RemoteException, NamingException, CreateException { + return getForumsEJBFromJNDI(softwareForumBeanProviderUrl); + } + + /** + * Get the Studio Forum EJB service for Studio competitions. + * + * @return the forums EJB service handler. + * @throws NamingException if a naming exception is encountered. + * @throws RemoteException if remote error occurs. + * @throws CreateException if error occurs when creating EJB handler + * + * @since 1.6.11 + */ + private Forums getStudioForums() throws RemoteException, NamingException, CreateException { + return getForumsEJBFromJNDI(studioForumBeanProviderUrl); + } + + /** + * Create studio forum with given parameters. It will lookup the ForumsHome + * interface, and create the studio forum by the ejb home interface. + * + * @param name the forum name + * @param userId the user id to user + * @return the long id of the create fourm + * @since 1.6.6 + */ + private long createStudioForum(String name, long userId) { + logger.debug("createStudioForm (name = " + name + ", userId = " + userId + ")"); + + try { + Forums forums = getSoftwareForums(); + long forumId = forums.createStudioForumV2(studioForumRootCategoryId, name); + if (forumId < 0) { + throw new Exception("createStudioForum returned negative forum ID: " + forumId); + } + forums.createForumWatch(userId, forumId); + return forumId; + } catch (Exception e) { + logger.error("*** Could not create a studio forum for " + name); + logger.error(e); + } + return -1; + } + + /** + * create forum with given parameters. It will lookup the ForumsHome interface, + * and ceate the forum by the ejb home interface. In the old version, this + * method misses the document, it's added in the version 1.1 + * + * @param asset The asset DTO to user + * @param userId userId The user id to use + * @param projectCategoryId The project category id to + * @return The long id of the created forum + */ + public long createForum(TCSubject tcSubject, AssetDTO asset, long userId, long projectCategoryId) { + long forumId = -1; + logger.debug("createForum (tcSubject = " + tcSubject.getUserId() + ", " + userId + ")"); + + try { + Forums forums = getSoftwareForums(); + + long phaseId = 0; + + try { + phaseId = Long.parseLong(asset.getPhase()); + } catch (Exception ee) { + } + + forumId = forums.createSoftwareComponentForums(asset.getName(), asset.getId(), asset.getCompVersionId(), phaseId, + Status.REQUESTED.getStatusId(), asset.getRootCategory().getId(), asset.getShortDescription(), + asset.getVersionText(), false, projectCategoryId); + + if (forumId < 0) { + throw new Exception("createStudioForum returned -1"); + } + + logger.error("Created forum " + forumId + " for " + asset.getName()); + + forums.assignRole(userId, "Software_Moderators_" + forumId); // BUGR- + // 1677 + + forums.createCategoryWatch(userId, forumId); + logger.debug("Exit createForum (" + userId + ")"); + + return forumId; + } catch (Exception e) { + logger.error("*** Could not create a forum for " + asset.getName()); + logger.error(e); + + return forumId; + } + } + + /** + * Close the forum + * + * @param forumid The long id of the forum + */ + public void closeForum(long forumid) { + long forumId = -1; + logger.debug("closeForum (forumid = " + forumid + ")"); + + try { + Properties p = new Properties(); + p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); + p.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces"); + p.put(Context.PROVIDER_URL, softwareForumBeanProviderUrl); + + Context c = new InitialContext(p); + ForumsHome forumsHome = (ForumsHome) c.lookup(ForumsHome.EJB_REF_NAME); + + Forums forums = forumsHome.create(); + + forums.closeCategory(forumid); + + logger.debug("Exit closeForum (" + forumid + ")"); + + } catch (Exception e) { + logger.error("*** Could not close forum for " + forumId); + logger.error(e); + } + } + + /** + *+ * Gets the list of all existing contests related to given project for my + * project widget. + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * + * @param pid given project id + * @return aList listing all existing contests. Empty list is
+ * returned if there are no contests found.
+ * @throws PersistenceException if any error occurs when getting contest.
+ */
+ @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
+ public List+ * Gets the list of all existing contests for my project widget. + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ *+ * Updated for v1.6 Direct Search Assembly - provided contest fee for each + * contest data + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @return aList listing all existing contests. Empty list is
+ * returned if there are no contests found.
+ * @throws PersistenceException if any error occurs when getting contest.
+ */
+ @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
+ public List+ * Version 1.7.1 - set project status id into the ProjectSummaryData returned + *
+ * + *+ * Version 1.7.5 - set project creation date into the ProjectSummaryData + * returned + *
+ * + * @param tcSubjectTCSubject object
+ * @return a list of ProjectSummaryData objects
+ *
+ * @throws ContestServiceException if any error occurs during processing
+ *
+ * @since 1.6
+ */
+ @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
+ public List+ * BURG-1716: We need to add a method to get software contest by project id, the + * method wil get all OR project related data, then from project property to get + * comp version id then to call getAssetByVersionId to get assetDTO, please + * check create software contest to see what data need to be returned. + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @param projectId the OR Project Id + * @return SoftwareCompetition + * @throws ContestServiceException if an error occurs when interacting with the + * service layer. + * @since BURG-1716 + */ + public SoftwareCompetition getSoftwareContestByProjectId(TCSubject tcSubject, long projectId) + throws ContestServiceException, PermissionServiceException { + logger.debug("getSoftwareContestByProjectId (tcSubject = " + tcSubject.getUserId() + ", " + projectId + ")"); + + SoftwareCompetition contest = new SoftwareCompetition(); + + try { + + checkSoftwareContestPermission(tcSubject, projectId, true); + + FullProjectData fullProjectData = this.projectServices.getFullProjectData(projectId); + + Boolean effortHoursEnabled = false; + try { + Client client = projectService.getClientByProject(fullProjectData.getProjectHeader().getTcDirectProjectId()); + if (client != null) { + effortHoursEnabled = client.isEffortHoursEnabled() == null ? false : client.isEffortHoursEnabled(); + } + + } catch (PersistenceFault e) { + effortHoursEnabled = false; + } + + if (!effortHoursEnabled) { + fullProjectData.getProjectHeader().getProperties().remove(ProjectPropertyType.EFFORT_HOURS_ESTIMATE); + } + + Long compVersionId = Long.parseLong(fullProjectData.getProjectHeader() + .getProperty(ProjectPropertyType.EXTERNAL_REFERENCE_ID_PROJECT_PROPERTY_KEY)); + contest.setAssetDTO(this.catalogService.getAssetByVersionId(compVersionId)); + contest.setProjectHeader(fullProjectData.getProjectHeader()); + contest.setProjectData(fullProjectData); + contest.setProjectPhases(fullProjectData); + contest.getProjectPhases().setId(fullProjectData.getProjectHeader().getId()); + contest.setId(projectId); + contest.setProjectResources(fullProjectData.getResources()); + + com.topcoder.project.phases.Phase[] allPhases = fullProjectData.getAllPhases(); + + Date startDate = contest.getProjectPhases().getStartDate(); + for (com.topcoder.project.phases.Phase p : contest.getProjectPhases().getPhases()) { + if (p.getPhaseType().getId() == PhaseType.REGISTRATION_PHASE.getId()) { + startDate = p.getFixedStartDate(); + break; + } + } + + // set project start date in production date + contest.getAssetDTO().setProductionDate(getXMLGregorianCalendar(startDate)); + + // set null to avoid cycle + contest.getAssetDTO().setDependencies(null); + + if (contest.getAssetDTO().getForum() != null) { + contest.getAssetDTO().getForum().setCompVersion(null); + } + + if (contest.getAssetDTO().getLink() != null) { + contest.getAssetDTO().getLink().setCompVersion(null); + } + + // need to remove loops before returning + removeDocumentationLoops(contest); + + // get the direct project milestone xref + contest + .setDirectProjectMilestoneId(projectServices.getProjectMilestoneRelation(contest.getProjectHeader().getId())); + + // get the security group id if there is any + List+ * Sends the email for specified template to specified to, cc, bcc address from + * specified from address. + *
+ * + * @param templateSource the template source + * @param templateName the template name or the file path of the template. + * @param subject the email subject line + * @param toAddr the to-address of the email + * @param ccAddr the from-address of the email + * @param bccAddr the bcc-address of the email + * @param fromAddr the from-address of the email + * @param phase the phase data + * @throws EmailMessageGenerationException thrown if error during email + * generation + * @throws EmailSendingException thrown if error during email sending. + * + * @since Cockpit Release Assembly for Receipts. + */ + private void sendEmail(String templateSource, String templateName, String subject, String[] toAddrs, String ccAddr, + String bccAddr, String fromAddr, com.topcoder.project.phases.Phase phase) + throws EmailMessageGenerationException, EmailSendingException { + boolean messageGenerated = false; + + try { + // Generate the message body first + Template template = (templateSource == null) ? documentGenerator.getTemplate(templateName) + : documentGenerator.getTemplate(templateSource, templateName); + String messageBody = this.emailMessageGenerator.generateMessage(documentGenerator, template, phase); + + logger.debug("Generated following email message of subject [" + subject + "] to be sent to [" + fromAddr + "] \n" + + messageBody); + + // Create a TCSEmailMessage to be sent + TCSEmailMessage email = new TCSEmailMessage(); + + // Set subject, from address and message body. + email.setSubject(subject); + email.setFromAddress(fromAddr); + email.setBody(messageBody); + email.setContentType("text/html"); + + ExceptionUtils.checkNull(toAddrs, null, null, "To address must be non-null."); + for (String toAddr : toAddrs) { + email.addToAddress(toAddr, TCSEmailMessage.TO); + } + + if (ccAddr != null) { + email.addToAddress(ccAddr, TCSEmailMessage.CC); + } + + if (bccAddr != null) { + email.addToAddress(bccAddr, TCSEmailMessage.BCC); + } + + // Now the email message is generated successfully + messageGenerated = true; + + // Send email + EmailEngine.send(email); + logger.debug("Sent email message of subject [" + subject + "] to [" + fromAddr + "]"); + } catch (BaseException e) { + rethrowEmailError(e, messageGenerated); + } catch (ConfigManagerException e) { + rethrowEmailError(e, messageGenerated); + } catch (IllegalArgumentException e) { + rethrowEmailError(e, messageGenerated); + } + } + + /** + *+ * Wrap the given error while sending email and re throw it. + *
+ * + *
+ * If given messageGenerated is false, then this error occurs while
+ * generating email message and thus an
+ * EmailMessageGenerationException will be thrown. Otherwise it
+ * means the error occurs while sending email and thus an
+ * EmailSendingException will be thrown.
+ *
messageGenerated is
+ * false.
+ * @throws EmailSendingException If messageGenerated is
+ * true.
+ *
+ * @since Cockpit Release Assembly for Receipts.
+ */
+ private void rethrowEmailError(Throwable e, boolean messageGenerated)
+ throws EmailMessageGenerationException, EmailSendingException {
+ try {
+ if (messageGenerated) {
+ throw (e instanceof EmailSendingException) ? (EmailSendingException) e
+ : new EmailSendingException("Error while sending email.", e);
+ } else {
+ throw (e instanceof EmailMessageGenerationException) ? (EmailMessageGenerationException) e
+ : new EmailMessageGenerationException("Error while generating email to be sent.", e);
+ }
+ } catch (Exception e1) {
+ logger.error("*** Could not generate or send an email to creator of contest", e1);
+ }
+ }
+
+ /**
+ * Creates and sends email for the activate contest receipt email.
+ *
+ *
+ * Updates in version 1.8.4: - Add the logic to dynamically load activation
+ * email template from the passed in competitionTypeId
+ *
+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @param contestId the contest id + * @param studio indicates whether the specified contest id is for studio + * contests. + * @return the spec review that matches the specified contest id. + * @throws ContestServiceException if any error during retrieval/save from + * persistence + * @since Cockpit Launch Contest - Inline Spec Review Part 2 + */ + public SpecReview getSpecReviews(TCSubject tcSubject, long contestId, boolean studio) throws ContestServiceException { + try { + return this.specReviewService.getSpecReviews(contestId, studio); + } catch (SpecReviewServiceException e) { + throw new ContestServiceException("Error during getSpecReviews", e); + } + } + + /** + * Save specified review comment and review status for specified section and + * specified contest id to persistence. + *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for + * the current user + * @param contestId the contest id + * @param studio indicates whether the specified contest id is for studio + * contests. + * @param sectionName the section name + * @param comment the comment + * @param isPass the is pass + * @param role the user role type + * @throws ContestServiceException if any error during retrieval/save from + * persistence + * @since Cockpit Launch Contest - Inline Spec Review Part 2 + */ + public void saveReviewStatus(TCSubject tcSubject, long contestId, boolean studio, String sectionName, String comment, + boolean isPass, String role) throws ContestServiceException { + try { + this.specReviewService.saveReviewStatus(tcSubject, contestId, studio, sectionName, comment, isPass, role); + } catch (SpecReviewServiceException e) { + throw new ContestServiceException("Error during saveReviewStatus", e); + } + } + + /** + * Save specified review comment for specified section and specified contest id + * to persistence. + *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for + * the current user + * @param contestId the contest id + * @param studio indicates whether the specified contest id is for studio + * contests. + * @param sectionName the section name + * @param comment the comment + * @param role the user role type + * @throws ContestServiceException if any error during retrieval/save from + * persistence + * @since Cockpit Launch Contest - Inline Spec Review Part 2 + */ + public void saveReviewComment(TCSubject tcSubject, long contestId, boolean studio, String sectionName, String comment, + String role) throws ContestServiceException { + try { + this.specReviewService.saveReviewComment(tcSubject, contestId, studio, sectionName, comment, role); + } catch (SpecReviewServiceException e) { + throw new ContestServiceException("Error during saveReviewComment", e); + } + } + + /** + * Mark review comment with specified comment id as seen. + *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @param commentId the comment id + * @throws ContestServiceException if any error during retrieval/save from + * persistence + * @since Cockpit Launch Contest - Inline Spec Review Part 2 + */ + public void markReviewCommentSeen(TCSubject tcSubject, long commentId) throws ContestServiceException { + try { + this.specReviewService.markReviewCommentSeen(tcSubject, commentId); + } catch (SpecReviewServiceException e) { + throw new ContestServiceException("Error during markReviewCommentSeen", e); + } + } + + /** + * Marks 'review done' by reviewer of the specs for specified contest. + * Persistence is updated and all end users having write/full permission on the + * contest are notified by email. + *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for + * the current user + * @param contestId the specified contest id. + * @param contestName the contest name + * @param studio whether contest is studio or not. + * @tcDirectProjectId the tc direct project id. + * @throws ContestServiceException if any error during retrieval/save from + * persistence + * @since 1.0.1 + */ + public void markReviewDone(TCSubject tcSubject, long contestId, String contestName, boolean studio, + long tcDirectProjectId) throws ContestServiceException { + try { + // get updates. + List+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @param contestId the specified contest id. + * @param studio whether contest is studio or not. + * @throws ContestServiceException if any error during retrieval/save from + * persistence + * @since 1.0.1 + */ + public void markReadyForReview(TCSubject tcSubject, long contestId, boolean studio) throws ContestServiceException { + try { + this.specReviewService.markReadyForReview(tcSubject, contestId, studio); + } catch (SpecReviewServiceException e) { + throw new ContestServiceException("Error during markReadyForReview", e); + } + } + + /** + * Marks 'resubmit for review' by the writer of the specs for specified contest. + * Persistence is updated. Reviewer (if any) is notified about the updates. + *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for + * the current user + * @param contestId the specified contest id. + * @param contestName the contest name + * @param studio whether contest is studio or not. + * @param reviewerUserId reviewer user id. + * @throws ContestServiceException if any error during retrieval/save from + * persistence + * @since 1.0.1 + */ + public void resubmitForReview(TCSubject tcSubject, long contestId, String contestName, boolean studio, + long reviewerUserId) throws ContestServiceException { + try { + // get updates. + List+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @param projectId the billing project id + * @return the list of project contest fees for the given project id + * @throws ContestServiceException if any persistence or other error occurs + * @since 1.0.1 + */ + public List+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @throws ContestServiceException if any other error occurs + * @since 1.1 + */ + public List+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @param userId The user id + * @param contestId The contest id + * @param isStudio true if the contest is a studio contest, false otherwise. + * @return true if the user is eligible for the specified contest, false + * otherwise. + * @throws ContestServiceException if any other error occurs + * @since 1.2.2 + */ + public boolean isEligible(TCSubject tcSubject, long userId, long contestId, boolean isStudio) + throws ContestServiceException { + String methodName = "isEligible"; + logger.info("Enter: " + methodName); + + boolean eligible = false; + + try { + List+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info + * for the current user + * @param billingProjectId; The ID of the billing project. + * @return The name of the eligibility group. + * @since 1.2.3 + */ + public String getEligibilityName(TCSubject tcSubject, long billingProjectId) { + String methodName = "getEligibilityName : billing project id = " + billingProjectId; + logger.info("Enter: " + methodName); + try { + ConfigManager cfgMgr = ConfigManager.getInstance(); + Property rootProperty = cfgMgr.getPropertyObject(CONTEST_ELIGIBILITY_MAPPING_NAMESPACE, + CONTEST_ELIGIBILITY_MAPPING_PREFIX); + Property eligibility = rootProperty.getProperty(Long.toString(billingProjectId)); + if (eligibility != null && !eligibility.equals("")) { + + return (String) (eligibility.getValue(ELIGIBILITY_NAME)); + } + return ""; + } catch (Exception e) { + logger.error("Cannot retrieve eligibility name."); + return ""; + } finally { + logger.info("Exit: " + methodName); + } + } + + /** + * Find eligibility admin role for the billing project. + *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info + * for the current user + * @param billingProjectId; The ID of the billing project. + * @return The name of the eligibility group. + * @since 1.2.3 + * + * public String getEligibilityAdminRole(TCSubject tcSubject, long + * billingProjectId) { String methodName = "getEligibilityAdminRole : + * billing project id = "+ billingProjectId; logger.info("Enter: " + + * methodName); try { ConfigManager cfgMgr = ConfigManager.getInstance(); + * Property rootProperty = + * cfgMgr.getPropertyObject(CONTEST_ELIGIBILITY_MAPPING_NAMESPACE, + * CONTEST_ELIGIBILITY_MAPPING_PREFIX); Property eligibility = + * rootProperty.getProperty(Long.toString(billingProjectId)); if + * (eligibility != null && !eligibility.equals("")) { + * + * return (String)(eligibility.getValue(ELIGIBILITY_ADMIN_ROLE)); } + * return ""; } catch (Exception e) { logger.error("Cannot retrieve + * eligibility admin role."); return ""; } finally { logger.info("Exit: " + * + methodName); } } + **/ + + /** + * Private helper method to remove loops within documentation collection in + * AssetDTO + * + * @param contest the contest which needs loops removal + * + * @since 1.3.4 + */ + private void removeDocumentationLoops(SoftwareCompetition contest) { + if (contest.getAssetDTO().getDocumentation() != null && contest.getAssetDTO().getDocumentation().size() > 0) { + for (CompDocumentation doc : contest.getAssetDTO().getDocumentation()) { + doc.setCompVersion(null); + } + } + } + + /** + * Returns whether the contest is private. + * + *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @param contestId The contest id + * @param isStudio true if the contest is a studio contest, false otherwise. + * @return true if the contest is a private one, false otherwise. + * + * @throws ContestServiceException if any other error occurs + * @since 1.2.3 + */ + public boolean isPrivate(TCSubject tcSubject, long contestId, boolean isStudio) throws ContestServiceException { + String methodName = "isPrivate"; + logger.info("Enter: " + methodName); + + List+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @param projectId the project id to create a Specification Review for + * @return the created project + * @throws ContestServiceException if any unexpected error occurs in the + * underlying services + * @since 1.4 + */ + public FullProjectData createSpecReview(TCSubject tcSubject, long projectId) throws ContestServiceException { + String method = "createSpecReview(tcSubject = " + tcSubject.getUserId() + "," + projectId + ")"; + logger.info("Enter: " + method); + + FullProjectData specReview = null; + try { + specReview = projectServices.createSpecReview(projectId, specReviewPrize, String.valueOf(tcSubject.getUserId()), + getUserName(tcSubject)); + } catch (ProjectServicesException e) { + logger.error("Operation failed in ProjectServices.", e); + throw new ContestServiceException("Operation failed in Project Services.", e); + } finally { + logger.info("Exit: " + method); + } + + return specReview; + } + + /** + * This method retrieves scorecard and review information associated to a + * project determined by parameter. Note: a single reviewer / review is assumed. + *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @param projectId the project id to search for + * @return the aggregated scorecard and review data + * @throws ContestServiceException if any unexpected error occurs in the + * underlying services + * @since 1.4 + */ + public ScorecardReviewData getScorecardAndReview(TCSubject tcSubject, long projectId) throws ContestServiceException { + String method = "getScorecardAndReview(tcSubject = " + tcSubject.getUserId() + "," + projectId + ")"; + logger.info("Enter: " + method); + + ScorecardReviewData scorecardReviewData = null; + try { + scorecardReviewData = projectServices.getScorecardAndReview(projectId); + } catch (ProjectServicesException e) { + logger.error("Operation failed in Project Services.", e); + throw new ContestServiceException("Operation failed in Project Services.", e); + } finally { + logger.info("Exit: " + method); + } + + return scorecardReviewData; + } + + /** + * This method uploads a mock file to the corresponding specification review + * project of the specified project id, so that it can continue with review. + * Regular submission or final fix will be uploaded according to the open phase. + *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @param projectId the project id of the original project + * @throws ContestServiceException if any unexpected error occurs in the + * underlying services, if the associated + * specification review project id cannot be + * found or if neither submission or final fixes + * phase are open. + * @since 1.4 + */ + public void markSoftwareContestReadyForReview(TCSubject tcSubject, long projectId) throws ContestServiceException { + String method = "markSoftwareContestReadyForReview(tcSubject = " + tcSubject.getUserId() + "," + projectId + ")"; + logger.info("Enter: " + method); + + try { + // get associated specification review project id + long specReviewProjectId = projectServices.getSpecReviewProjectId(projectId); + if (specReviewProjectId < 0) { + throw new ContestServiceException("Failed to get associated specification review."); + } + + // get associated specification review open phases + Set+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info for the + * current user + * @param reviewId the review id to add the comment to + * @param comment the review comment to add + * @throws ContestServiceException if any unexpected error occurs in the + * underlying services. + * @throws IllegalArgumentException if comment is null + * @since 1.4 + */ + public void addReviewComment(TCSubject tcSubject, long reviewId, Comment comment) throws ContestServiceException { + if (comment == null) { + throw new IllegalArgumentException("The comment cannot be null"); + } + + String method = "addReviewComment(tcSubject = " + tcSubject.getUserId() + "," + reviewId + ", " + comment + ")"; + logger.info("Enter: " + method); + + try { + projectServices.addReviewComment(reviewId, comment, String.valueOf(tcSubject.getUserId())); + } catch (ProjectServicesException e) { + logger.error("Operation failed in Project Services.", e); + throw new ContestServiceException("Operation failed in Project Services.", e); + } finally { + logger.info("Exit: " + method); + } + } + + /** + * create software forum watch with given parameters. It will lookup the + * ForumsHome interface, and ceate the forum by the ejb home interface. In the + * old version, this method misses the document, it's added in the version 1.1 + * + * + * @param asset The asset DTO to user + * @param userId userId The user id to use + * @param projectCategoryId The project category id to + * @return The long id of the created forum + */ + private void createSoftwareForumWatchAndRole(long forumId, long userId, boolean watch) { + logger.debug("createSoftwareForumWatchAndRole (" + forumId + ", " + userId + ")"); + + try { + Forums forums = getSoftwareForums(); + + String roleId = "Software_Moderators_" + forumId; + if (watch) { + forums.createCategoryWatch(userId, forumId); + } + + forums.assignRole(userId, roleId); + + logger.debug("Exit createSoftwareForumWatchAndRole (" + forumId + ", " + userId + ")"); + + } catch (Exception e) { + logger.error("*** Could not create a softwaer forum watch for " + forumId + ", " + userId); + logger.error(e); + } + } + + /** + * create stduio forum watch with given parameters. It will lookup the + * ForumsHome interface, and ceate the forum by the ejb home interface. In the + * old version, this method misses the document, it's added in the version 1.1 + * + * + * @param asset The asset DTO to user + * @param userId userId The user id to use + * @param projectCategoryId The project category id to + * @param isNewStudioForum whether the forum is ported to the studio part. + * @return The long id of the created forum + */ + private void createStudioForumWatchAndRole(long forumId, long userId, boolean watch, boolean isNewStudioForum) { + logger.debug("createStudioForumWatchAndRole (" + forumId + ", " + userId + ")"); + + try { + Forums forums = isNewStudioForum ? getSoftwareForums() : getStudioForums(); + + String roleId = "Software_Moderators_" + forumId; + if (watch) { + forums.createForumWatch(userId, forumId); + } + + forums.assignRole(userId, roleId); + + logger.debug("Exit createStudioForumWatchAndRole (" + forumId + ", " + userId + ")"); + + } catch (Exception e) { + logger.error("*** Could not create a studio forum watch for " + forumId + ", " + userId); + logger.error(e); + } + } + + /** + * delete software forum watch with given parameters. It will lookup the + * ForumsHome interface, and ceate the forum by the ejb home interface. In the + * old version, this method misses the document, it's added in the version 1.1 + * + * + * @param forumId The forum id to delete watch. + * @param userId userId The user id to use + */ + private void deleteSoftwareForumWatchAndRole(long forumId, long userId) { + logger.info("deleteForumWatch (" + forumId + ", " + userId + ")"); + + try { + Forums forums = getSoftwareForums(); + + String roleId = "Software_Moderators_" + forumId; + forums.deleteCategoryWatch(userId, forumId); + forums.removeRole(userId, roleId); + logger.debug("Exit deleteForumWatch (" + forumId + ", " + userId + ")"); + + } catch (Exception e) { + logger.error("*** Could not delete forum watch for " + forumId + ", " + userId); + logger.error(e); + } + } + + /** + * delete forum watch with given parameters. It will lookup the ForumsHome + * interface, and ceate the forum by the ejb home interface. In the old version, + * this method misses the document, it's added in the version 1.1 + * + * + * @param forumId The forum id to delete watch. + * @param userId userId The user id to use + * @param isNewStudioForum whethether the studio forum is ported to the software + * forum + */ + private void deleteStudioForumWatchAndRole(long forumId, long userId, boolean isNewStudioForum) { + logger.info("deleteForumWatch (" + forumId + ", " + userId + ")"); + + try { + Forums forums = isNewStudioForum ? getSoftwareForums() : getStudioForums(); + + String roleId = "Software_Moderators_" + forumId; + forums.deleteForumWatch(userId, forumId); + forums.removeRole(userId, roleId); + logger.debug("Exit deleteForumWatch (" + forumId + ", " + userId + ")"); + + } catch (Exception e) { + logger.error("*** Could not delete forum watch for " + forumId + ", " + userId); + logger.error(e); + } + } + + /** + * update forum name + * + * @param forumId The forum id to update + * @param name The name to use + */ + private void updateForumName(long forumId, String name) { + logger.info("updateForumName (" + forumId + ", " + name + ")"); + + try { + Forums forums = getSoftwareForums(); + + forums.updateComponentName(forumId, name); + + logger.debug("Exit updateForumName (" + forumId + ", " + name + ")"); + + } catch (Exception e) { + logger.error("*** Could not updateForumName for " + forumId + ", " + name); + logger.error(e); + } + } + + /** + * Update studio forum name. + * + * @param forumId The forum id to update + * @param name The name to use + */ + private void updateStudioForumName(long forumId, String name) { + logger.info("updateStudioForumName (" + forumId + ", " + name + ")"); + + try { + Forums forums = getSoftwareForums(); + + forums.updateStudioForumName(forumId, name); + + logger.debug("Exit updateStudioForumName (" + forumId + ", " + name + ")"); + + } catch (Exception e) { + logger.error("*** Could not updateStudioForumName for " + forumId + ", " + name); + logger.error(e); + } + } + + /** + * check if user agrees the term(s) associate with the project (if any) by role + * + * @param projectId OR project id + * @param userId userId The user id to use + * @param roleId role id + * @return true if user agreed terms or no term associated with project + */ + private boolean checkTerms(long projectId, long userId, int[] roleIds) { + logger.info("checkTerms (" + projectId + ", " + userId + ", " + roleIds + ")"); + + try { + Properties p = new Properties(); + p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); + p.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces"); + p.put(Context.PROVIDER_URL, userBeanProviderUrl); + + Context c = new InitialContext(p); + UserTermsOfUseHome userTermsOfUseHome = (UserTermsOfUseHome) c.lookup(UserTermsOfUseHome.EJB_REF_NAME); + + UserTermsOfUse userTerm = userTermsOfUseHome.create(); + + Properties p2 = new Properties(); + p2.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); + p2.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces"); + p2.put(Context.PROVIDER_URL, projectBeanProviderUrl); + + Context c2 = new InitialContext(p2); + ProjectRoleTermsOfUseHome projectRoleTermsOfUseHome = (ProjectRoleTermsOfUseHome) c2 + .lookup(ProjectRoleTermsOfUseHome.EJB_REF_NAME); + + ProjectRoleTermsOfUse projectTerm = projectRoleTermsOfUseHome.create(); + + List+ * Create new version for design or development contest. (project_status_id = + * 4-10 in tcs_catalog:project_status_lu). + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info + * for the current user + * @param projectId the project to create new version + * @param tcDirectProjectId tc direct project id + * @param autoDevCreating if it is true and it is design contest, then will + * create development too + * @param startDate the start date for the new version contest + * @return newly version contest id + * @throws ContestServiceException if any error occurs + */ + private long createNewVersionForDesignDevContest(TCSubject tcSubject, long projectId, long tcDirectProjectId, + boolean autoDevCreating, XMLGregorianCalendar startDate, boolean minorVersion) + throws ContestServiceException, PermissionServiceException { + try { + // 0.check the permission first + checkSoftwareProjectPermission(tcSubject, tcDirectProjectId, true); + // 1. for now, only completed can create new version + FullProjectData contest = this.projectServices.getFullProjectData(projectId); + // if auto dev creating, dont check, since we pass the new design project id + if (!autoDevCreating + && contest.getProjectHeader().getProjectStatus().getId() != ProjectStatus.COMPLETED_STATUS_ID) { + throw new ProjectServicesException( + "The design project or its corresponding development project is not completed." + + " You can not create new version for it."); + } + boolean isDevContest = contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.DEVELOPMENT + .getId(); + + // 2.create new version + Long compVersionId = Long.parseLong( + contest.getProjectHeader().getProperty(ProjectPropertyType.EXTERNAL_REFERENCE_ID_PROJECT_PROPERTY_KEY)); + AssetDTO dto = catalogService.getAssetByVersionId(compVersionId); + // close current version + dto.setPhase("Completed"); + com.topcoder.project.phases.Phase[] phases = contest.getAllPhases(); + dto.setProductionDate(getXMLGregorianCalendar(phases[phases.length - 1].getActualEndDate())); + // close current forum + if (createForum && dto.getForum() != null) { + closeForum(dto.getForum().getJiveCategoryId()); + } + dto.setForum(null); + catalogService.updateAsset(dto); + + // create minor or major version + dto.setToCreateMinorVersion(minorVersion); + dto.setProductionDate(null); + + // if it is dev only, or design, create new version here + if (!isDevContest || !autoDevCreating) { + // clear the version + dto.setCompVersionId(null); + dto.setForum(null); + dto.setDocumentation(new ArrayList+ * Create new version for design or development contest. (project_status_id = + * 4-10 in tcs_catalog:project_status_lu). + *
+ *+ * since version 1.5. + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info + * for the current user + * @param projectId the project to create new version + * @param tcDirectProjectId tc direct project id + * @param autoDevCreating if it is true and it is design contest, then will + * create development too + * @return newly version contest id + * @throws ContestServiceException if any error occurs + */ + public long createNewVersionForDesignDevContest(TCSubject tcSubject, long projectId, long tcDirectProjectId, + boolean autoDevCreating, boolean minorVersion) throws ContestServiceException, PermissionServiceException { + logger.debug( + "createNewVersionForDesignDevContest with parameter [TCSubject " + tcSubject.getUserId() + ", projectId =" + + projectId + ", tcDirectProjectId =" + tcDirectProjectId + ", autoDevCreating=" + autoDevCreating + "]."); + + return createNewVersionForDesignDevContest(tcSubject, projectId, tcDirectProjectId, autoDevCreating, + nextReOpenNewReleaseDay(), minorVersion); + } + + /** + *+ * Reopen the software contest. + *
+ *+ * since version 1.5. + *
+ *+ * Update in v1.5.1: add parameter TCSubject which contains the security info + * for current user. + *
+ * + * @param tcSubject TCSubject instance contains the login security info + * for the current user + * @param projectId the project to repost + * @param tcDirectProjectId the tc direct project id + * @return the newly created OR project id + * @throws ContestServiceException if any error occurs during repost + */ + public long reOpenSoftwareContest(TCSubject tcSubject, long projectId, long tcDirectProjectId) + throws ContestServiceException, PermissionServiceException { + logger.debug("reOpenSoftwareContest with parameter [TCSubject " + tcSubject.getUserId() + ", projectId =" + + projectId + ", tcDirectProjectId =" + tcDirectProjectId + "]."); + + long reOpenContestId = 0; + try { + + // 0.check the permission first + checkSoftwareProjectPermission(tcSubject, tcDirectProjectId, true); + + // 1.make sure it is failed status and can be re-opened. + FullProjectData contest = projectServices.getFullProjectData(projectId); + if (contest == null) { + throw new ContestServiceException("The project does not exist."); + } + if (contest.getProjectHeader().getProjectStatus().getId() != ProjectStatus.CANCELLED_FAILED_REVIEW_ID + && contest.getProjectHeader().getProjectStatus().getId() != ProjectStatus.CANCELLED_FAILED_SCREENING_ID + && contest.getProjectHeader().getProjectStatus().getId() != ProjectStatus.CANCELLED_ZERO_SUBMISSION_ID + && contest.getProjectHeader().getProjectStatus().getId() != ProjectStatus.CANCELLED_WINNER_UNRESPONSIVE_ID + && contest.getProjectHeader().getProjectStatus().getId() != ProjectStatus.CANCELLED_CLIENT_REQUEST.getId() + && contest.getProjectHeader().getProjectStatus().getId() != ProjectStatus.CANCELLED_REQUIREMENTS_INFEASIBLE + .getId() + && contest.getProjectHeader().getProjectStatus().getId() != ProjectStatus.CANCELLED_ZERO_REGISTRATIONS + .getId()) { + throw new ProjectServicesException("The project is not failed. You can not re-open it."); + } + + // set status to draft + contest.getProjectHeader().setProjectStatus(ProjectStatus.DRAFT); + + contest.setStartDate(getDate(nextReOpenNewReleaseDay())); + // 2.create the project + FullProjectData reOpendedProject = projectServices.createReOpenContest(contest, + String.valueOf(tcSubject.getUserId())); + + // 3. keep terms and eligibility + ListPhase associated with the resource.
+ * @param isStudio whether assign to studio contest.
+ * @since 1.6.9
+ */
+ private void assignRole(TCSubject tcSubject, long projectId, long roleId, long userId,
+ com.topcoder.project.phases.Phase phase, boolean addNotification, boolean addForumWatch, boolean isStudio,
+ boolean checkTerm) throws ContestServiceException {
+ logger.debug("enter methods assignRole");
+
+ try {
+ // com.topcoder.management.resource.Resource[] resources =
+ // projectServices.searchResources(projectId, roleId);
+
+ boolean found = false;
+
+ found = projectServices.resourceExists(projectId, roleId, userId);
+
+ boolean termChecking = !checkTerm || checkTerms(projectId, userId, new int[] { (int) roleId });
+
+ // if not found && user agreed terms (if any) && is eligible, add resource
+ if (!found && termChecking && isEligible(tcSubject, userId, projectId, false)) {
+
+ com.topcoder.management.resource.Resource newRes = new com.topcoder.management.resource.Resource();
+ newRes.setId(com.topcoder.management.resource.Resource.UNSET_ID);
+ newRes.setProject(projectId);
+
+ ResourceRole[] allroles = projectServices.getAllResourceRoles();
+ ResourceRole roleToSet = null;
+ if (allroles != null && allroles.length > 0) {
+ for (ResourceRole role : allroles) {
+ if (role.getId() == roleId) {
+ roleToSet = role;
+ }
+ }
+ }
+
+ if (roleToSet == null) {
+ throw new ContestServiceException("Invalid role id " + roleId);
+ }
+
+ newRes.setResourceRole(roleToSet);
+ if (phase != null) {
+ newRes.setPhase(phase.getId());
+ }
+
+ newRes.setProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID, String.valueOf(userId));
+ newRes.setProperty(RESOURCE_INFO_HANDLE, String.valueOf(userService.getUserHandle(userId)));
+ newRes.setProperty(RESOURCE_INFO_PAYMENT_STATUS, RESOURCE_INFO_PAYMENT_STATUS_NA);
+ newRes.setProperty(RESOURCE_INFO_REGISTRATION_DATE, DATE_FORMAT.format(new Date()));
+ newRes.setUserId(userId);
+ projectServices.updateResource(newRes, String.valueOf(tcSubject.getUserId()));
+
+ // only check notification setting for observer, else always addd
+ if (roleId != ResourceRole.RESOURCE_ROLE_OBSERVER_ID || addNotification) {
+ projectServices.addNotifications(userId, new long[] { projectId }, String.valueOf(tcSubject.getUserId()));
+ }
+
+ // create forum watch
+ long forumId = projectServices.getForumId(projectId);
+
+ // only check notification for observer
+ if (roleId != ResourceRole.RESOURCE_ROLE_OBSERVER_ID) {
+ addForumWatch = true;
+ }
+
+ if (forumId > 0 && createForum && !isStudio) {
+ createSoftwareForumWatchAndRole(forumId, userId, addForumWatch);
+ }
+
+ }
+
+ } catch (UserServiceException use) {
+ sessionContext.setRollbackOnly();
+ throw new ContestServiceException(use.getMessage(), use);
+ } catch (ContestServiceException cse) {
+ sessionContext.setRollbackOnly();
+ throw new ContestServiceException(cse.getMessage(), cse);
+ } finally {
+ logger.debug("exist method assignRole");
+ }
+ }
+
+ /**
+ * Assign the given roleId to the specified userId in the given project.
+ *
+ * @param tcSubject the TCSubject instance.
+ * @param projectId the id of the project.
+ * @param roleId the id of the role.
+ * @param userId the id of the user.
+ *
+ * @since BUGR-3731
+ */
+ public void assginRole(TCSubject tcSubject, long projectId, long roleId, long userId) throws ContestServiceException {
+ assignRole(tcSubject, projectId, roleId, userId, null, true, true, false, false);
+ }
+
+ /*
+ * Assigns the role for the given tc project and user, it will assign all
+ * projects uder tc direct projct
+ *
+ * @param tcprojectId the id of the tc direct project.
+ *
+ * @param roleId the id of the role
+ *
+ * @param userId the id of the user.
+ *
+ * @throws ContestServiceException if any error occurs
+ *
+ * @since BUGR - 3731
+ */
+ public void assginRoleByTCDirectProject(TCSubject tcSubject, long tcprojectId, long roleId, long userId)
+ throws ContestServiceException {
- try
- {
- components_user_id = userService.getUserId(RESOURCE_INFO_HANDLE_COMPONENTS);
+ List- * Checks if the login user is of given role - *
- * - * @param tcSubject TCSubject instance for login user - * @return true if it is given role - */ - private static boolean isRole(TCSubject tcSubject, String roleName) { - Set- * Get the user-name for current login user represented by tcSubject. - *
- * @param tcSubject TCSubject instance for login user - * @return user name - * @throws ContestServiceException fail to retrieve user-name - */ - private String getUserName(TCSubject tcSubject) throws ContestServiceException { - try { - return this.userService.getUserHandle(tcSubject.getUserId()); - } catch(Exception e) { - throw new ContestServiceException("Fail to get the user-name by user-id" + tcSubject.getUserId(), e); + cn.setContestId(c.getContestId()); + if (c.getForumId() != null) { + cn.setForumId(c.getForumId()); } - } - - /** - *
- * Converts specified XMLGregorianCalendar instance into
- * Date instance.
- *
XMLGregorianCalendar representing the date to
- * be converted.
- * @return a Date providing the converted value of specified
- * calendar or null if specified calendar
- * is null.
- */
- private Date getDate(XMLGregorianCalendar calendar) {
- if (calendar == null) {
- return null;
+ cn.setName(c.getCname());
+ // added in Direct Notification assembly
+ cn.setType(c.getType());
+ if (c.isStudio()) {
+ if (c.getForumType() == null) {
+ cn.setForumNotification(watchedStForumsSet.contains(cn.getForumId()));
+ } else {
+ cn.setForumNotification(watchedNewStForumsSet.contains(cn.getForumId()));
+ }
+ } else {
+ cn.setForumNotification(watchedSwForumsSet.contains(cn.getForumId()));
}
- return calendar.toGregorianCalendar().getTime();
- }
+ cn.setProjectNotification(notifiedContestsSet.contains(cn.getContestId()));
- /**
- *
- * Converts specified Date instance into
- * XMLGregorianCalendar instance.
- *
Date representing the date to be converted.
- * @return a XMLGregorianCalendar providing the converted value
- * of specified date or null if specified
- * date is null or if it can't be
- * converted to calendar.
- */
- private XMLGregorianCalendar getXMLGregorianCalendar(Date date) {
- if (date == null) {
- return null;
- }
+ cn.setIsStudio(c.isStudio());
- GregorianCalendar cal = new GregorianCalendar();
- cal.setTime(date);
+ // add new ContestNotification into coressponding ProjectNotification
+ pn.getContestNotifications().add(cn);
- try {
- return DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);
- } catch (DatatypeConfigurationException ex) {
- return null;
- }
- }
+ }
- /**
- * - * Processes the contest sale. - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param competition data that recognizes a contest. - * @param paymentData payment information (credit card/po details) that need to be processed. - * @return aSoftwareContestPaymentResult result of the payment processing.
- * @throws ContestServiceException if an error occurs when interacting with the service layer.
- * @since Module Contest Service Software Contest Sales Assembly
- * @since BUGR-1682 changed return value
- */
- public SoftwareContestPaymentResult processContestCreditCardSale(TCSubject tcSubject,
- SoftwareCompetition competition, CreditCardPaymentData paymentData) throws ContestServiceException, PermissionServiceException {
- logger.debug("processContestCreditCardSale");
-
- return processContestSaleInternal(tcSubject, competition, paymentData, null, null, null);
- }
+ result = new ArrayList- * Processes the contest sale. - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param competition data that recognizes a contest. - * @param paymentData payment information (credit card/po details) that need to be processed. - * @param multiRoundEndDate the end date for the multiround phase. No multiround if it's null. - * @param endDate the end date for submission phase. Can be null if to use default. - * @return aSoftwareContestPaymentResult result of the payment processing.
- * @throws ContestServiceException if an error occurs when interacting with the service layer.
- * @since Module Contest Service Software Contest Sales Assembly
- * @since 1.6.6
- */
- public SoftwareContestPaymentResult processContestCreditCardSale(TCSubject tcSubject,
- SoftwareCompetition competition, CreditCardPaymentData paymentData, Date multiRoundEndDate, Date endDate) throws ContestServiceException, PermissionServiceException {
- logger.debug("processContestCreditCardSale");
-
- return processContestSaleInternal(tcSubject, competition, paymentData, null, multiRoundEndDate, endDate);
- }
+ // sort the ProjectNotification by alphabetical order
+ Collections.sort(result, new Comparator- * Processes the contest sale. - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param competition data that recognizes a contest. - * @param paymentData payment information (credit card/po details) that need to be processed. - * @return aSoftwareContestPaymentResult result of the payment processing.
- * @throws ContestServiceException if an error occurs when interacting with the service layer.
- * @since Module Contest Service Software Contest Sales Assembly
- * @since BUGR-1682 changed return value
- */
- public SoftwareContestPaymentResult processContestPurchaseOrderSale(TCSubject tcSubject,
- SoftwareCompetition competition, TCPurhcaseOrderPaymentData paymentData) throws ContestServiceException, PermissionServiceException {
- logger.debug("processPurchaseOrderSale");
-
- return processContestSaleInternal(tcSubject, competition, paymentData, null, null, null);
- }
+ // for each ProjectNotification, sort ContestNotifications by alphabetical order
+ for (ProjectNotification pn : result) {
+ Collections.sort(pn.getContestNotifications(), new Comparator- * Processes the contest sale. - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param competition data that recognizes a contest. - * @param paymentData payment information (credit card/po details) that need to be processed. - * @param multiRoundEndDate the end date for the multiround phase. No multiround if it's null. - * @param endDate the end date for submission phase. Can be null if to use default. - * @return aSoftwareContestPaymentResult result of the payment processing.
- * @throws ContestServiceException if an error occurs when interacting with the service layer.
- * @since Module Contest Service Software Contest Sales Assembly
- * @since 1.6.6
- */
- public SoftwareContestPaymentResult processContestPurchaseOrderSale(TCSubject tcSubject,
- SoftwareCompetition competition, TCPurhcaseOrderPaymentData paymentData, Date multiRoundEndDate, Date endDate) throws ContestServiceException, PermissionServiceException {
- logger.debug("processPurchaseOrderSale");
-
- return processContestSaleInternal(tcSubject, competition, paymentData, null, multiRoundEndDate, endDate);
- }
+ return result;
- /**
- * - * Processes the contest sale. - *
- * - * @param tcSubject TCSubject instance contains the login security info for the current user - * @param competition data that recognizes a contest. - * @param paymentData payment information (credit card/po details) that need to be processed. - * @param multiRoundEndDate the end date for registration phase. - * @param multiRoundEndDate the end date for the multiround phase. No multiround if it's null. - * @param endDate the end date for submission phase. Can be null if to use default. - * @return aSoftwareContestPaymentResult result of the payment processing.
- * @throws ContestServiceException if an error occurs when interacting with the service layer.
- * @since Module Contest Service Software Contest Sales Assembly
- * @since 3.10
- */
- public SoftwareContestPaymentResult processContestPurchaseOrderSale(TCSubject tcSubject,
- SoftwareCompetition competition, TCPurhcaseOrderPaymentData paymentData,
- Date regEndDate, Date multiRoundEndDate, Date endDate)
- throws ContestServiceException, PermissionServiceException {
- logger.debug("processPurchaseOrderSale");
-
- return processContestSaleInternal(tcSubject, competition, paymentData, regEndDate, multiRoundEndDate, endDate);
+ } catch (ProjectServicesException pse) {
+ logger.error("ProjectServices operation failed in the contest service facade.", pse);
+ throw new ContestServiceException("Error occurs when operating with ProjectServices", pse);
+ } catch (Exception ex) {
+ // forum related exception should be caught and logged but not thrown out
+ logger.error("Operation failed in the contest service facade.", ex);
+ return result;
+ } finally {
+ logger.info("Exit getNotificationsForUser");
}
- /**
- * - * Processes the contest sale, activate the contest and start the specification review of the contest. - *
- * - * @param tcSubject TCSubject instance contains the login security info for the current user - * @param competition data that recognizes a contest. - * @param paymentData payment information (TCSubject tcSubject,credit card/po details) that need to be processed. - * @param multiRoundEndDate the end date for the multiround phase. No multiround if it's null. - * @param endDate the end date for submission phase. Can be null if to use default. - * @param startSpecReviewNow the flag whether to start spec review now. - * @return aPaymentResult result of the payment processing.
- * @throws ContestServiceException if an error occurs when interacting with the service layer.
- * @throws PermissionServiceException if there is error when assigning permission to user.
- * @throws SpecificationReviewServiceException if fail to start the spec review of the contest.
- * @since 1.8.5
- */
- public SoftwareContestPaymentResult purchaseActivateContestAndStartSpecReview(TCSubject tcSubject,
- SoftwareCompetition competition, TCPurhcaseOrderPaymentData paymentData,
- Date multiRoundEndDate, Date endDate, boolean startSpecReviewNow) throws ContestServiceException,
- PermissionServiceException, SpecificationReviewServiceException {
- return purchaseActivateContestAndStartSpecReview(tcSubject, competition, paymentData, null, multiRoundEndDate, endDate, startSpecReviewNow);
- }
+ }
- /**
- * - * Processes the contest sale, activate the contest and start the specification review of the contest. - *
- * - * @param tcSubject TCSubject instance contains the login security info for the current user - * @param competition data that recognizes a contest. - * @param paymentData payment information (TCSubject tcSubject,credit card/po details) that need to be processed. - * @param regEndDate the end date for registration phase. - * @param multiRoundEndDate the end date for the multiround phase. No multiround if it's null. - * @param endDate the end date for submission phase. Can be null if to use default. - * @param startSpecReviewNow the flag whether to start spec review now. - * @return aPaymentResult result of the payment processing.
- * @throws ContestServiceException if an error occurs when interacting with the service layer.
- * @throws PermissionServiceException if there is error when assigning permission to user.
- * @throws SpecificationReviewServiceException if fail to start the spec review of the contest.
- * @since 3.10
- */
- public SoftwareContestPaymentResult purchaseActivateContestAndStartSpecReview(TCSubject tcSubject,
- SoftwareCompetition competition, TCPurhcaseOrderPaymentData paymentData, Date regEndDate,
- Date multiRoundEndDate, Date endDate, boolean startSpecReviewNow) throws ContestServiceException,
- PermissionServiceException, SpecificationReviewServiceException {
-
- // purchase the contest and activate it
- final SoftwareContestPaymentResult softwareContestPaymentResult =
- processContestSaleInternal(tcSubject, competition, paymentData, regEndDate, multiRoundEndDate, endDate);
-
- // check if the contest has specification review phase
- final Set- * Processes the contest sale. - *
- *- * Updated for Cockpit Release Assembly for Receipts - Added code snippet to send email receipts on successful - * purchase. - *
- *- * Updated for Version 1.0.3 - For software contest, payment is made for the sum of various costs. - While doing so, - * only the increased amount is paid (if earlier payments were made). - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * - *- * Updates in 1.8.4: - * - Check the DR flag before adding DR points to the total cost - * - Fix the total member cost and total cost, they should be different. Total cost = total member cost + admin fee - * - Add the logics to dynamic load activation email tempalte according to the contest type - *
- * - * - * @param tcSubject TCSubject instance contains the login security info for the current user - * @param competition data that recognizes a contest. - * @param paymentData payment information (credit card/po details) that need to be processed. - * @param regEndDate the end date for registration phase. - * @param multiRoundEndDate the end date for the multiround phase. No multiround if it's null. - * @param endDate the end date for submission phase. Can be null if to use default. - * @return aSoftwareContestPaymentResult result of the payment processing.
- * @throws ContestServiceException if an error occurs when interacting with the service layer.
- * @since Module Contest Service Software Contest Sales Assembly
- * @since BUGR-1682 changed return value
- */
- private SoftwareContestPaymentResult processContestSaleInternal(TCSubject tcSubject,
- SoftwareCompetition competition, PaymentData paymentData, Date regEndDate, Date multiRoundEndDate, Date endDate) throws ContestServiceException, PermissionServiceException {
- logger.info("SoftwareCompetition: " + competition);
- logger.info("PaymentData: " + paymentData);
- logger.info("tcSubject: " + tcSubject.getUserId());
- logger.info("multiRoundEndDate: " + multiRoundEndDate);
-
- SoftwareContestPaymentResult softwareContestPaymentResult = null;
-
- PaymentResult result = null;
+ List
- * Returns a list containing all active Categories.
- *
- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @return a list containing all activeCategories. It can be empty if no objects found.
- * @throws ContestServiceException if an error occurs when interacting with the service layer.
- * @since TopCoder Service Layer Integration 3 Assembly
- */
- public List
- * Returns a list containing all active Technologies.
- *
- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @return a list containing all activeCategories. It can be empty if no objects found.
- * @throws ContestServiceException if an error occurs when interacting with the service layer.
- * @since TopCoder Service Layer Integration 3 Assembly
- */
- public List
- * Returns a list containing all Phases.
- *
- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @return a list containing all activeCategories. It can be empty if no objects found.
- * @throws ContestServiceException if an error occurs when interacting with the service layer.
- * @since TopCoder Service Layer Integration 3 Assembly
- */
- public List
- * Assigns a specified user to a specified assetDTO.
- *
- * If the user already assigned to the asset, this method simply does nothing. - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param userId the id of the user - * @param assetId the id of the assetDTO - * @throws ContestServiceException if an error occurs when interacting with the service layer. - * @since TopCoder Service Layer Integration 3 Assembly - */ - public void assignUserToAsset(TCSubject tcSubject, long userId, long assetId) throws ContestServiceException { - logger.debug("assignUserToAsset"); - - try { - catalogService.assignUserToAsset(userId, assetId); - logger.debug("Exit assignUserToAsset"); - } catch (EntityNotFoundException e) { - logger.error("Operation failed in the catalogService.", e); - throw new ContestServiceException("Operation failed in the catalogService.", e); - } catch (com.topcoder.catalog.service.PersistenceException e) { - logger.error("Operation failed in the catalogService.", e); - throw new ContestServiceException("Operation failed in the catalogService.", e); - } - } - - /** - *
- * Removes a specified user from a specified assetDTO.
- *
- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param userId the id of the user - * @param assetId the id of the asset - * @throws ContestServiceException if an error occurs when interacting with the service layer. - * @since TopCoder Service Layer Integration 3 Assembly - */ - public void removeUserFromAsset(TCSubject tcSubject, long userId, long assetId) throws ContestServiceException { - logger.debug("removeUserFromAsset"); - - try { - catalogService.removeUserFromAsset(userId, assetId); - logger.debug("Exit removeUserFromAsset"); - } catch (EntityNotFoundException e) { - logger.error("Operation failed in the catalogService.", e); - throw new ContestServiceException("Operation failed in the catalogService.", e); - } catch (com.topcoder.catalog.service.PersistenceException e) { - logger.error("Operation failed in the catalogService.", e); - throw new ContestServiceException("Operation failed in the catalogService.", e); - } - } - - /** - *- * This method finds all tc direct projects. Returns empty array if no projects found. - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @return Project array with project info, or empty array if none found - * @throws ContestServiceException if an error occurs when interacting with the service layer. - * @since TopCoder Service Layer Integration 3 Assembly - */ - public SoftwareCompetition[] findAllTcDirectProjects(TCSubject tcSubject) throws ContestServiceException { - logger.debug("findAllTcDirectProjects"); - - try { - Project[] projects = projectServices.findAllTcDirectProjects(tcSubject); - - SoftwareCompetition[] ret = new SoftwareCompetition[projects.length]; - - for (int i = 0; i < projects.length; i++) { - FullProjectData projectData = new FullProjectData(); - projectData.setProjectHeader(projects[i]); - - ret[i] = new SoftwareCompetition(); - ret[i].setProjectData(projectData); - ret[i].setType(CompetionType.SOFTWARE); - ret[i].setId(projectData.getProjectHeader().getId()); - } - - logger.debug("Exit findAllTcDirectProjects"); - - return ret; - } catch (ProjectServicesException e) { - logger.error("Operation failed in the projectServices.", e); - throw new ContestServiceException("Operation failed in the projectServices.", e); - } - } - - /** - *- * This method finds all given user tc direct projects . Returns empty array if no projects found. - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param operator The user to search for projects - * @return Project array with project info, or empty array if none found - * @throws ContestServiceException if an error occurs when interacting with the service layer. - * @since TopCoder Service Layer Integration 3 Assembly - */ - public SoftwareCompetition[] findAllTcDirectProjectsForUser(TCSubject tcSubject, String operator) - throws ContestServiceException { - logger.debug("findAllTcDirectProjectsForUser"); - - try { - Project[] projects = projectServices.findAllTcDirectProjectsForUser(tcSubject,operator); - - SoftwareCompetition[] ret = new SoftwareCompetition[projects.length]; - - for (int i = 0; i < projects.length; i++) { - FullProjectData projectData = new FullProjectData(); - projectData.setProjectHeader(projects[i]); - - ret[i] = new SoftwareCompetition(); - ret[i].setProjectData(projectData); - ret[i].setType(CompetionType.SOFTWARE); - ret[i].setId(projectData.getProjectHeader().getId()); - } - - logger.debug("Exit findAllTcDirectProjectsForUser"); - - return ret; - } catch (ProjectServicesException e) { - logger.error("Operation failed in the projectServices.", e); - throw new ContestServiceException("Operation failed in the projectServices.", e); - } - } - - /** - *- * This method retrieves the project along with all known associated information. Returns null if not found. - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param projectId The ID of the project to retrieve - * @return the project along with all known associated information - * @throws IllegalArgumentException If projectId is negative - * @throws ContestServiceException if an error occurs when interacting with the service layer. - * @since TopCoder Service Layer Integration 3 Assembly - */ - public SoftwareCompetition getFullProjectData(TCSubject tcSubject, long projectId) throws ContestServiceException, PermissionServiceException { - logger.debug("getFullProjectData"); - - try { - FullProjectData projectData = projectServices.getFullProjectData(projectId); - - if (projectData == null) { - return null; - } - - com.topcoder.project.phases.Phase[] allPhases = projectData.getAllPhases(); - - for (int i = 0; i < allPhases.length; i++) { - allPhases[i].setProject(null); - } - - SoftwareCompetition contest = new SoftwareCompetition(); - contest.setProjectData(projectData); - contest.setType(CompetionType.SOFTWARE); - contest.setId(projectData.getProjectHeader().getId()); - logger.debug("Exit getFullProjectData"); - - return contest; - } catch (ProjectServicesException e) { - logger.error("Operation failed in the projectServices.", e); - throw new ContestServiceException("Operation failed in the projectServices.", e); - } - } - - /** - * Checks the permission for the given tc-direct-project-id for the current caller. - * - * @param tcSubject the current caller - * @param tcDirectProjectId the project id - * @param readOnly true to check READ permission, false to check WRITE permission - * @throws PermissionServiceException if user(not admin) does not have the permission - */ - private void checkSoftwareProjectPermission(TCSubject tcSubject, long tcDirectProjectId, boolean readOnly) - throws PermissionServiceException { - if (!isRole(tcSubject, ADMIN_ROLE) && !isRole(tcSubject, TC_STAFF_ROLE)) { - if (!projectServices.checkProjectPermission(tcDirectProjectId, readOnly, tcSubject.getUserId())) { - // check group permission - checkGroupPermissionForProject(tcSubject, tcDirectProjectId, readOnly); - } - } - } - - /** - * Checks the permission for the given contestId for the current caller. - * - * @param tcSubject the current caller - * @param contestId the contest id - * @param readOnly true to check READ permission, false to check WRITE permission - * @throws PermissionServiceException if user(not admin) does not have the permission - */ - private void checkSoftwareContestPermission(TCSubject tcSubject, long contestId, boolean readOnly) - throws PermissionServiceException { - if (!isRole(tcSubject, ADMIN_ROLE) && !isRole(tcSubject, TC_STAFF_ROLE)) { - if (!projectServices.checkContestPermission(contestId, readOnly, tcSubject.getUserId())) { - // check group permission for project - checkGroupPermissionForProject(tcSubject, projectServices.getTcDirectProject(contestId), readOnly); - } - } - } - - /** - * Checks the group permission for the given tc-direct-project-id for the current caller. - * - * @param tcSubject the current caller - * @param tcDirectProjectId the project id - * @param readOnly true to check READ permission, false to check WRITE permission - * @throws PermissionServiceException if user(not admin) does not have the group permission - * @since 1.8.4 - */ - private void checkGroupPermissionForProject(TCSubject tcSubject, long tcDirectProjectId, boolean readOnly) - throws PermissionServiceException { - try { - // Check if user is administrator for client account - Long clientId = null; - - // get client id - DataAccess dataAccess = new DataAccess(DBMS.TCS_DW_DATASOURCE_NAME); - Request request = new Request(); - request.setContentHandle("non_admin_client_billing_accounts"); - request.setProperty("tdpis", String.valueOf(tcDirectProjectId)); - ResultSetContainer resultContainer = dataAccess.getData(request). - get("non_admin_client_billing_accounts"); - if (resultContainer != null && resultContainer.size() > 0) { - clientId = resultContainer.getLongItem(0, "client_id"); - } - long userId = tcSubject.getUserId(); - boolean isCustomerAdministrator = false; - if (clientId != null) { - isCustomerAdministrator = authorizationService.isCustomerAdministrator(userId, clientId); - } - if (isCustomerAdministrator) { - return; - } else { - // If not then check if user is granted desired permission to access the project based on - // security groups which user is member of - GroupPermissionType groupPermissionType = - authorizationService.checkAuthorization(userId, tcDirectProjectId, ResourceType.PROJECT); - if (groupPermissionType != null) { - if (readOnly && groupPermissionType != GroupPermissionType.REPORT) { - return; - } - if (!readOnly && (groupPermissionType == GroupPermissionType.WRITE - || groupPermissionType == GroupPermissionType.FULL)) { - return; - } - } - } - } catch (Exception e) { - throw new PermissionServiceException("Failed to authorize user against security groups", e); - } - - throw new PermissionServiceException("No " + (readOnly ? "read" : "write") + " permission on project"); - } - - /** - * Checks the billing project permission of the given contest for the current caller. - * - * @param contest the contest to check - * @return billing project id, if it is -1, then no billing project - * @throws ContestServiceException if user(not admin) does not have the permission - */ - private void checkBillingProjectPermission(TCSubject tcSubject, SoftwareCompetition contest) - throws PermissionServiceException, DAOException, ContestServiceException { - if (!isRole(tcSubject, ADMIN_ROLE) && !isRole(tcSubject, TC_STAFF_ROLE)) { - String billingProject = contest.getProjectHeader().getProperty(ProjectPropertyType.BILLING_PROJECT_PROJECT_PROPERTY_KEY); - - Project cur = projectServices.getProject(contest.getProjectHeader().getId()); - String curBilling = cur.getProperty(ProjectPropertyType.BILLING_PROJECT_PROJECT_PROPERTY_KEY); - - if (billingProject != null && !billingProject.equals("") && !billingProject.equals("0")) { - - // if billing not changed, no need to check - if (curBilling != null && !billingProject.equals("") && !billingProject.equals("0")) - { - if (billingProject.equals(billingProject)) - { - return; - } - } - long clientProjectId = Long.parseLong(billingProject); - if (!billingProjectDAO.checkClientProjectPermission(getUserName(tcSubject), clientProjectId)) { - throw new PermissionServiceException("No permission on billing project " + clientProjectId); - } - } - } - } - - /** - * get billing project id - * - * @param contest the contest to check - * @return billing project id, if it is 0, then no billing project - */ - private long getBillingProjectId(SoftwareCompetition contest) { - - String billingProject = contest.getProjectHeader().getProperty(ProjectPropertyType.BILLING_PROJECT_PROJECT_PROPERTY_KEY); - - if (billingProject != null && !billingProject.equals("") && !billingProject.equals("0")) { - long clientProjectId = Long.parseLong(billingProject); - return clientProjectId; - } - return 0; - - } - - /** - * Checks if the contest is development contest. - * @param contest the contest - * @return true if yes - */ - private boolean isDevContest(SoftwareCompetition contest) { - return contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.DEVELOPMENT.getId(); - } - - - /** - * Checks if the contest is of type Code - * - * @param contest the contest to check - * @return true if yes, false otherwise - * @since 2.0.0 - */ - private boolean isCodeContest(SoftwareCompetition contest) { - return contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.CODE.getId(); - } - - /** - * Checks if the contest is of type First2Finish - * - * @param contest the contest to check - * @return true if yes, false otherwise - * @since 2.0.1 - */ - private boolean isF2FContest(SoftwareCompetition contest) { - return contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.FIRST2FINISH.getId(); - } - - /** - * Checks if the contest is of type Design First2Finish - * - * @param contest the contest tocheck - * @return true if yes, false otherwise - * @since 3.0 - */ - private boolean isDesignF2FContest(SoftwareCompetition contest) { - return contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.DESIGN_FIRST2FINISH.getId(); - } - - - /** - * Checks if the contest is copilot contest. - * - * @param contest the contest - * @return true if yes - * @since 1.6.4 - */ - private boolean isCopilotContest(SoftwareCompetition contest) { - return contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.COPILOT_POSTING.getId(); - } - - /** - * Checks if the contest is studio contest. - * - * @param contest the conetst to check - * @return true if the contest is studio contest, false otherwise - * @since 1.6.6 - */ - private boolean isStudio(SoftwareCompetition contest) { - return contest.getProjectHeader().getProjectCategory().getProjectType().getId() == ProjectType.STUDIO.getId(); - } - - /** - * Checks if the contest is of type Marathon Match. - * - * @param contest the contest - * @return true if yes - * @since 3.14 - */ - private boolean isMMContest(SoftwareCompetition contest) { - return contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.MARATHON_MATCH.getId(); - } - - /** - *
- * Creates a new SoftwareCompetition in the persistence.
- *
- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param contest theSoftwareCompetition to create as a contest
- * @param tcDirectProjectId the TC direct project id. a long providing the ID of a client the new
- * competition belongs to.
- * @return the created SoftwareCompetition as a contest
- * @throws IllegalArgumentException if the input argument is invalid.
- * @throws ContestServiceException if an error occurs when interacting with the service layer.
- * @since TopCoder Service Layer Integration 3 Assembly
- */
- public SoftwareCompetition createSoftwareContest(TCSubject tcSubject, SoftwareCompetition contest,
- long tcDirectProjectId) throws ContestServiceException, PermissionServiceException {
- return createSoftwareContest(tcSubject, contest, tcDirectProjectId, null, null, null);
- }
-
- /**
- * Checks whether the given billing account is associated with the given direct project.
- *
- * @deprecated
- * @param billingAccountId the id of the billing account
- * @param directProjectId the id of the direct project
- * @throws PersistenceFault if there is any error with projectService
- * @throws ContestServiceException if the billing account is not assciated with the direct project
- * @since 1.9.3
- */
- private void checkContestBillingAccount(long billingAccountId, long directProjectId)
- throws PersistenceFault, ContestServiceException {
- if(billingAccountId <= 0) {
- return;
- }
-
- final List
- * Creates a new SoftwareCompetition in the persistence.
- *
- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * - *- * Update in v1.8.3: Add handling of auto creation of bug hunt for assembly competition. If the assembly contest - * has bugHuntProjectHeader set and the properties not empty in bugHuntProjectHeader. A bug hunt contest is - * automatically created. The bug hunt contest will - * - have copilot inserted as reviewer (if exists) - * - use the start date of approval date as the start date and producation date of bug hunt contest. - * - add a "Bug Race For" link between the bug race contest and assembly contest - *
- * - * @param tcSubject TCSubject instance contains the login security info for the current user - * @param contest theSoftwareCompetition to create as a contest
- * @param tcDirectProjectId the TC direct project id. a long providing the ID of a client the new
- * competition belongs to.
- * @param multiRoundEndDate the end date for the multiround phase. No multiround if it's null.
- * @param endDate the end date for submission phase. Can be null if to use default.
- * @return the created SoftwareCompetition as a contest
- * @throws IllegalArgumentException if the input argument is invalid.
- * @throws ContestServiceException if an error occurs when interacting with the service layer.
- * @since 1.6.6
- */
- public SoftwareCompetition createSoftwareContest(TCSubject tcSubject, SoftwareCompetition contest,
- long tcDirectProjectId, Date multiRoundEndDate, Date endDate) throws ContestServiceException, PermissionServiceException {
- return createSoftwareContest(tcSubject, contest, tcDirectProjectId, null, null, null);
- }
-
- /**
- *
- * Creates a new SoftwareCompetition in the persistence.
- *
SoftwareCompetition to create as a contest
- * @param tcDirectProjectId the TC direct project id. a long providing the ID of a client the new
- * competition belongs to.
- * @param regEndDate the registration end date
- * @param multiRoundEndDate the end date for the multiround phase. No multiround if it's null.
- * @param endDate the end date for submission phase. Can be null if to use default.
- * @return the created SoftwareCompetition as a contest
- * @throws IllegalArgumentException if the input argument is invalid.
- * @throws ContestServiceException if an error occurs when interacting with the service layer.
- */
- public SoftwareCompetition createSoftwareContest(TCSubject tcSubject, SoftwareCompetition contest,
- long tcDirectProjectId, Date regEndDate, Date multiRoundEndDate, Date endDate) throws ContestServiceException, PermissionServiceException {
- logger.debug("createSoftwareContest with information : [tcSubject = " + tcSubject.getUserId() + ", tcDirectProjectId ="
- + tcDirectProjectId + ", multiRoundEndDate = " + multiRoundEndDate + "]");
-
- try {
- ExceptionUtils.checkNull(contest, null, null, "The contest to create is null.");
- ExceptionUtils.checkNull(contest.getProjectHeader(), null, null, "The contest#ProjectHeader to create is null.");
-
- // check the permission
- //TODO liquid creaet project, and assign permission, check fails here
- //checkSoftwareProjectPermission(tcSubject, tcDirectProjectId, true);
- //check the billing project permission
- long billingProjectId = getBillingProjectId(contest);
-
- // check if billing project id is one of the billing accounts for the direct project
- if (billingProjectId > 0) {
- // do the checking
- checkContestBillingAccount(billingProjectId, contest.getProjectHeader().getTcDirectProjectId());
- }
-
- //check whether we need to auto-create-development contest for design
- boolean creatingDevContest = shouldAutoCreateDevContest(contest);
-
- // check whether we need to auto create bug hunt contest for the bug hunt
- boolean creatingBugHunt = shouldAutoCreateBugHuntContest(contest);
-
- //copy the data from design to development if it is going to do auto-dev-creating
- SoftwareCompetition devContest = null;
- if (creatingDevContest) {
- devContest = (SoftwareCompetition)contest.clone();
- }
-
- SoftwareCompetition bugHuntContest = null;
-
- if (creatingBugHunt) {
- // copy the data from assembly to bug hunt if creatingBugHunt is true
- bugHuntContest = (SoftwareCompetition) contest.clone();
- }
-
-
- boolean requireApproval = true;
-
- if(isStudio(contest)
- || contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.BUG_HUNT.getId()
- || contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.COPILOT_POSTING.getId() ) {
- // do not add approver for bug hunt and copilot posting
- requireApproval = false;
- }
-
- checkBillingProjectCCA(contest);
-
- //update the AssetDTO and update corresponding properties
- createUpdateAssetDTO(tcSubject, contest);
-
- com.topcoder.management.resource.Resource[] contestResources = createContestResources(tcSubject, contest, billingProjectId, requireApproval);
-
- //create contest resources
- contest.setProjectResources(contestResources);
-
- //set the tc-direct-project-id
- contest.getProjectHeader().setTcDirectProjectId(tcDirectProjectId);
-
- // set status to draft
- contest.getProjectHeader().setProjectStatus(ProjectStatus.DRAFT);
-
- //create project now
- FullProjectData projectData = projectServices.createProjectWithTemplate(contest.getProjectHeader(),
- contest.getProjectPhases(), contest.getProjectResources(), regEndDate, multiRoundEndDate, endDate,
- String.valueOf(tcSubject.getUserId()));
-
- //create mm entry
- if (contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.MARATHON_MATCH.getId()) {
- Date mStartDate = null;
- Date mRegEndDate = null;
- Date mEndDate = null;
- for (com.topcoder.project.phases.Phase p : projectData.getAllPhases()) {
- if (p.getPhaseType().getId() == PhaseType.REGISTRATION_PHASE.getId()) {
- mStartDate = p.getScheduledStartDate();
- mRegEndDate = p.getScheduledEndDate();
- } else if (p.getPhaseType().getId() == PhaseType.SUBMISSION_PHASE.getId()) {
- mEndDate = p.getScheduledEndDate();
- }
- }
- projectManager.createOrUpdateMarathonMatch(projectData.getProjectHeader(), mStartDate, mRegEndDate, mEndDate ,
- true, String.valueOf(tcSubject.getUserId()));
- }
-
- if (contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.DEVELOPMENT.getId()) {
- projectServices.linkDevelopmentToDesignContest(projectData.getProjectHeader().getId());
- }
-
- if(contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.BUG_HUNT.getId()
- && contest.getProjectHeader().isAutoCreationBugHunt() ) {
- // link the bug hunt to the parent contest if it's of type bug hunt and it's an auto created one
- projectServices.linkBugHuntToOtherContest(projectData.getProjectHeader().getId());
-
- // add copilot as reviewer
- for(com.topcoder.management.resource.Resource r : contestResources) {
- if(r.getResourceRole().getId() == ResourceRole.RESOURCE_ROLE_COPILOT_ID) {
- addReviewer(tcSubject, projectData.getProjectHeader().getId(), Long.parseLong(r.getProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID)));
- }
- }
- }
-
- if (contest.getProjectHeader().getAutoAssignReviewerId() > 0) {
- if(contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.CODE.getId()) {
- // no review payment for the contest
- addReviewer(tcSubject, projectData.getProjectHeader().getId(), contest.getProjectHeader().getAutoAssignReviewerId());
- }
- }
-
- // set copilot forum permission
- long forumId = 0;
-
- if (createForum) {
- forumId = contest.getAssetDTO().getForum().getJiveCategoryId();
- }
-
-// String adminRole = getEligibilityAdminRole(tcSubject, billingProjectId).trim();
-
- for (com.topcoder.management.resource.Resource r : contest.getProjectResources()) {
- long roleId = r.getResourceRole().getId();
- long uid = Long.parseLong(r.getProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID));
-
-
- if (r.getProperty(RESOURCE_INFO_HANDLE).equals(RESOURCE_INFO_HANDLE_COMPONENTS)
- || r.getProperty(RESOURCE_INFO_HANDLE).equals(RESOURCE_INFO_HANDLE_APPLICATIONS)
- /**|| r.getProperty(RESOURCE_INFO_HANDLE).equals(adminRole)**/)
- {
- continue;
- }
- boolean addNotification;
- boolean addForumWatch;
-
- List- * Detects whether the auto creating development contest is on. - *
- * @param contest the contest - * @return true if yes - */ - private boolean shouldAutoCreateDevContest(SoftwareCompetition contest) { - return contest.getDevelopmentProjectHeader() != null - && contest.getDevelopmentProjectHeader().getProperties() != null - && contest.getDevelopmentProjectHeader().getProperties().size() != 0; - } - - /** - *- * Detects whether need to auto create the bug hunt contest. - *
- * - * @param contest the contest - * @return true if yes, false otherwise - * @since 1.8.3 - */ - private boolean shouldAutoCreateBugHuntContest(SoftwareCompetition contest) { - return contest.getBugHuntProjectHeader() != null - && contest.getBugHuntProjectHeader().getProperties() != null - && contest.getBugHuntProjectHeader().getProperties().size() != 0; - } - - /** - * Create or updating the AssetDTO for the contest. If the AssetDTO already exists for development contest, we need - * to create dev-component. Also, creating forum if necessary. - *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- *- * Update in v1.6.4: set digital run flag to 'Off' and rated to 'No' if it's copilot selection contest. - *
- * - *- * Update in 1.8.3: - * - Reuse the same assetDTO as the parent contest for auto creation bug hunt contest. - *
- * - * @param tcSubject TCSubject instance contains the login security info for the current user - * @param contest the contest - * @throws EntityNotFoundException if any error occurs - * @throws com.topcoder.catalog.service.PersistenceException if any error occurs - */ - private void createUpdateAssetDTO(TCSubject tcSubject, SoftwareCompetition contest) throws EntityNotFoundException, - com.topcoder.catalog.service.PersistenceException, DAOException, ConfigManagerException { - //check if it is going to create development contest - boolean isDevContest = isDevContest(contest); - XMLGregorianCalendar productionDate = null; - if (contest.getAssetDTO() != null) { - AssetDTO assetDTO = contest.getAssetDTO(); - boolean useExistingAsset = false; - if (isDevContest && assetDTO.getVersionNumber()!= null && assetDTO.getVersionNumber().longValue() != 1) { - useExistingAsset = true; - productionDate = assetDTO.getProductionDate(); - assetDTO = catalogService.getAssetByVersionId(assetDTO.getVersionNumber()); - // for dev, we need to insert a row in comp version dates - catalogService.createDevComponent(assetDTO); - // set dev only flag - } else if (contest.getProjectHeader().isAutoCreationBugHunt()) { - // use the asset belong to the parent contest - useExistingAsset = true; - productionDate = assetDTO.getProductionDate() == null ? nextDay(): assetDTO.getProductionDate(); - } - // dev only - else if (isDevContest) - { - contest.getProjectHeader().setDevOnly(true); - } - - if (!useExistingAsset) { - productionDate = assetDTO.getProductionDate() == null ? nextDay():assetDTO.getProductionDate(); - assetDTO.setProductionDate(null); - if (contest.getProjectHeader() != null) { - // comp development, set phase to dev, otherwise to design - assetDTO.setPhase(isDevContest?"Development":"Design"); - } - assetDTO = this.catalogService.createAsset(assetDTO); - contest.setAssetDTO(assetDTO); - } - long forumId = 0; - // create forum - if (createForum) { - if (useExistingAsset && assetDTO.getForum() != null) { - forumId = assetDTO.getForum().getJiveCategoryId(); - } else { - if (!isStudio(contest)) { - // software contest - forumId = createForum(tcSubject, assetDTO, tcSubject.getUserId(), contest.getProjectHeader().getProjectCategory().getId()); - } else { - // studio contest - forumId = createStudioForum(assetDTO.getName(), tcSubject.getUserId()); - } - } - } - - // if forum created - if (forumId > 0 && (!useExistingAsset || assetDTO.getForum() == null)) { - // create a comp forum - CompForum compForum = new CompForum(); - compForum.setJiveCategoryId(forumId); - assetDTO.setForum(compForum); - assetDTO = this.catalogService.updateAsset(assetDTO); - // avoid cycle - assetDTO.getForum().setCompVersion(null); - } - contest.setAssetDTO(assetDTO); - - contest.getProjectHeader().setProperty(ProjectPropertyType.EXTERNAL_REFERENCE_ID_PROJECT_PROPERTY_KEY, assetDTO.getCompVersionId().toString()); - contest.getProjectHeader().setProperty(ProjectPropertyType.COMPONENT_ID_PROJECT_PROPERTY_KEY, assetDTO.getId().toString()); - contest.getProjectHeader().setProperty(ProjectPropertyType.ROOT_CATALOG_ID_PROJECT_PROPERTY_KEY, assetDTO.getRootCategory().getId().toString()); - contest.getProjectHeader().setProperty(ProjectPropertyType.SVN_MODULE_PROJECT_PROPERTY_KEY, ""); - contest.getProjectHeader().setProperty(ProjectPropertyType.NOTES_PROJECT_PROPERTY_KEY, ""); - contest.getProjectHeader().setProperty(ProjectPropertyType.PROJECT_VERSION_PROJECT_PROPERTY_KEY, "1.0"); - contest.getProjectHeader().setProperty(ProjectPropertyType.VERSION_ID_PROJECT_PROPERTY_KEY, "1"); - contest.getProjectHeader().setProperty(ProjectPropertyType.AUTOPILOT_OPTION_PROJECT_PROPERTY_KEY, "Off"); - contest.getProjectHeader().setProperty(ProjectPropertyType.STATUS_NOTIFICATION_PROJECT_PROPERTY_KEY, "On"); - contest.getProjectHeader().setProperty(ProjectPropertyType.TIMELINE_NOTIFICATION_PROJECT_PROPERTY_KEY, "On"); - contest.getProjectHeader().setProperty(ProjectPropertyType.PUBLIC_PROJECT_PROPERTY_KEY, "Yes"); - contest.getProjectHeader().setProperty(ProjectPropertyType.RATED_PROJECT_PROPERTY_KEY, "Yes"); - contest.getProjectHeader().setProperty(ProjectPropertyType.ELIGIBILITY_PROJECT_PROPERTY_KEY, "Open"); - - // set the forum type - if (!isStudio(contest)) { - // software contest - contest.getProjectHeader().setProperty(ProjectPropertyType.FORUM_TYPE, "Development"); - } else { - // studio contest - contest.getProjectHeader().setProperty(ProjectPropertyType.FORUM_TYPE, "Design"); - } - - if (contest.getProjectHeader().getProperty(ProjectPropertyType.DIGITAL_RRUN_FLAG_PROJECT_PROPERTY_KEY) == null) - { contest.getProjectHeader().setProperty(ProjectPropertyType.DIGITAL_RRUN_FLAG_PROJECT_PROPERTY_KEY, "On"); } - - if(isF2FContest(contest) || isDesignF2FContest(contest) || isMMContest(contest) - ) { - contest.getProjectHeader().setProperty(ProjectPropertyType.ALLOW_MULTIPLE_SUBMISSIONS_PROPERTY_KEY, "true"); - } - - boolean hasEligibility = false; - - long billingProjectId = getBillingProjectId(contest); - - // if creating contest, eligiblity is not commited, so above will not get back result - if (billingProjectId != 0 - && contest.getProjectHeader().getSecurityGroupId() > 0) { - hasEligibility = true; - } - - if (hasEligibility) - { - contest.getProjectHeader().setProperty(ProjectPropertyType.SEND_WINNDER_EMAILS_PROJECT_PROPERTY_KEY, "false"); - } - else - { - contest.getProjectHeader().setProperty(ProjectPropertyType.SEND_WINNDER_EMAILS_PROJECT_PROPERTY_KEY, "true"); - } - - - if (isDevContest && !hasEligibility && billingProjectId > 0) - { - String codename = billingProjectDAO.getProjectById(billingProjectId).getClient().getCodeName(); - String compname = contest.getAssetDTO().getName(); - if (codename != null && !codename.equals("")) - { - - codename = CodeNameUtil.decodeCodeName(codename, "users"); - compname = compname.toLowerCase().replaceAll(" ", "_").replaceAll("/", "_").replaceAll("&", "_"); - codename = codename.toLowerCase().replaceAll(" ", ""); - contest.getProjectHeader().setProperty(ProjectPropertyType.SVN_MODULE_PROJECT_PROPERTY_KEY, "https://coder.topcoder.com/tcs/clients/"+codename+"/components/"+compname+"/trunk"); - } - } - - contest.getProjectHeader().setProperty(ProjectPropertyType.TRACK_LATE_DELIVERABLES_PROJECT_PROPERTY_KEY, "true"); - - if (isCopilotContest(contest)) { - contest.getProjectHeader().setProperty(ProjectPropertyType.DIGITAL_RRUN_FLAG_PROJECT_PROPERTY_KEY, "Off"); - contest.getProjectHeader().setProperty(ProjectPropertyType.DR_POINTS_PROJECT_PROPERTY_KEY, "0"); - contest.getProjectHeader().setProperty(ProjectPropertyType.RATED_PROJECT_PROPERTY_KEY, "No"); - contest.getProjectHeader().setProperty(ProjectPropertyType.RELIABILITY_BONUS_ELIGIBLE_PROJECT_PROPERTY_KEY, "false"); - contest.getProjectHeader().setProperty(ProjectPropertyType.CONFIDENTIALITY_TYPE_PROJECT_PROPERTY_KEY, "standard_cca"); - contest.getProjectHeader().setProperty(ProjectPropertyType.TRACK_LATE_DELIVERABLES_PROJECT_PROPERTY_KEY, "false"); - } - - if (contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.BUG_HUNT.getId()) - { - contest.getProjectHeader().setProperty(ProjectPropertyType.RELIABILITY_BONUS_ELIGIBLE_PROJECT_PROPERTY_KEY, "false"); - } - - if (isStudio(contest)) { - contest.getProjectHeader().setProperty(ProjectPropertyType.RATED_PROJECT_PROPERTY_KEY, "No"); - contest.getProjectHeader().setProperty(ProjectPropertyType.TRACK_LATE_DELIVERABLES_PROJECT_PROPERTY_KEY, "false"); - } - - if (isF2FContest(contest) || isDesignF2FContest(contest)) { - // no rated for F2F || Design F2F - contest.getProjectHeader().setProperty(ProjectPropertyType.RATED_PROJECT_PROPERTY_KEY, "No"); - - // no Reliability for Code || F2F || Design F2F - contest.getProjectHeader().setProperty(ProjectPropertyType.RELIABILITY_BONUS_ELIGIBLE_PROJECT_PROPERTY_KEY, "false"); - contest.getProjectHeader().setProperty(ProjectPropertyType.RELIABILITY_BONUS_COST_PROJECT_PROPERTY_KEY, "0"); - - // no Approval Required for Code || F2F || Design F2F - contest.getProjectHeader().setProperty(ProjectPropertyType.APPROVAL_REQUIRED_PROJECT_PROPERTY_KEY, "false"); - } - - if(isF2FContest(contest) || isCodeContest(contest)) { - // no Digital Run for F2F/Code - contest.getProjectHeader().setProperty(ProjectPropertyType.DIGITAL_RRUN_FLAG_PROJECT_PROPERTY_KEY, "Off"); - contest.getProjectHeader().setProperty(ProjectPropertyType.DR_POINTS_PROJECT_PROPERTY_KEY, "0"); - } - - if (!isStudio(contest) && !isCopilotContest(contest) - && contest.getProjectHeader().getProjectCategory().getId() != ProjectCategory.BUG_HUNT.getId() - && !isCodeContest(contest) - && !isF2FContest(contest)) - { - contest.getProjectHeader().setProperty(ProjectPropertyType.REVIEW_FEEDBACK_FLAG_PROJECT_PROPERTY_KEY, "true"); - } - else - { - contest.getProjectHeader().setProperty(ProjectPropertyType.REVIEW_FEEDBACK_FLAG_PROJECT_PROPERTY_KEY, "false"); - } - - if (contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.REPORTING.getId() || - contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.BUG_HUNT.getId() || isDesignF2FContest(contest)) - { - contest.getProjectHeader().setProperty(ProjectPropertyType.DIGITAL_RRUN_FLAG_PROJECT_PROPERTY_KEY, "Off"); - contest.getProjectHeader().setProperty(ProjectPropertyType.DR_POINTS_PROJECT_PROPERTY_KEY, "0"); - contest.getProjectHeader().setProperty(ProjectPropertyType.RATED_PROJECT_PROPERTY_KEY, "No"); - } - - if (isPrivateProject(contest)) { - // not rate for private - contest.getProjectHeader().setProperty(ProjectPropertyType.RATED_PROJECT_PROPERTY_KEY, "No"); - } - -// if (contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.CONTENT_CREATION.getId()) -// { -// contest.getProjectHeader().setProperty(ProjectPropertyType.DIGITAL_RRUN_FLAG_PROJECT_PROPERTY_KEY, "Off"); -// contest.getProjectHeader().setProperty(ProjectPropertyType.DR_POINTS_PROJECT_PROPERTY_KEY, "0"); -// } - - if (forumId > 0) { - contest.getProjectHeader().setProperty(ProjectPropertyType.DEVELOPER_FORUM_ID_PROJECT_PROPERTY_KEY, String.valueOf(forumId)); - } - - contest.getProjectPhases().setStartDate(getDate(productionDate)); - } - } - - /** - *- * If the auto creating development contest is switch on, we need to prepare the contest here. - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param designContest the design contest - * @param tcDirectProjectId tc-direct-project-id - * @param devContest the development contest to create - * @throws DatatypeConfigurationException if any error occurs - * @throws ContestServiceException if any error occurs - */ - private void autoCreateDevContest(TCSubject tcSubject, SoftwareCompetition designContest, long tcDirectProjectId, - SoftwareCompetition devContest) throws DatatypeConfigurationException, ContestServiceException, PermissionServiceException { - devContest.setAssetDTO(designContest.getAssetDTO()); - devContest.getProjectHeader().getProperties().putAll( - designContest.getDevelopmentProjectHeader().getProperties()); - devContest.setDevelopmentProjectHeader(null); - devContest.getProjectHeader().getProjectCategory().setId(ProjectCategory.DEVELOPMENT.getId()); - devContest.getAssetDTO().setProductionDate(nextDevProdDay(devContest.getAssetDTO().getProductionDate())); - devContest.setProjectHeaderReason("Create corresponding development contest"); - createSoftwareContest(tcSubject, devContest, tcDirectProjectId); - } - /** - *- * Auto creates the bug hunt contest for the parent contest if auto create bug hunt is on. This method prepares - * the bug hunt contest before inserting into the persistence. - *
- * - * @param tcSubject instance contains the login security info for the current user - * @param assemblyContest the parent assembly contest - * @param tcDirectProjectId the if of the direct project - * @param bugHuntContest the bug hunt contest - * @param bugHuntStartTime the scheduled start time of the bug hunt contest - * @throws ContestServiceException if any error occurs realted to Contest Service facade - * @throws PermissionServiceException if any error occurs to Permission service facade - * @since 1.8.3 - */ - private void autoCreateBugHuntContest(TCSubject tcSubject, SoftwareCompetition assemblyContest, long tcDirectProjectId, - SoftwareCompetition bugHuntContest, Date bugHuntStartTime) throws ContestServiceException, PermissionServiceException { - // preCreationAssetDTO.setName("Bug Hunt For " + preCreationAssetDTO); - bugHuntContest.setAssetDTO(assemblyContest.getAssetDTO()); - bugHuntContest.getProjectHeader().getProperties().putAll(assemblyContest.getBugHuntProjectHeader().getProperties()); - - final Map- * Persists the GroupContestEligibility for the contest and client. If the eligiblity is not null, then the - * information will be copied from it. - *
- * @param projectHeader the contest header data - * @param eligiblity, the existing ContestEligibility, could be null - * @param isStudio true for studio - * @throws ContestEligibilityPersistenceException if any error occurs - */ - private void persistContestEligility(Project projectHeader, List- * Adding the contest resources when creating contest. manager or observer or client-manager will be added. - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- *- * Update in v1.6.8: gets the copilot resource from getResources() of SoftwareCompetition. - *
- * - *- * Update in v1.8.3: For auto created bug hunt contest, insert the copilot as reviewer of the bug hunt contest - * if the copilot exists. - *
- * - * @param tcSubject TCSubject instance contains the login security info for the current user - * @param contest the contest to create - * @param billingProjectId the billing project id - * @param requireApproval the flag of whether it's required - * @return resource array - * @throws ContestServiceException fail to retrieve user-handle - */ - private com.topcoder.management.resource.Resource[] createContestResources(TCSubject tcSubject, - SoftwareCompetition contest, long billingProjectId, boolean requireApproval) throws ContestServiceException, UserServiceException, PermissionServiceException { - - // check if contest contains copilot resource - com.topcoder.management.resource.Resource[] contestResources = contest.getResources(); - com.topcoder.management.resource.Resource copilot = null; - com.topcoder.management.resource.Resource appirioManager = null; - - // flag indicates whether current user is set as the copilot - boolean isCopilotCurrentUser = false; - boolean isAppirioManagerCurrentUser = false; - - if (contestResources.length > 1) { - for (int i = 1; i < contestResources.length; ++i) { - - if (contestResources[i].getResourceRole().getId() == ResourceRole.RESOURCE_ROLE_COPILOT_ID) { - // contains copilot resource - copilot = contestResources[1]; - - if (copilot.getProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID).equals( - String.valueOf(tcSubject.getUserId()))) { - isCopilotCurrentUser = true; - } - } else if (contestResources[i].getResourceRole().getId() == ResourceRole.RESOURCE_ROLE_MANAGER_ID) { - appirioManager = contestResources[i]; - if (appirioManager.getProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID).equals( - String.valueOf(tcSubject.getUserId()))) { - isAppirioManagerCurrentUser = true; - } - } - } - } - - // create an array to store the resources, if copilot exists and copilot is not current user, we create - // an array of length 3, otherwise of length 2 - com.topcoder.management.resource.Resource[] resources = - new com.topcoder.management.resource.Resource[2]; - - resources[0] = new com.topcoder.management.resource.Resource(); - resources[0].setId(com.topcoder.management.resource.Resource.UNSET_ID); - - // manager role - ResourceRole managerRole = new ResourceRole(); - managerRole.setId(ResourceRole.RESOURCE_ROLE_MANAGER_ID); - managerRole.setName(ResourceRole.RESOURCE_ROLE_MANAGER_NAME); - managerRole.setDescription(ResourceRole.RESOURCE_ROLE_MANAGER_DESC); - - // observer role - ResourceRole observerRole = new ResourceRole(); - observerRole.setId(ResourceRole.RESOURCE_ROLE_OBSERVER_ID); - observerRole.setName(ResourceRole.RESOURCE_ROLE_OBSERVER_NAME); - observerRole.setDescription(ResourceRole.RESOURCE_ROLE_OBSERVER_DESC); - - // client manager role - ResourceRole clientManagerRole = new ResourceRole(); - clientManagerRole.setId(ResourceRole.RESOURCE_ROLE_CLIENT_MANAGER_ID); - clientManagerRole.setName(ResourceRole.RESOURCE_ROLE_CLIENT_MANAGER_NAME); - clientManagerRole.setDescription(ResourceRole.RESOURCE_ROLE_CLIENT_MANAGER_DESC); - - // copilot role - ResourceRole copilotRole = new ResourceRole(); - copilotRole.setId(ResourceRole.RESOURCE_ROLE_COPILOT_ID); - - // is current user TC staff role - boolean tcstaff = isRole(tcSubject, TC_STAFF_ROLE); - boolean isObserverCopilot = false; - - if (appirioManager != null) { - resources[0] = appirioManager; - } else if (tcstaff) { - resources[0].setResourceRole(managerRole); - } else if (contest.getProjectHeader().getSecurityGroupId() > 0) { - resources[0].setResourceRole(managerRole); - } else { - if (isCopilotCurrentUser) { - // if copilot is current user, then set as copilot - resources[0] = copilot; - isObserverCopilot = true; - } else { - resources[0].setResourceRole(managerRole); - } - } - - if (!isObserverCopilot && appirioManager == null) { - // we don't override the copilot properties if the observer is the copilot - resources[0].setProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID, String.valueOf(tcSubject.getUserId())); - resources[0].setProperty(RESOURCE_INFO_HANDLE, getUserName(tcSubject)); - resources[0].setProperty(RESOURCE_INFO_PAYMENT_STATUS, RESOURCE_INFO_PAYMENT_STATUS_NA); - resources[0].setUserId(tcSubject.getUserId()); - } - - resources[0].setProperty(RESOURCE_INFO_REGISTRATION_DATE, DATE_FORMAT.format(new Date())); - - // for private, check if admin role is set, and use that if so - /** if (getEligibilityName(tcSubject, billingProjectId).trim().length() > 0) { - - String adminRole = getEligibilityAdminRole(tcSubject, billingProjectId).trim(); - - if (adminRole.length() > 0) - { - long roleId = userService.getUserId(adminRole); - resources[1] = new com.topcoder.management.resource.Resource(); - resources[1].setId(com.topcoder.management.resource.Resource.UNSET_ID); - resources[1].setResourceRole(managerRole); - resources[1].setProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID, Long.toString(roleId)); - resources[1].setProperty(RESOURCE_INFO_HANDLE, adminRole); - resources[1].setProperty(RESOURCE_INFO_PAYMENT_STATUS, RESOURCE_INFO_PAYMENT_STATUS_NA); - resources[1].setProperty(RESOURCE_INFO_REGISTRATION_DATE, DATE_FORMAT.format(new Date())); - } - } **/ - // design/dev, add Components - if (contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.DEVELOPMENT.getId() - || contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.DESIGN.getId()) { - - resources[1] = new com.topcoder.management.resource.Resource(); - resources[1].setId(com.topcoder.management.resource.Resource.UNSET_ID); - resources[1].setResourceRole(managerRole); - resources[1].setProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID, Long.toString(components_user_id)); - resources[1].setUserId(components_user_id); - resources[1].setProperty(RESOURCE_INFO_HANDLE, RESOURCE_INFO_HANDLE_COMPONENTS); - resources[1].setProperty(RESOURCE_INFO_PAYMENT_STATUS, RESOURCE_INFO_PAYMENT_STATUS_NA); - resources[1].setProperty(RESOURCE_INFO_REGISTRATION_DATE, DATE_FORMAT.format(new Date())); - } - // else add Applications - else { - resources[1] = new com.topcoder.management.resource.Resource(); - resources[1].setId(com.topcoder.management.resource.Resource.UNSET_ID); - resources[1].setResourceRole(managerRole); - resources[1].setProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID, Long.toString(applications_user_id)); - resources[1].setUserId(applications_user_id); - resources[1].setProperty(RESOURCE_INFO_HANDLE, RESOURCE_INFO_HANDLE_APPLICATIONS); - resources[1].setProperty(RESOURCE_INFO_PAYMENT_STATUS, RESOURCE_INFO_PAYMENT_STATUS_NA); - resources[1].setProperty(RESOURCE_INFO_REGISTRATION_DATE, DATE_FORMAT.format(new Date())); - } - - if (copilot != null && (!isCopilotCurrentUser || appirioManager != null)) { - com.topcoder.management.resource.Resource[] _resources = resources; - resources = new com.topcoder.management.resource.Resource[3]; - resources[0] = _resources[0]; - resources[1] = _resources[1]; - // when copilot exists and copilot is not current user, we store resource in another array element - resources[2] = copilot; - - // and set the registration date with current date - resources[2].setProperty(RESOURCE_INFO_REGISTRATION_DATE, DATE_FORMAT.format(new Date())); - } - - - // add users has permission on cockpit project as observers - ListSoftwareCompetition in one trasaction. If there is SoftwareCompetition
- * not in draft status, it won't be updated.
- *
- * @param tcSubject the tcSubject instance.
- * @param tcDirectProjectId the id of the tc direct project.
- * @param draftContests a list of SoftwareCompetition to update.
- * @return the list of updated SoftwareCompetition
- * @throws ContestServiceException if any error related to contest service facade.
- * @throws PermissionServiceException if any error related to permission service facade.
- * @since 1.9
- */
- public List
- * Updates a SoftwareCompetition in the persistence.
- *
- * Update in version 1.5, reduce the code redundancy in permission checking. - *
- *
- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param contest theSoftwareCompetition to update as a contest
- * @param tcDirectProjectId the TC direct project id.
- * @throws IllegalArgumentException if the input argument is invalid.
- * @throws ContestServiceException if an error occurs when interacting with the service layer.
- * @since TopCoder Service Layer Integration 3 Assembly
- */
- public SoftwareCompetition updateSoftwareContest(TCSubject tcSubject, SoftwareCompetition contest,
- long tcDirectProjectId) throws ContestServiceException, PermissionServiceException {
- return updateSoftwareContest(tcSubject, contest, tcDirectProjectId, null, null, null);
- }
-
- /**
- *
- * Updates a SoftwareCompetition in the persistence.
- *
- * Update in version 1.5, reduce the code redundancy in permission checking. - *
- *
- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * - *- * Update in 1.9.2: Update to support add copilot as the approver of the contest when updating the contest. - *
- * - * @param tcSubject TCSubject instance contains the login security info for the current user - * @param contest theSoftwareCompetition to update as a contest
- * @param tcDirectProjectId the TC direct project id.
- * @param multiRoundEndDate the end date for the multiround phase. No multiround if it's null.
- * @param endDate the end date for submission phase. Can be null if to use default.
- * @throws IllegalArgumentException if the input argument is invalid.
- * @throws ContestServiceException if an error occurs when interacting with the service layer.
- * @since 1.6.6
- */
- public SoftwareCompetition updateSoftwareContest(TCSubject tcSubject, SoftwareCompetition contest,
- long tcDirectProjectId, Date multiRoundEndDate, Date endDate) throws ContestServiceException, PermissionServiceException {
-
- return updateSoftwareContest(tcSubject, contest, tcDirectProjectId, null, multiRoundEndDate, endDate);
- }
-
- /**
- *
- * Updates a SoftwareCompetition in the persistence.
- *
SoftwareCompetition to update as a contest
- * @param tcDirectProjectId the TC direct project id.
- * @param regEndDate the registration end date
- * @param multiRoundEndDate the end date for the multiround phase. No multiround if it's null.
- * @param endDate the end date for submission phase. Can be null if to use default.
- * @throws IllegalArgumentException if the input argument is invalid.
- * @throws ContestServiceException if an error occurs when interacting with the service layer.
- */
- public SoftwareCompetition updateSoftwareContest(TCSubject tcSubject, SoftwareCompetition contest,
- long tcDirectProjectId, Date regEndDate, Date multiRoundEndDate, Date endDate) throws ContestServiceException, PermissionServiceException {
- logger.debug("updateSoftwareContest");
-
- try {
- XMLGregorianCalendar productionDate = null;
-
- if (contest.getAssetDTO() != null) {
- // product date is used to pass the project start date
- // bcoz we need to use XMLGregorianCalendar and project start
- // date
- // is Date and since it is not DTO and hard to change, we use
- // product date for now, but we need to set it null so it will
- // not
- // saved in catalog
- productionDate = contest.getAssetDTO().getProductionDate();
- contest.getAssetDTO().setProductionDate(null);
-
- // TODO: for some reason, versionid is not passed
- contest.getAssetDTO().setCompVersionId(contest.getAssetDTO().getVersionNumber());
- contest.setAssetDTO(this.catalogService.updateAsset(contest.getAssetDTO()));
- }
-
- String oldCMCTaskId = null;
- String cmcTaskId = null;
- Date oldStartDate = null;
- Date oldCheckpointEndDate = null;
- Date oldEndDate = null;
-
- if (contest.getProjectHeader() != null) {
-
- cmcTaskId = contest.getProjectHeader().getProperty(
- ProjectPropertyType.CLOUDSPOKES_CMC_TASK_PROPERTY_KEY);
-
- FullProjectData oldProjectData = projectServices.getFullProjectData(
- contest.getProjectHeader().getId());
-
- Project oldProject = oldProjectData.getProjectHeader();
-
- if(StringUtils.isNotEmpty(cmcTaskId)) {
-
- oldStartDate = oldProjectData.getStartDate();
-
- com.topcoder.project.phases.Phase[] oldPhases = oldProjectData.getAllPhases();
-
- for(com.topcoder.project.phases.Phase oldP : oldPhases) {
- if(oldP.getPhaseType().getId() == PhaseType.REGISTRATION_PHASE.getId()) {
- oldStartDate = oldP.getScheduledStartDate();
- }
- if(oldP.getPhaseType().getId() == PhaseType.CHECKPOINT_SUBMISSION_PHASE.getId()) {
- oldCheckpointEndDate = oldP.getScheduledEndDate();
- }
- if(oldP.getPhaseType().getId() == PhaseType.SUBMISSION_PHASE.getId()) {
- oldEndDate = oldP.getScheduledEndDate();
- }
- }
-
- // get the old cmcTaskID
- oldCMCTaskId = oldProject.getProperty(ProjectPropertyType.CLOUDSPOKES_CMC_TASK_PROPERTY_KEY);
- }
-
- // check the contest status - we do not accept change a active contet back to draft by the direct front end
- if(oldProject.getProjectStatus().getId() == ProjectStatus.ACTIVE.getId()
- && contest.getProjectHeader().getProjectStatus().getId() == ProjectStatus.DRAFT.getId()) {
- // old is active, the new value is draft, not allow, set back to active
- contest.getProjectHeader().setProjectStatus(ProjectStatus.ACTIVE);
-
- // keep the auto pilot property
- contest.getProjectHeader().setProperty(ProjectPropertyType.AUTOPILOT_OPTION_PROJECT_PROPERTY_KEY,
- oldProject.getProperty(ProjectPropertyType.AUTOPILOT_OPTION_PROJECT_PROPERTY_KEY));
- }
-
- // check the permissions
- checkSoftwareContestPermission(tcSubject, contest.getProjectHeader().getId(), false);
- //checkBillingProjectPermission(tcSubject, contest);
-
- //check billing cca
- checkBillingProjectCCA(contest);
-
- Set- * Updates contest observer resources from direct project if the direct project associated is changed. - *
- * - * @param tcSubject the current user - * @param contest the contest to be updated - * @throws Exception if any error occurs - */ - private void updateContestObserversFromDirectProject(TCSubject tcSubject, SoftwareCompetition contest) throws Exception { - long forumId = projectServices.getForumId(contest.getId()); - - // Remove all current observers - for(com.topcoder.management.resource.Resource resource : this.projectServices.searchResources(contest.getId(), ResourceRole.RESOURCE_ROLE_OBSERVER_ID)) { - deleteForumWatchAndRoleForResource(forumId, resource, contest, hasForumType(contest.getProjectHeader())); - this.projectServices.removeResource(resource, String.valueOf(tcSubject.getUserId())); - - } - - // Add observers - // add users has permission on cockpit project as observers - List- * Deletes forum and role for the resource. - *
- * - * @param forumId the forum id - * @param r the resource - * @param contest the contest data - * @param isNewForum whether the forum is ported from studio to software - */ - private void deleteForumWatchAndRoleForResource(long forumId, com.topcoder.management.resource.Resource r, - SoftwareCompetition contest, boolean isNewForum) { - if (forumId <= 0 || !createForum) { - return; - } - - long userId = Long.parseLong(r.getProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID)); - if (!isStudio(contest)) { - deleteSoftwareForumWatchAndRole(forumId, userId); - } else { - deleteStudioForumWatchAndRole(forumId, userId, isNewForum); - } - } - - /** - *- * Add forum and role for the resource and also notification day. - *
- * - * @param forumId the forum id - * @param r the resource - * @param contest the contest data - * @param isNewForum whether the forum is ported from studio to software - */ - private void addForumWatchAndRoleForResource(long forumId, com.topcoder.management.resource.Resource r, - SoftwareCompetition contest, TCSubject tcSubject, boolean isNewForum) throws Exception { - if (forumId <= 0 || !createForum) { - return; - } - - long userId = Long.parseLong(r.getProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID)); - long roleId = r.getResourceRole().getId(); - boolean addNotification; - boolean addForumWatch; - - List- * Adds a new submission for an user in a particular project. - *
- *- * If the project allows multiple submissions for users, it will add the new submission and return. If multiple - * submission are not allowed for the project, firstly it will add the new submission, secondly mark previous - * submissions as deleted and then return. - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param projectId the project's id - * @param filename the file name to use - * @param submission the submission file data - * @return the id of the new submission - * @throws IllegalArgumentException if any id is < 0, if any argument isnull or trim to empty
- * @throws ContestServiceException if an error occurs when interacting with the service layer.
- * @since TopCoder Service Layer Integration 3 Assembly
- */
- public long uploadSubmission(TCSubject tcSubject,long projectId, String filename,
- DataHandler submission) throws ContestServiceException{
- return uploadSubmission(tcSubject.getUserId(), projectId, filename, submission);
- }
-
- /**
- * - * Adds a new submission for an user in a particular project. - *
- *- * If the project allows multiple submissions for users, it will add the new submission and return. If multiple - * submission are not allowed for the project, firstly it will add the new submission, secondly mark previous - * submissions as deleted and then return. - *
- * - * @param userId user Id - * @param projectId project Id - * @param filename filename - * @param submission submission data - * @return - * @throws ContestServiceException - * @since 3.5 - */ - public long uploadSubmission(long userId, long projectId, String filename, DataHandler submission) - throws ContestServiceException { - logger.debug("uploadSubmission"); - - try { - logger.debug("Exit updateSoftwareContest"); - - return uploadExternalServices.uploadSubmission(projectId, - userId, filename, submission); - } catch (UploadServicesException e) { - logger.error("Operation failed in the uploadExternalServices.", e); - throw new ContestServiceException("Operation failed in the uploadExternalServices.", - e); - } catch (RemoteException e) { - logger.error("Operation failed in the uploadExternalServices.", e); - throw new ContestServiceException("Operation failed in the uploadExternalServices.", - e); - } - } - - /** - *- * Adds a new final fix upload for an user in a particular project. This submission always overwrite the previous - * ones. - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param projectId the project's id - * @param filename the file name to use - * @param finalFix the final fix file data - * @return the id of the created final fix submission - * @throws IllegalArgumentException if any id is < 0, if any argument isnull or trim to empty
- * @throws ContestServiceException if an error occurs when interacting with the service layer.
- * @since TopCoder Service Layer Integration 3 Assembly
- */
- public long uploadFinalFix(TCSubject tcSubject, long projectId, String filename, DataHandler finalFix)
- throws ContestServiceException {
- logger.debug("uploadFinalFix");
-
- try {
- logger.debug("Exit uploadFinalFix");
-
- return uploadExternalServices.uploadFinalFix(projectId, tcSubject.getUserId(), filename, finalFix);
- } catch (UploadServicesException e) {
- logger.error("Operation failed in the uploadExternalServices.", e);
- throw new ContestServiceException("Operation failed in the uploadExternalServices.", e);
- } catch (RemoteException e) {
- logger.error("Operation failed in the uploadExternalServices.", e);
- throw new ContestServiceException("Operation failed in the uploadExternalServices.", e);
- }
- }
-
- /**
- * - * Adds a new test case upload for an user in a particular project. This submission always overwrite the previous - * ones. - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param projectId the project's id - * @param filename the file name to use - * @param testCases the test cases data - * @return the id of the created test cases submission - * @throws IllegalArgumentException if any id is < 0, if any argument isnull or trim to empty
- * @throws ContestServiceException if an error occurs when interacting with the service layer.
- * @since TopCoder Service Layer Integration 3 Assembly
- */
- public long uploadTestCases(TCSubject tcSubject, long projectId, String filename, DataHandler testCases)
- throws ContestServiceException {
- logger.debug("uploadTestCases");
-
- try {
- logger.debug("Exit uploadTestCases");
-
- return uploadExternalServices.uploadTestCases(projectId, tcSubject.getUserId(), filename, testCases);
- } catch (UploadServicesException e) {
- logger.error("Operation failed in the uploadExternalServices.", e);
- throw new ContestServiceException("Operation failed in the uploadExternalServices.", e);
- } catch (RemoteException e) {
- logger.error("Operation failed in the uploadExternalServices.", e);
- throw new ContestServiceException("Operation failed in the uploadExternalServices.", e);
- }
- }
-
- /**
- * - * Sets the status of a existing submission. - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param submissionId the submission's id - * @param submissionStatusId the submission status id - * @param operator the operator which execute the operation - * @throws IllegalArgumentException if any id is < 0 or if operator is null or trim to empty - * @throws ContestServiceException if an error occurs when interacting with the service layer. - * @since TopCoder Service Layer Integration 3 Assembly - */ - public void setSubmissionStatus(TCSubject tcSubject, long submissionId, long submissionStatusId, String operator) - throws ContestServiceException { - logger.debug("setSubmissionStatus"); - - try { - uploadExternalServices.setSubmissionStatus(submissionId, submissionStatusId, operator); - logger.debug("Exit setSubmissionStatus"); - } catch (UploadServicesException e) { - logger.error("Operation failed in the uploadExternalServices.", e); - throw new ContestServiceException("Operation failed in the uploadExternalServices.", e); - } catch (RemoteException e) { - logger.error("Operation failed in the uploadExternalServices.", e); - throw new ContestServiceException("Operation failed in the uploadExternalServices.", e); - } - } - - /** - * Adds the given user as a new submitter to the given project id. - *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param projectId the project to which the user needs to be added - * @param userId the user to be added - * @return the added resource id - * @throws IllegalArgumentException if any id is < 0 - * @throws ContestServiceException if an error occurs when interacting with the service layer. - * @since TopCoder Service Layer Integration 3 Assembly - */ - public long addSubmitter(TCSubject tcSubject, long projectId, long userId) throws ContestServiceException { - logger.debug("AddSubmitter (tcSubject = " + tcSubject.getUserId() + ", " + projectId + "," + userId + ")"); - - try { - return uploadExternalServices.addSubmitter(projectId, userId); - } catch (UploadServicesException e) { - logger.error("Operation failed in the uploadExternalServices.", e); - throw new ContestServiceException("Operation failed in the uploadExternalServices.", e); - } catch (RemoteException e) { - logger.error("Operation failed in the uploadExternalServices.", e); - throw new ContestServiceException("Operation failed in the uploadExternalServices.", e); - } - } - - /** - * Get the EJB handler for Forum EJB service. - * - * @param url the EJB bean url - * @return the forum EJB service handler. - * @throws NamingException if a naming exception is encountered. - * @throws RemoteException if remote error occurs. - * @throws CreateException if error occurs when creating EJB handler - * - * @since 1.6.6 - */ - private Forums getForumsEJBFromJNDI(String url) throws NamingException, CreateException, RemoteException { - Properties p = new Properties(); - p.put(Context.INITIAL_CONTEXT_FACTORY, - "org.jnp.interfaces.NamingContextFactory"); - p.put(Context.URL_PKG_PREFIXES, - "org.jboss.naming:org.jnp.interfaces"); - - p.put(Context.PROVIDER_URL, url); - - Context c = new InitialContext(p); - ForumsHome forumsHome = (ForumsHome) c.lookup(ForumsHome.EJB_REF_NAME); - - return forumsHome.create(); - } - - /** - * Get the Software Forum EJB service for Software competitions. - * - * @return the forums EJB service handler. - * @throws NamingException if a naming exception is encountered. - * @throws RemoteException if remote error occurs. - * @throws CreateException if error occurs when creating EJB handler - * - * @since 1.6.11 - */ - private Forums getSoftwareForums() throws RemoteException, NamingException, CreateException { - return getForumsEJBFromJNDI(softwareForumBeanProviderUrl); - } - - /** - * Get the Studio Forum EJB service for Studio competitions. - * - * @return the forums EJB service handler. - * @throws NamingException if a naming exception is encountered. - * @throws RemoteException if remote error occurs. - * @throws CreateException if error occurs when creating EJB handler - * - * @since 1.6.11 - */ - private Forums getStudioForums() throws RemoteException, NamingException, CreateException { - return getForumsEJBFromJNDI(studioForumBeanProviderUrl); - } - - /** - * Create studio forum with given parameters. It will lookup the ForumsHome interface, and create the studio forum - * by the ejb home interface. - * - * @param name the forum name - * @param userId the user id to user - * @return the long id of the create fourm - * @since 1.6.6 - */ - private long createStudioForum(String name, long userId) { - logger.debug("createStudioForm (name = " + name + ", userId = " + userId + ")"); - - try { - Forums forums = getSoftwareForums(); - long forumId = forums.createStudioForumV2(studioForumRootCategoryId, name); - if (forumId < 0) { - throw new Exception("createStudioForum returned negative forum ID: " + forumId); - } - forums.createForumWatch(userId, forumId); - return forumId; - } catch (Exception e) { - logger.error("*** Could not create a studio forum for " + name); - logger.error(e); - } - return -1; - } - - /** - * create forum with given parameters. It will lookup the ForumsHome interface, and ceate the forum by the ejb home - * interface. In the old version, this method misses the document, it's added in the version 1.1 - * - * @param asset The asset DTO to user - * @param userId userId The user id to use - * @param projectCategoryId The project category id to - * @return The long id of the created forum - */ - public long createForum(TCSubject tcSubject, AssetDTO asset, long userId, long projectCategoryId) { - long forumId = -1; - logger.debug("createForum (tcSubject = " + tcSubject.getUserId() + ", " + userId + ")"); - - try { - Forums forums = getSoftwareForums(); - - long phaseId = 0; - - try { - phaseId = Long.parseLong(asset.getPhase()); - } catch (Exception ee) { - } - - forumId = forums.createSoftwareComponentForums(asset.getName(), - asset.getId(), asset.getCompVersionId(), phaseId, - Status.REQUESTED.getStatusId(), - asset.getRootCategory().getId(), - asset.getShortDescription(), asset.getVersionText(), false, - projectCategoryId); - - if (forumId < 0) { - throw new Exception("createStudioForum returned -1"); - } - - logger.error("Created forum " + forumId + " for " + - asset.getName()); - - forums.assignRole(userId, "Software_Moderators_" + forumId); //BUGR- - // 1677 - - forums.createCategoryWatch(userId, forumId); - logger.debug("Exit createForum (" + userId + ")"); - - return forumId; - } catch (Exception e) { - logger.error("*** Could not create a forum for " + asset.getName()); - logger.error(e); - - return forumId; - } - } - - /** - * Close the forum - * - * @param forumid The long id of the forum - */ - public void closeForum(long forumid) { - long forumId = -1; - logger.debug("closeForum (forumid = " + forumid + ")"); - - try { - Properties p = new Properties(); - p.put(Context.INITIAL_CONTEXT_FACTORY, - "org.jnp.interfaces.NamingContextFactory"); - p.put(Context.URL_PKG_PREFIXES, - "org.jboss.naming:org.jnp.interfaces"); - p.put(Context.PROVIDER_URL, softwareForumBeanProviderUrl); - - Context c = new InitialContext(p); - ForumsHome forumsHome = (ForumsHome) c.lookup(ForumsHome.EJB_REF_NAME); - - Forums forums = forumsHome.create(); - - forums.closeCategory(forumid); - - logger.debug("Exit closeForum (" + forumid + ")"); - - } catch (Exception e) { - logger.error("*** Could not close forum for " + forumId); - logger.error(e); - } - } - - /** - *- * Gets the list of all existing contests related to given project for my - * project widget. - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * - * @param pid - * given project id - * @return aList listing all existing contests. Empty list is
- * returned if there are no contests found.
- * @throws PersistenceException
- * if any error occurs when getting contest.
- */
- @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
- public List- * Gets the list of all existing contests for my project widget. - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- *- * Updated for v1.6 Direct Search Assembly - * - provided contest fee for each contest data - *
- * - * @param tcSubject TCSubject instance contains the login security info for the current user - * @return aList listing all existing contests. Empty list is returned if there are no contests found.
- * @throws PersistenceException if any error occurs when getting contest.
- */
- @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
- public ListVersion 1.7.1 - set project status id into the ProjectSummaryData returned
- * - *Version 1.7.5 - set project creation date into the ProjectSummaryData returned
- * - * @param tcSubjectTCSubject object
- * @return a list of ProjectSummaryData objects
- *
- * @throws ContestServiceException if any error occurs during processing
- *
- * @since 1.6
- */
- @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
- public List- * BURG-1716: We need to add a method to get software contest by project id, the method wil get all OR project - * related data, then from project property to get comp version id then to call getAssetByVersionId to get assetDTO, - * please check create software contest to see what data need to be returned. - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param projectId the OR Project Id - * @return SoftwareCompetition - * @throws ContestServiceException if an error occurs when interacting with the service layer. - * @since BURG-1716 - */ - public SoftwareCompetition getSoftwareContestByProjectId(TCSubject tcSubject, long projectId) - throws ContestServiceException, PermissionServiceException { - logger.debug("getSoftwareContestByProjectId (tcSubject = " + tcSubject.getUserId() + ", " + projectId + ")"); - - SoftwareCompetition contest = new SoftwareCompetition(); - - try { - - checkSoftwareContestPermission(tcSubject, projectId, true); - - FullProjectData fullProjectData = this.projectServices.getFullProjectData(projectId); - - Boolean effortHoursEnabled = false; - try { - Client client = projectService.getClientByProject(fullProjectData.getProjectHeader().getTcDirectProjectId()); - if (client != null) { - effortHoursEnabled = client.isEffortHoursEnabled() == null ? false : client.isEffortHoursEnabled(); - } - - } catch (PersistenceFault e) { - effortHoursEnabled = false; - } - - if(!effortHoursEnabled) { - fullProjectData.getProjectHeader().getProperties().remove(ProjectPropertyType.EFFORT_HOURS_ESTIMATE); - } - - Long compVersionId = Long.parseLong(fullProjectData.getProjectHeader() - .getProperty(ProjectPropertyType.EXTERNAL_REFERENCE_ID_PROJECT_PROPERTY_KEY)); - contest.setAssetDTO(this.catalogService.getAssetByVersionId( - compVersionId)); - contest.setProjectHeader(fullProjectData.getProjectHeader()); - contest.setProjectData(fullProjectData); - contest.setProjectPhases(fullProjectData); - contest.getProjectPhases() - .setId(fullProjectData.getProjectHeader().getId()); - contest.setId(projectId); - contest.setProjectResources(fullProjectData.getResources()); - - com.topcoder.project.phases.Phase[] allPhases = fullProjectData.getAllPhases(); - - Date startDate = contest.getProjectPhases().getStartDate(); - for (com.topcoder.project.phases.Phase p : contest.getProjectPhases().getPhases()) - { - if (p.getPhaseType().getId() == PhaseType.REGISTRATION_PHASE.getId()) - { - startDate = p.getFixedStartDate(); - break; - } - } - - // set project start date in production date - contest.getAssetDTO() - .setProductionDate(getXMLGregorianCalendar(startDate)); - - // set null to avoid cycle - contest.getAssetDTO().setDependencies(null); - - if (contest.getAssetDTO().getForum() != null) { - contest.getAssetDTO().getForum().setCompVersion(null); - } - - if (contest.getAssetDTO().getLink() != null) { - contest.getAssetDTO().getLink().setCompVersion(null); - } - - // need to remove loops before returning - removeDocumentationLoops(contest); - - // get the direct project milestone xref - contest.setDirectProjectMilestoneId(projectServices.getProjectMilestoneRelation(contest.getProjectHeader().getId())); - - // get the security group id if there is any - List- * Sends the email for specified template to specified to, cc, bcc address - * from specified from address. - *
- * - * @param templateSource - * the template source - * @param templateName - * the template name or the file path of the template. - * @param subject - * the email subject line - * @param toAddr - * the to-address of the email - * @param ccAddr - * the from-address of the email - * @param bccAddr - * the bcc-address of the email - * @param fromAddr - * the from-address of the email - * @param phase - * the phase data - * @throws EmailMessageGenerationException - * thrown if error during email generation - * @throws EmailSendingException - * thrown if error during email sending. - * - * @since Cockpit Release Assembly for Receipts. - */ - private void sendEmail(String templateSource, String templateName, String subject, String[] toAddrs, String ccAddr, String bccAddr, String fromAddr, com.topcoder.project.phases.Phase phase) - throws EmailMessageGenerationException, EmailSendingException { - boolean messageGenerated = false; - - try { - // Generate the message body first - Template template = (templateSource == null) - ? documentGenerator.getTemplate(templateName) - : documentGenerator.getTemplate(templateSource, templateName); - String messageBody = this.emailMessageGenerator.generateMessage(documentGenerator, - template, phase); - - logger.debug("Generated following email message of subject [" + - subject + "] to be sent to [" + fromAddr + "] \n" + - messageBody); - - // Create a TCSEmailMessage to be sent - TCSEmailMessage email = new TCSEmailMessage(); - - // Set subject, from address and message body. - email.setSubject(subject); - email.setFromAddress(fromAddr); - email.setBody(messageBody); - email.setContentType("text/html"); - - ExceptionUtils.checkNull(toAddrs, null, null, "To address must be non-null."); - for (String toAddr : toAddrs) { - email.addToAddress(toAddr, TCSEmailMessage.TO); - } - - if (ccAddr != null) { - email.addToAddress(ccAddr, TCSEmailMessage.CC); - } - - if (bccAddr != null) { - email.addToAddress(bccAddr, TCSEmailMessage.BCC); - } - - // Now the email message is generated successfully - messageGenerated = true; - - // Send email - EmailEngine.send(email); - logger.debug("Sent email message of subject [" + subject + - "] to [" + fromAddr + "]"); - } catch (BaseException e) { - rethrowEmailError(e, messageGenerated); - } catch (ConfigManagerException e) { - rethrowEmailError(e, messageGenerated); - } catch (IllegalArgumentException e) { - rethrowEmailError(e, messageGenerated); - } - } - - /** - *- * Wrap the given error while sending email and re throw it. - *
- * - *
- * If given messageGenerated is false, then this error occurs
- * while generating email message and thus an
- * EmailMessageGenerationException will be thrown. Otherwise it
- * means the error occurs while sending email and thus an
- * EmailSendingException will be thrown.
- *
messageGenerated is false.
- * @throws EmailSendingException
- * If messageGenerated is true.
- *
- * @since Cockpit Release Assembly for Receipts.
- */
- private void rethrowEmailError(Throwable e, boolean messageGenerated)
- throws EmailMessageGenerationException, EmailSendingException {
- try {
- if (messageGenerated) {
- throw (e instanceof EmailSendingException)
- ? (EmailSendingException) e
- : new EmailSendingException("Error while sending email.", e);
- } else {
- throw (e instanceof EmailMessageGenerationException)
- ? (EmailMessageGenerationException) e
- : new EmailMessageGenerationException("Error while generating email to be sent.",
- e);
- }
- } catch (Exception e1) {
- logger.error("*** Could not generate or send an email to creator of contest",
- e1);
- }
- }
-
- /**
- * Creates and sends email for the activate contest receipt email.
- *
- *
- * Updates in version 1.8.4:
- * - Add the logic to dynamically load activation email template from the passed in competitionTypeId
- *
- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param contestId the contest id - * @param studio indicates whether the specified contest id is for studio contests. - * @return the spec review that matches the specified contest id. - * @throws ContestServiceException if any error during retrieval/save from persistence - * @since Cockpit Launch Contest - Inline Spec Review Part 2 - */ - public SpecReview getSpecReviews(TCSubject tcSubject, long contestId, boolean studio) - throws ContestServiceException { - try { - return this.specReviewService.getSpecReviews(contestId, studio); - } catch (SpecReviewServiceException e) { - throw new ContestServiceException("Error during getSpecReviews", e); - } - } - - /** - * Save specified review comment and review status for specified section and specified contest id to persistence. - *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param contestId the contest id - * @param studio indicates whether the specified contest id is for studio contests. - * @param sectionName the section name - * @param comment the comment - * @param isPass the is pass - * @param role the user role type - * @throws ContestServiceException if any error during retrieval/save from persistence - * @since Cockpit Launch Contest - Inline Spec Review Part 2 - */ - public void saveReviewStatus(TCSubject tcSubject, long contestId, boolean studio, String sectionName, - String comment, boolean isPass, String role) throws ContestServiceException { - try { - this.specReviewService.saveReviewStatus(tcSubject, contestId, studio, sectionName, comment, isPass, role); - } catch (SpecReviewServiceException e) { - throw new ContestServiceException("Error during saveReviewStatus", e); - } - } - - /** - * Save specified review comment for specified section and specified contest id to persistence. - *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param contestId the contest id - * @param studio indicates whether the specified contest id is for studio contests. - * @param sectionName the section name - * @param comment the comment - * @param role the user role type - * @throws ContestServiceException if any error during retrieval/save from persistence - * @since Cockpit Launch Contest - Inline Spec Review Part 2 - */ - public void saveReviewComment(TCSubject tcSubject, long contestId, boolean studio, String sectionName, - String comment, String role) throws ContestServiceException { - try { - this.specReviewService.saveReviewComment(tcSubject, contestId, studio, sectionName, comment, role); - } catch (SpecReviewServiceException e) { - throw new ContestServiceException("Error during saveReviewComment", e); - } - } - - /** - * Mark review comment with specified comment id as seen. - *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param commentId the comment id - * @throws ContestServiceException if any error during retrieval/save from persistence - * @since Cockpit Launch Contest - Inline Spec Review Part 2 - */ - public void markReviewCommentSeen(TCSubject tcSubject, long commentId) throws ContestServiceException { - try { - this.specReviewService.markReviewCommentSeen(tcSubject, commentId); - } catch (SpecReviewServiceException e) { - throw new ContestServiceException("Error during markReviewCommentSeen", e); - } - } - /** - * Marks 'review done' by reviewer of the specs for specified contest. Persistence is updated and all end users - * having write/full permission on the contest are notified by email. - *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param contestId the specified contest id. - * @param contestName the contest name - * @param studio whether contest is studio or not. - * @tcDirectProjectId the tc direct project id. - * @throws ContestServiceException if any error during retrieval/save from persistence - * @since 1.0.1 - */ - public void markReviewDone(TCSubject tcSubject, long contestId, String contestName, boolean studio, - long tcDirectProjectId) throws ContestServiceException { - try { - // get updates. - List- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param contestId the specified contest id. - * @param studio whether contest is studio or not. - * @throws ContestServiceException if any error during retrieval/save from persistence - * @since 1.0.1 - */ - public void markReadyForReview(TCSubject tcSubject, long contestId, boolean studio) throws ContestServiceException { - try { - this.specReviewService.markReadyForReview(tcSubject, contestId, studio); - } catch (SpecReviewServiceException e) { - throw new ContestServiceException("Error during markReadyForReview", e); - } - } - - /** - * Marks 'resubmit for review' by the writer of the specs for specified contest. Persistence is updated. Reviewer - * (if any) is notified about the updates. - *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param contestId the specified contest id. - * @param contestName the contest name - * @param studio whether contest is studio or not. - * @param reviewerUserId reviewer user id. - * @throws ContestServiceException if any error during retrieval/save from persistence - * @since 1.0.1 - */ - public void resubmitForReview(TCSubject tcSubject, long contestId, String contestName, boolean studio, - long reviewerUserId) throws ContestServiceException { - try { - // get updates. - List- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param projectId the billing project id - * @return the list of project contest fees for the given project id - * @throws ContestServiceException if any persistence or other error occurs - * @since 1.0.1 - */ - public List- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @throws ContestServiceException if any other error occurs - * @since 1.1 - */ - public List- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param userId The user id - * @param contestId The contest id - * @param isStudio true if the contest is a studio contest, false otherwise. - * @return true if the user is eligible for the specified contest, false otherwise. - * @throws ContestServiceException if any other error occurs - * @since 1.2.2 - */ - public boolean isEligible(TCSubject tcSubject, long userId, long contestId, boolean isStudio) - throws ContestServiceException { - String methodName = "isEligible"; - logger.info("Enter: " + methodName); - - boolean eligible = false; - - try { - List- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param billingProjectId; The ID of the billing project. - * @return The name of the eligibility group. - * @since 1.2.3 - */ - public String getEligibilityName(TCSubject tcSubject, long billingProjectId) { - String methodName = "getEligibilityName : billing project id = "+ billingProjectId; - logger.info("Enter: " + methodName); - try { - ConfigManager cfgMgr = ConfigManager.getInstance(); - Property rootProperty = cfgMgr.getPropertyObject(CONTEST_ELIGIBILITY_MAPPING_NAMESPACE, - CONTEST_ELIGIBILITY_MAPPING_PREFIX); - Property eligibility = rootProperty.getProperty(Long.toString(billingProjectId)); - if (eligibility != null && !eligibility.equals("")) { - - return (String)(eligibility.getValue(ELIGIBILITY_NAME)); - } - return ""; - } catch (Exception e) { - logger.error("Cannot retrieve eligibility name."); - return ""; - } finally { - logger.info("Exit: " + methodName); - } - } - - /** - * Find eligibility admin role for the billing project. - *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param billingProjectId; The ID of the billing project. - * @return The name of the eligibility group. - * @since 1.2.3 - * - public String getEligibilityAdminRole(TCSubject tcSubject, long billingProjectId) { - String methodName = "getEligibilityAdminRole : billing project id = "+ billingProjectId; - logger.info("Enter: " + methodName); - try { - ConfigManager cfgMgr = ConfigManager.getInstance(); - Property rootProperty = cfgMgr.getPropertyObject(CONTEST_ELIGIBILITY_MAPPING_NAMESPACE, - CONTEST_ELIGIBILITY_MAPPING_PREFIX); - Property eligibility = rootProperty.getProperty(Long.toString(billingProjectId)); - if (eligibility != null && !eligibility.equals("")) { - - return (String)(eligibility.getValue(ELIGIBILITY_ADMIN_ROLE)); - } - return ""; - } catch (Exception e) { - logger.error("Cannot retrieve eligibility admin role."); - return ""; - } finally { - logger.info("Exit: " + methodName); - } - } **/ - - /** - * Private helper method to remove loops within documentation collection in AssetDTO - * - * @param contest the contest which needs loops removal - * - * @since 1.3.4 - */ - private void removeDocumentationLoops(SoftwareCompetition contest) { - if (contest.getAssetDTO().getDocumentation() != null && contest.getAssetDTO().getDocumentation().size() > 0) { - for (CompDocumentation doc : contest.getAssetDTO().getDocumentation()) { - doc.setCompVersion(null); - } - } - } - - /** - * Returns whether the contest is private. - * - *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param contestId - * The contest id - * @param isStudio - * true if the contest is a studio contest, false otherwise. - * @return true if the contest is a private one, false otherwise. - * - * @throws ContestServiceException - * if any other error occurs - * @since 1.2.3 - */ - public boolean isPrivate(TCSubject tcSubject, long contestId, boolean isStudio) throws ContestServiceException { - String methodName = "isPrivate"; - logger.info("Enter: " + methodName); - - List- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param projectId the project id to create a Specification Review for - * @return the created project - * @throws ContestServiceException if any unexpected error occurs in the underlying services - * @since 1.4 - */ - public FullProjectData createSpecReview(TCSubject tcSubject, long projectId) throws ContestServiceException { - String method = "createSpecReview(tcSubject = " + tcSubject.getUserId() + "," + projectId + ")"; - logger.info("Enter: " + method); - - FullProjectData specReview = null; - try { - specReview = projectServices.createSpecReview(projectId, specReviewPrize, String.valueOf(tcSubject.getUserId()), getUserName(tcSubject)); - } catch (ProjectServicesException e) { - logger.error("Operation failed in ProjectServices.", e); - throw new ContestServiceException("Operation failed in Project Services.", e); - } finally { - logger.info("Exit: " + method); - } - - return specReview; - } - - /** - * This method retrieves scorecard and review information associated to a project determined by parameter. Note: a - * single reviewer / review is assumed. - *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param projectId the project id to search for - * @return the aggregated scorecard and review data - * @throws ContestServiceException if any unexpected error occurs in the underlying services - * @since 1.4 - */ - public ScorecardReviewData getScorecardAndReview(TCSubject tcSubject, long projectId) - throws ContestServiceException { - String method = "getScorecardAndReview(tcSubject = " + tcSubject.getUserId() + "," + projectId + ")"; - logger.info("Enter: " + method); - - ScorecardReviewData scorecardReviewData = null; - try { - scorecardReviewData = projectServices.getScorecardAndReview(projectId); - } catch (ProjectServicesException e) { - logger.error("Operation failed in Project Services.", e); - throw new ContestServiceException("Operation failed in Project Services.", e); - } finally { - logger.info("Exit: " + method); - } - - return scorecardReviewData; - } - - /** - * This method uploads a mock file to the corresponding specification review project of the specified project id, so - * that it can continue with review. Regular submission or final fix will be uploaded according to the open phase. - *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param projectId the project id of the original project - * @throws ContestServiceException if any unexpected error occurs in the underlying services, if the associated - * specification review project id cannot be found or if neither submission or final fixes phase are - * open. - * @since 1.4 - */ - public void markSoftwareContestReadyForReview(TCSubject tcSubject, long projectId) throws ContestServiceException { - String method = "markSoftwareContestReadyForReview(tcSubject = " + tcSubject.getUserId() + "," + projectId + ")"; - logger.info("Enter: " + method); - - try { - // get associated specification review project id - long specReviewProjectId = projectServices.getSpecReviewProjectId(projectId); - if (specReviewProjectId < 0) { - throw new ContestServiceException("Failed to get associated specification review."); - } - - // get associated specification review open phases - Set- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param reviewId the review id to add the comment to - * @param comment the review comment to add - * @throws ContestServiceException if any unexpected error occurs in the underlying services. - * @throws IllegalArgumentException if comment is null - * @since 1.4 - */ - public void addReviewComment(TCSubject tcSubject, long reviewId, Comment comment) throws ContestServiceException { - if (comment == null) { - throw new IllegalArgumentException("The comment cannot be null"); - } - - String method = "addReviewComment(tcSubject = " + tcSubject.getUserId() + "," + reviewId + ", " + comment + ")"; - logger.info("Enter: " + method); - - try { - projectServices.addReviewComment(reviewId, comment, String.valueOf(tcSubject.getUserId())); - } catch (ProjectServicesException e) { - logger.error("Operation failed in Project Services.", e); - throw new ContestServiceException("Operation failed in Project Services.", e); - } finally { - logger.info("Exit: " + method); - } - } - - /** - * create software forum watch with given parameters. It will lookup the ForumsHome - * interface, and ceate the forum by the ejb home interface. In the old - * version, this method misses the document, it's added in the version 1.1 - * - * - * @param asset - * The asset DTO to user - * @param userId - * userId The user id to use - * @param projectCategoryId - * The project category id to - * @return The long id of the created forum - */ - private void createSoftwareForumWatchAndRole(long forumId, long userId, boolean watch) { - logger.debug("createSoftwareForumWatchAndRole (" + forumId + ", " + userId + ")"); - - try { - Forums forums = getSoftwareForums(); - - String roleId = "Software_Moderators_" + forumId; - if (watch) - { - forums.createCategoryWatch(userId, forumId); - } - - forums.assignRole(userId, roleId); - - logger.debug("Exit createSoftwareForumWatchAndRole (" + forumId + ", " + userId + ")"); - - } catch (Exception e) { - logger.error("*** Could not create a softwaer forum watch for " + forumId + ", " + userId ); - logger.error(e); - } - } - - /** - * create stduio forum watch with given parameters. It will lookup the ForumsHome - * interface, and ceate the forum by the ejb home interface. In the old - * version, this method misses the document, it's added in the version 1.1 - * - * - * @param asset - * The asset DTO to user - * @param userId - * userId The user id to use - * @param projectCategoryId - * The project category id to - * @param isNewStudioForum whether the forum is ported to the studio part. - * @return The long id of the created forum - */ - private void createStudioForumWatchAndRole(long forumId, long userId, boolean watch, boolean isNewStudioForum) { - logger.debug("createStudioForumWatchAndRole (" + forumId + ", " + userId + ")"); - - try { - Forums forums = isNewStudioForum ? getSoftwareForums() : getStudioForums(); - - String roleId = "Software_Moderators_" + forumId; - if (watch) - { - forums.createForumWatch(userId, forumId); - } - - forums.assignRole(userId, roleId); - - logger.debug("Exit createStudioForumWatchAndRole (" + forumId + ", " + userId + ")"); - - } catch (Exception e) { - logger.error("*** Could not create a studio forum watch for " + forumId + ", " + userId ); - logger.error(e); - } - } - - /** - * delete software forum watch with given parameters. It will lookup the ForumsHome - * interface, and ceate the forum by the ejb home interface. In the old - * version, this method misses the document, it's added in the version 1.1 - * - * - * @param forumId - * The forum id to delete watch. - * @param userId - * userId The user id to use - */ - private void deleteSoftwareForumWatchAndRole(long forumId, long userId) { - logger.info("deleteForumWatch (" + forumId + ", " + userId + ")"); - - try { - Forums forums = getSoftwareForums(); - - String roleId = "Software_Moderators_" + forumId; - forums.deleteCategoryWatch(userId, forumId); - forums.removeRole(userId, roleId); - logger.debug("Exit deleteForumWatch (" + forumId + ", " + userId + ")"); - - } catch (Exception e) { - logger.error("*** Could not delete forum watch for " + forumId + ", " + userId ); - logger.error(e); - } - } - - /** - * delete forum watch with given parameters. It will lookup the ForumsHome - * interface, and ceate the forum by the ejb home interface. In the old - * version, this method misses the document, it's added in the version 1.1 - * - * - * @param forumId - * The forum id to delete watch. - * @param userId - * userId The user id to use - * @param isNewStudioForum whethether the studio forum is ported to the software forum - */ - private void deleteStudioForumWatchAndRole(long forumId, long userId, boolean isNewStudioForum) { - logger.info("deleteForumWatch (" + forumId + ", " + userId + ")"); - - try { - Forums forums = isNewStudioForum ? getSoftwareForums() : getStudioForums(); - - String roleId = "Software_Moderators_" + forumId; - forums.deleteForumWatch(userId, forumId); - forums.removeRole(userId, roleId); - logger.debug("Exit deleteForumWatch (" + forumId + ", " + userId + ")"); - - } catch (Exception e) { - logger.error("*** Could not delete forum watch for " + forumId + ", " + userId ); - logger.error(e); - } - } - - - /** - * update forum name - * - * @param forumId - * The forum id to update - * @param name - * The name to use - */ - private void updateForumName(long forumId, String name) { - logger.info("updateForumName (" + forumId + ", " + name + ")"); - - try { - Forums forums = getSoftwareForums(); - - forums.updateComponentName(forumId, name); - - logger.debug("Exit updateForumName (" + forumId + ", " + name + ")"); - - } catch (Exception e) { - logger.error("*** Could not updateForumName for " + forumId + ", " + name ); - logger.error(e); - } - } - - /** - * Update studio forum name. - * - * @param forumId - * The forum id to update - * @param name - * The name to use - */ - private void updateStudioForumName(long forumId, String name) { - logger.info("updateStudioForumName (" + forumId + ", " + name + ")"); - - try { - Forums forums = getSoftwareForums(); - - forums.updateStudioForumName(forumId, name); - - logger.debug("Exit updateStudioForumName (" + forumId + ", " + name + ")"); - - } catch (Exception e) { - logger.error("*** Could not updateStudioForumName for " + forumId + ", " + name ); - logger.error(e); - } - } - - /** - * check if user agrees the term(s) associate with the project (if any) - * by role - * - * @param projectId - * OR project id - * @param userId - * userId The user id to use - * @param roleId - * role id - * @return true if user agreed terms or no term associated with project - */ - private boolean checkTerms(long projectId, long userId, int[] roleIds) { - logger.info("checkTerms (" + projectId + ", " + userId + ", " + roleIds + ")"); - - try { - Properties p = new Properties(); - p.put(Context.INITIAL_CONTEXT_FACTORY, - "org.jnp.interfaces.NamingContextFactory"); - p.put(Context.URL_PKG_PREFIXES, - "org.jboss.naming:org.jnp.interfaces"); - p.put(Context.PROVIDER_URL, userBeanProviderUrl); - - Context c = new InitialContext(p); - UserTermsOfUseHome userTermsOfUseHome = (UserTermsOfUseHome) c.lookup(UserTermsOfUseHome.EJB_REF_NAME); - - UserTermsOfUse userTerm = userTermsOfUseHome.create(); - - Properties p2 = new Properties(); - p2.put(Context.INITIAL_CONTEXT_FACTORY, - "org.jnp.interfaces.NamingContextFactory"); - p2.put(Context.URL_PKG_PREFIXES, - "org.jboss.naming:org.jnp.interfaces"); - p2.put(Context.PROVIDER_URL, projectBeanProviderUrl); - - Context c2 = new InitialContext(p2); - ProjectRoleTermsOfUseHome projectRoleTermsOfUseHome = (ProjectRoleTermsOfUseHome) c2.lookup(ProjectRoleTermsOfUseHome.EJB_REF_NAME); - - ProjectRoleTermsOfUse projectTerm = projectRoleTermsOfUseHome.create(); - - List- * Create new version for design or development contest. (project_status_id = 4-10 in - * tcs_catalog:project_status_lu). - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param projectId the project to create new version - * @param tcDirectProjectId tc direct project id - * @param autoDevCreating if it is true and it is design contest, then will create development too - * @param startDate the start date for the new version contest - * @return newly version contest id - * @throws ContestServiceException if any error occurs - */ - private long createNewVersionForDesignDevContest(TCSubject tcSubject, long projectId, long tcDirectProjectId, - boolean autoDevCreating, XMLGregorianCalendar startDate, boolean minorVersion) - throws ContestServiceException, PermissionServiceException { - try { - //0.check the permission first - checkSoftwareProjectPermission(tcSubject, tcDirectProjectId, true); - //1. for now, only completed can create new version - FullProjectData contest = this.projectServices.getFullProjectData(projectId); - // if auto dev creating, dont check, since we pass the new design project id - if (!autoDevCreating && contest.getProjectHeader().getProjectStatus().getId() != ProjectStatus.COMPLETED_STATUS_ID) { - throw new ProjectServicesException("The design project or its corresponding development project is not completed." - + " You can not create new version for it."); - } - boolean isDevContest = - contest.getProjectHeader().getProjectCategory().getId() == ProjectCategory.DEVELOPMENT.getId(); - - //2.create new version - Long compVersionId = Long.parseLong(contest.getProjectHeader().getProperty(ProjectPropertyType.EXTERNAL_REFERENCE_ID_PROJECT_PROPERTY_KEY)); - AssetDTO dto = catalogService.getAssetByVersionId(compVersionId); - // close current version - dto.setPhase("Completed"); - com.topcoder.project.phases.Phase[] phases = contest.getAllPhases(); - dto.setProductionDate(getXMLGregorianCalendar(phases[phases.length-1].getActualEndDate())); - // close current forum - if (createForum && dto.getForum() != null) - { - closeForum(dto.getForum().getJiveCategoryId()); - } - dto.setForum(null); - catalogService.updateAsset(dto); - - //create minor or major version - dto.setToCreateMinorVersion(minorVersion); - dto.setProductionDate(null); - - //if it is dev only, or design, create new version here - if (!isDevContest || !autoDevCreating) { - //clear the version - dto.setCompVersionId(null); - dto.setForum(null); - dto.setDocumentation(new ArrayList- * Create new version for design or development contest. (project_status_id = 4-10 in - * tcs_catalog:project_status_lu). - *
- *- * since version 1.5. - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param projectId the project to create new version - * @param tcDirectProjectId tc direct project id - * @param autoDevCreating if it is true and it is design contest, then will create development too - * @return newly version contest id - * @throws ContestServiceException if any error occurs - */ - public long createNewVersionForDesignDevContest(TCSubject tcSubject, long projectId, long tcDirectProjectId, - boolean autoDevCreating, boolean minorVersion) throws ContestServiceException, PermissionServiceException { - logger.debug("createNewVersionForDesignDevContest with parameter [TCSubject " + tcSubject.getUserId() + ", projectId =" + projectId - + ", tcDirectProjectId =" +tcDirectProjectId+", autoDevCreating="+ autoDevCreating +"]."); - - return createNewVersionForDesignDevContest(tcSubject, projectId, tcDirectProjectId, autoDevCreating, - nextReOpenNewReleaseDay(), minorVersion); - } - - /** - *- * Reopen the software contest. - *
- *- * since version 1.5. - *
- *- * Update in v1.5.1: add parameter TCSubject which contains the security info for current user. - *
- * @param tcSubject TCSubject instance contains the login security info for the current user - * @param projectId the project to repost - * @param tcDirectProjectId the tc direct project id - * @return the newly created OR project id - * @throws ContestServiceException if any error occurs during repost - */ - public long reOpenSoftwareContest(TCSubject tcSubject, long projectId, long tcDirectProjectId) - throws ContestServiceException, PermissionServiceException { - logger.debug("reOpenSoftwareContest with parameter [TCSubject " + tcSubject.getUserId() + ", projectId =" + projectId + ", tcDirectProjectId =" +tcDirectProjectId+"]."); - - long reOpenContestId = 0; - try { - - //0.check the permission first - checkSoftwareProjectPermission(tcSubject, tcDirectProjectId, true); - - //1.make sure it is failed status and can be re-opened. - FullProjectData contest = projectServices.getFullProjectData(projectId); - if (contest == null) { - throw new ContestServiceException("The project does not exist."); - } - if (contest.getProjectHeader().getProjectStatus().getId() != ProjectStatus.CANCELLED_FAILED_REVIEW_ID - && contest.getProjectHeader().getProjectStatus().getId() != ProjectStatus.CANCELLED_FAILED_SCREENING_ID - && contest.getProjectHeader().getProjectStatus().getId() != ProjectStatus.CANCELLED_ZERO_SUBMISSION_ID - && contest.getProjectHeader().getProjectStatus().getId() != ProjectStatus.CANCELLED_WINNER_UNRESPONSIVE_ID - && contest.getProjectHeader().getProjectStatus().getId() != ProjectStatus.CANCELLED_CLIENT_REQUEST.getId() - && contest.getProjectHeader().getProjectStatus().getId() != ProjectStatus.CANCELLED_REQUIREMENTS_INFEASIBLE.getId() - && contest.getProjectHeader().getProjectStatus().getId() != ProjectStatus.CANCELLED_ZERO_REGISTRATIONS.getId()) { - throw new ProjectServicesException("The project is not failed. You can not re-open it."); - } - - // set status to draft - contest.getProjectHeader().setProjectStatus(ProjectStatus.DRAFT); - - contest.setStartDate(getDate(nextReOpenNewReleaseDay())); - //2.create the project - FullProjectData reOpendedProject = - projectServices.createReOpenContest(contest, String.valueOf(tcSubject.getUserId())); - - //3. keep terms and eligibility - ListPhase associated with the resource.
- * @param isStudio whether assign to studio contest.
- * @since 1.6.9
- */
- private void assignRole(TCSubject tcSubject, long projectId, long roleId, long userId, com.topcoder.project.phases.Phase phase,
- boolean addNotification, boolean addForumWatch, boolean isStudio, boolean checkTerm)
- throws ContestServiceException {
- logger.debug("enter methods assignRole");
-
- try {
- // com.topcoder.management.resource.Resource[] resources = projectServices.searchResources(projectId, roleId);
-
- boolean found = false;
-
- found = projectServices.resourceExists(projectId, roleId, userId);
-
- boolean termChecking = !checkTerm || checkTerms(projectId, userId, new int[] { (int) roleId });
-
-
- // if not found && user agreed terms (if any) && is eligible, add resource
- if (!found && termChecking
- && isEligible(tcSubject, userId, projectId, false)) {
-
- com.topcoder.management.resource.Resource newRes = new com.topcoder.management.resource.Resource();
- newRes.setId(com.topcoder.management.resource.Resource.UNSET_ID);
- newRes.setProject(projectId);
-
- ResourceRole[] allroles = projectServices.getAllResourceRoles();
- ResourceRole roleToSet = null;
- if (allroles != null && allroles.length > 0)
- {
- for (ResourceRole role : allroles)
- {
- if (role.getId() == roleId)
- {
- roleToSet = role;
- }
- }
- }
-
- if (roleToSet == null)
- {
- throw new ContestServiceException("Invalid role id " + roleId);
- }
-
- newRes.setResourceRole(roleToSet);
- if (phase != null) {
- newRes.setPhase(phase.getId());
- }
-
- newRes.setProperty(RESOURCE_INFO_EXTERNAL_REFERENCE_ID, String.valueOf(userId));
- newRes.setProperty(RESOURCE_INFO_HANDLE, String.valueOf(userService.getUserHandle(userId)));
- newRes.setProperty(RESOURCE_INFO_PAYMENT_STATUS, RESOURCE_INFO_PAYMENT_STATUS_NA);
- newRes.setProperty(RESOURCE_INFO_REGISTRATION_DATE, DATE_FORMAT.format(new Date()));
- newRes.setUserId(userId);
- projectServices.updateResource(newRes, String.valueOf(tcSubject.getUserId()));
-
- // only check notification setting for observer, else always addd
- if (roleId != ResourceRole.RESOURCE_ROLE_OBSERVER_ID || addNotification) {
- projectServices.addNotifications(userId,
- new long[] { projectId },
- String.valueOf(tcSubject.getUserId()));
- }
-
-
- // create forum watch
- long forumId = projectServices.getForumId(projectId);
-
- // only check notification for observer
- if (roleId != ResourceRole.RESOURCE_ROLE_OBSERVER_ID)
- {
- addForumWatch = true;
- }
-
- if (forumId > 0 && createForum && !isStudio) {
- createSoftwareForumWatchAndRole(forumId, userId, addForumWatch);
- }
-
- }
-
- } catch (UserServiceException use) {
- sessionContext.setRollbackOnly();
- throw new ContestServiceException(use.getMessage(), use);
- } catch (ContestServiceException cse) {
- sessionContext.setRollbackOnly();
- throw new ContestServiceException(cse.getMessage(), cse);
- } finally {
- logger.debug("exist method assignRole");
- }
- }
-
- /**
- * Assign the given roleId to the specified userId in the given project.
- *
- * @param tcSubject the TCSubject instance.
- * @param projectId the id of the project.
- * @param roleId the id of the role.
- * @param userId the id of the user.
- *
- * @since BUGR-3731
- */
- public void assginRole(TCSubject tcSubject, long projectId, long roleId, long userId)
- throws ContestServiceException {
- assignRole(tcSubject, projectId, roleId, userId, null, true, true, false, false);
- }
-
- /* Assigns the role for the given tc project and user, it will assign all projects
- * uder tc direct projct
- *
- * @param tcprojectId the id of the tc direct project.
- * @param roleId the id of the role
- * @param userId the id of the user.
- * @throws ContestServiceException if any error occurs
- * @since BUGR - 3731
- */
- public void assginRoleByTCDirectProject(TCSubject tcSubject, long tcprojectId, long roleId, long userId) throws ContestServiceException
- {
-
- List