Merged HEAD-BUG-FIX (5.0/Cloud) to HEAD (5.0/Cloud)

76890: Merged PLATFORM1 (5.0/Cloud) to HEAD-BUG-FIX (5.0/Cloud)
      65482: Merge DEV to PLATFORM1
        ACE-502 - Transfer service : implement transferring of categories and tags
            58825 : 	MNT-8098 - Create categories on target runs as "System". Bug fix when removing categories which results in a "null" node ref.
            58716 : 	MNT-8098 - transfer of categories and tags.


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@77731 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Mark Rogers
2014-07-23 10:11:19 +00:00
parent 9a685756c1
commit f0fb9f279f
14 changed files with 705 additions and 26 deletions

View File

@@ -62,6 +62,7 @@ import org.alfresco.model.ContentModel;
import org.alfresco.repo.node.NodeUtils;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.repo.transfer.TransferContext;
import org.alfresco.repo.transfer.manifest.TransferManifestNodeFactory;
import org.alfresco.repo.transfer.manifest.TransferManifestNormalNode;
import org.alfresco.repo.version.VersionModel;
@@ -572,7 +573,7 @@ public class PublishingEventHelper
versionService.ensureVersioningEnabled(node, props);
}
versionService.createVersion(node, null);
TransferManifestNormalNode payload = (TransferManifestNormalNode) transferManifestNodeFactory.createTransferManifestNode(node, excludedAspectsTransferDefinition);
TransferManifestNormalNode payload = (TransferManifestNormalNode) transferManifestNodeFactory.createTransferManifestNode(node, excludedAspectsTransferDefinition, new TransferContext());
NodeSnapshotTransferImpl snapshot = new NodeSnapshotTransferImpl(payload);
return snapshot;
}

View File

