ML Authentication Issues:

- Everyone, including guest, gets explicit full rights to each new cm:mlContainer instance.
 - The MultilingualContentService better permission checks against the content nodes that go in and out of it.
 - Changed some of the API return values to be more explicit about whether the cm:mlContainer or cm:mlDocument is required.
 - Added explicit tests to ensure that even guest is able to manipulate the cm:mlContainer.
ML Languages List:
 - The default value is now punted to the top of the list.
Various neatening.


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5816 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2007-05-31 03:42:59 +00:00
parent cc2705ef49
commit e07a0a4c4b
11 changed files with 191 additions and 137 deletions

View File

@@ -52,6 +52,10 @@ import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.BaseSpringTest;
/**
* @author Andy Hind
*/
@SuppressWarnings("unused")
public class AuditServiceTest extends BaseSpringTest
{

View File

@@ -212,19 +212,29 @@ public class ContentFilterLanguagesMap implements ContentFilterLanguagesService
String value = langElem.getValue();
String def = langElem.getAttribute(ATTR_DEFAULT);
orderedLangCodes.add(code);
languagesByCode.put(code, value);
if(def != null && Boolean.parseBoolean(def))
boolean isDefault = (def != null && Boolean.parseBoolean(def));
if(isDefault)
{
if(defaultLanguage != null)
{
logger.warn("Ignoring default attribute is not unique le last matched will be used");
logger.warn("Content filter default language is not unique: " + code);
}
else
{
this.defaultLanguage = code;
}
this.defaultLanguage = code;
}
if (defaultLanguage == code)
{
orderedLangCodes.add(0, code);
}
else
{
orderedLangCodes.add(code);
}
}
// make the collections read-only

View File

