Checkpoint of MultilingualContentService

- New patch for multilingual root for holding containers


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@4730 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2007-01-04 17:14:51 +00:00
parent 7e4430cae9
commit 96653f2420
12 changed files with 504 additions and 29 deletions

View File

@@ -119,6 +119,10 @@
<prop key="path">/</prop> <prop key="path">/</prop>
<prop key="location">alfresco/bootstrap/categories.xml</prop> <prop key="location">alfresco/bootstrap/categories.xml</prop>
</props> </props>
<props>
<prop key="path">/</prop>
<prop key="location">alfresco/bootstrap/multilingualRoot.xml</prop>
</props>
<props> <props>
<prop key="path">/${spaces.company_home.childname}/${spaces.guest_home.childname}</prop> <prop key="path">/${spaces.company_home.childname}/${spaces.guest_home.childname}</prop>
<prop key="location">alfresco/bootstrap/tutorial.xml</prop> <prop key="location">alfresco/bootstrap/tutorial.xml</prop>

View File

@@ -0,0 +1,15 @@
<view:view xmlns:view="http://www.alfresco.org/view/repository/1.0"
xmlns:cm="http://www.alfresco.org/model/content/1.0"
xmlns:sys="http://www.alfresco.org/model/system/1.0"
xmlns:app="http://www.alfresco.org/model/application/1.0">
<cm:mlRoot view:childName="cm:multilingualRoot">
<view:acl view:inherit="false">
<view:ace view:access="ALLOWED">
<view:authority>GROUP_EVERYONE</view:authority>
<view:permission>Consumer</view:permission>
</view:ace>
</view:acl>
</cm:mlRoot>
</view:view>

View File

@@ -109,3 +109,5 @@ patch.systemDescriptorContent.description=Adds the version properties content to
patch.systemDescriptorContent.result=Added the version properties content to the system descriptor. patch.systemDescriptorContent.result=Added the version properties content to the system descriptor.
patch.systemDescriptorContent.err.no_version_properties=The version.properties resource could not be found. patch.systemDescriptorContent.err.no_version_properties=The version.properties resource could not be found.
patch.systemDescriptorContent.err.no_descriptor=The system descriptor could not be found. patch.systemDescriptorContent.err.no_descriptor=The system descriptor could not be found.
patch.multilingualBootstrap.description=Bootstraps the node that will hold the multilingual containers.

View File

@@ -3,6 +3,8 @@
<beans> <beans>
<!-- File/folder specific service -->
<bean name="fileFolderService" class="org.alfresco.repo.model.filefolder.FileFolderServiceImpl" init-method="init"> <bean name="fileFolderService" class="org.alfresco.repo.model.filefolder.FileFolderServiceImpl" init-method="init">
<property name="namespaceService"><ref bean="namespaceService" /></property> <property name="namespaceService"><ref bean="namespaceService" /></property>
<property name="dictionaryService"><ref bean="dictionaryService" /></property> <property name="dictionaryService"><ref bean="dictionaryService" /></property>
@@ -38,4 +40,10 @@
</property> </property>
</bean> </bean>
<!-- Multilingual specific service -->
<bean name="multilingualContentService" class="org.alfresco.repo.model.ml.MultilingualContentServiceImpl" >
<property name="nodeService"><ref bean="NodeService" /></property>
<property name="searchService"><ref bean="SearchService" /></property>
</bean>
</beans> </beans>

View File

