Merged V2.1 to HEAD

6383: ML contributions
   6400: AR-1625 Empty translations track pivot translation


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6406 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2007-08-02 23:57:38 +00:00
parent 9f7c5d6443
commit 81e364ebd3
15 changed files with 913 additions and 264 deletions

View File

@@ -68,7 +68,7 @@
<!-- Multilingual specific service --> <!-- Multilingual specific service -->
<bean name="multilingualContentService" class="org.alfresco.repo.model.ml.MultilingualContentServiceImpl" > <bean name="multilingualContentService" class="org.alfresco.repo.model.ml.MultilingualContentServiceImpl" >
<property name="nodeService"> <property name="nodeService">
<ref bean="nodeService" /> <ref bean="mlAwareNodeService" />
</property> </property>
<property name="searchService"> <property name="searchService">
<ref bean="admSearchService" /> <ref bean="admSearchService" />
@@ -82,6 +82,9 @@
<property name="fileFolderService"> <property name="fileFolderService">
<ref bean="fileFolderService" /> <ref bean="fileFolderService" />
</property> </property>
<property name="policyBehaviourFilter">
<ref bean="policyBehaviourFilter" />
</property>
</bean> </bean>
<!-- Edition service --> <!-- Edition service -->

View File

@@ -8,6 +8,9 @@
<property name="nodeService"> <property name="nodeService">
<ref bean="mlAwareNodeService" /> <ref bean="mlAwareNodeService" />
</property> </property>
<property name="multilingualContentService">
<ref bean="multilingualContentService" />
</property>
<property name="dictionaryService"> <property name="dictionaryService">
<ref bean="dictionaryService" /> <ref bean="dictionaryService" />
</property> </property>

View File

@@ -544,6 +544,7 @@
org.alfresco.service.cmr.ml.MultilingualContentService.addEmptyTranslation=ACL_NODE.0.sys:base.Read,ACL_NODE.0.sys:base.CreateChildren org.alfresco.service.cmr.ml.MultilingualContentService.addEmptyTranslation=ACL_NODE.0.sys:base.Read,ACL_NODE.0.sys:base.CreateChildren
org.alfresco.service.cmr.ml.MultilingualContentService.copyTranslationContainer=ACL_NODE.0.sys:base.Read,ACL_NODE.1.sys:base.CreateChildren org.alfresco.service.cmr.ml.MultilingualContentService.copyTranslationContainer=ACL_NODE.0.sys:base.Read,ACL_NODE.1.sys:base.CreateChildren
org.alfresco.service.cmr.ml.MultilingualContentService.moveTranslationContainer=ACL_NODE.0.sys:base.DeleteNode,ACL_NODE.1.sys:base.CreateChildren org.alfresco.service.cmr.ml.MultilingualContentService.moveTranslationContainer=ACL_NODE.0.sys:base.DeleteNode,ACL_NODE.1.sys:base.CreateChildren
org.alfresco.service.cmr.ml.MultilingualContentService.deleteTranslationContainer=ACL_NODE.0.sys:base.DeleteNode,ACL_NODE.0.sys:base.DeleteChildren
</value> </value>
</property> </property>
</bean> </bean>

View File

@@ -120,7 +120,7 @@ public class EditionServiceImpl implements EditionService
// Version the container and its translations // Version the container and its translations
versionService.createVersion(mlContainerToVersion, versionProperties, true); versionService.createVersion(mlContainerToVersion, versionProperties, true);
// 2. Third step: prepare the current edition of the mlContainer // 2. second step: prepare the current edition of the mlContainer
// Get the new starting point node, it will be returned // Get the new starting point node, it will be returned
NodeRef startNode; NodeRef startNode;
@@ -169,6 +169,7 @@ public class EditionServiceImpl implements EditionService
// set the starting translation become the pivot. // set the starting translation become the pivot.
nodeService.setProperty(mlContainerToVersion, ContentModel.PROP_LOCALE, locale); nodeService.setProperty(mlContainerToVersion, ContentModel.PROP_LOCALE, locale);
nodeService.setProperty(mlContainerToVersion, ContentModel.PROP_AUTHOR, author); nodeService.setProperty(mlContainerToVersion, ContentModel.PROP_AUTHOR, author);
nodeService.setProperty(mlContainerToVersion, ContentModel.PROP_NAME, name);
// Done // Done
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())

View File