@@ -48,6 +48,7 @@ import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.namespace.NamespaceService;
@@ -85,6 +86,7 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
private NodeService nodeService;
private SearchService searchService;
private VersionService versionService;
private PermissionService permissionService;
private SearchParameters searchParametersMLRoot;
private ContentFilterLanguagesService contentFilterLanguagesService;
private FileFolderService fileFolderService;
@@ -133,13 +135,30 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
{
NodeRef mlContainerRootNodeRef = getMLContainerRoot();
// Create the container
PropertyMap versionProperties = new PropertyMap();
versionProperties.put(ContentModel.PROP_AUTO_VERSION, Boolean.FALSE);
versionProperties.put(ContentModel.PROP_INITIAL_VERSION, Boolean.FALSE);
ChildAssociationRef assocRef = nodeService.createNode(
mlContainerRootNodeRef,
ContentModel.ASSOC_CHILDREN,
QNAME_ML_CONTAINER,
ContentModel.TYPE_MULTILINGUAL_CONTAINER);
// done
return assocRef.getChildRef();
ContentModel.TYPE_MULTILINGUAL_CONTAINER,
versionProperties);
NodeRef mlContainerNodeRef = assocRef.getChildRef();
// TODO: Examine the usage of versioning - why is autoversioning on and used in the UI?
// // The model makes the container versionable by default, but why?
// nodeService.addAspect(mlContainerNodeRef, ContentModel.ASPECT_VERSIONABLE, versionProperties);
// Set the permissions to allow anything by anyone
permissionService.setPermission(
mlContainerNodeRef,
PermissionService.ALL_AUTHORITIES,
PermissionService.ALL_PERMISSIONS, true);
permissionService.setPermission(
mlContainerNodeRef,
PermissionService.GUEST_AUTHORITY,
PermissionService.ALL_PERMISSIONS, true);
// Done
return mlContainerNodeRef;
}
/**
@@ -255,7 +274,8 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
{
PropertyMap properties = new PropertyMap();
properties.put(ContentModel.PROP_LOCALE, locale);
nodeService.addAspect(contentNodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT, properties);
nodeService.addAspect(contentNodeRef, ContentModel.ASPECT_LOCALIZED, properties);
nodeService.addAspect(contentNodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT, null);
}
else
{
@@ -341,7 +361,7 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
}
/** @inheritDoc */
public NodeRef makeTranslation(NodeRef contentNodeRef, Locale locale)
public void makeTranslation(NodeRef contentNodeRef, Locale locale)
{
NodeRef mlContainerNodeRef = makeTranslationImpl(null, contentNodeRef, locale);
// done
@@ -352,7 +372,6 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
" locale: " + locale + "\n" +
" container: " + mlContainerNodeRef);
}
return mlContainerNodeRef;
}
/** @inheritDoc */
@@ -410,32 +429,20 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
}
/** @inheritDoc */
public NodeRef addTranslation(NodeRef newTranslationNodeRef, NodeRef translationOfNodeRef, Locale locale)
public void addTranslation(NodeRef newTranslationNodeRef, NodeRef translationOfNodeRef, Locale locale)
{
NodeRef mlContainerNodeRef = null;
// Were we given the translation or the container
QName typeQName = nodeService.getType(translationOfNodeRef);
if (typeQName.equals(ContentModel.TYPE_MULTILINGUAL_CONTAINER))
{
// We have the container
mlContainerNodeRef = translationOfNodeRef;
}
else
{
// Get the container
mlContainerNodeRef = getOrCreateMLContainer(translationOfNodeRef, false);
}
// Get the container
NodeRef mlContainerNodeRef = getOrCreateMLContainer(translationOfNodeRef, false);
// Use the existing container to make the new content into a translation
makeTranslationImpl(mlContainerNodeRef, newTranslationNodeRef, locale);
// done
if (logger.isDebugEnabled())
{
logger.debug("Added a translation: \n" +
" Translation of: " + translationOfNodeRef + " of type " + typeQName + "\n" +
" Translation of: " + translationOfNodeRef + "\n" +
" New translation: " + newTranslationNodeRef + "\n" +
" Locale: " + locale);
}
return mlContainerNodeRef;
}
/** @inheritDoc */
@@ -661,7 +668,7 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
Locale nearestLocale = I18NUtil.getNearestLocale(containerLocale, locales);
if (nearestLocale == null)
{
// There is pivot translation
// There is no pivot translation
return null;
}
else
@@ -675,9 +682,8 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
*/
public NodeRef addEmptyTranslation(NodeRef translationOfNodeRef, String name, Locale locale)
{
QName typeQName = nodeService.getType(translationOfNodeRef);
boolean hasMLAspect = nodeService.hasAspect(translationOfNodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
if (hasMLAspect || typeQName.equals(ContentModel.TYPE_MULTILINGUAL_CONTAINER))
if (hasMLAspect)
{
// Get the pivot translation
NodeRef pivotTranslationNodeRef = getPivotTranslation(translationOfNodeRef);
@@ -688,22 +694,13 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
}
else
{
// We use the given translation, provided it is an actual translation
if (!hasMLAspect)
{
throw new IllegalArgumentException(
"The node provided is not associated with a pivot translation " +
"and is not in itself a translation: \n" +
" Translation: " + translationOfNodeRef + "\n" +
" Locale: " + locale);
}
// We use the given translation
}
}
else
{
throw new IllegalArgumentException(
"Node must have aspect " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT +
" or be a " + ContentModel.TYPE_MULTILINGUAL_CONTAINER + ": \n" +
"Node must have aspect " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT + ": \n" +
" Translation: " + translationOfNodeRef + "\n" +
" Locale: " + locale);
}
@@ -773,7 +770,7 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
if (logger.isDebugEnabled())
{
logger.debug("Added an empty translation: \n" +
" Translation of: " + translationOfNodeRef + " of type " + typeQName + "\n" +
" Translation of: " + translationOfNodeRef + "\n" +
" New translation: " + newTranslationNodeRef + "\n" +
" Locale: " + locale);
}
@@ -796,6 +793,11 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
this.versionService = versionService;
}
public void setPermissionService(PermissionService permissionService)
{
this.permissionService = permissionService;
}
public void setContentFilterLanguagesService(ContentFilterLanguagesService contentFilterLanguagesService)
{
this.contentFilterLanguagesService = contentFilterLanguagesService;
@@ -805,9 +807,4 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
{
this.fileFolderService = fileFolderService;
}
public void renameWithMLExtension(NodeRef translationNodeRef)
{
throw new UnsupportedOperationException();
}
}

View File

