/**********************************************************************************
* $URL:https://source.sakaiproject.org/svn/osp/trunk/matrix/tool/src/java/org/theospi/portfolio/matrix/control/ViewMatrixController.java $
* $Id:ViewMatrixController.java 9134 2006-05-08 20:28:42Z chmaurer@iupui.edu $
***********************************************************************************
*
* Copyright (c) 2005, 2006, 2007, 2008 The Sakai Foundation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.opensource.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**********************************************************************************/
package org.theospi.portfolio.matrix.control;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.assignment.api.Assignment;
import org.sakaiproject.assignment.api.AssignmentSubmission;
import org.sakaiproject.assignment.cover.AssignmentService;
import org.sakaiproject.authz.api.Role;
import org.sakaiproject.authz.api.SecurityService;
import org.sakaiproject.component.cover.ServerConfigurationService;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.metaobj.security.FunctionConstants;
import org.sakaiproject.metaobj.shared.model.Agent;
import org.sakaiproject.metaobj.shared.model.Id;
import org.sakaiproject.metaobj.utils.mvc.intf.FormController;
import org.sakaiproject.metaobj.utils.mvc.intf.LoadObjectController;
import org.sakaiproject.site.api.Group;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.api.ToolConfiguration;
import org.sakaiproject.site.cover.SiteService;
import org.sakaiproject.taggable.api.TaggableItem;
import org.sakaiproject.tool.api.Placement;
import org.sakaiproject.tool.api.ToolManager;
import org.sakaiproject.tool.api.ToolSession;
import org.sakaiproject.tool.cover.SessionManager;
import org.sakaiproject.user.api.User;
import org.sakaiproject.user.cover.UserDirectoryService;
import org.springframework.validation.Errors;
import org.springframework.web.servlet.ModelAndView;
import org.theospi.portfolio.assignment.AssignmentHelper;
import org.theospi.portfolio.matrix.MatrixFunctionConstants;
import org.theospi.portfolio.matrix.MatrixManager;
import org.theospi.portfolio.matrix.model.Cell;
import org.theospi.portfolio.matrix.model.Criterion;
import org.theospi.portfolio.matrix.model.Level;
import org.theospi.portfolio.matrix.model.Matrix;
import org.theospi.portfolio.matrix.model.Scaffolding;
import org.theospi.portfolio.matrix.model.ScaffoldingCell;
import org.theospi.portfolio.matrix.model.WizardPage;
import org.theospi.portfolio.matrix.model.impl.MatrixContentEntityProducer;
import org.theospi.portfolio.review.mgt.ReviewManager;
import org.theospi.portfolio.review.model.Review;
import org.theospi.portfolio.shared.model.Node;
import org.theospi.portfolio.shared.model.WizardMatrixConstants;
import org.theospi.portfolio.style.mgt.StyleManager;
import org.theospi.portfolio.security.Authorization;
import org.theospi.portfolio.wizard.taggable.api.WizardActivityProducer;
import org.springframework.transaction.annotation.Transactional;
public class ViewMatrixController extends AbstractMatrixController implements FormController, LoadObjectController {
protected final Log logger = LogFactory.getLog(getClass());
private SecurityService securityService;
public static final String VIEW_USER = "view_user";
public static final String GROUP_FILTER = "group_filter";
public static final String GROUP_FILTER_BUTTON = "filter";
private static int MATRIX_ROW_FOOTER = 10;
private ToolManager toolManager;
private StyleManager styleManager;
private ReviewManager reviewManager;
private WizardActivityProducer wizardActivityProducer;
@Transactional
public Object fillBackingObject(Object incomingModel, Map request, Map session, Map application) throws Exception {
MatrixGridBean grid = (MatrixGridBean)incomingModel;
String strScaffoldingId = (String)request.get("scaffolding_id");
if (strScaffoldingId == null) {
Placement placement = getToolManager().getCurrentPlacement();
strScaffoldingId = placement.getPlacementConfig().getProperty(
MatrixManager.EXPOSED_MATRIX_KEY);
}
Id scaffoldingId = getIdManager().getId(strScaffoldingId);
Scaffolding scaffolding = getMatrixManager().getScaffolding(scaffoldingId);
// Check for invalid scaffolding (could happen if scaffolding is deleted)
if (scaffolding == null )
{
logger.warn("Unable to find scaffolding: " + scaffoldingId );
return incomingModel;
}
Agent currentAgent = getAuthManager().getAgent();
boolean createAuthz = false;
String filterButton = (String)request.get(GROUP_FILTER_BUTTON);
String groupFilterRequest = (String)request.get(GROUP_FILTER);
String groupFilterSession = (String)session.get(GROUP_FILTER);
if (groupFilterRequest != null && filterButton != null) {
//TODO: Check that this user can filter on this group
}
else if (groupFilterSession != null) {
groupFilterRequest = groupFilterSession;
//TODO: Check if there is a better way to shuttle this to referenceData without modding the bean
request.put(GROUP_FILTER, groupFilterRequest);
}
session.put(GROUP_FILTER, groupFilterRequest);
//TODO: Check to make sure that the session user is in the filtered group
//If the user is, apply filter and select the user
//If not, apply and select the active user
//For right now, we're resetting when filtering
String userRequest = (String)request.get(VIEW_USER);
String userSession = (String)session.get(VIEW_USER);
if (groupFilterRequest != null && filterButton != null) {
userRequest = null;
}
else {
if (userRequest != null) {
currentAgent = getAgentManager().getAgent(getIdManager().getId(userRequest));
createAuthz = true;
} else if(userSession != null) {
userRequest = userSession;
currentAgent = getAgentManager().getAgent(getIdManager().getId(userSession));
// The authorize was already created by this point
}
}
session.put(VIEW_USER, userRequest);
Matrix matrix = getMatrixManager().getMatrix(scaffoldingId, currentAgent.getId());
if (matrix == null) {
if (currentAgent != null && !currentAgent.getId().getValue().equals("")) {
//Don't create a matrix unless the scaffolding has been published
// and the user has permission to use a matrix.
if (scaffolding.isPublished() || scaffolding.isPreview()) {
matrix = getMatrixManager().createMatrix(currentAgent, scaffolding);
}
}
}
if (matrix == null) {
grid.setScaffolding(scaffolding);
return incomingModel;
}
scaffolding = matrix.getScaffolding();
if (createAuthz) {
getAuthzManager().createAuthorization(getAuthManager().getAgent(),
FunctionConstants.READ_MATRIX, matrix.getId());
}
List<Level> levels = scaffolding.getLevels();
List<Criterion> criteria = scaffolding.getCriteria();
List matrixContents = new ArrayList();
Criterion criterion = new Criterion();
Level level = new Level();
List row = new ArrayList();
List<Cell> cells = getMatrixManager().getCells(matrix);
List<Review> reviews = getReviewManager().getReviewsByMatrix(matrix.getId().getValue());
for (Iterator<Criterion> criteriaIterator = criteria.iterator(); criteriaIterator.hasNext();) {
row = new ArrayList();
criterion = (Criterion) criteriaIterator.next();
for (Iterator<Level> levelsIterator = levels.iterator(); levelsIterator.hasNext();) {
level = (Level) levelsIterator.next();
CellFormBean cellBean = new CellFormBean();
Cell cell = getCell(cells, criterion, level);
if (cell == null) {
cell = new Cell();
cell.getWizardPage().setOwner(matrix.getOwner());
cell.setMatrix(matrix);
ScaffoldingCell scaffoldingCell = getMatrixManager().getScaffoldingCell(criterion, level);
cell.setScaffoldingCell(scaffoldingCell);
cell.setStatus(scaffoldingCell.getInitialStatus());
getMatrixManager().storeCell(cell);
}
List nodeList = new ArrayList(getMatrixManager().getPageContents(cell.getWizardPage()));
nodeList.addAll(getMatrixManager().getPageForms(cell.getWizardPage()));
cellBean.setCell(cell);
cellBean.setNodes(nodeList);
cellBean.setAssignments(getAssignments(cell.getWizardPage(), matrix.getOwner()));
String pageId = cell.getWizardPage().getId().getValue();
String siteId = cell.getWizardPage().getPageDefinition().getSiteId();
List reflections = new ArrayList();
List feedback = new ArrayList();
List evaluations = new ArrayList();
for (Review r : reviews) {
if (pageId.equals(r.getParent())) {
if (Review.REFLECTION_TYPE == r.getType()) {
reflections.add(r);
} else if (Review.FEEDBACK_TYPE == r.getType()) {
feedback.add(r);
} else if (Review.EVALUATION_TYPE == r.getType()) {
evaluations.add(r);
}
}
}
cellBean.setReflections(reflections);
cellBean.setReviews(feedback);
cellBean.setEvaluations(evaluations);
if (getMatrixManager().getTaggingManager().isTaggable()) {
TaggableItem item = wizardActivityProducer.getItem(cell.getWizardPage());
Set<TaggableItem> taggableItems = getMatrixManager().getTaggableItems(item, cell.getWizardPage().getPageDefinition().getReference(), cell.getWizardPage().getOwner().getId().getValue());
cellBean.setTaggableItems(taggableItems);
}
row.add(cellBean);
}
matrixContents.add(row);
}
grid.setMatrixId(matrix.getId());
grid.setMatrixOwner(matrix.getOwner());
grid.setScaffolding(scaffolding);
grid.setColumnLabels(levels);
grid.setRowLabels(criteria);
grid.setMatrixContents(matrixContents);
return incomingModel;
}
/* (non-Javadoc)
* @see org.theospi.utils.mvc.intf.FormController#referenceData(java.util.Map, java.lang.Object, org.springframework.validation.Errors)
*/
@Transactional
public Map referenceData(Map request, Object command, Errors errors) {
Map<String, Object> model = new HashMap<String, Object>();
MatrixGridBean grid = (MatrixGridBean) command;
Agent owner = grid.getMatrixOwner();
Boolean readOnly = Boolean.valueOf(false);
String worksiteId = grid.getScaffolding().getWorksiteId().getValue();
String filteredGroup = (String) request.get(GROUP_FILTER);
boolean allowAllGroups = getAuthzManager().isAuthorized(getAuthManager().getAgent(), MatrixFunctionConstants.VIEW_ALL_GROUPS, getIdManager().getId(grid.getScaffolding().getReference()));
List<Group> groupList = new ArrayList<Group>(getMatrixManager().getGroupList(worksiteId, allowAllGroups));
//Collections.sort(groupList);
//TODO: Figure out why ClassCastExceptions fire if we do this the obvious way... The User list sorts fine
Collections.sort(groupList, new Comparator<Group>() {
public int compare(Group arg0, Group arg1) {
return arg0.getTitle().toLowerCase().compareTo(arg1.getTitle().toLowerCase());
}});
List userList = new ArrayList(getMatrixManager().getUserList(worksiteId, filteredGroup, allowAllGroups, groupList));
Collections.sort(userList, new Comparator<User>(){
public int compare(User arg0, User arg1) {
return arg0.getSortName().compareToIgnoreCase(arg1.getSortName());
}
});
model.put("members", userList);
model.put("userGroups", groupList);
//TODO: Address why the fn:length() function can't be loaded or another handy way to pull collection size via EL
model.put("userGroupsCount", groupList.size());
model.put("hasGroups", getMatrixManager().hasGroups(worksiteId));
model.put("filteredGroup", request.get(GROUP_FILTER));
//TODO: Clean this up for efficiency.. We're going back to the SiteService too much
if ((owner != null && !owner.equals(getAuthManager().getAgent())) ||
!getAuthzManager().isAuthorized(MatrixFunctionConstants.CAN_USE_SCAFFOLDING, getIdManager().getId(grid.getScaffolding().getReference())))
readOnly = Boolean.valueOf(true);
model.put("worksite", worksiteId );
model.put("tool", getToolManager().getCurrentPlacement());
model.put("isMaintainer", isMaintainer());
model.put("matrixOwner", owner);
model.put("readOnlyMatrix", readOnly);
if (grid.getScaffolding() != null &&
getCurrentSitePageId().equals(grid.getScaffolding().getExposedPageId()))
{
model.put("isExposedPage", Boolean.valueOf(true));
}
model.put("styles",
getStyleManager().createStyleUrlList(getStyleManager().getStyles(grid.getScaffolding().getId())));
model.put("showFooter", getShowFooter(grid));
List<String> cellsICanAccess = getCellsICanAccess(getMatrixManager().getMatrix(grid.getMatrixId()));
model.put("cellsICanAccess", cellsICanAccess);
HashMap<String, Boolean> accessibleCells = new HashMap<String, Boolean>();
for (String s : cellsICanAccess) {
accessibleCells.put(s, true);
}
model.put("accessibleCells", accessibleCells);
return model;
}
/**
** Return true if matrix footer should be displayed. The footer will be displayed if the number of rows
** exceeds MATRIX_ROW_FOOTER0, which is configurable in sakai.properties as osp.matrixRowFooter.
** If osp.matrixRowFooter is -1, the footer will never be displayed.
**/
protected Boolean getShowFooter(MatrixGridBean grid) {
int matrixRowFooter = ServerConfigurationService.getInt("osp.matrixRowFooter", MATRIX_ROW_FOOTER );
if ( matrixRowFooter < 0 )
return Boolean.valueOf(false);
else if ( grid.getMatrixContents().size() > MATRIX_ROW_FOOTER )
return Boolean.valueOf(true);
else
return Boolean.valueOf(false);
}
/**
** Return true if matrix owner has submitted assignments associated with this cell
**/
protected List getAssignments(WizardPage wizPage, Agent owner) {
ArrayList submissions = new ArrayList();
try {
User user = UserDirectoryService.getUser(owner.getId().getValue());
ArrayList assignments =
AssignmentHelper.getSelectedAssignments(wizPage.getPageDefinition().getAttachments());
for ( Iterator it=assignments.iterator(); it.hasNext(); ) {
Assignment assign = (Assignment)it.next();
AssignmentSubmission assignSubmission = AssignmentService.getSubmission( assign.getId(),
user );
// assignments may be (incorrectly) marked as submitted, so check for valid submit time
if ( assignSubmission != null
&& assignSubmission.getSubmitted()
&& assignSubmission.getTimeSubmitted()!=null )
submissions.add(assignSubmission);
}
}
catch ( Exception e ) {
logger.warn(".getAssignments: " + e.toString());
}
return submissions;
}
/**
* Extract the site page id from the current request.
*
* @return The site page id implied from the current request.
*/
protected String getCurrentSitePageId()
{
ToolSession ts = SessionManager.getCurrentToolSession();
if (ts != null)
{
ToolConfiguration tool = SiteService.findTool(ts.getPlacementId());
if (tool != null)
{
return tool.getPageId();
}
}
return null;
} // getCurrentSitePageId
private Cell getCell(Collection<Cell> cells, Criterion criterion, Level level) {
for (Iterator<Cell> iter=cells.iterator(); iter.hasNext();) {
Cell cell = (Cell) iter.next();
if (cell.getScaffoldingCell().getRootCriterion().getId().getValue().equals(criterion.getId().getValue()) &&
cell.getScaffoldingCell().getLevel().getId().getValue().equals(level.getId().getValue())) {
return cell;
}
}
return null;
}
public ModelAndView handleRequest(Object requestModel, Map request, Map session, Map application, Errors errors) {
Map model = new HashMap();
//model.put("view_user", request.get("view_user"));
return new ModelAndView("success", model);
}
private List<String> getCellsICanAccess(Matrix matrix){
List<String> accessIds = new ArrayList<String>();
boolean canViewAllCells = getMatrixManager().canAccessAllMatrixCells(matrix.getScaffolding().getId());
for (Iterator iterator = matrix.getCells().iterator(); iterator
.hasNext();) {
Cell cell = (Cell) iterator.next();
if(!canViewAllCells){
if(getMatrixManager().canAccessMatrixCell(cell)){
accessIds.add(cell.getId().getValue());
}
}else{
accessIds.add(cell.getId().getValue());
}
}
return accessIds;
}
public ToolManager getToolManager() {
return toolManager;
}
public void setToolManager(ToolManager toolManager) {
this.toolManager = toolManager;
}
public StyleManager getStyleManager() {
return styleManager;
}
public void setStyleManager(StyleManager styleManager) {
this.styleManager = styleManager;
}
public SecurityService getSecurityService() {
return securityService;
}
public void setSecurityService(SecurityService securityService) {
this.securityService = securityService;
}
public WizardActivityProducer getWizardActivityProducer() {
return wizardActivityProducer;
}
public void setWizardActivityProducer(
WizardActivityProducer wizardActivityProducer) {
this.wizardActivityProducer = wizardActivityProducer;
}
public ReviewManager getReviewManager() {
return reviewManager;
}
public void setReviewManager(ReviewManager reviewManager) {
this.reviewManager = reviewManager;
}
}