@@ -24,6 +24,7 @@
*/ */
package org.alfresco.repo.model.ml; package org.alfresco.repo.model.ml;
import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -31,13 +32,18 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.transaction.SystemException;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.i18n.I18NUtil; import org.alfresco.i18n.I18NUtil;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.service.cmr.ml.ContentFilterLanguagesService; import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
import org.alfresco.service.cmr.ml.MultilingualContentService; import org.alfresco.service.cmr.ml.MultilingualContentService;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentData; import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
@@ -86,6 +92,8 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
private ContentFilterLanguagesService contentFilterLanguagesService; private ContentFilterLanguagesService contentFilterLanguagesService;
private FileFolderService fileFolderService; private FileFolderService fileFolderService;
private BehaviourFilter policyBehaviourFilter;
public MultilingualContentServiceImpl() public MultilingualContentServiceImpl()
{ {
searchParametersMLRoot = new SearchParameters(); searchParametersMLRoot = new SearchParameters();
@@ -284,8 +292,12 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
// Make one // Make one
mlContainerNodeRef = getOrCreateMLContainer(contentNodeRef, true); mlContainerNodeRef = getOrCreateMLContainer(contentNodeRef, true);
// set the pivot language Serializable containerFunctionalName = nodeService.getProperty(contentNodeRef, ContentModel.PROP_NAME);
// set the pivot language and the functional name
nodeService.setProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE, locale); nodeService.setProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE, locale);
nodeService.setProperty(mlContainerNodeRef, ContentModel.PROP_NAME, containerFunctionalName);
} }
else else
{ {
@@ -369,7 +381,57 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
} }
} }
/** {@inheritDoc} */
/** @inheritDoc */
public void deleteTranslationContainer(NodeRef mlContainerNodeRef)
{
if(!ContentModel.TYPE_MULTILINGUAL_CONTAINER.equals(nodeService.getType(mlContainerNodeRef)))
{
throw new IllegalArgumentException(
"Node type must be " + ContentModel.TYPE_MULTILINGUAL_CONTAINER);
}
// get the translations
Map<Locale, NodeRef> translations = this.getTranslations(mlContainerNodeRef);
// remember the number of childs
int translationCount = translations.size();
// remove the translations
for(NodeRef translationToRemove : translations.values())
{
// unmake the translation
this.unmakeTranslation(translationToRemove);
// remove it
if(nodeService.exists(translationToRemove))
{
nodeService.deleteNode(translationToRemove);
}
}
// if the mlContainer is not removed with the pivot,
if(nodeService.exists(mlContainerNodeRef))
{
// force its deletion
nodeService.deleteNode(mlContainerNodeRef);
if (logger.isWarnEnabled())
{
logger.warn("The ML container " + mlContainerNodeRef + " was not removed with it's pivot translation in the unmakeTranslation process.");
}
}
// done
if (logger.isDebugEnabled())
{
logger.debug("ML container removed: \n" +
" Container: " + mlContainerNodeRef + "\n" +
" Number of translations: " + translationCount);
}
}
/** @inheritDoc */
public void unmakeTranslation(NodeRef translationNodeRef) public void unmakeTranslation(NodeRef translationNodeRef)
{ {
// Get the container // Get the container
@@ -622,7 +684,9 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
public NodeRef addEmptyTranslation(NodeRef translationOfNodeRef, String name, Locale locale) public NodeRef addEmptyTranslation(NodeRef translationOfNodeRef, String name, Locale locale)
{ {
boolean hasMLAspect = nodeService.hasAspect(translationOfNodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT); boolean hasMLAspect = nodeService.hasAspect(translationOfNodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
if (hasMLAspect) boolean isMLContainer = nodeService.getType(translationOfNodeRef).equals(ContentModel.TYPE_MULTILINGUAL_CONTAINER);
if (hasMLAspect || isMLContainer)
{ {
// Get the pivot translation // Get the pivot translation
NodeRef pivotTranslationNodeRef = getPivotTranslation(translationOfNodeRef); NodeRef pivotTranslationNodeRef = getPivotTranslation(translationOfNodeRef);
@@ -717,15 +781,177 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
return newTranslationNodeRef; return newTranslationNodeRef;
} }
public void setNodeService(NodeService nodeService) /**
{ * @throws SystemException
this.nodeService = nodeService; * @throws Exception
* @throws FileNotFoundException
* @throws FileExistsException
* @inheritDoc
*/
public NodeRef copyTranslationContainer(NodeRef mlContainerNodeRef, NodeRef newParentRef, String prefixName) throws Exception
{
if(!ContentModel.TYPE_MULTILINGUAL_CONTAINER.equals(nodeService.getType(mlContainerNodeRef)))
{
throw new IllegalArgumentException(
"Node type must be " + ContentModel.TYPE_MULTILINGUAL_CONTAINER);
}
// if the container has no translation: nothing to do
if(nodeService.getChildAssocs(mlContainerNodeRef, ContentModel.ASSOC_MULTILINGUAL_CHILD, RegexQNamePattern.MATCH_ALL).size() < 1)
{
if (logger.isDebugEnabled())
{
logger.debug("MLContainer has no translation " + mlContainerNodeRef);
}
return null;
}
// keep a reference to the containing space before copy
NodeRef spaceBefore = nodeService.getPrimaryParent(getPivotTranslation(mlContainerNodeRef)).getParentRef();
if(spaceBefore.equals(newParentRef))
{
throw new AlfrescoRuntimeException(
"Impossible to copy the mlContainer, source folder is the same as the destination container.");
}
// get the pivot translation and its locale
NodeRef pivotNodeRef = getPivotTranslation(mlContainerNodeRef);
Locale pivotLocale = (Locale) nodeService.getProperty(pivotNodeRef, ContentModel.PROP_LOCALE);
String pivotName = prefixName + (String) nodeService.getProperty(pivotNodeRef, ContentModel.PROP_NAME);
if(prefixName == null)
{
prefixName = "";
}
NodeRef pivotCopyNodeRef = null;
pivotCopyNodeRef = fileFolderService.copy(pivotNodeRef, newParentRef, pivotName).getNodeRef();
// make the new pivot multilingual
this.makeTranslation(pivotCopyNodeRef, pivotLocale);
// get a reference to the new mlContainer
NodeRef newMLContainerNodeRef = getMLContainer(pivotCopyNodeRef, false);
// copy each other translation and make them multilingual too
for(Map.Entry<Locale, NodeRef> entry : getTranslations(mlContainerNodeRef).entrySet())
{
Locale translationLocale = entry.getKey();
NodeRef translationNodeRef = entry.getValue();
String name = prefixName + (String) nodeService.getProperty(translationNodeRef, ContentModel.PROP_NAME);
if(!translationNodeRef.equals(pivotNodeRef))
{
if(nodeService.hasAspect(translationNodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
{
// Turn off any empty translation policy behaviours to enabled the copy.
this.policyBehaviourFilter.disableBehaviour(ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION);
this.policyBehaviourFilter.disableBehaviour(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
try
{
// copy the translation
NodeRef copyNodeRef = fileFolderService.copy(translationNodeRef, newParentRef, name).getNodeRef();
// Add it to the newMLContainer
nodeService.addChild(
newMLContainerNodeRef,
copyNodeRef,
ContentModel.ASSOC_MULTILINGUAL_CHILD,
QNAME_ML_TRANSLATION);
}
finally
{
this.policyBehaviourFilter.enableBehaviour(ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION);
this.policyBehaviourFilter.enableBehaviour(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
}
}
else
{
// copy the translation
NodeRef copyNodeRef = fileFolderService.copy(translationNodeRef, newParentRef, name).getNodeRef();
// add it to the mlContainer
this.addTranslation(copyNodeRef, newMLContainerNodeRef, translationLocale);
// set its locale property
nodeService.setProperty(copyNodeRef, ContentModel.PROP_LOCALE, translationLocale);
}
}
else
{
// the pivot is already created
}
}
if (logger.isDebugEnabled())
{
logger.debug("MLContainer copied: \n" +
" Copy of : " + mlContainerNodeRef + "(translations located in " + spaceBefore + ") \n" +
" Copy : " + newMLContainerNodeRef + "(translations located in " + newParentRef + ") \n");
}
return newMLContainerNodeRef;
}
/**
* @inheritDoc
*/
public void moveTranslationContainer(NodeRef mlContainerNodeRef, NodeRef newParentRef) throws FileExistsException, FileNotFoundException
{
if(!ContentModel.TYPE_MULTILINGUAL_CONTAINER.equals(nodeService.getType(mlContainerNodeRef)))
{
throw new IllegalArgumentException(
"Node type must be " + ContentModel.TYPE_MULTILINGUAL_CONTAINER);
}
// if the container has no translation: nothing to do
if(nodeService.getChildAssocs(mlContainerNodeRef, ContentModel.ASSOC_MULTILINGUAL_CHILD, RegexQNamePattern.MATCH_ALL).size() < 1)
{
if (logger.isDebugEnabled())
{
logger.debug("MLContainer has no translation " + mlContainerNodeRef);
}
return;
}
// keep a reference to the containing space before moving
NodeRef spaceBefore = nodeService.getPrimaryParent(getPivotTranslation(mlContainerNodeRef)).getParentRef();
if(spaceBefore.equals(newParentRef))
{
// nothing to do
return;
}
// move each translation
for(NodeRef translationToMove : getTranslations(mlContainerNodeRef).values())
{
fileFolderService.move(translationToMove, newParentRef, null);
}
if (logger.isDebugEnabled())
{
logger.debug("MLContainer moved: \n" +
" Old location of " + mlContainerNodeRef + " : " + spaceBefore + ") \n" +
" New location of " + mlContainerNodeRef + " : " + newParentRef + ")");
}
} }
public void setSearchService(SearchService searchService)
{ public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setSearchService(SearchService searchService)
{
this.searchService = searchService; this.searchService = searchService;
} }
public void setPermissionService(PermissionService permissionService) public void setPermissionService(PermissionService permissionService)
{ {
@@ -742,13 +968,8 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
this.fileFolderService = fileFolderService; this.fileFolderService = fileFolderService;
} }
public NodeRef copyTranslationContainer(NodeRef translationNodeRef, NodeRef newParentRef) public void setPolicyBehaviourFilter(BehaviourFilter policyBehaviourFilter)
{ {
throw new UnsupportedOperationException("This operation is not yet supported"); this.policyBehaviourFilter = policyBehaviourFilter;
}
public void moveTranslationContainer(NodeRef translationNodeRef, NodeRef newParentRef)
{
throw new UnsupportedOperationException("This operation is not yet supported");
} }
} }

View File

@@ -35,7 +35,6 @@ import org.alfresco.repo.node.NodeServicePolicies;
import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.policy.PolicyScope; import org.alfresco.repo.policy.PolicyScope;
import org.alfresco.repo.version.VersionServicePolicies;
import org.alfresco.service.cmr.ml.MultilingualContentService; import org.alfresco.service.cmr.ml.MultilingualContentService;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
@@ -54,22 +53,10 @@ import org.alfresco.service.namespace.RegexQNamePattern;
*/ */
public class MultilingualDocumentAspect implements public class MultilingualDocumentAspect implements
CopyServicePolicies.OnCopyNodePolicy, CopyServicePolicies.OnCopyNodePolicy,
CopyServicePolicies.OnCopyCompletePolicy,
NodeServicePolicies.BeforeDeleteNodePolicy, NodeServicePolicies.BeforeDeleteNodePolicy,
NodeServicePolicies.OnUpdatePropertiesPolicy, NodeServicePolicies.OnUpdatePropertiesPolicy
VersionServicePolicies.OnCreateVersionPolicy
{ {
/**
* List of properties to set persistent when a version of the mlDocument is created
*/
public static final QName[] PROPERTIES_TO_VERSION = {
ContentModel.PROP_AUTHOR,
ContentModel.PROP_LOCALE,
ContentModel.PROP_TITLE,
ContentModel.PROP_DESCRIPTION,
};
// Dependencies // Dependencies
private PolicyComponent policyComponent; private PolicyComponent policyComponent;
private MultilingualContentService multilingualContentService; private MultilingualContentService multilingualContentService;
@@ -88,11 +75,6 @@ public class MultilingualDocumentAspect implements
ContentModel.ASPECT_MULTILINGUAL_DOCUMENT, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT,
new JavaBehaviour(this, "onCopyNode")); new JavaBehaviour(this, "onCopyNode"));
this.policyComponent.bindClassBehaviour(
QName.createQName(NamespaceService.ALFRESCO_URI, "onCopyComplete"),
ContentModel.ASPECT_MULTILINGUAL_DOCUMENT,
new JavaBehaviour(this, "onCopyComplete"));
this.policyComponent.bindClassBehaviour( this.policyComponent.bindClassBehaviour(
QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"), QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"),
ContentModel.ASPECT_MULTILINGUAL_DOCUMENT, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT,
@@ -103,11 +85,6 @@ public class MultilingualDocumentAspect implements
ContentModel.ASPECT_MULTILINGUAL_DOCUMENT, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT,
new JavaBehaviour(this, "onUpdateProperties")); new JavaBehaviour(this, "onUpdateProperties"));
this.policyComponent.bindClassBehaviour(
QName.createQName(NamespaceService.ALFRESCO_URI, "onCreateVersion"),
ContentModel.ASPECT_MULTILINGUAL_DOCUMENT,
new JavaBehaviour(this, "onCreateVersion"));
} }
/** /**
@@ -145,16 +122,6 @@ public class MultilingualDocumentAspect implements
copyDetails.removeAspect(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT); copyDetails.removeAspect(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
} }
/**
* The copy of <b>mlDocument</b> don't keep the 'locale' property.
*
* @see org.alfresco.repo.copy.CopyServicePolicies.OnCopyCompletePolicy#onCopyComplete(org.alfresco.service.namespace.QName, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef, boolean, java.util.Map)
*/
public void onCopyComplete(QName classRef, NodeRef sourceNodeRef, NodeRef destinationRef, boolean copyToNewNode, Map<NodeRef, NodeRef> copyMap)
{
nodeService.removeProperty(destinationRef, ContentModel.PROP_LOCALE);
}
/** /**
* If this is not an empty translation, then ensure that the node is properly * If this is not an empty translation, then ensure that the node is properly
* unhooked from the translation mechanism first. * unhooked from the translation mechanism first.
@@ -191,10 +158,10 @@ public class MultilingualDocumentAspect implements
// the after local property type can be either Locale or String // the after local property type can be either Locale or String
Serializable objLocaleAfter = after.get(ContentModel.PROP_LOCALE); Serializable objLocaleAfter = after.get(ContentModel.PROP_LOCALE);
if (objLocaleAfter instanceof Locale ) if (objLocaleAfter instanceof Locale )
{ {
localeAfter = (Locale) objLocaleAfter; localeAfter = (Locale) objLocaleAfter;
} }
else else
{ {
@@ -242,19 +209,4 @@ public class MultilingualDocumentAspect implements
// else no action to perform // else no action to perform
} }
/**
* Persist some specific properties in the version store
*
* @see org.alfresco.repo.model.ml.MultilingualDocumentAspect.PROPERTIES_TO_VERSION
* @see org.alfresco.repo.version.VersionServicePolicies.OnCreateVersionPolicy#onCreateVersion(org.alfresco.service.namespace.QName, org.alfresco.service.cmr.repository.NodeRef, java.util.Map, org.alfresco.repo.policy.PolicyScope)
*/
public void onCreateVersion(QName classRef, NodeRef versionableNode, Map<String, Serializable> versionProperties, PolicyScope nodeDetails)
{
for(QName prop : PROPERTIES_TO_VERSION)
{
nodeDetails.addProperty(prop, nodeService.getProperty(versionableNode, prop));
}
}
} }

View File

@@ -28,7 +28,6 @@ import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@@ -36,6 +35,7 @@ import java.util.Map;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.version.VersionModel; import org.alfresco.repo.version.VersionModel;
import org.alfresco.repo.version.common.VersionLabelComparator;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.Version; import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionHistory; import org.alfresco.service.cmr.version.VersionHistory;
@@ -210,24 +210,12 @@ public class EditionServiceImplTest extends AbstractMultilingualTestCases
return multilingualContentService.getTranslationContainer(chineseContentNodeRef); return multilingualContentService.getTranslationContainer(chineseContentNodeRef);
} }
private Comparator versionComparator = new Comparator()
{
public int compare(Object o1, Object o2)
{
String label01 = ((Version) o1).getVersionLabel();
String label02 = ((Version) o2).getVersionLabel();
// sort the list ascending
return label02.compareTo(label01);
}
};
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private List<Version> orderVersions(Collection<Version> allVersions) private List<Version> orderVersions(Collection<Version> allVersions)
{ {
List<Version> versionsAsList = new ArrayList<Version>(allVersions.size()); List<Version> versionsAsList = new ArrayList<Version>(allVersions.size());
versionsAsList.addAll(allVersions); versionsAsList.addAll(allVersions);
Collections.sort(versionsAsList, versionComparator); Collections.sort(versionsAsList, new VersionLabelComparator());
return versionsAsList; return versionsAsList;
} }
} }

View File

