diff --git a/config/alfresco/ibatis/org.hibernate.dialect.Dialect/audit-common-SqlMap.xml b/config/alfresco/ibatis/org.hibernate.dialect.Dialect/audit-common-SqlMap.xml
index 4efa79f994..7a7337f4c3 100644
--- a/config/alfresco/ibatis/org.hibernate.dialect.Dialect/audit-common-SqlMap.xml
+++ b/config/alfresco/ibatis/org.hibernate.dialect.Dialect/audit-common-SqlMap.xml
@@ -46,8 +46,7 @@
+ class="AuditQueryResult">
diff --git a/source/java/org/alfresco/repo/domain/audit/AbstractAuditDAOImpl.java b/source/java/org/alfresco/repo/domain/audit/AbstractAuditDAOImpl.java
index 40ae76eda7..ad4182ab3c 100644
--- a/source/java/org/alfresco/repo/domain/audit/AbstractAuditDAOImpl.java
+++ b/source/java/org/alfresco/repo/domain/audit/AbstractAuditDAOImpl.java
@@ -38,6 +38,7 @@ import org.alfresco.repo.audit.AuditState;
import org.alfresco.repo.audit.hibernate.HibernateAuditDAO;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.domain.contentdata.ContentDataDAO;
+import org.alfresco.repo.domain.propval.PropertyIdSearchRow;
import org.alfresco.repo.domain.propval.PropertyValueDAO;
import org.alfresco.service.cmr.audit.AuditInfo;
import org.alfresco.service.cmr.audit.AuditService.AuditQueryCallback;
@@ -298,15 +299,39 @@ public abstract class AbstractAuditDAOImpl implements AuditDAO
return;
}
// Get the value map
- // TODO: Should be done with a nested resultmapping
- Long auditValuesId = row.getAuditValuesId();
- Pair auditValuesPair = propertyValueDAO.getPropertyValueById(auditValuesId);
- if (auditValuesPair == null)
+ Map auditValues;
+ List propMapRows = row.getAuditValues();
+ if (propMapRows == null)
{
- // Ignore
- return;
+ // Use the audit values ID
+ Long auditValuesId = row.getAuditValuesId();
+ Pair auditValuesPair = propertyValueDAO.getPropertyValueById(auditValuesId);
+ if (auditValuesPair == null)
+ {
+ // Ignore
+ logger.warn("Audit entry not joined to audit properties: " + row);
+ return;
+ }
+ auditValues = (Map) auditValuesPair.getSecond();
+ }
+ else
+ {
+ // Resolve the map
+ try
+ {
+ auditValues = (Map) propertyValueDAO.convertPropertyIdSearchRows(propMapRows);
+ }
+ catch (ClassCastException e)
+ {
+ logger.warn("Audit entry not linked to a Map value: " + row);
+ return;
+ }
+ if (auditValues == null)
+ {
+ logger.warn("Audit entry incompletely joined to audit properties: " + row);
+ return;
+ }
}
- Map auditValues = (Map) auditValuesPair.getSecond();
more = callback.handleAuditEntry(
row.getAuditEntryId(),
row.getAuditAppName(),
diff --git a/source/java/org/alfresco/repo/domain/audit/ibatis/AuditDAOImpl.java b/source/java/org/alfresco/repo/domain/audit/ibatis/AuditDAOImpl.java
index 372978f39a..ed00c30894 100644
--- a/source/java/org/alfresco/repo/domain/audit/ibatis/AuditDAOImpl.java
+++ b/source/java/org/alfresco/repo/domain/audit/ibatis/AuditDAOImpl.java
@@ -29,6 +29,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.alfresco.ibatis.RollupRowHandler;
import org.alfresco.repo.domain.audit.AbstractAuditDAOImpl;
import org.alfresco.repo.domain.audit.AuditApplicationEntity;
import org.alfresco.repo.domain.audit.AuditEntryEntity;
@@ -175,25 +176,38 @@ public class AuditDAOImpl extends AbstractAuditDAOImpl
params.setAuditFromTime(from);
params.setAuditToTime(to);
+ // RowHandlers in RowHandlers: See 'groupBy' issue https://issues.apache.org/jira/browse/IBATIS-503
+ RowHandler shreddedRowHandler = new RowHandler()
+ {
+ public void handleRow(Object valueObject)
+ {
+ rowHandler.processResult((AuditQueryResult)valueObject);
+ }
+ };
+ RollupRowHandler rollupRowHandler = new RollupRowHandler(
+ new String[] {"auditEntryId"},
+ "auditValues",
+ shreddedRowHandler,
+ maxResults);
+
if (maxResults > 0)
{
- List rows = template.queryForList(SELECT_ENTRIES_SIMPLE, params, 0, maxResults);
+ // Calculate the maximum results required
+ int sqlMaxResults = (maxResults > 0 ? ((maxResults+1) * 20) : Integer.MAX_VALUE);
+
+ List rows = template.queryForList(SELECT_ENTRIES_WITH_VALUES, params, 0, sqlMaxResults);
for (AuditQueryResult row : rows)
{
- rowHandler.processResult(row);
+ rollupRowHandler.handleRow(row);
}
+ // Don't process last result:
+ // rollupRowHandler.processLastResults();
+ // The last result may be incomplete
}
else
{
- RowHandler rowHandlerInternal = new RowHandler()
- {
- public void handleRow(Object valueObject)
- {
- AuditQueryResult row = (AuditQueryResult) valueObject;
- rowHandler.processResult(row);
- }
- };
- template.queryWithRowHandler(SELECT_ENTRIES_SIMPLE, params, rowHandlerInternal);
+ template.queryWithRowHandler(SELECT_ENTRIES_WITH_VALUES, params, rollupRowHandler);
+ rollupRowHandler.processLastResults();
}
}
}
diff --git a/source/java/org/alfresco/repo/domain/propval/AbstractPropertyValueDAOImpl.java b/source/java/org/alfresco/repo/domain/propval/AbstractPropertyValueDAOImpl.java
index 7a4f51ea74..4f9b612a08 100644
--- a/source/java/org/alfresco/repo/domain/propval/AbstractPropertyValueDAOImpl.java
+++ b/source/java/org/alfresco/repo/domain/propval/AbstractPropertyValueDAOImpl.java
@@ -833,7 +833,7 @@ public abstract class AbstractPropertyValueDAOImpl implements PropertyValueDAO
protected abstract PropertyValueEntity createPropertyValue(Serializable value);
@SuppressWarnings("unchecked")
- protected Serializable convertPropertyIdSearchRows(List rows)
+ public Serializable convertPropertyIdSearchRows(List rows)
{
/*
* The results are ordered by the root_prop_id, current_prop_id and value_prop_id.
@@ -843,8 +843,21 @@ public abstract class AbstractPropertyValueDAOImpl implements PropertyValueDAO
final Map values = new HashMap(rows.size());
List keyRows = new ArrayList(5);
Serializable result = null;
+ Long rootPropId = null;
for (PropertyIdSearchRow row : rows)
{
+ // Check that we are handling a single root property
+ if (rootPropId == null)
+ {
+ rootPropId = row.getLinkEntity().getRootPropId();
+ }
+ else if (!rootPropId.equals(row.getLinkEntity().getRootPropId()))
+ {
+ throw new IllegalArgumentException(
+ "The root_prop_id for the property search rows must not change: \n" +
+ " Rows: " + rows);
+ }
+
PropertyLinkEntity linkEntity = row.getLinkEntity();
PropertyValueEntity valueEntity = row.getValueEntity();
// Construct the value (Maps and Collections should be CONSTRUCTABLE)
diff --git a/source/java/org/alfresco/repo/domain/propval/PropertyIdSearchRow.java b/source/java/org/alfresco/repo/domain/propval/PropertyIdSearchRow.java
index 44c06c2253..cb7b76ed8a 100644
--- a/source/java/org/alfresco/repo/domain/propval/PropertyIdSearchRow.java
+++ b/source/java/org/alfresco/repo/domain/propval/PropertyIdSearchRow.java
@@ -43,34 +43,6 @@ public class PropertyIdSearchRow
valueEntity = new PropertyValueEntity();
}
-// @Override
-// public int hashCode()
-// {
-// return (int) rootCollectionPropId + (int) valuePropId;
-// }
-//
-// @Override
-// public boolean equals(Object obj)
-// {
-// if (this == obj)
-// {
-// return true;
-// }
-// else if (obj instanceof PropertyCollectionLinkEntity)
-// {
-// PropertyCollectionLinkEntity that = (PropertyCollectionLinkEntity) obj;
-// return
-// this.rootCollectionPropId == that.rootCollectionPropId &&
-// this.currentCollectionPropId == that.currentCollectionPropId &&
-// this.valuePropId == that.valuePropId &&
-// this.keyPropId == that.keyPropId;
-// }
-// else
-// {
-// return false;
-// }
-// }
-//
@Override
public String toString()
{
diff --git a/source/java/org/alfresco/repo/domain/propval/PropertyValueDAO.java b/source/java/org/alfresco/repo/domain/propval/PropertyValueDAO.java
index 7d20dc5bad..831b8f325e 100644
--- a/source/java/org/alfresco/repo/domain/propval/PropertyValueDAO.java
+++ b/source/java/org/alfresco/repo/domain/propval/PropertyValueDAO.java
@@ -26,6 +26,7 @@ package org.alfresco.repo.domain.propval;
import java.io.Serializable;
import java.util.Date;
+import java.util.List;
import org.alfresco.repo.domain.CrcHelper;
import org.alfresco.util.Pair;
@@ -195,4 +196,18 @@ public interface PropertyValueDAO
* @param maxDepth the maximum depth of collections and maps to iterate into
*/
Pair getOrCreatePropertyValue(Serializable value, int maxDepth);
+
+ /**
+ * Utility method to convert property query results into the original value. Note
+ * that the rows must all share the same root property ID.
+ *
+ * If the rows passed in don't constitute a valid, full property - they don't contain all
+ * the link entities for the property - then the result may be null.
+ *
+ * @param rows the search results for a single root property
+ * @return Returns the root property as originally persisted, or null
+ * if the rows don't represent a complete property
+ * @throws IllegalArgumentException if rows don't all share the same root property ID
+ */
+ Serializable convertPropertyIdSearchRows(List rows);
}