@@ -108,7 +108,8 @@ public class EmptyTranslationAspectTest extends AbstractMultilingualTestCases {
NodeRef empty = null;
NodeRef mlContainer = multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
NodeRef mlContainer = multilingualContentService.getTranslationContainer(pivot);
multilingualContentService.addTranslation(otherTranslation, pivot, Locale.KOREAN);
empty = multilingualContentService.addEmptyTranslation(pivot, "empty_" + System.currentTimeMillis(), Locale.CHINESE);

View File

@@ -49,7 +49,8 @@ public class MLContainerTypeTest extends AbstractMultilingualTestCases
NodeRef trans3 = createContent();
NodeRef empty = null;
NodeRef mlContainer = multilingualContentService.makeTranslation(trans1, Locale.FRENCH);
multilingualContentService.makeTranslation(trans1, Locale.FRENCH);
NodeRef mlContainer = multilingualContentService.getTranslationContainer(trans1);
multilingualContentService.addTranslation(trans2, trans1, Locale.GERMAN);
multilingualContentService.addTranslation(trans3, trans1, Locale.ITALIAN);
empty = multilingualContentService.addEmptyTranslation(trans1, "EMPTY_" + System.currentTimeMillis(), Locale.JAPANESE);

View File

@@ -30,11 +30,15 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import net.sf.acegisecurity.Authentication;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionHistory;
@@ -49,45 +53,30 @@ public class MultilingualContentServiceImplTest extends AbstractMultilingualTest
public void testMakeTranslation() throws Exception
{
NodeRef contentNodeRef = createContent();
NodeRef chineseContentNodeRef = createContent();
// Turn the content into a translation with the appropriate structures
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(contentNodeRef, Locale.CHINESE);
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(chineseContentNodeRef);
// Check it
assertNotNull("Container not created", mlContainerNodeRef);
// Check the container child count
assertEquals("Incorrect number of child nodes", 1, nodeService.getChildAssocs(mlContainerNodeRef).size());
}
public void testAddTranslationUsingContainer() throws Exception
{
// Make a container with a single translation
NodeRef chineseContentNodeRef = createContent();
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
// Create some more content
NodeRef frenchContentNodeRef = createContent();
// Make this a translation of the Chinese
NodeRef newMLContainerNodeRef = multilingualContentService.addTranslation(
frenchContentNodeRef,
mlContainerNodeRef,
Locale.FRENCH);
// Make sure that the original container was used
assertEquals("Existing container should have been used", mlContainerNodeRef, newMLContainerNodeRef);
// Check the container child count
assertEquals("Incorrect number of child nodes", 2, nodeService.getChildAssocs(mlContainerNodeRef).size());
}
public void testAddTranslationUsingContent() throws Exception
{
// Make a container with a single translation
NodeRef chineseContentNodeRef = createContent();
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(chineseContentNodeRef);
// Create some more content
NodeRef frenchContentNodeRef = createContent();
// Make this a translation of the Chinese
NodeRef newMLContainerNodeRef = multilingualContentService.addTranslation(
multilingualContentService.addTranslation(
frenchContentNodeRef,
chineseContentNodeRef,
Locale.FRENCH);
NodeRef newMLContainerNodeRef = multilingualContentService.getTranslationContainer(frenchContentNodeRef);
// Make sure that the original container was used
assertEquals("Existing container should have been used", mlContainerNodeRef, newMLContainerNodeRef);
// Check the container child count
@@ -113,9 +102,9 @@ public class MultilingualContentServiceImplTest extends AbstractMultilingualTest
NodeRef nodeRef2 = createContent();
NodeRef nodeRef3 = createContent();
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(nodeRef1, loc1);
multilingualContentService.makeTranslation(nodeRef1, loc1);
List<Locale> missing = multilingualContentService.getMissingTranslations(mlContainerNodeRef, false);
List<Locale> missing = multilingualContentService.getMissingTranslations(nodeRef1, false);
// make sure that the missing language list size is correct
assertFalse("Missing Translation Size false. " +
@@ -124,13 +113,13 @@ public class MultilingualContentServiceImplTest extends AbstractMultilingualTest
// make sure that the missing language list is correct
assertFalse("Missing Translation List false. Locale " + loc1 + " found", missing.contains(loc1.toString()));
multilingualContentService.addTranslation(nodeRef2, mlContainerNodeRef, loc2);
multilingualContentService.addTranslation(nodeRef3, mlContainerNodeRef, loc3);
multilingualContentService.addTranslation(nodeRef2, nodeRef1, loc2);
multilingualContentService.addTranslation(nodeRef3, nodeRef1, loc3);
// Add the missing translations in
missing = multilingualContentService.getMissingTranslations(nodeRef1, false);
missing = multilingualContentService.getMissingTranslations(mlContainerNodeRef, false);
// make sure that the missing language list size is correct
// Make sure that the missing language list size is correct
assertFalse("Missing Translation Size false. " +
"Real size : " + missing.size() + ". Normal Size " + (langListSize - 3), missing.size() != (langListSize - 3));
@@ -141,29 +130,30 @@ public class MultilingualContentServiceImplTest extends AbstractMultilingualTest
public void testGetTranslationForLocale() throws Exception
{
NodeRef chineseContentNodeRef = createContent();
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
NodeRef frenchContentNodeRef = createContent();
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
// Get the chinese translation
assertEquals("Chinese translation should be present",
chineseContentNodeRef,
multilingualContentService.getTranslationForLocale(mlContainerNodeRef, Locale.CHINESE));
multilingualContentService.getTranslationForLocale(chineseContentNodeRef, Locale.CHINESE));
// Get the french translation
assertEquals("French translation should be present",
frenchContentNodeRef,
multilingualContentService.getTranslationForLocale(mlContainerNodeRef, Locale.FRENCH));
multilingualContentService.getTranslationForLocale(chineseContentNodeRef, Locale.FRENCH));
// The Italian should return the pivot
assertEquals("French translation should be present",
chineseContentNodeRef,
multilingualContentService.getTranslationForLocale(mlContainerNodeRef, Locale.ITALIAN));
multilingualContentService.getTranslationForLocale(chineseContentNodeRef, Locale.ITALIAN));
}
@SuppressWarnings("unused")
public void testGetPivotTranslation() throws Exception
{
NodeRef chineseContentNodeRef = createContent();
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(chineseContentNodeRef);
// make sure that the pivot language is set
assertNotNull("Pivot language not set", nodeService.getProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE));
@@ -189,10 +179,10 @@ public class MultilingualContentServiceImplTest extends AbstractMultilingualTest
public void testCreateEmptyTranslation() throws Exception
{
NodeRef chineseContentNodeRef = createContent("Document.txt");
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
// This should use the pivot language
NodeRef emptyNodeRef = multilingualContentService.addEmptyTranslation(mlContainerNodeRef, "Document.txt", Locale.CANADA);
NodeRef emptyNodeRef = multilingualContentService.addEmptyTranslation(chineseContentNodeRef, "Document.txt", Locale.CANADA);
// Ensure that the empty translation is not null
assertNotNull("The creation of the empty document failed ", emptyNodeRef);
@@ -215,7 +205,7 @@ public class MultilingualContentServiceImplTest extends AbstractMultilingualTest
public void testCreateEmptyTranslationNames() throws Exception
{
NodeRef chineseContentNodeRef = createContent("Document.txt");
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
NodeRef koreanContentNodeRef = createContent("Document_ko.txt");
multilingualContentService.addTranslation(koreanContentNodeRef, chineseContentNodeRef, Locale.KOREAN);
// Create with a null name, and off a non-pivot just to be sure
@@ -227,14 +217,14 @@ public class MultilingualContentServiceImplTest extends AbstractMultilingualTest
assertEquals("Empty translation name not generated correctly.", "Document_en_CA.txt", nullName);
// Create with the same name
NodeRef sameNameNodeRef = multilingualContentService.addEmptyTranslation(
mlContainerNodeRef,
chineseContentNodeRef,
"Document.txt",
Locale.CANADA_FRENCH);
String sameName = fileFolderService.getFileInfo(sameNameNodeRef).getName();
assertEquals("Empty translation name not generated correctly.", "Document_fr_CA.txt", sameName);
// Create with a different name
NodeRef differentNameNodeRef = multilingualContentService.addEmptyTranslation(
mlContainerNodeRef,
chineseContentNodeRef,
"Document2.txt",
Locale.JAPANESE);
String differentName = fileFolderService.getFileInfo(differentNameNodeRef).getName();
@@ -249,9 +239,11 @@ public class MultilingualContentServiceImplTest extends AbstractMultilingualTest
NodeRef frenchContentNodeRef = createContent();
NodeRef japaneseContentNodeRef = createContent();
// Add to container
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
multilingualContentService.addTranslation(frenchContentNodeRef, mlContainerNodeRef, Locale.FRENCH);
multilingualContentService.addTranslation(japaneseContentNodeRef, mlContainerNodeRef, Locale.JAPANESE);
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
multilingualContentService.addTranslation(japaneseContentNodeRef, chineseContentNodeRef, Locale.JAPANESE);
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(chineseContentNodeRef);
// Check the container child count
assertEquals("Incorrect number of child nodes", 3, nodeService.getChildAssocs(mlContainerNodeRef).size());
@@ -290,4 +282,64 @@ public class MultilingualContentServiceImplTest extends AbstractMultilingualTest
int count = translationsByLocale.size();
}
}
public void testGetTranslationContainerPermissions() throws Exception
{
// Grant the guest user rights to our working folder
PermissionService permissionService = serviceRegistry.getPermissionService();
AuthenticationComponent authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
permissionService.setPermission(
folderNodeRef,
PermissionService.GUEST_AUTHORITY,
PermissionService.ALL_PERMISSIONS,
true);
// Get the current authentication
Authentication authentication = authenticationComponent.getCurrentAuthentication();
try
{
authenticationComponent.setGuestUserAsCurrentUser();
// Create some documents
NodeRef chineseContentNodeRef = createContent();
// Make a translation
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
multilingualContentService.getTranslationContainer(chineseContentNodeRef);
}
finally
{
try { authenticationComponent.setCurrentAuthentication(authentication); } catch (Throwable e) {}
}
}
/**
* Check whether non-admin users can take part in ML document manipulation
*/
public void testPermissions() throws Exception
{
// Grant the guest user rights to our working folder
PermissionService permissionService = serviceRegistry.getPermissionService();
AuthenticationComponent authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
permissionService.setPermission(
folderNodeRef,
PermissionService.GUEST_AUTHORITY,
PermissionService.ALL_PERMISSIONS,
true);
// Get the current authentication
Authentication authentication = authenticationComponent.getCurrentAuthentication();
try
{
authenticationComponent.setGuestUserAsCurrentUser();
// Create some documents
NodeRef chineseContentNodeRef = createContent();
NodeRef frenchContentNodeRef = createContent();
// Do ML work
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
multilingualContentService.addEmptyTranslation(chineseContentNodeRef, null, Locale.JAPANESE);
multilingualContentService.createEdition(chineseContentNodeRef);
}
finally
{
try { authenticationComponent.setCurrentAuthentication(authentication); } catch (Throwable e) {}
}
}
}

