Yannick Pignot (European Commission) multilingual services

- EditionService for versioning of groups of translations
 - Quite a bit of trimming of whitespace that I have no intention of undoing.


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5927 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2007-06-13 01:13:25 +00:00
parent f4c758dfe5
commit 9e836f04f8
23 changed files with 1835 additions and 1067 deletions

View File

@@ -39,7 +39,7 @@
</property> </property>
</bean> </bean>
<bean id="mlContentInterceptor" class="org.alfresco.repo.model.ml.MLContentInterceptor" > <bean id="mlContentInterceptor" class="org.alfresco.repo.model.ml.MLContentInterceptor" >
<property name="nodeService"> <property name="nodeService">
<ref bean="nodeService"/> <ref bean="nodeService"/>
</property> </property>
@@ -73,9 +73,6 @@
<property name="searchService"> <property name="searchService">
<ref bean="admSearchService" /> <ref bean="admSearchService" />
</property> </property>
<property name="versionService">
<ref bean="versionService" />
</property>
<property name="permissionService"> <property name="permissionService">
<ref bean="permissionService" /> <ref bean="permissionService" />
</property> </property>
@@ -87,4 +84,29 @@
</property> </property>
</bean> </bean>
<!-- Edition service -->
<bean name="editionService" class="org.alfresco.repo.model.ml.EditionServiceImpl" >
<property name="nodeService">
<ref bean="NodeService" />
</property>
<property name="versionService">
<ref bean="VersionService" />
</property>
<property name="multilingualContentService">
<ref bean="MultilingualContentService" />
</property>
<property name="versionNodeService">
<ref bean="versionNodeService" />
</property>
<property name="policyBehaviourFilter">
<ref bean="policyBehaviourFilter" />
</property>
<property name="nodeArchiveService">
<ref bean="nodeArchiveService" />
</property>
<property name="fileFolderService">
<ref bean="FileFolderService" />
</property>
</bean>
</beans> </beans>

View File

@@ -149,7 +149,7 @@
</property> </property>
</bean> </bean>
<bean id="ADMSearchService" class="org.springframework.aop.framework.ProxyFactoryBean"> <bean id="ADMSearchService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces"> <property name="proxyInterfaces">
<value>org.alfresco.service.cmr.search.SearchService</value> <value>org.alfresco.service.cmr.search.SearchService</value>
</property> </property>
@@ -892,23 +892,23 @@
<property name="enableIndexing"> <property name="enableIndexing">
<value>true</value> <value>true</value>
</property> </property>
<property name="defaultMode"> <property name="defaultMode">
<value>SYNCHRONOUS</value> <value>SYNCHRONOUS</value>
</property> </property>
<property name="indexingDefinitions"> <property name="indexingDefinitions">
<list> <list>
<value>SYNCHRONOUS:TYPE:STAGING</value> <value>SYNCHRONOUS:TYPE:STAGING</value>
<value>UNINDEXED:TYPE:STAGING_PREVIEW</value> <value>UNINDEXED:TYPE:STAGING_PREVIEW</value>
<value>UNINDEXED:TYPE:AUTHOR</value> <value>UNINDEXED:TYPE:AUTHOR</value>
<value>UNINDEXED:TYPE:AUTHOR_PREVIEW</value> <value>UNINDEXED:TYPE:AUTHOR_PREVIEW</value>
<value>UNINDEXED:TYPE:WORKFLOW</value> <value>UNINDEXED:TYPE:WORKFLOW</value>
<value>UNINDEXED:TYPE:WORKFLOW_PREVIEW</value> <value>UNINDEXED:TYPE:WORKFLOW_PREVIEW</value>
<value>UNINDEXED:TYPE:AUTHOR_WORKFLOW</value> <value>UNINDEXED:TYPE:AUTHOR_WORKFLOW</value>
<value>UNINDEXED:TYPE:AUTHOR_WORKFLOW_PREVIEW</value> <value>UNINDEXED:TYPE:AUTHOR_WORKFLOW_PREVIEW</value>
<value>ASYNCHRONOUS:NAME:avmAsynchronousTest</value> <value>ASYNCHRONOUS:NAME:avmAsynchronousTest</value>
<value>SYNCHRONOUS:NAME:.*</value> <value>SYNCHRONOUS:NAME:.*</value>
</list> </list>
</property> </property>
</bean> </bean>
<!-- The AVMSyncService --> <!-- The AVMSyncService -->
@@ -1210,6 +1210,35 @@
</property> </property>
</bean> </bean>
<!-- EditionService -->
<bean id="EditionService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.ml.EditionService</value>
</property>
<property name="target">
<ref bean="editionService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="EditionService_transaction"/>
<idref bean="EditionService_security"/>
</list>
</property>
</bean>
<bean id="EditionService_transaction" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="*">${server.transaction.mode.default}</prop>
</props>
</property>
</bean>
<!-- ConfigurableService --> <!-- ConfigurableService -->
<bean id="ConfigurableService" class="org.springframework.aop.framework.ProxyFactoryBean"> <bean id="ConfigurableService" class="org.springframework.aop.framework.ProxyFactoryBean">
@@ -1319,7 +1348,7 @@
</property> </property>
</bean> </bean>
<!-- Write transaction advisor for link validation service. --> <!-- Write transaction advisor for link validation service. -->
<bean id="linkValidationServiceWriteTxnAdvisor" <bean id="linkValidationServiceWriteTxnAdvisor"
class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"> class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice"> <property name="advice">

View File

@@ -543,10 +543,30 @@
org.alfresco.service.cmr.ml.MultilingualContentService.unmakeTranslation=ACL_NODE.0.sys:base.Write org.alfresco.service.cmr.ml.MultilingualContentService.unmakeTranslation=ACL_NODE.0.sys:base.Write
org.alfresco.service.cmr.ml.MultilingualContentService.addTranslation=ACL_NODE.0.sys:base.Read,ACL_NODE.1.sys:base.Write org.alfresco.service.cmr.ml.MultilingualContentService.addTranslation=ACL_NODE.0.sys:base.Read,ACL_NODE.1.sys:base.Write
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.createEdition=ACL_NODE.0.sys:base.Write 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
</value> </value>
</property> </property>
</bean> </bean>
<!-- =================== -->
<!-- Edition Service -->
<!-- =================== -->
<bean id="EditionService_security" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
<property name="accessDecisionManager"><ref local="accessDecisionManager"/></property>
<property name="afterInvocationManager"><ref local="afterInvocationManager"/></property>
<property name="objectDefinitionSource">
<value>
org.alfresco.service.cmr.ml.EditionService.createEdition=ACL_NODE.0.sys:base.Read
org.alfresco.service.cmr.ml.EditionService.getEditions=ACL_NODE.0.sys:base.Read
org.alfresco.service.cmr.ml.EditionService.getVersionedTranslations=ACL_ALLOW
org.alfresco.service.cmr.ml.EditionService.getVersionedMetadatas=ACL_ALLOW
</value>
</property>
</bean>
<!-- ============================== --> <!-- ============================== -->
<!-- The Check-out/Check-in service --> <!-- The Check-out/Check-in service -->
<!-- ============================== --> <!-- ============================== -->

View File

