diff --git a/source/java/org/alfresco/repo/webservice/AbstractQuery.java b/source/java/org/alfresco/repo/webservice/AbstractQuery.java
new file mode 100644
index 0000000000..0dd23b54c0
--- /dev/null
+++ b/source/java/org/alfresco/repo/webservice/AbstractQuery.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2005-2007 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.webservice;
+
+import java.util.Set;
+
+import org.alfresco.repo.webservice.types.ResultSetRowNode;
+import org.alfresco.service.ServiceRegistry;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.namespace.QName;
+
+/**
+ * Abstract implementation of a QuerySession providing support for automatic id generation
+ * and provides support for paging through query results.
+ *
+ * Before executing, all the services need to be set.
+ *
+ * @author gavinc
+ */
+public abstract class AbstractQuery implements ServerQuery
+{
+ public AbstractQuery()
+ {
+ }
+
+ /**
+ * Override this method only if the query can limit the results without a post-query cut-off.
+ *
+ * {@inheritDoc}
+ */
+ public RESULTSET execute(ServiceRegistry serviceRegistry, long maxResults)
+ {
+ return execute(serviceRegistry);
+ }
+
+ /**
+ * Create a result set row node object for the provided node reference
+ *
+ * @param nodeRef
+ * the node reference
+ * @param nodeService
+ * the node service
+ * @return
+ * the result set row node
+ */
+ protected ResultSetRowNode createResultSetRowNode(NodeRef nodeRef, NodeService nodeService)
+ {
+ // Get the type
+ String type = nodeService.getType(nodeRef).toString();
+
+ // Get the aspects applied to the node
+ Set aspects = nodeService.getAspects(nodeRef);
+ String[] aspectNames = new String[aspects.size()];
+ int index = 0;
+ for (QName aspect : aspects)
+ {
+ aspectNames[index] = aspect.toString();
+ index++;
+ }
+
+ // Create and return the result set row node
+ return new ResultSetRowNode(nodeRef.getId(), type, aspectNames);
+ }
+}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/webservice/AbstractQuerySession.java b/source/java/org/alfresco/repo/webservice/AbstractQuerySession.java
new file mode 100644
index 0000000000..8972f7576c
--- /dev/null
+++ b/source/java/org/alfresco/repo/webservice/AbstractQuerySession.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2005-2007 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.webservice;
+
+import org.alfresco.service.ServiceRegistry;
+import org.alfresco.util.GUID;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * An abstract implementation of the query session that keeps track of the paging data.
+ * It provides support for paging of results of Serializable[]
instances.
+ *
+ * @author Derek Hulley
+ * @since 2.1
+ */
+public abstract class AbstractQuerySession implements QuerySession
+{
+ private static Log logger = LogFactory.getLog(AbstractQuerySession.class);
+
+ private String id;
+ private long maxResults;
+ private long batchSize;
+ private ServerQuery query;
+ /** a transient cache of the query results */
+ private transient RESULTSET cachedResults;
+
+ /**
+ * A pointer to the first row to be returned. When the last result is returned, the
+ * position will be out of range of the current results by 1.
+ */
+ private long position;
+ /**
+ * Keep track of whether the position has previously passed the end of a set of results.
+ */
+ private boolean expectMoreResults;
+
+ /**
+ * Common constructor that initialises the session's id and batch size
+ *
+ * @param maxResults
+ * the maximum number of results to retrieve for the query. This is not the page
+ * size, which is normally significantly smaller.
+ * @param batchSize
+ * the batch size this session will use
+ * @param query
+ * the query that generates the results
+ */
+ public AbstractQuerySession(long maxResults, long batchSize, ServerQuery query)
+ {
+ this.id = GUID.generate();
+ this.batchSize = batchSize;
+ this.maxResults = maxResults;
+ this.query = query;
+ this.position = 0;
+ this.expectMoreResults = true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getId()
+ {
+ return this.id;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ServerQuery getQuery()
+ {
+ return query;
+ }
+
+ /**
+ * Helper method to get the results. This may be a cached value or may be
+ * freshly retrieved from the query object.
+ *
+ * @param serviceRegistry the
+ * @return the query results, new or cached
+ */
+ protected RESULTSET getQueryResults(ServiceRegistry serviceRegistry)
+ {
+ if (cachedResults != null)
+ {
+ return cachedResults;
+ }
+ // Get the results and cache them
+ cachedResults = query.execute(serviceRegistry, maxResults);
+ // Done
+ return cachedResults;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean haveMoreResults()
+ {
+ return expectMoreResults;
+ }
+
+ protected abstract RESULTSETROW[] makeArray(int size);
+
+ /**
+ * Helper method to page through the results. The task of retrieving, unwrapping and
+ * rewrapping the array of results (rows) is left up to the derived implementations.
+ */
+ protected final RESULTSETROW[] getNextResults(RESULTSETROW[] allResults)
+ {
+ /*
+ * This class can't manipulate the query to get the results because each
+ * query implementation's results (the array of rows) is contained within
+ * a different type of object. This method helps
+ */
+
+ long allResultsSize = allResults.length;
+
+ RESULTSETROW[] batchedResults = null;
+ if (position >= allResultsSize)
+ {
+ // We are already past the last result
+ batchedResults = makeArray(0);
+ // Position is after last
+ position = allResultsSize;
+ }
+ else if (position == 0 && batchSize >= allResultsSize)
+ {
+ // We can give back the original results
+ batchedResults = allResults;
+ // Position is after last
+ position = allResultsSize;
+ }
+ else if ((position + batchSize) >= allResultsSize)
+ {
+ // There isn't an excess of rows remaining, so copy to the last one
+ long lastResultIndex = allResultsSize - 1L;
+ long rowCopyCount = lastResultIndex - position;
+ batchedResults = makeArray((int)rowCopyCount);
+ System.arraycopy(allResults, (int)position, batchedResults, 0, (int)rowCopyCount);
+ // Position is after last
+ position = allResultsSize;
+ }
+ else
+ {
+ // There are an excess of rows remaining
+ batchedResults = makeArray((int)batchSize);
+ System.arraycopy(allResults, (int)position, batchedResults, 0, (int)batchSize);
+ // Position increases by the batch size
+ position += batchSize;
+ }
+ // Keep track of whether we expect more results
+ if (position >= allResultsSize)
+ {
+ expectMoreResults = false;
+ }
+ // Done
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("\n" +
+ "Fetched next set of results: \n" +
+ " Total results count: " + allResultsSize + "\n" +
+ " Batch size: " + batchedResults.length + "\n" +
+ " New Position: " + position);
+ }
+ return batchedResults;
+// long allResultsSize = allResults.getTotalRowCount();
+//
+// ResultSet batchedResults = null;
+// if (position >= allResultsSize)
+// {
+// // We are already past the last result
+// batchedResults = new ResultSet();
+// batchedResults.setRows(new ResultSetRow[] {});
+// batchedResults.setTotalRowCount(0);
+// batchedResults.setMetaData(allResults.getMetaData());
+// // Position is after last
+// position = allResultsSize;
+// }
+// else if (position == 0 && batchSize >= allResultsSize)
+// {
+// // We can give back the original results
+// batchedResults = allResults;
+// // Position is after last
+// position = allResultsSize;
+// }
+// else if ((position + batchSize) >= allResultsSize)
+// {
+// // There isn't an excess of rows remaining, so copy to the last one
+// long lastResultIndex = allResultsSize - 1L;
+// long rowCopyCount = lastResultIndex - position;
+// ResultSetRow[] batchedRows = new ResultSetRow[(int)rowCopyCount];
+// ResultSetRow[] allRows = allResults.getRows();
+// System.arraycopy(allRows, (int)position, batchedRows, 0, (int)rowCopyCount);
+// // Build the results
+// batchedResults = new ResultSet();
+// batchedResults.setRows(batchedRows);
+// batchedResults.setTotalRowCount(rowCopyCount);
+// batchedResults.setMetaData(allResults.getMetaData());
+// // Position is after last
+// position = allResultsSize;
+// }
+// else
+// {
+// // There are an excess of rows remaining
+// ResultSetRow[] batchedRows = new ResultSetRow[(int)batchSize];
+// ResultSetRow[] allRows = allResults.getRows();
+// System.arraycopy(allRows, (int)position, batchedRows, 0, (int)batchSize);
+// // Build the results
+// batchedResults = new ResultSet();
+// batchedResults.setRows(batchedRows);
+// batchedResults.setTotalRowCount(batchSize);
+// batchedResults.setMetaData(allResults.getMetaData());
+// // Position increases by the batch size
+// position += batchSize;
+// }
+// // Keep track of whether we expect more results
+// if (position >= allResultsSize)
+// {
+// expectMoreResults = false;
+// }
+// // Done
+// if (logger.isDebugEnabled())
+// {
+// logger.debug("\n" +
+// "Fetched net set of results: \n" +
+// " Total results count: " + allResultsSize + "\n" +
+// " Batch size: " + batchedResults.getTotalRowCount() + "\n" +
+// " New Position: " + position);
+// }
+// return batchedResults;
+ }
+}
diff --git a/source/java/org/alfresco/repo/webservice/AbstractWebService.java b/source/java/org/alfresco/repo/webservice/AbstractWebService.java
index fe37be62c9..4cd169e21e 100644
--- a/source/java/org/alfresco/repo/webservice/AbstractWebService.java
+++ b/source/java/org/alfresco/repo/webservice/AbstractWebService.java
@@ -1,77 +1,117 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
- * Licensed under the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version
- * 2.1 of the License, or (at your option) any later version.
- * You may obtain a copy of the License at
- *
- * http://www.gnu.org/licenses/lgpl.txt
- *
- * 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.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.webservice;
+import org.alfresco.repo.cache.SimpleCache;
+import org.alfresco.service.ServiceRegistry;
+import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
/**
- * Abstract base class for all web service implementations, provides support for common
- * service injection
+ * Abstract base class for all web service implementations, provides support for common service injection
*
* @author gavinc
*/
public abstract class AbstractWebService
{
- protected NodeService nodeService;
- protected ContentService contentService;
- protected SearchService searchService;
- protected NamespaceService namespaceService;
-
- /**
- * Sets the instance of the NodeService to be used
- *
- * @param nodeService The NodeService
- */
- public void setNodeService(NodeService nodeService)
- {
- this.nodeService = nodeService;
- }
-
- /**
- * Sets the ContentService instance to use
- *
- * @param contentSvc The ContentService
- */
- public void setContentService(ContentService contentSvc)
- {
- this.contentService = contentSvc;
- }
-
- /**
- * Sets the instance of the SearchService to be used
- *
- * @param searchService The SearchService
- */
- public void setSearchService(SearchService searchService)
- {
- this.searchService = searchService;
- }
-
- /**
- * Sets the instance of the NamespaceService to be used
- *
- * @param namespaceService The NamespaceService
- */
- public void setNamespaceService(NamespaceService namespaceService)
- {
- this.namespaceService = namespaceService;
- }
+ protected ServiceRegistry serviceRegistry;
+ protected DictionaryService dictionaryService;
+ protected NodeService nodeService;
+ protected ContentService contentService;
+ protected SearchService searchService;
+ protected NamespaceService namespaceService;
+
+ protected SimpleCache querySessionCache;
+
+ public void setServiceRegistry(ServiceRegistry serviceRegistry)
+ {
+ this.serviceRegistry = serviceRegistry;
+ }
+
+ /**
+ * Sets the instance of the DictionaryService to be used
+ *
+ * @param dictionaryService
+ * The DictionaryService
+ */
+ public void setDictionaryService(DictionaryService dictionaryService)
+ {
+ this.dictionaryService = dictionaryService;
+ }
+
+ /**
+ * Sets the instance of the NodeService to be used
+ *
+ * @param nodeService The NodeService
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ /**
+ * Sets the ContentService instance to use
+ *
+ * @param contentSvc The ContentService
+ */
+ public void setContentService(ContentService contentSvc)
+ {
+ this.contentService = contentSvc;
+ }
+
+ /**
+ * Sets the instance of the SearchService to be used
+ *
+ * @param searchService The SearchService
+ */
+ public void setSearchService(SearchService searchService)
+ {
+ this.searchService = searchService;
+ }
+
+ /**
+ * Sets the instance of the NamespaceService to be used
+ *
+ * @param namespaceService The NamespaceService
+ */
+ public void setNamespaceService(NamespaceService namespaceService)
+ {
+ this.namespaceService = namespaceService;
+ }
+
+ /**
+ * Sets the cache to use for storing the the query session's paging information by query session ID.
+ *
+ * @param querySessionCache the cache. Cluster replication should be via serialization of
+ * the cache values.
+ */
+ public void setQuerySessionCache(SimpleCache querySessionCache)
+ {
+ this.querySessionCache = querySessionCache;
+ }
}
diff --git a/source/java/org/alfresco/repo/webservice/QuerySession.java b/source/java/org/alfresco/repo/webservice/QuerySession.java
new file mode 100644
index 0000000000..e913aea0e4
--- /dev/null
+++ b/source/java/org/alfresco/repo/webservice/QuerySession.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2005-2007 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.webservice;
+
+import java.io.Serializable;
+
+import org.alfresco.service.ServiceRegistry;
+
+/**
+ * An interface for objects that track the query and its results. The only commonality between
+ * the different types of results used in the WebServices return values is that they are
+ * Serializable.
+ *
+ * @author Derek Hulley
+ */
+public interface QuerySession extends Serializable
+{
+ /**
+ * Retrieves the id this query session can be identified as
+ *
+ * @return Id of this query session
+ */
+ public String getId();
+
+ /**
+ * Check if the session is expecting more results. This will be false if the
+ * cursor previously passed the end of a given set of results.
+ */
+ public boolean haveMoreResults();
+
+ /**
+ * Get the next batch of results from the full set of available results. If there are no results
+ * available, then this session must go and fetch them. It is up to the implementation to provide
+ * a means for this to occur.
+ *
+ * @param serviceRegistry
+ * the services to perform a query
+ * @param allResults
+ * All available results. It may be necessary to requery to get the results.
+ * @return
+ * Returns the next batch of results based on the maximum fetch size. If there are no
+ * more results, the resultset will be empty.
+ */
+ public RESULTSET getNextResults(ServiceRegistry serviceRegistry);
+}
diff --git a/source/java/org/alfresco/repo/webservice/repository/QuerySession.java b/source/java/org/alfresco/repo/webservice/ServerQuery.java
similarity index 50%
rename from source/java/org/alfresco/repo/webservice/repository/QuerySession.java
rename to source/java/org/alfresco/repo/webservice/ServerQuery.java
index dbb467a15c..00022e7624 100644
--- a/source/java/org/alfresco/repo/webservice/repository/QuerySession.java
+++ b/source/java/org/alfresco/repo/webservice/ServerQuery.java
@@ -22,53 +22,48 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
-package org.alfresco.repo.webservice.repository;
+package org.alfresco.repo.webservice;
import java.io.Serializable;
-import org.alfresco.service.cmr.dictionary.DictionaryService;
-import org.alfresco.service.cmr.repository.NodeService;
-import org.alfresco.service.cmr.search.SearchService;
-import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.service.ServiceRegistry;
/**
* Interface definition for a QuerySession.
*
* @author gavinc
*/
-public interface QuerySession extends Serializable
+public interface ServerQuery extends Serializable
{
/** System column namess */
public static String SYS_COL_ASSOC_TYPE = "associationType";
public static String SYS_COL_ASSOC_NAME = "associationName";
public static String SYS_COL_IS_PRIMARY = "isPrimary";
public static String SYS_COL_NTH_SIBLING = "nthSibling";
-
- /**
- * Retrieves the id this query session can be identified as
- *
- * @return Id of this query session
- */
- public String getId();
-
- /**
- * Returns a QueryResult object representing the next batch of results.
- * QueryResult will contain a maximum of items as determined by the
- * fetchSize
element of the QueryConfiguration SOAP header.
- *
- * When the last batch of results is being returned the querySession of
- * QueryResult will be null.
- *
- * @see org.alfresco.repo.webservice.repository.QuerySession#getId()
- * @param searchService The SearchService to use for gathering the results
- * @param nodeService The NodeService to use for gathering the results
- * @param namespaceService The NamespaceService to use
- * @return QueryResult containing the next batch of results or null if there
- * are no more results
- */
- public QueryResult getNextResultsBatch(
- SearchService searchService,
- NodeService nodeService,
- NamespaceService namespaceService,
- DictionaryService dictionaryService);
-}
+
+ /**
+ * Executes the query and returns the full query results.
+ *
+ * @param
+ * The services to help make the query
+ * @return
+ * The full set of query results.
+ * The results must be empty if there are no results.
+ */
+ public RESULTSET execute(ServiceRegistry serviceRegistry);
+
+ /**
+ * Executes the query and return all results up to given maximum number.
+ * Note that this is not the same as the page size, but rather is a total
+ * upper limit to the number of results that can viewed.
+ *
+ * @param
+ * The services to help make the query
+ * @param maxResults
+ * the total number of results to retrieve
+ * @return
+ * The full set of query results up to the maximum given.
+ * The results must be empty if there are no results.
+ */
+ public RESULTSET execute(ServiceRegistry serviceRegistry, long maxResults);
+}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/webservice/Utils.java b/source/java/org/alfresco/repo/webservice/Utils.java
index 01edb1eca8..b26b3abbfb 100644
--- a/source/java/org/alfresco/repo/webservice/Utils.java
+++ b/source/java/org/alfresco/repo/webservice/Utils.java
@@ -79,6 +79,8 @@ import org.springframework.web.context.support.WebApplicationContextUtils;
*/
public class Utils
{
+ /** Default batch size for query results - 1000 */
+ public static final int DEFAULT_BATCH_SIZE = 1000;
public static final String REPOSITORY_SERVICE_NAMESPACE = "http://www.alfresco.org/ws/service/repository/1.0";
/** Get the logger for this class */
@@ -384,8 +386,7 @@ public class Utils
}
NodeRef rootNodeRef = nodeService.getRootNode(convertToStoreRef(store));
- List nodes = searchService.selectNodes(rootNodeRef, path,
- null, namespaceService, false);
+ List nodes = searchService.selectNodes(rootNodeRef, path, null, namespaceService, false);
// make sure we only have one result
if (nodes.size() != 1)
@@ -589,7 +590,7 @@ public class Utils
*/
public static int getBatchSize(MessageContext msgContext)
{
- int batchSize = -1;
+ int batchSize = DEFAULT_BATCH_SIZE;
Integer batchConfigSize = (Integer) MessageContext.getCurrentContext()
.getProperty(QueryConfigHandler.ALF_FETCH_SIZE);
diff --git a/source/java/org/alfresco/repo/webservice/administration/AdministrationWebService.java b/source/java/org/alfresco/repo/webservice/administration/AdministrationWebService.java
index 354b4d5949..f9285ac823 100644
--- a/source/java/org/alfresco/repo/webservice/administration/AdministrationWebService.java
+++ b/source/java/org/alfresco/repo/webservice/administration/AdministrationWebService.java
@@ -36,19 +36,19 @@ import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
-import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.repo.webservice.AbstractWebService;
import org.alfresco.repo.webservice.Utils;
import org.alfresco.repo.webservice.action.ActionFault;
+import org.alfresco.repo.webservice.repository.RepositoryFault;
import org.alfresco.repo.webservice.types.NamedValue;
import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
-import org.alfresco.util.GUID;
import org.apache.axis.MessageContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -74,9 +74,6 @@ public class AdministrationWebService extends AbstractWebService implements
/** A set of ignored properties */
private static Set ignoredProperties = new HashSet(3);
- /** Simple cache used to store user query sessions */
- private SimpleCache querySessionCache;
-
/**
* Constructor
*/
@@ -118,18 +115,6 @@ public class AdministrationWebService extends AbstractWebService implements
this.authenticationService = authenticationService;
}
- /**
- * Sets the instance of the SimpleCache to be used
- *
- * @param querySessionCache
- * The SimpleCache
- */
- public void setQuerySessionCache(
- SimpleCache querySessionCache)
- {
- this.querySessionCache = querySessionCache;
- }
-
/**
* @see org.alfresco.repo.webservice.administration.AdministrationServiceSoapPort#queryUsers(org.alfresco.repo.webservice.administration.UserFilter)
*/
@@ -168,18 +153,33 @@ public class AdministrationWebService extends AbstractWebService implements
{
MessageContext msgContext = MessageContext.getCurrentContext();
+ // Create the query
+ UserQuery query = new UserQuery(filter);
+
// Create a user query session
- UserQuerySession userQuerySession = new UserQuerySession(Utils.getBatchSize(msgContext), filter);
- UserQueryResults userQueryResults = userQuerySession.getNextBatch();
+ UserQuerySession userQuerySession = new UserQuerySession(Long.MAX_VALUE, Utils.getBatchSize(msgContext), query);
+
+ // Get the next batch of results
+ UserQueryResults userQueryResults = userQuerySession.getNextResults(serviceRegistry);
+ String querySessionId = userQuerySession.getId();
// add the session to the cache if there are more results to come
- if (userQueryResults.getQuerySession() != null)
+ boolean haveMoreResults = userQuerySession.haveMoreResults();
+ if (haveMoreResults)
{
- // this.querySessionCache.putQuerySession(querySession);
- this.querySessionCache.put(userQueryResults.getQuerySession(), userQuerySession);
+ querySessionCache.put(querySessionId, userQuerySession);
}
- return userQueryResults;
+ // Construct the return value
+ // TODO: http://issues.alfresco.com/browse/AR-1689
+ // This looks odd, but I've chosen to be specific about when the ID is set on the return
+ // results and when it isn't.
+ UserQueryResults result = new UserQueryResults(
+ haveMoreResults ? querySessionId : null,
+ userQueryResults.getUserDetails());
+
+ // Done
+ return result;
}
/**
@@ -212,20 +212,34 @@ public class AdministrationWebService extends AbstractWebService implements
/**
*
- * @param querySession
+ * @param querySessionId
* @return
*/
- private UserQueryResults fetchMoreUsersImpl(String querySession)
+ private UserQueryResults fetchMoreUsersImpl(String querySessionId) throws RepositoryFault
{
- UserQueryResults queryResult = null;
- UserQuerySession session = this.querySessionCache.get(querySession);
+ UserQuerySession session = null;
+ try
+ {
+ session = (UserQuerySession) querySessionCache.get(querySessionId);
+ }
+ catch (ClassCastException e)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Query session was not generated by the AdministrationWebService: " + querySessionId);
+ }
+ throw new RepositoryFault(
+ 4,
+ "querySession with id '" + querySessionId + "' is invalid");
+ }
+ UserQueryResults queryResult = null;
if (session != null)
{
- queryResult = session.getNextBatch();
- if (queryResult.getQuerySession() == null)
+ queryResult = session.getNextResults(serviceRegistry);
+ if (!session.haveMoreResults())
{
- this.querySessionCache.remove(querySession);
+ this.querySessionCache.remove(querySessionId);
}
}
@@ -269,12 +283,13 @@ public class AdministrationWebService extends AbstractWebService implements
*/
private UserDetails getUserImpl(String userName)
{
+ NodeService nodeService = serviceRegistry.getNodeService();
UserDetails userDetails = null;
if (this.personService.personExists(userName) == true)
{
NodeRef nodeRef = this.personService.getPerson(userName);
- userDetails = createUserDetails(userName, nodeRef);
+ userDetails = createUserDetails(nodeService, userName, nodeRef);
}
else
{
@@ -291,7 +306,7 @@ public class AdministrationWebService extends AbstractWebService implements
* @param nodeRef the node reference
* @return the user details object populated with the appropriate property values
*/
- private UserDetails createUserDetails(String userName, NodeRef nodeRef)
+ /* package */ static UserDetails createUserDetails(NodeService nodeService, String userName, NodeRef nodeRef)
{
// Create the user details object
UserDetails userDetails = new UserDetails();
@@ -300,7 +315,7 @@ public class AdministrationWebService extends AbstractWebService implements
userDetails.setUserName(userName);
// Set the various property values
- Map properties = this.nodeService.getProperties(nodeRef);
+ Map properties = nodeService.getProperties(nodeRef);
List namedValues = new ArrayList(properties.size());
for (Map.Entry entry : properties.entrySet())
{
@@ -364,6 +379,7 @@ public class AdministrationWebService extends AbstractWebService implements
*/
private UserDetails[] createUsersImpl(NewUserDetails[] newUsers)
{
+ NodeService nodeService = serviceRegistry.getNodeService();
UserDetails[] userDetails = new UserDetails[newUsers.length];
int index = 0;
@@ -382,7 +398,7 @@ public class AdministrationWebService extends AbstractWebService implements
NodeRef personNodeRef = this.personService.createPerson(properties);
// Add the details to the result
- userDetails[index] = createUserDetails(newUser.getUserName(), personNodeRef);
+ userDetails[index] = createUserDetails(nodeService, newUser.getUserName(), personNodeRef);
index++;
}
@@ -424,6 +440,7 @@ public class AdministrationWebService extends AbstractWebService implements
*/
private UserDetails[] updateUsersImpl(UserDetails[] users)
{
+ NodeService nodeService = serviceRegistry.getNodeService();
UserDetails[] userDetails = new UserDetails[users.length];
int index = 0;
@@ -442,7 +459,7 @@ public class AdministrationWebService extends AbstractWebService implements
// Add the details to the result
NodeRef nodeRef = this.personService.getPerson(user.getUserName());
- userDetails[index] = createUserDetails(user.getUserName(), nodeRef);
+ userDetails[index] = createUserDetails(nodeService, user.getUserName(), nodeRef);
index++;
}
@@ -539,163 +556,4 @@ public class AdministrationWebService extends AbstractWebService implements
this.personService.deletePerson(userName);
}
}
-
- /**
- * User query session used to support batched user query
- *
- * @author Roy Wetherall
- */
- private class UserQuerySession implements Serializable
- {
- private static final long serialVersionUID = -2960711874297744356L;
-
- private int batchSize = -1;
- private UserFilter filter;
- protected int position = 0;
- private String id;
-
- /**
- * Constructor
- *
- * @param batchSize
- * @param filter
- */
- public UserQuerySession(int batchSize, UserFilter filter)
- {
- this.batchSize = batchSize;
- this.filter = filter;
- this.id = GUID.generate();
- }
-
- /**
- * @see org.alfresco.repo.webservice.repository.QuerySession#getId()
- */
- public String getId()
- {
- return this.id;
- }
-
- /**
- * Calculates the index of the last row to retrieve.
- *
- * @param totalRowCount The total number of rows in the results
- * @return The index of the last row to return
- */
- protected int calculateLastRowIndex(int totalRowCount)
- {
- int lastRowIndex = totalRowCount;
-
- // set the last row index if there are more results available
- // than the batch size
- if ((this.batchSize != -1) && ((this.position + this.batchSize) < totalRowCount))
- {
- lastRowIndex = this.position + this.batchSize;
- }
-
- return lastRowIndex;
- }
-
- /**
- * Calculates the value of the next position.
- * If the end of the result set is reached the position is set to -1
- *
- * @param totalRowCount The total number of rows in the results
- * @param queryResult The QueryResult object being returned to the client,
- * if there are no more results the id is removed from the QueryResult instance
- */
- protected void updatePosition(int totalRowCount, UserQueryResults queryResult)
- {
- if (this.batchSize == -1)
- {
- this.position = -1;
- queryResult.setQuerySession(null);
- }
- else
- {
- this.position += this.batchSize;
- if (this.position >= totalRowCount)
- {
- // signify that there are no more results
- this.position = -1;
- queryResult.setQuerySession(null);
- }
- }
- }
-
- /**
- * Gets the next batch of user details
- *
- * @return user query results
- */
- public UserQueryResults getNextBatch()
- {
- UserQueryResults queryResult = null;
-
- if (this.position != -1)
- {
- if (logger.isDebugEnabled())
- logger.debug("Before getNextBatch: " + toString());
-
- Set nodeRefs = AdministrationWebService.this.personService.getAllPeople();
-
- // Filter the results
- List filteredNodeRefs = null;
- if (filter != null && filter.getUserName() != null && filter.getUserName().length() != 0)
- {
- String userNameFilter = filter.getUserName();
-
- if (logger.isDebugEnabled() == true)
- {
- logger.debug("Applying user query filter (" + userNameFilter + ")");
- }
-
- filteredNodeRefs = new ArrayList(nodeRefs.size());
- for (NodeRef nodeRef : nodeRefs)
- {
- String userName = (String)AdministrationWebService.this.nodeService.getProperty(nodeRef, ContentModel.PROP_USERNAME);
- if (userName.matches(userNameFilter) == true)
- {
- filteredNodeRefs.add(nodeRef);
- }
- }
- }
- else
- {
- if (logger.isDebugEnabled() == true)
- {
- logger.debug("No user filter specified");
- }
-
- filteredNodeRefs = new ArrayList(nodeRefs);
- }
-
- int totalRows = filteredNodeRefs.size();
- int lastRow = calculateLastRowIndex(totalRows);
- int currentBatchSize = lastRow - this.position;
-
- if (logger.isDebugEnabled())
- logger.debug("Total rows = " + totalRows + ", current batch size = " + currentBatchSize);
-
- List userDetailsList = new ArrayList(currentBatchSize);
-
- for (int x = this.position; x < lastRow; x++)
- {
- NodeRef nodeRef = (NodeRef)filteredNodeRefs.get(x);
- String userName = (String)AdministrationWebService.this.nodeService.getProperty(nodeRef, ContentModel.PROP_USERNAME);
- UserDetails userDetails = AdministrationWebService.this.createUserDetails(userName, nodeRef);
- userDetailsList.add(userDetails);
- }
-
- queryResult = new UserQueryResults(getId(), (UserDetails[])userDetailsList.toArray(new UserDetails[userDetailsList.size()]));
-
- // move the position on
- updatePosition(totalRows, queryResult);
-
- if (logger.isDebugEnabled())
- logger.debug("After getNextBatch: " + toString());
- }
-
- return queryResult;
- }
- }
}
diff --git a/source/java/org/alfresco/repo/webservice/administration/UserQuery.java b/source/java/org/alfresco/repo/webservice/administration/UserQuery.java
new file mode 100644
index 0000000000..8793dd328b
--- /dev/null
+++ b/source/java/org/alfresco/repo/webservice/administration/UserQuery.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2005-2007 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.webservice.administration;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.webservice.AbstractQuery;
+import org.alfresco.service.ServiceRegistry;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.security.PersonService;
+
+/**
+ * A query to retrieve normal node associations.
+ *
+ * @author Derek Hulley
+ * @since 2.1
+ */
+public class UserQuery extends AbstractQuery
+{
+ private static final long serialVersionUID = -672399618512462040L;
+
+ private UserFilter userFilter;
+
+ /**
+ * @param userFilter
+ * The user filter
+ */
+ public UserQuery(UserFilter userFilter)
+ {
+ this.userFilter = userFilter;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("AssociationQuery")
+ .append("[ userFilter=").append(userFilter.getUserName())
+ .append("]");
+ return sb.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public UserQueryResults execute(ServiceRegistry serviceRegistry)
+ {
+ PersonService personService = serviceRegistry.getPersonService();
+ NodeService nodeService = serviceRegistry.getNodeService();
+
+ Set nodeRefs = personService.getAllPeople();
+
+ // Filter the results
+ List filteredNodeRefs = null;
+ if (userFilter != null && userFilter.getUserName() != null && userFilter.getUserName().length() != 0)
+ {
+ String userNameFilter = userFilter.getUserName();
+
+ filteredNodeRefs = new ArrayList(nodeRefs.size());
+ for (NodeRef nodeRef : nodeRefs)
+ {
+ String userName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_USERNAME);
+ if (userName.matches(userNameFilter) == true)
+ {
+ filteredNodeRefs.add(nodeRef);
+ }
+ }
+ }
+ else
+ {
+ filteredNodeRefs = new ArrayList(nodeRefs);
+ }
+
+ UserDetails[] results = new UserDetails[filteredNodeRefs.size()];
+ int index = 0;
+ for (NodeRef nodeRef : filteredNodeRefs)
+ {
+ String userName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_USERNAME);
+ results[index] = AdministrationWebService.createUserDetails(nodeService, userName, nodeRef);
+ index++;
+ }
+
+ UserQueryResults queryResults = new UserQueryResults(null, results);
+
+ // Done
+ return queryResults;
+ }
+}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/webservice/administration/UserQuerySession.java b/source/java/org/alfresco/repo/webservice/administration/UserQuerySession.java
new file mode 100644
index 0000000000..f681f1afb1
--- /dev/null
+++ b/source/java/org/alfresco/repo/webservice/administration/UserQuerySession.java
@@ -0,0 +1,41 @@
+package org.alfresco.repo.webservice.administration;
+
+import org.alfresco.repo.webservice.AbstractQuerySession;
+import org.alfresco.repo.webservice.ServerQuery;
+import org.alfresco.service.ServiceRegistry;
+
+/**
+ * A session for managing user-related queries.
+ *
+ * @author Derek Hulley
+ * @since 2.1
+ */
+public class UserQuerySession extends AbstractQuerySession
+{
+ private static final long serialVersionUID = 1823253197962982642L;
+
+ public UserQuerySession(long maxResults, long batchSize, ServerQuery query)
+ {
+ super(maxResults, batchSize, query);
+ }
+
+ @Override
+ protected UserDetails[] makeArray(int size)
+ {
+ return new UserDetails[size];
+ }
+
+ public UserQueryResults getNextResults(ServiceRegistry serviceRegistry)
+ {
+ UserQueryResults queryResults = getQueryResults(serviceRegistry);
+ UserDetails[] allRows = queryResults.getUserDetails();
+ UserDetails[] batchedRows = getNextResults(allRows);
+ // Build the user query results
+ UserQueryResults batchedResults = new UserQueryResults();
+// batchedResults.setQuerySession(getId()); TODO: http://issues.alfresco.com/browse/AR-1689
+
+ batchedResults.setUserDetails(batchedRows);
+ // Done
+ return batchedResults;
+ }
+}
diff --git a/source/java/org/alfresco/repo/webservice/repository/AbstractQuerySession.java b/source/java/org/alfresco/repo/webservice/repository/AbstractQuerySession.java
deleted file mode 100644
index 43b14eb379..0000000000
--- a/source/java/org/alfresco/repo/webservice/repository/AbstractQuerySession.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
- * As a special exception to the terms and conditions of version 2.0 of
- * the GPL, you may redistribute this Program in connection with Free/Libre
- * and Open Source Software ("FLOSS") applications as described in Alfresco's
- * FLOSS exception. You should have recieved a copy of the text describing
- * the FLOSS exception, and it is also available here:
- * http://www.alfresco.com/legal/licensing"
- */
-package org.alfresco.repo.webservice.repository;
-
-import java.util.Set;
-
-import org.alfresco.repo.webservice.types.ResultSetRowNode;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
-import org.alfresco.service.namespace.QName;
-import org.alfresco.util.GUID;
-
-/**
- * Abstract implementation of a QuerySession providing support
- * for automatic id generation and provides support for
- * paging through query results.
- *
- * @author gavinc
- */
-public abstract class AbstractQuerySession implements QuerySession
-{
- protected int batchSize;
- protected int position = 0;
-
- private String id;
-
- /**
- * Common constructor that initialises the session's id and batch size
- *
- * @param batchSize The batch size this session will use
- */
- public AbstractQuerySession(int batchSize)
- {
- this.id = GUID.generate();
- this.batchSize = batchSize;
- }
-
- /**
- * @see org.alfresco.repo.webservice.repository.QuerySession#getId()
- */
- public String getId()
- {
- return this.id;
- }
-
- /**
- * Calculates the index of the last row to retrieve.
- *
- * @param totalRowCount The total number of rows in the results
- * @return The index of the last row to return
- */
- protected int calculateLastRowIndex(int totalRowCount)
- {
- int lastRowIndex = totalRowCount;
-
- // set the last row index if there are more results available
- // than the batch size
- if ((this.batchSize != -1) && ((this.position + this.batchSize) < totalRowCount))
- {
- lastRowIndex = this.position + this.batchSize;
- }
-
- return lastRowIndex;
- }
-
- /**
- * Calculates the value of the next position.
- * If the end of the result set is reached the position is set to -1
- *
- * @param totalRowCount The total number of rows in the results
- * @param queryResult The QueryResult object being returned to the client,
- * if there are no more results the id is removed from the QueryResult instance
- */
- protected void updatePosition(int totalRowCount, QueryResult queryResult)
- {
- this.position += this.batchSize;
- if (this.position >= totalRowCount)
- {
- // signify that there are no more results
- this.position = -1;
- queryResult.setQuerySession(null);
- }
- }
-
- /**
- * Create a result set row node object for the provided node reference
- *
- * @param nodeRef the node reference
- * @param nodeService the node service
- * @return the result set row node
- */
- protected ResultSetRowNode createResultSetRowNode(NodeRef nodeRef, NodeService nodeService)
- {
- // Get the type
- String type = nodeService.getType(nodeRef).toString();
-
- // Get the aspects applied to the node
- Set aspects = nodeService.getAspects(nodeRef);
- String[] aspectNames = new String[aspects.size()];
- int index = 0;
- for (QName aspect : aspects)
- {
- aspectNames[index] = aspect.toString();
- index ++;
- }
-
- // Create and return the result set row node
- return new ResultSetRowNode(nodeRef.getId(), type, aspectNames);
- }
-}
diff --git a/source/java/org/alfresco/repo/webservice/repository/AssociatedQuerySession.java b/source/java/org/alfresco/repo/webservice/repository/AssociatedQuerySession.java
deleted file mode 100644
index 3f6034b9b6..0000000000
--- a/source/java/org/alfresco/repo/webservice/repository/AssociatedQuerySession.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
- * As a special exception to the terms and conditions of version 2.0 of
- * the GPL, you may redistribute this Program in connection with Free/Libre
- * and Open Source Software ("FLOSS") applications as described in Alfresco's
- * FLOSS exception. You should have recieved a copy of the text describing
- * the FLOSS exception, and it is also available here:
- * http://www.alfresco.com/legal/licensing"
- */
-package org.alfresco.repo.webservice.repository;
-
-import java.io.Serializable;
-import java.util.List;
-import java.util.Map;
-
-import org.alfresco.repo.webservice.Utils;
-import org.alfresco.repo.webservice.types.NamedValue;
-import org.alfresco.repo.webservice.types.Reference;
-import org.alfresco.repo.webservice.types.ResultSetRow;
-import org.alfresco.repo.webservice.types.ResultSetRowNode;
-import org.alfresco.service.cmr.dictionary.DictionaryService;
-import org.alfresco.service.cmr.repository.AssociationRef;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
-import org.alfresco.service.cmr.search.SearchService;
-import org.alfresco.service.namespace.NamespaceService;
-import org.alfresco.service.namespace.QName;
-import org.alfresco.service.namespace.QNamePattern;
-import org.alfresco.service.namespace.RegexQNamePattern;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Implementation of a QuerySession that stores the results from a query for
- * associations
- *
- * @author Roy Wetherall
- */
-public class AssociatedQuerySession extends AbstractQuerySession
-{
- private static final long serialVersionUID = 6488008047324436124L;
-
- private transient static Log logger = LogFactory
- .getLog(AssociatedQuerySession.class);
-
- private Reference node;
- private Association association;
-
- /**
- * Constructs a AssociatedQuerySession
- *
- * @param batchSize
- * The batch size to use for this session
- * @param node
- * The node to retrieve the associations
- */
- public AssociatedQuerySession(int batchSize, Reference node, Association association)
- {
- super(batchSize);
-
- this.node = node;
- this.association = association;
- }
-
- /**
- * @see org.alfresco.repo.webservice.repository.QuerySession#getNextResultsBatch(org.alfresco.service.cmr.search.SearchService,
- * org.alfresco.service.cmr.repository.NodeService,
- * org.alfresco.service.namespace.NamespaceService)
- */
- public QueryResult getNextResultsBatch(SearchService searchService,
- NodeService nodeService, NamespaceService namespaceService, DictionaryService dictionaryService)
- {
- QueryResult queryResult = null;
-
- if (this.position != -1)
- {
- if (logger.isDebugEnabled())
- logger.debug("Before getNextResultsBatch: " + toString());
-
- // create the node ref and get the children from the repository
- NodeRef nodeRef = Utils.convertToNodeRef(this.node, nodeService, searchService, namespaceService);
- List assocs = null;
- if (association != null)
- {
- assocs = nodeService.getTargetAssocs(nodeRef, RegexQNamePattern.MATCH_ALL);
- }
- else
- {
- QNamePattern name = RegexQNamePattern.MATCH_ALL;
- String assocType = association.getAssociationType();
- if (assocType != null)
- {
- name = QName.createQName(assocType);
- }
- if ("source".equals(association.getDirection()) == true)
- {
- assocs = nodeService.getSourceAssocs(nodeRef, name);
- }
- else
- {
- assocs = nodeService.getTargetAssocs(nodeRef, name);
- }
- }
-
- int totalRows = assocs.size();
- int lastRow = calculateLastRowIndex(totalRows);
- int currentBatchSize = lastRow - this.position;
-
- if (logger.isDebugEnabled())
- logger.debug("Total rows = " + totalRows
- + ", current batch size = " + currentBatchSize);
-
- org.alfresco.repo.webservice.types.ResultSet batchResults = new org.alfresco.repo.webservice.types.ResultSet();
- org.alfresco.repo.webservice.types.ResultSetRow[] rows = new org.alfresco.repo.webservice.types.ResultSetRow[currentBatchSize];
-
- int arrPos = 0;
- for (int x = this.position; x < lastRow; x++)
- {
- AssociationRef assoc = assocs.get(x);
- NodeRef childNodeRef = assoc.getTargetRef();
- ResultSetRowNode rowNode = createResultSetRowNode(childNodeRef, nodeService);
-
- // create columns for all the properties of the node
- // get the data for the row and build up the columns structure
- Map props = nodeService
- .getProperties(childNodeRef);
- NamedValue[] columns = new NamedValue[props.size()+2];
- int col = 0;
- for (QName propName : props.keySet())
- {
- columns[col] = Utils.createNamedValue(dictionaryService, propName, props.get(propName));
- col++;
- }
-
- // Now add the system columns containing the association details
- columns[col] = new NamedValue(SYS_COL_ASSOC_TYPE, Boolean.FALSE, assoc.getTypeQName().toString(), null);
-
- // Add one more column for the node's path
- col++;
- columns[col] = Utils.createNamedValue(dictionaryService, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "path"), nodeService.getPath(childNodeRef).toString());
-
- ResultSetRow row = new ResultSetRow();
- row.setRowIndex(x);
- row.setNode(rowNode);
- row.setColumns(columns);
-
- // add the row to the overall results
- rows[arrPos] = row;
- arrPos++;
- }
-
- // add the rows to the result set and set the total row count
- batchResults.setRows(rows);
- batchResults.setTotalRowCount(totalRows);
-
- queryResult = new QueryResult(getId(), batchResults);
-
- // move the position on
- updatePosition(totalRows, queryResult);
-
- if (logger.isDebugEnabled())
- logger.debug("After getNextResultsBatch: " + toString());
- }
-
- return queryResult;
- }
-
- /**
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString()
- {
- StringBuilder builder = new StringBuilder(super.toString());
- builder.append(" (id=").append(getId());
- builder.append(" batchSize=").append(this.batchSize);
- builder.append(" position=").append(this.position);
- builder.append(" node-id=").append(this.node.getUuid()).append(")");
- return builder.toString();
- }
-}
diff --git a/source/java/org/alfresco/repo/webservice/repository/AssociationQuery.java b/source/java/org/alfresco/repo/webservice/repository/AssociationQuery.java
new file mode 100644
index 0000000000..13211622ee
--- /dev/null
+++ b/source/java/org/alfresco/repo/webservice/repository/AssociationQuery.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2005-2007 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.webservice.repository;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+import org.alfresco.repo.webservice.AbstractQuery;
+import org.alfresco.repo.webservice.Utils;
+import org.alfresco.repo.webservice.types.NamedValue;
+import org.alfresco.repo.webservice.types.Reference;
+import org.alfresco.repo.webservice.types.ResultSet;
+import org.alfresco.repo.webservice.types.ResultSetRow;
+import org.alfresco.repo.webservice.types.ResultSetRowNode;
+import org.alfresco.service.ServiceRegistry;
+import org.alfresco.service.cmr.dictionary.DictionaryService;
+import org.alfresco.service.cmr.repository.AssociationRef;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.search.SearchService;
+import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.service.namespace.QNamePattern;
+import org.alfresco.service.namespace.RegexQNamePattern;
+
+/**
+ * A query to retrieve normal node associations.
+ *
+ * @author Derek Hulley
+ * @since 2.1
+ */
+public class AssociationQuery extends AbstractQuery
+{
+ private static final long serialVersionUID = -672399618512462040L;
+
+ private Reference node;
+ private Association association;
+
+ /**
+ * @param node
+ * The node to query against
+ * @param association
+ * The association type to query or null to query all
+ */
+ public AssociationQuery(Reference node, Association association)
+ {
+ this.node = node;
+ this.association = association;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("AssociationQuery")
+ .append("[ node=").append(node.getUuid())
+ .append(", association=").append(association)
+ .append("]");
+ return sb.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ResultSet execute(ServiceRegistry serviceRegistry)
+ {
+ SearchService searchService = serviceRegistry.getSearchService();
+ NodeService nodeService = serviceRegistry.getNodeService();
+ DictionaryService dictionaryService = serviceRegistry.getDictionaryService();
+ NamespaceService namespaceService = serviceRegistry.getNamespaceService();
+
+ // create the node ref and get the children from the repository
+ NodeRef nodeRef = Utils.convertToNodeRef(node, nodeService, searchService, namespaceService);
+ List assocRefs = null;
+ if (association != null)
+ {
+ assocRefs = nodeService.getTargetAssocs(nodeRef, RegexQNamePattern.MATCH_ALL);
+ }
+ else
+ {
+ QNamePattern name = RegexQNamePattern.MATCH_ALL;
+ String assocType = association.getAssociationType();
+ if (assocType != null)
+ {
+ name = QName.createQName(assocType);
+ }
+ if ("source".equals(association.getDirection()) == true)
+ {
+ assocRefs = nodeService.getSourceAssocs(nodeRef, name);
+ }
+ else
+ {
+ assocRefs = nodeService.getTargetAssocs(nodeRef, name);
+ }
+ }
+
+ int totalRows = assocRefs.size();
+
+ ResultSet results = new ResultSet();
+ ResultSetRow[] rows = new ResultSetRow[totalRows];
+
+ int index = 0;
+ for (AssociationRef assocRef : assocRefs)
+ {
+ NodeRef childNodeRef = assocRef.getTargetRef();
+ ResultSetRowNode rowNode = createResultSetRowNode(childNodeRef, nodeService);
+
+ // create columns for all the properties of the node
+ // get the data for the row and build up the columns structure
+ Map props = nodeService.getProperties(childNodeRef);
+ NamedValue[] columns = new NamedValue[props.size()+2];
+ int col = 0;
+ for (QName propName : props.keySet())
+ {
+ columns[col] = Utils.createNamedValue(dictionaryService, propName, props.get(propName));
+ col++;
+ }
+
+ // Now add the system columns containing the association details
+ columns[col] = new NamedValue(SYS_COL_ASSOC_TYPE, Boolean.FALSE, assocRef.getTypeQName().toString(), null);
+
+ // Add one more column for the node's path
+ col++;
+ columns[col] = Utils.createNamedValue(
+ dictionaryService,
+ QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "path"),
+ nodeService.getPath(childNodeRef).toString());
+
+ ResultSetRow row = new ResultSetRow();
+ row.setRowIndex(index);
+ row.setNode(rowNode);
+ row.setColumns(columns);
+
+ // add the row to the overall results
+ rows[index] = row;
+ index++;
+ }
+
+ // add the rows to the result set and set the total row count
+ results.setRows(rows);
+ results.setTotalRowCount(totalRows);
+
+ return results;
+ }
+}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/webservice/repository/ChildAssociationQuery.java b/source/java/org/alfresco/repo/webservice/repository/ChildAssociationQuery.java
new file mode 100644
index 0000000000..b890dab74d
--- /dev/null
+++ b/source/java/org/alfresco/repo/webservice/repository/ChildAssociationQuery.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2005-2007 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.webservice.repository;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+import org.alfresco.repo.webservice.AbstractQuery;
+import org.alfresco.repo.webservice.Utils;
+import org.alfresco.repo.webservice.types.NamedValue;
+import org.alfresco.repo.webservice.types.Reference;
+import org.alfresco.repo.webservice.types.ResultSet;
+import org.alfresco.repo.webservice.types.ResultSetRow;
+import org.alfresco.repo.webservice.types.ResultSetRowNode;
+import org.alfresco.service.ServiceRegistry;
+import org.alfresco.service.cmr.dictionary.DictionaryService;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.search.SearchService;
+import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.service.namespace.QName;
+
+/**
+ * A query to retrieve all child associations on a node.
+ *
+ * @author Derek Hulley
+ * @since 2.1
+ */
+public class ChildAssociationQuery extends AbstractQuery
+{
+ private static final long serialVersionUID = -4965097420552826582L;
+
+ private Reference node;
+
+ /**
+ * @param node
+ * The node to query against
+ */
+ public ChildAssociationQuery(Reference node)
+ {
+ this.node = node;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("ChildAssociationQuery")
+ .append("[ node=").append(node.getUuid())
+ .append("]");
+ return sb.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ResultSet execute(ServiceRegistry serviceRegistry)
+ {
+ SearchService searchService = serviceRegistry.getSearchService();
+ NodeService nodeService = serviceRegistry.getNodeService();
+ DictionaryService dictionaryService = serviceRegistry.getDictionaryService();
+ NamespaceService namespaceService = serviceRegistry.getNamespaceService();
+
+ // create the node ref and get the children from the repository
+ NodeRef nodeRef = Utils.convertToNodeRef(node, nodeService, searchService, namespaceService);
+ List assocRefs = nodeService.getChildAssocs(nodeRef);
+
+ int totalRows = assocRefs.size();
+
+ ResultSet results = new ResultSet();
+ ResultSetRow[] rows = new ResultSetRow[totalRows];
+
+ int index = 0;
+ for (ChildAssociationRef assocRef : assocRefs)
+ {
+ NodeRef childNodeRef = assocRef.getChildRef();
+ ResultSetRowNode rowNode = createResultSetRowNode(childNodeRef, nodeService);
+
+ // create columns for all the properties of the node
+ // get the data for the row and build up the columns structure
+ Map props = nodeService.getProperties(childNodeRef);
+ NamedValue[] columns = new NamedValue[props.size()+5];
+ int col = 0;
+ for (QName propName : props.keySet())
+ {
+ columns[col] = Utils.createNamedValue(dictionaryService, propName, props.get(propName));
+ col++;
+ }
+
+ // Now add the system columns containing the association details
+ columns[col] = new NamedValue(SYS_COL_ASSOC_TYPE, Boolean.FALSE, assocRef.getTypeQName().toString(), null);
+ col++;
+ columns[col] = new NamedValue(SYS_COL_ASSOC_NAME, Boolean.FALSE, assocRef.getQName().toString(), null);
+ col++;
+ columns[col] = new NamedValue(SYS_COL_IS_PRIMARY, Boolean.FALSE, Boolean.toString(assocRef.isPrimary()), null);
+ col++;
+ columns[col] = new NamedValue(SYS_COL_NTH_SIBLING, Boolean.FALSE, Integer.toString(assocRef.getNthSibling()), null);
+
+ // Add one more column for the node's path
+ col++;
+ columns[col] = Utils.createNamedValue(
+ dictionaryService,
+ QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "path"),
+ nodeService.getPath(childNodeRef).toString());
+
+ ResultSetRow row = new ResultSetRow();
+ row.setRowIndex(index);
+ row.setNode(rowNode);
+ row.setColumns(columns);
+
+ // add the row to the overall results
+ rows[index] = row;
+ index++;
+ }
+
+ // add the rows to the result set and set the total row count
+ results.setRows(rows);
+ results.setTotalRowCount(totalRows);
+
+ return results;
+ }
+}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/webservice/repository/ChildrenQuerySession.java b/source/java/org/alfresco/repo/webservice/repository/ChildrenQuerySession.java
deleted file mode 100644
index bfbccbc497..0000000000
--- a/source/java/org/alfresco/repo/webservice/repository/ChildrenQuerySession.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
- * As a special exception to the terms and conditions of version 2.0 of
- * the GPL, you may redistribute this Program in connection with Free/Libre
- * and Open Source Software ("FLOSS") applications as described in Alfresco's
- * FLOSS exception. You should have recieved a copy of the text describing
- * the FLOSS exception, and it is also available here:
- * http://www.alfresco.com/legal/licensing"
- */
-package org.alfresco.repo.webservice.repository;
-
-import java.io.Serializable;
-import java.util.List;
-import java.util.Map;
-
-import org.alfresco.repo.webservice.Utils;
-import org.alfresco.repo.webservice.types.NamedValue;
-import org.alfresco.repo.webservice.types.Reference;
-import org.alfresco.repo.webservice.types.ResultSetRow;
-import org.alfresco.repo.webservice.types.ResultSetRowNode;
-import org.alfresco.service.cmr.dictionary.DictionaryService;
-import org.alfresco.service.cmr.repository.ChildAssociationRef;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
-import org.alfresco.service.cmr.search.SearchService;
-import org.alfresco.service.namespace.NamespaceService;
-import org.alfresco.service.namespace.QName;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Implementation of a QuerySession that stores the results from a query for children
- *
- * @author gavinc
- */
-public class ChildrenQuerySession extends AbstractQuerySession
-{
- private static final long serialVersionUID = -5347036309571057074L;
-
- private transient static Log logger = LogFactory.getLog(ChildrenQuerySession.class);
-
- private Reference node;
-
- /**
- * Constructs a ChildrenQuerySession
- *
- * @param batchSize The batch size to use for this session
- * @param node The node to retrieve the parents
- */
- public ChildrenQuerySession(int batchSize, Reference node)
- {
- super(batchSize);
-
- this.node = node;
- }
-
- /**
- * @see org.alfresco.repo.webservice.repository.QuerySession#getNextResultsBatch(org.alfresco.service.cmr.search.SearchService, org.alfresco.service.cmr.repository.NodeService, org.alfresco.service.namespace.NamespaceService)
- */
- public QueryResult getNextResultsBatch(SearchService searchService, NodeService nodeService, NamespaceService namespaceService, DictionaryService dictionaryService)
- {
- QueryResult queryResult = null;
-
- if (this.position != -1)
- {
- if (logger.isDebugEnabled())
- logger.debug("Before getNextResultsBatch: " + toString());
-
- // create the node ref and get the children from the repository
- NodeRef nodeRef = Utils.convertToNodeRef(this.node, nodeService, searchService, namespaceService);
- List kids = nodeService.getChildAssocs(nodeRef);
-
- int totalRows = kids.size();
- int lastRow = calculateLastRowIndex(totalRows);
- int currentBatchSize = lastRow - this.position;
-
- if (logger.isDebugEnabled())
- logger.debug("Total rows = " + totalRows + ", current batch size = " + currentBatchSize);
-
- org.alfresco.repo.webservice.types.ResultSet batchResults = new org.alfresco.repo.webservice.types.ResultSet();
- org.alfresco.repo.webservice.types.ResultSetRow[] rows = new org.alfresco.repo.webservice.types.ResultSetRow[currentBatchSize];
-
- int arrPos = 0;
- for (int x = this.position; x < lastRow; x++)
- {
- ChildAssociationRef assoc = kids.get(x);
- NodeRef childNodeRef = assoc.getChildRef();
- ResultSetRowNode rowNode = createResultSetRowNode(childNodeRef, nodeService);
-
- // create columns for all the properties of the node
- // get the data for the row and build up the columns structure
- Map props = nodeService.getProperties(childNodeRef);
- NamedValue[] columns = new NamedValue[props.size()+5];
- int col = 0;
- for (QName propName : props.keySet())
- {
- columns[col] = Utils.createNamedValue(dictionaryService, propName, props.get(propName));
- col++;
- }
-
- // Now add the system columns containing the association details
- columns[col] = new NamedValue(SYS_COL_ASSOC_TYPE, Boolean.FALSE, assoc.getTypeQName().toString(), null);
- col++;
- columns[col] = new NamedValue(SYS_COL_ASSOC_NAME, Boolean.FALSE, assoc.getQName().toString(), null);
- col++;
- columns[col] = new NamedValue(SYS_COL_IS_PRIMARY, Boolean.FALSE, Boolean.toString(assoc.isPrimary()), null);
- col++;
- columns[col] = new NamedValue(SYS_COL_NTH_SIBLING, Boolean.FALSE, Integer.toString(assoc.getNthSibling()), null);
-
- // Add one more column for the node's path
- col++;
- columns[col] = Utils.createNamedValue(dictionaryService, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "path"), nodeService.getPath(childNodeRef).toString());
-
- ResultSetRow row = new ResultSetRow();
- row.setRowIndex(x);
- row.setNode(rowNode);
- row.setColumns(columns);
-
- // add the row to the overall results
- rows[arrPos] = row;
- arrPos++;
- }
-
- // add the rows to the result set and set the total row count
- batchResults.setRows(rows);
- batchResults.setTotalRowCount(totalRows);
-
- queryResult = new QueryResult(getId(), batchResults);
-
- // move the position on
- updatePosition(totalRows, queryResult);
-
- if (logger.isDebugEnabled())
- logger.debug("After getNextResultsBatch: " + toString());
- }
-
- return queryResult;
- }
-
- /**
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString()
- {
- StringBuilder builder = new StringBuilder(super.toString());
- builder.append(" (id=").append(getId());
- builder.append(" batchSize=").append(this.batchSize);
- builder.append(" position=").append(this.position);
- builder.append(" node-id=").append(this.node.getUuid()).append(")");
- return builder.toString();
- }
-}
diff --git a/source/java/org/alfresco/repo/webservice/repository/ParentAssociationQuery.java b/source/java/org/alfresco/repo/webservice/repository/ParentAssociationQuery.java
new file mode 100644
index 0000000000..00d5c67193
--- /dev/null
+++ b/source/java/org/alfresco/repo/webservice/repository/ParentAssociationQuery.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2005-2007 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.webservice.repository;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+import org.alfresco.repo.webservice.AbstractQuery;
+import org.alfresco.repo.webservice.Utils;
+import org.alfresco.repo.webservice.types.NamedValue;
+import org.alfresco.repo.webservice.types.Reference;
+import org.alfresco.repo.webservice.types.ResultSet;
+import org.alfresco.repo.webservice.types.ResultSetRow;
+import org.alfresco.repo.webservice.types.ResultSetRowNode;
+import org.alfresco.service.ServiceRegistry;
+import org.alfresco.service.cmr.dictionary.DictionaryService;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.search.SearchService;
+import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.service.namespace.QName;
+
+/**
+ * A query to retrieve all parent associations on a node.
+ *
+ * @author Derek Hulley
+ * @since 2.1
+ */
+public class ParentAssociationQuery extends AbstractQuery
+{
+ private static final long serialVersionUID = -4157476722256947274L;
+
+ private Reference node;
+
+ /**
+ * @param node
+ * The node to query against
+ */
+ public ParentAssociationQuery(Reference node)
+ {
+ this.node = node;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("ParentAssociationQuery")
+ .append("[ node=").append(node.getUuid())
+ .append("]");
+ return sb.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ResultSet execute(ServiceRegistry serviceRegistry)
+ {
+ SearchService searchService = serviceRegistry.getSearchService();
+ NodeService nodeService = serviceRegistry.getNodeService();
+ DictionaryService dictionaryService = serviceRegistry.getDictionaryService();
+ NamespaceService namespaceService = serviceRegistry.getNamespaceService();
+
+ // create the node ref and get the parent from the repository
+ NodeRef nodeRef = Utils.convertToNodeRef(node, nodeService, searchService, namespaceService);
+ List assocRefs = nodeService.getParentAssocs(nodeRef);
+
+ int totalRows = assocRefs.size();
+
+ ResultSet results = new ResultSet();
+ ResultSetRow[] rows = new ResultSetRow[totalRows];
+
+ int index = 0;
+ for (ChildAssociationRef assocRef : assocRefs)
+ {
+ NodeRef parentNodeRef = assocRef.getParentRef();
+ ResultSetRowNode rowNode = createResultSetRowNode(parentNodeRef, nodeService);
+
+ // create columns for all the properties of the node
+ // get the data for the row and build up the columns structure
+ Map props = nodeService.getProperties(parentNodeRef);
+ NamedValue[] columns = new NamedValue[props.size()+5];
+ int col = 0;
+ for (QName propName : props.keySet())
+ {
+ columns[col] = Utils.createNamedValue(dictionaryService, propName, props.get(propName));
+ col++;
+ }
+
+ // Now add the system columns containing the association details
+ columns[col] = new NamedValue(SYS_COL_ASSOC_TYPE, Boolean.FALSE, assocRef.getTypeQName().toString(), null);
+ col++;
+ columns[col] = new NamedValue(SYS_COL_ASSOC_NAME, Boolean.FALSE, assocRef.getQName().toString(), null);
+ col++;
+ columns[col] = new NamedValue(SYS_COL_IS_PRIMARY, Boolean.FALSE, Boolean.toString(assocRef.isPrimary()), null);
+ col++;
+ columns[col] = new NamedValue(SYS_COL_NTH_SIBLING, Boolean.FALSE, Integer.toString(assocRef.getNthSibling()), null);
+
+ // Add one more column for the node's path
+ col++;
+ columns[col] = Utils.createNamedValue(
+ dictionaryService,
+ QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "path"),
+ nodeService.getPath(parentNodeRef).toString());
+
+ ResultSetRow row = new ResultSetRow();
+ row.setRowIndex(index);
+ row.setNode(rowNode);
+ row.setColumns(columns);
+
+ // add the row to the overall results
+ rows[index] = row;
+ index++;
+ }
+
+ // add the rows to the result set and set the total row count
+ results.setRows(rows);
+ results.setTotalRowCount(totalRows);
+
+ return results;
+ }
+}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/webservice/repository/ParentsQuerySession.java b/source/java/org/alfresco/repo/webservice/repository/ParentsQuerySession.java
deleted file mode 100644
index 935171519f..0000000000
--- a/source/java/org/alfresco/repo/webservice/repository/ParentsQuerySession.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
- * As a special exception to the terms and conditions of version 2.0 of
- * the GPL, you may redistribute this Program in connection with Free/Libre
- * and Open Source Software ("FLOSS") applications as described in Alfresco's
- * FLOSS exception. You should have recieved a copy of the text describing
- * the FLOSS exception, and it is also available here:
- * http://www.alfresco.com/legal/licensing"
- */
-package org.alfresco.repo.webservice.repository;
-
-import java.io.Serializable;
-import java.util.List;
-import java.util.Map;
-
-import org.alfresco.repo.webservice.Utils;
-import org.alfresco.repo.webservice.types.NamedValue;
-import org.alfresco.repo.webservice.types.Reference;
-import org.alfresco.repo.webservice.types.ResultSetRow;
-import org.alfresco.repo.webservice.types.ResultSetRowNode;
-import org.alfresco.service.cmr.dictionary.DictionaryService;
-import org.alfresco.service.cmr.repository.ChildAssociationRef;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
-import org.alfresco.service.cmr.search.SearchService;
-import org.alfresco.service.namespace.NamespaceService;
-import org.alfresco.service.namespace.QName;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Implementation of a QuerySession that stores the results from a query for parents
- *
- * @author gavinc
- */
-public class ParentsQuerySession extends AbstractQuerySession
-{
- private static final long serialVersionUID = 2539375863409175463L;
-
- private transient static Log logger = LogFactory.getLog(ParentsQuerySession.class);
-
- private Reference node;
-
- /**
- * Constructs a ParentsQuerySession
- *
- * @param batchSize The batch size to use for this session
- * @param node The node to retrieve the parents
- */
- public ParentsQuerySession(int batchSize, Reference node)
- {
- super(batchSize);
-
- this.node = node;
- }
-
- /**
- * @see org.alfresco.repo.webservice.repository.QuerySession#getNextResultsBatch(org.alfresco.service.cmr.search.SearchService, org.alfresco.service.cmr.repository.NodeService, org.alfresco.service.namespace.NamespaceService)
- */
- public QueryResult getNextResultsBatch(SearchService searchService, NodeService nodeService, NamespaceService namespaceService, DictionaryService dictionaryService)
- {
- QueryResult queryResult = null;
-
- if (this.position != -1)
- {
- if (logger.isDebugEnabled())
- logger.debug("Before getNextResultsBatch: " + toString());
-
- // create the node ref and get the children from the repository
- NodeRef nodeRef = Utils.convertToNodeRef(this.node, nodeService, searchService, namespaceService);
- List parents = nodeService.getParentAssocs(nodeRef);
-
- int totalRows = parents.size();
- int lastRow = calculateLastRowIndex(totalRows);
- int currentBatchSize = lastRow - this.position;
-
- if (logger.isDebugEnabled())
- logger.debug("Total rows = " + totalRows + ", current batch size = " + currentBatchSize);
-
- org.alfresco.repo.webservice.types.ResultSet batchResults = new org.alfresco.repo.webservice.types.ResultSet();
- org.alfresco.repo.webservice.types.ResultSetRow[] rows = new org.alfresco.repo.webservice.types.ResultSetRow[currentBatchSize];
-
- int arrPos = 0;
- for (int x = this.position; x < lastRow; x++)
- {
- ChildAssociationRef assoc = parents.get(x);
- NodeRef parentNodeRef = assoc.getParentRef();
- ResultSetRowNode rowNode = createResultSetRowNode(parentNodeRef, nodeService);
-
- // create columns for all the properties of the node
- // get the data for the row and build up the columns structure
- Map props = nodeService.getProperties(parentNodeRef);
- NamedValue[] columns = new NamedValue[props.size()+5];
- int col = 0;
- for (QName propName : props.keySet())
- {
- columns[col] = Utils.createNamedValue(dictionaryService, propName, props.get(propName));
- col++;
- }
-
- // Now add the system columns containing the association details
- columns[col] = new NamedValue(SYS_COL_ASSOC_TYPE, Boolean.FALSE, assoc.getTypeQName().toString(), null);
- col++;
- columns[col] = new NamedValue(SYS_COL_ASSOC_NAME, Boolean.FALSE, assoc.getQName().toString(), null);
- col++;
- columns[col] = new NamedValue(SYS_COL_IS_PRIMARY, Boolean.FALSE, Boolean.toString(assoc.isPrimary()), null);
- col++;
- columns[col] = new NamedValue(SYS_COL_NTH_SIBLING, Boolean.FALSE, Integer.toString(assoc.getNthSibling()), null);
- // Add one more column for the node's path
- col++;
- columns[col] = Utils.createNamedValue(dictionaryService, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "path"), nodeService.getPath(parentNodeRef).toString());
-
- ResultSetRow row = new ResultSetRow();
- row.setRowIndex(x);
- row.setNode(rowNode);
- row.setColumns(columns);
-
- // add the row to the overall results
- rows[arrPos] = row;
- arrPos++;
- }
-
- // add the rows to the result set and set the total row count
- batchResults.setRows(rows);
- batchResults.setTotalRowCount(totalRows);
-
- queryResult = new QueryResult(getId(), batchResults);
-
- // move the position on
- updatePosition(totalRows, queryResult);
-
- if (logger.isDebugEnabled())
- logger.debug("After getNextResultsBatch: " + toString());
- }
-
- return queryResult;
- }
-
- /**
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString()
- {
- StringBuilder builder = new StringBuilder(super.toString());
- builder.append(" (id=").append(getId());
- builder.append(" batchSize=").append(this.batchSize);
- builder.append(" position=").append(this.position);
- builder.append(" node-id=").append(this.node.getUuid()).append(")");
- return builder.toString();
- }
-}
diff --git a/source/java/org/alfresco/repo/webservice/repository/RepositoryQuerySession.java b/source/java/org/alfresco/repo/webservice/repository/RepositoryQuerySession.java
new file mode 100644
index 0000000000..67c99c6ce3
--- /dev/null
+++ b/source/java/org/alfresco/repo/webservice/repository/RepositoryQuerySession.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2005-2007 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.webservice.repository;
+
+import org.alfresco.repo.webservice.AbstractQuerySession;
+import org.alfresco.repo.webservice.ServerQuery;
+import org.alfresco.repo.webservice.types.ResultSet;
+import org.alfresco.repo.webservice.types.ResultSetRow;
+import org.alfresco.service.ServiceRegistry;
+
+/**
+ * A query session for use with {@linkplain RepositoryWebService node-related queries} against the
+ * repository.
+ *
+ * @author Derek Hulley
+ * @since 2.1
+ */
+public class RepositoryQuerySession extends AbstractQuerySession
+{
+ private static final long serialVersionUID = -3621997639261137000L;
+
+ public RepositoryQuerySession(long maxResults, long batchSize, ServerQuery query)
+ {
+ super(maxResults, batchSize, query);
+ }
+
+ @Override
+ protected ResultSetRow[] makeArray(int size)
+ {
+ return new ResultSetRow[size];
+ }
+
+ public ResultSet getNextResults(ServiceRegistry serviceRegistry)
+ {
+ ResultSet queryResults = getQueryResults(serviceRegistry);
+ ResultSetRow[] allRows = queryResults.getRows();
+ ResultSetRow[] batchedRows = getNextResults(allRows);
+ // Build the resultset for the batched results
+ ResultSet batchedResults = new ResultSet();
+ batchedResults.setMetaData(queryResults.getMetaData());
+ batchedResults.setRows(batchedRows);
+ batchedResults.setTotalRowCount(batchedRows.length);
+ // Done
+ return batchedResults;
+ }
+}
diff --git a/source/java/org/alfresco/repo/webservice/repository/RepositoryWebService.java b/source/java/org/alfresco/repo/webservice/repository/RepositoryWebService.java
index 1389a89402..0e5ba72e60 100644
--- a/source/java/org/alfresco/repo/webservice/repository/RepositoryWebService.java
+++ b/source/java/org/alfresco/repo/webservice/repository/RepositoryWebService.java
@@ -31,10 +31,10 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
-import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.repo.webservice.AbstractWebService;
import org.alfresco.repo.webservice.CMLUtil;
+import org.alfresco.repo.webservice.ServerQuery;
import org.alfresco.repo.webservice.Utils;
import org.alfresco.repo.webservice.types.CML;
import org.alfresco.repo.webservice.types.ClassDefinition;
@@ -44,9 +44,9 @@ import org.alfresco.repo.webservice.types.NodeDefinition;
import org.alfresco.repo.webservice.types.Predicate;
import org.alfresco.repo.webservice.types.Query;
import org.alfresco.repo.webservice.types.Reference;
+import org.alfresco.repo.webservice.types.ResultSet;
import org.alfresco.repo.webservice.types.Store;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
-import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
@@ -67,23 +67,8 @@ public class RepositoryWebService extends AbstractWebService implements
{
private static Log logger = LogFactory.getLog(RepositoryWebService.class);
- private DictionaryService dictionaryService;
-
private CMLUtil cmlUtil;
- private SimpleCache querySessionCache;
-
- /**
- * Sets the instance of the DictionaryService to be used
- *
- * @param dictionaryService
- * The DictionaryService
- */
- public void setDictionaryService(DictionaryService dictionaryService)
- {
- this.dictionaryService = dictionaryService;
- }
-
/**
* Sets the CML Util
*
@@ -94,18 +79,6 @@ public class RepositoryWebService extends AbstractWebService implements
this.cmlUtil = cmlUtil;
}
- /**
- * Sets the instance of the SimpleCache to be used
- *
- * @param querySessionCache
- * The SimpleCache
- */
- public void setQuerySessionCache(
- SimpleCache querySessionCache)
- {
- this.querySessionCache = querySessionCache;
- }
-
/**
* {@inheritDoc}
*/
@@ -156,11 +129,58 @@ public class RepositoryWebService extends AbstractWebService implements
}
}
+ /**
+ * Executes the given query, caching the results as required.
+ */
+ private QueryResult executeQuery(final MessageContext msgContext, final ServerQuery query) throws RepositoryFault
+ {
+ try
+ {
+ RetryingTransactionCallback callback = new RetryingTransactionCallback()
+ {
+ public QueryResult execute() throws Throwable
+ {
+ // Construct a session to handle the iteration
+ long batchSize = Utils.getBatchSize(msgContext);
+ RepositoryQuerySession session = new RepositoryQuerySession(Long.MAX_VALUE, batchSize, query);
+ String sessionId = session.getId();
+
+ // Get the first batch of results
+ ResultSet batchedResults = session.getNextResults(serviceRegistry);
+ // Construct the result
+ // TODO: http://issues.alfresco.com/browse/AR-1689
+ boolean haveMoreResults = session.haveMoreResults();
+ QueryResult queryResult = new QueryResult(
+ haveMoreResults ? sessionId : null,
+ batchedResults);
+
+ // Cache the session
+ if (session.haveMoreResults())
+ {
+ querySessionCache.put(sessionId, session);
+ }
+
+ // Done
+ return queryResult;
+ }
+ };
+ return Utils.getRetryingTransactionHelper(MessageContext.getCurrentContext()).doInTransaction(callback, true);
+ }
+ catch (Throwable e)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.error("Unexpected error occurred", e);
+ }
+ e.printStackTrace();
+ throw new RepositoryFault(0, e.toString());
+ }
+ }
+
/**
* {@inheritDoc}
*/
- public QueryResult query(final Store store, final Query query, final boolean includeMetaData)
- throws RemoteException, RepositoryFault
+ public QueryResult query(final Store store, final Query query, final boolean includeMetaData) throws RemoteException, RepositoryFault
{
String language = query.getLanguage();
if (language.equals(Utils.QUERY_LANG_LUCENE) == false)
@@ -171,131 +191,52 @@ public class RepositoryWebService extends AbstractWebService implements
}
final MessageContext msgContext = MessageContext.getCurrentContext();
- try
- {
- RetryingTransactionCallback callback = new RetryingTransactionCallback()
- {
- public QueryResult execute() throws Throwable
- {
- // setup a query session and get the first batch of results
- QuerySession querySession = new ResultSetQuerySession(Utils
- .getBatchSize(msgContext), store, query, includeMetaData);
- QueryResult queryResult = querySession
- .getNextResultsBatch(searchService, nodeService, namespaceService, dictionaryService);
-
- // add the session to the cache if there are more results to come
- if (queryResult.getQuerySession() != null)
- {
- // this.querySessionCache.putQuerySession(querySession);
- querySessionCache.put(queryResult.getQuerySession(), querySession);
- }
-
- return queryResult;
- }
- };
- return Utils.getRetryingTransactionHelper(MessageContext.getCurrentContext()).doInTransaction(callback);
- }
- catch (Throwable e)
- {
- if (logger.isDebugEnabled())
- {
- logger.error("Unexpected error occurred", e);
- }
- e.printStackTrace();
- throw new RepositoryFault(0, e.toString());
- }
+ SearchQuery serverQuery = new SearchQuery(store, query);
+ QueryResult queryResult = executeQuery(msgContext, serverQuery);
+ // Done
+ return queryResult;
}
/**
* {@inheritDoc}
*/
- public QueryResult queryChildren(final Reference node) throws RemoteException,
- RepositoryFault
+ public QueryResult queryChildren(final Reference node) throws RemoteException, RepositoryFault
{
- try
- {
- RetryingTransactionCallback callback = new RetryingTransactionCallback()
- {
- public QueryResult execute() throws Throwable
- {
- // setup a query session and get the first batch of results
- QuerySession querySession = new ChildrenQuerySession(Utils
- .getBatchSize(MessageContext.getCurrentContext()), node);
- QueryResult queryResult = querySession
- .getNextResultsBatch(searchService, nodeService, namespaceService, dictionaryService);
-
- // add the session to the cache if there are more results to come
- if (queryResult.getQuerySession() != null)
- {
- querySessionCache.put(queryResult.getQuerySession(), querySession);
- }
-
- if (logger.isDebugEnabled())
- {
- logger.debug("Method end ... queryChildren");
- }
-
- return queryResult;
- }
- };
- return Utils.getRetryingTransactionHelper(MessageContext.getCurrentContext()).doInTransaction(callback);
- }
- catch (Throwable e)
- {
- if (logger.isDebugEnabled())
- {
- logger.error("Unexpected error occurred", e);
- }
- e.printStackTrace();
- throw new RepositoryFault(0, e.toString());
- }
+ final MessageContext msgContext = MessageContext.getCurrentContext();
+ ChildAssociationQuery query = new ChildAssociationQuery(node);
+ QueryResult queryResult = executeQuery(msgContext, query);
+ // Done
+ return queryResult;
}
-
+
/**
* {@inheritDoc}
*/
public QueryResult queryParents(final Reference node) throws RemoteException, RepositoryFault
{
- try
- {
- RetryingTransactionCallback callback = new RetryingTransactionCallback()
- {
- public QueryResult execute() throws Throwable
- {
- // setup a query session and get the first batch of results
- QuerySession querySession = new ParentsQuerySession(Utils
- .getBatchSize(MessageContext.getCurrentContext()), node);
- QueryResult queryResult = querySession.getNextResultsBatch(
- searchService, nodeService, namespaceService, dictionaryService);
-
- // add the session to the cache if there are more results to come
- if (queryResult.getQuerySession() != null)
- {
- // this.querySessionCache.putQuerySession(querySession);
- querySessionCache.put(queryResult.getQuerySession(), querySession);
- }
-
- return queryResult;
- }
- };
- return Utils.getRetryingTransactionHelper(MessageContext.getCurrentContext()).doInTransaction(callback);
-
- }
- catch (Throwable e)
- {
- if (logger.isDebugEnabled())
- {
- logger.error("Unexpected error occurred", e);
- }
- throw new RepositoryFault(0, e.toString());
- }
+ final MessageContext msgContext = MessageContext.getCurrentContext();
+ ParentAssociationQuery query = new ParentAssociationQuery(node);
+ QueryResult queryResult = executeQuery(msgContext, query);
+ // Done
+ return queryResult;
}
/**
* {@inheritDoc}
*/
- public QueryResult queryAssociated(final Reference node, final Association association)
- throws RemoteException, RepositoryFault
+ public QueryResult queryAssociated(final Reference node, final Association association) throws RemoteException, RepositoryFault
+ {
+ final MessageContext msgContext = MessageContext.getCurrentContext();
+ AssociationQuery query = new AssociationQuery(node, association);
+ QueryResult queryResult = executeQuery(msgContext, query);
+ // Done
+ return queryResult;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public QueryResult fetchMore(final String querySessionId) throws RemoteException, RepositoryFault
{
try
{
@@ -303,76 +244,54 @@ public class RepositoryWebService extends AbstractWebService implements
{
public QueryResult execute() throws Throwable
{
- // setup a query session and get the first batch of results
- QuerySession querySession = new AssociatedQuerySession(Utils.getBatchSize(MessageContext.getCurrentContext()), node, association);
- QueryResult queryResult = querySession.getNextResultsBatch(searchService, nodeService, namespaceService, dictionaryService);
-
- // add the session to the cache if there are more results to come
- if (queryResult.getQuerySession() != null)
+ RepositoryQuerySession session = null;
+ try
{
- // this.querySessionCache.putQuerySession(querySession);
- querySessionCache.put(queryResult.getQuerySession(), querySession);
+ // try and get the QuerySession with the given id from the cache
+ session = (RepositoryQuerySession) querySessionCache.get(querySessionId);
+ }
+ catch (ClassCastException e)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Query session was not generated by the RepositoryWebService: " + querySessionId);
+ }
+ throw new RepositoryFault(
+ 4,
+ "querySession with id '" + querySessionId + "' is invalid");
}
-
- return queryResult;
- }
- };
- return Utils.getRetryingTransactionHelper(MessageContext.getCurrentContext()).doInTransaction(callback);
- }
- catch (Throwable e)
- {
- if (logger.isDebugEnabled())
- {
- logger.error("Unexpected error occurred", e);
- }
- throw new RepositoryFault(0, e.toString());
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public QueryResult fetchMore(final String querySession) throws RemoteException, RepositoryFault
- {
- try
- {
- RetryingTransactionCallback callback = new RetryingTransactionCallback()
- {
- public QueryResult execute() throws Throwable
- {
- // try and get the QuerySession with the given id from the cache
- QuerySession session = querySessionCache.get(querySession);
if (session == null)
{
if (logger.isDebugEnabled())
{
- logger.debug("Invalid querySession id requested: " + querySession);
+ logger.debug("Invalid querySession id requested: " + querySessionId);
}
-
throw new RepositoryFault(
4,
- "querySession with id '" + querySession + "' is invalid");
+ "querySession with id '" + querySessionId + "' is invalid");
+ }
+
+ ResultSet moreResults = session.getNextResults(serviceRegistry);
+
+ // Drop the cache results if there are no more results expected
+ if (!session.haveMoreResults())
+ {
+ querySessionCache.remove(querySessionId);
}
// get the next batch of results
- QueryResult queryResult = session.getNextResultsBatch(
- searchService,
- nodeService,
- namespaceService,
- dictionaryService);
-
- // remove the QuerySession from the cache if there are no more
- // results to come
- if (queryResult.getQuerySession() == null)
- {
- querySessionCache.remove(querySession);
- }
+ // TODO: http://issues.alfresco.com/browse/AR-1689
+ boolean haveMoreResults = session.haveMoreResults();
+ QueryResult queryResult = new QueryResult(
+ haveMoreResults ? querySessionId : null,
+ moreResults);
+ // Done
return queryResult;
}
};
- return Utils.getRetryingTransactionHelper(MessageContext.getCurrentContext()).doInTransaction(callback);
+ return Utils.getRetryingTransactionHelper(MessageContext.getCurrentContext()).doInTransaction(callback, true);
}
catch (Throwable e)
{
diff --git a/source/java/org/alfresco/repo/webservice/repository/ResultSetQuerySession.java b/source/java/org/alfresco/repo/webservice/repository/ResultSetQuerySession.java
deleted file mode 100644
index 3a455d3874..0000000000
--- a/source/java/org/alfresco/repo/webservice/repository/ResultSetQuerySession.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
- * As a special exception to the terms and conditions of version 2.0 of
- * the GPL, you may redistribute this Program in connection with Free/Libre
- * and Open Source Software ("FLOSS") applications as described in Alfresco's
- * FLOSS exception. You should have recieved a copy of the text describing
- * the FLOSS exception, and it is also available here:
- * http://www.alfresco.com/legal/licensing"
- */
-package org.alfresco.repo.webservice.repository;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.alfresco.repo.webservice.Utils;
-import org.alfresco.repo.webservice.types.NamedValue;
-import org.alfresco.repo.webservice.types.Query;
-import org.alfresco.repo.webservice.types.ResultSetRowNode;
-import org.alfresco.repo.webservice.types.Store;
-import org.alfresco.service.cmr.dictionary.DictionaryService;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
-import org.alfresco.service.cmr.repository.Path;
-import org.alfresco.service.cmr.search.ResultSet;
-import org.alfresco.service.cmr.search.ResultSetRow;
-import org.alfresco.service.cmr.search.SearchService;
-import org.alfresco.service.namespace.NamespaceService;
-import org.alfresco.service.namespace.QName;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Implementation of a QuerySession that retrieves results from a repository ResultSet
- *
- * @author gavinc
- */
-public class ResultSetQuerySession extends AbstractQuerySession
-{
- private static final long serialVersionUID = -9154514445963635138L;
-
- private transient static Log logger = LogFactory.getLog(ResultSetQuerySession.class);
-
- private Store store;
- private Query query;
- @SuppressWarnings("unused")
- private boolean includeMetaData;
-
- /**
- * Constructs a ResultSetQuerySession
- *
- * @param batchSize The batch size to use for this session
- * @param store The repository store to query against
- * @param query The query to execute
- * @param includeMetaData Whether to include metadata in the query results
- */
- public ResultSetQuerySession(int batchSize, Store store, Query query, boolean includeMetaData)
- {
- super(batchSize);
-
- this.store = store;
- this.query = query;
- this.includeMetaData = includeMetaData;
- }
-
- /**
- * @see org.alfresco.repo.webservice.repository.QuerySession#getNextResultsBatch(org.alfresco.service.cmr.search.SearchService, org.alfresco.service.cmr.repository.NodeService, org.alfresco.service.namespace.NamespaceService)
- */
- public QueryResult getNextResultsBatch(SearchService searchService, NodeService nodeService, NamespaceService namespaceService, DictionaryService dictionaryService)
- {
- QueryResult queryResult = null;
-
- if (this.position != -1)
- {
- if (logger.isDebugEnabled())
- logger.debug("Before getNextResultsBatch: " + toString());
-
- // handle the special search string of * meaning, get everything
- String statement = query.getStatement();
- if (statement.equals("*"))
- {
- statement = "ISNODE:*";
- }
- ResultSet searchResults = null;
- try
- {
- searchResults = searchService.query(Utils.convertToStoreRef(this.store),
- this.query.getLanguage(), statement);
-
- int totalRows = searchResults.length();
- int lastRow = calculateLastRowIndex(totalRows);
- int currentBatchSize = lastRow - this.position;
-
- if (logger.isDebugEnabled())
- logger.debug("Total rows = " + totalRows + ", current batch size = " + currentBatchSize);
-
- org.alfresco.repo.webservice.types.ResultSet batchResults = new org.alfresco.repo.webservice.types.ResultSet();
- List rowList =
- new ArrayList();
-
- for (int x = this.position; x < lastRow; x++)
- {
- ResultSetRow origRow = searchResults.getRow(x);
- NodeRef nodeRef = origRow.getNodeRef();
-
- // search can return nodes that no longer exist, so we need to ignore these
- if(nodeService.exists(nodeRef) == false)
- {
- if(logger.isDebugEnabled())
- {
- logger.warn("Search returned node that doesn't exist: " + nodeRef);
- }
- continue;
- }
-
- ResultSetRowNode rowNode = createResultSetRowNode(nodeRef, nodeService);
-
- // get the data for the row and build up the columns structure
- Map values = origRow.getValues();
- NamedValue[] columns = new NamedValue[values.size() + 1];
- int col = 0;
- for (Path path : values.keySet())
- {
- // Get the attribute QName from the result path
- String attributeName = path.last().toString();
- if (attributeName.startsWith("@") == true)
- {
- attributeName = attributeName.substring(1);
- }
-
- columns[col] = Utils.createNamedValue(dictionaryService, QName.createQName(attributeName), values.get(path));
- col++;
- }
-
- // add one extra column for the node's path
- columns[col] = Utils.createNamedValue(dictionaryService, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "path"), nodeService.getPath(nodeRef).toString());
-
- org.alfresco.repo.webservice.types.ResultSetRow row = new org.alfresco.repo.webservice.types.ResultSetRow();
- row.setColumns(columns);
- row.setScore(origRow.getScore());
- row.setRowIndex(x);
- row.setNode(rowNode);
-
- // add the row to the overall results list
- rowList.add(row);
- }
-
- // TODO: build up the meta data data structure if we've been asked to
-
- // add the rows to the result set and set the total row count
- org.alfresco.repo.webservice.types.ResultSetRow[] rows =
- rowList.toArray(new org.alfresco.repo.webservice.types.ResultSetRow[rowList.size()]);;
- batchResults.setRows(rows);
- batchResults.setTotalRowCount(totalRows);
-
- queryResult = new QueryResult(getId(), batchResults);
-
- // move the position on
- updatePosition(totalRows, queryResult);
-
- if (logger.isDebugEnabled())
- logger.debug("After getNextResultsBatch: " + toString());
- }
- finally
- {
- if (searchResults != null)
- {
- searchResults.close();
- }
- }
- }
-
- return queryResult;
- }
-
- /**
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString()
- {
- StringBuilder builder = new StringBuilder(super.toString());
- builder.append(" (id=").append(getId());
- builder.append(" batchSize=").append(this.batchSize);
- builder.append(" position=").append(this.position);
- builder.append(" store=").append(this.store.getScheme()).append(":").append(this.store.getAddress());
- builder.append(" language=").append(this.query.getLanguage());
- builder.append(" statement=").append(this.query.getStatement());
- builder.append(")");
- return builder.toString();
- }
-}
diff --git a/source/java/org/alfresco/repo/webservice/repository/SearchQuery.java b/source/java/org/alfresco/repo/webservice/repository/SearchQuery.java
new file mode 100644
index 0000000000..d5bc6c18d8
--- /dev/null
+++ b/source/java/org/alfresco/repo/webservice/repository/SearchQuery.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2005-2007 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.webservice.repository;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.alfresco.repo.webservice.AbstractQuery;
+import org.alfresco.repo.webservice.Utils;
+import org.alfresco.repo.webservice.types.NamedValue;
+import org.alfresco.repo.webservice.types.Query;
+import org.alfresco.repo.webservice.types.ResultSet;
+import org.alfresco.repo.webservice.types.ResultSetRow;
+import org.alfresco.repo.webservice.types.ResultSetRowNode;
+import org.alfresco.repo.webservice.types.Store;
+import org.alfresco.service.ServiceRegistry;
+import org.alfresco.service.cmr.dictionary.DictionaryService;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.repository.Path;
+import org.alfresco.service.cmr.repository.StoreRef;
+import org.alfresco.service.cmr.search.SearchService;
+import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.service.namespace.QName;
+
+/**
+ * A query to using full search.
+ *
+ * @author Derek Hulley
+ * @since 2.1
+ */
+public class SearchQuery extends AbstractQuery
+{
+ private static final long serialVersionUID = 5429510102265380433L;
+
+ private Store store;
+ private Query query;
+
+ /**
+ * @param node The node to query against
+ * @param association The association type to query or null to query all
+ */
+ public SearchQuery(Store store, Query query)
+ {
+ this.store = store;
+ this.query = query;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("SearchQuery")
+ .append("[ store=").append(this.store.getScheme()).append(":").append(this.store.getAddress())
+ .append(" language=").append(this.query.getLanguage())
+ .append(" statement=").append(this.query.getStatement())
+ .append("]");
+ return sb.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ResultSet execute(ServiceRegistry serviceRegistry)
+ {
+ SearchService searchService = serviceRegistry.getSearchService();
+ NodeService nodeService = serviceRegistry.getNodeService();
+ DictionaryService dictionaryService = serviceRegistry.getDictionaryService();
+
+ // handle the special search string of * meaning, get everything
+ String statement = query.getStatement();
+ if (statement.equals("*"))
+ {
+ statement = "ISNODE:*";
+ }
+ org.alfresco.service.cmr.search.ResultSet searchResults = null;
+ try
+ {
+ StoreRef storeRef = Utils.convertToStoreRef(store);
+ searchResults = searchService.query(storeRef, query.getLanguage(), statement);
+ return convert(
+ nodeService,
+ dictionaryService,
+ searchResults);
+ }
+ finally
+ {
+ if (searchResults != null)
+ {
+ try
+ {
+ searchResults.close();
+ }
+ catch (Throwable e)
+ {
+ }
+ }
+ }
+ }
+
+ private ResultSet convert(
+ NodeService nodeService,
+ DictionaryService dictionaryService,
+ org.alfresco.service.cmr.search.ResultSet searchResults)
+ {
+ ResultSet results = new ResultSet();
+ List rowsList = new ArrayList();
+
+ int index = 0;
+ for (org.alfresco.service.cmr.search.ResultSetRow searchRow : searchResults)
+ {
+ NodeRef nodeRef = searchRow.getNodeRef();
+ // Search can return nodes that no longer exist, so we need to ignore these
+ if (!nodeService.exists(nodeRef))
+ {
+ continue;
+ }
+ ResultSetRowNode rowNode = createResultSetRowNode(nodeRef, nodeService);
+
+ // get the data for the row and build up the columns structure
+ Map values = searchRow.getValues();
+ NamedValue[] columns = new NamedValue[values.size() + 1];
+ int col = 0;
+ for (Path path : values.keySet())
+ {
+ // Get the attribute QName from the result path
+ String attributeName = path.last().toString();
+ if (attributeName.startsWith("@") == true)
+ {
+ attributeName = attributeName.substring(1);
+ }
+ columns[col] = Utils.createNamedValue(dictionaryService, QName.createQName(attributeName), values.get(path));
+ col++;
+ }
+
+ // add one extra column for the node's path
+ columns[col] = Utils.createNamedValue(dictionaryService, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "path"), nodeService.getPath(nodeRef).toString());
+
+ ResultSetRow row = new org.alfresco.repo.webservice.types.ResultSetRow();
+ row.setColumns(columns);
+ row.setScore(searchRow.getScore());
+ row.setRowIndex(index);
+ row.setNode(rowNode);
+
+ // add the row to the overall results list
+ rowsList.add(row);
+ index++;
+ }
+
+ // Convert list to array
+ int totalRows = rowsList.size();
+ ResultSetRow[] rows = rowsList.toArray(new org.alfresco.repo.webservice.types.ResultSetRow[totalRows]);
+
+ // add the rows to the result set and set the total row count
+ results.setRows(rows);
+ results.setTotalRowCount(totalRows);
+
+ return results;
+ }
+}
\ No newline at end of file
diff --git a/source/java/web-services-application-context.xml b/source/java/web-services-application-context.xml
index 392a2a95b5..b27e8d565c 100644
--- a/source/java/web-services-application-context.xml
+++ b/source/java/web-services-application-context.xml
@@ -10,28 +10,6 @@
-
-
-
-
-
- webservice.QuerySessionCache
-
-
-
-
-
-
-
-
-
-
- webservice.UserQuerySessionCache
-
-
-
-
-
@@ -63,6 +41,9 @@
+
+
+
@@ -79,7 +60,7 @@
-
+
@@ -210,6 +191,9 @@
+
+
+
@@ -229,7 +213,7 @@
-
+