diff --git a/config/alfresco/ibatis/org.hibernate.dialect.Dialect/node-common-SqlMap.xml b/config/alfresco/ibatis/org.hibernate.dialect.Dialect/node-common-SqlMap.xml
index 50a33144f7..aa15434089 100644
--- a/config/alfresco/ibatis/org.hibernate.dialect.Dialect/node-common-SqlMap.xml
+++ b/config/alfresco/ibatis/org.hibernate.dialect.Dialect/node-common-SqlMap.xml
@@ -927,11 +927,15 @@
join alf_node_properties prop on (childNode.id = prop.node_id)
where
- parentNode.id = #nodeId#
+ parentNode.id = #parentNodeId#
and prop.qname_id = #propertyQNameId#
and prop.string_value = #value.stringValue#
and prop.double_value = #value.doubleValue#
and prop.long_value = #value.longValue#
+
+ and prop.boolean_value = 1
+ and prop.boolean_value = 0
+
diff --git a/source/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java b/source/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java
index c65a461c53..c2d83aa186 100644
--- a/source/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java
+++ b/source/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java
@@ -2541,9 +2541,11 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
{
switch (nodeValue.getPersistedType())
{
+ case 1: // Boolean
case 3: // long
case 5: // double
case 6: // string
+ // no floats due to the range errors testing equality on a float.
break;
default:
diff --git a/source/java/org/alfresco/repo/domain/node/ChildPropertyEntity.java b/source/java/org/alfresco/repo/domain/node/ChildPropertyEntity.java
index 3a7f0d637b..19a25361a0 100644
--- a/source/java/org/alfresco/repo/domain/node/ChildPropertyEntity.java
+++ b/source/java/org/alfresco/repo/domain/node/ChildPropertyEntity.java
@@ -6,17 +6,17 @@ package org.alfresco.repo.domain.node;
*/
public class ChildPropertyEntity
{
- private Long nodeId;
+ private Long parentNodeId;
private Long propertyQNameId;
private NodePropertyValue value;
- public void setNodeId(Long nodeId)
+ public void setParentNodeId(Long nodeId)
{
- this.nodeId = nodeId;
+ this.parentNodeId = nodeId;
}
- public Long getNodeId()
+ public Long getParentNodeId()
{
- return nodeId;
+ return parentNodeId;
}
public void setPropertyQNameId(Long propertyQNameId)
{
diff --git a/source/java/org/alfresco/repo/domain/node/ibatis/NodeDAOImpl.java b/source/java/org/alfresco/repo/domain/node/ibatis/NodeDAOImpl.java
index 537f39aa37..3a6b4433d1 100644
--- a/source/java/org/alfresco/repo/domain/node/ibatis/NodeDAOImpl.java
+++ b/source/java/org/alfresco/repo/domain/node/ibatis/NodeDAOImpl.java
@@ -1335,8 +1335,9 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
ChildPropertyEntity assocProp = new ChildPropertyEntity();
// Parent
- assocProp.setNodeId(parentNodeId);
+ assocProp.setParentNodeId(parentNodeId);
+ // Property name
Pair propName = qnameDAO.getQName(propertyQName);
if(propName != null)
diff --git a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java
index 68d1d61c3a..38ae3bcd84 100644
--- a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java
+++ b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java
@@ -2222,6 +2222,18 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
}
}
+ private static List getChildAssocsByPropertyValueBannedProps = new ArrayList();
+ static
+ {
+ getChildAssocsByPropertyValueBannedProps.add(ContentModel.PROP_NODE_DBID);
+ getChildAssocsByPropertyValueBannedProps.add(ContentModel.PROP_NODE_UUID);
+ getChildAssocsByPropertyValueBannedProps.add(ContentModel.PROP_NAME);
+ getChildAssocsByPropertyValueBannedProps.add(ContentModel.PROP_MODIFIED);
+ getChildAssocsByPropertyValueBannedProps.add(ContentModel.PROP_MODIFIER);
+ getChildAssocsByPropertyValueBannedProps.add(ContentModel.PROP_CREATED);
+ getChildAssocsByPropertyValueBannedProps.add(ContentModel.PROP_CREATOR);
+ }
+
@Override
public List getChildAssocsByPropertyValue(NodeRef nodeRef,
QName propertyQName,
@@ -2231,6 +2243,13 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
Pair nodePair = getNodePairNotNull(nodeRef);
Long nodeId = nodePair.getFirst();
+ // Check the QName is not one of the "special" system maintained ones.
+
+ if(getChildAssocsByPropertyValueBannedProps.contains(propertyQName))
+ {
+ throw new IllegalArgumentException("getChildAssocsByPropertyValue does not allow search of system maintaied properties: " + propertyQName);
+ }
+
final List results = new ArrayList(10);
// We have a callback handler to filter results
ChildAssocRefQueryCallback callback = new ChildAssocRefQueryCallback()
diff --git a/source/java/org/alfresco/repo/node/db/DbNodeServiceImplTest.java b/source/java/org/alfresco/repo/node/db/DbNodeServiceImplTest.java
index 56b29b9c0f..7aa2a9d018 100644
--- a/source/java/org/alfresco/repo/node/db/DbNodeServiceImplTest.java
+++ b/source/java/org/alfresco/repo/node/db/DbNodeServiceImplTest.java
@@ -425,4 +425,121 @@ public class DbNodeServiceImplTest extends BaseNodeServiceTest
throw e;
}
}
+
+ /**
+ * Test Get Child Assocs By Property Value
+ * @throws Exception
+ */
+ public void testGetChildAssocsByPropertyValue() throws Exception
+ {
+ Map assocRefs;
+
+ assocRefs = buildNodeGraph();
+
+ ChildAssociationRef rootRef = assocRefs.get(QName.createQName(BaseNodeServiceTest.NAMESPACE, "root"));
+ ChildAssociationRef n1Ref = assocRefs.get(QName.createQName(BaseNodeServiceTest.NAMESPACE, "root_p_n1"));
+ ChildAssociationRef n2Ref = assocRefs.get(QName.createQName(BaseNodeServiceTest.NAMESPACE, "root_p_n2"));
+
+ /**
+ * Positive test - get n1 and n2 by the value of a text property in this case PROP_SUBJECT which
+ * contains "Hello World"
+ */
+ {
+ NodeRef parentNodeRef = n1Ref.getParentRef();
+ NodeRef childNodeRef = n1Ref.getChildRef();
+ assertTrue(nodeService.exists(parentNodeRef));
+ assertTrue(nodeService.exists(childNodeRef));
+
+ String subject = "Hello World";
+ nodeService.setProperty(n1Ref.getChildRef(), ContentModel.PROP_SUBJECT, subject);
+ List refs = nodeService.getChildAssocsByPropertyValue(parentNodeRef, ContentModel.PROP_SUBJECT, subject);
+ assertTrue("failed to read one assoc", refs.size() == 1);
+ assertTrue("content not correct", refs.contains(n1Ref));
+
+ // Now go for another two documents.
+ nodeService.setProperty(n2Ref.getChildRef(), ContentModel.PROP_SUBJECT, subject);
+ refs = nodeService.getChildAssocsByPropertyValue(parentNodeRef, ContentModel.PROP_SUBJECT, subject);
+ assertTrue("failed to read two assocs", refs.size() == 2);
+ assertTrue("content not correct", refs.contains(n1Ref));
+ assertTrue("content not correct", refs.contains(n2Ref));
+ }
+
+ /**
+ * Positive tests of various types that should be accepted by the query
+ */
+ {
+ NodeRef parentNodeRef = n1Ref.getParentRef();
+ NodeRef childNodeRef = n1Ref.getChildRef();
+ assertTrue(nodeService.exists(parentNodeRef));
+ assertTrue(nodeService.exists(childNodeRef));
+
+ // integer
+ int count = 123;
+ nodeService.setProperty(n1Ref.getChildRef(), ContentModel.PROP_COUNTER, count);
+ List refs = nodeService.getChildAssocsByPropertyValue(parentNodeRef, ContentModel.PROP_COUNTER, count);
+ assertTrue("failed to read one assoc", refs.size() == 1);
+ assertTrue("content not correct", refs.contains(n1Ref));
+
+ // Double
+ Double alfLat = new Double(51.5216666);
+ Double alfLon = new Double(0.43);
+ nodeService.setProperty(n1Ref.getChildRef(), ContentModel.PROP_LATITUDE, alfLat);
+ refs = nodeService.getChildAssocsByPropertyValue(parentNodeRef, ContentModel.PROP_LATITUDE, alfLat);
+ assertTrue("failed to read one assoc", refs.size() == 1);
+ assertTrue("content not correct", refs.contains(n1Ref));
+
+ // float
+ // not implemeted due to float precision issues with float equals.
+ //float score = 1.3f;
+ //nodeService.setProperty(n1Ref.getChildRef(), ContentModel.PROP_RATING_SCORE, score);
+ //refs = nodeService.getChildAssocsByPropertyValue(parentNodeRef, ContentModel.PROP_RATING_SCORE, score);
+ //assertTrue("failed to read one assoc", refs.size() == 1);
+ //assertTrue("content not correct", refs.contains(n1Ref));
+
+ // Boolean TRUE
+ Boolean beauty = Boolean.TRUE;
+ nodeService.setProperty(n1Ref.getChildRef(), ContentModel.PROP_ENABLED, beauty);
+ assertTrue((Boolean)nodeService.getProperty(n1Ref.getChildRef(), ContentModel.PROP_ENABLED));
+ refs = nodeService.getChildAssocsByPropertyValue(parentNodeRef, ContentModel.PROP_ENABLED, beauty);
+ assertTrue("failed to read one assoc", refs.size() == 1);
+ assertTrue("content not correct", refs.contains(n1Ref));
+
+ // Boolean FALSE
+ beauty = Boolean.FALSE;
+ nodeService.setProperty(n1Ref.getChildRef(), ContentModel.PROP_ENABLED, beauty);
+ assertTrue(!(Boolean)nodeService.getProperty(n1Ref.getChildRef(), ContentModel.PROP_ENABLED));
+ refs = nodeService.getChildAssocsByPropertyValue(parentNodeRef, ContentModel.PROP_ENABLED, beauty);
+ assertTrue("failed to read one assoc", refs.size() == 1);
+
+ }
+
+ /**
+ * Negative test - invalid to search on sys:node-dbid
+ */
+ try
+ {
+ List refs = nodeService.getChildAssocsByPropertyValue(n1Ref.getParentRef(), ContentModel.PROP_NODE_DBID, "Fail");
+ fail("sys:node-dbid not rejected");
+ }
+ catch (IllegalArgumentException ie)
+ {
+ // expect to go here
+ }
+
+ /**
+ * Negative test - invalid to search on type MLText
+ */
+ try
+ {
+ Serializable title = (String)nodeService.getProperty(n1Ref.getChildRef(), ContentModel.PROP_TITLE);
+ List refs = nodeService.getChildAssocsByPropertyValue(n1Ref.getParentRef(), ContentModel.PROP_NAME, title);
+ fail("MLText type not rejected");
+ }
+ catch (IllegalArgumentException ie)
+ {
+ // expect to go here
+ }
+
+
+ }
}