/*
* 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.admin.unlock;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Session;
import javax.jcr.query.Query;
import org.exoplatform.commons.exception.ExoMessageException;
import org.exoplatform.commons.utils.PageList;
import org.exoplatform.services.jcr.RepositoryService;
import org.exoplatform.services.jcr.core.ManageableRepository;
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.wcm.core.NodeLocation;
import org.exoplatform.services.wcm.utils.WCMCoreUtils;
/**
* Created by The eXo Platform SAS
* Author : eXoPlatform
* exo@exoplatform.com
* May 23, 2012
*/
public class UILockedNodePageList extends PageList<NodeLocation> {
private static final Log LOG = ExoLogger.getLogger(UILockedNodePageList.class);
private static final int QUERY_SIZE = 200;
private String query;
private Map<String, Integer> workspaceNodeMap;
private String[] workspaceNameList;
private List<NodeLocation> buffer;
public UILockedNodePageList(int pageSize) {
super(pageSize);
}
public UILockedNodePageList(String query, int pageSize, int currentPage) {
super(pageSize);
this.query = query;
workspaceNameList = getWorkSpaceNameList();
workspaceNodeMap = new HashMap<String, Integer>();
buffer = this.getData(0, Math.max(QUERY_SIZE, (currentPage + 10) * pageSize));
this.setAvailablePage(buffer.size());
}
/**
* gets list of workspace name in repository
* @return
*/
private String[] getWorkSpaceNameList() {
RepositoryService repoService = WCMCoreUtils.getService(RepositoryService.class);
String[] ret = new String[]{};
try {
ret = repoService.getCurrentRepository().getWorkspaceNames();
} catch (Exception e) {
if (LOG.isErrorEnabled()) {
LOG.error(e);
}
}
return ret;
}
@Override
protected void populateCurrentPage(int page) throws Exception {
currentListPage_ = buffer.subList(getFrom(), getTo());
}
@Override
protected void checkAndSetPage(int page) throws Exception
{
if (page + 10 > availablePage_) {
buffer.addAll(getData(buffer.size(), (page + 10) * getPageSize() - availablePage_ + QUERY_SIZE));
setAvailablePage(buffer.size());
}
if (page < 1 || page > availablePage_) {
Object[] args = {Integer.toString(page), Integer.toString(availablePage_)};
throw new ExoMessageException("PageList.page-out-of-range", args);
}
currentPage_ = page;
}
private List<NodeLocation> getData(int from, int count) {
// int count = this.getTo() - this.getFrom();//number of node need to query
// int delta = this.getFrom();
int delta = from;
List<NodeLocation> ret = new ArrayList<NodeLocation>();//data will be filled to this list
//iterate through all workspaces
for (String workspace : workspaceNameList) {
Integer lockedNodeCount = workspaceNodeMap.get(workspace);
if (lockedNodeCount != null) {
if (lockedNodeCount <= delta) {//(1.1)
delta -= lockedNodeCount;
} else if (delta < lockedNodeCount && lockedNodeCount <= delta + count) { //(1.2)
ret.addAll(queryNodes(workspace, delta, lockedNodeCount - delta));
delta = 0;
count -= (lockedNodeCount - delta);
} else if (delta + count < lockedNodeCount) {
ret = queryNodes(workspace, delta, count);
break;//delta = 0; count = 0;
}
} else { //lockedNodeCount==null
List<NodeLocation> queryNodeData = queryNodes(workspace, delta, count);
if (queryNodeData.size() == 0) {//(2.1), as (1.1) : lockedNodeCount <= delta
lockedNodeCount = queryNodes(workspace, 0, count).size();
delta -= lockedNodeCount;
workspaceNodeMap.put(workspace, lockedNodeCount);
} else if (0 < queryNodeData.size() && queryNodeData.size() < count) {
//(2.2), as (1.2) : delta < lockedNodeCount && lockedNodeCount <= delta + count
ret.addAll(queryNodeData);
delta = 0;
count -= queryNodeData.size();
} else if (queryNodeData.size() == count) {//(2.3), as (1.3) : delta + count < lockedNodeCount
ret = queryNodeData;
break;//delta = 0; count = 0;
}
}
if (count == 0) {
break;
}
}
return ret;
}
/**
* gets all nodes by this.query, in given workspace, from offset to (offset + limit)
* @throws Exception
*/
private List<NodeLocation> queryNodes(String workspace, int offset, int limit) {
List<NodeLocation> ret = new ArrayList<NodeLocation>();
try {
ManageableRepository repo = WCMCoreUtils.getService(RepositoryService.class).getCurrentRepository();
Session session = WCMCoreUtils.getSystemSessionProvider().getSession(workspace,
repo);
Query query = session.getWorkspace().getQueryManager().createQuery(this.query, Query.SQL);
((QueryImpl)query).setOffset(offset);
((QueryImpl)query).setLimit(limit);
for (NodeIterator iter = query.execute().getNodes(); iter.hasNext();) {
Node node = iter.nextNode();
if (node.isLocked()) {
ret.add(NodeLocation.getNodeLocationByNode(node));
}
}
} catch (Exception e) {
if (LOG.isErrorEnabled()) {
LOG.error(e);
}
}
return ret;
}
@Override
public List getAll() throws Exception {
return buffer;
}
}