mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-07 18:25:23 +00:00
transfer service : ALF-4128 alien nodes.
- unit test of multiple invasion - unit test move alien node via transfer. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@21685 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
parent
f79c9fc0e3
commit
b51e8ef744
@ -208,14 +208,8 @@
|
||||
|
||||
<aspect name="trx:alien">
|
||||
<title>Alien Node</title>
|
||||
<description>Nodes with this aspect are either alien nodes or have been invaded by alien content</description>
|
||||
<description>Nodes with this aspect are either alien nodes or have been invaded by other alien nodes</description>
|
||||
<properties>
|
||||
<property name="trx:alien">
|
||||
<title>Alien Content</title>
|
||||
<type>d:boolean</type>
|
||||
<mandatory enforced="false">false</mandatory>
|
||||
<default>false</default>
|
||||
</property>
|
||||
<property name="trx:invadedBy">
|
||||
<title>The repositories that have invaded this node</title>
|
||||
<type>d:text</type>
|
||||
|
@ -148,7 +148,7 @@ public class AlienProcessorImpl implements AlienProcessor
|
||||
|
||||
public void beforeDeleteAlien(NodeRef deletedNodeRef)
|
||||
{
|
||||
log.debug("on delete node - need to check for transferred node");
|
||||
log.debug("before delete node - need to check for alien invaders");
|
||||
|
||||
List<String>stuff = (List<String>)nodeService.getProperty(deletedNodeRef, TransferModel.PROP_INVADED_BY);
|
||||
|
||||
@ -272,12 +272,18 @@ public class AlienProcessorImpl implements AlienProcessor
|
||||
return nodeService.hasAspect(nodeRef, TransferModel.ASPECT_ALIEN);
|
||||
}
|
||||
|
||||
public void pruneNode(NodeRef parentNodeRef, String fromRepositoryId)
|
||||
public void pruneNode(NodeRef nodeToPrune, String fromRepositoryId)
|
||||
{
|
||||
Stack<NodeRef> nodesToPrune = new Stack<NodeRef>();
|
||||
Stack<NodeRef> foldersToRecalculate = new Stack<NodeRef>();
|
||||
nodesToPrune.add(parentNodeRef);
|
||||
|
||||
nodesToPrune.add(nodeToPrune);
|
||||
|
||||
ChildAssociationRef startingParent = nodeService.getPrimaryParent(nodeToPrune);
|
||||
|
||||
Stack<NodeRef> foldersToRecalculate = new Stack<NodeRef>();
|
||||
|
||||
/**
|
||||
* Now go and do the pruning.
|
||||
*/
|
||||
while(!nodesToPrune.isEmpty())
|
||||
{
|
||||
/**
|
||||
@ -297,6 +303,7 @@ public class AlienProcessorImpl implements AlienProcessor
|
||||
List<String>invadedBy = (List<String>)getNodeService().getProperty(currentNodeRef, TransferModel.PROP_INVADED_BY);
|
||||
if(invadedBy.contains(fromRepositoryId))
|
||||
{
|
||||
// Yes we are invaded by fromRepositoryId
|
||||
if(invadedBy.size() == 1)
|
||||
{
|
||||
// we are invaded by a single repository which must be fromRepositoryId
|
||||
@ -307,23 +314,24 @@ public class AlienProcessorImpl implements AlienProcessor
|
||||
{
|
||||
log.debug("folder has multiple invaders");
|
||||
// multiple invasion - so it must be a folder
|
||||
|
||||
//TODO replace with a more efficient query
|
||||
List<ChildAssociationRef> refs = getNodeService().getChildAssocs(parentNodeRef);
|
||||
List<ChildAssociationRef> refs = getNodeService().getChildAssocs(currentNodeRef);
|
||||
for(ChildAssociationRef ref : refs)
|
||||
{
|
||||
if(log.isDebugEnabled())
|
||||
{
|
||||
log.debug("will need to check child:" + ref);
|
||||
}
|
||||
nodesToPrune.push(ref.getChildRef());
|
||||
|
||||
/**
|
||||
* This folder can't be deleted so its invaded flag needs to be re-calculated
|
||||
*/
|
||||
if(!foldersToRecalculate.contains(ref.getParentRef()))
|
||||
{
|
||||
foldersToRecalculate.push(ref.getParentRef());
|
||||
}
|
||||
nodesToPrune.push(ref.getChildRef());
|
||||
}
|
||||
|
||||
/**
|
||||
* Yes we might do something to the children of this node.
|
||||
*/
|
||||
if(!foldersToRecalculate.contains(currentNodeRef))
|
||||
{
|
||||
foldersToRecalculate.push(currentNodeRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -353,9 +361,9 @@ public class AlienProcessorImpl implements AlienProcessor
|
||||
/**
|
||||
* This folder can't be deleted so its invaded flag needs to be re-calculated
|
||||
*/
|
||||
if(!foldersToRecalculate.contains(ref.getParentRef()))
|
||||
if(!foldersToRecalculate.contains(currentNodeRef))
|
||||
{
|
||||
foldersToRecalculate.push(ref.getParentRef());
|
||||
foldersToRecalculate.push(currentNodeRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -379,44 +387,52 @@ public class AlienProcessorImpl implements AlienProcessor
|
||||
}
|
||||
|
||||
/**
|
||||
* Now ripple the "invadedBy" flag upwards.
|
||||
* Now recalculate the "invadedBy" flag for those folders we could not delete.
|
||||
*/
|
||||
|
||||
while(!foldersToRecalculate.isEmpty())
|
||||
{
|
||||
NodeRef folderNodeRef = foldersToRecalculate.pop();
|
||||
|
||||
log.debug("recalculate invadedBy :" + folderNodeRef);
|
||||
|
||||
List<String>folderInvadedBy = (List<String>)getNodeService().getProperty(folderNodeRef, TransferModel.PROP_INVADED_BY);
|
||||
|
||||
boolean stillInvaded = false;
|
||||
//TODO need a more efficient query here
|
||||
List<ChildAssociationRef> refs = getNodeService().getChildAssocs(folderNodeRef);
|
||||
for(ChildAssociationRef ref : refs)
|
||||
recalcInvasion(folderNodeRef, fromRepositoryId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Now ripple up the invaded flag - may be a alien retreat.
|
||||
*/
|
||||
log.debug("now ripple upwards");
|
||||
|
||||
ChildAssociationRef ripple = startingParent;
|
||||
while(ripple != null)
|
||||
{
|
||||
if(log.isDebugEnabled())
|
||||
{
|
||||
NodeRef childNode = ref.getChildRef();
|
||||
List<String>childInvadedBy = (List<String>)getNodeService().getProperty(childNode, TransferModel.PROP_INVADED_BY);
|
||||
|
||||
if(childInvadedBy.contains(fromRepositoryId))
|
||||
log.debug("Checking parent:" + ripple);
|
||||
}
|
||||
|
||||
if(nodeService.hasAspect(ripple.getParentRef(), TransferModel.ASPECT_ALIEN))
|
||||
{
|
||||
if(recalcInvasion(ripple.getParentRef(), fromRepositoryId))
|
||||
{
|
||||
log.debug("folder is still invaded");
|
||||
stillInvaded = true;
|
||||
break;
|
||||
log.debug("parent is still invaded");
|
||||
ripple = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
log.debug("parent is no longer invaded");
|
||||
ripple = nodeService.getPrimaryParent(ripple.getParentRef());
|
||||
}
|
||||
}
|
||||
|
||||
if(!stillInvaded)
|
||||
else
|
||||
{
|
||||
List<String> newInvadedBy = new ArrayList<String>(folderInvadedBy);
|
||||
folderInvadedBy.remove(fromRepositoryId);
|
||||
getNodeService().setProperty(folderNodeRef, TransferModel.PROP_INVADED_BY, (Serializable)newInvadedBy);
|
||||
}
|
||||
ripple = null;
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("pruneNode: end");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is this node invaded ?
|
||||
* @param nodeRef
|
||||
@ -436,9 +452,9 @@ public class AlienProcessorImpl implements AlienProcessor
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the specified node as an alien node, invadedby the invader.
|
||||
* @param newAlien
|
||||
* @param invader
|
||||
* Mark the specified node as an alien node, invaded by the specified invader.
|
||||
* @param newAlien node that has been invaded.
|
||||
* @param invader the repository id of the invading repo.
|
||||
*/
|
||||
private void setAlien(NodeRef newAlien, String invader)
|
||||
{
|
||||
@ -448,23 +464,70 @@ public class AlienProcessorImpl implements AlienProcessor
|
||||
|
||||
if(invadedBy == null)
|
||||
{
|
||||
nodeService.setProperty(newAlien, TransferModel.PROP_ALIEN, Boolean.TRUE);
|
||||
invadedBy = new ArrayList<String>(1);
|
||||
}
|
||||
invadedBy.add(invader);
|
||||
|
||||
if(!invadedBy.contains(invader))
|
||||
{
|
||||
invadedBy.add(invader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the invaded by property
|
||||
*/
|
||||
nodeService.setProperty(newAlien, TransferModel.PROP_INVADED_BY, (Serializable) invadedBy);
|
||||
|
||||
// /**
|
||||
// * Experiment with a residual property
|
||||
// */
|
||||
// nodeService.setProperty(newAlien, QName.createQName(TransferModel.TRANSFER_MODEL_1_0_URI,
|
||||
// "invader" + invader), Boolean.TRUE);
|
||||
|
||||
nodeService.setProperty(newAlien, TransferModel.PROP_INVADED_BY, (Serializable) invadedBy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculate the whether this node is invaded by the specified repository
|
||||
* @param folderNodeRef the node to re-calculate
|
||||
* @param fromRepositoryId the repository who is transferring.
|
||||
*
|
||||
* @return true - still invaded, false, no longer invaded
|
||||
*/
|
||||
private boolean recalcInvasion(NodeRef folderNodeRef, String fromRepositoryId)
|
||||
{
|
||||
List<String>folderInvadedBy = (List<String>)nodeService.getProperty(folderNodeRef, TransferModel.PROP_INVADED_BY);
|
||||
|
||||
boolean stillInvaded = false;
|
||||
|
||||
//TODO need a more efficient query here
|
||||
List<ChildAssociationRef> refs = nodeService.getChildAssocs(folderNodeRef);
|
||||
for(ChildAssociationRef ref : refs)
|
||||
{
|
||||
NodeRef childNode = ref.getChildRef();
|
||||
List<String>childInvadedBy = (List<String>)getNodeService().getProperty(childNode, TransferModel.PROP_INVADED_BY);
|
||||
|
||||
if(childInvadedBy != null && childInvadedBy.contains(fromRepositoryId))
|
||||
{
|
||||
log.debug("folder is still invaded");
|
||||
stillInvaded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!stillInvaded)
|
||||
{
|
||||
log.debug("folder is no longer invaded by this repo:" + folderNodeRef);
|
||||
folderInvadedBy.remove(fromRepositoryId);
|
||||
if(folderInvadedBy.size() > 0)
|
||||
{
|
||||
if(log.isDebugEnabled())
|
||||
{
|
||||
log.debug("still invaded by:" + folderInvadedBy);
|
||||
}
|
||||
getNodeService().setProperty(folderNodeRef, TransferModel.PROP_INVADED_BY, (Serializable)folderInvadedBy);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.debug("no longer alien:" + folderNodeRef);
|
||||
getNodeService().removeAspect(folderNodeRef, TransferModel.ASPECT_ALIEN);
|
||||
}
|
||||
}
|
||||
|
||||
return stillInvaded;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
|
@ -69,6 +69,7 @@ public class DefaultManifestProcessorFactoryImpl implements ManifestProcessorFac
|
||||
RepoTertiaryManifestProcessorImpl tertiaryProcessor = new RepoTertiaryManifestProcessorImpl(receiver, transferId);
|
||||
tertiaryProcessor.setNodeService(nodeService);
|
||||
tertiaryProcessor.setAlienProcessor(getAlienProcessor());
|
||||
tertiaryProcessor.setNodeResolver(nodeResolver);
|
||||
processors.add(tertiaryProcessor);
|
||||
|
||||
return processors;
|
||||
|
@ -136,63 +136,35 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB
|
||||
// If we can find a corresponding node then we'll delete it.
|
||||
// If we can't find a corresponding node then we'll do nothing.
|
||||
logProgress("Processing incoming deleted node: " + node.getNodeRef());
|
||||
if (!nodeService.exists(node.getNodeRef()))
|
||||
|
||||
ChildAssociationRef origPrimaryParent = node.getPrimaryParentAssoc();
|
||||
NodeRef origNodeRef = new NodeRef(origPrimaryParent.getParentRef().getStoreRef(), node.getNodeRef().getId());
|
||||
|
||||
CorrespondingNodeResolver.ResolvedParentChildPair resolvedNodes = nodeResolver.resolveCorrespondingNode(
|
||||
origNodeRef, origPrimaryParent, node.getParentPath());
|
||||
|
||||
// Does a corresponding node exist in this repo?
|
||||
if (resolvedNodes.resolvedChild != null)
|
||||
{
|
||||
// It's not in our archive store. Check to see if we can find it in
|
||||
// its original store...
|
||||
ChildAssociationRef origPrimaryParent = node.getPrimaryParentAssoc();
|
||||
NodeRef origNodeRef = new NodeRef(origPrimaryParent.getParentRef().getStoreRef(), node.getNodeRef().getId());
|
||||
|
||||
CorrespondingNodeResolver.ResolvedParentChildPair resolvedNodes = nodeResolver.resolveCorrespondingNode(
|
||||
origNodeRef, origPrimaryParent, node.getParentPath());
|
||||
|
||||
// Does a corresponding node exist in this repo?
|
||||
if (resolvedNodes.resolvedChild != null)
|
||||
NodeRef exNode = resolvedNodes.resolvedChild;
|
||||
// Yes, it does. Delete it.
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
NodeRef exNode = resolvedNodes.resolvedChild;
|
||||
// Yes, it does. Delete it.
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Incoming deleted noderef " + node.getNodeRef()
|
||||
+ " has been resolved to existing local noderef " + exNode
|
||||
+ " - deleting");
|
||||
}
|
||||
|
||||
//TODO : do we have a business rule that only the "from" repo can delete a node? Yes we do.
|
||||
if(alienProcessor.isAlien(exNode))
|
||||
{
|
||||
logProgress("Pruning local node: " + exNode);
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Node to be deleted is alien prune rather than delete: " + exNode);
|
||||
}
|
||||
alienProcessor.pruneNode(exNode, header.getRepositoryId());
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO Need to restrict to the "from" repo Id.
|
||||
// Not alien - delete it.
|
||||
logProgress("Deleting local node: " + exNode);
|
||||
nodeService.deleteNode(exNode);
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Deleted local node: " + exNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logProgress("Unable to find corresponding node for incoming deleted node: " + node.getNodeRef());
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Incoming deleted noderef has no corresponding local noderef: " + node.getNodeRef()
|
||||
+ " - ignoring");
|
||||
}
|
||||
log.debug("Incoming deleted noderef " + node.getNodeRef()
|
||||
+ " has been resolved to existing local noderef " + exNode
|
||||
+ " - deleting");
|
||||
}
|
||||
|
||||
delete(exNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
logProgress("Incoming deleted node is already in the local archive store - ignoring: " + node.getNodeRef());
|
||||
logProgress("Unable to find corresponding node for incoming deleted node: " + node.getNodeRef());
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Incoming deleted noderef has no corresponding local noderef: " + node.getNodeRef()
|
||||
+ " - ignoring");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -372,6 +344,51 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB
|
||||
// Is the node that we've just added the parent of any orphans that
|
||||
// we've found earlier?
|
||||
checkOrphans(newNode.getChildRef());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete this node
|
||||
* @param exNode
|
||||
*/
|
||||
protected void delete(NodeRef nodeToDelete)
|
||||
{
|
||||
if(alienProcessor.isAlien(nodeToDelete))
|
||||
{
|
||||
logProgress("Pruning local node: " + nodeToDelete);
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Node to be deleted is alien prune rather than delete: " + nodeToDelete);
|
||||
}
|
||||
alienProcessor.pruneNode(nodeToDelete, header.getRepositoryId());
|
||||
}
|
||||
else
|
||||
{
|
||||
/**
|
||||
* Check that if the destination is "from" the transferring repo if it is "from" another repo then ignore
|
||||
*/
|
||||
if(nodeService.hasAspect(nodeToDelete, TransferModel.ASPECT_TRANSFERRED))
|
||||
{
|
||||
String fromRepository = (String)nodeService.getProperty(nodeToDelete, TransferModel.PROP_FROM_REPOSITORY_ID);
|
||||
String transferringRepo = header.getRepositoryId();
|
||||
|
||||
if(fromRepository != null && transferringRepo != null)
|
||||
{
|
||||
if(!fromRepository.equalsIgnoreCase(transferringRepo))
|
||||
{
|
||||
logProgress("Not deleting local node (not from the transferring repository): " + nodeToDelete);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Not alien or from another repo - delete it.
|
||||
logProgress("Deleting local node: " + nodeToDelete);
|
||||
nodeService.deleteNode(nodeToDelete);
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Deleted local node: " + nodeToDelete);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkOrphans(NodeRef parentNode)
|
||||
@ -410,7 +427,26 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB
|
||||
ChildAssociationRef primaryParentAssoc)
|
||||
{
|
||||
NodeRef nodeToUpdate = resolvedNodes.resolvedChild;
|
||||
|
||||
|
||||
/**
|
||||
* Check that if the destination is "from" the transferring repo if it is "from" another repo then ignore
|
||||
*/
|
||||
if(nodeService.hasAspect(nodeToUpdate, TransferModel.ASPECT_TRANSFERRED))
|
||||
{
|
||||
String fromRepository = (String)nodeService.getProperty(nodeToUpdate, TransferModel.PROP_FROM_REPOSITORY_ID);
|
||||
String transferringRepo = header.getRepositoryId();
|
||||
|
||||
if(fromRepository != null && transferringRepo != null)
|
||||
{
|
||||
if(!fromRepository.equalsIgnoreCase(transferringRepo))
|
||||
{
|
||||
logProgress("Not updating local node (not from the transferring repository): " + node.getNodeRef());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logProgress("Updating local node: " + node.getNodeRef());
|
||||
QName parentAssocType = primaryParentAssoc.getTypeQName();
|
||||
QName parentAssocName = primaryParentAssoc.getQName();
|
||||
@ -425,7 +461,8 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB
|
||||
parentAssocType = tempLocation.getTypeQName();
|
||||
parentAssocName = tempLocation.getQName();
|
||||
storeOrphanNode(primaryParentAssoc);
|
||||
}
|
||||
}
|
||||
|
||||
// First of all, do we need to move the node? If any aspect of the
|
||||
// primary parent association has changed
|
||||
// then the answer is "yes"
|
||||
@ -438,9 +475,9 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB
|
||||
/**
|
||||
* Yes, the parent assoc has changed so we need to move the node
|
||||
*/
|
||||
// the parent node may no longer be an alien
|
||||
if(nodeService.hasAspect(parentNodeRef, TransferModel.ASPECT_ALIEN))
|
||||
if(nodeService.hasAspect(currentParent.getParentRef(), TransferModel.ASPECT_ALIEN))
|
||||
{
|
||||
// old parent node ref may be alien
|
||||
alienProcessor.beforeDeleteAlien(node.getNodeRef());
|
||||
}
|
||||
|
||||
|
@ -19,23 +19,16 @@
|
||||
|
||||
package org.alfresco.repo.transfer;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.alfresco.repo.transfer.manifest.TransferManifestDeletedNode;
|
||||
import org.alfresco.repo.transfer.manifest.TransferManifestHeader;
|
||||
import org.alfresco.repo.transfer.manifest.TransferManifestNodeHelper;
|
||||
import org.alfresco.repo.transfer.manifest.TransferManifestNormalNode;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.transfer.TransferReceiver;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
@ -53,6 +46,7 @@ public class RepoTertiaryManifestProcessorImpl extends AbstractManifestProcessor
|
||||
{
|
||||
private NodeService nodeService;
|
||||
private AlienProcessor alienProcessor;
|
||||
CorrespondingNodeResolver nodeResolver;
|
||||
|
||||
private static final Log log = LogFactory.getLog(RepoTertiaryManifestProcessorImpl.class);
|
||||
|
||||
@ -83,38 +77,48 @@ public class RepoTertiaryManifestProcessorImpl extends AbstractManifestProcessor
|
||||
|
||||
protected void processNode(TransferManifestNormalNode node)
|
||||
{
|
||||
NodeRef nodeRef = node.getNodeRef();
|
||||
log.debug("processNode : " + nodeRef);
|
||||
|
||||
if(isSync)
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
|
||||
List<ChildAssociationRef> expectedChildren = node.getChildAssocs();
|
||||
|
||||
List<NodeRef> expectedChildNodeRefs = new ArrayList<NodeRef>();
|
||||
|
||||
for(ChildAssociationRef ref : expectedChildren)
|
||||
{
|
||||
if(log.isDebugEnabled())
|
||||
{
|
||||
log.debug("expecting child" + ref);
|
||||
}
|
||||
expectedChildNodeRefs.add(ref.getChildRef());
|
||||
}
|
||||
|
||||
log.debug("Processing node with incoming noderef of " + node.getNodeRef());
|
||||
}
|
||||
logProgress("Processing incoming node: " + node.getNodeRef() + " -- Source path = " + node.getParentPath() + "/" + node.getPrimaryParentAssoc().getQName());
|
||||
|
||||
// TODO Do we need to worry about path based nodes ? Assuming no at the moment.
|
||||
|
||||
/**
|
||||
* This processor only does processes sync requests.
|
||||
*/
|
||||
if(isSync)
|
||||
{
|
||||
ChildAssociationRef primaryParentAssoc = node.getPrimaryParentAssoc();
|
||||
|
||||
CorrespondingNodeResolver.ResolvedParentChildPair resolvedNodes = nodeResolver.resolveCorrespondingNode(node
|
||||
.getNodeRef(), primaryParentAssoc, node.getParentPath());
|
||||
|
||||
NodeRef nodeRef = resolvedNodes.resolvedChild;
|
||||
|
||||
if(nodeService.exists(nodeRef))
|
||||
{
|
||||
log.debug("destination node exists");
|
||||
log.debug("destination node exists - check the children");
|
||||
|
||||
//TODO Use more efficient query here.
|
||||
List<ChildAssociationRef> expectedChildren = node.getChildAssocs();
|
||||
|
||||
List<NodeRef> expectedChildNodeRefs = new ArrayList<NodeRef>();
|
||||
|
||||
for(ChildAssociationRef ref : expectedChildren)
|
||||
{
|
||||
if(log.isDebugEnabled())
|
||||
{
|
||||
log.debug("expecting child node" + ref);
|
||||
}
|
||||
expectedChildNodeRefs.add(ref.getChildRef());
|
||||
}
|
||||
|
||||
/**
|
||||
* yes this node exists in the destination.
|
||||
*/
|
||||
List<ChildAssociationRef> actualChildren = nodeService.getChildAssocs(nodeRef);
|
||||
|
||||
/**
|
||||
* For each destination child association
|
||||
* For each actual child association
|
||||
*/
|
||||
for(ChildAssociationRef child : actualChildren)
|
||||
{
|
||||
@ -131,46 +135,56 @@ public class RepoTertiaryManifestProcessorImpl extends AbstractManifestProcessor
|
||||
{
|
||||
/**
|
||||
* An unexpected child - if this node has been transferred then
|
||||
* it needs to be deleted.
|
||||
* it may need to be deleted.
|
||||
*
|
||||
* another repository then we have to prune the alien children
|
||||
* If from another repository then we have to prune the alien children
|
||||
* rather than deleting it.
|
||||
*/
|
||||
log.debug("an unexpected child node:" + child);
|
||||
if(nodeService.hasAspect(childNodeRef, TransferModel.ASPECT_TRANSFERRED))
|
||||
{
|
||||
log.debug("an unexpected transferred child node:" + child);
|
||||
String fromRepositoryId = (String)nodeService.getProperty(childNodeRef, TransferModel.PROP_FROM_REPOSITORY_ID);
|
||||
|
||||
// Yes this is a transferred node. When syncing we only delete nodes that are "from"
|
||||
// the system that is transferring to this repo.
|
||||
if(fromRepositoryId != null && manifestRepositoryId != null)
|
||||
{
|
||||
if(manifestRepositoryId.equalsIgnoreCase(fromRepositoryId))
|
||||
if(nodeService.hasAspect(childNodeRef, TransferModel.ASPECT_ALIEN))
|
||||
{
|
||||
// Yes the manifest repository Id and the from repository Id match.
|
||||
if(nodeService.hasAspect(childNodeRef, TransferModel.ASPECT_ALIEN))
|
||||
/**
|
||||
* This node can't be deleted since it contains alien content
|
||||
* it needs to be "pruned" of the transferring repo's content instead.
|
||||
*/
|
||||
log.debug("node to be deleted contains alien content so needs to be pruned." + childNodeRef);
|
||||
alienProcessor.pruneNode(childNodeRef, fromRepositoryId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Node
|
||||
log.debug("node not alien");
|
||||
if(manifestRepositoryId.equalsIgnoreCase(fromRepositoryId))
|
||||
{
|
||||
/**
|
||||
* This node can't be deleted since it contains alien content
|
||||
* it needs to be "pruned" of the transferring repo's content instead.
|
||||
*/
|
||||
log.debug("node to be deleted contains alien content so needs to be pruned." + childNodeRef);
|
||||
alienProcessor.pruneNode(childNodeRef, fromRepositoryId);
|
||||
//pruneNode(childNodeRef, fromRepositoryId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Destination node needs to be deleted.
|
||||
// Yes the manifest repository Id and the from repository Id match.
|
||||
// Destination node if from the transferring repo and needs to be deleted.
|
||||
nodeService.deleteNode(childNodeRef);
|
||||
log.debug("deleted node:" + childNodeRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log.debug("node does not have a transferred aspect");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
log.debug("not sync mode - do nothing");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,161 +216,6 @@ public class RepoTertiaryManifestProcessorImpl extends AbstractManifestProcessor
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Prune out the non aliens from the specified repository
|
||||
// *
|
||||
// * Need to walk the tree downwards pruning any aliens for this repository
|
||||
// *
|
||||
// * Also any folders remaining need to have their invaded by field rippled upwards since they may no
|
||||
// * longer be invaded by the specified repository if all the alien children have been pruned.
|
||||
// *
|
||||
// * @param nodeRef the node to prune
|
||||
// * @param fromRepositoryId the repository id of the nodes to prune.
|
||||
// */
|
||||
// private void pruneNode(NodeRef parentNodeRef, String fromRepositoryId)
|
||||
// {
|
||||
// Stack<NodeRef> nodesToPrune = new Stack<NodeRef>();
|
||||
// Stack<NodeRef> foldersToRecalculate = new Stack<NodeRef>();
|
||||
// nodesToPrune.add(parentNodeRef);
|
||||
//
|
||||
// while(!nodesToPrune.isEmpty())
|
||||
// {
|
||||
// /**
|
||||
// * for all alien children
|
||||
// *
|
||||
// * if from the repo with no (other) aliens - delete
|
||||
// *
|
||||
// * if from the repo with multiple alien invasions - leave alone but process children
|
||||
// */
|
||||
// NodeRef currentNodeRef = nodesToPrune.pop();
|
||||
//
|
||||
// log.debug("pruneNode:" + currentNodeRef);
|
||||
//
|
||||
// if(nodeService.hasAspect(currentNodeRef, TransferModel.ASPECT_ALIEN))
|
||||
// {
|
||||
// // Yes this is an alien node
|
||||
// List<String>invadedBy = (List<String>)nodeService.getProperty(currentNodeRef, TransferModel.PROP_INVADED_BY);
|
||||
// if(invadedBy.contains(fromRepositoryId))
|
||||
// {
|
||||
// if(invadedBy.size() == 1)
|
||||
// {
|
||||
// // we are invaded by a single repository which must be fromRepositoryId
|
||||
// log.debug("pruned - deleted node:" + currentNodeRef);
|
||||
// nodeService.deleteNode(currentNodeRef);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// log.debug("folder has multiple invaders");
|
||||
// // multiple invasion - so it must be a folder
|
||||
// //TODO replace with a more efficient query
|
||||
// List<ChildAssociationRef> refs = nodeService.getChildAssocs(parentNodeRef);
|
||||
// for(ChildAssociationRef ref : refs)
|
||||
// {
|
||||
// if(log.isDebugEnabled())
|
||||
// {
|
||||
// log.debug("will need to check child:" + ref);
|
||||
// }
|
||||
// nodesToPrune.push(ref.getChildRef());
|
||||
//
|
||||
// /**
|
||||
// * This folder can't be deleted so its invaded flag needs to be re-calculated
|
||||
// */
|
||||
// if(!foldersToRecalculate.contains(ref.getParentRef()))
|
||||
// {
|
||||
// foldersToRecalculate.push(ref.getParentRef());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// /**
|
||||
// * Current node has been invaded by another repository
|
||||
// *
|
||||
// * Need to check fromRepositoryId since its children may need to be pruned
|
||||
// */
|
||||
// nodeService.hasAspect(currentNodeRef, TransferModel.ASPECT_TRANSFERRED);
|
||||
// {
|
||||
// String fromRepoId = (String)nodeService.getProperty(currentNodeRef, TransferModel.PROP_FROM_REPOSITORY_ID);
|
||||
// if(fromRepositoryId.equalsIgnoreCase(fromRepoId))
|
||||
// {
|
||||
// log.debug("folder is from the transferring repository");
|
||||
// // invaded from somewhere else - so it must be a folder
|
||||
// List<ChildAssociationRef> refs = nodeService.getChildAssocs(currentNodeRef);
|
||||
// for(ChildAssociationRef ref : refs)
|
||||
// {
|
||||
// if(log.isDebugEnabled())
|
||||
// {
|
||||
// log.debug("will need to check child:" + ref);
|
||||
// }
|
||||
// nodesToPrune.push(ref.getChildRef());
|
||||
//
|
||||
// /**
|
||||
// * This folder can't be deleted so its invaded flag needs to be re-calculated
|
||||
// */
|
||||
// if(!foldersToRecalculate.contains(ref.getParentRef()))
|
||||
// {
|
||||
// foldersToRecalculate.push(ref.getParentRef());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // Current node does not contain alien nodes so it can be deleted.
|
||||
// nodeService.hasAspect(currentNodeRef, TransferModel.ASPECT_TRANSFERRED);
|
||||
// {
|
||||
// String fromRepoId = (String)nodeService.getProperty(currentNodeRef, TransferModel.PROP_FROM_REPOSITORY_ID);
|
||||
// if(fromRepositoryId.equalsIgnoreCase(fromRepoId))
|
||||
// {
|
||||
// // we are invaded by a single repository
|
||||
// log.debug("pruned - deleted non alien node:" + currentNodeRef);
|
||||
// nodeService.deleteNode(currentNodeRef);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Now ripple the "invadedBy" flag upwards.
|
||||
// */
|
||||
//
|
||||
// while(!foldersToRecalculate.isEmpty())
|
||||
// {
|
||||
// NodeRef folderNodeRef = foldersToRecalculate.pop();
|
||||
//
|
||||
// log.debug("recalculate invadedBy :" + folderNodeRef);
|
||||
//
|
||||
// List<String>folderInvadedBy = (List<String>)nodeService.getProperty(folderNodeRef, TransferModel.PROP_INVADED_BY);
|
||||
//
|
||||
// boolean stillInvaded = false;
|
||||
// //TODO need a more efficient query here
|
||||
// List<ChildAssociationRef> refs = nodeService.getChildAssocs(folderNodeRef);
|
||||
// for(ChildAssociationRef ref : refs)
|
||||
// {
|
||||
// NodeRef childNode = ref.getChildRef();
|
||||
// List<String>childInvadedBy = (List<String>)nodeService.getProperty(childNode, TransferModel.PROP_INVADED_BY);
|
||||
//
|
||||
// if(childInvadedBy.contains(fromRepositoryId))
|
||||
// {
|
||||
// log.debug("folder is still invaded");
|
||||
// stillInvaded = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if(!stillInvaded)
|
||||
// {
|
||||
// List<String> newInvadedBy = new ArrayList<String>(folderInvadedBy);
|
||||
// folderInvadedBy.remove(fromRepositoryId);
|
||||
// nodeService.setProperty(folderNodeRef, TransferModel.PROP_INVADED_BY, (Serializable)newInvadedBy);
|
||||
// }
|
||||
// }
|
||||
// log.debug("pruneNode: end");
|
||||
// }
|
||||
|
||||
public void setAlienProcessor(AlienProcessor alienProcessor)
|
||||
{
|
||||
this.alienProcessor = alienProcessor;
|
||||
@ -366,4 +225,13 @@ public class RepoTertiaryManifestProcessorImpl extends AbstractManifestProcessor
|
||||
{
|
||||
return alienProcessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nodeResolver
|
||||
* the nodeResolver to set
|
||||
*/
|
||||
public void setNodeResolver(CorrespondingNodeResolver nodeResolver)
|
||||
{
|
||||
this.nodeResolver = nodeResolver;
|
||||
}
|
||||
}
|
||||
|
@ -968,75 +968,7 @@ public class RepoTransferReceiverImpl implements TransferReceiver,
|
||||
log.debug("on create child association to transferred node");
|
||||
|
||||
final String localRepositoryId = descriptorService.getCurrentRepositoryDescriptor().getId();
|
||||
alienProcessor.onCreateChild(childAssocRef, localRepositoryId);
|
||||
//
|
||||
// ChildAssociationRef currentAssoc = childAssocRef;
|
||||
//
|
||||
// final String localRepositoryId = descriptorService.getCurrentRepositoryDescriptor().getId();
|
||||
//
|
||||
// // TODO Needs to check assoc is a cm:contains or subtype
|
||||
// if(childAssocRef.isPrimary())
|
||||
// {
|
||||
// NodeRef parentNodeRef = currentAssoc.getParentRef();
|
||||
// NodeRef childNodeRef = currentAssoc.getChildRef();
|
||||
//
|
||||
// /**
|
||||
// * Make the new child node ref an alien node
|
||||
// */
|
||||
// setAlien(childNodeRef, localRepositoryId);
|
||||
//
|
||||
// /**
|
||||
// * Now deal with the parents of this alien node
|
||||
// */
|
||||
// while(currentAssoc != null)
|
||||
// {
|
||||
// parentNodeRef = currentAssoc.getParentRef();
|
||||
// childNodeRef = currentAssoc.getChildRef();
|
||||
//
|
||||
// if(nodeService.hasAspect(parentNodeRef, TransferModel.ASPECT_TRANSFERRED) || nodeService.hasAspect(parentNodeRef, TransferModel.ASPECT_ALIEN))
|
||||
// {
|
||||
// if (!isInvaded(parentNodeRef, localRepositoryId))
|
||||
// {
|
||||
// if(log.isDebugEnabled())
|
||||
// {
|
||||
// log.debug("alien invades parent node:" + parentNodeRef + ", repositoryId:" + localRepositoryId);
|
||||
// }
|
||||
//
|
||||
// final NodeRef newAlien = parentNodeRef;
|
||||
//
|
||||
// /**
|
||||
// * Parent may be locked or not be editable by the current user
|
||||
// * turn off auditing and lock service for this transaction and
|
||||
// * run as admin.
|
||||
// */
|
||||
// RunAsWork<Void> actionRunAs = new RunAsWork<Void>()
|
||||
// {
|
||||
// public Void doWork() throws Exception
|
||||
// {
|
||||
// behaviourFilter.disableBehaviour(newAlien, ContentModel.ASPECT_AUDITABLE);
|
||||
// behaviourFilter.disableBehaviour(newAlien, ContentModel.ASPECT_LOCKABLE);
|
||||
// setAlien(newAlien, localRepositoryId);
|
||||
// return null;
|
||||
// }
|
||||
// };
|
||||
// AuthenticationUtil.runAs(actionRunAs, AuthenticationUtil.getSystemUserName());
|
||||
//
|
||||
// // Yes the parent has been invaded so step up to the parent's parent
|
||||
// currentAssoc = nodeService.getPrimaryParent(parentNodeRef);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// log.debug("parent node is already invaded");
|
||||
// currentAssoc = null;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// log.debug("parent is not a transferred node");
|
||||
// currentAssoc = null;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
alienProcessor.onCreateChild(childAssocRef, localRepositoryId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1048,175 +980,8 @@ public class RepoTransferReceiverImpl implements TransferReceiver,
|
||||
{
|
||||
log.debug("on delete node - need to check for transferred node");
|
||||
alienProcessor.beforeDeleteAlien(deletedNodeRef);
|
||||
//
|
||||
// List<String>stuff = (List<String>)nodeService.getProperty(deletedNodeRef, TransferModel.PROP_INVADED_BY);
|
||||
//
|
||||
// Vector<String> exInvaders = new Vector<String>(stuff);
|
||||
//
|
||||
// ChildAssociationRef currentAssoc = nodeService.getPrimaryParent(deletedNodeRef);
|
||||
//
|
||||
// while(currentAssoc != null && exInvaders != null && exInvaders.size() > 0)
|
||||
// {
|
||||
// NodeRef parentNodeRef = currentAssoc.getParentRef();
|
||||
// NodeRef currentNodeRef = currentAssoc.getChildRef();
|
||||
//
|
||||
// /**
|
||||
// * Does the parent have alien invaders ?
|
||||
// */
|
||||
// if(nodeService.hasAspect(parentNodeRef, TransferModel.ASPECT_ALIEN))
|
||||
// {
|
||||
// log.debug("parent node is alien - check siblings");
|
||||
//
|
||||
// /**
|
||||
// * For each invader of the deletedNode
|
||||
// */
|
||||
// Iterator<String> i = exInvaders.listIterator();
|
||||
// while(i.hasNext())
|
||||
// {
|
||||
// String exInvader = i.next();
|
||||
// log.debug("Checking exInvader:" + exInvader);
|
||||
//
|
||||
// /**
|
||||
// * Check the siblings of this node to see whether there are any other alien nodes for this invader.
|
||||
// */
|
||||
// //TODO replace with a more efficient query
|
||||
// List<ChildAssociationRef> refs = nodeService.getChildAssocs(parentNodeRef);
|
||||
//
|
||||
// for(ChildAssociationRef ref : refs)
|
||||
// {
|
||||
// NodeRef childRef = ref.getChildRef();
|
||||
// List<String>invadedBy = (List<String>)nodeService.getProperty(childRef, TransferModel.PROP_INVADED_BY);
|
||||
//
|
||||
// if(childRef.equals(currentNodeRef))
|
||||
// {
|
||||
// // do nothing - this is the node we are working with.
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if(invadedBy != null && invadedBy.contains(exInvader))
|
||||
// {
|
||||
// // There is a sibling so remove this from the list of ex invaders.
|
||||
// log.debug("yes there is a sibling so it remains an invader");
|
||||
// i.remove();
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// } // for each child assoc
|
||||
//
|
||||
// } // for each invader
|
||||
//
|
||||
// log.debug("end of checking siblings");
|
||||
//
|
||||
// if(exInvaders.size() > 0)
|
||||
// {
|
||||
// log.debug("removing invaders from parent node:" + parentNodeRef);
|
||||
// List<String> parentInvaders = (List<String>)nodeService.getProperty(parentNodeRef, TransferModel.PROP_INVADED_BY);
|
||||
//
|
||||
// final List<String> newInvaders = new ArrayList<String>(10);
|
||||
// for(String invader : parentInvaders)
|
||||
// {
|
||||
// if(exInvaders.contains(invader))
|
||||
// {
|
||||
// log.debug("removing invader:" + invader);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// newInvaders.add(invader);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// final NodeRef oldAlien = parentNodeRef;
|
||||
//
|
||||
// /**
|
||||
// * Parent may be locked or not be editable by the current user
|
||||
// * turn off auditing and lock service for this transaction and
|
||||
// * run as admin.
|
||||
// */
|
||||
// RunAsWork<Void> actionRunAs = new RunAsWork<Void>()
|
||||
// {
|
||||
// public Void doWork() throws Exception
|
||||
// {
|
||||
// behaviourFilter.disableBehaviour(oldAlien, ContentModel.ASPECT_AUDITABLE);
|
||||
// behaviourFilter.disableBehaviour(oldAlien, ContentModel.ASPECT_LOCKABLE);
|
||||
// if(newInvaders.size() > 0)
|
||||
// {
|
||||
// nodeService.setProperty(oldAlien, TransferModel.PROP_INVADED_BY, (Serializable)newInvaders);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// log.debug("parent node no is no longer alien");
|
||||
// nodeService.removeAspect(oldAlien, TransferModel.ASPECT_ALIEN);
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
// };
|
||||
// AuthenticationUtil.runAs(actionRunAs, AuthenticationUtil.getSystemUserName());
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Now step up to the parent's parent
|
||||
// */
|
||||
// currentAssoc = nodeService.getPrimaryParent(parentNodeRef);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// log.debug("parent is not an alien node");
|
||||
// currentAssoc = null;
|
||||
// }
|
||||
// } // end of while
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Is this node invaded ?
|
||||
// * @param nodeRef
|
||||
// * @param invader
|
||||
// * @return true, this node has been invaded by the invader
|
||||
// */
|
||||
// private boolean isInvaded(NodeRef nodeRef, String invader)
|
||||
// {
|
||||
// List<String>invadedBy = (List<String>)nodeService.getProperty(nodeRef, TransferModel.PROP_INVADED_BY);
|
||||
//
|
||||
// if(invadedBy == null)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// return invadedBy.contains(invader);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Mark the specified node as an alien node, invadedby the invader.
|
||||
// * @param newAlien
|
||||
// * @param invader
|
||||
// */
|
||||
// private void setAlien(NodeRef newAlien, String invader)
|
||||
// {
|
||||
// // Introduce a Multi-valued property
|
||||
// List<String> invadedBy = (List<String>)nodeService.getProperty(newAlien,
|
||||
// TransferModel.PROP_INVADED_BY);
|
||||
//
|
||||
// if(invadedBy == null)
|
||||
// {
|
||||
// nodeService.setProperty(newAlien, TransferModel.PROP_ALIEN, Boolean.TRUE);
|
||||
// invadedBy = new ArrayList<String>(1);
|
||||
// }
|
||||
// invadedBy.add(invader);
|
||||
//
|
||||
// /**
|
||||
// * Set the invaded by property
|
||||
// */
|
||||
// nodeService.setProperty(newAlien, TransferModel.PROP_INVADED_BY, (Serializable) invadedBy);
|
||||
//
|
||||
// /**
|
||||
// * Experiment with a residual property
|
||||
// */
|
||||
// nodeService.setProperty(newAlien, QName.createQName(TransferModel.TRANSFER_MODEL_1_0_URI,
|
||||
// "invader" + invader), Boolean.TRUE);
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
public void setDescriptorService(DescriptorService descriptorService)
|
||||
{
|
||||
this.descriptorService = descriptorService;
|
||||
|
@ -45,7 +45,7 @@ public interface TransferModel
|
||||
*/
|
||||
static final QName ASPECT_ALIEN = QName.createQName(TRANSFER_MODEL_1_0_URI, "alien");
|
||||
static final QName PROP_INVADED_BY = QName.createQName(TRANSFER_MODEL_1_0_URI, "invadedBy");
|
||||
static final QName PROP_ALIEN = QName.createQName(TRANSFER_MODEL_1_0_URI, "alien");
|
||||
// static final QName PROP_ALIEN = QName.createQName(TRANSFER_MODEL_1_0_URI, "alien");
|
||||
|
||||
/*
|
||||
* Type : Transfer Group
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user