@@ -45,7 +45,7 @@ import org.apache.commons.logging.LogFactory;
* *
* {@link org.alfresco.service.cmr.ml.ContentFilterLanguagesService Content Filter Languages Service} * {@link org.alfresco.service.cmr.ml.ContentFilterLanguagesService Content Filter Languages Service}
* *
* @author yanipig * @author Yannick Pignot
*/ */
public class ContentFilterLanguagesMap implements ContentFilterLanguagesService public class ContentFilterLanguagesMap implements ContentFilterLanguagesService
{ {

View File

@@ -0,0 +1,420 @@
/*
* 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.model.ml;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.node.archive.NodeArchiveService;
import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.repo.version.common.VersionUtil;
import org.alfresco.service.cmr.ml.EditionService;
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.FileNotFoundException;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionHistory;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Edition support implementation
*
* @author Yannick Pignot
*/
public class EditionServiceImpl implements EditionService
{
private static Log logger = LogFactory.getLog(EditionServiceImpl.class);
private VersionService versionService;
private NodeService nodeService;
private BehaviourFilter policyBehaviourFilter;
private MultilingualContentService multilingualContentService;
private NodeArchiveService nodeArchiveService;
private NodeService versionNodeService;
private FileFolderService fileFolderService;
/**
* List of properties to set persistent when an edition of the mlContainer is created
*/
public static final QName[] ML_CONTAINER_PROPERTIES_TO_VERSION = {
ContentModel.PROP_AUTHOR,
ContentModel.PROP_LOCALE
};
/** @inheritDoc */
public NodeRef createEdition(NodeRef startingTranslationNodeRef, Map<String, Serializable> versionProperties)
{
if (nodeService.hasAspect(startingTranslationNodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
{
return createEditionImpl(
startingTranslationNodeRef,
versionProperties
);
}
else
{
throw new IllegalArgumentException("The node " + startingTranslationNodeRef + " is not multilingual.");
}
}
private NodeRef createEditionImpl(NodeRef startingTranslationNodeRef, Map<String, Serializable> versionProperties)
{
// 1. First step: prepare and version the mlContainer
// Get the ml container to version
NodeRef mlContainerToVersion = multilingualContentService.getTranslationContainer(startingTranslationNodeRef);
// Get all the container's children
List<ChildAssociationRef> childAssocRefs = nodeService.getChildAssocs(
mlContainerToVersion, ContentModel.ASSOC_MULTILINGUAL_CHILD,
RegexQNamePattern.MATCH_ALL);
// get the last edition and add it the Version Histories property to the version
Version currentEdition = versionService.getCurrentVersion(mlContainerToVersion);
addVersionHitoryProperty(currentEdition, childAssocRefs);
if(versionProperties == null)
{
versionProperties = new HashMap<String, Serializable>();
}
// get the properties to add to the edition history
addPropertiesToVersion(versionProperties, mlContainerToVersion);
// Version the container and its translations
versionService.createVersion(mlContainerToVersion, versionProperties, true);
// 2. Third step: prepare the current edition of the mlContainer
// Get the new starting point node, it will be returned
NodeRef startNode;
// copy the translation before its deletion and get usefull properties
NodeRef space = nodeService.getPrimaryParent(startingTranslationNodeRef).getParentRef();
String name = (String) nodeService.getProperty(startingTranslationNodeRef, ContentModel.PROP_NAME);
Locale locale = (Locale) nodeService.getProperty(startingTranslationNodeRef, ContentModel.PROP_LOCALE);
String author = (String) nodeService.getProperty(startingTranslationNodeRef, ContentModel.PROP_AUTHOR);
for (int count = 0;; count++)
{
try
{
// genererate a temporary name.
String tempName = "TEMP_NAME" + System.currentTimeMillis() + "_" + count;
// try to copy the node
startNode = fileFolderService.copy(startingTranslationNodeRef, space, tempName).getNodeRef();
// copy completed without exception
break;
}
catch (FileExistsException e)
{
// try again with a new name
}
catch (FileNotFoundException e)
{
throw new IllegalStateException(e);
}
}
// remove the current translations of the mlContainer
removeTranslations(childAssocRefs);
// restore the original name of the node
nodeService.setProperty(startNode, ContentModel.PROP_NAME, name);
// add the starting node to the mlContainer, and set the author
multilingualContentService.addTranslation(startNode, mlContainerToVersion, locale);
nodeService.setProperty(startNode, ContentModel.PROP_AUTHOR, author);
// set the starting translation become the pivot.
nodeService.setProperty(mlContainerToVersion, ContentModel.PROP_LOCALE, locale);
nodeService.setProperty(mlContainerToVersion, ContentModel.PROP_AUTHOR, author);
// Done
if (logger.isDebugEnabled())
{
// Get the version information
Version mlContainerVersion = versionService.getCurrentVersion(mlContainerToVersion);
String mlContainerVersionLabel = mlContainerVersion.getVersionLabel();
logger.debug("Versioned multilingual container: \n"
+ " Container: " + mlContainerToVersion + "\n"
+ " Current Version: " + mlContainerVersionLabel);
}
return startNode;
}
/** @inheritDoc */
public VersionHistory getEditions(NodeRef mlContainer)
{
VersionHistory editionHistory = null;
// Only the mlContainer can have editions
if (nodeService.getType(mlContainer).equals(
ContentModel.TYPE_MULTILINGUAL_CONTAINER))
{
// get the editions of the mlContainer
editionHistory = versionService.getVersionHistory(mlContainer);
}
else
{
throw new IllegalArgumentException("The type of the node must be "
+ ContentModel.TYPE_CONTAINER);
}
if (logger.isDebugEnabled())
{
logger.debug("Found all editions: \n" + " Node: "
+ mlContainer + " (type "
+ ContentModel.TYPE_MULTILINGUAL_CONTAINER + ")\n"
+ " Editions: " + editionHistory);
}
return editionHistory;
}
/** @inheritDoc */
public Map<QName, Serializable> getVersionedMetadatas(Version version)
{
NodeRef frozenNodeRef = version.getFrozenStateNodeRef();
if(ContentModel.TYPE_MULTILINGUAL_CONTAINER.equals(nodeService.getType(frozenNodeRef)))
{
// for the mlContainer, the properties are set as a version properties
Map<String, Serializable> properties = version.getVersionProperties();
// The returned map of this method need a QName type key, not a String.
Map<QName, Serializable> convertedProperties = new HashMap<QName, Serializable>(properties.size());
// perform the convertion
for(Map.Entry<String, Serializable> entry : properties.entrySet())
{
convertedProperties.put(
QName.createQName(entry.getKey()),
entry.getValue());
}
return convertedProperties;
}
else
{
// for any other type of node, the properties are set as versioned metadata
return versionNodeService.getProperties(frozenNodeRef);
}
}
/** @inheritDoc */
public List<VersionHistory> getVersionedTranslations(Version mlContainerEdition)
{
// Ensure that the given version is an Edition of an mlContainer
if(!ContentModel.TYPE_MULTILINGUAL_CONTAINER.equals(nodeService.getType(mlContainerEdition.getVersionedNodeRef())))
{
throw new IllegalArgumentException("The type of the node must be " + ContentModel.TYPE_CONTAINER);
}
Map<QName, Serializable> properties = versionNodeService.getProperties(mlContainerEdition.getFrozenStateNodeRef());
// get the serialisation of the version histories in the version properties
List<VersionHistory> versionHistories = (List<VersionHistory>)
properties.get(VersionModel.PROP_QNAME_TRANSLATION_VERIONS);
if (versionHistories == null)
{
// the initial edition doesn't content translations (at the creation time of the mlContainer).
versionHistories = new ArrayList<VersionHistory>();
}
if (logger.isDebugEnabled())
{
logger.debug("Found all translations : \n"
+ " Versioned mlContainer: " + mlContainerEdition.getVersionedNodeRef() + "\n"
+ " Edition: " + mlContainerEdition
+ " Translations: " + versionHistories);
}
return versionHistories;
}
/**
* Util method to add the version histories of translations as a property of the frozen mlContainer
*/
private void addVersionHitoryProperty(Version edition, List<ChildAssociationRef> childAssocRefs)
{
List<VersionHistory> translationVersionHistories = new ArrayList<VersionHistory>(childAssocRefs.size());
for (ChildAssociationRef ref : childAssocRefs)
{
NodeRef translation = ref.getChildRef();
translationVersionHistories.add(versionService.getVersionHistory(translation));
}
// properties in which the version histories will be stored
Map<QName, Serializable> properties = new HashMap<QName, Serializable>();
// add the version history of the translation as property of the Edition
properties.put(VersionModel.PROP_QNAME_QNAME, VersionModel.PROP_QNAME_TRANSLATION_VERIONS);
properties.put(VersionModel.PROP_QNAME_IS_MULTI_VALUE, true);
properties.put(VersionModel.PROP_QNAME_MULTI_VALUE, (Serializable) translationVersionHistories);
// create the versioned property node
this.nodeService.createNode(
VersionUtil.convertNodeRef(edition.getFrozenStateNodeRef()),
VersionModel.CHILD_QNAME_VERSIONED_ATTRIBUTES,
VersionModel.CHILD_QNAME_VERSIONED_ATTRIBUTES,
VersionModel.TYPE_QNAME_VERSIONED_PROPERTY,
properties);
}
/**
* Util method to add the usefull properties to the existing properties of the given, mlContainer
*
* @link {@link EditionServiceImpl#ML_CONTAINER_PROPERTIES_TO_VERSION}
*/
private void addPropertiesToVersion(Map<String, Serializable> versionProperties, NodeRef mlContainerToVersion)
{
// add useful properties
for(QName prop : ML_CONTAINER_PROPERTIES_TO_VERSION)
{
versionProperties.put(prop.toString(), nodeService.getProperty(mlContainerToVersion, prop));
}
}
/**
* Util method to remove the given translations after making a new edition
*/
private void removeTranslations(List<ChildAssociationRef> childAssocRefs)
{
// Turn off any auto-version policy behaviours. Without that,
// the version history of the translations will be deleted.
this.policyBehaviourFilter.disableBehaviour(ContentModel.ASPECT_VERSIONABLE);
// Turn off any multilingual document policy behaviours. Without that,
// the mlcontainer of the translations will be deleted.
this.policyBehaviourFilter.disableBehaviour(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
try
{
for (ChildAssociationRef childAssoc : childAssocRefs)
{
NodeRef documentNodeRef = childAssoc.getChildRef();
// Permanently delete it
nodeService.deleteNode(documentNodeRef);
if(nodeService.exists(nodeArchiveService.getArchivedNode(documentNodeRef)))
{
nodeService.deleteNode(nodeArchiveService.getArchivedNode(documentNodeRef));
}
}
}
finally
{
// Turn auto-version and multinlingual document policies back on
this.policyBehaviourFilter.enableBehaviour(ContentModel.ASPECT_VERSIONABLE);
this.policyBehaviourFilter.enableBehaviour(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
}
}
/**
* @param nodeService
* the Node Service to set
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* @param versionService
* the Version Service to set
*/
public void setVersionService(VersionService versionService)
{
this.versionService = versionService;
}
/**
* @param multilingualContentService
* the Multilingual Content Service to set
*/
public void setMultilingualContentService(MultilingualContentService multilingualContentService)
{
this.multilingualContentService = multilingualContentService;
}
/**
* @param versionNodeService
* the Version Store Node Service to set
*/
public void setVersionNodeService(NodeService versionNodeService)
{
this.versionNodeService = versionNodeService;
}
/**
* @param policyBehaviourFilter the Behaviour Filter to set
*/
public void setPolicyBehaviourFilter(BehaviourFilter policyBehaviourFilter)
{
this.policyBehaviourFilter = policyBehaviourFilter;
}
/**
* @param nodeArchiveService the node Archive Service to set
*/
public void setNodeArchiveService(NodeArchiveService nodeArchiveService)
{
this.nodeArchiveService = nodeArchiveService;
}
/**
* @param fileFolderService the fileFolder Service to set
*/
public void setFileFolderService(FileFolderService fileFolderService)
{
this.fileFolderService = fileFolderService;
}
}

View File

@@ -44,7 +44,7 @@ import org.alfresco.service.namespace.QName;
* *
* {@link ContentModel#ASPECT_MULTILINGUAL_EMPTY_TRANSLATION ml empty document aspect} * {@link ContentModel#ASPECT_MULTILINGUAL_EMPTY_TRANSLATION ml empty document aspect}
* *
* @author yanipig * @author Yannick Pignot
*/ */
public class EmptyTranslationAspect implements public class EmptyTranslationAspect implements
CopyServicePolicies.OnCopyNodePolicy, CopyServicePolicies.OnCopyNodePolicy,

View File

@@ -45,7 +45,7 @@ import org.alfresco.service.namespace.QName;
* *
* {@link ContentModel#TYPE_MULTILINGUAL_CONTAINER multilingual container type} * {@link ContentModel#TYPE_MULTILINGUAL_CONTAINER multilingual container type}
* *
* @author yanipig * @author Yannick Pignot
*/ */
public class MLContainerType implements public class MLContainerType implements
NodeServicePolicies.OnUpdatePropertiesPolicy NodeServicePolicies.OnUpdatePropertiesPolicy

View File

@@ -24,7 +24,6 @@
*/ */
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;
@@ -35,7 +34,6 @@ import java.util.Set;
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.version.VersionModel;
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.FileFolderService; import org.alfresco.service.cmr.model.FileFolderService;
@@ -49,8 +47,6 @@ import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters; import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.service.namespace.RegexQNamePattern;
@@ -77,7 +73,7 @@ import org.apache.commons.logging.LogFactory;
* *
* @author Derek Hulley * @author Derek Hulley
* @author Philippe Dubois * @author Philippe Dubois
* @author yanipig * @author Yannick Pignot
*/ */
public class MultilingualContentServiceImpl implements MultilingualContentService public class MultilingualContentServiceImpl implements MultilingualContentService
{ {
@@ -85,7 +81,6 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
private NodeService nodeService; private NodeService nodeService;
private SearchService searchService; private SearchService searchService;
private VersionService versionService;
private PermissionService permissionService; private PermissionService permissionService;
private SearchParameters searchParametersMLRoot; private SearchParameters searchParametersMLRoot;
private ContentFilterLanguagesService contentFilterLanguagesService; private ContentFilterLanguagesService contentFilterLanguagesService;
@@ -136,8 +131,8 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
NodeRef mlContainerRootNodeRef = getMLContainerRoot(); NodeRef mlContainerRootNodeRef = getMLContainerRoot();
// Create the container // Create the container
PropertyMap versionProperties = new PropertyMap(); PropertyMap versionProperties = new PropertyMap();
versionProperties.put(ContentModel.PROP_AUTO_VERSION, Boolean.FALSE); //versionProperties.put(ContentModel.PROP_AUTO_VERSION, Boolean.FALSE);
versionProperties.put(ContentModel.PROP_INITIAL_VERSION, Boolean.FALSE); //versionProperties.put(ContentModel.PROP_INITIAL_VERSION, Boolean.FALSE);
ChildAssociationRef assocRef = nodeService.createNode( ChildAssociationRef assocRef = nodeService.createNode(
mlContainerRootNodeRef, mlContainerRootNodeRef,
ContentModel.ASSOC_CHILDREN, ContentModel.ASSOC_CHILDREN,
@@ -146,8 +141,8 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
versionProperties); versionProperties);
NodeRef mlContainerNodeRef = assocRef.getChildRef(); NodeRef mlContainerNodeRef = assocRef.getChildRef();
// TODO: Examine the usage of versioning - why is autoversioning on and used in the UI? // TODO: Examine the usage of versioning - why is autoversioning on and used in the UI?
// // The model makes the container versionable by default, but why? // The model makes the container versionable by default, but why?
// nodeService.addAspect(mlContainerNodeRef, ContentModel.ASPECT_VERSIONABLE, versionProperties); nodeService.addAspect(mlContainerNodeRef, ContentModel.ASPECT_VERSIONABLE, versionProperties);
// Set the permissions to allow anything by anyone // Set the permissions to allow anything by anyone
permissionService.setPermission( permissionService.setPermission(
mlContainerNodeRef, mlContainerNodeRef,
@@ -432,7 +427,17 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
public void addTranslation(NodeRef newTranslationNodeRef, NodeRef translationOfNodeRef, Locale locale) public void addTranslation(NodeRef newTranslationNodeRef, NodeRef translationOfNodeRef, Locale locale)
{ {
// Get the container // Get the container
NodeRef mlContainerNodeRef = getOrCreateMLContainer(translationOfNodeRef, false); NodeRef mlContainerNodeRef = null;
if(ContentModel.TYPE_MULTILINGUAL_CONTAINER.equals(nodeService.getType(translationOfNodeRef)))
{
mlContainerNodeRef = translationOfNodeRef;
}
else
{
mlContainerNodeRef = getOrCreateMLContainer(translationOfNodeRef, false);
}
// Use the existing container to make the new content into a translation // Use the existing container to make the new content into a translation
makeTranslationImpl(mlContainerNodeRef, newTranslationNodeRef, locale); makeTranslationImpl(mlContainerNodeRef, newTranslationNodeRef, locale);
// done // done
@@ -453,72 +458,6 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
return mlContainerNodeRef; return mlContainerNodeRef;
} }
/** @inheritDoc */
public void createEdition( NodeRef translationNodeRef)
{
NodeRef mlContainerNodeRef = getOrCreateMLContainer(translationNodeRef, false);
// Ensure that the translation given is one of the children
getOrCreateMLContainer(translationNodeRef, false);
// Get all the container's children
List<ChildAssociationRef> childAssocRefs = nodeService.getChildAssocs(
mlContainerNodeRef,
ContentModel.ASSOC_MULTILINGUAL_CHILD,
RegexQNamePattern.MATCH_ALL);
// Get and store the translation verions associated to the mlContainer
List<Version> versions = new ArrayList<Version>(childAssocRefs.size());
for (ChildAssociationRef childAssoc : childAssocRefs)
{
versions.add(versionService.getCurrentVersion(childAssoc.getChildRef()));
}
Map<String, Serializable> editionProperties = new HashMap<String, Serializable>();
editionProperties.put(
VersionModel.PROP_QNAME_TRANSLATION_VERIONS.toString(),
(Serializable) versions
);
// Version the container and all its children
versionService.createVersion(mlContainerNodeRef, editionProperties, true);
// Remove all the child documents apart from the given node
boolean found = false;
for (ChildAssociationRef childAssoc : childAssocRefs)
{
NodeRef documentNodeRef = childAssoc.getChildRef();
// Is this the node to keep?
if (documentNodeRef.equals(translationNodeRef))
{
// It is, so keep it
found = true;
continue;
}
// Delete it
nodeService.deleteNode(documentNodeRef);
}
// Check that we left a document
if (!found)
{
throw new AlfrescoRuntimeException(
"The translation provided is not a child of the multilingual container: \n" +
" Container: " + mlContainerNodeRef + "\n" +
" Translation: " + translationNodeRef);
}
// Done
if (logger.isDebugEnabled())
{
// Get the version information
Version mlContainerVersion = versionService.getCurrentVersion(mlContainerNodeRef);
String mlContainerVersionLabel = mlContainerVersion.getVersionLabel();
logger.debug(
"Versioned multilingual container: \n" +
" Container: " + mlContainerNodeRef + "\n" +
" Current Version: " + mlContainerVersionLabel);
}
}
/** @inheritDoc */ /** @inheritDoc */
public Map<Locale, NodeRef> getTranslations(NodeRef translationOfNodeRef) public Map<Locale, NodeRef> getTranslations(NodeRef translationOfNodeRef)
{ {
@@ -713,7 +652,7 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
name = translationOfName; name = translationOfName;
} }
// If there is a name clash, add the locale to the main portion of the filename // If there is a name clash, add the locale to the main portion of the filename
if (name.equals(translationOfName)) if (name.equalsIgnoreCase(translationOfName))
{ {
String localeStr = locale.toString(); String localeStr = locale.toString();
if (localeStr.endsWith("_")) if (localeStr.endsWith("_"))
@@ -788,15 +727,10 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
this.searchService = searchService; this.searchService = searchService;
} }
public void setVersionService(VersionService versionService)
{
this.versionService = versionService;
}
public void setPermissionService(PermissionService permissionService) public void setPermissionService(PermissionService permissionService)
{ {
this.permissionService = permissionService; this.permissionService = permissionService;
} }
public void setContentFilterLanguagesService(ContentFilterLanguagesService contentFilterLanguagesService) public void setContentFilterLanguagesService(ContentFilterLanguagesService contentFilterLanguagesService)
{ {
@@ -807,4 +741,14 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
{ {
this.fileFolderService = fileFolderService; this.fileFolderService = fileFolderService;
} }
public NodeRef copyTranslationContainer(NodeRef translationNodeRef, NodeRef newParentRef)
{
throw new UnsupportedOperationException("This operation is not yet supported");
}
public void moveTranslationContainer(NodeRef translationNodeRef, NodeRef newParentRef)
{
throw new UnsupportedOperationException("This operation is not yet supported");
}
} }

View File

@@ -35,6 +35,7 @@ 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;
@@ -55,14 +56,23 @@ public class MultilingualDocumentAspect implements
CopyServicePolicies.OnCopyNodePolicy, CopyServicePolicies.OnCopyNodePolicy,
CopyServicePolicies.OnCopyCompletePolicy, 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;
private NodeService nodeService; private NodeService nodeService;
@@ -92,6 +102,12 @@ public class MultilingualDocumentAspect implements
QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"), QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"),
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"));
} }
/** /**
@@ -227,4 +243,18 @@ 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,6 +28,7 @@ import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
import org.alfresco.repo.model.ml.tools.ContentFilterLanguagesMapTest; import org.alfresco.repo.model.ml.tools.ContentFilterLanguagesMapTest;
import org.alfresco.repo.model.ml.tools.EditionServiceImplTest;
import org.alfresco.repo.model.ml.tools.EmptyTranslationAspectTest; import org.alfresco.repo.model.ml.tools.EmptyTranslationAspectTest;
import org.alfresco.repo.model.ml.tools.MLContainerTypeTest; import org.alfresco.repo.model.ml.tools.MLContainerTypeTest;
import org.alfresco.repo.model.ml.tools.MultilingualContentServiceImplTest; import org.alfresco.repo.model.ml.tools.MultilingualContentServiceImplTest;
@@ -54,6 +55,7 @@ public class MultilingualTestSuite extends TestSuite
suite.addTestSuite(MultilingualContentServiceImplTest.class); suite.addTestSuite(MultilingualContentServiceImplTest.class);
suite.addTestSuite(MultilingualDocumentAspectTest.class); suite.addTestSuite(MultilingualDocumentAspectTest.class);
suite.addTestSuite(MLContainerTypeTest.class); suite.addTestSuite(MLContainerTypeTest.class);
suite.addTestSuite(EditionServiceImplTest.class);
return suite; return suite;
} }

View File

@@ -33,6 +33,7 @@ import org.alfresco.repo.transaction.TransactionUtil;
import org.alfresco.repo.transaction.TransactionUtil.TransactionWork; import org.alfresco.repo.transaction.TransactionUtil.TransactionWork;
import org.alfresco.service.ServiceRegistry; import org.alfresco.service.ServiceRegistry;
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.ml.MultilingualContentService;
import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.ContentWriter;
@@ -66,6 +67,8 @@ public abstract class AbstractMultilingualTestCases extends TestCase
protected NodeRef folderNodeRef; protected NodeRef folderNodeRef;
protected ContentFilterLanguagesService contentFilterLanguagesService; protected ContentFilterLanguagesService contentFilterLanguagesService;
protected NodeArchiveService nodeArchiveService; protected NodeArchiveService nodeArchiveService;
protected EditionService editionService;
@Override @Override
protected void setUp() throws Exception protected void setUp() throws Exception
{ {
@@ -78,6 +81,7 @@ public abstract class AbstractMultilingualTestCases extends TestCase
versionService = serviceRegistry.getVersionService(); versionService = serviceRegistry.getVersionService();
multilingualContentService = (MultilingualContentService) ctx.getBean("MultilingualContentService"); multilingualContentService = (MultilingualContentService) ctx.getBean("MultilingualContentService");
contentFilterLanguagesService = (ContentFilterLanguagesService) ctx.getBean("ContentFilterLanguagesService"); contentFilterLanguagesService = (ContentFilterLanguagesService) ctx.getBean("ContentFilterLanguagesService");
editionService = (EditionService) ctx.getBean("EditionService");
// Run as admin // Run as admin
authenticationComponent.setCurrentUser("admin"); authenticationComponent.setCurrentUser("admin");

View File

@@ -35,7 +35,7 @@ import java.util.Locale;
* @see org.alfresco.service.cmr.ml.ContentFilterLanguagesService * @see org.alfresco.service.cmr.ml.ContentFilterLanguagesService
* @see org.alfresco.repo.model.ml.ContentFilterLanguagesMap * @see org.alfresco.repo.model.ml.ContentFilterLanguagesMap
* *
* @author yanipig * @author Yannick Pignot
*/ */
public class ContentFilterLanguagesMapTest extends AbstractMultilingualTestCases public class ContentFilterLanguagesMapTest extends AbstractMultilingualTestCases
{ {

View File

@@ -0,0 +1,233 @@
/*
* 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.model.ml.tools;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionHistory;
import org.alfresco.service.cmr.version.VersionType;
/**
* Edition Service test cases
*
* @since 2.1
* @author Yannick Pignot
*/
public class EditionServiceImplTest extends AbstractMultilingualTestCases
{
private static String FRENCH_CONTENT = "FRENCH_CONTENT";
private static String CHINESE_CONTENT = "CHINESE_CONTENT";
private static String JAPANESE_CONTENT = "JAPANESE_CONTENT";
public void testAutoEdition() throws Exception
{
// create a mlContainer with some content
checkFirstVersion(this.createMLContainerWithContent());
}
public void testEditionLabels()
{
// create a mlContainer with some content
NodeRef mlContainerNodeRef = createMLContainerWithContent();
Map<String, Serializable> versionProperties = null;
List<Version> editions = null;
NodeRef pivot = multilingualContentService.getPivotTranslation(mlContainerNodeRef);
checkFirstVersion(mlContainerNodeRef);
/*
* at the creation (1.0)
*/
Version rootEdition = editionService.getEditions(mlContainerNodeRef).getAllVersions().iterator().next();
// Ensure that the version label is 1.0
assertTrue("The edition label would be 1.0 and not " + rootEdition.getVersionLabel(), rootEdition.getVersionLabel().equals("1.0"));
/*
* default (1.1)
*/
pivot = editionService.createEdition(pivot, versionProperties);
editions = orderVersions(editionService.getEditions(mlContainerNodeRef).getAllVersions());
Version firstEdition = editions.get(0);
// Ensure that the version label is 1.1
assertTrue("The edition label would be 1.1 and not " + firstEdition.getVersionLabel(), firstEdition.getVersionLabel().equals("1.1"));
/*
* major (2.0)
*/
versionProperties = new HashMap<String, Serializable>();
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR);
pivot = editionService.createEdition(pivot, versionProperties);
editions = orderVersions(editionService.getEditions(mlContainerNodeRef).getAllVersions());
Version secondEdition = editions.get(0);
// Ensure that the version label is 2.0
assertTrue("The edition label would be 2.0 and not " + secondEdition.getVersionLabel(), secondEdition.getVersionLabel().equals("2.0"));
/*
* minor (2.1)
*/
versionProperties = new HashMap<String, Serializable>();
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
pivot = editionService.createEdition(pivot, versionProperties);
editions = orderVersions(editionService.getEditions(mlContainerNodeRef).getAllVersions());
Version thirdEdition = editions.get(0);
// Ensure that the version label is 2.1
assertTrue("The edition label would be 2.1 and not " + thirdEdition.getVersionLabel(), thirdEdition.getVersionLabel().equals("2.1"));
}
public void testCreateEdition() throws Exception
{
// create a mlContainer with some content
NodeRef mlContainerNodeRef = createMLContainerWithContent();
// get the french translation
NodeRef frenchContentNodeRef = multilingualContentService.getTranslationForLocale(mlContainerNodeRef, Locale.FRENCH);
checkFirstVersion(mlContainerNodeRef);
// create a new edition form the french translation
NodeRef newStartingPoint = editionService.createEdition(frenchContentNodeRef, null);
// get the edition history
VersionHistory editionHistory = editionService.getEditions(mlContainerNodeRef);
// Ensure that the edition history contains two versions
assertTrue("The edition history must contain two versions", editionHistory.getAllVersions().size() == 2);
// Ensure that the locale of the container is changer
assertTrue("The locale of the conatiner should be changed", nodeService.getProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE).equals(Locale.FRENCH));
// get the two editions
Version rootEdition = editionHistory.getVersion("1.0");
Version actualEdition = editionHistory.getVersion("1.1");
// get the translations of the root versions
List<VersionHistory> rootVersionTranslations = editionService.getVersionedTranslations(rootEdition);
// Ensure that the editions are not null
assertNotNull("The root edition can't be null", rootEdition);
assertNotNull("The actual edition can't be null", actualEdition);
assertNotNull("The translations list of the root edition can't be null", rootVersionTranslations);
// Ensure that the new starting document noderef is different that the initial one
assertFalse("The created starting document must be different that the starting document of the edition", frenchContentNodeRef.equals(newStartingPoint));
// Ensure that the new starting document is the pivot of the current translation
assertTrue("The new pivot must be equal to the created starting document", newStartingPoint.equals(multilingualContentService.getPivotTranslation(mlContainerNodeRef)));
int numberOfTranslations;
// Ensure that the current translations size is 1
numberOfTranslations = multilingualContentService.getTranslations(mlContainerNodeRef).size();
assertEquals("The number of translations must be 1 and not " + numberOfTranslations, 1, numberOfTranslations);
// Ensure that the number of translations of the current edition is 0
numberOfTranslations = editionService.getVersionedTranslations(actualEdition).size();
assertEquals("The number of translations must be 0 and not " + numberOfTranslations, 0, numberOfTranslations);
// Ensure that the number of translations of the root verions is 3
numberOfTranslations = rootVersionTranslations.size();
assertEquals("The number of translations must be 3 and not " + numberOfTranslations, 3, numberOfTranslations);
}
public void testReadVersionedContent() throws Exception
{
}
public void testReadVersionedProperties() throws Exception
{
}
private void checkFirstVersion(NodeRef mlContainerNodeRef)
{
// get the edition list of edition
VersionHistory editionHistory = editionService.getEditions(mlContainerNodeRef);
// Ensure that the first edition of the mlContainer is created
assertNotNull("The edition history can't be null", editionHistory);
// Ensure that it contains only one version
assertTrue("The edition history must contain only one edition", editionHistory.getAllVersions().size() == 1);
// get the edition
Version currentEdition = editionHistory.getAllVersions().iterator().next();
// Ensure that this version is the edition of the mlContainer
assertTrue("The versioned mlContainer noderef of the editon must be the noderef of the created mlContainer", currentEdition.getVersionedNodeRef().equals(mlContainerNodeRef));
// get the list of translations
List<VersionHistory> translations = editionService.getVersionedTranslations(currentEdition);
// Ensure that the get versioned translations is empty
assertNotNull("The translations list of the current edition can't be null", translations);
// Ensure that the list is empty
assertTrue("The translations list of the current edition would be empty", translations.size() == 0);
}
private NodeRef createMLContainerWithContent()
{
NodeRef chineseContentNodeRef = createContent(CHINESE_CONTENT + "_1.0");
NodeRef frenchContentNodeRef = createContent(FRENCH_CONTENT + "_1.0");
NodeRef japaneseContentNodeRef = createContent(JAPANESE_CONTENT + "_1.0");
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
multilingualContentService.addTranslation(japaneseContentNodeRef, chineseContentNodeRef, Locale.JAPANESE);
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")
private List<Version> orderVersions(Collection<Version> allVersions)
{
List<Version> versionsAsList = new ArrayList<Version>(allVersions.size());
versionsAsList.addAll(allVersions);
Collections.sort(versionsAsList, versionComparator);
return versionsAsList;
}
}

View File

@@ -40,7 +40,7 @@ import org.alfresco.service.namespace.QName;
* *
* @see org.alfresco.service.cmr.ml.EmptyTranslationAspect * @see org.alfresco.service.cmr.ml.EmptyTranslationAspect
* *
* @author yanipig * @author Yannick Pignot
*/ */
public class EmptyTranslationAspectTest extends AbstractMultilingualTestCases { public class EmptyTranslationAspectTest extends AbstractMultilingualTestCases {

View File

@@ -37,7 +37,7 @@ import org.alfresco.service.namespace.QName;
* *
* @see org.alfresco.service.cmr.ml.MLContainerType * @see org.alfresco.service.cmr.ml.MLContainerType
* *
* @author yanipig * @author Yannick Pignot
*/ */
public class MLContainerTypeTest extends AbstractMultilingualTestCases public class MLContainerTypeTest extends AbstractMultilingualTestCases
{ {

View File

@@ -24,11 +24,8 @@
*/ */
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,8 +36,6 @@ import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionHistory;
/** /**
* @see org.alfresco.repo.ml.MultilingualContentServiceImpl * @see org.alfresco.repo.ml.MultilingualContentServiceImpl
@@ -231,58 +226,6 @@ public class MultilingualContentServiceImplTest extends AbstractMultilingualTest
assertEquals("Empty translation name not generated correctly.", "Document2.txt", differentName); assertEquals("Empty translation name not generated correctly.", "Document2.txt", differentName);
} }
@SuppressWarnings("unused")
public void testCreateEdition() throws Exception
{
// Make some content
NodeRef chineseContentNodeRef = createContent();
NodeRef frenchContentNodeRef = createContent();
NodeRef japaneseContentNodeRef = createContent();
// Add to container
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
multilingualContentService.addTranslation(japaneseContentNodeRef, chineseContentNodeRef, Locale.JAPANESE);
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(chineseContentNodeRef);
// Check the container child count
assertEquals("Incorrect number of child nodes", 3, nodeService.getChildAssocs(mlContainerNodeRef).size());
// Version each of the documents
List<NodeRef> nodeRefs = new ArrayList<NodeRef>(3);
nodeRefs.add(chineseContentNodeRef);
nodeRefs.add(frenchContentNodeRef);
nodeRefs.add(japaneseContentNodeRef);
versionService.createVersion(nodeRefs, null);
// Get the current versions of each of the documents
Version chineseVersionPreEdition = versionService.getCurrentVersion(chineseContentNodeRef);
Version frenchVersionPreEdition = versionService.getCurrentVersion(frenchContentNodeRef);
Version japaneseVersionPreEdition = versionService.getCurrentVersion(japaneseContentNodeRef);
// Create the edition, keeping the Chinese translation as the basis
multilingualContentService.createEdition(chineseContentNodeRef);
// Check the container child count
assertEquals("Incorrect number of child nodes", 1, nodeService.getChildAssocs(mlContainerNodeRef).size());
// Get the document versions now
Version chineseVersionPostEdition = versionService.getCurrentVersion(chineseContentNodeRef);
assertFalse("Expected document to be gone", nodeService.exists(frenchContentNodeRef));
assertFalse("Expected document to be gone", nodeService.exists(japaneseContentNodeRef));
// Now be sure that we can get the required information using the version service
VersionHistory mlContainerVersionHistory = versionService.getVersionHistory(mlContainerNodeRef);
Collection<Version> mlContainerVersions = mlContainerVersionHistory.getAllVersions();
// Loop through and get all the children of each version
for (Version mlContainerVersion : mlContainerVersions)
{
NodeRef versionedMLContainerNodeRef = mlContainerVersion.getFrozenStateNodeRef();
// Get all the children
Map<Locale, NodeRef> translationsByLocale = multilingualContentService.getTranslations(
versionedMLContainerNodeRef);
// Count the children
int count = translationsByLocale.size();
}
}
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
@@ -335,7 +278,6 @@ public class MultilingualContentServiceImplTest extends AbstractMultilingualTest
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE); multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH); multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
multilingualContentService.addEmptyTranslation(chineseContentNodeRef, null, Locale.JAPANESE); multilingualContentService.addEmptyTranslation(chineseContentNodeRef, null, Locale.JAPANESE);
multilingualContentService.createEdition(chineseContentNodeRef);
} }
finally finally
{ {

View File

@@ -37,7 +37,7 @@ import org.alfresco.service.namespace.QName;
* *
* @see org.alfresco.service.cmr.ml.MultilingualDocumentAspect * @see org.alfresco.service.cmr.ml.MultilingualDocumentAspect
* *
* @author yanipig * @author Yannick Pignot
*/ */
public class MultilingualDocumentAspectTest extends AbstractMultilingualTestCases public class MultilingualDocumentAspectTest extends AbstractMultilingualTestCases
{ {

View File

@@ -35,6 +35,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.version.common.VersionUtil;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.InvalidAspectException; import org.alfresco.service.cmr.dictionary.InvalidAspectException;
import org.alfresco.service.cmr.dictionary.PropertyDefinition; import org.alfresco.service.cmr.dictionary.PropertyDefinition;
@@ -149,7 +150,7 @@ public class NodeServiceImpl implements NodeService, VersionModel
*/ */
public boolean exists(NodeRef nodeRef) public boolean exists(NodeRef nodeRef)
{ {
return dbNodeService.exists(convertNodeRef(nodeRef)); return dbNodeService.exists(VersionUtil.convertNodeRef(nodeRef));
} }
/** /**
@@ -160,18 +161,6 @@ public class NodeServiceImpl implements NodeService, VersionModel
return dbNodeService.getNodeStatus(nodeRef); return dbNodeService.getNodeStatus(nodeRef);
} }
/**
* Convert the incomming node ref (with the version store protocol specified)
* to the internal representation with the workspace protocol.
*
* @param nodeRef the incomming verison protocol node reference
* @return the internal version node reference
*/
private NodeRef convertNodeRef(NodeRef nodeRef)
{
return new NodeRef(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, STORE_ID), nodeRef.getId());
}
/** /**
* Delegates to the <code>NodeService</code> used as the version store implementation * Delegates to the <code>NodeService</code> used as the version store implementation
*/ */
@@ -184,7 +173,7 @@ public class NodeServiceImpl implements NodeService, VersionModel
* @throws UnsupportedOperationException always * @throws UnsupportedOperationException always
*/ */
public ChildAssociationRef createNode( public ChildAssociationRef createNode(
NodeRef parentRef, NodeRef parentRef,
QName assocTypeQName, QName assocTypeQName,
QName assocQName, QName assocQName,
QName nodeTypeQName) throws InvalidNodeRefException QName nodeTypeQName) throws InvalidNodeRefException
@@ -197,7 +186,7 @@ public class NodeServiceImpl implements NodeService, VersionModel
* @throws UnsupportedOperationException always * @throws UnsupportedOperationException always
*/ */
public ChildAssociationRef createNode( public ChildAssociationRef createNode(
NodeRef parentRef, NodeRef parentRef,
QName assocTypeQName, QName assocTypeQName,
QName assocQName, QName assocQName,
QName nodeTypeQName, QName nodeTypeQName,
@@ -274,7 +263,7 @@ public class NodeServiceImpl implements NodeService, VersionModel
*/ */
public QName getType(NodeRef nodeRef) throws InvalidNodeRefException public QName getType(NodeRef nodeRef) throws InvalidNodeRefException
{ {
return (QName)this.dbNodeService.getProperty(convertNodeRef(nodeRef), PROP_QNAME_FROZEN_NODE_TYPE); return (QName)this.dbNodeService.getProperty(VersionUtil.convertNodeRef(nodeRef), PROP_QNAME_FROZEN_NODE_TYPE);
} }
/** /**
@@ -318,7 +307,7 @@ public class NodeServiceImpl implements NodeService, VersionModel
public Set<QName> getAspects(NodeRef nodeRef) throws InvalidNodeRefException public Set<QName> getAspects(NodeRef nodeRef) throws InvalidNodeRefException
{ {
return new HashSet<QName>( return new HashSet<QName>(
(ArrayList<QName>)this.dbNodeService.getProperty(convertNodeRef(nodeRef), PROP_QNAME_FROZEN_ASPECTS)); (ArrayList<QName>)this.dbNodeService.getProperty(VersionUtil.convertNodeRef(nodeRef), PROP_QNAME_FROZEN_ASPECTS));
} }
/** /**
@@ -326,9 +315,9 @@ public class NodeServiceImpl implements NodeService, VersionModel
*/ */
public Map<QName, Serializable> getProperties(NodeRef nodeRef) throws InvalidNodeRefException public Map<QName, Serializable> getProperties(NodeRef nodeRef) throws InvalidNodeRefException
{ {
Map<QName, Serializable> result = new HashMap<QName, Serializable>(); Map<QName, Serializable> result = new HashMap<QName, Serializable>();
Collection<ChildAssociationRef> children = this.dbNodeService.getChildAssocs(convertNodeRef(nodeRef), CHILD_QNAME_VERSIONED_ATTRIBUTES, RegexQNamePattern.MATCH_ALL); Collection<ChildAssociationRef> children = this.dbNodeService.getChildAssocs(VersionUtil.convertNodeRef(nodeRef), CHILD_QNAME_VERSIONED_ATTRIBUTES, RegexQNamePattern.MATCH_ALL);
for (ChildAssociationRef child : children) for (ChildAssociationRef child : children)
{ {
NodeRef versionedAttribute = child.getChildRef(); NodeRef versionedAttribute = child.getChildRef();
@@ -352,7 +341,7 @@ public class NodeServiceImpl implements NodeService, VersionModel
result.put(qName, value); result.put(qName, value);
} }
return result; return result;
} }
/** /**
@@ -362,7 +351,7 @@ public class NodeServiceImpl implements NodeService, VersionModel
{ {
// TODO should be doing this with a search ... // TODO should be doing this with a search ...
Map<QName, Serializable> properties = getProperties(convertNodeRef(nodeRef)); Map<QName, Serializable> properties = getProperties(VersionUtil.convertNodeRef(nodeRef));
return properties.get(qname); return properties.get(qname);
} }
@@ -428,7 +417,7 @@ public class NodeServiceImpl implements NodeService, VersionModel
*/ */
public List<ChildAssociationRef> getChildAssocs(NodeRef nodeRef) throws InvalidNodeRefException public List<ChildAssociationRef> getChildAssocs(NodeRef nodeRef) throws InvalidNodeRefException
{ {
return getChildAssocs(convertNodeRef(nodeRef), RegexQNamePattern.MATCH_ALL, RegexQNamePattern.MATCH_ALL); return getChildAssocs(VersionUtil.convertNodeRef(nodeRef), RegexQNamePattern.MATCH_ALL, RegexQNamePattern.MATCH_ALL);
} }
/** /**
@@ -438,7 +427,7 @@ public class NodeServiceImpl implements NodeService, VersionModel
{ {
// Get the child assocs from the version store // Get the child assocs from the version store
List<ChildAssociationRef> childAssocRefs = this.dbNodeService.getChildAssocs( List<ChildAssociationRef> childAssocRefs = this.dbNodeService.getChildAssocs(
convertNodeRef(nodeRef), VersionUtil.convertNodeRef(nodeRef),
RegexQNamePattern.MATCH_ALL, CHILD_QNAME_VERSIONED_CHILD_ASSOCS); RegexQNamePattern.MATCH_ALL, CHILD_QNAME_VERSIONED_CHILD_ASSOCS);
List<ChildAssociationRef> result = new ArrayList<ChildAssociationRef>(childAssocRefs.size()); List<ChildAssociationRef> result = new ArrayList<ChildAssociationRef>(childAssocRefs.size());
for (ChildAssociationRef childAssocRef : childAssocRefs) for (ChildAssociationRef childAssocRef : childAssocRefs)
@@ -525,7 +514,7 @@ public class NodeServiceImpl implements NodeService, VersionModel
{ {
// Get the child assocs from the version store // Get the child assocs from the version store
List<ChildAssociationRef> childAssocRefs = this.dbNodeService.getChildAssocs( List<ChildAssociationRef> childAssocRefs = this.dbNodeService.getChildAssocs(
convertNodeRef(sourceRef), VersionUtil.convertNodeRef(sourceRef),
RegexQNamePattern.MATCH_ALL, CHILD_QNAME_VERSIONED_ASSOCS); RegexQNamePattern.MATCH_ALL, CHILD_QNAME_VERSIONED_ASSOCS);
List<AssociationRef> result = new ArrayList<AssociationRef>(childAssocRefs.size()); List<AssociationRef> result = new ArrayList<AssociationRef>(childAssocRefs.size());
for (ChildAssociationRef childAssocRef : childAssocRefs) for (ChildAssociationRef childAssocRef : childAssocRefs)

View File

@@ -66,7 +66,7 @@ import org.alfresco.util.ParameterCheck;
* @author Roy Wetheral * @author Roy Wetheral
*/ */
public class VersionServiceImpl extends AbstractVersionServiceImpl public class VersionServiceImpl extends AbstractVersionServiceImpl
implements VersionService, VersionModel implements VersionService, VersionModel
{ {
/** /**
* Error message I18N id's * Error message I18N id's
@@ -135,22 +135,28 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
this.policyBehaviourFilter = policyBehaviourFilter; this.policyBehaviourFilter = policyBehaviourFilter;
} }
/** /**
* Initialise method * Initialise method
*/ */
@Override @Override
public void initialise() public void initialise()
{ {
super.initialise(); super.initialise();
// Register the serial version label behaviour // Register the serial version label behaviour
this.policyComponent.bindClassBehaviour( this.policyComponent.bindClassBehaviour(
QName.createQName(NamespaceService.ALFRESCO_URI, "calculateVersionLabel"), QName.createQName(NamespaceService.ALFRESCO_URI, "calculateVersionLabel"),
ContentModel.TYPE_CMOBJECT, ContentModel.TYPE_CMOBJECT,
new JavaBehaviour(new SerialVersionLabelPolicy(), "calculateVersionLabel")); new JavaBehaviour(new SerialVersionLabelPolicy(), "calculateVersionLabel"));
}
/** // Register the serial version label behaviour for the mlContainer too
this.policyComponent.bindClassBehaviour(
QName.createQName(NamespaceService.ALFRESCO_URI, "calculateVersionLabel"),
ContentModel.TYPE_MULTILINGUAL_CONTAINER,
new JavaBehaviour(new SerialVersionLabelPolicy(), "calculateVersionLabel"));
}
/**
* Gets the reference to the version store * Gets the reference to the version store
* *
* @return reference to the version store * @return reference to the version store
@@ -159,7 +165,7 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
{ {
return new StoreRef( return new StoreRef(
StoreRef.PROTOCOL_WORKSPACE, StoreRef.PROTOCOL_WORKSPACE,
VersionModel.STORE_ID); VersionModel.STORE_ID);
} }
/** /**
@@ -283,8 +289,8 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
throws ReservedVersionNameException throws ReservedVersionNameException
{ {
// Copy the version properties (to prevent unexpected side effects to the caller) // Copy the version properties (to prevent unexpected side effects to the caller)
Map<String, Serializable> versionProperties = new HashMap<String, Serializable>(); Map<String, Serializable> versionProperties = new HashMap<String, Serializable>();
if (origVersionProperties != null) if (origVersionProperties != null)
{ {
versionProperties.putAll(origVersionProperties); versionProperties.putAll(origVersionProperties);
@@ -297,7 +303,7 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
} }
// Call the policy behaviour // Call the policy behaviour
invokeBeforeCreateVersion(nodeRef); invokeBeforeCreateVersion(nodeRef);
// Check that the supplied additional version properties do not clash with the reserved ones // Check that the supplied additional version properties do not clash with the reserved ones
VersionUtil.checkVersionPropertyNames(versionProperties.keySet()); VersionUtil.checkVersionPropertyNames(versionProperties.keySet());
@@ -331,14 +337,14 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
} }
} }
// Create the node details // Create the node details
QName classRef = this.nodeService.getType(nodeRef); QName classRef = this.nodeService.getType(nodeRef);
PolicyScope nodeDetails = new PolicyScope(classRef); PolicyScope nodeDetails = new PolicyScope(classRef);
// Get the node details by calling the onVersionCreate policy behaviour // Get the node details by calling the onVersionCreate policy behaviour
invokeOnCreateVersion(nodeRef, versionProperties, nodeDetails); invokeOnCreateVersion(nodeRef, versionProperties, nodeDetails);
// Create the new version node (child of the version history) // Create the new version node (child of the version history)
NodeRef newVersionRef = createNewVersion( NodeRef newVersionRef = createNewVersion(
nodeRef, nodeRef,
versionHistoryRef, versionHistoryRef,
@@ -410,35 +416,35 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
if (this.nodeService.exists(nodeRef) == true) if (this.nodeService.exists(nodeRef) == true)
{ {
NodeRef versionHistoryRef = getVersionHistoryNodeRef(nodeRef); NodeRef versionHistoryRef = getVersionHistoryNodeRef(nodeRef);
if (versionHistoryRef != null) if (versionHistoryRef != null)
{ {
versionHistory = buildVersionHistory(versionHistoryRef, nodeRef); versionHistory = buildVersionHistory(versionHistoryRef, nodeRef);
} }
} }
return versionHistory; return versionHistory;
} }
/** /**
* @see VersionService#getCurrentVersion(NodeRef) * @see VersionService#getCurrentVersion(NodeRef)
*/ */
public Version getCurrentVersion(NodeRef nodeRef) public Version getCurrentVersion(NodeRef nodeRef)
{ {
Version version = null; Version version = null;
if (this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE) == true) if (this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE) == true)
{ {
VersionHistory versionHistory = getVersionHistory(nodeRef); VersionHistory versionHistory = getVersionHistory(nodeRef);
if (versionHistory != null) if (versionHistory != null)
{ {
String versionLabel = (String)this.nodeService.getProperty(nodeRef, ContentModel.PROP_VERSION_LABEL); String versionLabel = (String)this.nodeService.getProperty(nodeRef, ContentModel.PROP_VERSION_LABEL);
version = versionHistory.getVersion(versionLabel); version = versionHistory.getVersion(versionLabel);
} }
} }
return version; return version;
} }
/** /**
* Get a map containing the standard list of version properties populated. * Get a map containing the standard list of version properties populated.
@@ -449,38 +455,38 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
* @param versionNumber the version number * @param versionNumber the version number
* @return the standard version properties * @return the standard version properties
*/ */
private Map<QName, Serializable> getStandardVersionProperties(Map<String, Serializable> versionProperties, NodeRef nodeRef, NodeRef preceedingNodeRef, int versionNumber) private Map<QName, Serializable> getStandardVersionProperties(Map<String, Serializable> versionProperties, NodeRef nodeRef, NodeRef preceedingNodeRef, int versionNumber)
{ {
Map<QName, Serializable> result = new HashMap<QName, Serializable>(10); Map<QName, Serializable> result = new HashMap<QName, Serializable>(10);
// Set the version number for the new version // Set the version number for the new version
result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_VERSION_NUMBER), Integer.toString(versionNumber)); result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_VERSION_NUMBER), Integer.toString(versionNumber));
// Set the versionable node id // Set the versionable node id
result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_FROZEN_NODE_ID), nodeRef.getId()); result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_FROZEN_NODE_ID), nodeRef.getId());
// Set the versionable node store protocol // Set the versionable node store protocol
result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_FROZEN_NODE_STORE_PROTOCOL), nodeRef.getStoreRef().getProtocol()); result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_FROZEN_NODE_STORE_PROTOCOL), nodeRef.getStoreRef().getProtocol());
// Set the versionable node store id // Set the versionable node store id
result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_FROZEN_NODE_STORE_ID), nodeRef.getStoreRef().getIdentifier()); result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_FROZEN_NODE_STORE_ID), nodeRef.getStoreRef().getIdentifier());
// Store the current node type // Store the current node type
QName nodeType = this.nodeService.getType(nodeRef); QName nodeType = this.nodeService.getType(nodeRef);
result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_FROZEN_NODE_TYPE), nodeType); result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_FROZEN_NODE_TYPE), nodeType);
// Store the current aspects // Store the current aspects
Set<QName> aspects = this.nodeService.getAspects(nodeRef); Set<QName> aspects = this.nodeService.getAspects(nodeRef);
result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_FROZEN_ASPECTS), (Serializable)aspects); result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_FROZEN_ASPECTS), (Serializable)aspects);
// Calculate the version label // Calculate the version label
QName classRef = this.nodeService.getType(nodeRef); QName classRef = this.nodeService.getType(nodeRef);
Version preceedingVersion = getVersion(preceedingNodeRef); Version preceedingVersion = getVersion(preceedingNodeRef);
String versionLabel = invokeCalculateVersionLabel(classRef, preceedingVersion, versionNumber, versionProperties); String versionLabel = invokeCalculateVersionLabel(classRef, preceedingVersion, versionNumber, versionProperties);
result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_VERSION_LABEL), versionLabel); result.put(QName.createQName(NAMESPACE_URI, VersionModel.PROP_VERSION_LABEL), versionLabel);
return result; return result;
} }
/** /**
* Creates a new version node, setting the properties both calculated and specified. * Creates a new version node, setting the properties both calculated and specified.
@@ -488,22 +494,22 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
* @param versionableNodeRef the reference to the node being versioned * @param versionableNodeRef the reference to the node being versioned
* @param versionHistoryRef version history node reference * @param versionHistoryRef version history node reference
* @param preceedingNodeRef the version node preceeding this in the version history * @param preceedingNodeRef the version node preceeding this in the version history
* , null if none * , null if none
* @param versionProperties version properties * @param versionProperties version properties
* @param versionNumber the version number * @param versionNumber the version number
* @return the version node reference * @return the version node reference
*/ */
private NodeRef createNewVersion( private NodeRef createNewVersion(
NodeRef versionableNodeRef, NodeRef versionableNodeRef,
NodeRef versionHistoryRef, NodeRef versionHistoryRef,
Map<QName, Serializable> standardVersionProperties, Map<QName, Serializable> standardVersionProperties,
Map<String, Serializable> versionProperties, Map<String, Serializable> versionProperties,
PolicyScope nodeDetails) PolicyScope nodeDetails)
{ {
// Create the new version // Create the new version
ChildAssociationRef childAssocRef = this.dbNodeService.createNode( ChildAssociationRef childAssocRef = this.dbNodeService.createNode(
versionHistoryRef, versionHistoryRef,
CHILD_QNAME_VERSIONS, CHILD_QNAME_VERSIONS,
CHILD_QNAME_VERSIONS, CHILD_QNAME_VERSIONS,
TYPE_QNAME_VERSION, TYPE_QNAME_VERSION,
standardVersionProperties); standardVersionProperties);
@@ -512,14 +518,14 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
// Store the meta data // Store the meta data
storeVersionMetaData(versionNodeRef, versionProperties); storeVersionMetaData(versionNodeRef, versionProperties);
// Freeze the various parts of the node // Freeze the various parts of the node
freezeProperties(versionNodeRef, nodeDetails.getProperties()); freezeProperties(versionNodeRef, nodeDetails.getProperties());
freezeChildAssociations(versionNodeRef, nodeDetails.getChildAssociations()); freezeChildAssociations(versionNodeRef, nodeDetails.getChildAssociations());
freezeAssociations(versionNodeRef, nodeDetails.getAssociations()); freezeAssociations(versionNodeRef, nodeDetails.getAssociations());
freezeAspects(nodeDetails, versionNodeRef, nodeDetails.getAspects()); freezeAspects(nodeDetails, versionNodeRef, nodeDetails.getAspects());
// Return the created node reference // Return the created node reference
return versionNodeRef; return versionNodeRef;
} }
/** /**
@@ -528,7 +534,7 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
* @param versionNodeRef the version node reference * @param versionNodeRef the version node reference
* @param versionProperties the version properties * @param versionProperties the version properties
*/ */
private void storeVersionMetaData(NodeRef versionNodeRef, Map<String, Serializable> versionProperties) private void storeVersionMetaData(NodeRef versionNodeRef, Map<String, Serializable> versionProperties)
{ {
for (Map.Entry<String, Serializable> entry : versionProperties.entrySet()) for (Map.Entry<String, Serializable> entry : versionProperties.entrySet())
{ {
@@ -547,32 +553,32 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
} }
/** /**
* Freeze the aspects * Freeze the aspects
* *
* @param nodeDetails the node details * @param nodeDetails the node details
* @param versionNodeRef the version node reference * @param versionNodeRef the version node reference
* @param aspects the set of aspects * @param aspects the set of aspects
*/ */
private void freezeAspects(PolicyScope nodeDetails, NodeRef versionNodeRef, Set<QName> aspects) private void freezeAspects(PolicyScope nodeDetails, NodeRef versionNodeRef, Set<QName> aspects)
{ {
for (QName aspect : aspects) for (QName aspect : aspects)
{ {
// Freeze the details of the aspect // Freeze the details of the aspect
freezeProperties(versionNodeRef, nodeDetails.getProperties(aspect)); freezeProperties(versionNodeRef, nodeDetails.getProperties(aspect));
freezeChildAssociations(versionNodeRef, nodeDetails.getChildAssociations(aspect)); freezeChildAssociations(versionNodeRef, nodeDetails.getChildAssociations(aspect));
freezeAssociations(versionNodeRef, nodeDetails.getAssociations(aspect)); freezeAssociations(versionNodeRef, nodeDetails.getAssociations(aspect));
} }
} }
/** /**
* Freeze associations * Freeze associations
* *
* @param versionNodeRef the version node reference * @param versionNodeRef the version node reference
* @param associations the list of associations * @param associations the list of associations
*/ */
private void freezeAssociations(NodeRef versionNodeRef, List<AssociationRef> associations) private void freezeAssociations(NodeRef versionNodeRef, List<AssociationRef> associations)
{ {
for (AssociationRef targetAssoc : associations) for (AssociationRef targetAssoc : associations)
{ {
HashMap<QName, Serializable> properties = new HashMap<QName, Serializable>(); HashMap<QName, Serializable> properties = new HashMap<QName, Serializable>();
@@ -585,24 +591,24 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
// Create child version reference // Create child version reference
this.dbNodeService.createNode( this.dbNodeService.createNode(
versionNodeRef, versionNodeRef,
CHILD_QNAME_VERSIONED_ASSOCS, CHILD_QNAME_VERSIONED_ASSOCS,
CHILD_QNAME_VERSIONED_ASSOCS, CHILD_QNAME_VERSIONED_ASSOCS,
TYPE_QNAME_VERSIONED_ASSOC, TYPE_QNAME_VERSIONED_ASSOC,
properties); properties);
} }
} }
/** /**
* Freeze child associations * Freeze child associations
* *
* @param versionNodeRef the version node reference * @param versionNodeRef the version node reference
* @param childAssociations the child associations * @param childAssociations the child associations
*/ */
private void freezeChildAssociations(NodeRef versionNodeRef, List<ChildAssociationRef> childAssociations) private void freezeChildAssociations(NodeRef versionNodeRef, List<ChildAssociationRef> childAssociations)
{ {
for (ChildAssociationRef childAssocRef : childAssociations) for (ChildAssociationRef childAssocRef : childAssociations)
{ {
HashMap<QName, Serializable> properties = new HashMap<QName, Serializable>(); HashMap<QName, Serializable> properties = new HashMap<QName, Serializable>();
// Set the qname, isPrimary and nthSibling properties // Set the qname, isPrimary and nthSibling properties
properties.put(PROP_QNAME_ASSOC_QNAME, childAssocRef.getQName()); properties.put(PROP_QNAME_ASSOC_QNAME, childAssocRef.getQName());
@@ -616,27 +622,27 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
// Create child version reference // Create child version reference
this.dbNodeService.createNode( this.dbNodeService.createNode(
versionNodeRef, versionNodeRef,
CHILD_QNAME_VERSIONED_CHILD_ASSOCS, CHILD_QNAME_VERSIONED_CHILD_ASSOCS,
CHILD_QNAME_VERSIONED_CHILD_ASSOCS, CHILD_QNAME_VERSIONED_CHILD_ASSOCS,
TYPE_QNAME_VERSIONED_CHILD_ASSOC, TYPE_QNAME_VERSIONED_CHILD_ASSOC,
properties); properties);
} }
} }
/** /**
* Freeze properties * Freeze properties
* *
* @param versionNodeRef the version node reference * @param versionNodeRef the version node reference
* @param properties the properties * @param properties the properties
*/ */
private void freezeProperties(NodeRef versionNodeRef, Map<QName, Serializable> properties) private void freezeProperties(NodeRef versionNodeRef, Map<QName, Serializable> properties)
{ {
// Copy the property values from the node onto the version node // Copy the property values from the node onto the version node
for (Map.Entry<QName, Serializable> entry : properties.entrySet()) for (Map.Entry<QName, Serializable> entry : properties.entrySet())
{ {
// Get the property values // Get the property values
HashMap<QName, Serializable> props = new HashMap<QName, Serializable>(); HashMap<QName, Serializable> props = new HashMap<QName, Serializable>();
props.put(PROP_QNAME_QNAME, entry.getKey()); props.put(PROP_QNAME_QNAME, entry.getKey());
if (entry.getValue() instanceof Collection) if (entry.getValue() instanceof Collection)
{ {
@@ -652,25 +658,25 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
// Create the node storing the frozen attribute details // Create the node storing the frozen attribute details
this.dbNodeService.createNode( this.dbNodeService.createNode(
versionNodeRef, versionNodeRef,
CHILD_QNAME_VERSIONED_ATTRIBUTES, CHILD_QNAME_VERSIONED_ATTRIBUTES,
CHILD_QNAME_VERSIONED_ATTRIBUTES, CHILD_QNAME_VERSIONED_ATTRIBUTES,
TYPE_QNAME_VERSIONED_PROPERTY, TYPE_QNAME_VERSIONED_PROPERTY,
props); props);
} }
} }
/** /**
* Gets the version stores root node * Gets the version stores root node
* *
* @return the node ref to the root node of the version store * @return the node ref to the root node of the version store
*/ */
private NodeRef getRootNode() private NodeRef getRootNode()
{ {
// Get the version store root node reference // Get the version store root node reference
return this.dbNodeService.getRootNode(getVersionStoreReference()); return this.dbNodeService.getRootNode(getVersionStoreReference());
} }
/** /**
* Builds a version history object from the version history reference. * Builds a version history object from the version history reference.
* <p> * <p>
* The node ref is passed to enable the version history to be scoped to the * The node ref is passed to enable the version history to be scoped to the
@@ -694,8 +700,8 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
versionHistoryNodeRefs.add(0, currentVersion); versionHistoryNodeRefs.add(0, currentVersion);
List<AssociationRef> preceedingVersions = this.dbNodeService.getSourceAssocs( List<AssociationRef> preceedingVersions = this.dbNodeService.getSourceAssocs(
currentVersion, currentVersion,
VersionModel.ASSOC_SUCCESSOR); VersionModel.ASSOC_SUCCESSOR);
if (preceedingVersions.size() == 1) if (preceedingVersions.size() == 1)
{ {
preceedingVersion = (AssociationRef)preceedingVersions.toArray()[0]; preceedingVersion = (AssociationRef)preceedingVersions.toArray()[0];
@@ -772,8 +778,8 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
// Create and return the version object // Create and return the version object
NodeRef newNodeRef = new NodeRef(new StoreRef(STORE_PROTOCOL, STORE_ID), versionRef.getId()); NodeRef newNodeRef = new NodeRef(new StoreRef(STORE_PROTOCOL, STORE_ID), versionRef.getId());
Version result = new VersionImpl(versionProperties, newNodeRef); Version result = new VersionImpl(versionProperties, newNodeRef);
// done // done
return result; return result;
} }
/** /**
@@ -820,8 +826,8 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
*/ */
public void revert(NodeRef nodeRef) public void revert(NodeRef nodeRef)
{ {
revert(nodeRef, getCurrentVersion(nodeRef), true); revert(nodeRef, getCurrentVersion(nodeRef), true);
} }
/** /**
* @see org.alfresco.service.cmr.version.VersionService#revert(org.alfresco.service.cmr.repository.NodeRef, boolean) * @see org.alfresco.service.cmr.version.VersionService#revert(org.alfresco.service.cmr.repository.NodeRef, boolean)
@@ -842,11 +848,11 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
/** /**
* @see org.alfresco.service.cmr.version.VersionService#revert(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.version.Version, boolean) * @see org.alfresco.service.cmr.version.VersionService#revert(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.version.Version, boolean)
*/ */
public void revert(NodeRef nodeRef, Version version, boolean deep) public void revert(NodeRef nodeRef, Version version, boolean deep)
{ {
// Check the mandatory parameters // Check the mandatory parameters
ParameterCheck.mandatory("nodeRef", nodeRef); ParameterCheck.mandatory("nodeRef", nodeRef);
ParameterCheck.mandatory("version", version); ParameterCheck.mandatory("version", version);
// Cross check that the version provided relates to the node reference provided // Cross check that the version provided relates to the node reference provided
if (nodeRef.getId().equals(version.getVersionProperty(VersionModel.PROP_FROZEN_NODE_ID)) == false) if (nodeRef.getId().equals(version.getVersionProperty(VersionModel.PROP_FROZEN_NODE_ID)) == false)
@@ -863,30 +869,30 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
String currentVersionLabel = (String)this.nodeService.getProperty(nodeRef, ContentModel.PROP_VERSION_LABEL); String currentVersionLabel = (String)this.nodeService.getProperty(nodeRef, ContentModel.PROP_VERSION_LABEL);
// Get the node that represents the frozen state // Get the node that represents the frozen state
NodeRef versionNodeRef = version.getFrozenStateNodeRef(); NodeRef versionNodeRef = version.getFrozenStateNodeRef();
// Revert the property values // Revert the property values
this.nodeService.setProperties(nodeRef, this.nodeService.getProperties(versionNodeRef)); this.nodeService.setProperties(nodeRef, this.nodeService.getProperties(versionNodeRef));
// Apply/remove the aspects as required // Apply/remove the aspects as required
Set<QName> aspects = new HashSet<QName>(this.nodeService.getAspects(nodeRef)); Set<QName> aspects = new HashSet<QName>(this.nodeService.getAspects(nodeRef));
for (QName versionAspect : this.nodeService.getAspects(versionNodeRef)) for (QName versionAspect : this.nodeService.getAspects(versionNodeRef))
{ {
if (aspects.contains(versionAspect) == false) if (aspects.contains(versionAspect) == false)
{ {
this.nodeService.addAspect(nodeRef, versionAspect, null); this.nodeService.addAspect(nodeRef, versionAspect, null);
} }
else else
{ {
aspects.remove(versionAspect); aspects.remove(versionAspect);
} }
} }
for (QName aspect : aspects) for (QName aspect : aspects)
{ {
this.nodeService.removeAspect(nodeRef, aspect); this.nodeService.removeAspect(nodeRef, aspect);
} }
// Re-add the versionable aspect to the reverted node // Re-add the versionable aspect to the reverted node
if (this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE) == false) if (this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE) == false)
{ {
this.nodeService.addAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE, null); this.nodeService.addAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE, null);
@@ -895,22 +901,22 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
// Re-set the version label property (since it should not be modified from the origional) // Re-set the version label property (since it should not be modified from the origional)
this.nodeService.setProperty(nodeRef, ContentModel.PROP_VERSION_LABEL, currentVersionLabel); this.nodeService.setProperty(nodeRef, ContentModel.PROP_VERSION_LABEL, currentVersionLabel);
// Add/remove the child nodes // Add/remove the child nodes
List<ChildAssociationRef> children = new ArrayList<ChildAssociationRef>(this.nodeService.getChildAssocs(nodeRef)); List<ChildAssociationRef> children = new ArrayList<ChildAssociationRef>(this.nodeService.getChildAssocs(nodeRef));
for (ChildAssociationRef versionedChild : this.nodeService.getChildAssocs(versionNodeRef)) for (ChildAssociationRef versionedChild : this.nodeService.getChildAssocs(versionNodeRef))
{ {
if (children.contains(versionedChild) == false) if (children.contains(versionedChild) == false)
{ {
if (this.nodeService.exists(versionedChild.getChildRef()) == true) if (this.nodeService.exists(versionedChild.getChildRef()) == true)
{ {
// The node was a primary child of the parent, but that is no longer the case. Dispite this // The node was a primary child of the parent, but that is no longer the case. Dispite this
// the node still exits so this means it has been moved. // the node still exits so this means it has been moved.
// The best thing to do in this situation will be to re-add the node as a child, but it will not // The best thing to do in this situation will be to re-add the node as a child, but it will not
// be a primary child. // be a primary child.
this.nodeService.addChild(nodeRef, versionedChild.getChildRef(), versionedChild.getTypeQName(), versionedChild.getQName()); this.nodeService.addChild(nodeRef, versionedChild.getChildRef(), versionedChild.getTypeQName(), versionedChild.getQName());
} }
else else
{ {
if (versionedChild.isPrimary() == true) if (versionedChild.isPrimary() == true)
{ {
// Only try to resotre missing children if we are doing a deep revert // Only try to resotre missing children if we are doing a deep revert
@@ -931,40 +937,40 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
// else // else
// Since this was never a primary assoc and the child has been deleted we won't recreate // Since this was never a primary assoc and the child has been deleted we won't recreate
// the missing node as it was never owned by the node and we wouldn't know where to put it. // the missing node as it was never owned by the node and we wouldn't know where to put it.
} }
} }
else else
{ {
children.remove(versionedChild); children.remove(versionedChild);
} }
} }
for (ChildAssociationRef ref : children) for (ChildAssociationRef ref : children)
{ {
this.nodeService.removeChild(nodeRef, ref.getChildRef()); this.nodeService.removeChild(nodeRef, ref.getChildRef());
} }
// Add/remove the target associations // Add/remove the target associations
for (AssociationRef assocRef : this.nodeService.getTargetAssocs(nodeRef, RegexQNamePattern.MATCH_ALL)) for (AssociationRef assocRef : this.nodeService.getTargetAssocs(nodeRef, RegexQNamePattern.MATCH_ALL))
{ {
this.nodeService.removeAssociation(assocRef.getSourceRef(), assocRef.getTargetRef(), assocRef.getTypeQName()); this.nodeService.removeAssociation(assocRef.getSourceRef(), assocRef.getTargetRef(), assocRef.getTypeQName());
} }
for (AssociationRef versionedAssoc : this.nodeService.getTargetAssocs(versionNodeRef, RegexQNamePattern.MATCH_ALL)) for (AssociationRef versionedAssoc : this.nodeService.getTargetAssocs(versionNodeRef, RegexQNamePattern.MATCH_ALL))
{ {
if (this.nodeService.exists(versionedAssoc.getTargetRef()) == true) if (this.nodeService.exists(versionedAssoc.getTargetRef()) == true)
{ {
this.nodeService.createAssociation(nodeRef, versionedAssoc.getTargetRef(), versionedAssoc.getTypeQName()); this.nodeService.createAssociation(nodeRef, versionedAssoc.getTargetRef(), versionedAssoc.getTypeQName());
} }
// else // else
// Since the tareget of the assoc no longer exists we can't recreate the assoc // Since the tareget of the assoc no longer exists we can't recreate the assoc
} }
} }
finally finally
{ {
// Turn auto-version policies back on // Turn auto-version policies back on
this.policyBehaviourFilter.enableBehaviour(nodeRef, ContentModel.ASPECT_VERSIONABLE); this.policyBehaviourFilter.enableBehaviour(nodeRef, ContentModel.ASPECT_VERSIONABLE);
} }
} }
/** /**
* @see org.alfresco.service.cmr.version.VersionService#restore(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, org.alfresco.service.namespace.QName) * @see org.alfresco.service.cmr.version.VersionService#restore(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, org.alfresco.service.namespace.QName)
@@ -1075,25 +1081,25 @@ public class VersionServiceImpl extends AbstractVersionServiceImpl
return version; return version;
} }
/** /**
* @see org.alfresco.cms.version.VersionService#deleteVersionHistory(NodeRef) * @see org.alfresco.cms.version.VersionService#deleteVersionHistory(NodeRef)
*/ */
public void deleteVersionHistory(NodeRef nodeRef) public void deleteVersionHistory(NodeRef nodeRef)
throws AspectMissingException throws AspectMissingException
{ {
// Get the version history node for the node is question and delete it // Get the version history node for the node is question and delete it
NodeRef versionHistoryNodeRef = getVersionHistoryNodeRef(nodeRef); NodeRef versionHistoryNodeRef = getVersionHistoryNodeRef(nodeRef);
if (versionHistoryNodeRef != null) if (versionHistoryNodeRef != null)
{ {
// Delete the version history node // Delete the version history node
this.dbNodeService.deleteNode(versionHistoryNodeRef); this.dbNodeService.deleteNode(versionHistoryNodeRef);
if (this.nodeService.exists(nodeRef) == true && this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE) == true) if (this.nodeService.exists(nodeRef) == true && this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE) == true)
{ {
// Reset the version label property on the versionable node // Reset the version label property on the versionable node
this.nodeService.setProperty(nodeRef, ContentModel.PROP_VERSION_LABEL, null); this.nodeService.setProperty(nodeRef, ContentModel.PROP_VERSION_LABEL, null);
} }
} }
} }
} }

