/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see .
*/
package org.alfresco.web.bean;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.repo.web.scripts.FileTypeImageUtils;
import org.alfresco.service.cmr.repository.CopyService;
import org.alfresco.service.cmr.repository.FileTypeImageSize;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.TemplateImageResolver;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.OwnableService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.context.UIContextService;
import org.alfresco.web.bean.actions.handlers.SimpleWorkflowHandler;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.bean.workflow.WorkflowUtil;
import org.alfresco.web.ui.common.ReportedException;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.Utils.URLMode;
import org.alfresco.web.ui.common.component.UIActionLink;
import org.alfresco.web.ui.common.component.UIPanel.ExpandedEvent;
/**
* Backing bean provided access to the details of a Node
*
* @author Kevin Roast
*/
public abstract class BaseDetailsBean extends BaseDialogBean
{
private static final String MSG_SUCCESS_OWNERSHIP = "success_ownership";
/** OwnableService bean reference */
transient private OwnableService ownableService;
/** CopyService bean reference */
transient private CopyService copyService;
/** The PermissionService reference */
transient private PermissionService permissionService;
/** Selected template Id */
protected String template;
/** The map of workflow properties */
protected Map workflowProperties;
protected Map panels = new HashMap(4, 1.0f);
private static final String MSG_ERROR_WORKFLOW_REJECT = "error_workflow_reject";
private static final String MSG_ERROR_WORKFLOW_APPROVE = "error_workflow_approve";
private static final String MSG_ERROR_UPDATE_SIMPLEWORKFLOW = "error_update_simpleworkflow";
public BaseDetailsBean()
{
// initial state of some panels that don't use the default
panels.put("workflow-panel", false);
panels.put("category-panel", false);
}
// ------------------------------------------------------------------------------
// Bean property getters and setters
/**
* Sets the ownable service instance the bean should use
*
* @param ownableService The OwnableService
*/
public void setOwnableService(OwnableService ownableService)
{
this.ownableService = ownableService;
}
protected OwnableService getOwnableService()
{
if (ownableService == null)
{
ownableService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getOwnableService();
}
return ownableService;
}
/**
* Sets the copy service instance the bean should use
*
* @param copyService The CopyService
*/
public void setCopyService(CopyService copyService)
{
this.copyService = copyService;
}
protected CopyService getCopyService()
{
if (copyService == null)
{
copyService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getCopyService();
}
return copyService;
}
/**
* @param permissionService The PermissionService to set.
*/
public void setPermissionService(PermissionService permissionService)
{
this.permissionService = permissionService;
}
protected PermissionService getPermissionService()
{
if (permissionService == null)
{
permissionService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getPermissionService();
}
return permissionService;
}
/**
* @return Returns the panels expanded state map.
*/
public Map getPanels()
{
return this.panels;
}
/**
* @param panels The panels expanded state map.
*/
public void setPanels(Map panels)
{
this.panels = panels;
}
/**
* Returns the Node this bean is currently representing
*
* @return The Node
*/
public abstract Node getNode();
/**
* Returns the id of the current node
*
* @return The id
*/
public String getId()
{
return getNode().getId();
}
/**
* Returns the name of the current node
*
* @return Name of the current
*/
public String getName()
{
return getNode().getName();
}
/**
* Return the Alfresco NodeRef URL for the current node
*
* @return the Alfresco NodeRef URL
*/
public String getNodeRefUrl()
{
return getNode().getNodeRef().toString();
}
/**
* Returns the WebDAV URL for the current node
*
* @return The WebDAV url
*/
public String getWebdavUrl()
{
Node node = getLinkResolvedNode();
return Utils.generateURL(FacesContext.getCurrentInstance(), node, URLMode.WEBDAV);
}
/**
* Returns the CIFS path for the current node
*
* @return The CIFS path
*/
public String getCifsPath()
{
Node node = getLinkResolvedNode();
return Utils.generateURL(FacesContext.getCurrentInstance(), node, URLMode.CIFS);
}
/**
* Returns the URL to access the details page for the current node
*
* @return The bookmark URL
*/
public String getBookmarkUrl()
{
return Utils.generateURL(FacesContext.getCurrentInstance(), getNode(), URLMode.SHOW_DETAILS);
}
/**
* Resolve the actual Node from any Link object that may be proxying it
*
* @return current Node or Node resolved from any Link object
*/
protected abstract Node getLinkResolvedNode();
/**
* @return Returns the template Id.
*/
public String getTemplate()
{
// return current template if it exists
NodeRef ref = (NodeRef)getNode().getProperties().get(ContentModel.PROP_TEMPLATE);
return ref != null ? ref.getId() : this.template;
}
/**
* @param template The template Id to set.
*/
public void setTemplate(String template)
{
this.template = template;
}
/**
* @return true if the current node has a custom Template or Webscript view applied and
* references a template/webscript that currently exists in the system.
*/
public boolean getHasCustomView()
{
return getHasWebscriptView() || getHasTemplateView();
}
/**
* @return true if the current node has a Template based custom view available
*/
public boolean getHasTemplateView()
{
if (getNode().hasAspect(ContentModel.ASPECT_TEMPLATABLE))
{
NodeRef templateRef = (NodeRef)getNode().getProperties().get(ContentModel.PROP_TEMPLATE);
return (templateRef != null && this.getNodeService().exists(templateRef) &&
this.getPermissionService().hasPermission(templateRef, PermissionService.READ) == AccessStatus.ALLOWED);
}
return false;
}
/**
* @return true if the current node has a Webscript based custom view available
*/
public boolean getHasWebscriptView()
{
if (getNode().hasAspect(ContentModel.ASPECT_WEBSCRIPTABLE))
{
return (getNode().getProperties().get(ContentModel.PROP_WEBSCRIPT) != null);
}
return false;
}
/**
* @return String of the NodeRef for the custom view for the node
*/
public String getTemplateRef()
{
NodeRef ref = (NodeRef)getNode().getProperties().get(ContentModel.PROP_TEMPLATE);
return ref != null ? ref.toString() : null;
}
/**
* @return Webscript URL for the custom view for the node
*/
public String getWebscriptUrl()
{
return (String)getNode().getProperties().get(ContentModel.PROP_WEBSCRIPT);
}
/**
* Returns a model for use by a template on the Details page.
*
* @return model containing current current node info.
*/
public abstract Map getTemplateModel();
/** Template Image resolver helper */
protected TemplateImageResolver imageResolver = new TemplateImageResolver()
{
private static final long serialVersionUID = 1539708282743314697L;
public String resolveImagePathForName(String filename, FileTypeImageSize size)
{
return FileTypeImageUtils.getFileTypeImage(FacesContext.getCurrentInstance(), filename, size);
}
};
/**
* Returns the properties for the attached workflow as a map
*
* @return Properties of the attached workflow, null if there is no workflow
*/
public Map getWorkflowProperties()
{
if (this.workflowProperties == null &&
getNode().hasAspect(ApplicationModel.ASPECT_SIMPLE_WORKFLOW))
{
// get the exisiting properties for the node
Map props = getNode().getProperties();
String approveStepName = (String)props.get(
ApplicationModel.PROP_APPROVE_STEP.toString());
String rejectStepName = (String)props.get(
ApplicationModel.PROP_REJECT_STEP.toString());
Boolean approveMove = (Boolean)props.get(
ApplicationModel.PROP_APPROVE_MOVE.toString());
Boolean rejectMove = (Boolean)props.get(
ApplicationModel.PROP_REJECT_MOVE.toString());
NodeRef approveFolder = (NodeRef)props.get(
ApplicationModel.PROP_APPROVE_FOLDER.toString());
NodeRef rejectFolder = (NodeRef)props.get(
ApplicationModel.PROP_REJECT_FOLDER.toString());
// put the workflow properties in a separate map for use by the JSP
this.workflowProperties = new HashMap(7);
this.workflowProperties.put(SimpleWorkflowHandler.PROP_APPROVE_STEP_NAME,
approveStepName);
this.workflowProperties.put(SimpleWorkflowHandler.PROP_APPROVE_ACTION,
approveMove ? "move" : "copy");
this.workflowProperties.put(SimpleWorkflowHandler.PROP_APPROVE_FOLDER, approveFolder);
if (rejectStepName == null || rejectMove == null || rejectFolder == null)
{
this.workflowProperties.put(SimpleWorkflowHandler.PROP_REJECT_STEP_PRESENT, "no");
}
else
{
this.workflowProperties.put(SimpleWorkflowHandler.PROP_REJECT_STEP_PRESENT,
"yes");
this.workflowProperties.put(SimpleWorkflowHandler.PROP_REJECT_STEP_NAME,
rejectStepName);
this.workflowProperties.put(SimpleWorkflowHandler.PROP_REJECT_ACTION,
rejectMove ? "move" : "copy");
this.workflowProperties.put(SimpleWorkflowHandler.PROP_REJECT_FOLDER,
rejectFolder);
}
}
return this.workflowProperties;
}
/**
* Cancel Workflow Edit dialog
*/
public String cancelWorkflowEdit()
{
// resets the workflow properties map so any changes made
// don't appear to be persisted
this.workflowProperties.clear();
this.workflowProperties = null;
return "cancel";
}
/**
* Saves the details of the workflow stored in workflowProperties
* to the current node
*
* @return The outcome string
*/
public String saveWorkflow()
{
String outcome = "cancel";
try
{
RetryingTransactionHelper txnHelper = Repository.getRetryingTransactionHelper(FacesContext.getCurrentInstance());
RetryingTransactionCallback