/*
* Copyright (C) 2003-2012 eXo Platform SAS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.exoplatform.ecm.webui.component.explorer;
import org.apache.commons.lang.StringUtils;
import org.exoplatform.commons.utils.*;
import org.exoplatform.ecm.jcr.model.Preference;
import org.exoplatform.ecm.webui.component.explorer.control.action.ManageVersionsActionComponent;
import org.exoplatform.ecm.webui.component.explorer.versions.UIActivateVersion;
import org.exoplatform.ecm.webui.component.explorer.versions.UIVersionInfo;
import org.exoplatform.ecm.webui.utils.JCRExceptionManager;
import org.exoplatform.ecm.webui.utils.Utils;
import org.exoplatform.portal.webui.util.Util;
import org.exoplatform.portal.webui.workspace.UIPortalApplication;
import org.exoplatform.services.cms.link.*;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.security.ConversationState;
import org.exoplatform.services.security.IdentityConstants;
import org.exoplatform.services.wcm.core.NodeLocation;
import org.exoplatform.services.wcm.core.NodetypeConstant;
import org.exoplatform.services.wcm.utils.WCMCoreUtils;
import org.exoplatform.web.application.ApplicationMessage;
import org.exoplatform.web.application.RequestContext;
import org.exoplatform.webui.config.annotation.ComponentConfig;
import org.exoplatform.webui.config.annotation.EventConfig;
import org.exoplatform.webui.core.*;
import org.exoplatform.webui.event.Event;
import org.exoplatform.webui.event.EventListener;
import javax.jcr.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* Created by The eXo Platform SAS
* Author : eXoPlatform
* exo@exoplatform.com
* Nov 29, 2012
*/
@ComponentConfig (
template = "app:/groovy/webui/component/explorer/UIDocumentNodeList.gtmpl",
events = {
@EventConfig(listeners = UIDocumentNodeList.ExpandNodeActionListener.class),
@EventConfig(listeners = UIDocumentNodeList.CollapseNodeActionListener.class),
@EventConfig(listeners = UIDocumentNodeList.ManageVersionsActionListener.class),
@EventConfig(listeners = UIDocumentNodeList.MoreActionListener.class)
}
)
public class UIDocumentNodeList extends UIContainer {
private static final Log LOG = ExoLogger.getLogger(UIDocumentNodeList.class.getName());
private UIPageIterator pageIterator_;
private LinkManager linkManager_;
private List dataList_;
private int padding_;
private boolean showMoreButton_ = true;
public UIDocumentNodeList() throws Exception {
linkManager_ = WCMCoreUtils.getService(LinkManager.class);
addChild(ManageVersionsActionComponent.class, null, null);
pageIterator_ = addChild(UIPageIterator.class, null, "UIDocumentNodeListPageIterator");
padding_ = 0;
}
@SuppressWarnings("unchecked")
public List<Node> getNodeChildrenList() throws Exception {
return NodeLocation.getNodeListByLocationList(showMoreButton_ ? dataList_ : pageIterator_.getCurrentPageData());
}
public void setPageList(PageList p) throws Exception {
pageIterator_.setPageList(p);
dataList_ = new ArrayList();
if (p != null && p.getAvailable() > 0) {
dataList_.addAll(p.getPage(1));
}
updateUIDocumentNodeListChildren();
}
public int getPadding() { return padding_; }
public void setPadding(int value) { padding_ = value; }
public boolean isShowMoreButton() {
return showMoreButton_ && (pageIterator_ != null) &&
(pageIterator_.getPageList() != null) &&
(dataList_ != null) && (dataList_.size() < pageIterator_.getPageList().getAvailable());
}
public void setShowMoreButton(boolean value) { showMoreButton_ = value; }
public void setCurrentNode(Node node) throws Exception {
setPageList(this.getPageList(node.getPath()));
}
public void updateUIDocumentNodeListChildren() throws Exception {
Set<String> ids = new HashSet<String>();
//get all ids of UIDocumentNodeList children
for (UIComponent component : getChildren()) {
if (component instanceof UIDocumentNodeList) {
ids.add(component.getId());
}
}
//remove all UIDocumentNodeList children
for (String id : ids) {
this.removeChildById(id);
}
//add new UIDocumentNodeList children
for (Node node : getNodeChildrenList()) {
if (node instanceof NodeLinkAware) {
node = ((NodeLinkAware)node).getRealNode();
}
try {
Node targetNode = linkManager_.isLink(node) ? linkManager_.getTarget(node) : node;
if (targetNode.isNodeType(NodetypeConstant.NT_FOLDER) || targetNode.isNodeType(NodetypeConstant.NT_UNSTRUCTURED)) {
addUIDocList(getID(node));
}
} catch(ItemNotFoundException ine) {
continue;
}
}
}
public UIPageIterator getContentPageIterator() {
return pageIterator_;
}
public String getID(Node node) throws Exception {
return this.getAncestorOfType(UIDocumentInfo.class).getClass().getSimpleName() +
this.getClass().getSimpleName() + String.valueOf(Math.abs(node.getPath().hashCode()));
}
public UIComponent addUIDocList(String id) throws Exception {
UIDocumentNodeList child = addChild(UIDocumentNodeList.class, null, id);
child.setPadding(padding_ + 1);
child.getContentPageIterator().setId(child.getId() + "PageIterator");
return child;
}
/**
* gets the name of file
* @param file the file
* @param title the title
* @return name of file
* @throws Exception
*/
public String getFileName(Node file, String title) throws Exception {
if (!file.isNodeType(NodetypeConstant.NT_FILE) || title == null) {
return title;
} else {
int index = title.lastIndexOf('.');
if (index != -1) {
return title.substring(0, index);
} else {
return title;
}
}
}
/**
* gets the extension of file
* @param file the file
* @param title the title
* @return extension of file
* @throws Exception
*/
public String getFileExtension(Node file, String title) throws Exception {
if (!file.isNodeType(NodetypeConstant.NT_FILE) || title == null) {
return "";
} else {
int index = title.lastIndexOf('.');
if (index != -1) {
return title.substring(index);
} else {
return "";
}
}
}
/**
* gets date presentation of file
* @param file the file
* @return file date presentation
* @throws Exception
*/
public String getFileDate(Node file) throws Exception {
String createdDate = this.getDatePropertyValue(file, NodetypeConstant.EXO_DATE_CREATED);
String modifiedDate = this.getDatePropertyValue(file, NodetypeConstant.EXO_LAST_MODIFIED_DATE);
return StringUtils.isEmpty(modifiedDate) ||
equalDates(file, NodetypeConstant.EXO_DATE_CREATED, NodetypeConstant.EXO_LAST_MODIFIED_DATE)?
getLabel("CreatedOn") + " " + createdDate : getLabel("Updated") + " " + modifiedDate;
}
private boolean equalDates(Node node, String p1, String p2) {
Calendar pr1 = null;
Calendar pr2 = null;
try {
pr1 = node.getProperty(p1).getDate();
} catch (PathNotFoundException e) {
pr1 = null;
} catch (ValueFormatException e) {
pr1 = null;
} catch (RepositoryException e) {
pr1 = null;
}
try {
pr2 = node.getProperty(p2).getDate();
} catch (PathNotFoundException e) {
pr2 = null;
} catch (ValueFormatException e) {
pr2 = null;
} catch (RepositoryException e) {
pr2 = null;
}
if ((pr1 == null) && (pr2 == null)) return true;
if ((pr1 == null) || (pr2 == null)) return false;
return Math.abs(pr1.getTimeInMillis() - pr2.getTimeInMillis()) < 3000;
}
public String getDatePropertyValue(Node node, String propertyName) throws Exception {
try {
Property property = node.getProperty(propertyName);
if(property != null) {
Locale locale = Util.getUIPortal().getAncestorOfType(UIPortalApplication.class).getLocale();
DateFormat dateFormat = SimpleDateFormat.getDateInstance(SimpleDateFormat.SHORT, locale);
return dateFormat.format(property.getDate().getTime());
}
} catch(PathNotFoundException PNE) {
return "";
}
return "";
}
/**
* gets label
* @param id the id
* @return label
*/
public String getLabel(String id) {
RequestContext context = RequestContext.getCurrentInstance();
ResourceBundle res = context.getApplicationResourceBundle();
try {
return res.getString("UIDocumentNodeList.label." + id);
} catch (MissingResourceException ex) {
return id;
}
}
/**
* gets number of version of the node
* @param file the node
* @return version number
*/
public String getVersionNumber(Node file) throws Exception {
if (file.isNodeType(NodetypeConstant.MIX_VERSIONABLE)) {
int size = (int)file.getVersionHistory().getAllVersions().getSize()-1;
return "V" + size;
} else {
return "";
}
}
public String getAuthorName(Node file) throws Exception {
String userName = getAncestorOfType(UIDocumentInfo.class).getPropertyValue(file, NodetypeConstant.EXO_LAST_MODIFIER);
if (StringUtils.isEmpty(userName) || IdentityConstants.SYSTEM.equals(userName)) {
return StringUtils.EMPTY;
}
return String.format("%s %s",
getLabel("by"),
userName.equals(ConversationState.getCurrent().getIdentity().getUserId()) ? getLabel("you") : userName);
}
public String getFileSize(Node file) throws Exception {
return org.exoplatform.services.cms.impl.Utils.fileSize(file);
}
@SuppressWarnings("unchecked")
private PageList<Object> getPageList(String path) throws Exception {
UIJCRExplorer uiExplorer = this.getAncestorOfType(UIJCRExplorer.class);
Preference pref = uiExplorer.getPreference();
DocumentProviderUtils docProviderUtil = DocumentProviderUtils.getInstance();
if (docProviderUtil.canSortType(pref.getSortType()) && uiExplorer.getAllItemByTypeFilterMap().isEmpty()) {
return docProviderUtil.getPageList(
uiExplorer.getWorkspaceName(),
path,
pref,
uiExplorer.getAllItemFilterMap(),
uiExplorer.getAllItemByTypeFilterMap(),
(NodeLinkAware) ItemLinkAware.newInstance(uiExplorer.getWorkspaceName(), path,
uiExplorer.getNodeByPath(path, uiExplorer.getSession())));
}
List<Node> nodeList = null;
UIDocumentInfo uiDocInfo = this.getAncestorOfType(UIDocumentInfo.class);
int nodesPerPage = pref.getNodesPerPage();
Set<String> allItemByTypeFilterMap = uiExplorer.getAllItemByTypeFilterMap();
if (allItemByTypeFilterMap.size() > 0)
nodeList = uiDocInfo.filterNodeList(uiExplorer.getChildrenList(path, !pref.isShowPreferenceDocuments()));
else
nodeList = uiDocInfo.filterNodeList(uiExplorer.getChildrenList(path, pref.isShowPreferenceDocuments()));
ListAccess<Object> nodeAccList =
new ListAccessImpl<Object>(Object.class, NodeLocation.getLocationsByNodeList(nodeList));
return new LazyPageList<Object>(nodeAccList, nodesPerPage);
}
static public class ExpandNodeActionListener extends EventListener<UIDocumentNodeList> {
public void execute(Event<UIDocumentNodeList> event) throws Exception {
UIDocumentNodeList uicomp = event.getSource();
NodeFinder nodeFinder = uicomp.getApplicationComponent(NodeFinder.class);
String uri = event.getRequestContext().getRequestParameter(OBJECTID);
String workspaceName = event.getRequestContext().getRequestParameter("workspaceName");
UIApplication uiApp = uicomp.getAncestorOfType(UIApplication.class);
try {
// Manage ../ and ./
uri = LinkUtils.evaluatePath(uri);
// Just in order to check if the node exists
Item item = nodeFinder.getItem(workspaceName, uri);
if ((item instanceof Node) && Utils.isInTrash((Node) item)) {
return;
}
// uiExplorer.setSelectNode(workspaceName, uri);
Node clickedNode = (Node)item;
// UIDocumentNodeList uiDocNodeListChild = uicomp.addChild(UIDocumentNodeList.class, null,
// String.valueOf(clickedNode.getPath().hashCode()));
UIDocumentNodeList uiDocNodeListChild = uicomp.getChildById(uicomp.getID(clickedNode));
uiDocNodeListChild.setCurrentNode(clickedNode);
uicomp.getAncestorOfType(UIDocumentInfo.class).getExpandedFolders().add(uri);
event.getRequestContext().addUIComponentToUpdateByAjax(uiDocNodeListChild);
} catch(ItemNotFoundException nu) {
uiApp.addMessage(new ApplicationMessage("UIDocumentInfo.msg.null-exception", null, ApplicationMessage.WARNING)) ;
return ;
} catch(PathNotFoundException pa) {
uiApp.addMessage(new ApplicationMessage("UIDocumentInfo.msg.path-not-found", null, ApplicationMessage.WARNING)) ;
return ;
} catch(AccessDeniedException ace) {
uiApp.addMessage(new ApplicationMessage("UIDocumentInfo.msg.access-denied", null, ApplicationMessage.WARNING)) ;
return ;
} catch(RepositoryException e) {
if (LOG.isErrorEnabled()) {
LOG.error("Repository cannot be found");
}
uiApp.addMessage(new ApplicationMessage("UIDocumentInfo.msg.repository-error", null,
ApplicationMessage.WARNING)) ;
return ;
} catch (Exception e) {
JCRExceptionManager.process(uiApp, e);
return;
}
}
}
static public class CollapseNodeActionListener extends EventListener<UIDocumentNodeList> {
public void execute(Event<UIDocumentNodeList> event) throws Exception {
UIDocumentNodeList uicomp = event.getSource();
NodeFinder nodeFinder = uicomp.getApplicationComponent(NodeFinder.class);
String uri = event.getRequestContext().getRequestParameter(OBJECTID);
String workspaceName = event.getRequestContext().getRequestParameter("workspaceName");
UIApplication uiApp = uicomp.getAncestorOfType(UIApplication.class);
try {
// Manage ../ and ./
uri = LinkUtils.evaluatePath(uri);
// Just in order to check if the node exists
Item item = nodeFinder.getItem(workspaceName, uri);
if ((item instanceof Node) && Utils.isInTrash((Node) item)) {
return;
}
Node clickedNode = (Node)item;
UIDocumentNodeList uiDocNodeListChild = uicomp.getChildById(uicomp.getID(clickedNode));
uiDocNodeListChild.setPageList(EmptySerializablePageList.get());
uicomp.getAncestorOfType(UIDocumentInfo.class).getExpandedFolders().remove(uri);
event.getRequestContext().addUIComponentToUpdateByAjax(uiDocNodeListChild);
} catch(ItemNotFoundException nu) {
uiApp.addMessage(new ApplicationMessage("UIDocumentInfo.msg.null-exception", null, ApplicationMessage.WARNING)) ;
return ;
} catch(PathNotFoundException pa) {
uiApp.addMessage(new ApplicationMessage("UIDocumentInfo.msg.path-not-found", null, ApplicationMessage.WARNING)) ;
return ;
} catch(AccessDeniedException ace) {
uiApp.addMessage(new ApplicationMessage("UIDocumentInfo.msg.access-denied", null, ApplicationMessage.WARNING)) ;
return ;
} catch(RepositoryException e) {
if (LOG.isErrorEnabled()) {
LOG.error("Repository cannot be found");
}
uiApp.addMessage(new ApplicationMessage("UIDocumentInfo.msg.repository-error", null,
ApplicationMessage.WARNING)) ;
return ;
} catch (Exception e) {
JCRExceptionManager.process(uiApp, e);
return;
}
}
}
public static class ManageVersionsActionListener extends EventListener<UIDocumentNodeList> {
public void execute(Event<UIDocumentNodeList> event) throws Exception {
NodeFinder nodeFinder = event.getSource().getApplicationComponent(NodeFinder.class);
UIJCRExplorer uiExplorer = event.getSource().getAncestorOfType(UIJCRExplorer.class);
UIPopupContainer UIPopupContainer = uiExplorer.getChild(UIPopupContainer.class);
String uri = event.getRequestContext().getRequestParameter(OBJECTID);
String workspaceName = event.getRequestContext().getRequestParameter("workspaceName");
// Manage ../ and ./
uri = LinkUtils.evaluatePath(uri);
// Just in order to check if the node exists
Node currentNode = (Node)nodeFinder.getItem(workspaceName, uri);
uiExplorer.setIsHidePopup(false);
if (currentNode.canAddMixin(Utils.MIX_VERSIONABLE)) {
UIPopupContainer.activate(UIActivateVersion.class, 400);
event.getRequestContext().addUIComponentToUpdateByAjax(UIPopupContainer);
} else if (currentNode.isNodeType(Utils.MIX_VERSIONABLE)) {
UIWorkingArea uiWorkingArea = uiExplorer.getChild(UIWorkingArea.class);
UIDocumentWorkspace uiDocumentWorkspace = uiWorkingArea.getChild(UIDocumentWorkspace.class);
UIVersionInfo uiVersionInfo = uiDocumentWorkspace.getChild(UIVersionInfo.class);
uiVersionInfo.setCurrentNode(currentNode);
uiVersionInfo.setRootOwner(currentNode.getProperty("exo:lastModifier").getString());
uiVersionInfo.activate();
uiDocumentWorkspace.setRenderedChild(UIVersionInfo.class);
event.getRequestContext().addUIComponentToUpdateByAjax(uiDocumentWorkspace);
}
}
}
public static class MoreActionListener extends EventListener<UIDocumentNodeList> {
public void execute(Event<UIDocumentNodeList> event) throws Exception {
UIDocumentNodeList uicomp = event.getSource();
UIApplication uiApp = uicomp.getAncestorOfType(UIApplication.class);
try {
int currentPage = uicomp.dataList_.size() / uicomp.pageIterator_.getPageList().getPageSize();
uicomp.dataList_.addAll(uicomp.pageIterator_.getPageList().getPage(currentPage + 1));
event.getRequestContext().addUIComponentToUpdateByAjax(uicomp);
} catch(AccessDeniedException ace) {
uiApp.addMessage(new ApplicationMessage("UIDocumentInfo.msg.access-denied", null, ApplicationMessage.WARNING)) ;
return ;
} catch(RepositoryException e) {
if (LOG.isErrorEnabled()) {
LOG.error("Repository cannot be found");
}
uiApp.addMessage(new ApplicationMessage("UIDocumentInfo.msg.repository-error", null,
ApplicationMessage.WARNING)) ;
return ;
} catch (Exception e) {
JCRExceptionManager.process(uiApp, e);
return;
}
}
}
}