Fixed ETHREEOH-1719: Renaming 'Web Project' makes it a DM space and the AVMstore gets corrupted

- An injected list of namespaces determine whether a node's association path QName is modified
   during a rename or not:
      <property name="systemNamespaces">
         <list>
            <value>http://www.alfresco.org/model/application/1.0</value>
            <value>http://www.alfresco.org/model/site/1.0</value>
         </list>
      </property>

 - Added a method to FileFolderService to specify the association QName on creation
   This is used by the tests, but can be used by apps as well.


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@14262 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2009-05-11 12:04:55 +00:00
parent db96926f4b
commit 4ed216c5e6
4 changed files with 94 additions and 10 deletions

View File

@@ -14,6 +14,12 @@
<property name="contentService"><ref bean="contentService" /></property> <property name="contentService"><ref bean="contentService" /></property>
<property name="mimetypeService"><ref bean="mimetypeService" /></property> <property name="mimetypeService"><ref bean="mimetypeService" /></property>
<property name="systemNamespaces">
<list>
<value>http://www.alfresco.org/model/application/1.0</value>
<value>http://www.alfresco.org/model/site/1.0</value>
</list>
</property>
<property name="systemPaths"> <property name="systemPaths">
<list> <list>
<value>/${spaces.company_home.childname}</value> <value>/${spaces.company_home.childname}</value>

View File