@@ -27,7 +27,9 @@ import org.alfresco.repo.transfer.requisite.TransferRequsiteWriter;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.CategoryService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.tagging.TaggingService;
import org.alfresco.service.cmr.transfer.TransferReceiver;
/**
@@ -41,6 +43,8 @@ public class DefaultManifestProcessorFactoryImpl implements ManifestProcessorFac
private PermissionService permissionService;
private CorrespondingNodeResolverFactory nodeResolverFactory;
private AlienProcessor alienProcessor;
private CategoryService categoryService;
private TaggingService taggingService;
/*
* (non-Javadoc)
@@ -59,6 +63,8 @@ public class DefaultManifestProcessorFactoryImpl implements ManifestProcessorFac
primaryProcessor.setDictionaryService(dictionaryService);
primaryProcessor.setPermissionService(getPermissionService());
primaryProcessor.setAlienProcessor(getAlienProcessor());
primaryProcessor.setCategoryService(categoryService);
primaryProcessor.setTaggingService(getTaggingService());
processors.add(primaryProcessor);
RepoSecondaryManifestProcessorImpl secondaryProcessor = new RepoSecondaryManifestProcessorImpl(receiver, transferId);
@@ -143,4 +149,24 @@ public class DefaultManifestProcessorFactoryImpl implements ManifestProcessorFac
return alienProcessor;
}
public CategoryService getCategoryService()
{
return categoryService;
}
public void setCategoryService(CategoryService categoryService)
{
this.categoryService = categoryService;
}
public TaggingService getTaggingService()
{
return taggingService;
}
public void setTaggingService(TaggingService taggingService)
{
this.taggingService = taggingService;
}
}

View File

@@ -22,22 +22,27 @@ package org.alfresco.repo.transfer;
import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.transfer.CorrespondingNodeResolver.ResolvedParentChildPair;
import org.alfresco.repo.transfer.manifest.ManifestAccessControl;
import org.alfresco.repo.transfer.manifest.ManifestCategory;
import org.alfresco.repo.transfer.manifest.ManifestPermission;
import org.alfresco.repo.transfer.manifest.TransferManifestDeletedNode;
import org.alfresco.repo.transfer.manifest.TransferManifestHeader;
import org.alfresco.repo.transfer.manifest.TransferManifestNode;
import org.alfresco.repo.transfer.manifest.TransferManifestNormalNode;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
@@ -48,10 +53,14 @@ import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.CategoryService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AccessPermission;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.tagging.TaggingService;
import org.alfresco.service.cmr.transfer.TransferReceiver;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
@@ -92,6 +101,9 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB
private DictionaryService dictionaryService;
private CorrespondingNodeResolver nodeResolver;
private AlienProcessor alienProcessor;
private SearchService searchService;
private CategoryService categoryService;
private TaggingService taggingService;
// State within this class
/**
@@ -104,6 +116,11 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB
* If at the end of processing there are still orphans then an exception will be thrown.
*/
private Map<NodeRef, List<ChildAssociationRef>> orphans = new HashMap<NodeRef, List<ChildAssociationRef>>(89);
/**
* node ref mapping from source to destination categories
*/
private Map<NodeRef, NodeRef> categoryMap = new HashMap<NodeRef, NodeRef>();
/**
* @param transferId
@@ -277,6 +294,8 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB
// First, create a shallow copy of the supplied property map...
Map<QName, Serializable> props = new HashMap<QName, Serializable>(node.getProperties());
processCategories(props, node.getManifestCategories());
injectTransferred(props);
// Split out the content properties and sanitise the others
@@ -532,6 +551,8 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB
Map<QName, Serializable> props = new HashMap<QName, Serializable>(node.getProperties());
Map<QName, Serializable> existingProps = nodeService.getProperties(nodeToUpdate);
processCategories(props, node.getManifestCategories());
// inject transferred properties/aspect here
injectTransferred(props);
@@ -966,6 +987,181 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB
{
return permissionService;
}
/**
* Process categories.
*
* CRUD of Categories and Tags - also maps noderefs of type d:content from source to target
*
*
* @param properties
* @param manifestCategories
*/
private void processCategories(Map<QName, Serializable> properties, Map<NodeRef, ManifestCategory> manifestCategories)
{
if(manifestCategories != null)
{
for(Map.Entry<QName, Serializable> val : properties.entrySet())
{
PropertyDefinition def = dictionaryService.getProperty(val.getKey());
if(def != null)
{
if(def.getDataType().getName().isMatch(DataTypeDefinition.CATEGORY))
{
Serializable thing = val.getValue();
if(thing != null)
{
if(def.isMultiValued())
{
if(thing instanceof java.util.Collection)
{
List<NodeRef> newCategories = new ArrayList<NodeRef>();
java.util.Collection<NodeRef> c = (java.util.Collection<NodeRef>)thing;
for(NodeRef sourceCategoryNodeRef : c)
{
if(log.isDebugEnabled())
{
log.debug("sourceCategoryNodeRef" + sourceCategoryNodeRef);
}
// substitute target node ref fot source node ref
NodeRef targetNodeRef = processCategory(sourceCategoryNodeRef, manifestCategories);
newCategories.add(targetNodeRef);
}
// substitute target node refs for source node refs
properties.put(val.getKey(), (Serializable)newCategories);
}
else
{
throw new AlfrescoRuntimeException("Multi valued object is not a collection" + val.getKey() );
}
}
else
{
NodeRef sourceCategoryNodeRef = (NodeRef)thing;
if(log.isDebugEnabled())
{
log.debug("sourceCategoryNodeRef:" + sourceCategoryNodeRef);
}
NodeRef targetNodeRef = processCategory(sourceCategoryNodeRef, manifestCategories);
// substitute target node ref for source node ref
properties.put(val.getKey(), targetNodeRef);
}
}
}
}
}
}
}
/**
* process category - maps the category node ref from the source system to the target system.
*
* It will lazily create any missing categories and tags as it executes.
*
* @param sourceCategoryNodeRef
* @param manifestCategories
* @return targetNodeRef
*/
private NodeRef processCategory(final NodeRef sourceCategoryNodeRef, final Map<NodeRef, ManifestCategory> manifestCategories)
{
// first check cache to see whether we have already mapped this category
NodeRef destinationNodeRef = categoryMap.get(sourceCategoryNodeRef);
if(destinationNodeRef != null)
{
return destinationNodeRef;
}
// No we havn't seen this category before, have we got the details in the manifest
ManifestCategory category = manifestCategories.get(sourceCategoryNodeRef);
if(category != null)
{
final String path = category.getPath();
final Path catPath = PathHelper.stringToPath(path);
final Path.Element aspectName = catPath.get(2);
final QName aspectQName = QName.createQName(aspectName.getElementString());
if(aspectQName.equals(ContentModel.ASPECT_TAGGABLE))
{
Path.Element tagName = catPath.get(3);
// Category is a tag
QName tagQName = QName.createQName(tagName.getElementString());
destinationNodeRef = taggingService.getTagNodeRef(sourceCategoryNodeRef.getStoreRef(), tagQName.getLocalName());
if(destinationNodeRef != null)
{
log.debug("found existing tag" + tagQName.getLocalName());
categoryMap.put(sourceCategoryNodeRef, destinationNodeRef);
return destinationNodeRef;
}
destinationNodeRef = taggingService.createTag(sourceCategoryNodeRef.getStoreRef(), tagQName.getLocalName());
if(destinationNodeRef != null)
{
log.debug("created new tag" + tagQName.getLocalName());
categoryMap.put(sourceCategoryNodeRef, destinationNodeRef);
return destinationNodeRef;
}
}
else
{
// Categories are finniky about permissions, so run as system
RunAsWork<NodeRef> processCategory = new RunAsWork<NodeRef>()
{
@Override
public NodeRef doWork() throws Exception
{
QName rootCatName = QName.createQName(catPath.get(3).getElementString());
Collection<ChildAssociationRef> roots = categoryService.getRootCategories(sourceCategoryNodeRef.getStoreRef(), aspectQName);
/**
* Get the root category node ref
*/
NodeRef rootCategoryNodeRef = null;
for(ChildAssociationRef ref : roots)
{
if(ref.getQName().equals(rootCatName))
{
rootCategoryNodeRef = ref.getChildRef();
break;
}
}
if(rootCategoryNodeRef == null)
{
// Root category does not exist
rootCategoryNodeRef = categoryService.createRootCategory(sourceCategoryNodeRef.getStoreRef(), aspectQName, rootCatName.getLocalName());
}
NodeRef workingNodeRef = rootCategoryNodeRef;
// Root category does already exist - step through any sub-categories
for(int i = 4; i < catPath.size(); i++)
{
Path.Element element = catPath.get(i);
QName subCatName = QName.createQName(element.toString());
ChildAssociationRef child = categoryService.getCategory(workingNodeRef, aspectQName, subCatName.getLocalName());
if(child != null)
{
workingNodeRef = child.getChildRef();
}
else
{
workingNodeRef = categoryService.createCategory(workingNodeRef, subCatName.getLocalName());
}
}
return workingNodeRef;
}
};
destinationNodeRef = AuthenticationUtil.runAs(processCategory, AuthenticationUtil.SYSTEM_USER_NAME);
categoryMap.put(sourceCategoryNodeRef, destinationNodeRef);
return destinationNodeRef;
}
} // if manifest category exists
return sourceCategoryNodeRef;
}
/**
* inject transferred
@@ -1010,4 +1206,24 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB
return alienProcessor;
}
public CategoryService getCategoryService()
{
return categoryService;
}
public void setCategoryService(CategoryService categoryService)
{
this.categoryService = categoryService;
}
public TaggingService getTaggingService()
{
return taggingService;
}
public void setTaggingService(TaggingService taggingService)
{
this.taggingService = taggingService;
}
}

View File

@@ -576,6 +576,8 @@ public class TransferServiceImpl2 implements TransferService2
}
};
eventProcessor.addObserver(reportCallback);
TransferContext transferContext = new TransferContext();
// start transfer
ClientTransferState clientState = ClientTransferState.Begin;
@@ -589,7 +591,7 @@ public class TransferServiceImpl2 implements TransferService2
{
eventProcessor.start();
manifest = createManifest(definition, localRepositoryId, fromVersion);
manifest = createManifest(definition, localRepositoryId, fromVersion, transferContext);
logger.debug("transfer begin");
target = getTransferTarget(targetName);
checkTargetEnabled(target);
@@ -919,7 +921,7 @@ public class TransferServiceImpl2 implements TransferService2
}
}
private File createManifest(TransferDefinition definition, String repositoryId, TransferVersion fromVersion)
private File createManifest(TransferDefinition definition, String repositoryId, TransferVersion fromVersion, TransferContext transferContext)
throws IOException, SAXException
{
// which nodes to write to the snapshot
@@ -966,7 +968,7 @@ public class TransferServiceImpl2 implements TransferService2
{
for (NodeRef nodeRef : nodes)
{
TransferManifestNode node = transferManifestNodeFactory.createTransferManifestNode(nodeRef, definition);
TransferManifestNode node = transferManifestNodeFactory.createTransferManifestNode(nodeRef, definition, transferContext);
formatter.writeTransferManifestNode(node);
}
}
@@ -974,7 +976,7 @@ public class TransferServiceImpl2 implements TransferService2
{
for (NodeRef nodeRef : nodesToRemove)
{
TransferManifestNode node = transferManifestNodeFactory.createTransferManifestNode(nodeRef, definition,
TransferManifestNode node = transferManifestNodeFactory.createTransferManifestNode(nodeRef, definition, transferContext,
true);
formatter.writeTransferManifestNode(node);
}

View File

@@ -57,6 +57,9 @@ public interface ManifestModel extends TransferModel
static final String LOCALNAME_ELEMENT_CONTENT_HEADER = "content";
static final String LOCALNAME_ELEMENT_ACL = "acl";
static final String LOCALNAME_ELEMENT_ACL_PERMISSION = "permission";
static final String LOCALNAME_ELEMENT_CATEGORIES = "categories";
static final String LOCALNAME_ELEMENT_CATEGORY = "category";
// Manifest file prefix
static final String MANIFEST_PREFIX = "xfer";

View File

@@ -18,6 +18,7 @@
*/
package org.alfresco.repo.transfer.manifest;
import org.alfresco.repo.transfer.TransferContext;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.transfer.TransferDefinition;
@@ -29,9 +30,10 @@ public interface TransferManifestNodeFactory
* specifying <code>false</code> as the value of the <code>forceDelete</code> parameter.
* @param nodeRef The identifier of the node to be distilled for transfer
* @param definition The transfer definition against which the node is being transferred
* @param transferContext internal runtime context of a transfer
* @return An object that holds a snapshot of the state of the specified node suitable for transfer elsewhere.
*/
TransferManifestNode createTransferManifestNode(NodeRef nodeRef, TransferDefinition definition);
TransferManifestNode createTransferManifestNode(NodeRef nodeRef, TransferDefinition definition, TransferContext transferContext);
/**
* Create an object that represents the specified node in a form that can be used to transfer it elsewhere
@@ -40,7 +42,8 @@ public interface TransferManifestNodeFactory
* @param forceDelete If this flag is set then the returned TransferManifestNode object will represent the removal
* of the specified node, even if the node still exists in this repository. This allows a node to be removed from the
* target repository even if it hasn't been removed in the source repository.
* @param transferContext internal runtime context of a transfer
* @return An object that holds a snapshot of the state of the specified node suitable for transfer elsewhere.
*/
TransferManifestNode createTransferManifestNode(NodeRef nodeRef, TransferDefinition definition, boolean forceDelete);
TransferManifestNode createTransferManifestNode(NodeRef nodeRef, TransferDefinition definition, TransferContext transferContext, boolean forceDelete);
}