View File

@@ -44,7 +44,8 @@ public class MultilingualDocumentAspectTest extends AbstractMultilingualTestCase
public void testCopy() throws Exception
{
NodeRef original = createContent();
NodeRef mlContainer = multilingualContentService.makeTranslation(original, Locale.FRENCH);
multilingualContentService.makeTranslation(original, Locale.FRENCH);
NodeRef mlContainer = multilingualContentService.getTranslationContainer(original);
NodeRef copy =
fileFolderService.copy(original, nodeService.getPrimaryParent(original).getParentRef(), "COPY" + System.currentTimeMillis()).getNodeRef();
@@ -67,7 +68,7 @@ public class MultilingualDocumentAspectTest extends AbstractMultilingualTestCase
NodeRef parent = nodeService.getPrimaryParent(trad1).getParentRef();
NodeRef mlContainer = multilingualContentService.makeTranslation(trad1, Locale.FRENCH);
multilingualContentService.makeTranslation(trad1, Locale.FRENCH);
multilingualContentService.addTranslation(trad2, trad1, Locale.GERMAN);
multilingualContentService.addTranslation(trad3, trad1, Locale.ITALIAN);
@@ -76,7 +77,7 @@ public class MultilingualDocumentAspectTest extends AbstractMultilingualTestCase
// Ensure that the deleted node is romoved from its space
assertEquals("The deleted node must be removed to the space", 2, nodeService.getChildAssocs(parent).size());
// Ensure that the mlContainer doesn't keep an association to the deleted node
assertEquals("The deleted node must be removed to the child associations of the mlContainer", 2, multilingualContentService.getTranslations(mlContainer).size());
assertEquals("The deleted node must be removed to the child associations of the mlContainer", 2, multilingualContentService.getTranslations(trad1).size());
// retore the deleted node
NodeRef restoredNode = nodeArchiveService.restoreArchivedNode(nodeArchiveService.getArchivedNode(trad3)).getRestoredNodeRef();
@@ -84,21 +85,17 @@ public class MultilingualDocumentAspectTest extends AbstractMultilingualTestCase
// Ensure that the restored node is restored to it s original space
assertEquals("The restored node must be restaured to the the space", 3, nodeService.getChildAssocs(parent).size());
// Ensure that the restored node is not linked to the mlContainer
assertEquals("The restored node would not be restaured to the mlContainer", 2, multilingualContentService.getTranslations(mlContainer).size());
assertEquals("The restored node would not be restaured to the mlContainer", 2, multilingualContentService.getTranslations(trad1).size());
// Ensure that the restored node doesn't keep the mlDocument aspect
assertFalse("The restored node can't keep the multilingual aspect", nodeService.hasAspect(restoredNode, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
// DH: The locale is stored on an aspect that is independent of the ML model.
// It is therefore not possible to remove the locale just because the node
// is being unhooked from the ML structures
// // Ensure that the restored node doesn't keep the locale property
// assertNull("The restaured node can't keep the locale property", nodeService.getProperty(restoredNode, ContentModel.PROP_LOCALE));
}
public void testDeletePivot() throws Exception
{
NodeRef pivot = createContent();
NodeRef trans1 = createContent();
NodeRef mlContainer = multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
NodeRef mlContainer = multilingualContentService.getTranslationContainer(pivot);
multilingualContentService.addTranslation(trans1, pivot, Locale.KOREAN);
//nodeService.deleteNode(trans1);
@@ -112,16 +109,13 @@ public class MultilingualDocumentAspectTest extends AbstractMultilingualTestCase
assertTrue("The last translation would not be removed", nodeService.exists(trans1));
// Ensure that trans1 has no mlDocument aspect
assertFalse("The last translation can't keep the multilingual aspect", nodeService.hasAspect(trans1, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
// DH: Here too, the sys:locale property must be left alone as it is independent of the
// ML model
// // Ensure that trans1 has no locale propety
// assertNull("The last translation can't keep the locale property", nodeService.getProperty(trans1, ContentModel.PROP_LOCALE));
}
public void testDeleteLastNode() throws Exception
{
NodeRef pivot = createContent();
NodeRef mlContainer = multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
NodeRef mlContainer = multilingualContentService.getTranslationContainer(pivot);
nodeService.deleteNode(pivot);
@@ -139,7 +133,8 @@ public class MultilingualDocumentAspectTest extends AbstractMultilingualTestCase
{
NodeRef pivot = createContent();
NodeRef trans1 = createContent();
NodeRef mlContainer = multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
NodeRef mlContainer = multilingualContentService.getTranslationContainer(pivot);
multilingualContentService.addTranslation(trans1, pivot, Locale.KOREAN);
// modify the locale for the translation

View File

@@ -198,7 +198,8 @@ public class VersionableAspect implements ContentServicePolicies.OnContentUpdate
if (initialVersion == true)
{
Map<NodeRef, NodeRef> versionedNodeRefs = (Map)AlfrescoTransactionSupport.getResource(KEY_VERSIONED_NODEREFS);
@SuppressWarnings("unchecked")
Map<NodeRef, NodeRef> versionedNodeRefs = (Map<NodeRef, NodeRef>) AlfrescoTransactionSupport.getResource(KEY_VERSIONED_NODEREFS);
if (versionedNodeRefs == null || versionedNodeRefs.containsKey(nodeRef) == false)
{
// Queue create version action

View File

@@ -42,16 +42,6 @@ import org.alfresco.service.cmr.repository.NodeRef;
@PublicService
public interface MultilingualContentService
{
/**
* Rename an existing <b>sys:localized</b> by adding locale suffixes to the base name.
* Where there are name clashes with existing documents, a numerical naming scheme will be
* adopted.
*
* @param localizedNodeRef An existing <b>sys:localized</b>
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {"localizedNodeRef"})
void renameWithMLExtension(NodeRef localizedNodeRef);
/**
* Checks whether an existing document is part of a translation group.
*
@@ -66,12 +56,11 @@ public interface MultilingualContentService
* creating a <b>cm:mlContainer</b> parent. If it is already a translation, then nothing is done.
*
* @param contentNodeRef An existing <b>cm:content</b>
* @return Returns the <b>cm:mlContainer</b> translation parent
*
* @see org.alfresco.model.ContentModel#ASPECT_MULTILINGUAL_DOCUMENT
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {"contentNodeRef", "locale"})
NodeRef makeTranslation(NodeRef contentNodeRef, Locale locale);
void makeTranslation(NodeRef contentNodeRef, Locale locale);
/**
* Removes the node from any associated translations. If the translation is the
@@ -87,14 +76,15 @@ public interface MultilingualContentService
* as necessary.
*
* @param newTranslationNodeRef An existing <b>cm:content</b>
* @param translationOfNodeRef An existing <b>cm:mlDocument</b> or <b>cm:mlContainer</b>
* @return Returns the <b>cm:mlContainer</b> translation parent
* @param translationOfNodeRef An existing <b>cm:mlDocument</b>
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {"newTranslationNodeRef", "translationOfNodeRef", "locale"})
NodeRef addTranslation(NodeRef newTranslationNodeRef, NodeRef translationOfNodeRef, Locale locale);
void addTranslation(NodeRef newTranslationNodeRef, NodeRef translationOfNodeRef, Locale locale);
/**
* Convenience method for super user.
*
* @param translationNodeRef An existing <b>cm:mlDocument</b>
* @return Returns the <b>cm:mlContainer</b> translation parent
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {"translationNodeRef"})
@@ -139,12 +129,12 @@ public interface MultilingualContentService
/**
* Given <b>cm:mlDocument</b> or a <b>cm:mlContainer</b>, this node returns each
* locale that the node hasn't a translation yet.
* Given a <b>cm:mlDocument</b> or <b>cm:mlContainer</b> this node returns each locale for
* which there isn't a translation.
*
* @param localizedNodeRef the <b>cm:mlDocument</b> or the <b>cm:mlContainer</b>
* @param addThisNodeLocale if true, add the locale of the given <b>cm:mlDocument</b> in the list.
* @return
* @param localizedNodeRef the <b>cm:mlDocument</b> or <b>cm:mlContainer</b>
* @param addThisNodeLocale if true, add the locale of the given <b>cm:mlDocument</b> in the list.
* @return Returns a list of missng locales
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {"localizedNodeRef", "addThisNodeLocale"})
List<Locale> getMissingTranslations(NodeRef localizedNodeRef, boolean addThisNodeLocale);
@@ -155,7 +145,8 @@ public interface MultilingualContentService
* for the translations is stored on the parent, and the child that has the same locale is the
* pivot translation.
*
* @param nodeRef a <b>cm:mlDocument</b>
* @param nodeRef a <b>cm:mlDocument</b> translation or <b>cm:mlContainer</b> translation
* container
* @return Returns a corresponding <b>cm:mlDocument</b> that matches the locale of
* of the <b>cm:mlContainer</b>. <tt>null</tt> is returned if there is no
* pivot translation.
@@ -174,7 +165,7 @@ public interface MultilingualContentService
* <p/>
* The necessary translation structures will be created as necessary.
*
* @param translationOfNodeRef An existing <b>cm:mlDocument</b> or <b>cm:mlContainer</b>
* @param translationOfNodeRef An existing <b>cm:mlDocument</b>
* @param name The name of the file to create, or <tt>null</tt> to use
* the default naming convention.
* @return Returns the new created <b>cm:mlEmptyTranslation</b>