mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged SWIFT to HEAD
25250: SWIFT branch moved to 4.0.0 schema 5000 25435: Initial checkin for ALF-7069 25450: ALF-7069: - add maxResults to SOLR DAO - refactoring 25480: ALF-7069: further enhancements + unit tests - include/exclude aspects, store protocol + identifier git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@27999 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -253,4 +253,9 @@
|
|||||||
<property name="controlDAO" ref="controlDAO"/>
|
<property name="controlDAO" ref="controlDAO"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="solrDAO" class="org.alfresco.repo.domain.solr.ibatis.SOLRDAOImpl" init-method="init">
|
||||||
|
<property name="sqlMapClientTemplate" ref="solrSqlMapClientTemplate"/>
|
||||||
|
<property name="qNameDAO" ref="qnameDAO"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
@@ -41,6 +41,7 @@
|
|||||||
<sqlMap resource="alfresco/ibatis/#resource.dialect#/permissions-insert-SqlMap.xml"/>
|
<sqlMap resource="alfresco/ibatis/#resource.dialect#/permissions-insert-SqlMap.xml"/>
|
||||||
<sqlMap resource="alfresco/ibatis/#resource.dialect#/usage-common-SqlMap.xml"/>
|
<sqlMap resource="alfresco/ibatis/#resource.dialect#/usage-common-SqlMap.xml"/>
|
||||||
<sqlMap resource="alfresco/ibatis/#resource.dialect#/usage-insert-SqlMap.xml"/>
|
<sqlMap resource="alfresco/ibatis/#resource.dialect#/usage-insert-SqlMap.xml"/>
|
||||||
|
<sqlMap resource="alfresco/ibatis/#resource.dialect#/solr-common-SqlMap.xml"/>
|
||||||
|
|
||||||
<!-- Canned queries -->
|
<!-- Canned queries -->
|
||||||
<sqlMap resource="alfresco/ibatis/#resource.dialect#/query-test-common-SqlMap.xml"/>
|
<sqlMap resource="alfresco/ibatis/#resource.dialect#/query-test-common-SqlMap.xml"/>
|
||||||
|
@@ -78,5 +78,7 @@
|
|||||||
<bean id="avmSqlMapClientTemplate" class="org.springframework.orm.ibatis.SqlMapClientTemplate">
|
<bean id="avmSqlMapClientTemplate" class="org.springframework.orm.ibatis.SqlMapClientTemplate">
|
||||||
<property name="sqlMapClient" ref="alfrescoSqlMapClient"/>
|
<property name="sqlMapClient" ref="alfrescoSqlMapClient"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
<bean id="solrSqlMapClientTemplate" class="org.springframework.orm.ibatis.SqlMapClientTemplate">
|
||||||
|
<property name="sqlMapClient" ref="alfrescoSqlMapClient"/>
|
||||||
|
</bean>
|
||||||
</beans>
|
</beans>
|
||||||
|
@@ -0,0 +1,116 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<!DOCTYPE sqlMap
|
||||||
|
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
|
||||||
|
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
|
||||||
|
|
||||||
|
<sqlMap namespace="alfresco.solr">
|
||||||
|
|
||||||
|
<typeAlias alias="SOLRTransaction" type="org.alfresco.repo.domain.solr.TransactionEntity"/>
|
||||||
|
<typeAlias alias="Node" type="org.alfresco.repo.domain.node.NodeEntity"/>
|
||||||
|
<typeAlias alias="SOLRTransactionParameters" type="org.alfresco.repo.domain.solr.SOLRTransactionParameters"/>
|
||||||
|
<typeAlias alias="NodeParameters" type="org.alfresco.repo.domain.solr.NodeParameters"/>
|
||||||
|
|
||||||
|
<resultMap id="result_Node" class="Node">
|
||||||
|
<result property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
|
<result property="deleted" column="node_deleted" jdbcType="BIT" javaType="java.lang.Boolean" />
|
||||||
|
<result property="transaction.id" column="txn_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<resultMap id="result_Transaction" class="SOLRTransaction">
|
||||||
|
<result property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
|
<result property="commitTimeMs" column="commit_time_ms" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
|
<result property="updates" column="updates" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
|
<result property="deletes" column="deletes" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<select id="select_Txns" parameterClass="SOLRTransactionParameters" resultMap="result_Transaction">
|
||||||
|
select
|
||||||
|
txn.id as id,
|
||||||
|
txn.commit_time_ms as commit_time_ms,
|
||||||
|
(select
|
||||||
|
count(node.id)
|
||||||
|
from
|
||||||
|
alf_node node
|
||||||
|
where
|
||||||
|
txn.id = node.transaction_id and
|
||||||
|
node.node_deleted = 0
|
||||||
|
) as updates,
|
||||||
|
(select
|
||||||
|
count(node.id)
|
||||||
|
from
|
||||||
|
alf_node node
|
||||||
|
where
|
||||||
|
txn.id = node.transaction_id and
|
||||||
|
node.node_deleted = 1
|
||||||
|
) as deletes
|
||||||
|
from
|
||||||
|
alf_transaction txn
|
||||||
|
<dynamic prepend="where">
|
||||||
|
<isNotNull property="txnFromCommitTime" prepend="and">
|
||||||
|
<![CDATA[txn.commit_time_ms >= #txnFromCommitTime#]]>
|
||||||
|
</isNotNull>
|
||||||
|
<isNotNull property="minTxnId" prepend="and">
|
||||||
|
<![CDATA[txn.id >= #minTxnId#]]>
|
||||||
|
</isNotNull>
|
||||||
|
</dynamic>
|
||||||
|
order by txn.commit_time_ms ASC, txn.id ASC
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="select_Txn_Nodes" parameterClass="NodeParameters" resultMap="result_Node">
|
||||||
|
select
|
||||||
|
node.id as id,
|
||||||
|
node.node_deleted as node_deleted,
|
||||||
|
node.transaction_id as txn_id
|
||||||
|
from
|
||||||
|
alf_transaction txn
|
||||||
|
join alf_node node on (txn.id = node.transaction_id)
|
||||||
|
<dynamic>
|
||||||
|
<isEqual property="storeFilter" compareValue="true">
|
||||||
|
join alf_store store on (store.id = node.store_id)
|
||||||
|
</isEqual>
|
||||||
|
</dynamic>
|
||||||
|
<dynamic prepend="where">
|
||||||
|
<isNotNull property="transactionIds" prepend="and">
|
||||||
|
txn.id in <iterate property="transactionIds" open="(" close=")" conjunction=", ">#transactionIds[]#</iterate>
|
||||||
|
</isNotNull>
|
||||||
|
<isNotNull property="fromNodeId" prepend="and">
|
||||||
|
<![CDATA[node.id >= #fromNodeId#]]>
|
||||||
|
</isNotNull>
|
||||||
|
<isNotNull property="toNodeId" prepend="and">
|
||||||
|
<![CDATA[node.id <= #toNodeId#]]>
|
||||||
|
</isNotNull>
|
||||||
|
<isNotNull property="storeProtocol" prepend="and">
|
||||||
|
store.protocol = #storeProtocol#
|
||||||
|
</isNotNull>
|
||||||
|
<isNotNull property="storeIdentifier" prepend="and">
|
||||||
|
store.identifier = #storeIdentifier#
|
||||||
|
</isNotNull>
|
||||||
|
<isNotNull property="includeTypeIds" prepend="and">
|
||||||
|
node.type_qname_id in <iterate property="includeTypeIds" open="(" close=")" conjunction=", ">#includeTypeIds[]#</iterate>
|
||||||
|
</isNotNull>
|
||||||
|
<isNotNull property="excludeTypeIds" prepend="and">
|
||||||
|
node.type_qname_id not in <iterate property="excludeTypeIds" open="(" close=")" conjunction=", ">#excludeTypeIds[]#</iterate>
|
||||||
|
</isNotNull>
|
||||||
|
<isNotNull property="includeAspectIds" prepend="and">
|
||||||
|
exists (
|
||||||
|
select *
|
||||||
|
from alf_node_aspects aspects
|
||||||
|
where
|
||||||
|
aspects.node_id = node.id
|
||||||
|
and aspects.qname_id in <iterate property="includeAspectIds" open="(" close=")" conjunction=", ">#includeAspectIds[]#</iterate>
|
||||||
|
)
|
||||||
|
</isNotNull>
|
||||||
|
<isNotNull property="excludeAspectIds" prepend="and">
|
||||||
|
not exists (
|
||||||
|
select *
|
||||||
|
from alf_node_aspects aspects
|
||||||
|
where
|
||||||
|
aspects.node_id = node.id
|
||||||
|
and aspects.qname_id in <iterate property="excludeAspectIds" open="(" close=")" conjunction=", ">#excludeAspectIds[]#</iterate>
|
||||||
|
)
|
||||||
|
</isNotNull>
|
||||||
|
</dynamic>
|
||||||
|
order by node.id ASC
|
||||||
|
</select>
|
||||||
|
</sqlMap>
|
@@ -4,10 +4,10 @@
|
|||||||
|
|
||||||
# Version label
|
# Version label
|
||||||
|
|
||||||
version.major=3
|
version.major=4
|
||||||
version.minor=5
|
version.minor=0
|
||||||
version.revision=0
|
version.revision=0
|
||||||
version.label=a
|
version.label=
|
||||||
|
|
||||||
# Edition label
|
# Edition label
|
||||||
|
|
||||||
@@ -19,4 +19,4 @@ version.build=@build-number@
|
|||||||
|
|
||||||
# Schema number
|
# Schema number
|
||||||
|
|
||||||
version.schema=4306
|
version.schema=5000
|
||||||
|
167
source/java/org/alfresco/repo/domain/solr/NodeParameters.java
Normal file
167
source/java/org/alfresco/repo/domain/solr/NodeParameters.java
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
package org.alfresco.repo.domain.solr;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores node parameters for use in SOLR DAO queries
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class NodeParameters
|
||||||
|
{
|
||||||
|
private List<Long> transactionIds;
|
||||||
|
private Long fromNodeId;
|
||||||
|
private Long toNodeId;
|
||||||
|
|
||||||
|
private String storeProtocol;
|
||||||
|
private String storeIdentifier;
|
||||||
|
|
||||||
|
private Set<QName> includeNodeTypes;
|
||||||
|
private Set<QName> excludeNodeTypes;
|
||||||
|
private List<Long> includeTypeIds;
|
||||||
|
private List<Long> excludeTypeIds;
|
||||||
|
|
||||||
|
private Set<QName> includeAspects;
|
||||||
|
private Set<QName> excludeAspects;
|
||||||
|
private List<Long> includeAspectIds;
|
||||||
|
private List<Long> excludeAspectIds;
|
||||||
|
|
||||||
|
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<Long> txnIds)
|
||||||
|
{
|
||||||
|
this.transactionIds = txnIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Long> 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<QName> getIncludeNodeTypes()
|
||||||
|
{
|
||||||
|
return includeNodeTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<QName> getExcludeNodeTypes()
|
||||||
|
{
|
||||||
|
return excludeNodeTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<QName> getIncludeAspects()
|
||||||
|
{
|
||||||
|
return includeAspects;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<QName> getExcludeAspects()
|
||||||
|
{
|
||||||
|
return excludeAspects;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIncludeNodeTypes(Set<QName> includeNodeTypes)
|
||||||
|
{
|
||||||
|
this.includeNodeTypes = includeNodeTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExcludeNodeTypes(Set<QName> excludeNodeTypes)
|
||||||
|
{
|
||||||
|
this.excludeNodeTypes = excludeNodeTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIncludeAspects(Set<QName> includeAspects)
|
||||||
|
{
|
||||||
|
this.includeAspects = includeAspects;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExcludeAspects(Set<QName> excludeAspects)
|
||||||
|
{
|
||||||
|
this.excludeAspects = excludeAspects;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Long> getIncludeAspectIds()
|
||||||
|
{
|
||||||
|
return includeAspectIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIncludeAspectIds(List<Long> includeAspectIds)
|
||||||
|
{
|
||||||
|
this.includeAspectIds = includeAspectIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Long> getExcludeAspectIds()
|
||||||
|
{
|
||||||
|
return excludeAspectIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExcludeAspectIds(List<Long> excludeAspectIds)
|
||||||
|
{
|
||||||
|
this.excludeAspectIds = excludeAspectIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Long> getIncludeTypeIds()
|
||||||
|
{
|
||||||
|
return includeTypeIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIncludeTypeIds(List<Long> includeTypeIds)
|
||||||
|
{
|
||||||
|
this.includeTypeIds = includeTypeIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Long> getExcludeTypeIds()
|
||||||
|
{
|
||||||
|
return excludeTypeIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExcludeTypeIds(List<Long> excludeTypeIds)
|
||||||
|
{
|
||||||
|
this.excludeTypeIds = excludeTypeIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
31
source/java/org/alfresco/repo/domain/solr/SOLRDAO.java
Normal file
31
source/java/org/alfresco/repo/domain/solr/SOLRDAO.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package org.alfresco.repo.domain.solr;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.repo.domain.node.Node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DAO support for SOLR web scripts.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
// TODO - permit shortened form of QNames for e.g. aspects i.e. cm:content vs {http://www.alfresco.org/model/content/1.0}content?
|
||||||
|
public interface SOLRDAO
|
||||||
|
{
|
||||||
|
public List<Transaction> getTransactions(Long minTxnId, Long fromCommitTime, int maxResults);
|
||||||
|
public void getNodes(NodeParameters nodeParameters, int maxResults, NodeQueryCallback callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interface that will be used to give query results to the calling code.
|
||||||
|
*/
|
||||||
|
public static interface NodeQueryCallback
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle a node.
|
||||||
|
*
|
||||||
|
* @param node the node
|
||||||
|
* @return Return <tt>true</tt> to continue processing rows or <tt>false</tt> to stop
|
||||||
|
*/
|
||||||
|
boolean handleNode(Node node);
|
||||||
|
}
|
||||||
|
}
|
250
source/java/org/alfresco/repo/domain/solr/SOLRDAOTest.java
Normal file
250
source/java/org/alfresco/repo/domain/solr/SOLRDAOTest.java
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
package org.alfresco.repo.domain.solr;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.domain.node.Node;
|
||||||
|
import org.alfresco.repo.domain.solr.SOLRDAO.NodeQueryCallback;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
|
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.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
|
import org.alfresco.util.ApplicationContextHelper;
|
||||||
|
import org.alfresco.util.PropertyMap;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
|
||||||
|
public class SOLRDAOTest extends TestCase
|
||||||
|
{
|
||||||
|
private ConfigurableApplicationContext ctx = (ConfigurableApplicationContext) ApplicationContextHelper.getApplicationContext();
|
||||||
|
|
||||||
|
private AuthenticationComponent authenticationComponent;
|
||||||
|
private TransactionService transactionService;
|
||||||
|
private RetryingTransactionHelper txnHelper;
|
||||||
|
private NodeService nodeService;
|
||||||
|
private FileFolderService fileFolderService;
|
||||||
|
private SOLRDAO solrDAO;
|
||||||
|
|
||||||
|
private StoreRef storeRef;
|
||||||
|
private NodeRef rootNodeRef;
|
||||||
|
private NodeRef container1;
|
||||||
|
private NodeRef content1;
|
||||||
|
private NodeRef content2;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUp() throws Exception
|
||||||
|
{
|
||||||
|
ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||||
|
transactionService = serviceRegistry.getTransactionService();
|
||||||
|
txnHelper = transactionService.getRetryingTransactionHelper();
|
||||||
|
|
||||||
|
solrDAO = (SOLRDAO)ctx.getBean("solrDAO");
|
||||||
|
nodeService = (NodeService)ctx.getBean("NodeService");
|
||||||
|
fileFolderService = (FileFolderService)ctx.getBean("FileFolderService");
|
||||||
|
authenticationComponent = (AuthenticationComponent)ctx.getBean("authenticationComponent");
|
||||||
|
|
||||||
|
authenticationComponent.setSystemUserAsCurrentUser();
|
||||||
|
|
||||||
|
storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, getName() + System.currentTimeMillis());
|
||||||
|
rootNodeRef = nodeService.getRootNode(storeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildTransactions1()
|
||||||
|
{
|
||||||
|
txnHelper.doInTransaction(new RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
|
||||||
|
System.out.println("content1 = " + content1);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
txnHelper.doInTransaction(new RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
public Void execute() throws Throwable
|
||||||
|
{
|
||||||
|
FileInfo content2Info = fileFolderService.create(container1, "Content2", ContentModel.TYPE_CONTENT);
|
||||||
|
content2 = content2Info.getNodeRef();
|
||||||
|
|
||||||
|
System.out.println("content2 = " + content2);
|
||||||
|
|
||||||
|
fileFolderService.delete(content1);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildTransactions2()
|
||||||
|
{
|
||||||
|
txnHelper.doInTransaction(new RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
|
||||||
|
System.out.println("content1 = " + content1);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
txnHelper.doInTransaction(new RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
public Void execute() throws Throwable
|
||||||
|
{
|
||||||
|
FileInfo content2Info = fileFolderService.create(container1, "Content2", ContentModel.TYPE_CONTENT);
|
||||||
|
content2 = content2Info.getNodeRef();
|
||||||
|
|
||||||
|
System.out.println("content2 = " + content2);
|
||||||
|
|
||||||
|
fileFolderService.delete(content1);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testQueryTransactions1()
|
||||||
|
{
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
buildTransactions1();
|
||||||
|
|
||||||
|
List<Transaction> txns = solrDAO.getTransactions(null, startTime, 0);
|
||||||
|
assertEquals("Number of transactions is incorrect", 2, txns.size());
|
||||||
|
|
||||||
|
int[] updates = new int[] {1, 1};
|
||||||
|
int[] deletes = new int[] {0, 1};
|
||||||
|
List<Long> txnIds = new ArrayList<Long>(txns.size());
|
||||||
|
int i = 0;
|
||||||
|
for(Transaction txn : txns)
|
||||||
|
{
|
||||||
|
assertEquals("Number of deletes is incorrect", deletes[i], txn.getDeletes());
|
||||||
|
assertEquals("Number of updates is incorrect", updates[i], txn.getUpdates());
|
||||||
|
i++;
|
||||||
|
|
||||||
|
txnIds.add(txn.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
TestNodeQueryCallback nodeQueryCallback = new TestNodeQueryCallback(container1, content1, content2);
|
||||||
|
NodeParameters nodeParameters = new NodeParameters();
|
||||||
|
nodeParameters.setTransactionIds(txnIds);
|
||||||
|
solrDAO.getNodes(nodeParameters, 0, nodeQueryCallback);
|
||||||
|
|
||||||
|
assertEquals("Unxpected nodes", 3, nodeQueryCallback.getSuccessCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testQueryTransactions2()
|
||||||
|
{
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
buildTransactions2();
|
||||||
|
|
||||||
|
List<Transaction> txns = solrDAO.getTransactions(null, startTime, 0);
|
||||||
|
assertEquals("Number of transactions is incorrect", 2, txns.size());
|
||||||
|
|
||||||
|
int[] updates = new int[] {1, 1};
|
||||||
|
int[] deletes = new int[] {0, 1};
|
||||||
|
List<Long> txnIds = new ArrayList<Long>(txns.size());
|
||||||
|
int i = 0;
|
||||||
|
for(Transaction txn : txns)
|
||||||
|
{
|
||||||
|
assertEquals("Number of deletes is incorrect", deletes[i], txn.getDeletes());
|
||||||
|
assertEquals("Number of updates is incorrect", updates[i], txn.getUpdates());
|
||||||
|
i++;
|
||||||
|
|
||||||
|
txnIds.add(txn.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
TestNodeQueryCallback nodeQueryCallback = new TestNodeQueryCallback(container1, content1, content2);
|
||||||
|
NodeParameters nodeParameters = new NodeParameters();
|
||||||
|
nodeParameters.setTransactionIds(txnIds);
|
||||||
|
solrDAO.getNodes(nodeParameters, 0, nodeQueryCallback);
|
||||||
|
|
||||||
|
assertEquals("Unxpected nodes", 3, nodeQueryCallback.getSuccessCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static class TestNodeQueryCallback implements NodeQueryCallback
|
||||||
|
{
|
||||||
|
private int successCount = 0;
|
||||||
|
private NodeRef container1;
|
||||||
|
private NodeRef content1;
|
||||||
|
private NodeRef content2;
|
||||||
|
|
||||||
|
public TestNodeQueryCallback(NodeRef container1,
|
||||||
|
NodeRef content1, NodeRef content2) {
|
||||||
|
super();
|
||||||
|
this.container1 = container1;
|
||||||
|
this.content1 = content1;
|
||||||
|
this.content2 = content2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handleNode(Node node) {
|
||||||
|
NodeRef nodeRef = node.getNodeRef();
|
||||||
|
Boolean isDeleted = node.getDeleted();
|
||||||
|
|
||||||
|
System.out.println("Node: " + node.toString());
|
||||||
|
|
||||||
|
if(nodeRef.equals(container1) && !isDeleted)
|
||||||
|
{
|
||||||
|
successCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nodeRef.equals(content1) && isDeleted)
|
||||||
|
{
|
||||||
|
successCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nodeRef.equals(content2) && !isDeleted)
|
||||||
|
{
|
||||||
|
successCount++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSuccessCount()
|
||||||
|
{
|
||||||
|
return successCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,14 @@
|
|||||||
|
package org.alfresco.repo.domain.solr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for SOLR transaction objects.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public interface SOLRTransaction
|
||||||
|
{
|
||||||
|
public Long getId();
|
||||||
|
public Long getCommitTimeMs();
|
||||||
|
public int getUpdates();
|
||||||
|
public int getDeletes();
|
||||||
|
}
|
@@ -0,0 +1,76 @@
|
|||||||
|
package org.alfresco.repo.domain.solr;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds parameters for SOLR DAO calls
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class SOLRTransactionParameters {
|
||||||
|
private Long minTxnId;
|
||||||
|
private Long txnFromCommitTime;
|
||||||
|
private List<Long> transactionIds;
|
||||||
|
private Long fromNodeId;
|
||||||
|
private Long toNodeId;
|
||||||
|
|
||||||
|
public SOLRTransactionParameters()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinTxnId(Long minTxnId)
|
||||||
|
{
|
||||||
|
this.minTxnId = minTxnId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getMinTxnId()
|
||||||
|
{
|
||||||
|
return minTxnId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTxnFromCommitTime(Long txnFromCommitTime) {
|
||||||
|
this.txnFromCommitTime = txnFromCommitTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getTxnFromCommitTime() {
|
||||||
|
return txnFromCommitTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTransactionIds(List<Long> txnIds) {
|
||||||
|
this.transactionIds = txnIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Long> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder(512);
|
||||||
|
sb.append("SOLRTransactionParameters")
|
||||||
|
.append(", txnFromCommitTime").append(txnFromCommitTime == null ? null : new Date(txnFromCommitTime))
|
||||||
|
.append(", fromNodeId").append(fromNodeId == null ? null : fromNodeId)
|
||||||
|
.append(", toNodeId").append(toNodeId == null ? null : toNodeId)
|
||||||
|
.append(", txnIds").append(transactionIds == null ? null : transactionIds.size())
|
||||||
|
.append("]");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
14
source/java/org/alfresco/repo/domain/solr/Transaction.java
Normal file
14
source/java/org/alfresco/repo/domain/solr/Transaction.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package org.alfresco.repo.domain.solr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for SOLR transaction objects.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public interface Transaction
|
||||||
|
{
|
||||||
|
public Long getId();
|
||||||
|
public Long getCommitTimeMs();
|
||||||
|
public int getUpdates();
|
||||||
|
public int getDeletes();
|
||||||
|
}
|
@@ -0,0 +1,75 @@
|
|||||||
|
package org.alfresco.repo.domain.solr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bean to represent SOLR transaction data.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class TransactionEntity implements Transaction
|
||||||
|
{
|
||||||
|
private Long id;
|
||||||
|
private Long commitTimeMs;
|
||||||
|
private int updates;
|
||||||
|
private int deletes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Required default constructor
|
||||||
|
*/
|
||||||
|
public TransactionEntity()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder(512);
|
||||||
|
sb.append("TransactionEntity")
|
||||||
|
.append("[ ID=").append(id)
|
||||||
|
.append(", updates=").append(updates)
|
||||||
|
.append(", deletes=").append(deletes)
|
||||||
|
.append(", commitTimeMs=").append(commitTimeMs)
|
||||||
|
.append("]");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId()
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id)
|
||||||
|
{
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUpdates()
|
||||||
|
{
|
||||||
|
return updates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdates(int updates)
|
||||||
|
{
|
||||||
|
this.updates = updates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDeletes()
|
||||||
|
{
|
||||||
|
return deletes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeletes(int deletes)
|
||||||
|
{
|
||||||
|
this.deletes = deletes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getCommitTimeMs()
|
||||||
|
{
|
||||||
|
return commitTimeMs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCommitTimeMs(Long commitTimeMs)
|
||||||
|
{
|
||||||
|
this.commitTimeMs = commitTimeMs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -0,0 +1,147 @@
|
|||||||
|
package org.alfresco.repo.domain.solr.ibatis;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.alfresco.repo.domain.node.Node;
|
||||||
|
import org.alfresco.repo.domain.node.NodeEntity;
|
||||||
|
import org.alfresco.repo.domain.qname.QNameDAO;
|
||||||
|
import org.alfresco.repo.domain.solr.NodeParameters;
|
||||||
|
import org.alfresco.repo.domain.solr.SOLRDAO;
|
||||||
|
import org.alfresco.repo.domain.solr.SOLRTransactionParameters;
|
||||||
|
import org.alfresco.repo.domain.solr.Transaction;
|
||||||
|
import org.springframework.orm.ibatis.SqlMapClientTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DAO support for SOLR web scripts.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class SOLRDAOImpl implements SOLRDAO
|
||||||
|
{
|
||||||
|
private static final String SELECT_TRANSACTIONS = "alfresco.solr.select_Txns";
|
||||||
|
private static final String SELECT_NODES = "alfresco.solr.select_Txn_Nodes";
|
||||||
|
|
||||||
|
private QNameDAO qnameDAO;
|
||||||
|
private SqlMapClientTemplate template;
|
||||||
|
|
||||||
|
public void setSqlMapClientTemplate(SqlMapClientTemplate sqlMapClientTemplate)
|
||||||
|
{
|
||||||
|
this.template = sqlMapClientTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SqlMapClientTemplate getSqlMapClientTemplate()
|
||||||
|
{
|
||||||
|
return this.template;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setQNameDAO(QNameDAO qnameDAO)
|
||||||
|
{
|
||||||
|
this.qnameDAO = qnameDAO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize
|
||||||
|
*/
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public List<Transaction> getTransactions(Long minTxnId, Long fromCommitTime, int maxResults)
|
||||||
|
{
|
||||||
|
if(minTxnId == null && fromCommitTime == null && (maxResults == 0 || maxResults == Integer.MAX_VALUE))
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Must specify at least one parameter");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Transaction> txns = null;
|
||||||
|
SOLRTransactionParameters params = new SOLRTransactionParameters();
|
||||||
|
params.setMinTxnId(minTxnId);
|
||||||
|
params.setTxnFromCommitTime(fromCommitTime);
|
||||||
|
|
||||||
|
if(maxResults != 0 && maxResults != Integer.MAX_VALUE)
|
||||||
|
{
|
||||||
|
txns = (List<Transaction>)template.queryForList(SELECT_TRANSACTIONS, params, 0, maxResults);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
txns = (List<Transaction>)template.queryForList(SELECT_TRANSACTIONS, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
return txns;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
// TODO should create qnames if don't exist?
|
||||||
|
public void getNodes(NodeParameters nodeParameters, int maxResults, NodeQueryCallback callback)
|
||||||
|
{
|
||||||
|
List<NodeEntity> nodes = null;
|
||||||
|
NodeQueryRowHandler rowHandler = new NodeQueryRowHandler(callback);
|
||||||
|
|
||||||
|
if(nodeParameters.getIncludeTypeIds() == null && nodeParameters.getIncludeNodeTypes() != null)
|
||||||
|
{
|
||||||
|
Set<Long> qnamesIds = qnameDAO.convertQNamesToIds(nodeParameters.getIncludeNodeTypes(), false);
|
||||||
|
nodeParameters.setIncludeTypeIds(new ArrayList<Long>(qnamesIds));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nodeParameters.getExcludeTypeIds() == null && nodeParameters.getExcludeNodeTypes() != null)
|
||||||
|
{
|
||||||
|
Set<Long> qnamesIds = qnameDAO.convertQNamesToIds(nodeParameters.getExcludeNodeTypes(), false);
|
||||||
|
nodeParameters.setExcludeTypeIds(new ArrayList<Long>(qnamesIds));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nodeParameters.getExcludeAspectIds() == null && nodeParameters.getExcludeAspects() != null)
|
||||||
|
{
|
||||||
|
Set<Long> qnamesIds = qnameDAO.convertQNamesToIds(nodeParameters.getExcludeAspects(), false);
|
||||||
|
nodeParameters.setExcludeAspectIds(new ArrayList<Long>(qnamesIds));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nodeParameters.getIncludeAspectIds() == null && nodeParameters.getIncludeAspects() != null)
|
||||||
|
{
|
||||||
|
Set<Long> qnamesIds = qnameDAO.convertQNamesToIds(nodeParameters.getIncludeAspects(), false);
|
||||||
|
nodeParameters.setIncludeAspectIds(new ArrayList<Long>(qnamesIds));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(maxResults != 0 && maxResults != Integer.MAX_VALUE)
|
||||||
|
{
|
||||||
|
nodes = (List<NodeEntity>)template.queryForList(SELECT_NODES, nodeParameters, 0, maxResults);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nodes = (List<NodeEntity>)template.queryForList(SELECT_NODES, nodeParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(NodeEntity node : nodes)
|
||||||
|
{
|
||||||
|
rowHandler.processResult(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that passes results from a result entity into the client callback
|
||||||
|
*/
|
||||||
|
protected class NodeQueryRowHandler
|
||||||
|
{
|
||||||
|
private final NodeQueryCallback callback;
|
||||||
|
private boolean more;
|
||||||
|
|
||||||
|
private NodeQueryRowHandler(NodeQueryCallback callback)
|
||||||
|
{
|
||||||
|
this.callback = callback;
|
||||||
|
this.more = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void processResult(Node row)
|
||||||
|
{
|
||||||
|
if (!more)
|
||||||
|
{
|
||||||
|
// No more results required
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
more = callback.handleNode(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user