/***************************************************************************
* Copyright (C) 2003-2009 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 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 org.exoplatform.wcm.connector.collaboration;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.commons.lang.StringUtils;
import org.exoplatform.ecm.utils.comparator.PropertyValueComparator;
import org.exoplatform.services.cms.drives.DriveData;
import org.exoplatform.services.cms.drives.ManageDriveService;
import org.exoplatform.services.cms.folksonomy.NewFolksonomyService;
import org.exoplatform.services.cms.templates.TemplateService;
import org.exoplatform.services.jcr.RepositoryService;
import org.exoplatform.services.jcr.core.ManageableRepository;
import org.exoplatform.services.jcr.ext.common.SessionProvider;
import org.exoplatform.services.jcr.impl.core.query.QueryImpl;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.rest.resource.ResourceContainer;
import org.exoplatform.services.wcm.utils.WCMCoreUtils;
/**
* Returns the latest edited documents.
*
* @LevelAPI Provisional
*
* @anchor GetEditedDocumentRESTService
*/
@Path("/presentation/document/edit/")
public class GetEditedDocumentRESTService implements ResourceContainer {
/** The Constant LAST_MODIFIED_PROPERTY. */
private static final String LAST_MODIFIED_PROPERTY = "Last-Modified";
/** The Constant IF_MODIFIED_SINCE_DATE_FORMAT. */
private static final String IF_MODIFIED_SINCE_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss z";
private RepositoryService repositoryService;
private TemplateService templateService;
private NewFolksonomyService newFolksonomyService;
private ManageDriveService manageDriveService;
private static final String DATE_MODIFIED = "exo:dateModified";
private static final String JCR_PRIMARYTYPE = "jcr:primaryType";
private static final String NT_BASE = "nt:base";
private static final String EXO_OWNER = "exo:owner";
private static final int NO_PER_PAGE = 5;
private static final String QUERY_STATEMENT = "SELECT * FROM $0 WHERE $1 ORDER BY $2 DESC";
private static final String GADGET = "gadgets";
private boolean show_gadget = false;
private static final Log LOG = ExoLogger.getLogger(GetEditedDocumentRESTService.class.getName());
public GetEditedDocumentRESTService(RepositoryService repositoryService,
TemplateService templateService, NewFolksonomyService newFolksonomyService, ManageDriveService manageDriveService) {
this.repositoryService = repositoryService;
this.templateService = templateService;
this.newFolksonomyService = newFolksonomyService;
this.manageDriveService = manageDriveService;
}
/**
* Returns the latest edited documents.
*
* @param repository The repository name.
* @param showItems Returns the number of items in each page.
* @param showGadgetWs Shows the gadget workspace or not.
* @return Response inputstream.
* @throws Exception
*
* @anchor GetEditedDocumentRESTService.getLastEditedDoc
*/
@Path("/{repository}/")
@GET
public Response getLastEditedDoc(@PathParam("repository") String repository,
@QueryParam("showItems") String showItems, @QueryParam("showGadgetWs") String showGadgetWs) throws Exception {
List<Node> lstLastEditedNode = getLastEditedNode(showItems, showGadgetWs);
List<DocumentNode> lstDocNode = getDocumentData(lstLastEditedNode);
ListEditDocumentNode listEditDocumentNode = new ListEditDocumentNode();
listEditDocumentNode.setLstDocNode(lstDocNode);
DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
return Response.ok(listEditDocumentNode, new MediaType("application", "json"))
.header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date()))
.build();
}
private List<Node> getLastEditedNode(String noOfItem, String showGadgetWs) throws Exception{
if (showGadgetWs != null && showGadgetWs.length() > 0) {
show_gadget = Boolean.parseBoolean(showGadgetWs);
}
ArrayList<Node> lstNode = new ArrayList<Node>();
StringBuffer bf = new StringBuffer(1024);
List<String> lstNodeType = templateService.getDocumentTemplates();
if (lstNodeType != null) {
for (String nodeType : lstNodeType) {
bf.append("(").append(JCR_PRIMARYTYPE).append("=").append("'").append(nodeType).append("'")
.append(")").append(" OR ");
}
}
if (bf.length() == 1) return null;
bf.delete(bf.lastIndexOf("OR") - 1, bf.length());
if (noOfItem == null || noOfItem.trim().length() == 0) noOfItem = String.valueOf(NO_PER_PAGE);
String queryStatement = StringUtils.replace(QUERY_STATEMENT, "$0", NT_BASE);
queryStatement = StringUtils.replace(queryStatement, "$1", bf.toString());
queryStatement = StringUtils.replace(queryStatement, "$2", DATE_MODIFIED);
ManageableRepository manageableRepository = repositoryService.getCurrentRepository();
try {
String[] workspaces = manageableRepository.getWorkspaceNames();
List<String> lstWorkspace = new ArrayList<String>();
//Arrays.asList() return fixed size list;
lstWorkspace.addAll(Arrays.asList(workspaces));
if (!show_gadget && lstWorkspace.contains(GADGET)) {
lstWorkspace.remove(GADGET);
}
SessionProvider provider = WCMCoreUtils.createAnonimProvider();
QueryImpl query = null;
Session session = null;
QueryResult queryResult = null;
QueryManager queryManager = null;
for (String workspace : lstWorkspace) {
session = provider.getSession(workspace, manageableRepository);
queryManager = session.getWorkspace().getQueryManager();
query = (QueryImpl) queryManager.createQuery(queryStatement, Query.SQL);
query.setLimit(Integer.parseInt(noOfItem));
query.setOffset(0);
queryResult = query.execute();
puttoList(lstNode, queryResult.getNodes());
session.logout();
}
} catch (RepositoryException e) {
if (LOG.isErrorEnabled()) {
LOG.error("Exception when execute SQL " + queryStatement, e);
}
}
return lstNode;
}
private void puttoList(List<Node> lstNode, NodeIterator nodeIter) {
if (nodeIter != null) {
while (nodeIter.hasNext()) {
lstNode.add(nodeIter.nextNode());
}
}
}
private List<DocumentNode> getDocumentData(List<Node> lstNode) throws Exception {
return getDocumentData(lstNode, String.valueOf(NO_PER_PAGE));
}
private String getDateFormat(Calendar date) {
return String.valueOf(date.getTimeInMillis());
}
private List<DocumentNode> getDocumentData(List<Node> lstNode, String noOfItem) throws Exception {
if (lstNode == null || lstNode.size() == 0) return null;
List<DocumentNode> lstDocNode = new ArrayList<DocumentNode>();
DocumentNode docNode = null;
StringBuilder tags = null;
Collections.sort(lstNode, new PropertyValueComparator(DATE_MODIFIED, PropertyValueComparator.DESCENDING_ORDER));
ManageableRepository manageableRepository = repositoryService.getCurrentRepository();
List<DriveData> lstDrive = manageDriveService.getAllDrives();
for (Node node : lstNode) {
docNode = new DocumentNode();
docNode.setName(node.getName());
docNode.setPath(node.getPath());
docNode.setLastAuthor(node.getProperty(EXO_OWNER).getString());
docNode.setLstAuthor(node.getProperty(EXO_OWNER).getString());
docNode.setDateEdited(getDateFormat(node.getProperty(DATE_MODIFIED).getDate()));
tags = new StringBuilder(1024);
List<Node> tagList = newFolksonomyService.getLinkedTagsOfDocumentByScope(NewFolksonomyService.PUBLIC,
"",
node,
manageableRepository.getConfiguration()
.getDefaultWorkspaceName());
for(Node tag : tagList) {
tags.append(tag.getName()).append(", ");
}
if (tags.lastIndexOf(",") > 0) {
tags.delete(tags.lastIndexOf(","), tags.length());
}
docNode.setTags(tags.toString());
docNode.setDriveName(getDriveName(lstDrive, node));
if (lstDocNode.size() < Integer.parseInt(noOfItem)) lstDocNode.add(docNode);
}
return lstDocNode;
}
private String getDriveName(List<DriveData> lstDrive, Node node) throws RepositoryException{
String driveName = "";
for (DriveData drive : lstDrive) {
if (node.getSession().getWorkspace().getName().equals(drive.getWorkspace())
&& node.getPath().contains(drive.getHomePath()) && drive.getHomePath().equals("/")) {
driveName = drive.getName();
break;
}
}
return driveName;
}
public class DocumentNode {
private String nodeName_;
private String nodePath_;
private String driveName_;
private String dateEdited_;
private String tags;
private String lastAuthor;
private String lstAuthor;
public String getTags() {
return tags;
}
public void setTags(String tags) {
this.tags = tags;
}
public String getLastAuthor() {
return lastAuthor;
}
public void setLastAuthor(String lastAuthor) {
this.lastAuthor = lastAuthor;
}
public String getLstAuthor() {
return lstAuthor;
}
public void setLstAuthor(String lstAuthor) {
this.lstAuthor = lstAuthor;
}
public void setName(String nodeName) {
nodeName_ = nodeName;
}
public String getName() {
return nodeName_;
}
public void setPath(String nodePath) {
nodePath_ = nodePath;
}
public String getPath() {
return nodePath_;
}
public void setDriveName(String driveName) {
driveName_ = driveName;
}
public String getDriveName() {
return driveName_;
}
public String getDateEdited() {
return dateEdited_;
}
public void setDateEdited(String dateEdited_) {
this.dateEdited_ = dateEdited_;
}
}
public class ListEditDocumentNode {
private List<DocumentNode> lstDocNode;
public List<DocumentNode> getLstDocNode() {
return lstDocNode;
}
public void setLstDocNode(List<DocumentNode> lstDocNode) {
this.lstDocNode = lstDocNode;
}
}
}