@@ -103,6 +103,7 @@ public class FileFolderServiceImpl implements FileFolderService
private SearchService searchService; private SearchService searchService;
private ContentService contentService; private ContentService contentService;
private MimetypeService mimetypeService; private MimetypeService mimetypeService;
private Set<String> systemNamespaces;
// TODO: Replace this with a more formal means of identifying "system" folders (i.e. aspect or UUID) // TODO: Replace this with a more formal means of identifying "system" folders (i.e. aspect or UUID)
private List<String> systemPaths; private List<String> systemPaths;
@@ -112,6 +113,7 @@ public class FileFolderServiceImpl implements FileFolderService
*/ */
public FileFolderServiceImpl() public FileFolderServiceImpl()
{ {
systemNamespaces = new HashSet<String>(5);
} }
public void setNamespaceService(NamespaceService namespaceService) public void setNamespaceService(NamespaceService namespaceService)
@@ -149,6 +151,22 @@ public class FileFolderServiceImpl implements FileFolderService
this.mimetypeService = mimetypeService; this.mimetypeService = mimetypeService;
} }
/**
* Set the namespaces that should be treated as 'system' namespaces.
* <p>
* When files or folders are renamed, the association path (QName) is normally
* modified to follow the name of the node. If, however, the namespace of the
* patch QName is in this list, the association path is left alone. This allows
* parts of the application to use well-known paths even if the end-user is
* able to modify the objects <b>cm:name</b> value.
*
* @param systemNamespaces a list of system namespaces
*/
public void setSystemNamespaces(List<String> systemNamespaces)
{
this.systemNamespaces.addAll(systemNamespaces);
}
// TODO: Replace this with a more formal means of identifying "system" folders (i.e. aspect or UUID) // TODO: Replace this with a more formal means of identifying "system" folders (i.e. aspect or UUID)
public void setSystemPaths(List<String> systemPaths) public void setSystemPaths(List<String> systemPaths)
{ {
@@ -572,8 +590,9 @@ public class FileFolderServiceImpl implements FileFolderService
} }
} }
QName existingQName = assocRef.getQName();
QName qname; QName qname;
if (nameChanged) if (nameChanged && !systemNamespaces.contains(existingQName.getNamespaceURI()))
{ {
// Change the localname to match the new name // Change the localname to match the new name
qname = QName.createQName( qname = QName.createQName(
@@ -583,9 +602,7 @@ public class FileFolderServiceImpl implements FileFolderService
else else
{ {
// Keep the localname // Keep the localname
qname = QName.createQName( qname = existingQName;
assocRef.getQName().getNamespaceURI(),
assocRef.getQName().getLocalName());
} }
QName targetParentType = nodeService.getType(targetParentRef); QName targetParentType = nodeService.getType(targetParentRef);
@@ -714,6 +731,16 @@ public class FileFolderServiceImpl implements FileFolderService
} }
public FileInfo create(NodeRef parentNodeRef, String name, QName typeQName) throws FileExistsException public FileInfo create(NodeRef parentNodeRef, String name, QName typeQName) throws FileExistsException
{
return createImpl(parentNodeRef, name, typeQName, null);
}
public FileInfo create(NodeRef parentNodeRef, String name, QName typeQName, QName assocQName) throws FileExistsException
{
return createImpl(parentNodeRef, name, typeQName, assocQName);
}
private FileInfo createImpl(NodeRef parentNodeRef, String name, QName typeQName, QName assocQName) throws FileExistsException
{ {
// file or folder // file or folder
boolean isFolder = false; boolean isFolder = false;
@@ -738,16 +765,19 @@ public class FileFolderServiceImpl implements FileFolderService
} }
// create the node // create the node
QName qname = QName.createQName( if (assocQName == null)
NamespaceService.CONTENT_MODEL_1_0_URI, {
QName.createValidLocalName(name)); assocQName = QName.createQName(
NamespaceService.CONTENT_MODEL_1_0_URI,
QName.createValidLocalName(name));
}
ChildAssociationRef assocRef = null; ChildAssociationRef assocRef = null;
try try
{ {
assocRef = nodeService.createNode( assocRef = nodeService.createNode(
parentNodeRef, parentNodeRef,
ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS,
qname, assocQName,
typeQName, typeQName,
properties); properties);
} }

View File

@@ -299,6 +299,35 @@ public class FileFolderServiceImplTest extends TestCase
assertNotNull("Folder info for new name is not present", checkInfo); assertNotNull("Folder info for new name is not present", checkInfo);
} }
public void testRenameWithoutAssocQNameChange() throws Exception
{
FileInfo folderInfo = getByName(NAME_L0_FOLDER_A, true);
assertNotNull(folderInfo);
NodeRef folderNodeRef = folderInfo.getNodeRef();
// Create a child file
QName assocQName = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "abc");
NodeRef newFileNodeRef = fileFolderService.create(
folderNodeRef,
"AnotherFile.txt",
ContentModel.TYPE_CONTENT,
assocQName).getNodeRef();
// Make sure that the correct association QName was used
QName checkQName = nodeService.getPrimaryParent(newFileNodeRef).getQName();
assertEquals(
"The given assoc QName was not used for the path",
assocQName,
checkQName);
// Rename
String newName = "AnotherFile-new.txt";
folderInfo = fileFolderService.rename(newFileNodeRef, newName);
// Make sure that the association QName did not change
checkQName = nodeService.getPrimaryParent(newFileNodeRef).getQName();
assertEquals(
"The given assoc QName was not used for the path after a rename",
assocQName,
nodeService.getPrimaryParent(newFileNodeRef).getQName());
}
public void testRenameDuplicate() throws Exception public void testRenameDuplicate() throws Exception
{ {
FileInfo folderInfo = getByName(NAME_L0_FOLDER_A, true); FileInfo folderInfo = getByName(NAME_L0_FOLDER_A, true);

View File

@@ -169,18 +169,37 @@ public interface FileFolderService
throws FileExistsException, FileNotFoundException; throws FileExistsException, FileNotFoundException;
/** /**
* Create a file or folder; or any valid node of type derived from file or folder * Create a file or folder; or any valid node of type derived from file or folder.
* <p>
* The association QName for the patch defaults to <b>cm:filename</b> i.e. the
* <b>Content Model</b> namespace with the filename as the local name.
* *
* @param parentNodeRef the parent node. The parent must be a valid * @param parentNodeRef the parent node. The parent must be a valid
* {@link org.alfresco.model.ContentModel#TYPE_CONTAINER container}. * {@link org.alfresco.model.ContentModel#TYPE_FOLDER folder}.
* @param name the name of the node * @param name the name of the node
* @param typeQName the type to create * @param typeQName the type to create
* @return Returns the new node's file information * @return Returns the new node's file information
* @throws FileExistsException * @throws FileExistsException
*
* @see {@link #create(NodeRef, String, QName, QName)}
*/ */
@Auditable(key = Auditable.Key.ARG_0, parameters = {"parentNodeRef", "name", "typeQName"}) @Auditable(key = Auditable.Key.ARG_0, parameters = {"parentNodeRef", "name", "typeQName"})
public FileInfo create(NodeRef parentNodeRef, String name, QName typeQName) throws FileExistsException; public FileInfo create(NodeRef parentNodeRef, String name, QName typeQName) throws FileExistsException;
/**
* Create a file or folder; or any valid node of type derived from file or folder
*
* @param parentNodeRef the parent node. The parent must be a valid
* {@link org.alfresco.model.ContentModel#TYPE_FOLDER folder}.
* @param name the name of the node
* @param typeQName the type to create
* @param assocQName the association QName to set for the path (may be <tt>null</tt>).
* @return Returns the new node's file information
* @throws FileExistsException
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {"parentNodeRef", "name", "typeQName"})
public FileInfo create(NodeRef parentNodeRef, String name, QName typeQName, QName assocQName) throws FileExistsException;
/** /**
* Delete a file or folder * Delete a file or folder
* *