diff --git a/config/alfresco/action-services-context.xml b/config/alfresco/action-services-context.xml
index 2dceed950f..04f990f6d5 100644
--- a/config/alfresco/action-services-context.xml
+++ b/config/alfresco/action-services-context.xml
@@ -338,6 +338,9 @@
{http://www.alfresco.org/model/content/1.0}content
+
+ true
+
diff --git a/config/alfresco/core-services-context.xml b/config/alfresco/core-services-context.xml
index a85fc04226..8972ba2b74 100644
--- a/config/alfresco/core-services-context.xml
+++ b/config/alfresco/core-services-context.xml
@@ -488,7 +488,7 @@
20
- 7
+ 5
diff --git a/config/alfresco/extension/wcm-xml-metadata-extracter-context.xml.sample b/config/alfresco/extension/wcm-xml-metadata-extracter-context.xml.sample
index e5f454810a..d143498d71 100644
--- a/config/alfresco/extension/wcm-xml-metadata-extracter-context.xml.sample
+++ b/config/alfresco/extension/wcm-xml-metadata-extracter-context.xml.sample
@@ -53,6 +53,9 @@
+
+ true
+
diff --git a/source/java/org/alfresco/repo/action/executer/ContentMetadataExtracter.java b/source/java/org/alfresco/repo/action/executer/ContentMetadataExtracter.java
index f4e29ba44e..33a7b1f1a5 100644
--- a/source/java/org/alfresco/repo/action/executer/ContentMetadataExtracter.java
+++ b/source/java/org/alfresco/repo/action/executer/ContentMetadataExtracter.java
@@ -56,14 +56,18 @@ import org.alfresco.service.namespace.QName;
*/
public class ContentMetadataExtracter extends ActionExecuterAbstractBase
{
- /**
- * The node service
- */
private NodeService nodeService;
+ private ContentService contentService;
+ private DictionaryService dictionaryService;
+ private MetadataExtracterRegistry metadataExtracterRegistry;
+ private boolean carryAspectProperties;
+
+ public ContentMetadataExtracter()
+ {
+ carryAspectProperties = true;
+ }
/**
- * Set the node service
- *
* @param nodeService the node service
*/
public void setNodeService(NodeService nodeService)
@@ -71,11 +75,6 @@ public class ContentMetadataExtracter extends ActionExecuterAbstractBase
this.nodeService = nodeService;
}
- /**
- * Our content service
- */
- private ContentService contentService;
-
/**
* @param contentService The contentService to set.
*/
@@ -84,11 +83,6 @@ public class ContentMetadataExtracter extends ActionExecuterAbstractBase
this.contentService = contentService;
}
- /**
- * The dictionary service
- */
- private DictionaryService dictionaryService;
-
/**
* @param dictService The DictionaryService to set.
*/
@@ -97,11 +91,6 @@ public class ContentMetadataExtracter extends ActionExecuterAbstractBase
this.dictionaryService = dictService;
}
- /**
- * Our Extracter
- */
- private MetadataExtracterRegistry metadataExtracterRegistry;
-
/**
* @param metadataExtracterRegistry The metadataExtracterRegistry to set.
*/
@@ -110,6 +99,18 @@ public class ContentMetadataExtracter extends ActionExecuterAbstractBase
this.metadataExtracterRegistry = metadataExtracterRegistry;
}
+ /**
+ * Whether or not aspect-related properties must be carried to the new version of the node
+ *
+ * @param carryAspectProperties true (default) to carry all aspect-linked
+ * properties forward. false will clean the
+ * aspect of any unextracted values.
+ */
+ public void setCarryAspectProperties(boolean carryAspectProperties)
+ {
+ this.carryAspectProperties = carryAspectProperties;
+ }
+
/**
* @see org.alfresco.repo.action.executer.ActionExecuter#execute(org.alfresco.service.cmr.repository.NodeRef,
* NodeRef)
@@ -155,6 +156,7 @@ public class ContentMetadataExtracter extends ActionExecuterAbstractBase
// Check that all properties have the appropriate aspect applied
Set requiredAspectQNames = new HashSet(3);
+ Set aspectPropertyQNames = new HashSet(17);
for (QName propertyQName : modifiedProperties.keySet())
{
@@ -169,6 +171,21 @@ public class ContentMetadataExtracter extends ActionExecuterAbstractBase
{
QName aspectQName = propertyContainerDef.getName();
requiredAspectQNames.add(aspectQName);
+ // Get all properties associated with the aspect
+ Set aspectProperties = propertyContainerDef.getProperties().keySet();
+ aspectPropertyQNames.addAll(aspectProperties);
+ }
+ }
+
+ if (!carryAspectProperties)
+ {
+ // Remove any node properties that are defined on the aspects but were not extracted
+ for (QName aspectPropertyQName : aspectPropertyQNames)
+ {
+ if (!modifiedProperties.containsKey(aspectPropertyQName))
+ {
+ nodeProperties.remove(aspectPropertyQName);
+ }
}
}
diff --git a/source/java/org/alfresco/repo/node/BaseNodeServiceTest.java b/source/java/org/alfresco/repo/node/BaseNodeServiceTest.java
index 9dbb34fadc..1150f7869a 100644
--- a/source/java/org/alfresco/repo/node/BaseNodeServiceTest.java
+++ b/source/java/org/alfresco/repo/node/BaseNodeServiceTest.java
@@ -78,6 +78,7 @@ import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.BaseSpringTest;
import org.alfresco.util.GUID;
import org.alfresco.util.PropertyMap;
+import org.apache.commons.collections.map.SingletonMap;
import org.hibernate.Session;
import org.springframework.context.ApplicationContext;
@@ -679,6 +680,95 @@ public abstract class BaseNodeServiceTest extends BaseSpringTest
0, nodeService.getTargetAssocs(sourceNodeRef, RegexQNamePattern.MATCH_ALL).size());
}
+ private static final QName ASPECT_QNAME_TEST_RENDERED = QName.createQName(NAMESPACE, "rendered");
+ private static final QName ASSOC_TYPE_QNAME_TEST_RENDITION = QName.createQName(NAMESPACE, "rendition-page");
+ private static final QName TYPE_QNAME_TEST_RENDITION_PAGE = QName.createQName(NAMESPACE, "rendition-page");
+ private static final QName PROP_QNAME_TEST_RENDITION_PAGE_CONTENT = QName.createQName(NAMESPACE, "rendition-page-content");
+ public void testAspectWithChildAssociationsCreationAndRetrieval() throws Exception
+ {
+ // Create a folder. This is like the user's home folder, say.
+ NodeRef folderNodeRef = nodeService.createNode(
+ rootNodeRef,
+ ContentModel.ASSOC_CHILDREN,
+ QName.createQName(BaseNodeServiceTest.NAMESPACE, "UserX-" + GUID.generate()),
+ ContentModel.TYPE_FOLDER).getChildRef();
+ // Create a document. This is the actual document uploaded by the user.
+ NodeRef fileNodeRef = nodeService.createNode(
+ folderNodeRef,
+ ContentModel.ASSOC_CONTAINS,
+ QName.createQName(BaseNodeServiceTest.NAMESPACE, "Uploaded.pdf"),
+ ContentModel.TYPE_FOLDER).getChildRef();
+ // So, thus far, this is exactly what you have. Now for the bit to add some renditions.
+ // First, we can make some content data pages - spoofed, of course
+ List renditionContentPages = new ArrayList(20);
+ // This loop is where you will, outside of the transaction, push the page content into the repo
+ for(int i = 0; i < 100; i++)
+ {
+ ContentData contentData = new ContentData(null, MimetypeMap.MIMETYPE_PDF, 10245, "UTF-8");
+ renditionContentPages.add(contentData);
+ }
+
+ nodeService.addAspect(fileNodeRef, ASPECT_QNAME_TEST_RENDERED, null);
+ int pageNumber = 0;
+ for (ContentData renditionContentPage : renditionContentPages)
+ {
+ pageNumber++;
+ QName renditionQName = makePageAssocName(pageNumber);
+ Map properties = Collections.singletonMap(
+ PROP_QNAME_TEST_RENDITION_PAGE_CONTENT,
+ (Serializable) renditionContentPage);
+ nodeService.createNode(
+ fileNodeRef,
+ ASSOC_TYPE_QNAME_TEST_RENDITION,
+ renditionQName,
+ TYPE_QNAME_TEST_RENDITION_PAGE,
+ properties);
+ }
+
+ // That's it for uploading. Now we retrieve them.
+ if (!nodeService.hasAspect(fileNodeRef, ASPECT_QNAME_TEST_RENDERED))
+ {
+ // Jump to the original rendition retrieval code
+ return;
+ }
+ // It has the aspect, so it's the new model
+ List fetchedRenditionChildAssocs = nodeService.getChildAssocs(
+ fileNodeRef,
+ ASSOC_TYPE_QNAME_TEST_RENDITION,
+ RegexQNamePattern.MATCH_ALL);
+ assertEquals(
+ "We didn't get the correct number of pages back",
+ renditionContentPages.size(),
+ fetchedRenditionChildAssocs.size());
+ // Get page ... 5. This is to prove that they are ordered.
+ ChildAssociationRef fetchedRenditionChildAssoc5 = fetchedRenditionChildAssocs.get(4);
+ QName page5QName = makePageAssocName(5);
+ assertEquals(
+ "Local name of page 5 assoc is not correct",
+ page5QName,
+ fetchedRenditionChildAssoc5.getQName());
+ // Now retrieve page 5 using the NodeService
+ List fetchedRenditionChildAssocsPage5 = nodeService.getChildAssocs(
+ fileNodeRef,
+ ASSOC_TYPE_QNAME_TEST_RENDITION,
+ page5QName);
+ assertEquals("Expected exactly one result", 1, fetchedRenditionChildAssocsPage5.size());
+ assertEquals("Targeted page retrieval was not correct",
+ page5QName,
+ fetchedRenditionChildAssocsPage5.get(0).getQName());
+ }
+ private static final int MAX_RENDITION_PAGES = 100;
+ private static QName makePageAssocName(int pageNumber)
+ {
+ if (pageNumber > MAX_RENDITION_PAGES)
+ {
+ throw new IllegalArgumentException("Rendition page number may not exceed " + MAX_RENDITION_PAGES);
+ }
+ String pageLocalName = String.format("renditionpage%05d", pageNumber);
+ QName renditionQName = QName.createQName(NAMESPACE, pageLocalName);
+ return renditionQName;
+ }
+
public void testCreateNodeNoProperties() throws Exception
{
// flush to ensure that the pure JDBC query will work
diff --git a/source/java/org/alfresco/repo/node/BaseNodeServiceTest_model.xml b/source/java/org/alfresco/repo/node/BaseNodeServiceTest_model.xml
index ab0cafc0b8..210fd831fc 100644
--- a/source/java/org/alfresco/repo/node/BaseNodeServiceTest_model.xml
+++ b/source/java/org/alfresco/repo/node/BaseNodeServiceTest_model.xml
@@ -274,6 +274,17 @@
+
+
+ Rendition Page
+ sys:base
+
+
+ d:content
+ true
+
+
+
@@ -351,7 +362,24 @@
-
+
+
+ Aspect for Hanging Renditions Off
+
+
+
+ false
+ false
+
+
+ test:rendition-page
+ false
+ true
+
+
+
+
+