View File

@@ -27,6 +27,8 @@ import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.transfer.TransferContext;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
@@ -60,12 +62,12 @@ public class TransferManifestNodeFactoryImpl implements TransferManifestNodeFact
//NOOP
}
public TransferManifestNode createTransferManifestNode(NodeRef nodeRef, TransferDefinition definition)
public TransferManifestNode createTransferManifestNode(NodeRef nodeRef, TransferDefinition definition, TransferContext transferContext)
{
return createTransferManifestNode(nodeRef, definition, false);
return createTransferManifestNode(nodeRef, definition, transferContext, false);
}
public TransferManifestNode createTransferManifestNode(NodeRef nodeRef, TransferDefinition definition, boolean forceDelete)
public TransferManifestNode createTransferManifestNode(NodeRef nodeRef, TransferDefinition definition, TransferContext transferContext, boolean forceDelete)
{
NodeRef.Status status = nodeService.getNodeStatus(nodeRef);
@@ -203,6 +205,57 @@ public class TransferManifestNodeFactoryImpl implements TransferManifestNodeFact
}
}
acl.setPermissions(mps);
/**
* Expand d:category information so we can re-create on target
*/
Map<NodeRef, ManifestCategory> categories = new HashMap<NodeRef, ManifestCategory>();
Map<QName, Serializable> properties = node.getProperties();
for(Map.Entry<QName, Serializable> val : properties.entrySet())
{
PropertyDefinition def = dictionaryService.getProperty(val.getKey());
if(def != null)
{
if(def.getDataType().getName().isMatch(DataTypeDefinition.CATEGORY))
{
if(def.isMultiValued())
{
Serializable thing = val.getValue();
if(thing instanceof java.util.Collection)
{
java.util.Collection<NodeRef> c = (java.util.Collection<NodeRef>)thing;
for(NodeRef categoryNodeRef : c)
{
if(categoryNodeRef != null)
{
categories.put(categoryNodeRef, getManifestCategory(transferContext, categoryNodeRef));
}
}
}
else
{
NodeRef categoryNodeRef = (NodeRef)val.getValue();
if(categoryNodeRef != null)
{
categories.put(categoryNodeRef, getManifestCategory(transferContext, categoryNodeRef));
}
}
}
else
{
NodeRef categoryNodeRef = (NodeRef)val.getValue();
if(categoryNodeRef != null)
{
categories.put(categoryNodeRef, getManifestCategory(transferContext, categoryNodeRef));
}
}
}
}
}
node.setManifestCategories(categories);
return node;
}
@@ -264,6 +317,22 @@ public class TransferManifestNodeFactoryImpl implements TransferManifestNodeFact
return filteredProperties;
}
}
private ManifestCategory getManifestCategory(TransferContext transferContext, NodeRef categoryNodeRef)
{
ManifestCategory c = transferContext.getManifestCategoriesCache().get(categoryNodeRef);
if(c != null)
{
return c;
}
c = new ManifestCategory();
Path p = nodeService.getPath(categoryNodeRef);
c.setPath(p.toString());
transferContext.getManifestCategoriesCache().put(categoryNodeRef, c);
return c;
}
public void setNodeService(NodeService nodeService)
{

View File

@@ -51,6 +51,9 @@ public class TransferManifestNormalNode implements TransferManifestNode
private List<AssociationRef> targetAssocs;
private Path parentPath;
private ManifestAccessControl accessControl;
// NodeRef is noderef of type d:category ManifestCategory provides the extra meta-data
private Map<NodeRef, ManifestCategory> categories;
public void setNodeRef(NodeRef nodeRef)
{
@@ -190,5 +193,15 @@ public class TransferManifestNormalNode implements TransferManifestNode
{
this.ancestorType = ancestorType;
}
public void setManifestCategories(Map<NodeRef, ManifestCategory> categories)
{
this.categories = categories;
}
public Map<NodeRef, ManifestCategory> getManifestCategories()
{
return this.categories;
}
}

View File

@@ -349,6 +349,18 @@ public class XMLTransferManifestReader extends DefaultHandler implements Content
perm.setStatus(status);
props.put("permission", perm);
}
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_CATEGORIES))
{
props.put("categories", new HashMap<NodeRef, ManifestCategory>());
}
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_CATEGORY))
{
ManifestCategory cat = new ManifestCategory();
String path = (String)atts.getValue("", "path");
cat.setPath(path);
props.put("category", cat);
}
} // if transfer URI
} // startElement
@@ -634,6 +646,18 @@ public class XMLTransferManifestReader extends DefaultHandler implements Content
ManifestPermission permission = (ManifestPermission)props.get("permission");
acl.addPermission(permission);
}
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_CATEGORIES))
{
TransferManifestNormalNode node = (TransferManifestNormalNode)props.get("node");
Map<NodeRef, ManifestCategory> categories = (Map<NodeRef, ManifestCategory> )props.get("categories");
node.setManifestCategories(categories);
}
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_CATEGORY))
{
Map<NodeRef, ManifestCategory> categories = (Map<NodeRef, ManifestCategory> )props.get("categories");
ManifestCategory category = (ManifestCategory)props.get("category");
categories.put(new NodeRef(buffer.toString().trim()),category);
}
} // if transfer URI