View File

@@ -27,6 +27,8 @@ package org.alfresco.repo.version.common;
import java.util.Collection; import java.util.Collection;
import org.alfresco.repo.version.VersionModel; import org.alfresco.repo.version.VersionModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.version.ReservedVersionNameException; import org.alfresco.service.cmr.version.ReservedVersionNameException;
/** /**
@@ -68,4 +70,16 @@ public class VersionUtil
} }
} }
} }
/**
* Convert the incomming node ref (with the version store protocol specified)
* to the internal representation with the workspace protocol.
*
* @param nodeRef the incomming verison protocol node reference
* @return the internal version node reference
*/
public static NodeRef convertNodeRef(NodeRef nodeRef)
{
return new NodeRef(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, VersionModel.STORE_ID), nodeRef.getId());
}
} }

View File

@@ -35,7 +35,7 @@ import org.alfresco.service.PublicService;
/** /**
* This service interface provides support for content filter languages . * This service interface provides support for content filter languages .
* *
* @author yanipig * @author Yannick Pignot
* *
*/ */
@PublicService @PublicService

View File

@@ -0,0 +1,95 @@
/*
* 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.service.cmr.ml;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.alfresco.service.Auditable;
import org.alfresco.service.PublicService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionHistory;
import org.alfresco.service.namespace.QName;
/**
* The API to manage editions of a mlContainer. An edition is a version of a <b>mlContainer</b>
*
* @since 2.1
* @author Yannick Pignot
*/
@PublicService
public interface EditionService
{
/**
* Create a new edition of an existing <b>cm:mlContainer</b> using any one of the
* associated <b>cm:mlDocument</b> transalations.
*
* If startingTranslationNodeRef is multilingual, it will be copied. The copy will become the pivot translation
* of the new Edition of the <b>cm:mlContainer</b>. The reference of the copy will be returned.
*
* @param translationNodeRef The specific <b>cm:mlDocument</b> to use as the starting point
* of the new edition. All other translations will be removed.
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {"translationNodeRef", "versionProperties"})
NodeRef createEdition(NodeRef translationNodeRef, Map<String, Serializable> versionProperties);
/**
* Get editions of an existing <b>cm:mlContainer</b>.
*
* @param mlContainer An existing <b>cm:mlContainer</b>
* @return The Version History of the mlContainer
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {"mlContainer"})
VersionHistory getEditions(NodeRef mlContainer);
/**
* Get the different <b>cm:mlDocument</b> transalation version histories of a specific edition of a <b>cm:mlContainer</b>
*
* @param mlContainerEdition An existing version of a mlContainer
* @return The list of <b>cm:mlDocument</b> transalation versions of the edition
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {"mlContainerEdition"})
List<VersionHistory> getVersionedTranslations(Version mlContainerEdition);
/**
* Get the the versioned metadata of a specific <b>cm:mlDocument</b> transalation version or a specific
* <b>cm:mlContainer</b> version
*
* @see org.alfresco.repo.model.ml.MultilingualDocumentAspect.PROPERTIES_TO_VERSION the versioned metadata
* of a <b>cm:mlDocument</b> transalation added to the usual metadata versioned for a normal node.
*
* @see org.alfresco.repo.model.ml.MLContainerType.PROPERTIES_TO_VERSION the versioned metadata
* of a <b>cm:mlContainer</b> added to the usual metadata versioned for a normal node.
*
* @param version An existing version of a <b>cm:mlDocument</b> translation version or
* an existing version of a <b>cm:mlContainer</b> version.
* @return The versioned metadata
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {"version"})
Map<QName, Serializable> getVersionedMetadatas(Version version);
}

View File

@@ -90,16 +90,6 @@ public interface MultilingualContentService
@Auditable(key = Auditable.Key.ARG_0, parameters = {"translationNodeRef"}) @Auditable(key = Auditable.Key.ARG_0, parameters = {"translationNodeRef"})
NodeRef getTranslationContainer(NodeRef translationNodeRef); NodeRef getTranslationContainer(NodeRef translationNodeRef);
/**
* Create a new edition of an existing <b>cm:mlContainer</b> using any one of the
* associated <b>cm:mlDocument</b> transalations.
*
* @param translationNodeRef The specific <b>cm:mlDocument</b> to use as the starting point
* of the new edition. All other translations will be removed.
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {"translationNodeRef"})
void createEdition(NodeRef translationNodeRef);
/** /**
* Gets the set of sibling translations associated with the given <b>cm:mlDocument</b> or * Gets the set of sibling translations associated with the given <b>cm:mlDocument</b> or
* <b>cm:mlContainer</b>. * <b>cm:mlContainer</b>.
@@ -172,4 +162,32 @@ public interface MultilingualContentService
*/ */
@Auditable(key = Auditable.Key.ARG_0, parameters = {"translationOfNodeRef", "name", "locale"}) @Auditable(key = Auditable.Key.ARG_0, parameters = {"translationOfNodeRef", "name", "locale"})
NodeRef addEmptyTranslation(NodeRef translationOfNodeRef, String name, Locale locale); NodeRef addEmptyTranslation(NodeRef translationOfNodeRef, String name, Locale locale);
/**
* Copies the given <b>cm:mlContainer</b>.
* <p>
* This involves the copy of the <b>cm:mlContainer</b> node and the copy of its <b>cm:mlDocument</b>.
* <p>
*
* @param translationNodeRef The <b>cm:mlContainer</b> to copy
* @param newParentRef The new parent of the copied <b>cm:mlDocument</b>
* @return The copied <b>cm:mlContainer</b>
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {"translationNodeRef", "newParentRef"})
NodeRef copyTranslationContainer(NodeRef translationNodeRef, NodeRef newParentRef);
/**
* Moves the location of the given <b>cm:mlContainer</b>.
* <p>
* This not involves changing the <b>cm:mlContainer</b> node but moves its <b>cm:mlDocument</b>.
* <p>
*
* @param translationNodeRef The <b>cm:mlContainer</b> to move
* @param newParentRef The new parent of the moved <b>cm:mlDocument</b>
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {"translationNodeRef", "newParentRef"})
void moveTranslationContainer(NodeRef translationNodeRef, NodeRef newParentRef);
} }