@@ -15,17 +15,20 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of * As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre * the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's * and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing * FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here: * the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing" * http://www.alfresco.com/legal/licensing"
*/ */
package org.alfresco.repo.model.ml.tools; package org.alfresco.repo.model.ml.tools;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map;
import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.Authentication;
@@ -39,13 +42,13 @@ import org.alfresco.service.cmr.security.PermissionService;
/** /**
* @see org.alfresco.repo.ml.MultilingualContentServiceImpl * @see org.alfresco.repo.ml.MultilingualContentServiceImpl
* *
* @author Derek Hulley * @author Derek Hulley
* @author Philippe Dubois * @author Philippe Dubois
*/ */
public class MultilingualContentServiceImplTest extends AbstractMultilingualTestCases public class MultilingualContentServiceImplTest extends AbstractMultilingualTestCases
{ {
public void testMakeTranslation() throws Exception public void testMakeTranslation() throws Exception
{ {
NodeRef chineseContentNodeRef = createContent(); NodeRef chineseContentNodeRef = createContent();
@@ -57,7 +60,7 @@ public class MultilingualContentServiceImplTest extends AbstractMultilingualTest
// Check the container child count // Check the container child count
assertEquals("Incorrect number of child nodes", 1, nodeService.getChildAssocs(mlContainerNodeRef).size()); assertEquals("Incorrect number of child nodes", 1, nodeService.getChildAssocs(mlContainerNodeRef).size());
} }
public void testAddTranslationUsingContent() throws Exception public void testAddTranslationUsingContent() throws Exception
{ {
// Make a container with a single translation // Make a container with a single translation
@@ -77,58 +80,58 @@ public class MultilingualContentServiceImplTest extends AbstractMultilingualTest
// Check the container child count // Check the container child count
assertEquals("Incorrect number of child nodes", 2, nodeService.getChildAssocs(mlContainerNodeRef).size()); assertEquals("Incorrect number of child nodes", 2, nodeService.getChildAssocs(mlContainerNodeRef).size());
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
public void testGetMissingTranslation() throws Exception public void testGetMissingTranslation() throws Exception
{ {
List<String> langList = contentFilterLanguagesService.getFilterLanguages(); List<String> langList = contentFilterLanguagesService.getFilterLanguages();
int langListSize = langList.size(); int langListSize = langList.size();
// make sure that it exists at least tree language filter // make sure that it exists at least tree language filter
assertFalse("The testGetMissingTranslation test case needs at least three language", langListSize < 3); assertFalse("The testGetMissingTranslation test case needs at least three language", langListSize < 3);
// get the first tree locale of the content filter language list // get the first tree locale of the content filter language list
Locale loc1 = I18NUtil.parseLocale(langList.get(0)); Locale loc1 = I18NUtil.parseLocale(langList.get(0));
Locale loc2 = I18NUtil.parseLocale(langList.get(1)); Locale loc2 = I18NUtil.parseLocale(langList.get(1));
Locale loc3 = I18NUtil.parseLocale(langList.get(2)); Locale loc3 = I18NUtil.parseLocale(langList.get(2));
// create three content // create three content
NodeRef nodeRef1 = createContent(); NodeRef nodeRef1 = createContent();
NodeRef nodeRef2 = createContent(); NodeRef nodeRef2 = createContent();
NodeRef nodeRef3 = createContent(); NodeRef nodeRef3 = createContent();
multilingualContentService.makeTranslation(nodeRef1, loc1); multilingualContentService.makeTranslation(nodeRef1, loc1);
List<Locale> missing = multilingualContentService.getMissingTranslations(nodeRef1, false); List<Locale> missing = multilingualContentService.getMissingTranslations(nodeRef1, 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. " + assertFalse("Missing Translation Size false. " +
"Real size : " + missing.size() + ". Normal Size " + (langListSize - 1), missing.size() != (langListSize - 1)); "Real size : " + missing.size() + ". Normal Size " + (langListSize - 1), missing.size() != (langListSize - 1));
// make sure that the missing language list is correct // make sure that the missing language list is correct
assertFalse("Missing Translation List false. Locale " + loc1 + " found", missing.contains(loc1.toString())); assertFalse("Missing Translation List false. Locale " + loc1 + " found", missing.contains(loc1.toString()));
multilingualContentService.addTranslation(nodeRef2, nodeRef1, loc2); multilingualContentService.addTranslation(nodeRef2, nodeRef1, loc2);
multilingualContentService.addTranslation(nodeRef3, nodeRef1, loc3); multilingualContentService.addTranslation(nodeRef3, nodeRef1, loc3);
// Add the missing translations in // Add the missing translations in
missing = multilingualContentService.getMissingTranslations(nodeRef1, false); missing = multilingualContentService.getMissingTranslations(nodeRef1, 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. " + assertFalse("Missing Translation Size false. " +
"Real size : " + missing.size() + ". Normal Size " + (langListSize - 3), missing.size() != (langListSize - 3)); "Real size : " + missing.size() + ". Normal Size " + (langListSize - 3), missing.size() != (langListSize - 3));
// make sure that the missing language list is correct // make sure that the missing language list is correct
assertFalse("Missing Translation List false. Locale " + loc2 + " or " + loc3 + " found", missing.contains(loc2.toString()) || missing.contains(loc3.toString())); assertFalse("Missing Translation List false. Locale " + loc2 + " or " + loc3 + " found", missing.contains(loc2.toString()) || missing.contains(loc3.toString()));
} }
public void testGetTranslationForLocale() throws Exception public void testGetTranslationForLocale() throws Exception
{ {
NodeRef chineseContentNodeRef = createContent(); NodeRef chineseContentNodeRef = createContent();
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE); multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
NodeRef frenchContentNodeRef = createContent(); NodeRef frenchContentNodeRef = createContent();
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH); multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
// Get the chinese translation // Get the chinese translation
assertEquals("Chinese translation should be present", assertEquals("Chinese translation should be present",
chineseContentNodeRef, chineseContentNodeRef,
@@ -142,61 +145,61 @@ public class MultilingualContentServiceImplTest extends AbstractMultilingualTest
chineseContentNodeRef, chineseContentNodeRef,
multilingualContentService.getTranslationForLocale(chineseContentNodeRef, Locale.ITALIAN)); multilingualContentService.getTranslationForLocale(chineseContentNodeRef, Locale.ITALIAN));
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
public void testGetPivotTranslation() throws Exception public void testGetPivotTranslation() throws Exception
{ {
NodeRef chineseContentNodeRef = createContent(); NodeRef chineseContentNodeRef = createContent();
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE); multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(chineseContentNodeRef); NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(chineseContentNodeRef);
// make sure that the pivot language is set // make sure that the pivot language is set
assertNotNull("Pivot language not set", nodeService.getProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE)); assertNotNull("Pivot language not set", nodeService.getProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE));
// make sure that the pivot language is correctly set // make sure that the pivot language is correctly set
assertEquals("Pivot language not correctly set", Locale.CHINESE, nodeService.getProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE)); assertEquals("Pivot language not correctly set", Locale.CHINESE, nodeService.getProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE));
NodeRef frenchContentNodeRef = createContent(); NodeRef frenchContentNodeRef = createContent();
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH); multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
// make sure that the pivot noderef is correct // make sure that the pivot noderef is correct
assertEquals("Unable to get pivot from container", chineseContentNodeRef, multilingualContentService.getPivotTranslation(mlContainerNodeRef)); assertEquals("Unable to get pivot from container", chineseContentNodeRef, multilingualContentService.getPivotTranslation(mlContainerNodeRef));
assertEquals("Unable to get pivot from translation", chineseContentNodeRef, multilingualContentService.getPivotTranslation(frenchContentNodeRef)); assertEquals("Unable to get pivot from translation", chineseContentNodeRef, multilingualContentService.getPivotTranslation(frenchContentNodeRef));
// modify the pivot language // modify the pivot language
nodeService.setProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE, Locale.FRENCH); nodeService.setProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE, Locale.FRENCH);
// make sure that the modified pivot noderef is correct // make sure that the modified pivot noderef is correct
assertEquals("Pivot node ref not correct", frenchContentNodeRef, multilingualContentService.getPivotTranslation(mlContainerNodeRef)); assertEquals("Pivot node ref not correct", frenchContentNodeRef, multilingualContentService.getPivotTranslation(mlContainerNodeRef));
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
public void testCreateEmptyTranslation() throws Exception public void testCreateEmptyTranslation() throws Exception
{ {
NodeRef chineseContentNodeRef = createContent("Document.txt"); NodeRef chineseContentNodeRef = createContent("Document.txt");
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE); multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
// This should use the pivot language // This should use the pivot language
NodeRef emptyNodeRef = multilingualContentService.addEmptyTranslation(chineseContentNodeRef, "Document.txt", Locale.CANADA); NodeRef emptyNodeRef = multilingualContentService.addEmptyTranslation(chineseContentNodeRef, "Document.txt", Locale.CANADA);
// Ensure that the empty translation is not null // Ensure that the empty translation is not null
assertNotNull("The creation of the empty document failed ", emptyNodeRef); assertNotNull("The creation of the empty document failed ", emptyNodeRef);
// Ensure that the empty translation has the mlDocument aspect // Ensure that the empty translation has the mlDocument aspect
assertTrue("The empty document must have the mlDocument aspect", assertTrue("The empty document must have the mlDocument aspect",
nodeService.hasAspect(emptyNodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT)); nodeService.hasAspect(emptyNodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
// Ensure that the empty translation has the mlEmptyTranslation aspect // Ensure that the empty translation has the mlEmptyTranslation aspect
assertTrue("The empty document must have the mlEmptyTranslation aspect", assertTrue("The empty document must have the mlEmptyTranslation aspect",
nodeService.hasAspect(emptyNodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION)); nodeService.hasAspect(emptyNodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION));
// Check that the auto renaming worked // Check that the auto renaming worked
String emptyName = DefaultTypeConverter.INSTANCE.convert(String.class, String emptyName = DefaultTypeConverter.INSTANCE.convert(String.class,
nodeService.getProperty(emptyNodeRef, ContentModel.PROP_NAME)); nodeService.getProperty(emptyNodeRef, ContentModel.PROP_NAME));
assertEquals("Empty auto-rename didn't work for same-named document", "Document_en_CA.txt", emptyName); assertEquals("Empty auto-rename didn't work for same-named document", "Document_en_CA.txt", emptyName);
// Check that the content is identical // Check that the content is identical
ContentData chineseContentData = fileFolderService.getReader(chineseContentNodeRef).getContentData(); ContentData chineseContentData = fileFolderService.getReader(chineseContentNodeRef).getContentData();
ContentData emptyContentData = fileFolderService.getReader(emptyNodeRef).getContentData(); ContentData emptyContentData = fileFolderService.getReader(emptyNodeRef).getContentData();
} }
public void testCreateEmptyTranslationNames() throws Exception public void testCreateEmptyTranslationNames() throws Exception
{ {
NodeRef chineseContentNodeRef = createContent("Document.txt"); NodeRef chineseContentNodeRef = createContent("Document.txt");
@@ -225,7 +228,7 @@ public class MultilingualContentServiceImplTest extends AbstractMultilingualTest
String differentName = fileFolderService.getFileInfo(differentNameNodeRef).getName(); String differentName = fileFolderService.getFileInfo(differentNameNodeRef).getName();
assertEquals("Empty translation name not generated correctly.", "Document2.txt", differentName); assertEquals("Empty translation name not generated correctly.", "Document2.txt", differentName);
} }
public void testGetTranslationContainerPermissions() throws Exception public void testGetTranslationContainerPermissions() throws Exception
{ {
// Grant the guest user rights to our working folder // Grant the guest user rights to our working folder
@@ -252,7 +255,7 @@ public class MultilingualContentServiceImplTest extends AbstractMultilingualTest
try { authenticationComponent.setCurrentAuthentication(authentication); } catch (Throwable e) {} try { authenticationComponent.setCurrentAuthentication(authentication); } catch (Throwable e) {}
} }
} }
/** /**
* Check whether non-admin users can take part in ML document manipulation * Check whether non-admin users can take part in ML document manipulation
*/ */
@@ -284,4 +287,284 @@ public class MultilingualContentServiceImplTest extends AbstractMultilingualTest
try { authenticationComponent.setCurrentAuthentication(authentication); } catch (Throwable e) {} try { authenticationComponent.setCurrentAuthentication(authentication); } catch (Throwable e) {}
} }
} }
public void testDeleteMultilingualContent() throws Exception
{
NodeRef chineseContentNodeRef = createContent();
NodeRef frenchContentNodeRef = createContent();
NodeRef japaneseContentNodeRef = createContent();
NodeRef emptyGermanContentNodeRef = null;
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
multilingualContentService.addTranslation(japaneseContentNodeRef, chineseContentNodeRef, Locale.JAPANESE);
emptyGermanContentNodeRef = multilingualContentService.addEmptyTranslation(chineseContentNodeRef, null, Locale.GERMAN);
// the mlContainer to remove
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(chineseContentNodeRef);
// Ensure that the the mlContainer is correctly created
assertEquals("Incorrect number of translations", 4, multilingualContentService.getTranslations(mlContainerNodeRef).size());
// remove the mlContainer
multilingualContentService.deleteTranslationContainer(mlContainerNodeRef);
// get the archived node ref
NodeRef archivedChineseContentNodeRef = nodeArchiveService.getArchivedNode(chineseContentNodeRef);
NodeRef archivedFrenchContentNodeRef = nodeArchiveService.getArchivedNode(frenchContentNodeRef);
NodeRef archivedJapaneseContentNodeRef = nodeArchiveService.getArchivedNode(japaneseContentNodeRef);
NodeRef archivedEmptyGermanContentNodeRef = nodeArchiveService.getArchivedNode(emptyGermanContentNodeRef);
NodeRef archivedMlContainerNodeRef = nodeArchiveService.getArchivedNode(mlContainerNodeRef);
// Ensure that the mlContainer is removed
assertFalse("The multilingual container must be removed", nodeService.exists(mlContainerNodeRef));
// Ensure that the mlContainer IS NOT archived
assertFalse("The multilingual container can't be archived", nodeService.exists(archivedMlContainerNodeRef));
// Ensure that the translations are removed
assertFalse("The translation must be removed: " + Locale.CHINESE, nodeService.exists(chineseContentNodeRef));
assertFalse("The translation must be removed: " + Locale.JAPANESE, nodeService.exists(japaneseContentNodeRef));
assertFalse("The translation must be removed: " + Locale.FRENCH, nodeService.exists(frenchContentNodeRef));
assertFalse("The empty translation must be removed: " + Locale.GERMAN, nodeService.exists(emptyGermanContentNodeRef));
// Ensure that the translations ARE archived
assertTrue("The translation must be archived: " + Locale.CHINESE, nodeService.exists(archivedChineseContentNodeRef));
assertTrue("The translation must be archived: " + Locale.JAPANESE, nodeService.exists(archivedJapaneseContentNodeRef));
assertTrue("The translation must be archived: " + Locale.FRENCH, nodeService.exists(archivedFrenchContentNodeRef));
// Ensure that the empty translation IS NOT archived
assertFalse("The empty document can't be archived: " + Locale.GERMAN, nodeService.exists(archivedEmptyGermanContentNodeRef));
// Ensure that the mlDocument aspect is removed
assertFalse("The " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT + " aspect must be removed for " + Locale.CHINESE, nodeService.hasAspect(archivedChineseContentNodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
assertFalse("The " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT + " aspect must be removed for " + Locale.JAPANESE, nodeService.hasAspect(archivedJapaneseContentNodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
assertFalse("The " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT + " aspect must be removed for " + Locale.FRENCH, nodeService.hasAspect(archivedFrenchContentNodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
}
@SuppressWarnings("unused")
public void testCopyMLContainerInNewSpace() throws Exception
{
NodeRef chineseContentNodeRef = createContent();
NodeRef frenchContentNodeRef = createContent();
NodeRef japaneseContentNodeRef = createContent();
NodeRef emptyGermanContentNodeRef = null;
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
multilingualContentService.addTranslation(japaneseContentNodeRef, chineseContentNodeRef, Locale.JAPANESE);
emptyGermanContentNodeRef = multilingualContentService.addEmptyTranslation(chineseContentNodeRef, null, Locale.GERMAN);
// the mlContainer to copy
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(chineseContentNodeRef);
// Ensure that the the mlContainer is correctly created
assertEquals("Incorrect number of translations", 4, multilingualContentService.getTranslations(mlContainerNodeRef).size());
// get the actual space
NodeRef actualSpace = folderNodeRef;
// create a new space
NodeRef destinationSpace = fileFolderService.create(folderNodeRef, "testCopyMLContainerInNewSpace" + System.currentTimeMillis(), ContentModel.TYPE_FOLDER).getNodeRef();
// Ensure that the new space is created
assertTrue("The destiation space is not created " + destinationSpace, nodeService.exists(destinationSpace));
// copy the mlContainer
NodeRef newMLContainer = multilingualContentService.copyTranslationContainer(mlContainerNodeRef, destinationSpace, "");
assertEquals("Incorrect number of translations for the new mlContainer", 4, multilingualContentService.getTranslations(newMLContainer).size());
// Ensure that a new mlContainer is created
assertTrue("The new mlContainer is not created ", nodeService.exists(newMLContainer));
// Ensure that the newMLContainer is a copy of the source mlContainer
assertFalse("The newMLContainer is not a copy of the source mlContainer, the ref is the same " + newMLContainer , newMLContainer.equals(mlContainerNodeRef));
assertEquals("The newMLContainer is not a copy of the source mlContainer, the locales are not the same " + newMLContainer ,
nodeService.getProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE),
nodeService.getProperty(newMLContainer, ContentModel.PROP_LOCALE));
assertEquals("The newMLContainer is not a copy of the source mlContainer, the authors are not the same " + newMLContainer ,
nodeService.getProperty(mlContainerNodeRef, ContentModel.PROP_AUTHOR),
nodeService.getProperty(newMLContainer, ContentModel.PROP_AUTHOR));
// get the source translations
Map<Locale, NodeRef> sourceTranslations = multilingualContentService.getTranslations(mlContainerNodeRef);
// get the copies
Map<Locale, NodeRef> copyTranslations = multilingualContentService.getTranslations(newMLContainer);
// Ensure that the translations are copies from the source translations
assertEquals("They are not the same number of translation in the source mlContainer and in its copy", sourceTranslations.size(), copyTranslations.size());
for(Map.Entry<Locale, NodeRef> entry : sourceTranslations.entrySet())
{
Locale locale = entry.getKey();
NodeRef sourceNodeRef = entry.getValue();
NodeRef sourceParent = nodeService.getPrimaryParent(sourceNodeRef).getParentRef();
NodeRef copyTranslation = multilingualContentService.getTranslationForLocale(newMLContainer, locale);
NodeRef copyParent = nodeService.getPrimaryParent(copyTranslation).getParentRef();
// Ensure that the copy exists
assertNotNull("No copy found for the locale " + locale, copyTranslation);
assertTrue("No copy exists for the locale " + locale, nodeService.exists(copyTranslation));
// Ensure that the copy has the mlDocument aspect
assertTrue("The copy must have the mlDocument aspect",
nodeService.hasAspect(copyTranslation, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
// Ensure that the copy is an empty translation if the source too
assertEquals("The call of nodeService.hasAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION) must return the same result for the source and the copy",
nodeService.hasAspect(sourceNodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION),
nodeService.hasAspect(copyTranslation, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION));
// Ensure that the copy and the source are different
assertNotSame("The copy has the same ref as the source", sourceNodeRef, copyTranslation);
// Ensure that the parent of the source is correct
assertEquals("The source would not be moved", sourceParent, actualSpace);
// Ensure that the parent of the copy is correct
assertEquals("The copy is not in the right space", copyParent, destinationSpace);
}
}
@SuppressWarnings("unused")
public void testCopyMLContainerInSameSpace() throws Exception
{
NodeRef chineseContentNodeRef = createContent();
NodeRef frenchContentNodeRef = createContent();
NodeRef japaneseContentNodeRef = createContent();
NodeRef emptyGermanContentNodeRef = null;
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
multilingualContentService.addTranslation(japaneseContentNodeRef, chineseContentNodeRef, Locale.JAPANESE);
emptyGermanContentNodeRef = multilingualContentService.addEmptyTranslation(chineseContentNodeRef, null, Locale.GERMAN);
// the mlContainer to copy
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(chineseContentNodeRef);
// Ensure that the the mlContainer is correctly created
assertEquals("Incorrect number of translations", 4, multilingualContentService.getTranslations(mlContainerNodeRef).size());
// get the actual space
NodeRef actualSpace = folderNodeRef;
try
{
// copy the mlContainer
NodeRef newMLContainer = multilingualContentService.copyTranslationContainer(mlContainerNodeRef, actualSpace, "");
fail("The copy of the mlContainer in the same space would faile");
}
catch(Exception e)
{
// test asserted
}
}
@SuppressWarnings("unused")
public void testCopyAndRenameMLContainer() throws Exception
{
NodeRef chineseContentNodeRef = createContent();
NodeRef frenchContentNodeRef = createContent();
NodeRef japaneseContentNodeRef = createContent();
NodeRef emptyGermanContentNodeRef = null;
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
multilingualContentService.addTranslation(japaneseContentNodeRef, chineseContentNodeRef, Locale.JAPANESE);
emptyGermanContentNodeRef = multilingualContentService.addEmptyTranslation(chineseContentNodeRef, null, Locale.GERMAN);
// the mlContainer to copy
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(chineseContentNodeRef);
// Ensure that the the mlContainer is correctly created
assertEquals("Incorrect number of translations", 4, multilingualContentService.getTranslations(mlContainerNodeRef).size());
// get the actual space
NodeRef actualSpace = folderNodeRef;
// create a new space
NodeRef destinationSpace = fileFolderService.create(folderNodeRef, "testCopyMLContainerInNewSpace" + System.currentTimeMillis(), ContentModel.TYPE_FOLDER).getNodeRef();
// Ensure that the new space is created
assertTrue("The destiation space is not created " + destinationSpace, nodeService.exists(destinationSpace));
String PREFIX = "COPY OF " ;
NodeRef newMLContainer = multilingualContentService.copyTranslationContainer(mlContainerNodeRef, destinationSpace, PREFIX);
// Ensure that a new mlContainer is created
assertTrue("The new mlContainer is not created ", nodeService.exists(newMLContainer));
// Ensure that the newMLContainer is a copy of the source mlContainer
assertFalse("The newMLContainer is not a copy of the source mlContainer, the ref is the same " + newMLContainer , newMLContainer.equals(mlContainerNodeRef));
// get the source translations
Map<Locale, NodeRef> sourceTranslations = multilingualContentService.getTranslations(mlContainerNodeRef);
// get the copies
Map<Locale, NodeRef> copyTranslations = multilingualContentService.getTranslations(newMLContainer);
// Ensure that the translations are copies from the source translations
assertEquals("They are not the same number of translation in the source mlContainer and in its copy", sourceTranslations.size(), copyTranslations.size());
for(Map.Entry<Locale, NodeRef> entry : sourceTranslations.entrySet())
{
Locale locale = entry.getKey();
NodeRef sourceNodeRef = entry.getValue();
NodeRef copyNodeRef = multilingualContentService.getTranslationForLocale(newMLContainer, locale);
String sourceName = (String) nodeService.getProperty(sourceNodeRef, ContentModel.PROP_NAME);
String copyName = (String) nodeService.getProperty(copyNodeRef, ContentModel.PROP_NAME);
String theoricalCopyName = PREFIX + sourceName;
// Ensure that the name of the copy is correct
assertTrue("The name of the copied translation is incorect: " + copyName + " and should be " + theoricalCopyName, theoricalCopyName.equals(copyName));
}
}
@SuppressWarnings("unused")
public void testMoveMLContainer() throws Exception
{
NodeRef chineseContentNodeRef = createContent();
NodeRef frenchContentNodeRef = createContent();
NodeRef japaneseContentNodeRef = createContent();
NodeRef emptyGermanContentNodeRef = null;
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
multilingualContentService.addTranslation(japaneseContentNodeRef, chineseContentNodeRef, Locale.JAPANESE);
emptyGermanContentNodeRef = multilingualContentService.addEmptyTranslation(chineseContentNodeRef, null, Locale.GERMAN);
// the mlContainer to copy
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(chineseContentNodeRef);
// Ensure that the the mlContainer is correctly created
assertEquals("Incorrect number of translations", 4, multilingualContentService.getTranslations(mlContainerNodeRef).size());
// get the actual space
NodeRef actualSpace = folderNodeRef;
// create a new space
NodeRef destinationSpace = fileFolderService.create(folderNodeRef, "testCopyMLContainerInNewSpace", ContentModel.TYPE_FOLDER).getNodeRef();
// Ensure that the new space is created
assertTrue("The destiation space is not created " + destinationSpace, nodeService.exists(destinationSpace));
// move the mlContainer
multilingualContentService.moveTranslationContainer(mlContainerNodeRef, destinationSpace);
// Esure that the nodes are moved
assertEquals("The node should be moved", destinationSpace, nodeService.getPrimaryParent(chineseContentNodeRef).getParentRef());
assertEquals("The node should be moved", destinationSpace, nodeService.getPrimaryParent(frenchContentNodeRef).getParentRef());
assertEquals("The node should be moved", destinationSpace, nodeService.getPrimaryParent(japaneseContentNodeRef).getParentRef());
assertEquals("The node should be moved", destinationSpace, nodeService.getPrimaryParent(emptyGermanContentNodeRef).getParentRef());
// Ensure the mlContainer is not changed
assertEquals("The mlContainer should not be changed", mlContainerNodeRef, multilingualContentService.getTranslationContainer(chineseContentNodeRef));
assertEquals("The mlContainer should not be changed", mlContainerNodeRef, multilingualContentService.getTranslationContainer(frenchContentNodeRef));
assertEquals("The mlContainer should not be changed", mlContainerNodeRef, multilingualContentService.getTranslationContainer(japaneseContentNodeRef));
assertEquals("The mlContainer should not be changed", mlContainerNodeRef, multilingualContentService.getTranslationContainer(emptyGermanContentNodeRef));
}
} }

View File

@@ -15,11 +15,11 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of * As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre * the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's * and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing * FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here: * the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing" * http://www.alfresco.com/legal/licensing"
*/ */
package org.alfresco.repo.model.ml.tools; package org.alfresco.repo.model.ml.tools;
@@ -34,62 +34,59 @@ import org.alfresco.service.namespace.QName;
/** /**
* Multilingual document aspect test cases * Multilingual document aspect test cases
* *
* @see org.alfresco.service.cmr.ml.MultilingualDocumentAspect * @see org.alfresco.service.cmr.ml.MultilingualDocumentAspect
* *
* @author Yannick Pignot * @author Yannick Pignot
*/ */
public class MultilingualDocumentAspectTest extends AbstractMultilingualTestCases public class MultilingualDocumentAspectTest extends AbstractMultilingualTestCases
{ {
public void testCopy() throws Exception public void testCopy() throws Exception
{ {
NodeRef original = createContent(); NodeRef original = createContent();
multilingualContentService.makeTranslation(original, Locale.FRENCH); multilingualContentService.makeTranslation(original, Locale.FRENCH);
NodeRef mlContainer = multilingualContentService.getTranslationContainer(original); NodeRef mlContainer = multilingualContentService.getTranslationContainer(original);
NodeRef copy = NodeRef copy =
fileFolderService.copy(original, nodeService.getPrimaryParent(original).getParentRef(), "COPY" + System.currentTimeMillis()).getNodeRef(); fileFolderService.copy(original, nodeService.getPrimaryParent(original).getParentRef(), "COPY" + System.currentTimeMillis()).getNodeRef();
// Ensure that the copy removes the mlDocument aspect // Ensure that the copy removes the mlDocument aspect
assertFalse("The copy of a mlDocument can't have the multilingual aspect", nodeService.hasAspect(copy, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT)); assertFalse("The copy of a mlDocument can't have the multilingual aspect", nodeService.hasAspect(copy, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
// Ensure that the copy removes the association between the mlConatiner and the new node // Ensure that the copy removes the association between the mlConatiner and the new node
assertEquals("The copy of a mlDocument can't be a children of the mlContainer", 1, multilingualContentService.getTranslations(mlContainer).size()); assertEquals("The copy of a mlDocument can't be a children of the mlContainer", 1, multilingualContentService.getTranslations(mlContainer).size());
// Ensure that the copy removes the Locale property of the new node
assertNull("The copy of a mlDocument can't keep the locale property", nodeService.getProperty(copy, ContentModel.PROP_LOCALE));
} }
public void testDeleteNode() throws Exception public void testDeleteNode() throws Exception
{ {
NodeRef trad1 = createContent(); NodeRef trad1 = createContent();
NodeRef trad2 = createContent(); NodeRef trad2 = createContent();
NodeRef trad3 = createContent(); NodeRef trad3 = createContent();
NodeRef parent = nodeService.getPrimaryParent(trad1).getParentRef(); NodeRef parent = nodeService.getPrimaryParent(trad1).getParentRef();
multilingualContentService.makeTranslation(trad1, Locale.FRENCH); multilingualContentService.makeTranslation(trad1, Locale.FRENCH);
multilingualContentService.addTranslation(trad2, trad1, Locale.GERMAN); multilingualContentService.addTranslation(trad2, trad1, Locale.GERMAN);
multilingualContentService.addTranslation(trad3, trad1, Locale.ITALIAN); multilingualContentService.addTranslation(trad3, trad1, Locale.ITALIAN);
nodeService.deleteNode(trad3); nodeService.deleteNode(trad3);
// Ensure that the deleted node is romoved from its space // 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()); 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 // 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(trad1).size()); assertEquals("The deleted node must be removed to the child associations of the mlContainer", 2, multilingualContentService.getTranslations(trad1).size());
// retore the deleted node // retore the deleted node
NodeRef restoredNode = nodeArchiveService.restoreArchivedNode(nodeArchiveService.getArchivedNode(trad3)).getRestoredNodeRef(); NodeRef restoredNode = nodeArchiveService.restoreArchivedNode(nodeArchiveService.getArchivedNode(trad3)).getRestoredNodeRef();
// Ensure that the restored node is restored to it s original space // 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()); 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 // 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(trad1).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 // 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)); assertFalse("The restored node can't keep the multilingual aspect", nodeService.hasAspect(restoredNode, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
} }
public void testDeletePivot() throws Exception public void testDeletePivot() throws Exception
{ {
NodeRef pivot = createContent(); NodeRef pivot = createContent();
@@ -97,11 +94,11 @@ public class MultilingualDocumentAspectTest extends AbstractMultilingualTestCase
multilingualContentService.makeTranslation(pivot, Locale.FRENCH); multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
NodeRef mlContainer = multilingualContentService.getTranslationContainer(pivot); NodeRef mlContainer = multilingualContentService.getTranslationContainer(pivot);
multilingualContentService.addTranslation(trans1, pivot, Locale.KOREAN); multilingualContentService.addTranslation(trans1, pivot, Locale.KOREAN);
//nodeService.deleteNode(trans1); //nodeService.deleteNode(trans1);
nodeService.deleteNode(pivot); nodeService.deleteNode(pivot);
// Ensure that pivot is removed // Ensure that pivot is removed
assertFalse("The pivot would be removed", nodeService.exists(pivot)); assertFalse("The pivot would be removed", nodeService.exists(pivot));
// Ensure that the mlContainer is removed // Ensure that the mlContainer is removed
assertFalse("The mlContainer must be removed if the pivot is removed", nodeService.exists(mlContainer)); assertFalse("The mlContainer must be removed if the pivot is removed", nodeService.exists(mlContainer));
@@ -110,25 +107,25 @@ public class MultilingualDocumentAspectTest extends AbstractMultilingualTestCase
// Ensure that trans1 has no mlDocument aspect // Ensure that trans1 has no mlDocument aspect
assertFalse("The last translation can't keep the multilingual aspect", nodeService.hasAspect(trans1, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT)); assertFalse("The last translation can't keep the multilingual aspect", nodeService.hasAspect(trans1, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
} }
public void testDeleteLastNode() throws Exception public void testDeleteLastNode() throws Exception
{ {
NodeRef pivot = createContent(); NodeRef pivot = createContent();
multilingualContentService.makeTranslation(pivot, Locale.FRENCH); multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
NodeRef mlContainer = multilingualContentService.getTranslationContainer(pivot); NodeRef mlContainer = multilingualContentService.getTranslationContainer(pivot);
nodeService.deleteNode(pivot); nodeService.deleteNode(pivot);
// Ensure that the mlContainer is removed too // Ensure that the mlContainer is removed too
assertFalse("The mlContainer must be removed if the last translation is removed", nodeService.exists(mlContainer)); assertFalse("The mlContainer must be removed if the last translation is removed", nodeService.exists(mlContainer));
} }
public void testRemoveAspect() throws Exception public void testRemoveAspect() throws Exception
{ {
// entierly covered by the delete tests // entierly covered by the delete tests
} }
public void testUpdateLocale() throws Exception public void testUpdateLocale() throws Exception
{ {
NodeRef pivot = createContent(); NodeRef pivot = createContent();
@@ -136,12 +133,12 @@ public class MultilingualDocumentAspectTest extends AbstractMultilingualTestCase
multilingualContentService.makeTranslation(pivot, Locale.FRENCH); multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
NodeRef mlContainer = multilingualContentService.getTranslationContainer(pivot); NodeRef mlContainer = multilingualContentService.getTranslationContainer(pivot);
multilingualContentService.addTranslation(trans1, pivot, Locale.KOREAN); multilingualContentService.addTranslation(trans1, pivot, Locale.KOREAN);
// modify the locale for the translation // modify the locale for the translation
Map<QName, Serializable> props = nodeService.getProperties(trans1); Map<QName, Serializable> props = nodeService.getProperties(trans1);
props.put(ContentModel.PROP_LOCALE, Locale.GERMAN); props.put(ContentModel.PROP_LOCALE, Locale.GERMAN);
nodeService.setProperties(trans1, props); nodeService.setProperties(trans1, props);
// Ensure that the pivot reference is not changed for the mlContainer and the locale is changed for the translation // Ensure that the pivot reference is not changed for the mlContainer and the locale is changed for the translation
assertEquals("The locale for the pivot would be changed ",Locale.GERMAN, nodeService.getProperty(trans1, ContentModel.PROP_LOCALE)); assertEquals("The locale for the pivot would be changed ",Locale.GERMAN, nodeService.getProperty(trans1, ContentModel.PROP_LOCALE));
assertEquals("The pivot reference would not be changed in the mlContainer", Locale.FRENCH, nodeService.getProperty(mlContainer, ContentModel.PROP_LOCALE)); assertEquals("The pivot reference would not be changed in the mlContainer", Locale.FRENCH, nodeService.getProperty(mlContainer, ContentModel.PROP_LOCALE));
@@ -150,68 +147,68 @@ public class MultilingualDocumentAspectTest extends AbstractMultilingualTestCase
props = nodeService.getProperties(pivot); props = nodeService.getProperties(pivot);
props.put(ContentModel.PROP_LOCALE, Locale.US); props.put(ContentModel.PROP_LOCALE, Locale.US);
nodeService.setProperties(pivot, props); nodeService.setProperties(pivot, props);
// Ensure that the pivot reference is changed (in the pivot and in the mlContainer) // Ensure that the pivot reference is changed (in the pivot and in the mlContainer)
assertEquals("The locale for the pivot would be changed ", Locale.US, nodeService.getProperty(pivot, ContentModel.PROP_LOCALE)); assertEquals("The locale for the pivot would be changed ", Locale.US, nodeService.getProperty(pivot, ContentModel.PROP_LOCALE));
assertEquals("The pivot reference would be changes in the mlContainer", Locale.US, nodeService.getProperty(mlContainer, ContentModel.PROP_LOCALE)); assertEquals("The pivot reference would be changes in the mlContainer", Locale.US, nodeService.getProperty(mlContainer, ContentModel.PROP_LOCALE));
} }
public void testUpdateRedundantLocale() throws Exception public void testUpdateRedundantLocale() throws Exception
{ {
NodeRef pivot = createContent(); NodeRef pivot = createContent();
NodeRef trans1 = createContent(); NodeRef trans1 = createContent();
NodeRef trans2 = createContent(); NodeRef trans2 = createContent();
multilingualContentService.makeTranslation(pivot, Locale.FRENCH); multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
multilingualContentService.addTranslation(trans1, pivot, Locale.KOREAN); multilingualContentService.addTranslation(trans1, pivot, Locale.KOREAN);
multilingualContentService.addTranslation(trans2, pivot, Locale.JAPANESE); multilingualContentService.addTranslation(trans2, pivot, Locale.JAPANESE);
// 1. Try with redundant locale // 1. Try with redundant locale
// modify the locale for the translation 2 // modify the locale for the translation 2
Map<QName, Serializable> props = nodeService.getProperties(trans2); Map<QName, Serializable> props = nodeService.getProperties(trans2);
props.put(ContentModel.PROP_LOCALE, Locale.KOREAN); props.put(ContentModel.PROP_LOCALE, Locale.KOREAN);
boolean exceptionCatched = false; boolean exceptionCatched = false;
try try
{ {
nodeService.setProperties(trans2, props); nodeService.setProperties(trans2, props);
// test failed // test failed
} catch (Exception ignore) } catch (Exception ignore)
{ {
exceptionCatched = true; exceptionCatched = true;
} }
// Ensure that the the exception was catched. // Ensure that the the exception was catched.
assertTrue("The modification of this locale must catch an exception because it is already in use in another translation", exceptionCatched); assertTrue("The modification of this locale must catch an exception because it is already in use in another translation", exceptionCatched);
// Ensure that the locale of the trans2 is unchanged // Ensure that the locale of the trans2 is unchanged
assertEquals("The locale must not be changed", assertEquals("The locale must not be changed",
Locale.JAPANESE, Locale.JAPANESE,
(Locale) nodeService.getProperty(trans2, ContentModel.PROP_LOCALE)); (Locale) nodeService.getProperty(trans2, ContentModel.PROP_LOCALE));
// 2. Try with a non-redundant locale // 2. Try with a non-redundant locale
props = nodeService.getProperties(trans2); props = nodeService.getProperties(trans2);
props.put(ContentModel.PROP_LOCALE, Locale.ITALIAN); props.put(ContentModel.PROP_LOCALE, Locale.ITALIAN);
exceptionCatched = false; exceptionCatched = false;
try try
{ {
nodeService.setProperties(trans2, props); nodeService.setProperties(trans2, props);
} catch (Exception ignore) } catch (Exception ignore)
{ {
// test failed // test failed
exceptionCatched = true; exceptionCatched = true;
} }
// Ensure that the exception was not catched // Ensure that the exception was not catched
assertFalse("The modification of the locale would not throws an exception", exceptionCatched); assertFalse("The modification of the locale would not throws an exception", exceptionCatched);
// Ensure that the locale is modified // Ensure that the locale is modified
assertEquals("The locale must be changed", assertEquals("The locale must be changed",
Locale.ITALIAN, Locale.ITALIAN,
(Locale) nodeService.getProperty(trans2, ContentModel.PROP_LOCALE)); (Locale) nodeService.getProperty(trans2, ContentModel.PROP_LOCALE));
} }
} }

View File

@@ -25,19 +25,24 @@
package org.alfresco.repo.node; package org.alfresco.repo.node;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import org.alfresco.i18n.I18NUtil; import org.alfresco.i18n.I18NUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition; import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.ml.MultilingualContentService;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.MLText; import org.alfresco.service.cmr.repository.MLText;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.util.EqualsHelper;
import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation; import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@@ -71,6 +76,8 @@ public class MLPropertyInterceptor implements MethodInterceptor
/** Direct access to the NodeService */ /** Direct access to the NodeService */
private NodeService nodeService; private NodeService nodeService;
/** Direct access to the MultilingualContentService */
private MultilingualContentService multilingualContentService;
/** Used to access property definitions */ /** Used to access property definitions */
private DictionaryService dictionaryService; private DictionaryService dictionaryService;
@@ -108,7 +115,12 @@ public class MLPropertyInterceptor implements MethodInterceptor
this.nodeService = bean; this.nodeService = bean;
} }
public void setDictionaryService(DictionaryService dictionaryService) public void setMultilingualContentService(MultilingualContentService multilingualContentService)
{
this.multilingualContentService = multilingualContentService;
}
public void setDictionaryService(DictionaryService dictionaryService)
{ {
this.dictionaryService = dictionaryService; this.dictionaryService = dictionaryService;
} }
@@ -142,13 +154,19 @@ public class MLPropertyInterceptor implements MethodInterceptor
NodeRef nodeRef = (NodeRef) args[0]; NodeRef nodeRef = (NodeRef) args[0];
QName propertyQName = (QName) args[1]; QName propertyQName = (QName) args[1];
// Get the pivot translation, if appropriate
NodeRef pivotNodeRef = getPivotNodeRef(nodeRef);
Serializable value = (Serializable) invocation.proceed(); Serializable value = (Serializable) invocation.proceed();
ret = convertOutboundProperty(contentLocale, nodeRef, propertyQName, value); ret = convertOutboundProperty(contentLocale, nodeRef, pivotNodeRef, propertyQName, value);
} }
else if (methodName.equals("getProperties")) else if (methodName.equals("getProperties"))
{ {
NodeRef nodeRef = (NodeRef) args[0]; NodeRef nodeRef = (NodeRef) args[0];
// Get the pivot translation, if appropriate
NodeRef pivotNodeRef = getPivotNodeRef(nodeRef);
Map<QName, Serializable> properties = (Map<QName, Serializable>) invocation.proceed(); Map<QName, Serializable> properties = (Map<QName, Serializable>) invocation.proceed();
Map<QName, Serializable> convertedProperties = new HashMap<QName, Serializable>(properties.size() * 2); Map<QName, Serializable> convertedProperties = new HashMap<QName, Serializable>(properties.size() * 2);
// Check each return value type // Check each return value type
@@ -156,7 +174,7 @@ public class MLPropertyInterceptor implements MethodInterceptor
{ {
QName propertyQName = entry.getKey(); QName propertyQName = entry.getKey();
Serializable value = entry.getValue(); Serializable value = entry.getValue();
Serializable convertedValue = convertOutboundProperty(contentLocale, nodeRef, propertyQName, value); Serializable convertedValue = convertOutboundProperty(contentLocale, nodeRef, pivotNodeRef, propertyQName, value);
// Add it to the return map // Add it to the return map
convertedProperties.put(propertyQName, convertedValue); convertedProperties.put(propertyQName, convertedValue);
} }
@@ -173,6 +191,10 @@ public class MLPropertyInterceptor implements MethodInterceptor
else if (methodName.equals("setProperties")) else if (methodName.equals("setProperties"))
{ {
NodeRef nodeRef = (NodeRef) args[0]; NodeRef nodeRef = (NodeRef) args[0];
// Get the pivot translation, if appropriate
NodeRef pivotNodeRef = getPivotNodeRef(nodeRef);
Map<QName, Serializable> newProperties =(Map<QName, Serializable>) args[1]; Map<QName, Serializable> newProperties =(Map<QName, Serializable>) args[1];
// Get the current properties for the node // Get the current properties for the node
Map<QName, Serializable> currentProperties = nodeService.getProperties(nodeRef); Map<QName, Serializable> currentProperties = nodeService.getProperties(nodeRef);
@@ -185,7 +207,7 @@ public class MLPropertyInterceptor implements MethodInterceptor
// Get the current property value // Get the current property value
Serializable currentValue = currentProperties.get(propertyQName); Serializable currentValue = currentProperties.get(propertyQName);
// Convert the inbound property value // Convert the inbound property value
inboundValue = convertInboundProperty(contentLocale, nodeRef, propertyQName, inboundValue, currentValue); inboundValue = convertInboundProperty(contentLocale, nodeRef, pivotNodeRef, propertyQName, inboundValue, currentValue);
// Put the value into the map // Put the value into the map
convertedProperties.put(propertyQName, inboundValue); convertedProperties.put(propertyQName, inboundValue);
} }
@@ -199,8 +221,11 @@ public class MLPropertyInterceptor implements MethodInterceptor
QName propertyQName = (QName) args[1]; QName propertyQName = (QName) args[1];
Serializable inboundValue = (Serializable) args[2]; Serializable inboundValue = (Serializable) args[2];
// Get the pivot translation, if appropriate
NodeRef pivotNodeRef = getPivotNodeRef(nodeRef);
// Convert the property // Convert the property
inboundValue = convertInboundProperty(contentLocale, nodeRef, propertyQName, inboundValue, null); inboundValue = convertInboundProperty(contentLocale, nodeRef, pivotNodeRef, propertyQName, inboundValue, null);
// Pass this through to the node service // Pass this through to the node service
nodeService.setProperty(nodeRef, propertyQName, inboundValue); nodeService.setProperty(nodeRef, propertyQName, inboundValue);
@@ -214,23 +239,73 @@ public class MLPropertyInterceptor implements MethodInterceptor
return ret; return ret;
} }
/**
* @param nodeRef
* a potential empty translation
* @return
* the pivot translation node or <tt>null</tt>
*/
private NodeRef getPivotNodeRef(NodeRef nodeRef)
{
if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
{
return multilingualContentService.getPivotTranslation(nodeRef);
}
else
{
return null;
}
}
/** /**
* Ensure that content is spoofed for empty translations. * Ensure that content is spoofed for empty translations.
*/ */
private Serializable convertOutboundProperty( private Serializable convertOutboundProperty(
Locale contentLocale, Locale contentLocale,
NodeRef nodeRef, NodeRef nodeRef,
NodeRef pivotNodeRef,
QName propertyQName, QName propertyQName,
Serializable outboundValue) Serializable outboundValue)
{ {
Serializable ret = null; Serializable ret = null;
// Is it content? if (outboundValue == null)
if (outboundValue != null && outboundValue instanceof MLText) {
ret = null;
}
if (outboundValue instanceof MLText)
{ {
// It is MLText // It is MLText
MLText mlText = (MLText) outboundValue; MLText mlText = (MLText) outboundValue;
ret = mlText.getClosestValue(contentLocale); ret = mlText.getClosestValue(contentLocale);
} }
else if (pivotNodeRef != null) // It is an empty translation
{
if (propertyQName.equals(ContentModel.PROP_MODIFIED))
{
// An empty translation's modified date must be the later of its own
// modified date and the pivot translation's modified date
Date emptyLastModified = (Date) outboundValue;
Date pivotLastModified = (Date) nodeService.getProperty(pivotNodeRef, ContentModel.PROP_MODIFIED);
if (emptyLastModified.compareTo(pivotLastModified) < 0)
{
ret = pivotLastModified;
}
else
{
ret = emptyLastModified;
}
}
else if (propertyQName.equals(ContentModel.PROP_CONTENT))
{
// An empty translation's cm:content must track the cm:content of the
// pivot translation.
ret = nodeService.getProperty(pivotNodeRef, ContentModel.PROP_CONTENT);
}
else
{
ret = outboundValue;
}
}
else else
{ {
ret = outboundValue; ret = outboundValue;
@@ -257,6 +332,7 @@ public class MLPropertyInterceptor implements MethodInterceptor
private Serializable convertInboundProperty( private Serializable convertInboundProperty(
Locale contentLocale, Locale contentLocale,
NodeRef nodeRef, NodeRef nodeRef,
NodeRef pivotNodeRef,
QName propertyQName, QName propertyQName,
Serializable inboundValue, Serializable inboundValue,
Serializable currentValue) Serializable currentValue)
@@ -264,7 +340,11 @@ public class MLPropertyInterceptor implements MethodInterceptor
Serializable ret = null; Serializable ret = null;
PropertyDefinition propertyDef = this.dictionaryService.getProperty(propertyQName); PropertyDefinition propertyDef = this.dictionaryService.getProperty(propertyQName);
//if no type definition associated to the name then just proceed //if no type definition associated to the name then just proceed
if (propertyDef != null && propertyDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT)) if (propertyDef == null)
{
ret = inboundValue;
}
else if (propertyDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT))
{ {
// Don't mess with multivalued properties or instances already of type MLText // Don't mess with multivalued properties or instances already of type MLText
if (propertyDef.isMultiValued() || (inboundValue instanceof MLText) ) if (propertyDef.isMultiValued() || (inboundValue instanceof MLText) )
@@ -293,7 +373,25 @@ public class MLPropertyInterceptor implements MethodInterceptor
ret = returnMLValue; ret = returnMLValue;
} }
} }
else // It is not defined as d:mltext in the dictionary else if (pivotNodeRef != null && propertyQName.equals(ContentModel.PROP_CONTENT))
{
// It is an empty translation. The content must not change if it matches
// the content of the pivot translation
ContentData pivotContentData = (ContentData) nodeService.getProperty(pivotNodeRef, ContentModel.PROP_CONTENT);
ContentData emptyContentData = (ContentData) inboundValue;
String pivotContentUrl = pivotContentData == null ? null : pivotContentData.getContentUrl();
String emptyContentUrl = emptyContentData == null ? null : emptyContentData.getContentUrl();
if (EqualsHelper.nullSafeEquals(pivotContentUrl, emptyContentUrl))
{
// They are a match. So the empty translation must be reset to it's original value
ret = (ContentData) nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT);
}
else
{
ret = inboundValue;
}
}
else
{ {
ret = inboundValue; ret = inboundValue;
} }

View File

@@ -15,11 +15,11 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of * As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre * the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's * and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing * FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here: * the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing" * http://www.alfresco.com/legal/licensing"
*/ */
package org.alfresco.repo.service; package org.alfresco.repo.service;
@@ -39,6 +39,8 @@ import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.lock.LockService; import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.ml.ContentFilterLanguagesService; import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
import org.alfresco.service.cmr.ml.EditionService;
import org.alfresco.service.cmr.ml.MultilingualContentService;
import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.CopyService; import org.alfresco.service.cmr.repository.CopyService;
@@ -71,7 +73,7 @@ import org.springframework.beans.factory.BeanFactoryAware;
/** /**
* Implementation of a Service Registry based on the definition of * Implementation of a Service Registry based on the definition of
* Services contained within a Spring Bean Factory. * Services contained within a Spring Bean Factory.
* *
* @author David Caruana * @author David Caruana
*/ */
public class ServiceDescriptorRegistry public class ServiceDescriptorRegistry
@@ -80,7 +82,7 @@ public class ServiceDescriptorRegistry
// Bean Factory within which the registry lives // Bean Factory within which the registry lives
private BeanFactory beanFactory = null; private BeanFactory beanFactory = null;
/* (non-Javadoc) /* (non-Javadoc)
* @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory) * @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory)
*/ */
@@ -88,7 +90,7 @@ public class ServiceDescriptorRegistry
{ {
this.beanFactory = beanFactory; this.beanFactory = beanFactory;
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.repo.service.ServiceRegistry#getServices() * @see org.alfresco.repo.service.ServiceRegistry#getServices()
*/ */
@@ -112,7 +114,7 @@ public class ServiceDescriptorRegistry
*/ */
public Object getService(QName service) public Object getService(QName service)
{ {
return beanFactory.getBean(service.getLocalName()); return beanFactory.getBean(service.getLocalName());
} }
/* (non-Javadoc) /* (non-Javadoc)
@@ -122,7 +124,7 @@ public class ServiceDescriptorRegistry
{ {
return (DescriptorService)getService(DESCRIPTOR_SERVICE); return (DescriptorService)getService(DESCRIPTOR_SERVICE);
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.repo.service.ServiceRegistry#getNodeService() * @see org.alfresco.repo.service.ServiceRegistry#getNodeService()
*/ */
@@ -186,7 +188,7 @@ public class ServiceDescriptorRegistry
{ {
return (SearchService)getService(SEARCH_SERVICE); return (SearchService)getService(SEARCH_SERVICE);
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.service.ServiceRegistry#getTransactionService() * @see org.alfresco.service.ServiceRegistry#getTransactionService()
*/ */
@@ -218,7 +220,7 @@ public class ServiceDescriptorRegistry
{ {
return (CheckOutCheckInService)getService(COCI_SERVICE); return (CheckOutCheckInService)getService(COCI_SERVICE);
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.service.ServiceRegistry#getCategoryService() * @see org.alfresco.service.ServiceRegistry#getCategoryService()
*/ */
@@ -234,7 +236,7 @@ public class ServiceDescriptorRegistry
{ {
return (NamespaceService)getService(NAMESPACE_SERVICE); return (NamespaceService)getService(NAMESPACE_SERVICE);
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.service.ServiceRegistry#getImporterService() * @see org.alfresco.service.ServiceRegistry#getImporterService()
*/ */
@@ -250,7 +252,7 @@ public class ServiceDescriptorRegistry
{ {
return (ExporterService)getService(EXPORTER_SERVICE); return (ExporterService)getService(EXPORTER_SERVICE);
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.service.ServiceRegistry#getRuleService() * @see org.alfresco.service.ServiceRegistry#getRuleService()
*/ */
@@ -258,7 +260,7 @@ public class ServiceDescriptorRegistry
{ {
return (RuleService)getService(RULE_SERVICE); return (RuleService)getService(RULE_SERVICE);
} }
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see org.alfresco.service.ServiceRegistry#getActionService() * @see org.alfresco.service.ServiceRegistry#getActionService()
@@ -275,7 +277,7 @@ public class ServiceDescriptorRegistry
{ {
return (PermissionService)getService(PERMISSIONS_SERVICE); return (PermissionService)getService(PERMISSIONS_SERVICE);
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.service.ServiceRegistry#getAuthorityService() * @see org.alfresco.service.ServiceRegistry#getAuthorityService()
*/ */
@@ -315,7 +317,7 @@ public class ServiceDescriptorRegistry
{ {
return (WorkflowService)getService(WORKFLOW_SERVICE); return (WorkflowService)getService(WORKFLOW_SERVICE);
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.service.ServiceRegistry#getWorkflowService() * @see org.alfresco.service.ServiceRegistry#getWorkflowService()
*/ */
@@ -366,7 +368,7 @@ public class ServiceDescriptorRegistry
{ {
return (PersonService)getService(PERSON_SERVICE); return (PersonService)getService(PERSON_SERVICE);
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.service.ServiceRegistry#getCrossRepositoryCopyService() * @see org.alfresco.service.ServiceRegistry#getCrossRepositoryCopyService()
*/ */
@@ -386,7 +388,7 @@ public class ServiceDescriptorRegistry
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.service.ServiceRegistry#getContentFilterLanguagesService() * @see org.alfresco.service.ServiceRegistry#getContentFilterLanguagesService()
*/ */
public ContentFilterLanguagesService getContentFilterLanguagesService() public ContentFilterLanguagesService getContentFilterLanguagesService()
{ {
return (ContentFilterLanguagesService) getService(CONTENT_FILTER_LANGUAGES_SERVICE); return (ContentFilterLanguagesService) getService(CONTENT_FILTER_LANGUAGES_SERVICE);
} }
@@ -406,4 +408,20 @@ public class ServiceDescriptorRegistry
{ {
return (VirtServerRegistry)getService(VIRT_SERVER_REGISTRY); return (VirtServerRegistry)getService(VIRT_SERVER_REGISTRY);
} }
/* (non-Javadoc)
* @see org.alfresco.service.ServiceRegistry#getEditionService()
*/
public EditionService getEditionService()
{
return (EditionService) getService(EDITION_SERVICE);
}
/* (non-Javadoc)
* @see org.alfresco.service.ServiceRegistry#getMultilingualContentService()
*/
public MultilingualContentService getMultilingualContentService()
{
return (MultilingualContentService) getService(MULTILINGUAL_CONTENT_SERVICE);
}
} }

View File

@@ -378,6 +378,11 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
ContentModel.PROP_VERSION_LABEL, ContentModel.PROP_VERSION_LABEL,
version.getVersionLabel()); version.getVersionLabel());
// Freeze the version label property
Map<QName, Serializable> versionLabelAsMap = new HashMap<QName, Serializable>(1);
versionLabelAsMap.put(ContentModel.PROP_VERSION_LABEL, version.getVersionLabel());
this.freezeProperties(newVersionRef, versionLabelAsMap);
// Invoke the policy behaviour // Invoke the policy behaviour
invokeAfterCreateVersion(nodeRef, version); invokeAfterCreateVersion(nodeRef, version);

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.version.common;
import java.util.Comparator;
import org.alfresco.service.cmr.version.Version;
/**
* A comparator to sort a version list according theires version labels ascending
*
* @author Yanick Pignot
*/
public class VersionLabelComparator implements Comparator
{
public int compare(Object version1, Object version2)
{
String labelV1 = ((Version) version1).getVersionLabel();
String labelV2 = ((Version) version2).getVersionLabel();
// sort the list ascending
return labelV2.compareTo(labelV1);
}
}

View File

@@ -15,11 +15,11 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of * As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre * the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's * and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing * FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here: * the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing" * http://www.alfresco.com/legal/licensing"
*/ */
package org.alfresco.service; package org.alfresco.service;
@@ -38,6 +38,8 @@ import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.lock.LockService; import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.ml.ContentFilterLanguagesService; import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
import org.alfresco.service.cmr.ml.EditionService;
import org.alfresco.service.cmr.ml.MultilingualContentService;
import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.CopyService; import org.alfresco.service.cmr.repository.CopyService;
@@ -67,15 +69,15 @@ import org.alfresco.service.transaction.TransactionService;
/** /**
* This interface represents the registry of public Repository Services. * This interface represents the registry of public Repository Services.
* The registry provides meta-data about each service and provides * The registry provides meta-data about each service and provides
* access to the service interface. * access to the service interface.
* *
* @author David Caruana * @author David Caruana
*/ */
@PublicService @PublicService
public interface ServiceRegistry public interface ServiceRegistry
{ {
// Service Bean Names // Service Bean Names
static final String SERVICE_REGISTRY = "ServiceRegistry"; static final String SERVICE_REGISTRY = "ServiceRegistry";
static final QName REGISTRY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ServiceRegistry"); static final QName REGISTRY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ServiceRegistry");
@@ -89,6 +91,8 @@ public interface ServiceRegistry
static final QName CONTENT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ContentService"); static final QName CONTENT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ContentService");
static final QName MIMETYPE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "MimetypeService"); static final QName MIMETYPE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "MimetypeService");
static final QName CONTENT_FILTER_LANGUAGES_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ContentFilterLanguagesService"); static final QName CONTENT_FILTER_LANGUAGES_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ContentFilterLanguagesService");
static final QName MULTILINGUAL_CONTENT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "MultilingualContentService");
static final QName EDITION_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "EditionService");
static final QName SEARCH_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "SearchService"); static final QName SEARCH_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "SearchService");
static final QName CATEGORY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CategoryService"); static final QName CATEGORY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CategoryService");
static final QName COPY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CopyService"); static final QName COPY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CopyService");
@@ -126,14 +130,14 @@ public interface ServiceRegistry
/** /**
* Is the specified service provided by the Repository? * Is the specified service provided by the Repository?
* *
* @param service name of service to test provision of * @param service name of service to test provision of
* @return true => provided, false => not provided * @return true => provided, false => not provided
*/ */
@NotAuditable @NotAuditable
boolean isServiceProvided(QName service); boolean isServiceProvided(QName service);
/** /**
* Get the specified service. * Get the specified service.
* *
* @param service name of service to retrieve * @param service name of service to retrieve
@@ -141,13 +145,13 @@ public interface ServiceRegistry
*/ */
@NotAuditable @NotAuditable
Object getService(QName service); Object getService(QName service);
/** /**
* @return the descriptor service * @return the descriptor service
*/ */
@NotAuditable @NotAuditable
DescriptorService getDescriptorService(); DescriptorService getDescriptorService();
/** /**
* @return the transaction service * @return the transaction service
*/ */
@@ -165,13 +169,13 @@ public interface ServiceRegistry
*/ */
@NotAuditable @NotAuditable
NamespaceService getNamespaceService(); NamespaceService getNamespaceService();
/** /**
* @return the authentication service (or null, if one is not provided) * @return the authentication service (or null, if one is not provided)
*/ */
@NotAuditable @NotAuditable
AuthenticationService getAuthenticationService(); AuthenticationService getAuthenticationService();
/** /**
* @return the node service (or null, if one is not provided) * @return the node service (or null, if one is not provided)
*/ */
@@ -183,7 +187,7 @@ public interface ServiceRegistry
*/ */
@NotAuditable @NotAuditable
ContentService getContentService(); ContentService getContentService();
/** /**
* @return the mimetype service (or null, if one is not provided) * @return the mimetype service (or null, if one is not provided)
*/ */
@@ -195,19 +199,19 @@ public interface ServiceRegistry
*/ */
@NotAuditable @NotAuditable
ContentFilterLanguagesService getContentFilterLanguagesService(); ContentFilterLanguagesService getContentFilterLanguagesService();
/** /**
* @return the search service (or null, if one is not provided) * @return the search service (or null, if one is not provided)
*/ */
@NotAuditable @NotAuditable
SearchService getSearchService(); SearchService getSearchService();
/** /**
* @return the version service (or null, if one is not provided) * @return the version service (or null, if one is not provided)
*/ */
@NotAuditable @NotAuditable
VersionService getVersionService(); VersionService getVersionService();
/** /**
* @return the lock service (or null, if one is not provided) * @return the lock service (or null, if one is not provided)
*/ */
@@ -219,73 +223,73 @@ public interface ServiceRegistry
*/ */
@NotAuditable @NotAuditable
DictionaryService getDictionaryService(); DictionaryService getDictionaryService();
/** /**
* @return the copy service (or null, if one is not provided) * @return the copy service (or null, if one is not provided)
*/ */
@NotAuditable @NotAuditable
CopyService getCopyService(); CopyService getCopyService();
/** /**
* @return the checkout / checkin service (or null, if one is not provided) * @return the checkout / checkin service (or null, if one is not provided)
*/ */
@NotAuditable @NotAuditable
CheckOutCheckInService getCheckOutCheckInService(); CheckOutCheckInService getCheckOutCheckInService();
/** /**
* @return the category service (or null, if one is not provided) * @return the category service (or null, if one is not provided)
*/ */
@NotAuditable @NotAuditable
CategoryService getCategoryService(); CategoryService getCategoryService();
/** /**
* @return the importer service or null if not present * @return the importer service or null if not present
*/ */
@NotAuditable @NotAuditable
ImporterService getImporterService(); ImporterService getImporterService();
/** /**
* @return the exporter service or null if not present * @return the exporter service or null if not present
*/ */
@NotAuditable @NotAuditable
ExporterService getExporterService(); ExporterService getExporterService();
/** /**
* @return the rule service (or null, if one is not provided) * @return the rule service (or null, if one is not provided)
*/ */
@NotAuditable @NotAuditable
RuleService getRuleService(); RuleService getRuleService();
/** /**
* @return the action service (or null if one is not provided) * @return the action service (or null if one is not provided)
*/ */
@NotAuditable @NotAuditable
ActionService getActionService(); ActionService getActionService();
/** /**
* @return the permission service (or null if one is not provided) * @return the permission service (or null if one is not provided)
*/ */
@NotAuditable @NotAuditable
PermissionService getPermissionService(); PermissionService getPermissionService();
/** /**
* @return the authority service (or null if one is not provided) * @return the authority service (or null if one is not provided)
*/ */
@NotAuditable @NotAuditable
AuthorityService getAuthorityService(); AuthorityService getAuthorityService();
/** /**
* @return the template service (or null if one is not provided) * @return the template service (or null if one is not provided)
*/ */
@NotAuditable @NotAuditable
TemplateService getTemplateService(); TemplateService getTemplateService();
/** /**
* @return the file-folder manipulation service (or null if one is not provided) * @return the file-folder manipulation service (or null if one is not provided)
*/ */
@NotAuditable @NotAuditable
FileFolderService getFileFolderService(); FileFolderService getFileFolderService();
/** /**
* @return the script execution service (or null if one is not provided) * @return the script execution service (or null if one is not provided)
*/ */
@@ -297,7 +301,7 @@ public interface ServiceRegistry
*/ */
@NotAuditable @NotAuditable
WorkflowService getWorkflowService(); WorkflowService getWorkflowService();
/** /**
* @return the audit service (or null if one is not provided) * @return the audit service (or null if one is not provided)
*/ */
@@ -306,13 +310,13 @@ public interface ServiceRegistry
/** /**
* Get the AVMService. * Get the AVMService.
* @return The AVM service (or null if one is not provided); * @return The AVM service (or null if one is not provided);
*/ */
@NotAuditable @NotAuditable
AVMService getAVMService(); AVMService getAVMService();
/** /**
* Get the AVMLockingAwareService. * Get the AVMLockingAwareService.
* @return The AVM locking aware service (or null if one is not provided); * @return The AVM locking aware service (or null if one is not provided);
*/ */
@NotAuditable @NotAuditable
@@ -331,39 +335,53 @@ public interface ServiceRegistry
*/ */
@NotAuditable @NotAuditable
OwnableService getOwnableService(); OwnableService getOwnableService();
/** /**
* Get the person service (or null if one is not provided) * Get the person service (or null if one is not provided)
* @return * @return
*/ */
@NotAuditable @NotAuditable
PersonService getPersonService(); PersonService getPersonService();
/** /**
* Get the cross repository copy service (or null if one is not provided) * Get the cross repository copy service (or null if one is not provided)
* @return * @return
*/ */
@NotAuditable @NotAuditable
CrossRepositoryCopyService getCrossRepositoryCopyService(); CrossRepositoryCopyService getCrossRepositoryCopyService();
/** /**
* Get the attribute service (or null if one is not provided) * Get the attribute service (or null if one is not provided)
* @return * @return
*/ */
@NotAuditable @NotAuditable
AttributeService getAttributeService(); AttributeService getAttributeService();
/** /**
* Get the AVM locking service (or null if one is not provided) * Get the AVM locking service (or null if one is not provided)
* @return * @return
*/ */
@NotAuditable @NotAuditable
AVMLockingService getAVMLockingService(); AVMLockingService getAVMLockingService();
/** /**
* Get the Virtualisation Server registry service bean * Get the Virtualisation Server registry service bean
* @return * @return
*/ */
@NotAuditable @NotAuditable
VirtServerRegistry getVirtServerRegistry(); VirtServerRegistry getVirtServerRegistry();
/**
* Get the Multilingual Content Service
* @return
*/
@NotAuditable
MultilingualContentService getMultilingualContentService();
/**
* Get the Edition Service
* @return
*/
@NotAuditable
EditionService getEditionService();
} }

View File

@@ -31,6 +31,8 @@ import java.util.Set;
import org.alfresco.service.Auditable; import org.alfresco.service.Auditable;
import org.alfresco.service.PublicService; import org.alfresco.service.PublicService;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
/** /**
@@ -171,10 +173,14 @@ public interface MultilingualContentService
* *
* @param translationNodeRef The <b>cm:mlContainer</b> to copy * @param translationNodeRef The <b>cm:mlContainer</b> to copy
* @param newParentRef The new parent of the copied <b>cm:mlDocument</b> * @param newParentRef The new parent of the copied <b>cm:mlDocument</b>
* @param prefixName The prefix of the name of the copied translations. Can be null.
* @return The copied <b>cm:mlContainer</b> * @return The copied <b>cm:mlContainer</b>
* @throws FileNotFoundException
* @throws FileExistsException
* @throws Exception
*/ */
@Auditable(key = Auditable.Key.ARG_0, parameters = {"translationNodeRef", "newParentRef"}) @Auditable(key = Auditable.Key.ARG_0, parameters = {"mlContainerNodeRef", "newParentRef"})
NodeRef copyTranslationContainer(NodeRef translationNodeRef, NodeRef newParentRef); NodeRef copyTranslationContainer(NodeRef mlContainerNodeRef, NodeRef newParentRef, String prefixName) throws FileExistsException, FileNotFoundException, Exception;
/** /**
* Moves the location of the given <b>cm:mlContainer</b>. * Moves the location of the given <b>cm:mlContainer</b>.
@@ -184,10 +190,18 @@ public interface MultilingualContentService
* *
* @param translationNodeRef The <b>cm:mlContainer</b> to move * @param translationNodeRef The <b>cm:mlContainer</b> to move
* @param newParentRef The new parent of the moved <b>cm:mlDocument</b> * @param newParentRef The new parent of the moved <b>cm:mlDocument</b>
* @throws FileExistsException
* @throws FileNotFoundException
*/ */
@Auditable(key = Auditable.Key.ARG_0, parameters = {"translationNodeRef", "newParentRef"}) @Auditable(key = Auditable.Key.ARG_0, parameters = {"mlContainerNodeRef", "newParentRef"})
void moveTranslationContainer(NodeRef translationNodeRef, NodeRef newParentRef); void moveTranslationContainer(NodeRef mlContainerNodeRef, NodeRef newParentRef) throws FileExistsException, FileNotFoundException;
/**
* Delete the given mlContainer and its translations. The translations will lost their <b>cm:mlDocument</b> aspect and
* will be archved. The empty translations will be permanently deleted.
*
* @param mlContainerNodeRef The <b>cm:mlContainer</b> to remove
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {"mlContainerNodeRef"})
void deleteTranslationContainer(NodeRef mlContainerNodeRef);
} }