View File

@@ -36,6 +36,7 @@ import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.MLText;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.repository.datatype.TypeConversionException;
@@ -281,6 +282,8 @@ public class XMLTransferManifestWriter implements TransferManifestWriter
{
writePrimaryParent(node.getPrimaryParentAssoc(), node.getParentPath());
}
writeCategories(node.getManifestCategories());
writeAspects(node.getAspects());
@@ -300,6 +303,42 @@ public class XMLTransferManifestWriter implements TransferManifestWriter
ManifestModel.LOCALNAME_ELEMENT_NODE, PREFIX + ":"
+ ManifestModel.LOCALNAME_ELEMENT_NODE);
}
private void writeCategories(Map<NodeRef, ManifestCategory> categories) throws SAXException
{
writer.startElement(TransferModel.TRANSFER_MODEL_1_0_URI,
ManifestModel.LOCALNAME_ELEMENT_PROPERTIES, PREFIX + ":"
+ ManifestModel.LOCALNAME_ELEMENT_CATEGORIES, EMPTY_ATTRIBUTES);
if (categories != null)
{
for (Entry<NodeRef, ManifestCategory> entry : categories.entrySet())
{
writeCategory(entry.getKey(), entry.getValue());
}
}
writer.endElement(TransferModel.TRANSFER_MODEL_1_0_URI,
ManifestModel.LOCALNAME_ELEMENT_PROPERTIES, PREFIX + ":"
+ ManifestModel.LOCALNAME_ELEMENT_CATEGORIES);
}
@SuppressWarnings("unchecked")
private void writeCategory (NodeRef nodeRef, ManifestCategory value) throws SAXException
{
AttributesImpl attributes = new AttributesImpl();
attributes.addAttribute(TransferModel.TRANSFER_MODEL_1_0_URI, "path", "path", "String",
value.getPath());
writer.startElement(TransferModel.TRANSFER_MODEL_1_0_URI,
ManifestModel.LOCALNAME_ELEMENT_CATEGORY, PREFIX + ":"
+ ManifestModel.LOCALNAME_ELEMENT_CATEGORY, attributes);
writeValue(nodeRef);
writer.endElement(TransferModel.TRANSFER_MODEL_1_0_URI,
ManifestModel.LOCALNAME_ELEMENT_CATEGORY, PREFIX + ":"
+ ManifestModel.LOCALNAME_ELEMENT_CATEGORY);
}
private void writeProperties(Map<QName, Serializable> properties) throws SAXException
{