@@ -218,15 +218,27 @@
</type> </type>
<!-- Multilingual --> <!-- Multilingual -->
<type name="cm:mlRoot">
<title>Multilingual Root</title>
<parent>sys:container</parent>
<associations>
<child-association name="cm:mlContainer">
<source>
<mandatory>false</mandatory>
<many>false</many>
</source>
<target>
<class>cm:mlContainer</class>
<mandatory>false</mandatory>
<many>true</many>
</target>
</child-association>
</associations>
</type>
<type name="cm:mlContainer"> <type name="cm:mlContainer">
<title>Multilingual Container</title> <title>Multilingual Container</title>
<parent>sys:base</parent> <parent>sys:container</parent>
<properties>
<property name="cm:mlEditionLabel">
<title>Edition Label</title>
<type>d:text</type>
</property>
</properties>
<associations> <associations>
<child-association name="cm:mlChild"> <child-association name="cm:mlChild">
<source> <source>
@@ -234,12 +246,15 @@
<many>false</many> <many>false</many>
</source> </source>
<target> <target>
<class>sys:localized</class> <class>cm:mlDocument</class>
<mandatory>true</mandatory> <mandatory>true</mandatory>
<many>true</many> <many>true</many>
</target> </target>
</child-association> </child-association>
</associations> </associations>
<mandatory-aspects>
<aspect>cm:versionable</aspect>
</mandatory-aspects>
</type> </type>
</types> </types>
@@ -694,6 +709,14 @@
</properties> </properties>
</aspect> </aspect>
<aspect name="cm:mlDocument">
<title>Multilingual Document</title>
<mandatory-aspects>
<aspect>sys:localized</aspect>
<aspect>cm:versionable</aspect>
</mandatory-aspects>
</aspect>
</aspects> </aspects>
</model> </model>

View File

@@ -517,5 +517,25 @@
<ref bean="contentService" /> <ref bean="contentService" />
</property> </property>
</bean> </bean>
<bean id="patch.multilingualBootstrap" class="org.alfresco.repo.admin.patch.impl.GenericBootstrapPatch" parent="basePatch" >
<property name="id"><value>patch.multilingualBootstrap</value></property>
<property name="description"><value>patch.multilingualBootstrap.description</value></property>
<property name="fixesFromSchema"><value>0</value></property>
<property name="fixesToSchema"><value>29</value></property>
<property name="targetSchema"><value>30</value></property>
<!-- bootstrap view -->
<property name="importerBootstrap">
<ref bean="spacesBootstrap" />
</property>
<property name="checkPath">
<value>/cm:multilingualRoot</value>
</property>
<property name="bootstrapView">
<props>
<prop key="path">/</prop>
<prop key="location">alfresco/bootstrap/multilingualRoot.xml</prop>
</props>
</property>
</bean>
</beans> </beans>

View File

@@ -1222,4 +1222,43 @@
</property> </property>
</bean> </bean>
<!-- MultilingualContentService -->
<bean id="MultilingualContentService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.ml.MultilingualContentService</value>
</property>
<property name="target">
<ref bean="multilingualContentService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="MultilingualContentService_transaction"/>
<idref local="exceptionTranslator"/>
<idref local="MultilingualContentService_descriptor"/>
</list>
</property>
</bean>
<bean id="MultilingualContentService_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>
<bean id="MultilingualContentService_descriptor" parent="AlfrescoServiceDescriptor">
<property name="interface">
<value>org.alfresco.service.cmr.ml.MultilingualContentService</value>
</property>
<property name="description">
<value>Multilingual Content Service</value>
</property>
</bean>
</beans> </beans>

View File

@@ -19,4 +19,4 @@ version.build=@build-number@
# Schema number # Schema number
version.schema=23 version.schema=30

View File

@@ -43,7 +43,7 @@ public interface ContentModel
// tag for temporary nodes // tag for temporary nodes
static final QName ASPECT_TEMPORARY = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "temporary"); static final QName ASPECT_TEMPORARY = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "temporary");
// tag for temporary nodes // tag for localized nodes
static final QName ASPECT_LOCALIZED = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "localized"); static final QName ASPECT_LOCALIZED = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "localized");
static final QName PROP_LOCALE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "locale"); static final QName PROP_LOCALE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "locale");
@@ -200,6 +200,10 @@ public interface ContentModel
static final QName ASPECT_REFERENCES_NODE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "referencesnode"); static final QName ASPECT_REFERENCES_NODE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "referencesnode");
static final QName PROP_NODE_REF = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "noderef"); static final QName PROP_NODE_REF = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "noderef");
// Multilingual Type
static final QName TYPE_MULTILINGUAL_CONTAINER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlContainer");
static final QName ASSOC_MULTILINGUAL_CHILD = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlChild");
static final QName ASPECT_MULTILINGUAL_DOCUMENT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlDocument");
// //
// User Model Definitions // User Model Definitions

