Java tutorial
/*! LICENSE * * Copyright (c) 2015, The Agile Factory SA and/or its affiliates. All rights * reserved. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. */ package controllers.core; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.inject.Inject; import org.apache.commons.lang3.tuple.Pair; import com.avaje.ebean.ExpressionList; import com.avaje.ebean.OrderBy; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import be.objectify.deadbolt.java.actions.Dynamic; import constants.IMafConstants; import controllers.ControllersUtils; import controllers.core.TimesheetController.OptionData; import dao.delivery.DeliverableDAO; import dao.delivery.IterationDAO; import dao.delivery.RequirementDAO; import dao.pmo.ActorDao; import dao.pmo.PortfolioEntryDao; import framework.highcharts.pattern.BasicBar; import framework.highcharts.pattern.DistributedDonut; import framework.highcharts.pattern.RangeLine; import framework.security.ISecurityService; import framework.services.account.IAccountManagerPlugin; import framework.services.account.IPreferenceManagerPlugin; import framework.services.configuration.II18nMessagesPlugin; import framework.services.custom_attribute.ICustomAttributeManagerService; import framework.services.session.IUserSessionManagerPlugin; import framework.utils.FilterConfig; import framework.utils.Msg; import framework.utils.Pagination; import framework.utils.Table; import framework.utils.Utilities; import models.delivery.Deliverable; import models.delivery.Iteration; import models.delivery.PortfolioEntryDeliverable; import models.delivery.Requirement; import models.delivery.RequirementPriority; import models.delivery.RequirementSeverity; import models.delivery.RequirementStatus.Type; import models.pmo.Actor; import models.pmo.PortfolioEntry; import play.Configuration; import play.Logger; import play.data.Form; import play.mvc.Controller; import play.mvc.Result; import play.mvc.With; import security.CheckPortfolioEntryExists; import security.dynamic.PortfolioEntryDynamicHelper; import services.tableprovider.ITableProvider; import utils.form.DeliverableFormData; import utils.form.DeliverableRequirementsFormData; import utils.form.FollowDeliverableFormData; import utils.form.IterationFormData; import utils.form.RequirementFormData; import utils.table.DeliverableListView; import utils.table.IterationListView; import utils.table.RequirementListView; /** * The controller which allows to manage the delivery part of a portfolio entry. * * @author Johann Kohler */ public class PortfolioEntryDeliveryController extends Controller { @Inject private II18nMessagesPlugin messagesPlugin; @Inject private ISecurityService securityService; @Inject private Configuration configuration; @Inject private IUserSessionManagerPlugin userSessionManagerPlugin; @Inject private II18nMessagesPlugin i18nMessagesPlugin; @Inject private IAccountManagerPlugin accountManagerPlugin; @Inject private ITableProvider tableProvider; @Inject private IPreferenceManagerPlugin preferenceManagerPlugin; @Inject private ICustomAttributeManagerService customAttributeManagerService; private static Logger.ALogger log = Logger.of(PortfolioEntryDeliveryController.class); public static Form<IterationFormData> iterationFormTemplate = Form.form(IterationFormData.class); public static Form<RequirementFormData> formTemplate = Form.form(RequirementFormData.class); public static Form<DeliverableFormData> deliverableFormTemplate = Form.form(DeliverableFormData.class); private static Form<DeliverableRequirementsFormData> deliverableRequirementsFormTemplate = Form .form(DeliverableRequirementsFormData.class); private static Form<FollowDeliverableFormData> followDeliverableFormTemplate = Form .form(FollowDeliverableFormData.class); /** * Display the list of the deliverables of a portfolio entry. * * @param id * the portfolio entry id */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_DETAILS_DYNAMIC_PERMISSION) public Result deliverables(Long id) { // get the portfolio entry PortfolioEntry portfolioEntry = PortfolioEntryDao.getPEById(id); try { boolean existDeliverables = DeliverableDAO.getDeliverableAsExprByPE(id).findRowCount() > 0 ? true : false; // get the filter config String uid = getUserSessionManagerPlugin().getUserSessionId(ctx()); FilterConfig<DeliverableListView> filterConfig = this.getTableProvider().get().deliverable.filterConfig .getCurrent(uid, request()); // get the table Pair<Table<DeliverableListView>, Pagination<Deliverable>> t = getDeliverablesTable(id, filterConfig); return ok(views.html.core.portfolioentrydelivery.deliverables.render(existDeliverables, portfolioEntry, t.getLeft(), t.getRight(), filterConfig)); } catch (Exception e) { return ControllersUtils.logAndReturnUnexpectedError(e, log, getConfiguration(), getI18nMessagesPlugin()); } } /** * Filter the deliverables. * * @param id * the portfolio entry id */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_DETAILS_DYNAMIC_PERMISSION) public Result deliverablesFilter(Long id) { try { // get the filter config String uid = getUserSessionManagerPlugin().getUserSessionId(ctx()); FilterConfig<DeliverableListView> filterConfig = this.getTableProvider().get().deliverable.filterConfig .persistCurrentInDefault(uid, request()); if (filterConfig == null) { return ok(views.html.framework_views.parts.table.dynamic_tableview_no_more_compatible.render()); } else { // get the table Pair<Table<DeliverableListView>, Pagination<Deliverable>> t = getDeliverablesTable(id, filterConfig); return ok( views.html.framework_views.parts.table.dynamic_tableview.render(t.getLeft(), t.getRight())); } } catch (Exception e) { return ControllersUtils.logAndReturnUnexpectedError(e, log, getConfiguration(), getI18nMessagesPlugin()); } } /** * Get the deliverables table for a portfolio entry and a filter config. * * @param portfolioEntryId * the portfolio entry id * @param filterConfig * the filter config. */ private Pair<Table<DeliverableListView>, Pagination<Deliverable>> getDeliverablesTable(Long portfolioEntryId, FilterConfig<DeliverableListView> filterConfig) { ExpressionList<Deliverable> expressionList = filterConfig .updateWithSearchExpression(DeliverableDAO.getDeliverableAsExprByPE(portfolioEntryId)); filterConfig.updateWithSortExpression(expressionList); Pagination<Deliverable> pagination = new Pagination<Deliverable>(this.getPreferenceManagerPlugin(), expressionList); pagination.setCurrentPage(filterConfig.getCurrentPage()); List<DeliverableListView> deliverableListView = new ArrayList<DeliverableListView>(); for (Deliverable deliverable : pagination.getListOfObjects()) { PortfolioEntryDeliverable portfolioEntryDeliverable = DeliverableDAO .getPortfolioEntryDeliverableById(portfolioEntryId, deliverable.id); deliverableListView.add(new DeliverableListView(portfolioEntryDeliverable)); } Set<String> columnsToHide = filterConfig.getColumnsToHide(); if (!getSecurityService().dynamic("PORTFOLIO_ENTRY_EDIT_DYNAMIC_PERMISSION", "")) { columnsToHide.add("editActionLink"); columnsToHide.add("deleteActionLink"); } Table<DeliverableListView> table = this.getTableProvider().get().deliverable.templateTable .fillForFilterConfig(deliverableListView, columnsToHide); return Pair.of(table, pagination); } /** * View details of a deliverable. * * @param id * the portfolio entry id * @param deliverableId * the deliverable id */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_DETAILS_DYNAMIC_PERMISSION) public Result viewDeliverable(Long id, Long deliverableId) { PortfolioEntryDeliverable portfolioEntryDeliverable = DeliverableDAO.getPortfolioEntryDeliverableById(id, deliverableId); Deliverable deliverable = portfolioEntryDeliverable.getDeliverable(); PortfolioEntry portfolioEntry = portfolioEntryDeliverable.getPortfolioEntry(); List<RequirementListView> requirementsListView = new ArrayList<>(); for (Requirement requirement : deliverable.requirements) { requirementsListView.add(new RequirementListView(requirement)); } Set<String> columnsToHide = new HashSet<>(); columnsToHide.add("deliverables"); columnsToHide.add("iteration"); columnsToHide.add("category"); columnsToHide.add("requirementPriority"); columnsToHide.add("requirementSeverity"); columnsToHide.add("isScoped"); columnsToHide.add("author"); columnsToHide.add("storyPoints"); columnsToHide.add("initialEstimation"); columnsToHide.add("effort"); columnsToHide.add("remainingEffort"); columnsToHide.add("editActionLink"); if (!getSecurityService().dynamic("PORTFOLIO_ENTRY_EDIT_DYNAMIC_PERMISSION", "")) { columnsToHide.add("editActionLink"); } Table<RequirementListView> filledRequirementsTable = this.getTableProvider().get().requirement.templateTable .fill(requirementsListView, columnsToHide); // construct the corresponding form data (for the custom attributes) DeliverableFormData deliverableFormData = new DeliverableFormData(deliverable, portfolioEntryDeliverable); return ok(views.html.core.portfolioentrydelivery.deliverable_view.render(portfolioEntry, portfolioEntryDeliverable, deliverableFormData, filledRequirementsTable)); } /** * Form to manage a deliverable. * * @param id * the portfolio entry id * @param deliverableId * the deliverable id (0 for create case) */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_EDIT_DYNAMIC_PERMISSION) public Result manageDeliverable(Long id, Long deliverableId) { // get the portfolioEntry PortfolioEntry portfolioEntry = PortfolioEntryDao.getPEById(id); // initiate the form with the template Form<DeliverableFormData> deliverableForm = deliverableFormTemplate; boolean isOwner = false; if (!deliverableId.equals(Long.valueOf(0))) { // edit PortfolioEntryDeliverable portfolioEntryDeliverable = DeliverableDAO .getPortfolioEntryDeliverableById(id, deliverableId); Deliverable deliverable = portfolioEntryDeliverable.getDeliverable(); deliverableForm = deliverableFormTemplate .fill(new DeliverableFormData(deliverable, portfolioEntryDeliverable)); isOwner = portfolioEntryDeliverable.type.equals(PortfolioEntryDeliverable.Type.OWNER); // add the custom attributes values this.getCustomAttributeManagerService().fillWithValues(deliverableForm, Deliverable.class, deliverableId); } else { // create // add the custom attributes default values this.getCustomAttributeManagerService().fillWithValues(deliverableForm, Deliverable.class, null); isOwner = true; } return ok(views.html.core.portfolioentrydelivery.deliverable_manage.render(portfolioEntry, deliverableForm, isOwner)); } /** * Process the creation/edition of a deliverable. */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_EDIT_DYNAMIC_PERMISSION) public Result processManageDeliverable() { // bind the form Form<DeliverableFormData> boundForm = deliverableFormTemplate.bindFromRequest(); // get the portfolioEntry Long id = Long.valueOf(boundForm.data().get("id")); PortfolioEntry portfolioEntry = PortfolioEntryDao.getPEById(id); // get the is owner attribute boolean isOwner = Boolean.valueOf(boundForm.data().get("isOwner")); if (boundForm.hasErrors() || (isOwner && this.getCustomAttributeManagerService().validateValues(boundForm, Deliverable.class))) { return ok(views.html.core.portfolioentrydelivery.deliverable_manage.render(portfolioEntry, boundForm, isOwner)); } DeliverableFormData deliverableFormData = boundForm.get(); PortfolioEntryDeliverable portfolioEntryDeliverable = null; Deliverable deliverable = null; if (deliverableFormData.deliverableId == null) { // create case deliverable = new Deliverable(); deliverableFormData.fillDeliverable(deliverable); deliverable.save(); portfolioEntryDeliverable = new PortfolioEntryDeliverable(portfolioEntry, deliverable); portfolioEntryDeliverable.type = PortfolioEntryDeliverable.Type.OWNER; deliverableFormData.fillPortfolioEntryDeliverable(portfolioEntryDeliverable); portfolioEntryDeliverable.save(); Utilities.sendSuccessFlashMessage(Msg.get("core.portfolio_entry_delivery.deliverable.add.successful")); } else { // edit case portfolioEntryDeliverable = DeliverableDAO.getPortfolioEntryDeliverableById(id, deliverableFormData.deliverableId); deliverable = portfolioEntryDeliverable.getDeliverable(); if (portfolioEntryDeliverable.type.equals(PortfolioEntryDeliverable.Type.OWNER)) { deliverableFormData.fillDeliverable(deliverable); deliverable.save(); } deliverableFormData.fillPortfolioEntryDeliverable(portfolioEntryDeliverable); portfolioEntryDeliverable.save(); Utilities.sendSuccessFlashMessage(Msg.get("core.portfolio_entry_delivery.deliverable.edit.successful")); } // save the custom attributes if (portfolioEntryDeliverable.type.equals(PortfolioEntryDeliverable.Type.OWNER)) { this.getCustomAttributeManagerService().validateAndSaveValues(boundForm, Deliverable.class, deliverable.id); } return redirect(controllers.core.routes.PortfolioEntryDeliveryController.deliverables(portfolioEntry.id)); } /** * Form to follow a deliverable from another portfolio entry. * * @param id * the portfolio entry id */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_EDIT_DYNAMIC_PERMISSION) public Result followDeliverable(Long id) { // get the portfolioEntry PortfolioEntry portfolioEntry = PortfolioEntryDao.getPEById(id); return ok(views.html.core.portfolioentrydelivery.deliverable_follow.render(portfolioEntry, followDeliverableFormTemplate)); } /** * Process the form to follow a deliverable from another portfolio entry. */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_EDIT_DYNAMIC_PERMISSION) public Result processFollowDeliverable() { // bind the form Form<FollowDeliverableFormData> boundForm = followDeliverableFormTemplate.bindFromRequest(); // get the portfolioEntry Long id = Long.valueOf(boundForm.data().get("id")); PortfolioEntry portfolioEntry = PortfolioEntryDao.getPEById(id); if (boundForm.hasErrors()) { return ok(views.html.core.portfolioentrydelivery.deliverable_follow.render(portfolioEntry, boundForm)); } FollowDeliverableFormData followDeliverableFormData = boundForm.get(); if (!PortfolioEntryDynamicHelper.isPortfolioEntryViewAllowed(followDeliverableFormData.otherPortfolioEntry, this.getSecurityService())) { return forbidden(views.html.error.access_forbidden.render("")); } if (id.equals(followDeliverableFormData.otherPortfolioEntry)) { boundForm.reject("otherPortfolioEntry", Msg.get("core.portfolio_entry_delivery.deliverable.follow.error.same_portfolio_entry")); return ok(views.html.core.portfolioentrydelivery.deliverable_follow.render(portfolioEntry, boundForm)); } if (DeliverableDAO.getPortfolioEntryDeliverableById(id, followDeliverableFormData.otherDeliverable) != null) { boundForm.reject("otherDeliverable", Msg.get("core.portfolio_entry_delivery.deliverable.follow.error.already_assigned")); return ok(views.html.core.portfolioentrydelivery.deliverable_follow.render(portfolioEntry, boundForm)); } Deliverable deliverable = DeliverableDAO.getDeliverableById(followDeliverableFormData.otherDeliverable); PortfolioEntryDeliverable portfolioEntryDeliverable = new PortfolioEntryDeliverable(portfolioEntry, deliverable); portfolioEntryDeliverable.type = PortfolioEntryDeliverable.Type.FOLLOWER; portfolioEntryDeliverable.save(); Utilities.sendSuccessFlashMessage(Msg.get("core.portfolio_entry_delivery.deliverable.follow.successful")); return redirect(controllers.core.routes.PortfolioEntryDeliveryController.deliverables(portfolioEntry.id)); } /** * Follow a deliverable: get the deliverables of the other portfolio entry * (represented by the "id" query param). */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_VIEW_DYNAMIC_PERMISSION) public Result getDeliverables() { Long id = Long.valueOf(request().getQueryString("id")); List<Deliverable> deliverables = DeliverableDAO.getDeliverableAsExprByPE(id).findList(); List<OptionData> options = new ArrayList<OptionData>(); for (Deliverable deliverable : deliverables) { options.add(new OptionData(deliverable.id, deliverable.getName())); } ObjectMapper mapper = new ObjectMapper(); return ok((JsonNode) mapper.valueToTree(options)); } /** * Unfollow a deliverable. * * @param id * the portfolio entry id * @param deliverableId * the deliverable id */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_EDIT_DYNAMIC_PERMISSION) public Result unfollowDeliverable(Long id, Long deliverableId) { PortfolioEntryDeliverable portfolioEntryDeliverable = DeliverableDAO.getPortfolioEntryDeliverableById(id, deliverableId); portfolioEntryDeliverable.delete(); Utilities.sendSuccessFlashMessage(Msg.get("core.portfolio_entry_delivery.deliverable.unfollow.successful")); return redirect(controllers.core.routes.PortfolioEntryDeliveryController.deliverables(id)); } /** * Delete a deliverable. * * @param id * the portfolio entry id * @param deliverableId * the deliverable id */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_EDIT_DYNAMIC_PERMISSION) public Result deleteDeliverable(Long id, Long deliverableId) { PortfolioEntryDeliverable portfolioEntryDeliverable = DeliverableDAO.getPortfolioEntryDeliverableById(id, deliverableId); if (!portfolioEntryDeliverable.type.equals(PortfolioEntryDeliverable.Type.OWNER)) { return forbidden(views.html.error.access_forbidden.render("")); } Deliverable deliverable = portfolioEntryDeliverable.getDeliverable(); deliverable.doDelete(); Utilities.sendSuccessFlashMessage(Msg.get("core.portfolio_entry_delivery.deliverable.delete.successful")); return redirect(controllers.core.routes.PortfolioEntryDeliveryController.deliverables(id)); } /** * Form to edit the requirements assignments of the deliverable. * * @param id * the portfolio entry id * @param deliverableId * the deliverable id */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_EDIT_DYNAMIC_PERMISSION) public Result editDeliverableRequirements(Long id, Long deliverableId) { PortfolioEntryDeliverable portfolioEntryDeliverable = DeliverableDAO.getPortfolioEntryDeliverableById(id, deliverableId); if (!portfolioEntryDeliverable.type.equals(PortfolioEntryDeliverable.Type.OWNER)) { return forbidden(views.html.error.access_forbidden.render("")); } PortfolioEntry portfolioEntry = portfolioEntryDeliverable.getPortfolioEntry(); Deliverable deliverable = portfolioEntryDeliverable.getDeliverable(); // construct the form Form<DeliverableRequirementsFormData> deliverableRequirementsForm = deliverableRequirementsFormTemplate .fill(new DeliverableRequirementsFormData(portfolioEntryDeliverable)); return ok(views.html.core.portfolioentrydelivery.deliverable_requirements_edit.render(portfolioEntry, deliverable, deliverableRequirementsForm)); } /** * Process the form to edit the requirements assignments of the deliverable. */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_EDIT_DYNAMIC_PERMISSION) public Result processEditDeliverableRequirements() { // bind the form Form<DeliverableRequirementsFormData> boundForm = deliverableRequirementsFormTemplate.bindFromRequest(); // get the portfolioEntry deliverable relation Long id = Long.valueOf(boundForm.data().get("id")); Long deliverableId = Long.valueOf(boundForm.data().get("deliverableId")); PortfolioEntryDeliverable portfolioEntryDeliverable = DeliverableDAO.getPortfolioEntryDeliverableById(id, deliverableId); PortfolioEntry portfolioEntry = portfolioEntryDeliverable.getPortfolioEntry(); Deliverable deliverable = portfolioEntryDeliverable.getDeliverable(); if (!portfolioEntryDeliverable.type.equals(PortfolioEntryDeliverable.Type.OWNER)) { return forbidden(views.html.error.access_forbidden.render("")); } if (boundForm.hasErrors()) { return ok(views.html.core.portfolioentrydelivery.deliverable_requirements_edit.render(portfolioEntry, deliverable, boundForm)); } DeliverableRequirementsFormData deliverableRequirementsFormData = boundForm.get(); deliverableRequirementsFormData.fill(deliverable); deliverable.save(); Utilities.sendSuccessFlashMessage( Msg.get("core.portfolio_entry_delivery.deliverable.requirements.edit.successful")); return redirect(controllers.core.routes.PortfolioEntryDeliveryController.viewDeliverable(portfolioEntry.id, deliverable.id)); } /** * Display the list of the requirements of a portfolio entry. * * @param id * the portfolio entry id */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_DETAILS_DYNAMIC_PERMISSION) public Result requirements(Long id) { // get the portfolio entry PortfolioEntry portfolioEntry = PortfolioEntryDao.getPEById(id); try { // get the filter config String uid = getUserSessionManagerPlugin().getUserSessionId(ctx()); FilterConfig<RequirementListView> filterConfig = this.getTableProvider().get().requirement.filterConfig .getCurrent(uid, request()); ExpressionList<Requirement> expressionList = filterConfig .updateWithSearchExpression(RequirementDAO.getRequirementAsExprByPE(id)); filterConfig.updateWithSortExpression(expressionList); Pagination<Requirement> pagination = new Pagination<Requirement>(this.getPreferenceManagerPlugin(), expressionList); pagination.setCurrentPage(filterConfig.getCurrentPage()); List<RequirementListView> requirementListView = new ArrayList<RequirementListView>(); for (Requirement requirement : pagination.getListOfObjects()) { requirementListView.add(new RequirementListView(requirement)); } Set<String> hideColumns = filterConfig.getColumnsToHide(); if (!getSecurityService().dynamic("PORTFOLIO_ENTRY_EDIT_DYNAMIC_PERMISSION", "")) { hideColumns.add("editActionLink"); } Table<RequirementListView> filledTable = this.getTableProvider().get().requirement.templateTable .fillForFilterConfig(requirementListView, hideColumns); return ok(views.html.core.portfolioentrydelivery.requirements.render(portfolioEntry, filledTable, pagination, filterConfig)); } catch (Exception e) { return ControllersUtils.logAndReturnUnexpectedError(e, log, getConfiguration(), getMessagesPlugin()); } } /** * Filter the requirements. * * @param id * the portfolio entry id */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_DETAILS_DYNAMIC_PERMISSION) public Result requirementsFilter(Long id) { try { // get the filter config String uid = getUserSessionManagerPlugin().getUserSessionId(ctx()); FilterConfig<RequirementListView> filterConfig = this.getTableProvider().get().requirement.filterConfig .persistCurrentInDefault(uid, request()); if (filterConfig == null) { return ok(views.html.framework_views.parts.table.dynamic_tableview_no_more_compatible.render()); } else { ExpressionList<Requirement> expressionList = filterConfig .updateWithSearchExpression(RequirementDAO.getRequirementAsExprByPE(id)); filterConfig.updateWithSortExpression(expressionList); Pagination<Requirement> pagination = new Pagination<Requirement>(this.getPreferenceManagerPlugin(), expressionList); pagination.setCurrentPage(filterConfig.getCurrentPage()); List<RequirementListView> requirementListView = new ArrayList<RequirementListView>(); for (Requirement requirement : pagination.getListOfObjects()) { requirementListView.add(new RequirementListView(requirement)); } Set<String> hideColumns = filterConfig.getColumnsToHide(); if (!getSecurityService().dynamic("PORTFOLIO_ENTRY_EDIT_DYNAMIC_PERMISSION", "")) { hideColumns.add("editActionLink"); } Table<RequirementListView> filledTable = this.getTableProvider().get().requirement.templateTable .fillForFilterConfig(requirementListView, hideColumns); return ok(views.html.framework_views.parts.table.dynamic_tableview.render(filledTable, pagination)); } } catch (Exception e) { return ControllersUtils.logAndReturnUnexpectedError(e, log, getConfiguration(), getMessagesPlugin()); } } /** * Display the status (charts) of the requirements of a portfolio entry. * * @param id * the portfolio entry id */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_DETAILS_DYNAMIC_PERMISSION) public Result requirementsStatus(Long id) { // get the portfolio entry PortfolioEntry portfolioEntry = PortfolioEntryDao.getPEById(id); // priority pie chart (for the needs) DistributedDonut distributedDonutPriority = new DistributedDonut(getMessagesPlugin()); DistributedDonut.Elem mustElem = new DistributedDonut.Elem( Msg.get("core.portfolio_entry_delivery.requirement.status.priority.must.true.label")); double mustTotal = 0; for (Type type : Type.values()) { Double count = Double.valueOf( RequirementDAO.getRequirementNeedsAsExprByPEAndStatusType(id, type, true).findRowCount()); if (count != null && count.doubleValue() != 0) { mustElem.addSubValue(Msg.get("object.requirement_status.type." + type.name() + ".label"), count); mustTotal += count.doubleValue(); } } if (mustTotal != 0) { mustElem.setValue(mustTotal); distributedDonutPriority.addElem(mustElem); } DistributedDonut.Elem notMustElem = new DistributedDonut.Elem( Msg.get("core.portfolio_entry_delivery.requirement.status.priority.must.false.label")); double notMustTotal = 0; for (Type type : Type.values()) { Double count = Double.valueOf( RequirementDAO.getRequirementNeedsAsExprByPEAndStatusType(id, type, false).findRowCount()); if (count != null && count.doubleValue() != 0) { notMustElem.addSubValue(Msg.get("object.requirement_status.type." + type.name() + ".label"), count); notMustTotal += count.doubleValue(); } } if (notMustTotal != 0) { notMustElem.setValue(notMustTotal); distributedDonutPriority.addElem(notMustElem); } if (distributedDonutPriority.isEmpty()) { distributedDonutPriority = null; } // priority bar chart (for the needs) BasicBar basicBarPriority = null; if (distributedDonutPriority != null) { basicBarPriority = new BasicBar(); for (Type type : Type.values()) { basicBarPriority.addCategory(Msg.get("object.requirement_status.type." + type.name() + ".label")); } for (RequirementPriority priority : RequirementDAO.getRequirementPriorityAsList()) { BasicBar.Elem elem = new BasicBar.Elem(priority.getName()); for (Type type : Type.values()) { elem.addValue(Double.valueOf(RequirementDAO .getRequirementNeedsAsExprByPEAndStatusTypeAndPriority(id, type, priority.id) .findRowCount())); } basicBarPriority.addElem(elem); } } // severity pie chart (for the defects) DistributedDonut distributedDonutSeverity = new DistributedDonut(getMessagesPlugin()); DistributedDonut.Elem blockerElem = new DistributedDonut.Elem( Msg.get("core.portfolio_entry_delivery.requirement.status.severity.blocker.true.label")); double blockerTotal = 0; for (Type type : Type.values()) { Double count = Double.valueOf( RequirementDAO.getRequirementDefectsAsExprByPEAndStatusType(id, type, true).findRowCount()); if (count != null && count.doubleValue() != 0) { blockerElem.addSubValue(Msg.get("object.requirement_status.type." + type.name() + ".label"), count); blockerTotal += count.doubleValue(); } } if (blockerTotal != 0) { blockerElem.setValue(blockerTotal); distributedDonutSeverity.addElem(blockerElem); } DistributedDonut.Elem nonBlockerElem = new DistributedDonut.Elem( Msg.get("core.portfolio_entry_delivery.requirement.status.severity.blocker.false.label")); double nonBlockerTotal = 0; for (Type type : Type.values()) { Double count = Double.valueOf( RequirementDAO.getRequirementDefectsAsExprByPEAndStatusType(id, type, false).findRowCount()); if (count != null && count.doubleValue() != 0) { nonBlockerElem.addSubValue(Msg.get("object.requirement_status.type." + type.name() + ".label"), count); nonBlockerTotal += count.doubleValue(); } } if (nonBlockerTotal != 0) { nonBlockerElem.setValue(nonBlockerTotal); distributedDonutSeverity.addElem(nonBlockerElem); } if (distributedDonutSeverity.isEmpty()) { distributedDonutSeverity = null; } // severity bar chart (for the defects) BasicBar basicBarSeverity = null; if (distributedDonutSeverity != null) { basicBarSeverity = new BasicBar(); for (Type type : Type.values()) { basicBarSeverity.addCategory(Msg.get("object.requirement_status.type." + type.name() + ".label")); } for (RequirementSeverity requirementSeverity : RequirementDAO.getRequirementSeverityAsList()) { BasicBar.Elem elem = new BasicBar.Elem(requirementSeverity.getName()); for (Type type : Type.values()) { elem.addValue(Double .valueOf(RequirementDAO.getRequirementDefectsAsExprByPEAndStatusTypeAndSeverity(id, type, requirementSeverity.id).findRowCount())); } basicBarSeverity.addElem(elem); } } return ok(views.html.core.portfolioentrydelivery.requirements_status.render(portfolioEntry, distributedDonutPriority, basicBarPriority, distributedDonutSeverity, basicBarSeverity)); } /** * View all details of a requirement. * * @param id * the portfolio entry id * @param requirementId * the requirement id */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_DETAILS_DYNAMIC_PERMISSION) public Result viewRequirement(Long id, Long requirementId) { // get the portfolio entry PortfolioEntry portfolioEntry = PortfolioEntryDao.getPEById(id); // get the requirement Requirement requirement = RequirementDAO.getRequirementById(requirementId); // construct the corresponding form data (for the custom attributes) RequirementFormData requirementFormData = new RequirementFormData(requirement); // security: the portfolioEntry must be related to the object if (!requirement.portfolioEntry.id.equals(id)) { return forbidden(views.html.error.access_forbidden.render("")); } return ok(views.html.core.portfolioentrydelivery.requirement_view.render(portfolioEntry, requirement, requirementFormData)); } /** * Form to manage a requirement. * * If it is provided externally (for example by Redmine), then it's possible * to edit only the deliverables and custom attributes. * * @param id * the portfolio entry id * @param requirementId * the requirement id (0 for create) */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_EDIT_DYNAMIC_PERMISSION) public Result manageRequirement(Long id, Long requirementId) { // get the portfolio entry PortfolioEntry portfolioEntry = PortfolioEntryDao.getPEById(id); // initiate the form with the template Form<RequirementFormData> requirementForm = null; // initiate the requirement Requirement requirement = null; if (!requirementId.equals(Long.valueOf(0))) { // edit // get the requirement requirement = RequirementDAO.getRequirementById(requirementId); // security: the portfolio entry must be related to the object if (!requirement.portfolioEntry.id.equals(id)) { return forbidden(views.html.error.access_forbidden.render("")); } requirementForm = formTemplate.fill(new RequirementFormData(requirement)); // add the custom attributes values this.getCustomAttributeManagerService().fillWithValues(requirementForm, Requirement.class, requirementId); } else { // create Actor actor = ActorDao.getActorByUidOrCreateDefaultActor(getAccountManagerPlugin(), getUserSessionManagerPlugin().getUserSessionId(ctx())); requirementForm = formTemplate.fill(new RequirementFormData(actor)); // add the custom attributes default values this.getCustomAttributeManagerService().fillWithValues(requirementForm, Requirement.class, null); } return ok(views.html.core.portfolioentrydelivery.requirement_manage.render(portfolioEntry, requirement, requirementForm)); } /** * Process the edition of a requirement. */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_EDIT_DYNAMIC_PERMISSION) public Result processManageRequirement() { // bind the form Form<RequirementFormData> boundForm = formTemplate.bindFromRequest(); // get the portfolioEntry Long id = Long.valueOf(boundForm.data().get("id")); PortfolioEntry portfolioEntry = PortfolioEntryDao.getPEById(id); // get the requirement Requirement requirement = null; String requirementIdString = boundForm.data().get("requirementId"); if (requirementIdString != null) { requirement = RequirementDAO.getRequirementById(Long.valueOf(requirementIdString)); } if (boundForm.hasErrors() || this.getCustomAttributeManagerService().validateValues(boundForm, Requirement.class)) { return ok(views.html.core.portfolioentrydelivery.requirement_manage.render(portfolioEntry, requirement, boundForm)); } RequirementFormData requirementFormData = boundForm.get(); if (requirement == null) { // create case requirement = new Requirement(); requirement.portfolioEntry = portfolioEntry; requirementFormData.fill(requirement); requirement.save(); Utilities.sendSuccessFlashMessage(Msg.get("core.portfolio_entry_delivery.requirement.add.successful")); } else { // edit case // security: the portfolio entry must be related to the object if (!requirement.portfolioEntry.id.equals(id)) { return forbidden(views.html.error.access_forbidden.render("")); } requirementFormData.fill(requirement); requirement.update(); Utilities.sendSuccessFlashMessage(Msg.get("core.portfolio_entry_delivery.requirement.edit.successful")); } // save the custom attributes this.getCustomAttributeManagerService().validateAndSaveValues(boundForm, Requirement.class, requirement.id); return redirect(controllers.core.routes.PortfolioEntryDeliveryController.requirements(portfolioEntry.id)); } /** * Display the iterations of a portfolio entry. * * @param id * the portfolio entry id */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_DETAILS_DYNAMIC_PERMISSION) public Result iterations(Long id) { // get the portfolio entry PortfolioEntry portfolioEntry = PortfolioEntryDao.getPEById(id); try { // get the filter config String uid = getUserSessionManagerPlugin().getUserSessionId(ctx()); FilterConfig<IterationListView> filterConfig = this.getTableProvider().get().iteration.filterConfig .getCurrent(uid, request()); // get the table Pair<Table<IterationListView>, Pagination<Iteration>> t = getIterationsTable(id, filterConfig); // burndown chart ExpressionList<Iteration> expressionList = filterConfig .updateWithSearchExpression(IterationDAO.getIterationAllAsExprByPE(id)); OrderBy<Iteration> orderBy = expressionList.orderBy(); orderBy.asc("endDate"); List<Iteration> iterations = expressionList.findList(); RangeLine rangeLine = null; if (iterations != null && iterations.size() > 0) { rangeLine = new RangeLine(); // the first value name is start rangeLine.addValueName(Msg.get("core.portfolio_entry_delivery.iterations.burndown.start.label")); // compute the total story points, add the ranges and the value // names Integer totalStoryPoints = 0; for (Iteration iteration : iterations) { if (iteration.storyPoints != null && iteration.endDate != null) { rangeLine.addRange(iteration.getName()); rangeLine.addValueName( Msg.get("core.portfolio_entry_delivery.iterations.burndown.end_of_iteration.label", iteration.getName())); totalStoryPoints += iteration.storyPoints; } } // add the elems RangeLine.Elem plannedElem = new RangeLine.Elem( Msg.get("core.portfolio_entry_delivery.iterations.burndown.planned.label")); RangeLine.Elem realElem = new RangeLine.Elem( Msg.get("core.portfolio_entry_delivery.iterations.burndown.real.label")); rangeLine.addElem(plannedElem); rangeLine.addElem(realElem); plannedElem.addValue(totalStoryPoints.doubleValue()); realElem.addValue(totalStoryPoints.doubleValue()); Integer currentPlannedStoryPoints = totalStoryPoints; Integer currentRealStoryPoints = totalStoryPoints; for (Iteration iteration : iterations) { if (iteration.storyPoints != null && iteration.endDate != null) { currentPlannedStoryPoints -= iteration.storyPoints; plannedElem.addValue(currentPlannedStoryPoints.doubleValue()); if (iteration.isClosed) { // sum of closed story points of requirements currentRealStoryPoints -= RequirementDAO .getStoryPointClosedAsCountByIteration(iteration.id); realElem.addValue(currentRealStoryPoints.doubleValue()); } else { currentRealStoryPoints -= iteration.storyPoints; realElem.addValue(null); } } } } return ok(views.html.core.portfolioentrydelivery.iterations.render(portfolioEntry, t.getLeft(), t.getRight(), filterConfig, rangeLine)); } catch (Exception e) { return ControllersUtils.logAndReturnUnexpectedError(e, log, getConfiguration(), getMessagesPlugin()); } } /** * Filter the iterations. * * @param id * the portfolio entry id */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_DETAILS_DYNAMIC_PERMISSION) public Result iterationsFilter(Long id) { try { // get the filter config String uid = getUserSessionManagerPlugin().getUserSessionId(ctx()); FilterConfig<IterationListView> filterConfig = this.getTableProvider().get().iteration.filterConfig .persistCurrentInDefault(uid, request()); if (filterConfig == null) { return ok(views.html.framework_views.parts.table.dynamic_tableview_no_more_compatible.render()); } else { // get the table Pair<Table<IterationListView>, Pagination<Iteration>> t = getIterationsTable(id, filterConfig); return ok( views.html.framework_views.parts.table.dynamic_tableview.render(t.getLeft(), t.getRight())); } } catch (Exception e) { return ControllersUtils.logAndReturnUnexpectedError(e, log, getConfiguration(), getMessagesPlugin()); } } /** * Get the iterations table for a portfolio entry and a filter config. * * @param portfolioEntryId * the portfolio entry id * @param filterConfig * the filter config. */ private Pair<Table<IterationListView>, Pagination<Iteration>> getIterationsTable(Long portfolioEntryId, FilterConfig<IterationListView> filterConfig) { ExpressionList<Iteration> expressionList = filterConfig .updateWithSearchExpression(IterationDAO.getIterationAllAsExprByPE(portfolioEntryId)); filterConfig.updateWithSortExpression(expressionList); Pagination<Iteration> pagination = new Pagination<Iteration>(this.getPreferenceManagerPlugin(), expressionList); pagination.setCurrentPage(filterConfig.getCurrentPage()); List<IterationListView> iterationListView = new ArrayList<IterationListView>(); for (Iteration iteration : pagination.getListOfObjects()) { iterationListView.add(new IterationListView(iteration)); } Set<String> hideColumns = filterConfig.getColumnsToHide(); if (!getSecurityService().dynamic("PORTFOLIO_ENTRY_EDIT_DYNAMIC_PERMISSION", "")) { hideColumns.add("editActionLink"); } Table<IterationListView> table = this.getTableProvider().get().iteration.templateTable .fillForFilterConfig(iterationListView, hideColumns); return Pair.of(table, pagination); } /** * Display the details of an iteration. * * @param id * the portfolio entry id * @param iterationId * the iteration id */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_DETAILS_DYNAMIC_PERMISSION) public Result viewIteration(Long id, Long iterationId) { // get the portfolio entry PortfolioEntry portfolioEntry = PortfolioEntryDao.getPEById(id); // get the iteration Iteration iteration = IterationDAO.getIterationById(iterationId); // construct the corresponding form data (for the custom attributes) IterationFormData iterationFormData = new IterationFormData(iteration); // security: the portfolioEntry must be related to the object if (!iteration.portfolioEntry.id.equals(id)) { return forbidden(views.html.error.access_forbidden.render("")); } return ok(views.html.core.portfolioentrydelivery.iteration_view.render(portfolioEntry, iteration, iterationFormData)); } /** * Edit an iteration. * * @param id * the portfolio entry id * @param iterationId * the iteration id */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_EDIT_DYNAMIC_PERMISSION) public Result editIteration(Long id, Long iterationId) { // get the portfolioEntry PortfolioEntry portfolioEntry = PortfolioEntryDao.getPEById(id); Iteration iteration = IterationDAO.getIterationById(iterationId); // security: the portfolioEntry must be related to the object if (!iteration.portfolioEntry.id.equals(id)) { return forbidden(views.html.error.access_forbidden.render("")); } Form<IterationFormData> iterationForm = iterationFormTemplate.fill(new IterationFormData(iteration)); // add the custom attributes values this.getCustomAttributeManagerService().fillWithValues(iterationForm, Iteration.class, iterationId); return ok(views.html.core.portfolioentrydelivery.iteration_edit.render(portfolioEntry, iterationForm)); } /** * Save an iteration. */ @With(CheckPortfolioEntryExists.class) @Dynamic(IMafConstants.PORTFOLIO_ENTRY_EDIT_DYNAMIC_PERMISSION) public Result processEditIteration() { // bind the form Form<IterationFormData> boundForm = iterationFormTemplate.bindFromRequest(); // get the portfolioEntry Long id = Long.valueOf(boundForm.data().get("id")); PortfolioEntry portfolioEntry = PortfolioEntryDao.getPEById(id); if (boundForm.hasErrors() || this.getCustomAttributeManagerService().validateValues(boundForm, Iteration.class)) { return ok(views.html.core.portfolioentrydelivery.iteration_edit.render(portfolioEntry, boundForm)); } IterationFormData iterationFormData = boundForm.get(); Iteration iteration = IterationDAO.getIterationById(iterationFormData.iterationId); // security: the portfolioEntry must be related to the object if (!iteration.portfolioEntry.id.equals(id)) { return forbidden(views.html.error.access_forbidden.render("")); } iterationFormData.fill(iteration); iteration.update(); // save the custom attributes this.getCustomAttributeManagerService().validateAndSaveValues(boundForm, Iteration.class, iteration.id); Utilities.sendSuccessFlashMessage(Msg.get("core.portfolio_entry_delivery.iteration.edit.successful")); return redirect(controllers.core.routes.PortfolioEntryDeliveryController.iterations(id)); } /** * Get the messages service. */ private II18nMessagesPlugin getMessagesPlugin() { return messagesPlugin; } /** * Get the security service. */ private ISecurityService getSecurityService() { return securityService; } /** * Get the Play configuration service. */ private Configuration getConfiguration() { return configuration; } /** * Get the user session manager service. */ private IUserSessionManagerPlugin getUserSessionManagerPlugin() { return userSessionManagerPlugin; } /** * Get the i18n messages service. */ private II18nMessagesPlugin getI18nMessagesPlugin() { return i18nMessagesPlugin; } /** * Get the account manager service. */ private IAccountManagerPlugin getAccountManagerPlugin() { return this.accountManagerPlugin; } /** * Get the table provider. */ private ITableProvider getTableProvider() { return this.tableProvider; } /** * Get the preference manager service. */ private IPreferenceManagerPlugin getPreferenceManagerPlugin() { return this.preferenceManagerPlugin; } /** * Get the custom attribute manager service. */ private ICustomAttributeManagerService getCustomAttributeManagerService() { return this.customAttributeManagerService; } }