diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/solr/getNodes.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/getNodes.get.desc.xml
new file mode 100644
index 0000000000..e13345fe5d
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/getNodes.get.desc.xml
@@ -0,0 +1,8 @@
+
+ Get the nodes in the given transactions
+ Get the nodes updated/deleted in the given transactions.
+ /api/solr/nodes?txnIds={txnIds}&{fromNodeId?}&{toNodeId?}&{count?}
+ argument
+ admin
+ required
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/solr/getNodes.get.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/getNodes.get.json.ftl
new file mode 100644
index 0000000000..326c334e6c
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/getNodes.get.json.ftl
@@ -0,0 +1,11 @@
+<#import "solr.lib.ftl" as solrLib/>
+{
+ "nodes" :
+ [
+ <#list nodes as node>
+ <@solrLib.nodeJSON node=node/>
+ <#if node_has_next>,#if>
+ #list>
+ ],
+ "count": ${count}
+}
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/solr/getTransactions.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/getTransactions.get.desc.xml
new file mode 100644
index 0000000000..571da798db
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/getTransactions.get.desc.xml
@@ -0,0 +1,8 @@
+
+ Get transactions
+ Get the transactions from the given commit time.
+ /api/solr/transactions?fromCommitTime={fromCommitTime}
+ argument
+ admin
+ required
+
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/solr/getTransactions.get.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/getTransactions.get.json.ftl
new file mode 100644
index 0000000000..8adfc6aa3d
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/getTransactions.get.json.ftl
@@ -0,0 +1,10 @@
+<#import "solr.lib.ftl" as solrLib/>
+{
+ "transactions" :
+ [
+ <#list transactions as txn>
+ <@solrLib.transactionJSON txn=txn/>
+ <#if txn_has_next>,#if>
+ #list>
+ ]
+}
\ No newline at end of file
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/solr/solr.lib.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/solr.lib.ftl
new file mode 100644
index 0000000000..552aa77c9a
--- /dev/null
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/solr/solr.lib.ftl
@@ -0,0 +1,16 @@
+<#macro transactionJSON txn>
+{
+ "id": "${txn.id?c}",
+ "commitTimeMs": "${txn.commitTimeMs?c}",
+ "updates": "${txn.updates?c}",
+ "deletes": "${txn.deletes?c}"
+}
+#macro>
+
+<#macro nodeJSON node>
+{
+ "nodeID": "${node.id?c}",
+ "txnID": "${node.transaction.id?c}",
+ "deleted": "${node.deleted?string}"
+}
+#macro>
\ No newline at end of file
diff --git a/config/alfresco/web-scripts-application-context.xml b/config/alfresco/web-scripts-application-context.xml
index 2fce714baa..329290e6e3 100644
--- a/config/alfresco/web-scripts-application-context.xml
+++ b/config/alfresco/web-scripts-application-context.xml
@@ -1176,4 +1176,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/java/org/alfresco/repo/web/scripts/solr/GetNodes.java b/source/java/org/alfresco/repo/web/scripts/solr/GetNodes.java
new file mode 100644
index 0000000000..da1b403a1f
--- /dev/null
+++ b/source/java/org/alfresco/repo/web/scripts/solr/GetNodes.java
@@ -0,0 +1,155 @@
+package org.alfresco.repo.web.scripts.solr;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.alfresco.repo.domain.node.Node;
+import org.alfresco.repo.domain.solr.NodeParameters;
+import org.alfresco.repo.domain.solr.SOLRDAO;
+import org.alfresco.repo.domain.solr.SOLRDAO.NodeQueryCallback;
+import org.alfresco.service.namespace.QName;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.extensions.webscripts.DeclarativeWebScript;
+import org.springframework.extensions.webscripts.Status;
+import org.springframework.extensions.webscripts.WebScriptException;
+import org.springframework.extensions.webscripts.WebScriptRequest;
+
+/**
+ * Support for SOLR. Get a list of nodes in the given transactions.
+ *
+ * Supports fromNodeId, toNodeId, count (all optional) to control the number of nodes returned
+ * e.g. (null, null, 1000) will return at most 1000 nodes starting from the first node in the first transaction.
+ * e.g. (1234, null, 1000) will return at most 1000 nodes starting from the node id 1234.
+ *
+ * @since 4.0
+ */
+public class GetNodes extends DeclarativeWebScript
+{
+ protected static final Log logger = LogFactory.getLog(GetNodes.class);
+
+ private SOLRDAO solrDAO;
+
+ /**
+ * @param solrDAO the solrDAO to set
+ */
+ public void setSolrDAO(SOLRDAO solrDAO)
+ {
+ this.solrDAO = solrDAO;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.Status)
+ */
+ @Override
+ protected Map executeImpl(WebScriptRequest req, Status status)
+ {
+ String txnIdsString = req.getParameter("txnIds");
+ if(txnIdsString == null)
+ {
+ throw new WebScriptException("txnIds parameter is required for GetNodes");
+ }
+
+ String param = req.getParameter("fromNodeId");
+ Long fromNodeId = (param == null ? null : Long.valueOf(param));
+
+ param = req.getParameter("toNodeId");
+ Long toNodeId = (param == null ? null : Long.valueOf(param));
+
+ param = req.getParameter("excludeAspects");
+ Set excludeAspects = null;
+ if(param != null)
+ {
+ String[] excludeAspectsStrings = param.split(",");
+ excludeAspects = new HashSet(excludeAspectsStrings.length);
+ for(String excludeAspect : excludeAspectsStrings)
+ {
+ excludeAspects.add(QName.createQName(excludeAspect.trim()));
+ }
+ }
+
+ param = req.getParameter("includeAspects");
+ Set includeAspects = null;
+ if(param != null)
+ {
+ String[] includeAspectsStrings = param.split(",");
+ includeAspects = new HashSet(includeAspectsStrings.length);
+ for(String includeAspect : includeAspectsStrings)
+ {
+ includeAspects.add(QName.createQName(includeAspect.trim()));
+ }
+ }
+
+ param = req.getParameter("maxResults");
+ int maxResults = (param == null ? 0 : Integer.valueOf(param));
+
+ param = req.getParameter("storeProtocol");
+ String storeProtocol = param;
+
+ param = req.getParameter("storeIdentifier");
+ String storeIdentifier = param;
+
+ String[] txnIdStrings = txnIdsString.split(",");
+ List txnIds = new ArrayList(txnIdStrings.length);
+ for(String txnIdString : txnIdStrings)
+ {
+ txnIds.add(Long.valueOf(txnIdString.trim()));
+ }
+
+ WebNodeQueryCallback nodeQueryCallback = new WebNodeQueryCallback(maxResults);
+ NodeParameters nodeParameters = new NodeParameters();
+ nodeParameters.setTransactionIds(txnIds);
+ nodeParameters.setFromNodeId(fromNodeId);
+ nodeParameters.setToNodeId(toNodeId);
+ nodeParameters.setExcludeAspects(excludeAspects);
+ nodeParameters.setIncludeAspects(includeAspects);
+ nodeParameters.setStoreProtocol(storeProtocol);
+ nodeParameters.setStoreIdentifier(storeIdentifier);
+ solrDAO.getNodes(nodeParameters, maxResults, nodeQueryCallback);
+
+ Map model = new HashMap(2, 1.0f);
+ List nodes = nodeQueryCallback.getNodes();
+ model.put("nodes", nodes);
+ model.put("count", nodes.size());
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Result: \n\tRequest: " + req + "\n\tModel: " + model);
+ }
+
+ return model;
+ }
+
+ /**
+ *
+ *
+ */
+ private static class WebNodeQueryCallback implements NodeQueryCallback
+ {
+ private ArrayList nodes;
+
+ public WebNodeQueryCallback(int count) {
+ super();
+ nodes = new ArrayList(count == 0 || count == Integer.MAX_VALUE ? 100 : count);
+ }
+
+ @Override
+ public boolean handleNode(Node node) {
+ nodes.add(node);
+
+ // continue - get next node
+ return true;
+ }
+
+ public List getNodes()
+ {
+ return nodes;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/web/scripts/solr/GetTransactions.java b/source/java/org/alfresco/repo/web/scripts/solr/GetTransactions.java
new file mode 100644
index 0000000000..7be5548aa3
--- /dev/null
+++ b/source/java/org/alfresco/repo/web/scripts/solr/GetTransactions.java
@@ -0,0 +1,63 @@
+package org.alfresco.repo.web.scripts.solr;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.alfresco.repo.domain.solr.SOLRDAO;
+import org.alfresco.repo.domain.solr.Transaction;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.extensions.webscripts.DeclarativeWebScript;
+import org.springframework.extensions.webscripts.Status;
+import org.springframework.extensions.webscripts.WebScriptException;
+import org.springframework.extensions.webscripts.WebScriptRequest;
+
+/**
+ * Support for SOLR. Get a list of transactions with a commit time greater than or equal to the given parameter.
+ *
+ * @since 4.0
+ */
+public class GetTransactions extends DeclarativeWebScript
+{
+ protected static final Log logger = LogFactory.getLog(GetTransactions.class);
+
+ private SOLRDAO solrDAO;
+
+ /**
+ * @param solrDAO the SOLDAO to set
+ */
+ public void setSolrDAO(SOLRDAO solrDAO)
+ {
+ this.solrDAO = solrDAO;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.Status)
+ */
+ @Override
+ protected Map executeImpl(WebScriptRequest req, Status status)
+ {
+ String minTxnIdParam = req.getParameter("minTxnId");
+ String fromCommitTimeParam = req.getParameter("fromCommitTime");
+ String maxResultsParam = req.getParameter("maxResults");
+
+ Long minTxnId = (minTxnIdParam == null ? null : Long.valueOf(minTxnIdParam));
+ Long fromCommitTime = (fromCommitTimeParam == null ? null : Long.valueOf(fromCommitTimeParam));
+ int maxResults = (maxResultsParam == null ? 0 : Integer.valueOf(maxResultsParam));
+
+ List transactions = solrDAO.getTransactions(minTxnId, fromCommitTime, maxResults);
+
+ Map model = new HashMap(1, 1.0f);
+ model.put("transactions", transactions);
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Result: \n\tRequest: " + req + "\n\tModel: " + model);
+ }
+
+ return model;
+ }
+
+}
diff --git a/source/java/org/alfresco/repo/web/scripts/solr/SOLRWebScriptTest.java b/source/java/org/alfresco/repo/web/scripts/solr/SOLRWebScriptTest.java
new file mode 100644
index 0000000000..839179cd10
--- /dev/null
+++ b/source/java/org/alfresco/repo/web/scripts/solr/SOLRWebScriptTest.java
@@ -0,0 +1,1043 @@
+package org.alfresco.repo.web.scripts.solr;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.domain.node.NodeDAO;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.transaction.RetryingTransactionHelper;
+import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
+import org.alfresco.repo.web.scripts.BaseWebScriptTest;
+import org.alfresco.service.ServiceRegistry;
+import org.alfresco.service.cmr.model.FileFolderService;
+import org.alfresco.service.cmr.model.FileInfo;
+import org.alfresco.service.cmr.repository.ContentService;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.repository.StoreRef;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.service.transaction.TransactionService;
+import org.alfresco.util.Pair;
+import org.alfresco.util.PropertyMap;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.springframework.context.ApplicationContext;
+import org.springframework.extensions.webscripts.Status;
+import org.springframework.extensions.webscripts.TestWebScriptServer;
+import org.springframework.extensions.webscripts.TestWebScriptServer.Response;
+
+/**
+ * Test the SOLR web scripts
+ *
+ * @since 4.0
+ */
+// TODO check txn ids are correct - how to get txn ids?
+// TODO create a node in txn1 and delete it in txn2 - only the delete in txn2 appears. Will SOLR not then see this as deletion of a non-existent node?
+// TODO test getTxns: combinations of fromTxnId, fromCommitTime, maxResults
+// TODO move/duplicate tests to SOLRDAO tests
+public class SOLRWebScriptTest extends BaseWebScriptTest
+{
+ protected static final Log logger = LogFactory.getLog(SOLRWebScriptTest.class);
+
+ private ApplicationContext ctx;
+ private NodeDAO nodeDAO;
+ private TransactionService transactionService;
+ private NodeService nodeService;
+ private ContentService contentService;
+ private FileFolderService fileFolderService;
+ private RetryingTransactionHelper txnHelper;
+
+ private String admin;
+
+ private StoreRef storeRef;
+ private StoreRef storeRef1;
+ private NodeRef rootNodeRef;
+ private NodeRef rootNodeRef1;
+
+ private NodeRef container1;
+ private NodeRef container2;
+ private NodeRef container3;
+ private NodeRef container4;
+ private NodeRef container5;
+ private NodeRef content1;
+ private NodeRef content2;
+ private NodeRef content3;
+
+ private long container1NodeID;
+ private long container2NodeID;
+ private long container3NodeID;
+ private long container4NodeID;
+ private long container5NodeID;
+ private long content1NodeID;
+ private long content2NodeID;
+ private long content3NodeID;
+ private long content4NodeID;
+ private long content5NodeID;
+
+ private JSONObject firstNode;
+ private JSONObject secondNode;
+ private JSONObject thirdNode;
+
+ private NodeRef[][] contents = new NodeRef[10][100];
+ private Long[][] nodeIDs = new Long[10][100];
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ ctx = getServer().getApplicationContext();
+
+ ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
+ transactionService = serviceRegistry.getTransactionService();
+ nodeService = serviceRegistry.getNodeService();
+ contentService = serviceRegistry.getContentService();
+ fileFolderService = serviceRegistry.getFileFolderService();
+ txnHelper = transactionService.getRetryingTransactionHelper();
+ nodeDAO = (NodeDAO)ctx.getBean("nodeDAO");
+
+ admin = AuthenticationUtil.getAdminUserName();
+
+ AuthenticationUtil.setFullyAuthenticatedUser(admin);
+
+ storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, getName() + ".1." + System.currentTimeMillis());
+ rootNodeRef = nodeService.getRootNode(storeRef);
+
+ storeRef1 = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, getName() + ".2." + System.currentTimeMillis());
+ rootNodeRef1 = nodeService.getRootNode(storeRef1);
+ }
+
+ @Override
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+ }
+
+ private JSONArray getNodes(GetNodesParameters parameters, Integer maxResults) throws Exception
+ {
+ StringBuilder url = new StringBuilder("/api/solr/nodes?txnIds=");
+ url.append(join(parameters.getTransactionIds(), ","));
+ if(parameters.getFromNodeId() != null)
+ {
+ url.append("&fromNodeId=");
+ url.append(parameters.getFromNodeId());
+ }
+ if(parameters.getToNodeId() != null)
+ {
+ url.append("&toNodeId=");
+ url.append(parameters.getToNodeId());
+ }
+ if(parameters.getExcludeAspects() != null)
+ {
+ url.append("&excludeAspects=");
+ Set excludeAspects = parameters.getExcludeAspects();
+ int i = 0;
+ for(QName excludeAspect : excludeAspects)
+ {
+ url.append(excludeAspect.toString());
+ if(i < (excludeAspects.size() - 1))
+ {
+ url.append(",");
+ }
+ i++;
+ }
+ }
+ if(parameters.getIncludeAspects() != null)
+ {
+ url.append("&includeAspects=");
+ Set includeAspects = parameters.getIncludeAspects();
+ int i = 0;
+ for(QName includeAspect : includeAspects)
+ {
+ url.append(includeAspect.toString());
+ if(i < (includeAspects.size() - 1))
+ {
+ url.append(",");
+ }
+ i++;
+ }
+ }
+ if(parameters.getStoreProtocol() != null)
+ {
+ url.append("&storeProtocol=");
+ url.append(parameters.getStoreProtocol());
+ }
+ if(parameters.getStoreIdentifier() != null)
+ {
+ url.append("&storeIdentifier=");
+ url.append(parameters.getStoreIdentifier());
+ }
+ if(maxResults != null)
+ {
+ url.append("&maxResults=");
+ url.append(maxResults);
+ }
+
+ TestWebScriptServer.GetRequest req = new TestWebScriptServer.GetRequest(url.toString());
+ Response response = sendRequest(req, Status.STATUS_OK, admin);
+
+// assertEquals("Expected application/json content type", "application/json[;charset=UTF-8]", response.getContentType());
+
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(response.getContentAsString());
+ }
+
+ JSONObject json = new JSONObject(response.getContentAsString());
+ json.write(new PrintWriter(System.out));
+
+ JSONArray nodes = json.getJSONArray("nodes");
+
+ assertEquals("Node count is incorrect", nodes.length(), json.getInt("count"));
+
+ return nodes;
+ }
+
+ private void buildTransactions1()
+ {
+ txnHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public Void execute() throws Throwable
+ {
+ PropertyMap props = new PropertyMap();
+ props.put(ContentModel.PROP_NAME, "Container1");
+ container1 = nodeService.createNode(
+ rootNodeRef,
+ ContentModel.ASSOC_CHILDREN,
+ ContentModel.ASSOC_CHILDREN,
+ ContentModel.TYPE_FOLDER,
+ props).getChildRef();
+
+ System.out.println("container1 = " + container1);
+
+ FileInfo content1Info = fileFolderService.create(container1, "Content1", ContentModel.TYPE_CONTENT);
+ content1 = content1Info.getNodeRef();
+
+ container1NodeID = getNodeID(container1);
+ content1NodeID = getNodeID(content1);
+
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("content1 = " + content1);
+ }
+
+ return null;
+ }
+ });
+
+ txnHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public Void execute() throws Throwable
+ {
+ FileInfo content2Info = fileFolderService.create(container1, "Content2", ContentModel.TYPE_CONTENT);
+ content2 = content2Info.getNodeRef();
+ content2NodeID = getNodeID(content2);
+
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("content2 = " + content2);
+ }
+
+ nodeService.addAspect(content1, ContentModel.ASPECT_TEMPORARY, null);
+ fileFolderService.delete(content1);
+
+ return null;
+ }
+ });
+ }
+
+ private List getTransactionIds(JSONArray transactions) throws JSONException
+ {
+ List txnIds = new ArrayList(transactions.length());
+
+ int numTxns = transactions.length();
+ for(int i = 0; i < numTxns; i++)
+ {
+ JSONObject txn = transactions.getJSONObject(i);
+ txnIds.add(txn.getLong("id"));
+ }
+
+ return txnIds;
+ }
+
+ public static String join(Collection s, String delimiter) {
+ StringBuffer buffer = new StringBuffer();
+ Iterator iter = s.iterator();
+ while (iter.hasNext()) {
+ buffer.append(iter.next());
+ if (iter.hasNext()) {
+ buffer.append(delimiter);
+ }
+ }
+ return buffer.toString();
+ }
+
+ public void testGetTransactions1() throws Exception
+ {
+ long fromCommitTime = System.currentTimeMillis();
+
+ buildTransactions1();
+
+ String url = "/api/solr/transactions?fromCommitTime=" + fromCommitTime;
+ TestWebScriptServer.GetRequest req = new TestWebScriptServer.GetRequest(url);
+ Response response = sendRequest(req, Status.STATUS_OK, admin);
+
+// assertEquals("Expected application/json content type", "application/json[;charset=UTF-8]", response.getContentType());
+
+ System.out.println(response.getContentAsString());
+ JSONObject json = new JSONObject(response.getContentAsString());
+
+ JSONArray transactions = json.getJSONArray("transactions");
+ assertEquals("Number of transactions is incorrect", 2, transactions.length());
+
+ int[] updates = new int[] {1, 1};
+ int[] deletes = new int[] {0, 1};
+ StringBuilder txnIds = new StringBuilder();
+ int numTxns = transactions.length();
+ List transactionIds = getTransactionIds(transactions);
+ for(int i = 0; i < numTxns; i++)
+ {
+ JSONObject txn = transactions.getJSONObject(i);
+ assertEquals("Number of deletes is incorrect", deletes[i], txn.getLong("deletes"));
+ assertEquals("Number of updates is incorrect", updates[i], txn.getLong("updates"));
+
+// txnIds.append(txn.getString("id"));
+// if(i < (numTxns - 1))
+// {
+// txnIds.append(",");
+// }
+ }
+
+ // get all nodes at once
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("txnIds = " + txnIds.toString());
+ }
+
+ GetNodesParameters parameters = new GetNodesParameters();
+ parameters.setTransactionIds(transactionIds);
+ JSONArray nodes = getNodes(parameters, null);
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("nodes:");
+ logger.debug(nodes.toString(3));
+ }
+ assertEquals("Number of nodes is incorrect", 3, nodes.length());
+
+ JSONObject lastNode = nodes.getJSONObject(2);
+ assertTrue("nodeID is missing", lastNode.has("nodeID"));
+ Long fromNodeId = lastNode.getLong("nodeID");
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("fromNodeId = " + fromNodeId);
+ }
+ assertNotNull("Unexpected null fromNodeId", fromNodeId);
+
+ firstNode = nodes.getJSONObject(0);
+ secondNode = nodes.getJSONObject(1);
+ //assertEquals("Expected transaction ids to be the same", firstNode.getLong("txnID") == secondNode.getLong("txnID"));
+ assertEquals("Expected node update", false, firstNode.getBoolean("deleted"));
+ assertEquals("Expected node deleted", true, secondNode.getBoolean("deleted"));
+ assertEquals("Node id is incorrect", container1NodeID, firstNode.getLong("nodeID"));
+ assertEquals("Node id is incorrect", content1NodeID, secondNode.getLong("nodeID"));
+
+ // get first 2 nodes
+ parameters = new GetNodesParameters();
+ parameters.setTransactionIds(transactionIds);
+ nodes = getNodes(parameters, 2);
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("nodes:");
+ logger.debug(nodes.toString(3));
+ }
+ assertEquals("Number of nodes is incorrect", 2, nodes.length());
+
+ lastNode = nodes.getJSONObject(1);
+ assertTrue("nodeID is missing", lastNode.has("nodeID"));
+ fromNodeId = lastNode.getLong("nodeID");
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("fromNodeId = " + fromNodeId);
+ }
+ assertNotNull("Unexpected null fromNodeId", fromNodeId);
+
+ // get 4 nodes starting with fromNodeId, should return only 2 nodes (including fromNodeId)
+ parameters = new GetNodesParameters();
+ parameters.setTransactionIds(transactionIds);
+ parameters.setFromNodeId(fromNodeId);
+ nodes = getNodes(parameters, 4);
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("nodes:");
+ logger.debug(nodes.toString(3));
+ }
+ assertEquals("Number of nodes is incorrect", 2, nodes.length());
+
+ firstNode = nodes.getJSONObject(0);
+ secondNode = nodes.getJSONObject(1);
+ assertEquals("Expected node deleted", true, firstNode.getBoolean("deleted"));
+ assertEquals("Expected node updated", false, secondNode.getBoolean("deleted"));
+ assertEquals("Node id is incorrect", content1NodeID, firstNode.getLong("nodeID"));
+ assertEquals("Node id is incorrect", content2NodeID, secondNode.getLong("nodeID"));
+
+ // get 0 (all) nodes starting with fromNodeId, should return 2 nodes
+ parameters = new GetNodesParameters();
+ parameters.setTransactionIds(transactionIds);
+ parameters.setFromNodeId(fromNodeId);
+ nodes = getNodes(parameters, 0);
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("nodes:");
+ logger.debug(nodes.toString(3));
+ }
+ assertEquals("Number of nodes is incorrect", 2, nodes.length());
+
+ // get 2 nodes ending with toNodeId, should return 2 nodes
+ long toNodeId = content2NodeID;
+ parameters = new GetNodesParameters();
+ parameters.setTransactionIds(transactionIds);
+ parameters.setToNodeId(toNodeId);
+ nodes = getNodes(parameters, 2);
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("nodes:");
+ logger.debug(nodes.toString(3));
+ }
+ assertEquals("Number of nodes is incorrect", 2, nodes.length());
+
+ firstNode = nodes.getJSONObject(0);
+ secondNode = nodes.getJSONObject(1);
+ assertEquals("Expected node deleted", false, firstNode.getBoolean("deleted"));
+ assertEquals("Node id is incorrect", container1NodeID, firstNode.getLong("nodeID"));
+ assertEquals("Expected node updated", true, secondNode.getBoolean("deleted"));
+ assertEquals("Node id is incorrect", content1NodeID, secondNode.getLong("nodeID"));
+
+ // get 1 node ending with toNodeId, should return 1 nodes
+ toNodeId = content2NodeID;
+ parameters = new GetNodesParameters();
+ parameters.setTransactionIds(transactionIds);
+ parameters.setToNodeId(toNodeId);
+ nodes = getNodes(parameters, 1);
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("nodes:");
+ logger.debug(nodes.toString(3));
+ }
+ assertEquals("Number of nodes is incorrect", 1, nodes.length());
+
+ firstNode = nodes.getJSONObject(0);
+ assertEquals("Expected node updated", false, firstNode.getBoolean("deleted"));
+ assertEquals("Node id is incorrect", container1NodeID, firstNode.getLong("nodeID"));
+
+ // get 3 nodes ending with toNodeId, should return 3 nodes
+ toNodeId = content2NodeID;
+ parameters = new GetNodesParameters();
+ parameters.setTransactionIds(transactionIds);
+ parameters.setToNodeId(toNodeId);
+ nodes = getNodes(parameters, 3);
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("nodes:");
+ logger.debug(nodes.toString(3));
+ }
+ assertEquals("Number of nodes is incorrect", 3, nodes.length());
+
+ firstNode = nodes.getJSONObject(0);
+ assertEquals("Expected node updated", false, firstNode.getBoolean("deleted"));
+ assertEquals("Node id is incorrect", container1NodeID, firstNode.getLong("nodeID"));
+
+ secondNode = nodes.getJSONObject(1);
+ assertEquals("Expected node deleted", true, secondNode.getBoolean("deleted"));
+ assertEquals("Node id is incorrect", content1NodeID, secondNode.getLong("nodeID"));
+
+ thirdNode = nodes.getJSONObject(2);
+ assertEquals("Expected node updated", false, thirdNode.getBoolean("deleted"));
+ assertEquals("Node id is incorrect", content2NodeID, thirdNode.getLong("nodeID"));
+ }
+
+ private void buildTransactions2()
+ {
+ txnHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public Void execute() throws Throwable
+ {
+ PropertyMap props = new PropertyMap();
+ props.put(ContentModel.PROP_NAME, "Container2");
+ container2 = nodeService.createNode(
+ rootNodeRef,
+ ContentModel.ASSOC_CHILDREN,
+ ContentModel.ASSOC_CHILDREN,
+ ContentModel.TYPE_FOLDER,
+ props).getChildRef();
+ container2NodeID = getNodeID(container2);
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("container2 = " + container2);
+ }
+
+ FileInfo content1Info = fileFolderService.create(container2, "Content1", ContentModel.TYPE_CONTENT);
+ content1 = content1Info.getNodeRef();
+ content1NodeID = getNodeID(content1);
+
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("content1 = " + content1);
+ }
+
+ FileInfo content2Info = fileFolderService.create(container2, "Content2", ContentModel.TYPE_CONTENT);
+ content2 = content2Info.getNodeRef();
+ content2NodeID = getNodeID(content2);
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("content2 = " + content2);
+ }
+
+ return null;
+ }
+ });
+
+ txnHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public Void execute() throws Throwable
+ {
+ FileInfo content3Info = fileFolderService.create(container2, "Content3", ContentModel.TYPE_CONTENT);
+ content3 = content3Info.getNodeRef();
+ content3NodeID = getNodeID(content3);
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("content3 = " + content3);
+ }
+
+ nodeService.addAspect(content1, ContentModel.ASPECT_TEMPORARY, null);
+ fileFolderService.delete(content1);
+
+ nodeService.setProperty(content3, ContentModel.PROP_NAME, "Content 3 New Name");
+
+ return null;
+ }
+ });
+ }
+
+ public void testGetTransactions2() throws Exception
+ {
+ long fromCommitTime = System.currentTimeMillis();
+
+ buildTransactions2();
+
+ String url = "/api/solr/transactions?fromCommitTime=" + fromCommitTime;
+ TestWebScriptServer.GetRequest req = new TestWebScriptServer.GetRequest(url);
+ Response response = sendRequest(req, Status.STATUS_OK, admin);
+
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(response.getContentAsString());
+ }
+ JSONObject json = new JSONObject(response.getContentAsString());
+
+ JSONArray transactions = json.getJSONArray("transactions");
+ assertEquals("Number of transactions is incorrect", 2, transactions.length());
+
+ // first txn has 2 updates rather than three because content1 is deleted in txn 2 and therefore
+ // "belongs" to that txn (because txn2 was the last to alter the node)
+ int[] updates = new int[] {2, 1};
+ int[] deletes = new int[] {0, 1};
+ StringBuilder txnIds = new StringBuilder();
+ int numTxns = transactions.length();
+ for(int i = 0; i < numTxns; i++)
+ {
+ JSONObject txn = transactions.getJSONObject(i);
+ assertEquals("Number of deletes is incorrect", deletes[i], txn.getLong("deletes"));
+ assertEquals("Number of updates is incorrect", updates[i], txn.getLong("updates"));
+
+ txnIds.append(txn.getString("id"));
+ if(i < (numTxns - 1))
+ {
+ txnIds.append(",");
+ }
+ }
+
+ // get all nodes at once
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("txnIds = " + txnIds.toString());
+ }
+
+ List transactionIds = getTransactionIds(transactions);
+
+ // get all nodes in the txns
+ GetNodesParameters parameters = new GetNodesParameters();
+ parameters.setTransactionIds(transactionIds);
+ JSONArray nodes = getNodes(parameters, null);
+ assertEquals("Number of nodes is incorrect", 4, nodes.length());
+ JSONObject lastNode = nodes.getJSONObject(nodes.length() - 1);
+ Long fromNodeId = lastNode.getLong("nodeID");
+ assertNotNull("Unexpected null fromNodeId", fromNodeId);
+
+ // get first 2 nodes
+ parameters = new GetNodesParameters();
+ parameters.setTransactionIds(transactionIds);
+ nodes = getNodes(parameters, 2);
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("nodes:");
+ logger.debug(nodes.toString(3));
+ }
+ assertEquals("Number of nodes is incorrect", 2, nodes.length());
+
+ firstNode = nodes.getJSONObject(0);
+ assertTrue("nodeID is missing", firstNode.has("nodeID"));
+ secondNode = nodes.getJSONObject(1);
+ assertTrue("nodeID is missing", secondNode.has("nodeID"));
+ fromNodeId = secondNode.getLong("nodeID");
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("fromNodeId = " + fromNodeId);
+ }
+ assertNotNull("Unexpected null nodeID", fromNodeId);
+
+ //assertEquals("Expected transaction ids to be the same", firstNode.getLong("txnID"), secondNode.getLong("txnID"));
+ assertEquals("Expected node update", false, firstNode.getBoolean("deleted"));
+ assertEquals("Expected node delete", true, secondNode.getBoolean("deleted"));
+ assertEquals("Incorrect node id", container2NodeID, firstNode.getLong("nodeID"));
+ assertEquals("Incorrect node id", content1NodeID, secondNode.getLong("nodeID"));
+
+ // get 10 nodes (including fromNodeId) starting with fromNodeId, should return only 3 nodes
+ parameters = new GetNodesParameters();
+ parameters.setTransactionIds(transactionIds);
+ parameters.setFromNodeId(fromNodeId);
+ nodes = getNodes(parameters, 10);
+ assertEquals("Number of nodes is incorrect", 3, nodes.length());
+
+ firstNode = nodes.getJSONObject(0);
+ assertTrue("nodeID is missing", firstNode.has("nodeID"));
+ secondNode = nodes.getJSONObject(1);
+ assertTrue("nodeID is missing", secondNode.has("nodeID"));
+ thirdNode = nodes.getJSONObject(2);
+ assertTrue("nodeID is missing", thirdNode.has("nodeID"));
+
+ assertEquals("Expected node delete", true, firstNode.getBoolean("deleted"));
+ assertEquals("Expected node update", false, secondNode.getBoolean("deleted"));
+ assertEquals("Expected node update", false, thirdNode.getBoolean("deleted"));
+ assertEquals("Incorrect node id", content1NodeID, firstNode.getLong("nodeID"));
+ assertEquals("Incorrect node id", content2NodeID, secondNode.getLong("nodeID"));
+ assertEquals("Incorrect node id", content3NodeID, thirdNode.getLong("nodeID"));
+
+ // test with from and to node ids
+ parameters = new GetNodesParameters();
+ parameters.setTransactionIds(transactionIds);
+ parameters.setFromNodeId(container2NodeID);
+ parameters.setToNodeId(content3NodeID);
+ nodes = getNodes(parameters, 2);
+ assertEquals("Number of nodes is incorrect", 2, nodes.length());
+
+ firstNode = nodes.getJSONObject(0);
+ assertTrue("nodeID is missing", firstNode.has("nodeID"));
+ secondNode = nodes.getJSONObject(1);
+ assertTrue("nodeID is missing", secondNode.has("nodeID"));
+ assertEquals("Incorrect node id", container2NodeID, firstNode.getLong("nodeID"));
+ assertEquals("Incorrect node id", content1NodeID, secondNode.getLong("nodeID"));
+
+ // test right truncation
+ parameters = new GetNodesParameters();
+ parameters.setTransactionIds(transactionIds);
+ parameters.setToNodeId(content3NodeID);
+ nodes = getNodes(parameters, 2);
+ assertEquals("Number of nodes is incorrect", 2, nodes.length());
+
+ firstNode = nodes.getJSONObject(0);
+ assertTrue("nodeID is missing", firstNode.has("nodeID"));
+ secondNode = nodes.getJSONObject(1);
+ assertTrue("nodeID is missing", secondNode.has("nodeID"));
+ assertEquals("Incorrect node id", container2NodeID, firstNode.getLong("nodeID"));
+ assertEquals("Incorrect node id", content1NodeID, secondNode.getLong("nodeID"));
+
+ // test left truncation, specifying from node only
+ parameters = new GetNodesParameters();
+ parameters.setTransactionIds(transactionIds);
+ parameters.setFromNodeId(container2NodeID);
+ nodes = getNodes(parameters, 2);
+ assertEquals("Number of nodes is incorrect", 2, nodes.length());
+
+ firstNode = nodes.getJSONObject(0);
+ assertTrue("nodeID is missing", firstNode.has("nodeID"));
+ secondNode = nodes.getJSONObject(1);
+ assertTrue("nodeID is missing", secondNode.has("nodeID"));
+ assertEquals("Incorrect node id", container2NodeID, firstNode.getLong("nodeID"));
+ assertEquals("Incorrect node id", content1NodeID, secondNode.getLong("nodeID"));
+ }
+
+ private void buildTransactions3()
+ {
+ txnHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public Void execute() throws Throwable
+ {
+ PropertyMap props = new PropertyMap();
+ props.put(ContentModel.PROP_NAME, "Container3");
+ container3 = nodeService.createNode(
+ rootNodeRef,
+ ContentModel.ASSOC_CHILDREN,
+ ContentModel.ASSOC_CHILDREN,
+ ContentModel.TYPE_FOLDER,
+ props).getChildRef();
+ container3NodeID = getNodeID(container3);
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("container3 = " + container3);
+ }
+
+ for(int i = 0; i < 100; i++)
+ {
+ FileInfo content1Info = fileFolderService.create(container3, "Content" + i, ContentModel.TYPE_CONTENT);
+ contents[3][i] = content1Info.getNodeRef();
+ nodeIDs[3][i] = getNodeID(contents[3][i]);
+
+ if(i % 2 == 1)
+ {
+ nodeService.addAspect(contents[3][i], ContentModel.ASPECT_TEMPORARY, null);
+ }
+ }
+
+ return null;
+ }
+ });
+ }
+
+ public void testGetNodesExcludeAspects() throws Exception
+ {
+ long fromCommitTime = System.currentTimeMillis();
+
+ buildTransactions3();
+
+ String url = "/api/solr/transactions?fromCommitTime=" + fromCommitTime;
+ TestWebScriptServer.GetRequest req = new TestWebScriptServer.GetRequest(url);
+ Response response = sendRequest(req, Status.STATUS_OK, admin);
+
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(response.getContentAsString());
+ }
+ JSONObject json = new JSONObject(response.getContentAsString());
+
+ JSONArray transactions = json.getJSONArray("transactions");
+ assertEquals("Number of transactions is incorrect", 1, transactions.length());
+
+ // first txn has 2 updates rather than three because content1 is deleted in txn 2 and therefore
+ // "belongs" to that txn (because txn2 was the last to alter the node)
+
+ List transactionIds = getTransactionIds(transactions);
+
+ Set excludeAspects = new HashSet(1);
+ excludeAspects.add(ContentModel.ASPECT_TEMPORARY);
+
+ // get all nodes, exclude nodes with temporary aspect
+ GetNodesParameters parameters = new GetNodesParameters();
+ parameters.setTransactionIds(transactionIds);
+ parameters.setExcludeAspects(excludeAspects);
+ JSONArray nodes = getNodes(parameters, 0);
+ assertEquals("Number of nodes is incorrect", 51, nodes.length());
+ }
+
+ private void buildTransactions4()
+ {
+ txnHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public Void execute() throws Throwable
+ {
+ PropertyMap props = new PropertyMap();
+ props.put(ContentModel.PROP_NAME, "Container4");
+ container4 = nodeService.createNode(
+ rootNodeRef,
+ ContentModel.ASSOC_CHILDREN,
+ ContentModel.ASSOC_CHILDREN,
+ ContentModel.TYPE_FOLDER,
+ props).getChildRef();
+ container4NodeID = getNodeID(container4);
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("container4 = " + container4);
+ }
+
+ for(int i = 0; i < 100; i++)
+ {
+ FileInfo content1Info = fileFolderService.create(container4, "Content" + i, ContentModel.TYPE_CONTENT);
+ contents[4][i] = content1Info.getNodeRef();
+ nodeIDs[4][i] = getNodeID(contents[4][i]);
+
+ if(i % 2 == 1)
+ {
+ nodeService.addAspect(contents[4][i], ContentModel.ASPECT_TEMPORARY, null);
+ }
+ }
+
+ return null;
+ }
+ });
+
+ txnHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public Void execute() throws Throwable
+ {
+ PropertyMap props = new PropertyMap();
+ props.put(ContentModel.PROP_NAME, "Container5");
+ container5 = nodeService.createNode(
+ rootNodeRef1,
+ ContentModel.ASSOC_CHILDREN,
+ ContentModel.ASSOC_CHILDREN,
+ ContentModel.TYPE_FOLDER,
+ props).getChildRef();
+ container5NodeID = getNodeID(container5);
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("container5 = " + container5);
+ }
+
+ for(int i = 0; i < 100; i++)
+ {
+ FileInfo content1Info = fileFolderService.create(container5, "Content" + i, ContentModel.TYPE_CONTENT);
+ contents[5][i] = content1Info.getNodeRef();
+ nodeIDs[5][i] = getNodeID(contents[5][i]);
+
+ if(i % 2 == 1)
+ {
+ nodeService.addAspect(contents[5][i], ContentModel.ASPECT_TEMPORARY, null);
+ }
+ }
+
+ return null;
+ }
+ });
+ }
+
+ public void testGetNodesStoreName() throws Exception
+ {
+ long fromCommitTime = System.currentTimeMillis();
+
+ buildTransactions4();
+
+ String url = "/api/solr/transactions?fromCommitTime=" + fromCommitTime;
+ TestWebScriptServer.GetRequest req = new TestWebScriptServer.GetRequest(url);
+ Response response = sendRequest(req, Status.STATUS_OK, admin);
+
+ if(logger.isDebugEnabled())
+ {
+ logger.debug(response.getContentAsString());
+ }
+ JSONObject json = new JSONObject(response.getContentAsString());
+
+ JSONArray transactions = json.getJSONArray("transactions");
+ assertEquals("Number of transactions is incorrect", 2, transactions.length());
+
+ // first txn has 2 updates rather than three because content1 is deleted in txn 2 and therefore
+ // "belongs" to that txn (because txn2 was the last to alter the node)
+
+ List transactionIds = getTransactionIds(transactions);
+
+ // exact store name
+ GetNodesParameters parameters = new GetNodesParameters();
+ parameters.setTransactionIds(transactionIds);
+ parameters.setStoreProtocol(storeRef.getProtocol());
+ parameters.setStoreIdentifier(storeRef.getIdentifier());
+ JSONArray nodes = getNodes(parameters, 0);
+ assertEquals("Number of nodes is incorrect", 101, nodes.length());
+
+ nodes = getNodes(parameters, 50);
+ assertEquals("Number of nodes is incorrect", 50, nodes.length());
+
+ // store protocol
+ parameters = new GetNodesParameters();
+ parameters.setTransactionIds(transactionIds);
+ parameters.setStoreProtocol(storeRef.getProtocol());
+ nodes = getNodes(parameters, 0);
+ assertEquals("Number of nodes is incorrect", 202, nodes.length());
+
+ // store identifier
+ parameters = new GetNodesParameters();
+ parameters.setTransactionIds(transactionIds);
+ parameters.setStoreIdentifier(storeRef.getIdentifier());
+ nodes = getNodes(parameters, 0);
+ assertEquals("Number of nodes is incorrect", 101, nodes.length());
+ }
+
+/* private void buildTransactions3()
+ {
+ txnHelper.doInTransaction(new RetryingTransactionCallback()
+ {
+ public Void execute() throws Throwable
+ {
+ PropertyMap props = new PropertyMap();
+ props.put(ContentModel.PROP_NAME, "Container1");
+ container3 = nodeService.createNode(
+ rootNodeRef,
+ ContentModel.ASSOC_CHILDREN,
+ ContentModel.ASSOC_CHILDREN,
+ ContentModel.TYPE_FOLDER,
+ props).getChildRef();
+
+ System.out.println("container1 = " + container1);
+
+ FileInfo content1Info = fileFolderService.create(container3, "Content1", ContentModel.TYPE_CONTENT);
+ content1 = content1Info.getNodeRef();
+
+ container3NodeID = getNodeID(container3);
+ content1NodeID = getNodeID(content1);
+
+ ContentWriter writer = contentService.getWriter(content1Info.getNodeRef(), ContentModel.PROP_CONTENT, true);
+ writer.putContent("test content");
+
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("content1 = " + content1);
+ }
+
+ return null;
+ }
+ });
+ }
+
+ public void testGetContent() throws Exception
+ {
+ long nodeId = -1l;
+ String propertyName = ContentModel.PROP_CONTENT.toString();
+
+ buildTransactions3();
+
+ String url = "/api/solr/content?nodeId=" + nodeId + "&propertyName=" + propertyName;
+ TestWebScriptServer.GetRequest req = new TestWebScriptServer.GetRequest(url);
+ Response response = sendRequest(req, Status.STATUS_OK, admin);
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("content1 = " + response.getContentAsString());
+ }
+
+ assertEquals("Content length is incorrect", "test content".length(), response.getContentLength());
+
+ }*/
+
+ private long getNodeID(NodeRef nodeRef)
+ {
+ Pair pair = nodeDAO.getNodePair(nodeRef);
+ assertNotNull("Can't find node " + nodeRef, pair);
+ return pair.getFirst();
+ }
+
+ private static class GetNodesParameters
+ {
+ private List transactionIds;
+ private Long fromNodeId;
+ private Long toNodeId;
+
+ private String storeProtocol;
+ private String storeIdentifier;
+
+ private Set includeNodeTypes;
+ private Set excludeNodeTypes;
+
+ private Set includeAspects;
+ private Set excludeAspects;
+
+ public boolean getStoreFilter()
+ {
+ return (storeProtocol != null || storeIdentifier != null);
+ }
+
+ public void setStoreProtocol(String storeProtocol)
+ {
+ this.storeProtocol = storeProtocol;
+ }
+
+ public String getStoreProtocol()
+ {
+ return storeProtocol;
+ }
+
+ public void setStoreIdentifier(String storeIdentifier)
+ {
+ this.storeIdentifier = storeIdentifier;
+ }
+
+ public String getStoreIdentifier()
+ {
+ return storeIdentifier;
+ }
+
+ public void setTransactionIds(List txnIds)
+ {
+ this.transactionIds = txnIds;
+ }
+
+ public List getTransactionIds()
+ {
+ return transactionIds;
+ }
+
+ public Long getFromNodeId()
+ {
+ return fromNodeId;
+ }
+
+ public void setFromNodeId(Long fromNodeId)
+ {
+ this.fromNodeId = fromNodeId;
+ }
+
+ public Long getToNodeId()
+ {
+ return toNodeId;
+ }
+
+ public void setToNodeId(Long toNodeId)
+ {
+ this.toNodeId = toNodeId;
+ }
+
+ public Set getIncludeNodeTypes()
+ {
+ return includeNodeTypes;
+ }
+
+ public Set getExcludeNodeTypes()
+ {
+ return excludeNodeTypes;
+ }
+
+ public Set getIncludeAspects()
+ {
+ return includeAspects;
+ }
+
+ public Set getExcludeAspects()
+ {
+ return excludeAspects;
+ }
+
+ public void setIncludeNodeTypes(Set includeNodeTypes)
+ {
+ this.includeNodeTypes = includeNodeTypes;
+ }
+
+ public void setExcludeNodeTypes(Set excludeNodeTypes)
+ {
+ this.excludeNodeTypes = excludeNodeTypes;
+ }
+
+ public void setIncludeAspects(Set includeAspects)
+ {
+ this.includeAspects = includeAspects;
+ }
+
+ public void setExcludeAspects(Set excludeAspects)
+ {
+ this.excludeAspects = excludeAspects;
+ }
+
+ }
+}
\ No newline at end of file