View File

@@ -0,0 +1,226 @@
/*
* Copyright (C) 2007 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.model.ml;
import java.util.List;
import java.util.Locale;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.ml.MultilingualContentService;
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.repository.StoreRef;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.util.PropertyMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Multilingual support implementation
*
* @author Derek Hulley
*/
public class MultilingualContentServiceImpl implements MultilingualContentService
{
private static Log logger = LogFactory.getLog(MultilingualContentServiceImpl.class);
private NodeService nodeService;
private SearchService searchService;
private VersionService versionService;
private SearchParameters searchParametersMLRoot;
public MultilingualContentServiceImpl()
{
searchParametersMLRoot = new SearchParameters();
searchParametersMLRoot.setLanguage(SearchService.LANGUAGE_XPATH);
searchParametersMLRoot.setLimit(1);
searchParametersMLRoot.addStore(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore"));
searchParametersMLRoot.setQuery("/cm:multilingualRoot");
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setSearchService(SearchService searchService)
{
this.searchService = searchService;
}
public void setVersionService(VersionService versionService)
{
this.versionService = versionService;
}
public void renameWithMLExtension(NodeRef translationNodeRef)
{
throw new UnsupportedOperationException();
}
/**
* @return Returns a reference to the node that will hold all the <b>cm:mlContainer</b> nodes.
*/
private NodeRef getMLContainerRoot()
{
ResultSet rs = searchService.query(searchParametersMLRoot);
try
{
if (rs.length() > 0)
{
NodeRef mlRootNodeRef = rs.getNodeRef(0);
// done
return mlRootNodeRef;
}
else
{
throw new AlfrescoRuntimeException(
"Unable to find bootstrap location for ML Root using query: " + searchParametersMLRoot.getQuery());
}
}
finally
{
rs.close();
}
}
private static final QName QNAME_ML_CONTAINER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlContainer");
private static final QName QNAME_ML_TRANSLATION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlTranslation");
/**
* @return Returns a new <b>cm:mlContainer</b>
*/
private NodeRef makeMLContainer()
{
NodeRef mlContainerRootNodeRef = getMLContainerRoot();
// Create the container
ChildAssociationRef assocRef = nodeService.createNode(
mlContainerRootNodeRef,
ContentModel.ASSOC_CHILDREN,
QNAME_ML_CONTAINER,
ContentModel.TYPE_MULTILINGUAL_CONTAINER);
// done
return assocRef.getChildRef();
}
/**
* Retrieve or create a <b>cm:mlDocument</b> container for the given node, which must have the
* <b>cm:mlDocument</b> already applied.
*
* @param mlDocumentNodeRef an existing <b>cm:mlDocument</b>
* @return Returns the <b>cm:mlContainer</b> parent
*/
private NodeRef getOrCreateMLContainer(NodeRef mlDocumentNodeRef)
{
if (!nodeService.hasAspect(mlDocumentNodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
{
throw new IllegalArgumentException(
"Node must have aspect " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT + " applied");
}
// Now check if a parent mlContainer exists
NodeRef mlContainerNodeRef = null;
boolean createAssociation = false;
List<ChildAssociationRef> parentAssocRefs = nodeService.getParentAssocs(
mlDocumentNodeRef,
ContentModel.ASSOC_MULTILINGUAL_CHILD,
RegexQNamePattern.MATCH_ALL);
if (parentAssocRefs.size() == 0)
{
// Create a ML container
mlContainerNodeRef = makeMLContainer();
createAssociation = true;
}
else if (parentAssocRefs.size() == 1)
{
// Just get it
ChildAssociationRef toKeepAssocRef = parentAssocRefs.get(0);
mlContainerNodeRef = toKeepAssocRef.getParentRef();
createAssociation = true;
}
else if (parentAssocRefs.size() > 1)
{
// This is a problem - destroy all but the first
logger.warn("Cleaning up multiple multilingual containers on node: " + mlDocumentNodeRef);
ChildAssociationRef toKeepAssocRef = parentAssocRefs.get(0);
mlContainerNodeRef = toKeepAssocRef.getParentRef();
// Remove all the associations to the container
boolean first = true;
for (ChildAssociationRef assocRef : parentAssocRefs)
{
if (first)
{
first = false;
continue;
}
nodeService.removeChildAssociation(assocRef);
}
}
// Associate the translation with the container
if (createAssociation)
{
nodeService.addChild(
mlContainerNodeRef,
mlDocumentNodeRef,
ContentModel.ASSOC_MULTILINGUAL_CHILD,
QNAME_ML_TRANSLATION);
}
// done
return mlContainerNodeRef;
}
public NodeRef makeTranslation(NodeRef contentNodeRef, Locale locale)
{
// Add the aspect using the given locale, of necessary
if (!nodeService.hasAspect(contentNodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
{
PropertyMap properties = new PropertyMap();
properties.put(ContentModel.PROP_LOCALE, locale);
nodeService.addAspect(contentNodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT, properties);
}
else
{
// The aspect is present, so just ensure that the locale is correct
nodeService.setProperty(contentNodeRef, ContentModel.PROP_LOCALE, locale);
}
// Get or create the container
NodeRef mlContainerNodeRef = getOrCreateMLContainer(contentNodeRef);
// done
return mlContainerNodeRef;
}
public NodeRef addTranslation(NodeRef newTranslationNodeRef, NodeRef translationOfNodeRef, Locale locale)
{
throw new UnsupportedOperationException();
}
public NodeRef getTranslationContainer(NodeRef translationNodeRef)
{
throw new UnsupportedOperationException();
}
public NodeRef createEdition(NodeRef mlContainerNodeRef, NodeRef translationNodeRef)
{
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright (C) 2007 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.model.ml;
import java.util.Locale;
import junit.framework.TestCase;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.transaction.TransactionUtil;
import org.alfresco.repo.transaction.TransactionUtil.TransactionWork;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.ml.MultilingualContentService;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper;
import org.springframework.context.ApplicationContext;
/**
* @see org.alfresco.repo.ml.MultilingualContentServiceImpl
*
* @author Derek Hulley
*/
public class MultilingualContentServiceImplTest extends TestCase
{
private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
private ServiceRegistry serviceRegistry;
private AuthenticationComponent authenticationComponent;
private TransactionService transactionService;
private NodeService nodeService;
private FileFolderService fileFolderService;
private MultilingualContentService multilingualContentService;
private NodeRef folderNodeRef;
@Override
protected void setUp() throws Exception
{
serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
authenticationComponent = (AuthenticationComponent) ctx.getBean("AuthenticationComponent");
transactionService = serviceRegistry.getTransactionService();
nodeService = serviceRegistry.getNodeService();
fileFolderService = serviceRegistry.getFileFolderService();
multilingualContentService = (MultilingualContentService) ctx.getBean("MultilingualContentService");
// Run as admin
authenticationComponent.setCurrentUser("admin");
// Create a folder to work in
TransactionWork<NodeRef> createFolderWork = new TransactionWork<NodeRef>()
{
public NodeRef doWork() throws Exception
{
StoreRef storeRef = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore");
NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
// Create the folder
NodeRef folderNodeRef = nodeService.createNode(
rootNodeRef,
ContentModel.ASSOC_CHILDREN,
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "testFolder"),
ContentModel.TYPE_FOLDER).getChildRef();
// done
return folderNodeRef;
}
};
folderNodeRef = TransactionUtil.executeInUserTransaction(transactionService, createFolderWork);
}
@Override
protected void tearDown() throws Exception
{
// Clear authentication
try
{
authenticationComponent.clearCurrentSecurityContext();
}
catch (Throwable e)
{
e.printStackTrace();
}
}
private NodeRef createContent()
{
NodeRef contentNodeRef = fileFolderService.create(
folderNodeRef,
"" + System.currentTimeMillis(),
ContentModel.TYPE_CONTENT).getNodeRef();
// add some content
ContentWriter contentWriter = fileFolderService.getWriter(contentNodeRef);
contentWriter.putContent("ABC");
// done
return contentNodeRef;
}
public void testSetup() throws Exception
{
// Ensure that content can be created
createContent();
}
public void testMakeTranslation() throws Exception
{
NodeRef contentNodeRef = createContent();
// Turn the content into a translation with the appropriate structures
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(contentNodeRef, Locale.CHINESE);
// Check it
assertNotNull("Container not created", mlContainerNodeRef);
}
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2006 Alfresco, Inc. * Copyright (C) 2007 Alfresco, Inc.
* *
* Licensed under the Mozilla Public License version 1.1 * Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a * with a permitted attribution clause. You may obtain a
@@ -31,30 +31,33 @@ import org.alfresco.service.cmr.repository.NodeRef;
public interface MultilingualContentService public interface MultilingualContentService
{ {
/** /**
* Rename an existing <b>cm:translation</b> by adding locale suffixes to the base name. * Rename an existing <b>sys:localized</b> by adding locale suffixes to the base name.
* Where there are name clashes with existing documents, a numerical naming scheme will be * Where there are name clashes with existing documents, a numerical naming scheme will be
* adopted. * adopted.
* *
* @param translationNodeRef An existing <b>cm:translation</b> * @param localizedNodeRef An existing <b>sys:localized</b>
*/ */
@Auditable(key = Auditable.Key.ARG_0, parameters = {"translationNodeRef"}) @Auditable(key = Auditable.Key.ARG_0, parameters = {"localizedNodeRef"})
void renameWithMLExtension(NodeRef translationNodeRef); void renameWithMLExtension(NodeRef localizedNodeRef);
/** /**
* Make an existing document translatable. If it is already translatable, then nothing is done. * Make an existing document into a translation by adding the <b>cm:mlDocument</b> aspect and
* creating a <b>cm:mlContainer</b> parent. If it is already a translation, then nothing is done.
* *
* @param contentNodeRef An existing <b>cm:content</b> * @param contentNodeRef An existing <b>cm:content</b>
* @return Returns the <b>cm:mlContainer</b> translation parent * @return Returns the <b>cm:mlContainer</b> translation parent
*
* @see org.alfresco.model.ContentModel#ASPECT_MULTILINGUAL_DOCUMENT
*/ */
@Auditable(key = Auditable.Key.ARG_0, parameters = {"contentNodeRef", "locale"}) @Auditable(key = Auditable.Key.ARG_0, parameters = {"contentNodeRef", "locale"})
NodeRef makeTranslatable(NodeRef contentNodeRef, Locale locale); NodeRef makeTranslation(NodeRef contentNodeRef, Locale locale);
/** /**
* Make a translation out of an existing document. The necessary translation structures will be created * Make a translation out of an existing document. The necessary translation structures will be created
* as necessary. * as necessary.
* *
* @param newTranslationNodeRef An existing <b>cm:content</b> * @param newTranslationNodeRef An existing <b>cm:content</b>
* @param translationOfNodeRef An existing <b>cm:translation</b> or <b>cm:mlContainer</b> * @param translationOfNodeRef An existing <b>cm:mlDocument</b> or <b>cm:mlContainer</b>
* @return Returns the <b>cm:mlContainer</b> translation parent * @return Returns the <b>cm:mlContainer</b> translation parent
*/ */
@Auditable(key = Auditable.Key.ARG_0, parameters = {"newTranslationNodeRef", "translationOfNodeRef", "locale"}) @Auditable(key = Auditable.Key.ARG_0, parameters = {"newTranslationNodeRef", "translationOfNodeRef", "locale"})
@@ -71,7 +74,7 @@ public interface MultilingualContentService
* Create a new edition of an existing <b>cm:mlContainer</b>. * Create a new edition of an existing <b>cm:mlContainer</b>.
* *
* @param mlContainerNodeRef An existing <b>cm:mlContainer</b> * @param mlContainerNodeRef An existing <b>cm:mlContainer</b>
* @param translationNodeRef The specific <b>cm:translation</b> to use as the starting point * @param translationNodeRef The specific <b>cm:mlDocument</b> to use as the starting point
* of the new edition. * of the new edition.
* @return Returns the <b>cm:mlContainer</b> * @return Returns the <b>cm:mlContainer</b>
*/ */