mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Phase one of merge of EC multilingual work
These files are their changes plus adjustments for formatting and immediate clashes I anticipate that this will break the build, but there are too many changes coming to risk it. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5740 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -101,7 +101,7 @@ public interface ContentModel
|
||||
// copy aspect constants
|
||||
static final QName ASPECT_COPIEDFROM = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "copiedfrom");
|
||||
static final QName PROP_COPY_REFERENCE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "source");
|
||||
|
||||
|
||||
// working copy aspect contants
|
||||
static final QName ASPECT_WORKING_COPY = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "workingcopy");
|
||||
static final QName PROP_WORKING_COPY_OWNER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "workingCopyOwner");
|
||||
@@ -142,7 +142,7 @@ public interface ContentModel
|
||||
public final static QName PROP_LOCK_OWNER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "lockOwner");
|
||||
public final static QName PROP_LOCK_TYPE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "lockType");
|
||||
public final static QName PROP_EXPIRY_DATE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "expiryDate");
|
||||
|
||||
|
||||
// version aspect
|
||||
static final QName ASPECT_VERSIONABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "versionable");
|
||||
static final QName PROP_VERSION_LABEL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "versionLabel");
|
||||
@@ -212,6 +212,7 @@ public interface ContentModel
|
||||
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");
|
||||
static final QName ASPECT_MULTILINGUAL_EMPTY_TRANSLATION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlEmptyTranslation");
|
||||
|
||||
//
|
||||
// User Model Definitions
|
||||
|
@@ -27,10 +27,13 @@ package org.alfresco.repo.content;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.avm.AVMNodeConverter;
|
||||
import org.alfresco.repo.content.ContentServicePolicies.OnContentReadPolicy;
|
||||
import org.alfresco.repo.content.ContentServicePolicies.OnContentUpdatePolicy;
|
||||
@@ -47,6 +50,7 @@ import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.InvalidTypeException;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.ContentIOException;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
@@ -59,6 +63,7 @@ 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.namespace.RegexQNamePattern;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.EqualsHelper;
|
||||
import org.alfresco.util.Pair;
|
||||
@@ -143,9 +148,9 @@ public class RoutingContentService implements ContentService
|
||||
}
|
||||
|
||||
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||
{
|
||||
this.policyComponent = policyComponent;
|
||||
}
|
||||
{
|
||||
this.policyComponent = policyComponent;
|
||||
}
|
||||
|
||||
public void setAvmService(AVMService service)
|
||||
{
|
||||
@@ -162,23 +167,23 @@ public class RoutingContentService implements ContentService
|
||||
*/
|
||||
public void init()
|
||||
{
|
||||
// Bind on update properties behaviour
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"),
|
||||
this,
|
||||
new JavaBehaviour(this, "onUpdateProperties"));
|
||||
|
||||
// Register on content update policy
|
||||
this.onContentUpdateDelegate = this.policyComponent.registerClassPolicy(OnContentUpdatePolicy.class);
|
||||
// Bind on update properties behaviour
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"),
|
||||
this,
|
||||
new JavaBehaviour(this, "onUpdateProperties"));
|
||||
|
||||
// Register on content update policy
|
||||
this.onContentUpdateDelegate = this.policyComponent.registerClassPolicy(OnContentUpdatePolicy.class);
|
||||
this.onContentReadDelegate = this.policyComponent.registerClassPolicy(OnContentReadPolicy.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update properties policy behaviour
|
||||
*
|
||||
* @param nodeRef the node reference
|
||||
* @param before the before values of the properties
|
||||
* @param after the after values of the properties
|
||||
* @param nodeRef the node reference
|
||||
* @param before the before values of the properties
|
||||
* @param after the after values of the properties
|
||||
*/
|
||||
public void onUpdateProperties(
|
||||
NodeRef nodeRef,
|
||||
@@ -274,7 +279,7 @@ public class RoutingContentService implements ContentService
|
||||
}
|
||||
|
||||
private ContentReader getReader(NodeRef nodeRef, QName propertyQName, boolean fireContentReadPolicy)
|
||||
{
|
||||
{
|
||||
ContentData contentData = null;
|
||||
Serializable propValue = nodeService.getProperty(nodeRef, propertyQName);
|
||||
if (propValue instanceof Collection)
|
||||
@@ -293,8 +298,9 @@ public class RoutingContentService implements ContentService
|
||||
|
||||
if (contentData == null)
|
||||
{
|
||||
// if no value or a value other content, and a property definition has been provided, ensure that it's CONTENT or ANY
|
||||
PropertyDefinition contentPropDef = dictionaryService.getProperty(propertyQName);
|
||||
|
||||
// if no value or a value other content, and a property definition has been provided, ensure that it's CONTENT or ANY
|
||||
if (contentPropDef != null &&
|
||||
(!(contentPropDef.getDataType().getName().equals(DataTypeDefinition.CONTENT) ||
|
||||
contentPropDef.getDataType().getName().equals(DataTypeDefinition.ANY))))
|
||||
@@ -310,8 +316,66 @@ public class RoutingContentService implements ContentService
|
||||
// check that the URL is available
|
||||
if (contentData == null || contentData.getContentUrl() == null)
|
||||
{
|
||||
// there is no URL - the interface specifies that this is not an error condition
|
||||
return null;
|
||||
// if the node is an empty translation, the reader must be the reader of its pivot translation
|
||||
if(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT)
|
||||
&& nodeService.hasAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
|
||||
{
|
||||
// NOTE : don't use the MultilingualContentService here because :
|
||||
// A valid SecureContext can't be provided in the RequestContext
|
||||
|
||||
List<ChildAssociationRef> parentAssocRefs = nodeService.getParentAssocs(
|
||||
nodeRef,
|
||||
ContentModel.ASSOC_MULTILINGUAL_CHILD,
|
||||
RegexQNamePattern.MATCH_ALL);
|
||||
|
||||
if (parentAssocRefs.size() == 1)
|
||||
{
|
||||
// Get the ml container and its locale
|
||||
NodeRef container = parentAssocRefs.get(0).getParentRef();
|
||||
Locale containerLocale = (Locale) nodeService.getProperty(container, ContentModel.PROP_LOCALE);
|
||||
|
||||
// Get each translation
|
||||
List<ChildAssociationRef> assocRefs = nodeService.getChildAssocs(
|
||||
container,
|
||||
ContentModel.ASSOC_MULTILINGUAL_CHILD,
|
||||
RegexQNamePattern.MATCH_ALL);
|
||||
|
||||
|
||||
// found the pivot translation
|
||||
NodeRef pivot = null;
|
||||
|
||||
for(ChildAssociationRef assoc : assocRefs)
|
||||
{
|
||||
pivot = assoc.getChildRef();
|
||||
Locale pivotLocale = (Locale) nodeService.getProperty(pivot, ContentModel.PROP_LOCALE);
|
||||
|
||||
if(containerLocale.equals(pivotLocale))
|
||||
{
|
||||
break; // the pivot is set
|
||||
}
|
||||
else
|
||||
{
|
||||
pivot = null;
|
||||
}
|
||||
}
|
||||
|
||||
// returns the reader of this pivot translation if it's different to
|
||||
// the node in parameter
|
||||
|
||||
if (pivot != null && !nodeRef.getId().equals(pivot.getId()))
|
||||
{
|
||||
return getReader(pivot, propertyQName, fireContentReadPolicy);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// there is no URL - the interface specifies that this is not an error condition
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
String contentUrl = contentData.getContentUrl();
|
||||
|
||||
@@ -541,4 +605,4 @@ public class RoutingContentService implements ContentService
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
119
source/java/org/alfresco/repo/model/filefolder/FolderType.java
Normal file
119
source/java/org/alfresco/repo/model/filefolder/FolderType.java
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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.filefolder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.node.NodeServicePolicies;
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
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.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
|
||||
|
||||
/**
|
||||
* Class containing behaviour for the folder type.
|
||||
*
|
||||
* {@link ContentModel#TYPE_FOLDER folder type}
|
||||
*
|
||||
* @author yanipig
|
||||
*/
|
||||
public class FolderType implements
|
||||
NodeServicePolicies.BeforeDeleteNodePolicy
|
||||
{
|
||||
|
||||
// Dependencies
|
||||
private PolicyComponent policyComponent;
|
||||
private NodeService nodeService;
|
||||
|
||||
|
||||
/**
|
||||
* Initialise the Folder type
|
||||
*
|
||||
* Ensures that the {@link ContentModel#TYPE_FOLDER} folder type
|
||||
*/
|
||||
public void init()
|
||||
{
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"),
|
||||
ContentModel.TYPE_FOLDER,
|
||||
new JavaBehaviour(this, "beforeDeleteNode"));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param policyComponent the policy component to register behaviour with
|
||||
*/
|
||||
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||
{
|
||||
this.policyComponent = policyComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nodeService the Node Service to set
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Since the multilingual document don't keep their <b>mlDocument</b> aspect, the <b>mlEmptyTranslation<b>
|
||||
* can't be archived and the deletion of a container doesn't call the right policies, the deletion of a
|
||||
* folder must explicitly remove this aspect.
|
||||
*
|
||||
* @see org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy#beforeDeleteNode(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
public void beforeDeleteNode(NodeRef nodeRef)
|
||||
{
|
||||
List<ChildAssociationRef> childAssociations = nodeService.getChildAssocs(nodeRef, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
|
||||
|
||||
for(ChildAssociationRef childAssoc : childAssociations)
|
||||
{
|
||||
NodeRef child = childAssoc.getChildRef();
|
||||
|
||||
if(nodeService.exists(child))
|
||||
{
|
||||
// Remove the mlDocument aspect of each multilingual node contained in the folder.
|
||||
// The policies of this aspect perform the right logic.
|
||||
if(nodeService.hasAspect(child, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
|
||||
{
|
||||
nodeService.removeAspect(child, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
|
||||
}
|
||||
// Recurse the process if needed
|
||||
else if(nodeService.getType(child).equals(ContentModel.TYPE_FOLDER))
|
||||
{
|
||||
beforeDeleteNode(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.filefolder;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.model.ml.tools.AbstractMultilingualTestCases;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
/**
|
||||
* Multilingual container type test cases
|
||||
*
|
||||
* @see org.alfresco.service.cmr.ml.MLContainerType
|
||||
*
|
||||
* @author yanipig
|
||||
*/
|
||||
public class FolderTypeTest extends AbstractMultilingualTestCases {
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void testRemoveSpace() throws Exception
|
||||
{
|
||||
NodeRef pivot = createContent();
|
||||
NodeRef trans2 = createContent();
|
||||
NodeRef trans3 = createContent();
|
||||
NodeRef empty;
|
||||
|
||||
NodeRef mlContainer = multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||
multilingualContentService.addTranslation(trans2, pivot, Locale.GERMAN);
|
||||
multilingualContentService.addTranslation(trans3, pivot, Locale.ITALIAN);;
|
||||
empty = multilingualContentService.addEmptyTranslation(pivot, "Empty_" + System.currentTimeMillis(), Locale.ENGLISH);
|
||||
|
||||
|
||||
NodeRef space = fileFolderService.create(
|
||||
nodeService.getPrimaryParent(pivot).getParentRef(),
|
||||
"folder_" + System.currentTimeMillis(),
|
||||
ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
|
||||
nodeService.moveNode(pivot, space, ContentModel.ASSOC_CONTAINS, this.nodeService.getPrimaryParent(pivot).getQName());
|
||||
nodeService.moveNode(trans2, space, ContentModel.ASSOC_CONTAINS, this.nodeService.getPrimaryParent(trans2).getQName());
|
||||
nodeService.moveNode(trans3, space, ContentModel.ASSOC_CONTAINS, this.nodeService.getPrimaryParent(trans3).getQName());
|
||||
nodeService.moveNode(empty, space, ContentModel.ASSOC_CONTAINS, this.nodeService.getPrimaryParent(empty).getQName());
|
||||
|
||||
// Ensure that the nodes are correctly moved
|
||||
assertEquals("Move nodes failed", 4, nodeService.getChildAssocs(space).size());
|
||||
|
||||
// 1. Delete space
|
||||
|
||||
nodeService.deleteNode(space);
|
||||
|
||||
// Ensute that the space is deleted
|
||||
assertFalse("The deletion of the space failed", nodeService.exists(space));
|
||||
|
||||
// Ensure that the nodes are archived
|
||||
assertTrue("The space " + space + " must be archived", nodeService.exists(nodeArchiveService.getArchivedNode(trans2)));
|
||||
assertTrue("The node " + pivot + " must be archived", nodeService.exists(nodeArchiveService.getArchivedNode(pivot)));
|
||||
assertTrue("The node " + trans2 + " must be archived", nodeService.exists(nodeArchiveService.getArchivedNode(trans2)));
|
||||
assertTrue("The node " + trans3 + " must be archived", nodeService.exists(nodeArchiveService.getArchivedNode(trans3)));
|
||||
|
||||
// Ensure that the mlContainer is deleted and not archived
|
||||
assertFalse("The mlContainer " + mlContainer + " must be deleted", nodeService.exists(mlContainer));
|
||||
assertFalse("The mlContainer " + mlContainer + " can't be archived", nodeService.exists(nodeArchiveService.getArchivedNode(mlContainer)));
|
||||
|
||||
// 2. Restore space
|
||||
nodeArchiveService.restoreArchivedNode(nodeArchiveService.getArchivedNode(space));
|
||||
|
||||
// Ensure that the nodes are restaured
|
||||
assertFalse("The space " + space + "must be restored", nodeService.exists(nodeArchiveService.getArchivedNode(space)));
|
||||
assertFalse("The node " + pivot + "must be restored", nodeService.exists(nodeArchiveService.getArchivedNode(pivot)));
|
||||
assertFalse("The node " + trans2 + "must be restored", nodeService.exists(nodeArchiveService.getArchivedNode(trans2)));
|
||||
assertFalse("The node " + trans3 + "must be restored", nodeService.exists(nodeArchiveService.getArchivedNode(trans3)));
|
||||
|
||||
// Ensure that the mlContainer is not restored
|
||||
assertFalse("The mlContainer " + mlContainer + " must be deleted and can't be restored", nodeService.exists(mlContainer));
|
||||
|
||||
// 3. Delete space and remove it from the arhives
|
||||
|
||||
nodeService.deleteNode(space);
|
||||
nodeService.deleteNode(nodeArchiveService.getArchivedNode(space));
|
||||
|
||||
assertFalse("The space " + space + "can't be archived", nodeService.exists(nodeArchiveService.getArchivedNode(space)));
|
||||
assertFalse("The node " + pivot + "can't be archived", nodeService.exists(nodeArchiveService.getArchivedNode(pivot)));
|
||||
assertFalse("The node " + trans2 + "can't be archived", nodeService.exists(nodeArchiveService.getArchivedNode(trans2)));
|
||||
assertFalse("The node " + trans3 + "can't be archived", nodeService.exists(nodeArchiveService.getArchivedNode(trans3)));
|
||||
|
||||
assertFalse("The space " + space + "must be deleted", nodeService.exists(space));
|
||||
assertFalse("The node " + pivot + "must be deleted", nodeService.exists(pivot));
|
||||
assertFalse("The node " + trans2 + "must be deleted", nodeService.exists(trans2));
|
||||
assertFalse("The node " + trans3 + "must be deleted", nodeService.exists(trans3));
|
||||
}
|
||||
}
|
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* 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.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.config.Config;
|
||||
import org.alfresco.config.ConfigElement;
|
||||
import org.alfresco.config.ConfigLookupContext;
|
||||
import org.alfresco.config.ConfigService;
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Provides a an implementation of the <b>Content Filter Languages Service</b>
|
||||
*
|
||||
* {@link org.alfresco.service.cmr.ml.ContentFilterLanguagesService Content Filter Languages Service}
|
||||
*
|
||||
* @author yanipig
|
||||
*/
|
||||
public class ContentFilterLanguagesMap implements ContentFilterLanguagesService
|
||||
{
|
||||
private static final String CONFIG_AREA = "content-filter-lang";
|
||||
|
||||
private static final String CONFIG_CONDITION = "Languages Filter Map";
|
||||
|
||||
private static final String USED_STANDARD_CONFIG_CONDITION = "Standard In Use";
|
||||
private static final String USED_STANDARD_ELEMENT = "standard";
|
||||
|
||||
private static final String DEFAULT_LANGUAGE_LIST_STANDARD = "ISO 639-1";
|
||||
|
||||
private static final String ATTR_CODE = "code";
|
||||
private static final String ATTR_ORDER = "order";
|
||||
private static final String ATTR_DEFAULT = "default";
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ContentFilterLanguagesMap.class);
|
||||
|
||||
private ConfigService configService;
|
||||
|
||||
private List<String> orderedLangCodes;
|
||||
private Map<String, String> languagesByCode;
|
||||
|
||||
private String defaultLanguage = null;
|
||||
|
||||
/**
|
||||
* @param configService the config service to use to read languages
|
||||
*/
|
||||
public ContentFilterLanguagesMap(ConfigService configService)
|
||||
{
|
||||
this.configService = configService;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.ml.ContentFilterLanguagesService#getFilterLanguages()
|
||||
*/
|
||||
public List<String> getFilterLanguages()
|
||||
{
|
||||
return orderedLangCodes;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.ml.ContentFilterLanguagesService#getMissingLanguages(java.util.List)
|
||||
*/
|
||||
public List<String> getMissingLanguages(List<String> availableLanguages)
|
||||
{
|
||||
|
||||
if(availableLanguages == null || availableLanguages.size() == 0)
|
||||
{
|
||||
return orderedLangCodes;
|
||||
}
|
||||
|
||||
List<String> returnList = new ArrayList<String>(orderedLangCodes.size() - availableLanguages.size());
|
||||
|
||||
int index = 0;
|
||||
|
||||
for(String lang : orderedLangCodes)
|
||||
{
|
||||
if(!availableLanguages.contains(lang))
|
||||
{
|
||||
returnList.add(index, lang);
|
||||
index ++;
|
||||
}
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.ml.ContentFilterLanguagesService#getLabelByCode(java.lang.String)
|
||||
*/
|
||||
public String getLabelByCode(String code)
|
||||
{
|
||||
// get the translated language label
|
||||
String label;
|
||||
|
||||
label = I18NUtil.getMessage(MESSAGE_PREFIX + code);
|
||||
|
||||
// if not found, get the default name (found in content-filter-lang.xml)
|
||||
if(label == null || label.length() == 0)
|
||||
{
|
||||
label = languagesByCode.get(code);
|
||||
}
|
||||
|
||||
// if not found, return the language code
|
||||
if(label == null || label.length() == 0)
|
||||
{
|
||||
label = code + " (label not found)";
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.ml.ContentFilterLanguagesService#getOrderByCode(java.lang.String)
|
||||
*/
|
||||
public int getOrderByCode(String code)
|
||||
{
|
||||
if (orderedLangCodes.contains(code))
|
||||
{
|
||||
return orderedLangCodes.indexOf(code);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Language code not found : " + code);
|
||||
}
|
||||
}
|
||||
|
||||
public String getDefaultLanguage()
|
||||
{
|
||||
return this.defaultLanguage ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises the map using the configuration service provided
|
||||
*/
|
||||
public void init()
|
||||
{
|
||||
ConfigLookupContext clContext = new ConfigLookupContext(CONFIG_AREA);
|
||||
|
||||
// get which standart is defined by the user (ISO 639-1 by default)
|
||||
String standard = DEFAULT_LANGUAGE_LIST_STANDARD;
|
||||
|
||||
Config configStandard = configService.getConfig(USED_STANDARD_CONFIG_CONDITION, clContext);
|
||||
|
||||
if(configStandard != null
|
||||
&& configStandard.getConfigElement(USED_STANDARD_ELEMENT) != null)
|
||||
{
|
||||
standard = configStandard.getConfigElement(USED_STANDARD_ELEMENT).getValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("No standard configured, use by default : " + DEFAULT_LANGUAGE_LIST_STANDARD);
|
||||
}
|
||||
|
||||
|
||||
Config configConditions = configService.getConfig(CONFIG_CONDITION, clContext);
|
||||
Map<String, ConfigElement> configElements = configConditions.getConfigElements();
|
||||
|
||||
ConfigElement configLanguages = null;
|
||||
|
||||
// get the list of languages of the matched standard
|
||||
if(configElements.containsKey(standard))
|
||||
{
|
||||
configLanguages = configElements.get(standard);
|
||||
}
|
||||
|
||||
// if the santard is not matched, get the first list
|
||||
else
|
||||
{
|
||||
configLanguages = configElements.values().iterator().next();
|
||||
logger.warn("Ignoring prefered standard doesn't found, choose : " + configLanguages.getName());
|
||||
}
|
||||
|
||||
List<ConfigElement> languages = configLanguages.getChildren();
|
||||
|
||||
// get the size of the lists
|
||||
int listSize = languages.size();
|
||||
this.orderedLangCodes = new ArrayList<String>(listSize);
|
||||
this.languagesByCode = new HashMap<String, String>(listSize);
|
||||
|
||||
// construct the languages map and list
|
||||
for (ConfigElement langElem : languages)
|
||||
{
|
||||
String code = convertToOldISOCode(langElem.getAttribute(ATTR_CODE));
|
||||
String order = langElem.getAttribute(ATTR_ORDER);
|
||||
String value = langElem.getValue();
|
||||
String def = langElem.getAttribute(ATTR_DEFAULT);
|
||||
|
||||
orderedLangCodes.add(Integer.parseInt(order) - 1, code);
|
||||
|
||||
languagesByCode.put(code, value);
|
||||
|
||||
if(def != null && Boolean.parseBoolean(def))
|
||||
{
|
||||
if(defaultLanguage != null)
|
||||
{
|
||||
logger.warn("Ignoring default attribute is not unique le last matched will be used");
|
||||
}
|
||||
|
||||
this.defaultLanguage = code;
|
||||
}
|
||||
}
|
||||
|
||||
// make the collections read-only
|
||||
this.orderedLangCodes = Collections.unmodifiableList(this.orderedLangCodes);
|
||||
this.languagesByCode = Collections.unmodifiableMap(this.languagesByCode);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.ml.ContentFilterLanguagesService#convertToOldISOCode(java.lang.String)
|
||||
*/
|
||||
public String convertToOldISOCode(String code)
|
||||
{
|
||||
if(code.equalsIgnoreCase("he"))
|
||||
code = "iw";
|
||||
else if(code.equalsIgnoreCase("id"))
|
||||
code = "in";
|
||||
else if(code.equalsIgnoreCase("yi"))
|
||||
code = "ji";
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.ml.ContentFilterLanguagesService#convertToNewISOCode(java.lang.String)
|
||||
*/
|
||||
public String convertToNewISOCode(String code) {
|
||||
|
||||
if(code.equalsIgnoreCase("iw"))
|
||||
code = "he";
|
||||
else if(code.equalsIgnoreCase("in"))
|
||||
code = "id";
|
||||
else if(code.equalsIgnoreCase("ji"))
|
||||
code = "yi";
|
||||
|
||||
return code;
|
||||
}
|
||||
}
|
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* 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 org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.ContentServicePolicies;
|
||||
import org.alfresco.repo.copy.CopyServicePolicies;
|
||||
import org.alfresco.repo.node.NodeServicePolicies;
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.repo.policy.PolicyScope;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Class containing behaviour for the multilingual empty translation aspect.
|
||||
* An empty translation is a document's properties translation. This kind of node
|
||||
* doesn't have a content.
|
||||
*
|
||||
* {@link ContentModel#ASPECT_MULTILINGUAL_EMPTY_TRANSLATION ml empty document aspect}
|
||||
*
|
||||
* @author yanipig
|
||||
*/
|
||||
public class EmptyTranslationAspect implements
|
||||
CopyServicePolicies.OnCopyNodePolicy,
|
||||
NodeServicePolicies.BeforeDeleteNodePolicy,
|
||||
NodeServicePolicies.OnRemoveAspectPolicy,
|
||||
ContentServicePolicies.OnContentUpdatePolicy
|
||||
{
|
||||
|
||||
// Dependencies
|
||||
private PolicyComponent policyComponent;
|
||||
|
||||
private NodeService nodeService;
|
||||
|
||||
|
||||
/**
|
||||
* Initialise the Multilingual Empty Translation Aspect
|
||||
* <p>
|
||||
* Ensures that the {@link ContentModel#ASPECT_MULTILINGUAL_EMPTY_TRANSLATION ml empty document aspect}
|
||||
*/
|
||||
public void init()
|
||||
{
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "onCopyNode"),
|
||||
ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION,
|
||||
new JavaBehaviour(this, "onCopyNode"));
|
||||
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "onContentUpdate"),
|
||||
ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION,
|
||||
new JavaBehaviour(this, "onContentUpdate"));
|
||||
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"),
|
||||
ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION,
|
||||
new JavaBehaviour(this, "beforeDeleteNode"));
|
||||
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "onRemoveAspect"),
|
||||
ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION,
|
||||
new JavaBehaviour(this, "onRemoveAspect"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param policyComponent the policy component to register behaviour with
|
||||
*/
|
||||
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||
{
|
||||
this.policyComponent = policyComponent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param nodeService the Node Service to set
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a <b>cm:mlEmptyTranslation<b> is not permit.
|
||||
*
|
||||
* @see org.alfresco.repo.copy.CopyServicePolicies.OnCopyNodePolicy#onCopyNode(org.alfresco.service.namespace.QName, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.StoreRef, boolean, org.alfresco.repo.policy.PolicyScope)
|
||||
*/
|
||||
public void onCopyNode(QName classRef, NodeRef sourceNodeRef, StoreRef destinationStoreRef, boolean copyToNewNode, PolicyScope copyDetails)
|
||||
{
|
||||
throw new IllegalStateException("It's impossible to copy an empty translation");
|
||||
}
|
||||
|
||||
/**
|
||||
* If a content is added to a <b>cm:mlEmptyTranslation<b>, remove this aspect.
|
||||
*
|
||||
* @see org.alfresco.repo.content.ContentServicePolicies.OnContentUpdatePolicy#onContentUpdate(org.alfresco.service.cmr.repository.NodeRef, boolean)
|
||||
*/
|
||||
public void onContentUpdate(NodeRef nodeRef, boolean newContent)
|
||||
{
|
||||
if(newContent)
|
||||
{
|
||||
nodeService.removeAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If a <b>cm:mlEmptyTranslation<b> is deleted, it can't be archived.
|
||||
*
|
||||
* @see org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy#beforeDeleteNode(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
public void beforeDeleteNode(NodeRef nodeRef)
|
||||
{
|
||||
// add TEMPORARY ASPECT to force the deleteNode
|
||||
nodeService.addAspect(nodeRef, ContentModel.ASPECT_TEMPORARY, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the aspect <b>cm:mlEmptyTranslation<b> is removed <b>and the content url property is null</b>, the node can't be store much time.
|
||||
*
|
||||
* @see org.alfresco.repo.node.NodeServicePolicies.OnRemoveAspectPolicy#onRemoveAspect(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName) *
|
||||
*/
|
||||
public void onRemoveAspect(NodeRef nodeRef, QName aspectTypeQName)
|
||||
{
|
||||
// if the node is updated, the URL will not be null and the rome aspect don't delete
|
||||
// the translation. It will be a simple mlDocument.
|
||||
if(aspectTypeQName.equals(ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION)
|
||||
&& ((ContentData) nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT)).getContentUrl() == null)
|
||||
{
|
||||
// add TEMPORARY ASPECT to force the deleteNode
|
||||
nodeService.addAspect(nodeRef, ContentModel.ASPECT_TEMPORARY, null);
|
||||
nodeService.deleteNode(nodeRef);
|
||||
}
|
||||
}
|
||||
}
|
172
source/java/org/alfresco/repo/model/ml/MLContainerType.java
Normal file
172
source/java/org/alfresco/repo/model/ml/MLContainerType.java
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* 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.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.node.NodeServicePolicies;
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.service.cmr.ml.MultilingualContentService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Class containing behaviour for the multilingual multilingual container type.
|
||||
* A multilingual container type is fonctionally named '<b>Logical Document</b>'.
|
||||
* It links each translation of a semantical message together
|
||||
*
|
||||
* {@link ContentModel#TYPE_MULTILINGUAL_CONTAINER multilingual container type}
|
||||
*
|
||||
* @author yanipig
|
||||
*/
|
||||
public class MLContainerType implements
|
||||
NodeServicePolicies.BeforeDeleteNodePolicy,
|
||||
NodeServicePolicies.OnUpdatePropertiesPolicy
|
||||
{
|
||||
/**
|
||||
* set a property with this QName when the deletion process is running on the mlContainer. In this case
|
||||
* the policies of the remove aspect of mlDocument don't delete one more time the mlContainer.
|
||||
*/
|
||||
/*package*/ static QName PROP_NAME_DELETION_RUNNING = QName.createQName("__MLContanier_", "Deletion_Running");
|
||||
|
||||
// Dependencies
|
||||
private PolicyComponent policyComponent;
|
||||
|
||||
private NodeService nodeService;
|
||||
|
||||
private MultilingualContentService multilingualContentService;
|
||||
|
||||
/**
|
||||
* Initialise the Multilingual Container Type
|
||||
* <p>
|
||||
* Ensures that the {@link ContentModel#ASPECT_MULTILINGUAL_EMPTY_TRANSLATION ml empty document aspect}
|
||||
*/
|
||||
public void init()
|
||||
{
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"),
|
||||
ContentModel.TYPE_MULTILINGUAL_CONTAINER,
|
||||
new JavaBehaviour(this, "onUpdateProperties"));
|
||||
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"),
|
||||
ContentModel.TYPE_MULTILINGUAL_CONTAINER,
|
||||
new JavaBehaviour(this, "beforeDeleteNode"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param policyComponent the policy component to register behaviour with
|
||||
*/
|
||||
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||
{
|
||||
this.policyComponent = policyComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param multilingualContentService the Multilingual Content Service to set
|
||||
*/
|
||||
public void setMultilingualContentService(
|
||||
MultilingualContentService multilingualContentService)
|
||||
{
|
||||
this.multilingualContentService = multilingualContentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nodeService the Node Service to set
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a <b>cm:mlContainer<b> is deleted, it can't be archived.
|
||||
*
|
||||
* @see org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy#beforeDeleteNode(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
public void beforeDeleteNode(NodeRef nodeRef)
|
||||
{
|
||||
Map<Locale, NodeRef> translations = multilingualContentService.getTranslations(nodeRef);
|
||||
|
||||
// add the DELETION_RUNNING property
|
||||
nodeService.setProperty(nodeRef, PROP_NAME_DELETION_RUNNING, new Boolean(true));
|
||||
|
||||
for(Map.Entry<Locale, NodeRef> entry : translations.entrySet())
|
||||
{
|
||||
nodeService.removeAspect(entry.getValue(), ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
|
||||
}
|
||||
|
||||
// remove the DELETION_RUNNING property
|
||||
Map<QName, Serializable> prop = nodeService.getProperties(nodeRef);
|
||||
prop.remove(PROP_NAME_DELETION_RUNNING);
|
||||
nodeService.setProperties(nodeRef, prop);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The property <b>locale</b> of a <b>cm:mlContainer</b> represents the locale of the pivot translation.
|
||||
*
|
||||
* Since the pivot must be an existing translation and the pivot can t be empty, some tests must be performed when
|
||||
* the locale of the mlContainer is updated.
|
||||
*
|
||||
* @see org.alfresco.repo.node.NodeServicePolicies.OnUpdatePropertiesPolicy#onUpdateProperties(org.alfresco.service.cmr.repository.NodeRef, java.util.Map, java.util.Map)
|
||||
*/
|
||||
public void onUpdateProperties(NodeRef nodeRef, Map<QName, Serializable> before, Map<QName, Serializable> after)
|
||||
{
|
||||
Locale localeAfter = (Locale) after.get(ContentModel.PROP_LOCALE);
|
||||
Locale localeBefore = (Locale) before.get(ContentModel.PROP_LOCALE);
|
||||
|
||||
// The locale can be set as null if the container have no children.
|
||||
// Normaly, it's ONLY the case at the creation of the container.
|
||||
if(localeAfter == null && nodeService.getChildAssocs(nodeRef).size() != 0)
|
||||
{
|
||||
throw new IllegalArgumentException("A Locale property must be defined for a Multilingual Container and can't be null");
|
||||
}
|
||||
|
||||
if(localeAfter != null && !localeAfter.equals(localeBefore))
|
||||
{
|
||||
Map<Locale, NodeRef> translations = multilingualContentService.getTranslations(nodeRef);
|
||||
|
||||
//get the new pivot translation
|
||||
NodeRef pivot = translations.get(localeAfter);
|
||||
|
||||
if(pivot == null)
|
||||
{
|
||||
throw new IllegalArgumentException("The pivot translation must be an existing translation");
|
||||
}
|
||||
else if(nodeService.hasAspect(pivot, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
|
||||
{
|
||||
throw new IllegalArgumentException("The pivot translation can't be an empty translation");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -15,15 +15,17 @@
|
||||
* 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:
|
||||
* 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;
|
||||
@@ -33,8 +35,12 @@ import java.util.Set;
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.version.VersionModel;
|
||||
import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
|
||||
import org.alfresco.service.cmr.ml.MultilingualContentService;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
@@ -52,19 +58,22 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Multilingual support implementation
|
||||
*
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @author Philippe Dubois
|
||||
* @author yanipig
|
||||
*/
|
||||
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;
|
||||
|
||||
private ContentFilterLanguagesService contentFilterLanguagesService;
|
||||
private FileFolderService fileFolderService;
|
||||
|
||||
public MultilingualContentServiceImpl()
|
||||
{
|
||||
searchParametersMLRoot = new SearchParameters();
|
||||
@@ -73,27 +82,7 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
|
||||
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.
|
||||
*/
|
||||
@@ -119,7 +108,7 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
|
||||
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");
|
||||
/**
|
||||
@@ -137,11 +126,11 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
|
||||
// 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>
|
||||
* @param allowCreate <tt>true</tt> if a <b>cm:mlContainer</b> must be created if on doesn't exist,
|
||||
* otherwise <tt>false</tt> if a parent <b>cm:mlContainer</b> is expected to exist.
|
||||
@@ -225,12 +214,15 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
|
||||
// The aspect is present, so just ensure that the locale is correct
|
||||
nodeService.setProperty(contentNodeRef, ContentModel.PROP_LOCALE, locale);
|
||||
}
|
||||
|
||||
|
||||
// Do we make use of an existing container?
|
||||
if (mlContainerNodeRef == null)
|
||||
{
|
||||
// Make one
|
||||
mlContainerNodeRef = getOrCreateMLContainer(contentNodeRef, true);
|
||||
|
||||
// set the pivot language
|
||||
nodeService.setProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE, locale);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -240,7 +232,7 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Duplicate locale in document pool: " + locale);
|
||||
}
|
||||
|
||||
|
||||
// Use the existing container
|
||||
nodeService.addChild(
|
||||
mlContainerNodeRef,
|
||||
@@ -248,6 +240,7 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
|
||||
ContentModel.ASSOC_MULTILINGUAL_CHILD,
|
||||
QNAME_ML_TRANSLATION);
|
||||
}
|
||||
|
||||
// done
|
||||
return mlContainerNodeRef;
|
||||
}
|
||||
@@ -266,7 +259,7 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
|
||||
}
|
||||
return mlContainerNodeRef;
|
||||
}
|
||||
|
||||
|
||||
/** @inheritDoc */
|
||||
public NodeRef addTranslation(NodeRef newTranslationNodeRef, NodeRef translationOfNodeRef, Locale locale)
|
||||
{
|
||||
@@ -307,7 +300,7 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
|
||||
/** @inheritDoc */
|
||||
public void createEdition( NodeRef translationNodeRef)
|
||||
{
|
||||
NodeRef mlContainerNodeRef = getOrCreateMLContainer(translationNodeRef, false);
|
||||
NodeRef mlContainerNodeRef = getOrCreateMLContainer(translationNodeRef, false);
|
||||
// Ensure that the translation given is one of the children
|
||||
getOrCreateMLContainer(translationNodeRef, false);
|
||||
// Get all the container's children
|
||||
@@ -315,8 +308,25 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
|
||||
mlContainerNodeRef,
|
||||
ContentModel.ASSOC_MULTILINGUAL_CHILD,
|
||||
RegexQNamePattern.MATCH_ALL);
|
||||
// Version the container and all its children
|
||||
versionService.createVersion(mlContainerNodeRef, null, true);
|
||||
|
||||
|
||||
// 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)
|
||||
@@ -416,4 +426,173 @@ public class MultilingualContentServiceImpl implements MultilingualContentServic
|
||||
}
|
||||
return nearestNodeRef;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public List<Locale> getMissingTranslations(NodeRef localizedNodeRef, boolean addThisNodeLocale)
|
||||
{
|
||||
List<Locale> foundLocales = new ArrayList<Locale>(getTranslations(localizedNodeRef).keySet());
|
||||
List<String> foundLanguages = new ArrayList<String>();
|
||||
|
||||
|
||||
// transform locales into languages codes
|
||||
for(Locale locale : foundLocales)
|
||||
{
|
||||
foundLanguages.add(locale.getLanguage());
|
||||
}
|
||||
|
||||
// add the locale of the given node if required
|
||||
if(addThisNodeLocale)
|
||||
{
|
||||
Locale localeNode = (Locale) nodeService.getProperty(localizedNodeRef, ContentModel.PROP_LOCALE);
|
||||
|
||||
if(localeNode != null)
|
||||
{
|
||||
foundLanguages.remove(localeNode.toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("No locale found for the node " + localizedNodeRef);
|
||||
}
|
||||
}
|
||||
|
||||
List<String> missingLanguages = null;
|
||||
|
||||
if(foundLanguages.size() == 0)
|
||||
{
|
||||
// The given node is the only one available translation and it must
|
||||
// be return.
|
||||
// MissingLanguages become the entire list pf languages.
|
||||
missingLanguages = contentFilterLanguagesService.getFilterLanguages();
|
||||
}
|
||||
else
|
||||
{
|
||||
// get the missing languages form the list of content filter languages
|
||||
missingLanguages = contentFilterLanguagesService.getMissingLanguages(foundLanguages);
|
||||
}
|
||||
// construct a list of locales
|
||||
List<Locale> missingLocales = new ArrayList<Locale>(missingLanguages.size() + 1);
|
||||
|
||||
for(String lang : missingLanguages)
|
||||
{
|
||||
missingLocales.add(I18NUtil.parseLocale(lang));
|
||||
}
|
||||
|
||||
return missingLocales;
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public NodeRef getPivotTranslation(NodeRef nodeRef)
|
||||
{
|
||||
if(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
|
||||
{
|
||||
NodeRef container = getTranslationContainer(nodeRef);
|
||||
Locale containerLocale = (Locale) nodeService.getProperty(container, ContentModel.PROP_LOCALE);
|
||||
|
||||
return getTranslationForLocale(nodeRef, containerLocale);
|
||||
}
|
||||
else if(ContentModel.TYPE_MULTILINGUAL_CONTAINER.equals(nodeService.getType(nodeRef)))
|
||||
{
|
||||
Locale containerLocale = (Locale) nodeService.getProperty(nodeRef, ContentModel.PROP_LOCALE);
|
||||
|
||||
return getTranslationForLocale(getTranslations(nodeRef).get(containerLocale), containerLocale);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("The node is not multilingual " + nodeRef);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc */
|
||||
public NodeRef addEmptyTranslation(NodeRef translationOfNodeRef, String name, Locale locale)
|
||||
{
|
||||
// any node used as reference
|
||||
NodeRef anyTranslation;
|
||||
// the empty document to create
|
||||
NodeRef newTranslationNodeRef = null;
|
||||
|
||||
QName typeQName = nodeService.getType(translationOfNodeRef);
|
||||
if (typeQName.equals(ContentModel.TYPE_MULTILINGUAL_CONTAINER))
|
||||
{
|
||||
// Set the ml container ans get the pivot
|
||||
anyTranslation = getPivotTranslation(translationOfNodeRef);
|
||||
}
|
||||
else if(nodeService.hasAspect(translationOfNodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
|
||||
{
|
||||
anyTranslation = translationOfNodeRef;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException(
|
||||
"Node must have aspect " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT + " applied or be a " + ContentModel.TYPE_MULTILINGUAL_CONTAINER);
|
||||
}
|
||||
|
||||
// Create the document in the space of the node of reference
|
||||
NodeRef parentNodeRef = nodeService.getPrimaryParent(anyTranslation).getParentRef();
|
||||
|
||||
newTranslationNodeRef = fileFolderService.create(
|
||||
parentNodeRef,
|
||||
name,
|
||||
ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
|
||||
// add the translation to the container
|
||||
addTranslation(newTranslationNodeRef, translationOfNodeRef, locale);
|
||||
|
||||
// set it empty
|
||||
nodeService.addAspect(newTranslationNodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION, null);
|
||||
|
||||
// get the extension and set the ContentData property with an null URL.
|
||||
String extension = "";
|
||||
int dotIdx;
|
||||
if((dotIdx = name.lastIndexOf(".")) > -1 )
|
||||
{
|
||||
extension = name.substring(dotIdx);
|
||||
}
|
||||
|
||||
nodeService.setProperty(newTranslationNodeRef, ContentModel.PROP_CONTENT,
|
||||
new ContentData(null, extension, 0, "UTF-8", locale));
|
||||
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Added an empty translation: \n" +
|
||||
" Translation of: " + translationOfNodeRef + " of type " + typeQName + "\n" +
|
||||
" New translation: " + newTranslationNodeRef + "\n" +
|
||||
" Locale: " + locale);
|
||||
}
|
||||
|
||||
return newTranslationNodeRef;
|
||||
}
|
||||
|
||||
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 setContentFilterLanguagesService(ContentFilterLanguagesService contentFilterLanguagesService)
|
||||
{
|
||||
this.contentFilterLanguagesService = contentFilterLanguagesService;
|
||||
}
|
||||
|
||||
public void setFileFolderService(FileFolderService fileFolderService)
|
||||
{
|
||||
this.fileFolderService = fileFolderService;
|
||||
}
|
||||
|
||||
public void renameWithMLExtension(NodeRef translationNodeRef)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
* 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.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.copy.CopyServicePolicies;
|
||||
import org.alfresco.repo.node.NodeServicePolicies;
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.repo.policy.PolicyScope;
|
||||
import org.alfresco.service.cmr.ml.MultilingualContentService;
|
||||
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.namespace.RegexQNamePattern;
|
||||
|
||||
|
||||
/**
|
||||
* Class containing behaviour for the multilingual document aspect.
|
||||
*
|
||||
* {@link ContentModel#ASPECT_MULTILINGUAL_DOCUMENT ml document aspect}
|
||||
*
|
||||
* @author yanipig
|
||||
*/
|
||||
public class MultilingualDocumentAspect implements
|
||||
CopyServicePolicies.OnCopyNodePolicy,
|
||||
CopyServicePolicies.OnCopyCompletePolicy,
|
||||
NodeServicePolicies.BeforeDeleteNodePolicy,
|
||||
NodeServicePolicies.BeforeRemoveAspectPolicy,
|
||||
NodeServicePolicies.OnRemoveAspectPolicy,
|
||||
NodeServicePolicies.OnUpdatePropertiesPolicy
|
||||
{
|
||||
|
||||
// Dependencies
|
||||
private PolicyComponent policyComponent;
|
||||
|
||||
private MultilingualContentService multilingualContentService;
|
||||
|
||||
private NodeService nodeService;
|
||||
|
||||
|
||||
/**
|
||||
* Initialise the Multilingual Aspect
|
||||
*
|
||||
* Ensures that the {@link ContentModel#ASPECT_MULTILINGUAL_DOCUMENT ml document aspect}
|
||||
*/
|
||||
public void init()
|
||||
{
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "onCopyNode"),
|
||||
ContentModel.ASPECT_MULTILINGUAL_DOCUMENT,
|
||||
new JavaBehaviour(this, "onCopyNode"));
|
||||
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"),
|
||||
ContentModel.ASPECT_MULTILINGUAL_DOCUMENT,
|
||||
new JavaBehaviour(this, "beforeDeleteNode"));
|
||||
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "beforeRemoveAspect"),
|
||||
ContentModel.ASPECT_MULTILINGUAL_DOCUMENT,
|
||||
new JavaBehaviour(this, "beforeRemoveAspect"));
|
||||
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"),
|
||||
ContentModel.ASPECT_MULTILINGUAL_DOCUMENT,
|
||||
new JavaBehaviour(this, "onUpdateProperties"));
|
||||
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "onCopyComplete"),
|
||||
ContentModel.ASPECT_MULTILINGUAL_DOCUMENT,
|
||||
new JavaBehaviour(this, "onCopyComplete"));
|
||||
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "onRemoveAspect"),
|
||||
ContentModel.ASPECT_MULTILINGUAL_DOCUMENT,
|
||||
new JavaBehaviour(this, "onRemoveAspect"));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param policyComponent the policy component to register behaviour with
|
||||
*/
|
||||
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||
{
|
||||
this.policyComponent = policyComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param multilingualContentService the Multilingual Content Service to set
|
||||
*/
|
||||
public void setMultilingualContentService(
|
||||
MultilingualContentService multilingualContentService)
|
||||
{
|
||||
this.multilingualContentService = multilingualContentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nodeService the Node Service to set
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* The copy of a <b>cm:mlDocument</b> can't keep the Multilingual aspect.
|
||||
*
|
||||
* @see org.alfresco.repo.copy.CopyServicePolicies.OnCopyNodePolicy#onCopyNode(org.alfresco.service.namespace.QName, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.StoreRef, boolean, org.alfresco.repo.policy.PolicyScope)
|
||||
*/
|
||||
public void onCopyNode(QName classRef, NodeRef sourceNodeRef, StoreRef destinationStoreRef, boolean copyToNewNode, PolicyScope copyDetails)
|
||||
{
|
||||
copyDetails.removeAspect(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* The copy of <b>mlDocument</b> don't keep the 'locale' property.
|
||||
*
|
||||
* @see org.alfresco.repo.copy.CopyServicePolicies.OnCopyCompletePolicy#onCopyComplete(org.alfresco.service.namespace.QName, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef, boolean, java.util.Map)
|
||||
*/
|
||||
public void onCopyComplete(QName classRef, NodeRef sourceNodeRef, NodeRef destinationRef, boolean copyToNewNode, Map<NodeRef, NodeRef> copyMap)
|
||||
{
|
||||
Map<QName, Serializable> copiedProp = nodeService.getProperties(destinationRef);
|
||||
copiedProp.remove(ContentModel.PROP_LOCALE);
|
||||
nodeService.setProperties(destinationRef, copiedProp);
|
||||
}
|
||||
|
||||
/**
|
||||
* A <b>cm:mlDocument</b> is pivot translation it is a multilingual document (non empty) if it's language matches the language
|
||||
* of its <b>cm:mlDocument</b>. And a pivot translation can't be removed if it's not the last translation of the <b>cm:mlContainer</b>.
|
||||
*
|
||||
* If a translation is deleted, it's multilingual aspect is lost.
|
||||
*
|
||||
* @see org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy#beforeDeleteNode(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
public void beforeDeleteNode(NodeRef nodeRef)
|
||||
{
|
||||
nodeService.removeAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* When a pivot translation is deleted, it's <b>cm:mlContainer is deleted too.</b>
|
||||
*
|
||||
* <i>Note: When the pivot translation and the mlContainer are deleted, the mlDocument apsect is removed from
|
||||
* the other translations. It will be better to don't allow the deletion of the pivot if other translation is
|
||||
* available at the client side level.</i>
|
||||
*
|
||||
* @see org.alfresco.repo.node.NodeServicePolicies.BeforeRemoveAspectPolicy#beforeRemoveAspect(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName)
|
||||
*/
|
||||
public void beforeRemoveAspect(NodeRef nodeRef, QName aspectTypeQName)
|
||||
{
|
||||
if(aspectTypeQName.equals(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
|
||||
{
|
||||
NodeRef mlContainer = multilingualContentService.getTranslationContainer(nodeRef);
|
||||
|
||||
// nothing to do if the mlContainer is in a deletion process
|
||||
Boolean inDeleteProcess = (Boolean) nodeService.getProperty(mlContainer, MLContainerType.PROP_NAME_DELETION_RUNNING);
|
||||
if(inDeleteProcess != null && inDeleteProcess == true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Locale mlContainerLocale = (Locale) nodeService.getProperty(mlContainer, ContentModel.PROP_LOCALE);
|
||||
Locale nodeRefLocale = (Locale) nodeService.getProperty(nodeRef, ContentModel.PROP_LOCALE);
|
||||
|
||||
nodeService.removeChild(mlContainer, nodeRef);
|
||||
|
||||
// if last translation or if nodeRef is pivot translation
|
||||
if(multilingualContentService.getTranslations(mlContainer).size() == 0
|
||||
|| mlContainerLocale.equals(nodeRefLocale))
|
||||
{
|
||||
// delete the mlContainer
|
||||
nodeService.deleteNode(mlContainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* After removing the <b>cm:mlDocument</b> aspect :
|
||||
* - the node is removed is it's a <b>cm:mlEmptyTranslation</b>
|
||||
* - if not, only the locale property is removed
|
||||
*
|
||||
* @see org.alfresco.repo.node.NodeServicePolicies.OnRemoveAspectPolicy#onRemoveAspect(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName)
|
||||
*/
|
||||
public void onRemoveAspect(NodeRef nodeRef, QName aspectTypeQName)
|
||||
{
|
||||
if(aspectTypeQName.equals(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
|
||||
{
|
||||
|
||||
if(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
|
||||
{
|
||||
// note: if the node has the temporary aspect and the mlEmptyTranslation in a same
|
||||
// time, it means that the node is being deleted by another process...
|
||||
if(!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_TEMPORARY))
|
||||
{
|
||||
nodeService.deleteNode(nodeRef);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Map<QName, Serializable> props = nodeService.getProperties(nodeRef);
|
||||
props.remove(ContentModel.PROP_LOCALE);
|
||||
nodeService.setProperties(nodeRef, props);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the locale is unique inside the <b>mlContainer</b>.
|
||||
*
|
||||
* If the locale of a pivot translation is modified, the pivot locale reference of the mlContainer
|
||||
* must be modified too.
|
||||
*
|
||||
* @see org.alfresco.repo.node.NodeServicePolicies.OnUpdatePropertiesPolicy#onUpdateProperties(org.alfresco.service.cmr.repository.NodeRef, java.util.Map, java.util.Map)
|
||||
*/
|
||||
public void onUpdateProperties(NodeRef nodeRef, Map<QName, Serializable> before, Map<QName, Serializable> after)
|
||||
{
|
||||
Locale localeBefore = (Locale) before.get(ContentModel.PROP_LOCALE);
|
||||
Locale localeAfter;
|
||||
|
||||
// the after local property type can be either Locale or String
|
||||
Serializable objLocaleAfter = after.get(ContentModel.PROP_LOCALE);
|
||||
if (objLocaleAfter instanceof Locale )
|
||||
{
|
||||
localeAfter = (Locale) objLocaleAfter;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
localeAfter = I18NUtil.parseLocale(objLocaleAfter.toString());
|
||||
}
|
||||
|
||||
// if the local has been modified
|
||||
if(!localeBefore.equals(localeAfter))
|
||||
{
|
||||
NodeRef mlContainer = multilingualContentService.getTranslationContainer(nodeRef);
|
||||
|
||||
// Since the map returned by the getTranslations doesn't duplicate keys, the size of this map will be
|
||||
// different of the size of the number of children of the mlContainer if a duplicate locale is found.
|
||||
int transSize = multilingualContentService.getTranslations(mlContainer).size();
|
||||
int childSize = nodeService.getChildAssocs(mlContainer, ContentModel.ASSOC_MULTILINGUAL_CHILD, RegexQNamePattern.MATCH_ALL).size();
|
||||
|
||||
// if duplicate locale found
|
||||
if(transSize != childSize)
|
||||
{
|
||||
// throw an exception and the current transaction will be rolled back. The properties will not be
|
||||
// longer in an illegal state.
|
||||
throw new IllegalArgumentException("The locale " + localeAfter +
|
||||
" can't be changed for the node " + nodeRef +
|
||||
" because this locale is already in use in an other translation of the same " +
|
||||
ContentModel.TYPE_MULTILINGUAL_CONTAINER + ".");
|
||||
}
|
||||
|
||||
// get the locale of ML Container
|
||||
Locale localMlContainer = (Locale) nodeService.getProperty(
|
||||
mlContainer,
|
||||
ContentModel.PROP_LOCALE);
|
||||
|
||||
// if locale of the container is equals to the locale of
|
||||
// the node (before update). The nodeRef is the pivot language
|
||||
// and the locale of the mlContainer must be modified
|
||||
if(localeBefore.equals(localMlContainer))
|
||||
{
|
||||
nodeService.setProperty(
|
||||
mlContainer,
|
||||
ContentModel.PROP_LOCALE,
|
||||
localeAfter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// else no action to perform
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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 junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import org.alfresco.repo.model.filefolder.FolderTypeTest;
|
||||
import org.alfresco.repo.model.ml.tools.ContentFilterLanguagesMapTest;
|
||||
import org.alfresco.repo.model.ml.tools.EmptyTranslationAspectTest;
|
||||
import org.alfresco.repo.model.ml.tools.MLContainerTypeTest;
|
||||
import org.alfresco.repo.model.ml.tools.MultilingualContentServiceImplTest;
|
||||
import org.alfresco.repo.model.ml.tools.MultilingualDocumentAspectTest;
|
||||
|
||||
|
||||
/**
|
||||
* Multilingual test suite
|
||||
*
|
||||
* @author yanipig
|
||||
*/
|
||||
public class MultilingualTestSuite extends TestSuite
|
||||
{
|
||||
/**
|
||||
* Creates the test suite
|
||||
*
|
||||
* @return the test suite
|
||||
*/
|
||||
public static Test suite()
|
||||
{
|
||||
TestSuite suite = new TestSuite();
|
||||
|
||||
suite.addTestSuite(EmptyTranslationAspectTest.class);
|
||||
suite.addTestSuite(ContentFilterLanguagesMapTest.class);
|
||||
suite.addTestSuite(MultilingualContentServiceImplTest.class);
|
||||
suite.addTestSuite(MultilingualDocumentAspectTest.class);
|
||||
suite.addTestSuite(MLContainerTypeTest.class);
|
||||
suite.addTestSuite(FolderTypeTest.class);
|
||||
|
||||
return suite;
|
||||
}
|
||||
}
|
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* 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 junit.framework.TestCase;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.node.archive.NodeArchiveService;
|
||||
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.ContentFilterLanguagesService;
|
||||
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.cmr.version.VersionService;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Base multilingual test cases
|
||||
*
|
||||
* @author yanipig
|
||||
*/
|
||||
public abstract class AbstractMultilingualTestCases extends TestCase
|
||||
{
|
||||
|
||||
protected static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
|
||||
|
||||
protected ServiceRegistry serviceRegistry;
|
||||
protected AuthenticationComponent authenticationComponent;
|
||||
protected TransactionService transactionService;
|
||||
protected NodeService nodeService;
|
||||
protected FileFolderService fileFolderService;
|
||||
protected VersionService versionService;
|
||||
protected MultilingualContentService multilingualContentService;
|
||||
protected NodeRef folderNodeRef;
|
||||
protected ContentFilterLanguagesService contentFilterLanguagesService;
|
||||
protected NodeArchiveService nodeArchiveService;
|
||||
@Override
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
nodeArchiveService = (NodeArchiveService) ctx.getBean("nodeArchiveService");
|
||||
serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||
authenticationComponent = (AuthenticationComponent) ctx.getBean("AuthenticationComponent");
|
||||
transactionService = serviceRegistry.getTransactionService();
|
||||
nodeService = serviceRegistry.getNodeService();
|
||||
fileFolderService = serviceRegistry.getFileFolderService();
|
||||
versionService = serviceRegistry.getVersionService();
|
||||
multilingualContentService = (MultilingualContentService) ctx.getBean("MultilingualContentService");
|
||||
contentFilterLanguagesService = (ContentFilterLanguagesService) ctx.getBean("ContentFilterLanguagesService");
|
||||
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
protected 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();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* 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.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Content filter language service test cases
|
||||
*
|
||||
* @see org.alfresco.service.cmr.ml.ContentFilterLanguagesService
|
||||
* @see org.alfresco.repo.model.ml.ContentFilterLanguagesMap
|
||||
*
|
||||
* @author yanipig
|
||||
*/
|
||||
public class ContentFilterLanguagesMapTest extends AbstractMultilingualTestCases
|
||||
{
|
||||
|
||||
public void testGetFilterLanguages() throws Exception
|
||||
{
|
||||
// get the list of content filter languages
|
||||
List<String> lggs = contentFilterLanguagesService.getFilterLanguages();
|
||||
|
||||
// Ensure that the list is not null
|
||||
assertNotNull("Language list is null", lggs);
|
||||
|
||||
// Ensure that the list is read-only
|
||||
try
|
||||
{
|
||||
lggs.add("NEW LOCALE");
|
||||
assertTrue("Add a value to the content filter language list is not permit, this list would be read only", false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// test case ok
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
lggs.remove(0);
|
||||
assertTrue("Remove a value to the content filter language list is not permit, this list would be read only", false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// test case ok
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testGetMissingLanguages() throws Exception
|
||||
{
|
||||
List<String> lggs = contentFilterLanguagesService.getFilterLanguages();
|
||||
|
||||
// get missing languages with null parameter
|
||||
List<String> missingLggsNull = contentFilterLanguagesService.getMissingLanguages(null);
|
||||
|
||||
// Ensure that the returned list is not null
|
||||
assertNotNull("Language list returned with the null parameter is null", missingLggsNull);
|
||||
// Ensure that the returned list is entire
|
||||
assertEquals("Language list returned with the null parameter corrupted", missingLggsNull.size(), lggs.size());
|
||||
|
||||
// get missing languages with empty collection parameter
|
||||
List<String> missingLggsEmpty = contentFilterLanguagesService.getMissingLanguages(Collections.EMPTY_LIST);
|
||||
|
||||
// Ensure that the returned list is not null
|
||||
assertNotNull("Language list returned with the empty parameter is null", missingLggsEmpty);
|
||||
// Ensure that the returned list is entire
|
||||
assertEquals("Language list returned with the empty parameter corrupted", missingLggsEmpty.size(), lggs.size());
|
||||
|
||||
// get missing languages with a two locale list
|
||||
List<String> param = new ArrayList<String>();
|
||||
param.add(0, lggs.get(0));
|
||||
param.add(1, lggs.get(1));
|
||||
List<String> missingLggsOk = contentFilterLanguagesService.getMissingLanguages(param);
|
||||
|
||||
// Ensure that the returned list is not null
|
||||
assertNotNull("Language list returned with the correct parameter is null", missingLggsOk);
|
||||
// Ensure that the returned list size is correct
|
||||
assertEquals("Language list size returned with the correct parameter is not correct", missingLggsOk.size(), (lggs.size() - 2));
|
||||
// Ensure that the returned list don't content the preceding locales
|
||||
assertFalse("Language found : " + param.get(0), missingLggsOk.contains(param.get(0)));
|
||||
assertFalse("Language found : " + param.get(1), missingLggsOk.contains(param.get(1)));
|
||||
// get missing languages with a not found locale
|
||||
param.add(2, "WRONG LOCALE CODE");
|
||||
List<String> missingLggsWrong = contentFilterLanguagesService.getMissingLanguages(param);
|
||||
|
||||
// Ensure that the returned list is not null
|
||||
assertNotNull("Language list returned with the wrong parameter is null", missingLggsWrong);
|
||||
// Ensure that the returned list size is correct
|
||||
assertEquals("Language list size returned with the correct parameter is not correct", missingLggsWrong.size(), (lggs.size() - 2));
|
||||
// Ensure that the returned list don't content the wrong locale
|
||||
assertFalse("Language found : " + param.get(0), missingLggsWrong.contains(param.get(0)));
|
||||
assertFalse("Language found : " + param.get(1), missingLggsWrong.contains(param.get(1)));
|
||||
assertFalse("Language found : " + param.get(2), missingLggsWrong.contains(param.get(2)));
|
||||
}
|
||||
|
||||
public void testISOCodeConvertions() throws Exception
|
||||
{
|
||||
// New ISO code list
|
||||
String[] newCode = {"he", "id", "yi"};
|
||||
String[] oldCode = {"iw", "in", "ji"};
|
||||
|
||||
Locale loc0 = new Locale(newCode[0]);
|
||||
Locale loc1 = new Locale(newCode[1]);
|
||||
Locale loc2 = new Locale(newCode[2]);
|
||||
|
||||
// Ensure that java.util.Locale has converted the new ISO code into new iso code
|
||||
assertEquals("java.util.Locale Convertion not correct for " + newCode[0], oldCode[0], loc0.getLanguage());
|
||||
assertEquals("java.util.Locale Convertion not correct for " + newCode[1], oldCode[1], loc1.getLanguage());
|
||||
assertEquals("java.util.Locale Convertion not correct for " + newCode[2], oldCode[2], loc2.getLanguage());
|
||||
|
||||
// Ensure that the convertion is correcte
|
||||
assertEquals("Convertion of new ISO codes not correct for " + newCode[0], oldCode[0], contentFilterLanguagesService.convertToOldISOCode(newCode[0]));
|
||||
assertEquals("Convertion of new ISO codes not correct for " + newCode[1], oldCode[1], contentFilterLanguagesService.convertToOldISOCode(newCode[1]));
|
||||
assertEquals("Convertion of new ISO codes not correct for " + newCode[2], oldCode[2], contentFilterLanguagesService.convertToOldISOCode(newCode[2]));
|
||||
|
||||
|
||||
assertEquals("Convertion of old ISO codes not correct for " + oldCode[0], newCode[0], contentFilterLanguagesService.convertToNewISOCode(oldCode[0]));
|
||||
assertEquals("Convertion of old ISO codes not correct for " + oldCode[1], newCode[1], contentFilterLanguagesService.convertToNewISOCode(oldCode[1]));
|
||||
assertEquals("Convertion of old ISO codes not correct for " + oldCode[2], newCode[2], contentFilterLanguagesService.convertToNewISOCode(oldCode[2]));
|
||||
}
|
||||
}
|
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* 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.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Empty translations aspect test cases
|
||||
*
|
||||
* @see org.alfresco.service.cmr.ml.EmptyTranslationAspect
|
||||
*
|
||||
* @author yanipig
|
||||
*/
|
||||
public class EmptyTranslationAspectTest extends AbstractMultilingualTestCases {
|
||||
|
||||
protected ContentService contentService;
|
||||
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
contentService = (ContentService) ctx.getBean("ContentService");
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testCopy() throws Exception
|
||||
{
|
||||
NodeRef pivot = createContent();
|
||||
NodeRef empty = null;
|
||||
|
||||
multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||
|
||||
empty = multilingualContentService.addEmptyTranslation(pivot, "empty_" + System.currentTimeMillis(), Locale.CHINESE);
|
||||
|
||||
boolean exceptionCatched = false;
|
||||
NodeRef copy = null;
|
||||
|
||||
try
|
||||
{
|
||||
copy = fileFolderService.copy(
|
||||
empty,
|
||||
nodeService.getPrimaryParent(empty).getParentRef(),
|
||||
"copyOfEmpty" + System.currentTimeMillis()).getNodeRef();
|
||||
|
||||
// test failed
|
||||
}
|
||||
catch (Exception ignore)
|
||||
{
|
||||
exceptionCatched = true;
|
||||
}
|
||||
|
||||
// Ensure that the copy of an empty translation throws an exception
|
||||
assertTrue("The copy of a translation must throws an exception", exceptionCatched);
|
||||
// Ensure that the copy node is null
|
||||
assertNull("The copy must fail ", copy);
|
||||
}
|
||||
|
||||
public void testDeleteNode() throws Exception
|
||||
{
|
||||
NodeRef pivot = createContent();
|
||||
NodeRef empty = null;
|
||||
|
||||
multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||
|
||||
empty = multilingualContentService.addEmptyTranslation(pivot, "empty_" + System.currentTimeMillis(), Locale.CHINESE);
|
||||
|
||||
nodeService.deleteNode(empty);
|
||||
|
||||
// Ensure that the empty translation is removed from the workspace
|
||||
assertFalse("The empty translation must be removed from the wokspace", nodeService.exists(empty));
|
||||
// Ensure that the empty translation is not archived
|
||||
assertFalse("The empty translation must be removed from the wokspace", nodeService.exists(nodeArchiveService.getArchivedNode(empty)));
|
||||
}
|
||||
|
||||
public void testGetContent() throws Exception
|
||||
{
|
||||
NodeRef pivot = createContent();
|
||||
NodeRef otherTranslation = createContent();
|
||||
|
||||
NodeRef empty = null;
|
||||
|
||||
NodeRef mlContainer = multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||
multilingualContentService.addTranslation(otherTranslation, pivot, Locale.KOREAN);
|
||||
|
||||
empty = multilingualContentService.addEmptyTranslation(pivot, "empty_" + System.currentTimeMillis(), Locale.CHINESE);
|
||||
|
||||
// Modify the content of the pivot
|
||||
String contentString = fileFolderService.getReader(pivot).getContentString();
|
||||
contentString += "_TEST_";
|
||||
|
||||
fileFolderService.getWriter(pivot).putContent(contentString);
|
||||
|
||||
// Ensure that the URL property of the empty translation content is null
|
||||
assertNull("The URL property of an empty translation must be null", ((ContentData) nodeService.getProperty(empty, ContentModel.PROP_CONTENT)).getContentUrl());
|
||||
// Ensure that the content retourned by a get reader of the empty document is the same as the pivot
|
||||
assertEquals("The content retourned of the empty translation must be the same that the content of the pivot",
|
||||
fileFolderService.getReader(pivot).getContentString(),
|
||||
fileFolderService.getReader(empty).getContentString());
|
||||
// Ensure that the content retourned by a get reader of the empty document is different to the non-pivot translation
|
||||
assertNotSame("The content retourned of the empty translation must be different that the content of a non-pivot translation",
|
||||
fileFolderService.getReader(otherTranslation).getContentString(),
|
||||
fileFolderService.getReader(empty).getContentString());
|
||||
|
||||
|
||||
// modify the pivot
|
||||
Map<QName, Serializable> props = nodeService.getProperties(mlContainer);
|
||||
props.put(ContentModel.PROP_LOCALE, Locale.KOREAN);
|
||||
nodeService.setProperties(mlContainer, props);
|
||||
|
||||
// Ensure that the modicfication of the pivot is take in account
|
||||
assertEquals("The modification of the pivot is not take in account",
|
||||
fileFolderService.getReader(otherTranslation).getContentString(),
|
||||
fileFolderService.getReader(empty).getContentString());
|
||||
}
|
||||
|
||||
public void testUpdateContent() throws Exception
|
||||
{
|
||||
NodeRef pivot = createContent();
|
||||
NodeRef empty = null;
|
||||
|
||||
multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||
|
||||
empty = multilingualContentService.addEmptyTranslation(pivot, "empty_" + System.currentTimeMillis(), Locale.CHINESE);
|
||||
|
||||
// update the empty translation content
|
||||
ContentWriter writer = contentService.getWriter(empty, ContentModel.PROP_CONTENT, true);
|
||||
writer.setMimetype("text/plain");
|
||||
writer.putContent("ANY_CONTENT");
|
||||
|
||||
// Ensure that the URL property of the empty translation content is not null
|
||||
assertNotNull("The url of an updated (ex)empty transation can't be null", ((ContentData) nodeService.getProperty(empty, ContentModel.PROP_CONTENT)).getContentUrl());
|
||||
// Ensure that the mlEmptyTranslation aspect is removed
|
||||
assertFalse("The " + ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION + " aspect of an updated (ex)empty translation must be removed", nodeService.hasAspect(empty, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION));
|
||||
// Ensure that the mlDocument aspect is not removed
|
||||
assertTrue("The " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT + " aspect of an updated (ex)empty translation must be keeped", nodeService.hasAspect(empty, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
|
||||
// Ensure that the content is written
|
||||
assertEquals("The content of the (ex)empty translation is not correct",
|
||||
fileFolderService.getReader(empty).getContentString(),
|
||||
"ANY_CONTENT");
|
||||
// Ensure that the content is different that the content of the pivot
|
||||
assertNotSame("The content of the (ex)empty translation is not updated and is the same as the content of the pivot",
|
||||
fileFolderService.getReader(empty).getContentString(),
|
||||
fileFolderService.getReader(pivot).getContentString());
|
||||
}
|
||||
|
||||
public void testRemoveAspect() throws Exception
|
||||
{
|
||||
NodeRef pivot = createContent();
|
||||
NodeRef empty = null;
|
||||
|
||||
multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||
|
||||
// 1. remove mlEmptyTranslation aspect with empty content
|
||||
empty = multilingualContentService.addEmptyTranslation(pivot, "empty_" + System.currentTimeMillis(), Locale.CHINESE);
|
||||
nodeService.removeAspect(empty, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION);
|
||||
|
||||
// Ensure that the empty translation is deleted
|
||||
assertFalse("After removed the " + ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION + " of an empty translation with no content the node must be deleted",
|
||||
nodeService.exists(empty));
|
||||
assertFalse("After removed the " + ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION + " of an empty translation with no content the node must be deleted and can't be archived",
|
||||
nodeService.exists(nodeArchiveService.getArchivedNode(empty)));
|
||||
|
||||
// 2. remove mlDocument aspect with empty content
|
||||
empty = multilingualContentService.addEmptyTranslation(pivot, "empty_" + System.currentTimeMillis(), Locale.CHINESE);
|
||||
nodeService.removeAspect(empty, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT);
|
||||
|
||||
// Ensure that the empty translation is deleted
|
||||
assertFalse("After removed the " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT + " of an empty translation with no content the node must be deleted",
|
||||
nodeService.exists(empty));
|
||||
assertFalse("After removed the " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT + " of an empty translation with no content the node must be deleted and can't be archived",
|
||||
nodeService.exists(nodeArchiveService.getArchivedNode(empty)));
|
||||
|
||||
// 3. remove mlEmptyTranslation aspect with not empty content
|
||||
empty = multilingualContentService.addEmptyTranslation(pivot, "empty_" + System.currentTimeMillis(), Locale.CHINESE);
|
||||
ContentWriter writer = contentService.getWriter(empty, ContentModel.PROP_CONTENT, true);
|
||||
writer.setMimetype("text/plain");
|
||||
writer.putContent("ANY_CONTENT");
|
||||
nodeService.removeAspect(empty, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION);
|
||||
|
||||
// Ensure that the empty translation is NOT deleted
|
||||
assertTrue("After removed the " + ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION + " of an empty translation with content the node must NOT be deleted",
|
||||
nodeService.exists(empty));
|
||||
// Ensure that the mlEmptyTranslation aspect is removed
|
||||
assertFalse("After removed the " + ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION + " of an empty translation with content this aspect must be removed",
|
||||
nodeService.hasAspect(empty, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION));
|
||||
// Ensure that the mlEmptyDocument in NOT removed
|
||||
assertTrue("After removed the " + ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION + " of an empty translation with content the " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT + " aspect must be keeped",
|
||||
nodeService.hasAspect(empty, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Multilingual container type test cases
|
||||
*
|
||||
* @see org.alfresco.service.cmr.ml.MLContainerType
|
||||
*
|
||||
* @author yanipig
|
||||
*/
|
||||
public class MLContainerTypeTest extends AbstractMultilingualTestCases {
|
||||
|
||||
|
||||
public void testDeleteNode() throws Exception
|
||||
{
|
||||
NodeRef pivot = createContent();
|
||||
NodeRef empty;
|
||||
|
||||
NodeRef mlContainer = multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||
empty = multilingualContentService.addEmptyTranslation(pivot, "Empty_" + System.currentTimeMillis(), Locale.ENGLISH);
|
||||
|
||||
nodeService.deleteNode(mlContainer);
|
||||
|
||||
// Ensure that the mlContainer is deleted
|
||||
assertFalse("The mlContainer must be deleted", nodeService.exists(mlContainer));
|
||||
// Ensure that the empty translation is deleted
|
||||
assertFalse("The mlEmptyTranslation must be deleted", nodeService.exists(empty));
|
||||
// Ensure that the non-empty document is not deleted
|
||||
assertTrue("The mlDocument must not be deleted", nodeService.exists(pivot));
|
||||
// Ensure that the mlDocument property of the non-empty document is removed
|
||||
assertFalse("The " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT + " aspect of the mlDocument must be removed",
|
||||
nodeService.hasAspect(pivot, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void testEditLocale() throws Exception
|
||||
{
|
||||
NodeRef trans1 = createContent();
|
||||
NodeRef trans2 = createContent();
|
||||
NodeRef trans3 = createContent();
|
||||
NodeRef empty = null;
|
||||
|
||||
NodeRef mlContainer = multilingualContentService.makeTranslation(trans1, Locale.FRENCH);
|
||||
multilingualContentService.addTranslation(trans2, trans1, Locale.GERMAN);
|
||||
multilingualContentService.addTranslation(trans3, trans1, Locale.ITALIAN);
|
||||
empty = multilingualContentService.addEmptyTranslation(trans1, "EMPTY_" + System.currentTimeMillis(), Locale.JAPANESE);
|
||||
|
||||
// 1. Locale as null
|
||||
|
||||
// Ensure that the setting of the locale of the mlContainer as null throws an excpetion
|
||||
assertTrue("The setting of the locale of a mlContainer must throws an exception",
|
||||
setLocaleProp(mlContainer, null));
|
||||
// Ensure that the locale of the mlContainer is not changed
|
||||
assertEquals("The locale of the mlContainer would not be changed",
|
||||
Locale.FRENCH,
|
||||
nodeService.getProperty(mlContainer, ContentModel.PROP_LOCALE));
|
||||
|
||||
// 2. Set an non-existing locale
|
||||
|
||||
// Ensure that the setting of the locale of the mlContainer as a non-existing translation language throws an excpetion
|
||||
assertTrue("The setting of the locale of a mlContainer as a non-existing translation language must throws an exception",
|
||||
setLocaleProp(mlContainer, Locale.US));
|
||||
// Ensure that the locale of the mlContainer is not changed
|
||||
assertEquals("The locale of the mlContainer would not be changed",
|
||||
Locale.FRENCH,
|
||||
nodeService.getProperty(mlContainer, ContentModel.PROP_LOCALE));
|
||||
|
||||
// 3. Set the locale of a empty translation
|
||||
|
||||
// Ensure that the setting of the locale of the mlContainer as an empty translation language throws an excpetion
|
||||
assertTrue("The setting of the locale of a mlContainer as an empty translation language must throws an exception",
|
||||
setLocaleProp(mlContainer, Locale.JAPANESE));
|
||||
// Ensure that the locale of the mlContainer is not changed
|
||||
assertEquals("The locale of the mlContainer would not be changed",
|
||||
Locale.FRENCH,
|
||||
nodeService.getProperty(mlContainer, ContentModel.PROP_LOCALE));
|
||||
|
||||
// 4. Set an existing and valid locale
|
||||
|
||||
// Ensure that the setting of the locale of the mlContainer as an existing and a non-empty translation DOESN'T throw an excpetion
|
||||
assertFalse("The setting of the locale of a mlContainer as an existing and a non-empty translation DOESN'T throw an excpetion",
|
||||
setLocaleProp(mlContainer, Locale.ITALIAN));
|
||||
// Ensure that the locale of the mlContainer is not changed
|
||||
assertEquals("The locale of the mlContainer would be changed",
|
||||
Locale.ITALIAN,
|
||||
nodeService.getProperty(mlContainer, ContentModel.PROP_LOCALE));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private boolean setLocaleProp(NodeRef node, Locale locale) throws Exception
|
||||
{
|
||||
Map<QName, Serializable> props = nodeService.getProperties(node);
|
||||
props.put(ContentModel.PROP_LOCALE, locale);
|
||||
|
||||
boolean exceptionCatched = false;
|
||||
|
||||
try
|
||||
{
|
||||
nodeService.setProperties(node, props);
|
||||
|
||||
}
|
||||
catch (IllegalArgumentException ignore)
|
||||
{
|
||||
exceptionCatched = true;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
throw new Exception(ex);
|
||||
}
|
||||
|
||||
|
||||
return exceptionCatched;
|
||||
}
|
||||
}
|
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* 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.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.version.Version;
|
||||
import org.alfresco.service.cmr.version.VersionHistory;
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.ml.MultilingualContentServiceImpl
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @author Philippe Dubois
|
||||
*/
|
||||
public class MultilingualContentServiceImplTest extends AbstractMultilingualTestCases
|
||||
{
|
||||
|
||||
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);
|
||||
// Check the container child count
|
||||
assertEquals("Incorrect number of child nodes", 1, nodeService.getChildAssocs(mlContainerNodeRef).size());
|
||||
}
|
||||
|
||||
public void testAddTranslationUsingContainer() throws Exception
|
||||
{
|
||||
// Make a container with a single translation
|
||||
NodeRef chineseContentNodeRef = createContent();
|
||||
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||
// Create some more content
|
||||
NodeRef frenchContentNodeRef = createContent();
|
||||
// Make this a translation of the Chinese
|
||||
NodeRef newMLContainerNodeRef = multilingualContentService.addTranslation(
|
||||
frenchContentNodeRef,
|
||||
mlContainerNodeRef,
|
||||
Locale.FRENCH);
|
||||
// Make sure that the original container was used
|
||||
assertEquals("Existing container should have been used", mlContainerNodeRef, newMLContainerNodeRef);
|
||||
// Check the container child count
|
||||
assertEquals("Incorrect number of child nodes", 2, nodeService.getChildAssocs(mlContainerNodeRef).size());
|
||||
}
|
||||
|
||||
public void testAddTranslationUsingContent() throws Exception
|
||||
{
|
||||
// Make a container with a single translation
|
||||
NodeRef chineseContentNodeRef = createContent();
|
||||
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||
// Create some more content
|
||||
NodeRef frenchContentNodeRef = createContent();
|
||||
// Make this a translation of the Chinese
|
||||
NodeRef newMLContainerNodeRef = multilingualContentService.addTranslation(
|
||||
frenchContentNodeRef,
|
||||
chineseContentNodeRef,
|
||||
Locale.FRENCH);
|
||||
// Make sure that the original container was used
|
||||
assertEquals("Existing container should have been used", mlContainerNodeRef, newMLContainerNodeRef);
|
||||
// Check the container child count
|
||||
assertEquals("Incorrect number of child nodes", 2, nodeService.getChildAssocs(mlContainerNodeRef).size());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void testGetMissingTranslation() throws Exception
|
||||
{
|
||||
List<String> langList = contentFilterLanguagesService.getFilterLanguages();
|
||||
int langListSize = langList.size();
|
||||
|
||||
// make sure that it exists at least tree language filter
|
||||
assertFalse("The testGetMissingTranslation test case needs at least three language", langListSize < 3);
|
||||
|
||||
// get the first tree locale of the content filter language list
|
||||
Locale loc1 = I18NUtil.parseLocale(langList.get(0));
|
||||
Locale loc2 = I18NUtil.parseLocale(langList.get(1));
|
||||
Locale loc3 = I18NUtil.parseLocale(langList.get(2));
|
||||
|
||||
// create three content
|
||||
NodeRef nodeRef1 = createContent();
|
||||
NodeRef nodeRef2 = createContent();
|
||||
NodeRef nodeRef3 = createContent();
|
||||
|
||||
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(nodeRef1, loc1);
|
||||
|
||||
List<Locale> missing = multilingualContentService.getMissingTranslations(mlContainerNodeRef, false);
|
||||
|
||||
// make sure that the missing language list size is correct
|
||||
assertFalse("Missing Translation Size false. " +
|
||||
"Real size : " + missing.size() + ". Normal Size " + (langListSize - 1), missing.size() != (langListSize - 1));
|
||||
|
||||
// make sure that the missing language list is correct
|
||||
assertFalse("Missing Translation List false. Locale " + loc1 + " found", missing.contains(loc1.toString()));
|
||||
|
||||
multilingualContentService.addTranslation(nodeRef2, mlContainerNodeRef, loc2);
|
||||
multilingualContentService.addTranslation(nodeRef3, mlContainerNodeRef, loc3);
|
||||
|
||||
|
||||
missing = multilingualContentService.getMissingTranslations(mlContainerNodeRef, false);
|
||||
|
||||
// make sure that the missing language list size is correct
|
||||
assertFalse("Missing Translation Size false. " +
|
||||
"Real size : " + missing.size() + ". Normal Size " + (langListSize - 3), missing.size() != (langListSize - 3));
|
||||
|
||||
// make sure that the missing language list is correct
|
||||
assertFalse("Missing Translation List false. Locale " + loc2 + " or " + loc3 + " found", missing.contains(loc2.toString()) || missing.contains(loc3.toString()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void testPivotTranslation() throws Exception
|
||||
{
|
||||
NodeRef chineseContentNodeRef = createContent();
|
||||
|
||||
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||
|
||||
// make sure that the pivot language is set
|
||||
assertNotNull("Pivot language not set", nodeService.getProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE));
|
||||
|
||||
// make sure that the pivot language is correctly set
|
||||
assertTrue("Pivot language not correctly set", nodeService.getProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE).equals(Locale.CHINESE));
|
||||
|
||||
NodeRef frenchContentNodeRef = createContent();
|
||||
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
|
||||
|
||||
// make sure that the pivot noderef is correct
|
||||
assertTrue("Pivot node ref not correct", multilingualContentService.getPivotTranslation(mlContainerNodeRef).equals(chineseContentNodeRef));
|
||||
|
||||
// modify the pivot language
|
||||
nodeService.setProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE, Locale.FRENCH);
|
||||
|
||||
// make sure that the modified pivot noderef is correct
|
||||
assertTrue("Pivot node ref not correct", multilingualContentService.getPivotTranslation(mlContainerNodeRef).equals(frenchContentNodeRef));
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void testCreateEmptyTranslation() throws Exception
|
||||
{
|
||||
NodeRef chineseContentNodeRef = createContent();
|
||||
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||
|
||||
NodeRef empty = multilingualContentService.addEmptyTranslation(chineseContentNodeRef, "" + System.currentTimeMillis(), Locale.CANADA);
|
||||
|
||||
// Ensure that the empty translation is not null
|
||||
assertNotNull("The creation of the empty document failed ", empty);
|
||||
// Ensure that the empty translation has the mlDocument aspect
|
||||
assertTrue("The empty document must have the mlDocument aspect", nodeService.hasAspect(empty, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
|
||||
// Ensure that the empty translation has the mlEmptyTranslation aspect
|
||||
assertTrue("The empty document must have the mlEmptyTranslation aspect", nodeService.hasAspect(empty, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void testCreateEdition() throws Exception
|
||||
{
|
||||
// Make some content
|
||||
NodeRef chineseContentNodeRef = createContent();
|
||||
NodeRef frenchContentNodeRef = createContent();
|
||||
NodeRef japaneseContentNodeRef = createContent();
|
||||
// Add to container
|
||||
NodeRef mlContainerNodeRef = multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||
multilingualContentService.addTranslation(frenchContentNodeRef, mlContainerNodeRef, Locale.FRENCH);
|
||||
multilingualContentService.addTranslation(japaneseContentNodeRef, mlContainerNodeRef, Locale.JAPANESE);
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* 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.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Multilingual document aspect test cases
|
||||
*
|
||||
* @see org.alfresco.service.cmr.ml.MultilingualDocumentAspect
|
||||
*
|
||||
* @author yanipig
|
||||
*/
|
||||
public class MultilingualDocumentAspectTest extends AbstractMultilingualTestCases
|
||||
{
|
||||
public void testCopy() throws Exception
|
||||
{
|
||||
NodeRef original = createContent();
|
||||
NodeRef mlContainer = multilingualContentService.makeTranslation(original, Locale.FRENCH);
|
||||
|
||||
NodeRef copy =
|
||||
fileFolderService.copy(original, nodeService.getPrimaryParent(original).getParentRef(), "COPY" + System.currentTimeMillis()).getNodeRef();
|
||||
|
||||
// Ensure that the copy removes the mlDocument aspect
|
||||
assertFalse("The copy of a mlDocument can't have the multilingual aspect", nodeService.hasAspect(copy, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
|
||||
|
||||
// Ensure that the copy removes the association between the mlConatiner and the new node
|
||||
assertEquals("The copy of a mlDocument can't be a children of the mlContainer", 1, multilingualContentService.getTranslations(mlContainer).size());
|
||||
|
||||
// Ensure that the copy removes the Locale property of the new node
|
||||
assertNull("The copy of a mlDocument can't keep the locale property", nodeService.getProperty(copy, ContentModel.PROP_LOCALE));
|
||||
}
|
||||
|
||||
public void testDeleteNode() throws Exception
|
||||
{
|
||||
NodeRef trad1 = createContent();
|
||||
NodeRef trad2 = createContent();
|
||||
NodeRef trad3 = createContent();
|
||||
|
||||
NodeRef parent = nodeService.getPrimaryParent(trad1).getParentRef();
|
||||
|
||||
NodeRef mlContainer = multilingualContentService.makeTranslation(trad1, Locale.FRENCH);
|
||||
multilingualContentService.addTranslation(trad2, trad1, Locale.GERMAN);
|
||||
multilingualContentService.addTranslation(trad3, trad1, Locale.ITALIAN);
|
||||
|
||||
nodeService.deleteNode(trad3);
|
||||
|
||||
// Ensure that the deleted node is romoved from its space
|
||||
assertEquals("The deleted node must be removed to the space", 2, nodeService.getChildAssocs(parent).size());
|
||||
// Ensure that the mlContainer doesn't keep an association to the deleted node
|
||||
assertEquals("The deleted node must be removed to the child associations of the mlContainer", 2, multilingualContentService.getTranslations(mlContainer).size());
|
||||
|
||||
// retore the deleted node
|
||||
NodeRef restoredNode = nodeArchiveService.restoreArchivedNode(nodeArchiveService.getArchivedNode(trad3)).getRestoredNodeRef();
|
||||
|
||||
// Ensure that the restored node is restored to it s original space
|
||||
assertEquals("The restaured node must be restaured to the the space", 3, nodeService.getChildAssocs(parent).size());
|
||||
// Ensure that the restored node is not linked to the mlContainer
|
||||
assertEquals("The restaured node would not be restaured to the mlContainer", 2, multilingualContentService.getTranslations(mlContainer).size());
|
||||
// Ensure that the restored node doesn't keep the mlDocument aspect
|
||||
assertFalse("The restaured node can't keep the multilingual aspect", nodeService.hasAspect(restoredNode, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
|
||||
// Ensure that the restored node doesn't keep the locale property
|
||||
assertNull("The restaured node can't keep the locale property", nodeService.getProperty(restoredNode, ContentModel.PROP_LOCALE));
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void testDeletePivot() throws Exception
|
||||
{
|
||||
NodeRef pivot = createContent();
|
||||
NodeRef trans1 = createContent();
|
||||
NodeRef mlContainer = multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||
multilingualContentService.addTranslation(trans1, pivot, Locale.KOREAN);
|
||||
|
||||
//nodeService.deleteNode(trans1);
|
||||
nodeService.deleteNode(pivot);
|
||||
|
||||
// Ensure that pivot is removed
|
||||
assertFalse("The pivot would be removed", nodeService.exists(pivot));
|
||||
// Ensure that the mlContainer is removed
|
||||
assertFalse("The mlContainer must be removed if the pivot is removed", nodeService.exists(mlContainer));
|
||||
// Ensure that trans1 is NOT removed
|
||||
assertTrue("The last translation would not be removed", nodeService.exists(trans1));
|
||||
// Ensure that trans1 has no mlDocument aspect
|
||||
assertFalse("The last translation can't keep the multilingual aspect", nodeService.hasAspect(trans1, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
|
||||
// Ensure that trans1 has no locale propety
|
||||
assertNull("The last translation can't keep the locale property", nodeService.getProperty(trans1, ContentModel.PROP_LOCALE));
|
||||
}
|
||||
|
||||
public void testDeleteLastNode() throws Exception
|
||||
{
|
||||
NodeRef pivot = createContent();
|
||||
NodeRef mlContainer = multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||
|
||||
nodeService.deleteNode(pivot);
|
||||
|
||||
// Ensure that the mlContainer is removed too
|
||||
assertFalse("The mlContainer must be removed if the last translation is removed", nodeService.exists(mlContainer));
|
||||
|
||||
}
|
||||
|
||||
public void testRemoveAspect() throws Exception
|
||||
{
|
||||
// entierly covered by the delete tests
|
||||
}
|
||||
|
||||
public void testUpdateLocale() throws Exception
|
||||
{
|
||||
NodeRef pivot = createContent();
|
||||
NodeRef trans1 = createContent();
|
||||
NodeRef mlContainer = multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||
multilingualContentService.addTranslation(trans1, pivot, Locale.KOREAN);
|
||||
|
||||
// modify the locale for the translation
|
||||
Map<QName, Serializable> props = nodeService.getProperties(trans1);
|
||||
props.put(ContentModel.PROP_LOCALE, Locale.GERMAN);
|
||||
nodeService.setProperties(trans1, props);
|
||||
|
||||
// Ensure that the pivot reference is not changed for the mlContainer and the locale is changed for the translation
|
||||
assertEquals("The locale for the pivot would be changed ",Locale.GERMAN, nodeService.getProperty(trans1, ContentModel.PROP_LOCALE));
|
||||
assertEquals("The pivot reference would not be changed in the mlContainer", Locale.FRENCH, nodeService.getProperty(mlContainer, ContentModel.PROP_LOCALE));
|
||||
|
||||
// modify the locale for the pivot
|
||||
props = nodeService.getProperties(pivot);
|
||||
props.put(ContentModel.PROP_LOCALE, Locale.US);
|
||||
nodeService.setProperties(pivot, props);
|
||||
|
||||
// Ensure that the pivot reference is changed (in the pivot and in the mlContainer)
|
||||
assertEquals("The locale for the pivot would be changed ", Locale.US, nodeService.getProperty(pivot, ContentModel.PROP_LOCALE));
|
||||
assertEquals("The pivot reference would be changes in the mlContainer", Locale.US, nodeService.getProperty(mlContainer, ContentModel.PROP_LOCALE));
|
||||
}
|
||||
|
||||
public void testUpdateRedundantLocale() throws Exception
|
||||
{
|
||||
NodeRef pivot = createContent();
|
||||
NodeRef trans1 = createContent();
|
||||
NodeRef trans2 = createContent();
|
||||
|
||||
multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||
multilingualContentService.addTranslation(trans1, pivot, Locale.KOREAN);
|
||||
multilingualContentService.addTranslation(trans2, pivot, Locale.JAPANESE);
|
||||
|
||||
// 1. Try with redundant locale
|
||||
|
||||
// modify the locale for the translation 2
|
||||
Map<QName, Serializable> props = nodeService.getProperties(trans2);
|
||||
props.put(ContentModel.PROP_LOCALE, Locale.KOREAN);
|
||||
|
||||
boolean exceptionCatched = false;
|
||||
|
||||
try
|
||||
{
|
||||
nodeService.setProperties(trans2, props);
|
||||
// test failed
|
||||
} catch (Exception ignore)
|
||||
{
|
||||
exceptionCatched = true;
|
||||
}
|
||||
|
||||
// Ensure that the the exception was catched.
|
||||
assertTrue("The modification of this locale must catch an exception because it is already in use in another translation", exceptionCatched);
|
||||
// Ensure that the locale of the trans2 is unchanged
|
||||
assertEquals("The locale must not be changed",
|
||||
Locale.JAPANESE,
|
||||
(Locale) nodeService.getProperty(trans2, ContentModel.PROP_LOCALE));
|
||||
|
||||
// 2. Try with a non-redundant locale
|
||||
|
||||
props = nodeService.getProperties(trans2);
|
||||
props.put(ContentModel.PROP_LOCALE, Locale.ITALIAN);
|
||||
|
||||
exceptionCatched = false;
|
||||
|
||||
try
|
||||
{
|
||||
nodeService.setProperties(trans2, props);
|
||||
|
||||
} catch (Exception ignore)
|
||||
{
|
||||
// test failed
|
||||
exceptionCatched = true;
|
||||
}
|
||||
|
||||
// Ensure that the exception was not catched
|
||||
assertFalse("The modification of the locale would not throws an exception", exceptionCatched);
|
||||
// Ensure that the locale is modified
|
||||
assertEquals("The locale must be changed",
|
||||
Locale.ITALIAN,
|
||||
(Locale) nodeService.getProperty(trans2, ContentModel.PROP_LOCALE));
|
||||
}
|
||||
}
|
||||
|
181
source/java/org/alfresco/repo/node/MLTranslationInterceptor.java
Normal file
181
source/java/org/alfresco/repo/node/MLTranslationInterceptor.java
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* 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.node;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
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.namespace.QName;
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Interceptor to
|
||||
* - filter the multilingual nodes to display the documents in the prefered language of teh user
|
||||
*
|
||||
* @author yanipig
|
||||
*/
|
||||
public class MLTranslationInterceptor implements MethodInterceptor
|
||||
{
|
||||
private static Log logger = LogFactory
|
||||
.getLog(MLTranslationInterceptor.class);
|
||||
|
||||
private NodeService nodeService;
|
||||
|
||||
private MultilingualContentService multilingualContentService;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable
|
||||
{
|
||||
Object ret = null;
|
||||
String methodName = invocation.getMethod().getName();
|
||||
|
||||
// intercept the methods getChildAssocs and getChildByNames to apply filter.
|
||||
if (methodName.equals("getChildAssocs") || methodName.equals("getChildByName"))
|
||||
{
|
||||
ret = invocation.proceed();
|
||||
|
||||
NodeRef parent = (NodeRef) invocation.getArguments()[0];
|
||||
|
||||
// all the association returned by the method
|
||||
List<ChildAssociationRef> allChildAssoc = (List<ChildAssociationRef>) ret;
|
||||
|
||||
// get the user content filter language
|
||||
Locale filterLocale = I18NUtil.getContentLocaleOrNull();
|
||||
|
||||
if(filterLocale != null
|
||||
&& nodeService.getType(parent).equals(ContentModel.TYPE_FOLDER)
|
||||
&& ret != null
|
||||
&& !allChildAssoc.isEmpty()
|
||||
)
|
||||
{
|
||||
|
||||
// the list of Association to return
|
||||
List<ChildAssociationRef> toReturn = new ArrayList();
|
||||
// the ml containers found in the folder
|
||||
List<NodeRef> mlContainers = new ArrayList();
|
||||
|
||||
// construct the list of ML Container
|
||||
for (ChildAssociationRef assoc : allChildAssoc)
|
||||
{
|
||||
NodeRef child = assoc.getChildRef();
|
||||
|
||||
QName type = nodeService.getType(child);
|
||||
|
||||
if(type.equals(ContentModel.TYPE_CONTENT) &&
|
||||
nodeService.hasAspect(child, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
|
||||
{
|
||||
NodeRef container = multilingualContentService.getTranslationContainer(child);
|
||||
|
||||
if (!mlContainers.contains(container))
|
||||
{
|
||||
mlContainers.add(container);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// no specific treatment for folder and non-multilingual document
|
||||
toReturn.add(assoc);
|
||||
}
|
||||
}
|
||||
|
||||
// for each mlContainer found, choose the unique document to return
|
||||
for(NodeRef container : mlContainers)
|
||||
{
|
||||
// get each translation language
|
||||
Set<Locale> locales = multilingualContentService.getTranslations(container).keySet();
|
||||
|
||||
if(locales != null && locales.size() > 0)
|
||||
{
|
||||
Locale matchedLocal = I18NUtil.getNearestLocale(filterLocale, locales);
|
||||
|
||||
NodeRef matchedTranslation = null;
|
||||
|
||||
// if the filter language is not found
|
||||
if(matchedLocal == null)
|
||||
{
|
||||
// get the pivot translation
|
||||
matchedTranslation = multilingualContentService.getPivotTranslation(container);
|
||||
}
|
||||
else
|
||||
{
|
||||
// get the matched translation
|
||||
matchedTranslation = multilingualContentService.getTranslations(container).get(matchedLocal);
|
||||
}
|
||||
|
||||
toReturn.add(new ChildAssociationRef(null, null, null, matchedTranslation));
|
||||
}
|
||||
}
|
||||
|
||||
ret = toReturn;
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Filter has found " +
|
||||
allChildAssoc.size() + " entries, " +
|
||||
mlContainers.size() + " different ML Container " +
|
||||
"and returns " + toReturn.size() + " nodes");
|
||||
}
|
||||
}
|
||||
|
||||
} else
|
||||
{
|
||||
ret = invocation.proceed();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public MultilingualContentService getMultilingualContentService()
|
||||
{
|
||||
return multilingualContentService;
|
||||
}
|
||||
|
||||
public void setMultilingualContentService(
|
||||
MultilingualContentService multilingualContentService)
|
||||
{
|
||||
this.multilingualContentService = multilingualContentService;
|
||||
}
|
||||
|
||||
public NodeService getNodeService()
|
||||
{
|
||||
return nodeService;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
}
|
@@ -37,6 +37,7 @@ import org.alfresco.service.cmr.avmsync.AVMSyncService;
|
||||
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.lock.LockService;
|
||||
import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.CopyService;
|
||||
@@ -255,7 +256,7 @@ public class ServiceDescriptorRegistry
|
||||
*/
|
||||
public ActionService getActionService()
|
||||
{
|
||||
return (ActionService)getService(ACTION_SERVICE);
|
||||
return (ActionService)getService(ACTION_SERVICE);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -364,6 +365,14 @@ public class ServiceDescriptorRegistry
|
||||
return (AttributeService)getService(ATTRIBUTE_SERVICE);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.ServiceRegistry#getContentFilterLanguagesService()
|
||||
*/
|
||||
public ContentFilterLanguagesService getContentFilterLanguagesService()
|
||||
{
|
||||
return (ContentFilterLanguagesService) getService(CONTENT_FILTER_LANGUAGES_SERVICE);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.ServiceRegistry#getAVMLockingService()
|
||||
*/
|
||||
|
@@ -15,11 +15,11 @@
|
||||
* 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:
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.version;
|
||||
@@ -29,9 +29,9 @@ import org.alfresco.service.cmr.version.VersionService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* interface conating the constants used by the light weight
|
||||
* interface conating the constants used by the light weight
|
||||
* version store implementation
|
||||
*
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public interface VersionModel
|
||||
@@ -40,20 +40,20 @@ public interface VersionModel
|
||||
* Namespace
|
||||
*/
|
||||
public static final String NAMESPACE_URI = "http://www.alfresco.org/model/versionstore/1.0";
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* The store protocol
|
||||
*/
|
||||
public static final String STORE_PROTOCOL = VersionService.VERSION_STORE_PROTOCOL;
|
||||
|
||||
|
||||
/**
|
||||
* The store id
|
||||
*/
|
||||
public static final String STORE_ID = "lightWeightVersionStore";
|
||||
|
||||
|
||||
|
||||
|
||||
public static final String PROP_VERSION_LABEL = "versionLabel";
|
||||
public static final String PROP_CREATED_DATE = ContentModel.PROP_CREATED.getLocalName();
|
||||
public static final String PROP_CREATED_DATE = ContentModel.PROP_CREATED.getLocalName();
|
||||
public static final String PROP_CREATOR = ContentModel.PROP_CREATOR.getLocalName();
|
||||
public static final String PROP_VERSION_TYPE = "versionType";
|
||||
public static final String PROP_VERSION_NUMBER = "versionNumber";
|
||||
@@ -62,29 +62,29 @@ public interface VersionModel
|
||||
public static final String PROP_FROZEN_NODE_STORE_PROTOCOL = "frozenNodeStoreProtocol";
|
||||
public static final String PROP_FROZEN_NODE_STORE_ID = "frozenNodeStoreId";
|
||||
public static final String PROP_FROZEN_ASPECTS = "frozenAspects";
|
||||
|
||||
|
||||
/** The version store root aspect */
|
||||
public static final QName ASPECT_VERSION_STORE_ROOT = QName.createQName(NAMESPACE_URI, "versionStoreRoot");
|
||||
|
||||
|
||||
/**
|
||||
* Version history type
|
||||
*/
|
||||
public static final String TYPE_VERSION_HISTORY = "versionHistory";
|
||||
public static final QName TYPE_QNAME_VERSION_HISTORY = QName.createQName(NAMESPACE_URI, TYPE_VERSION_HISTORY);
|
||||
|
||||
|
||||
/**
|
||||
* Version history properties and associations
|
||||
*/
|
||||
public static final String PROP_VERSIONED_NODE_ID = "versionedNodeId";
|
||||
public static final QName PROP_QNAME_VERSIONED_NODE_ID = QName.createQName(NAMESPACE_URI, PROP_VERSIONED_NODE_ID);
|
||||
public static final QName PROP_QNAME_VERSIONED_NODE_ID = QName.createQName(NAMESPACE_URI, PROP_VERSIONED_NODE_ID);
|
||||
public static final QName ASSOC_ROOT_VERSION = QName.createQName(NAMESPACE_URI, "rootVersion");
|
||||
|
||||
|
||||
/**
|
||||
* Verison type
|
||||
*/
|
||||
public static final String TYPE_VERSION = "version";
|
||||
public static final QName TYPE_QNAME_VERSION = QName.createQName(NAMESPACE_URI, TYPE_VERSION);
|
||||
|
||||
|
||||
/**
|
||||
* Version type properties and associations
|
||||
*/
|
||||
@@ -95,14 +95,14 @@ public interface VersionModel
|
||||
public static final QName PROP_QNAME_FROZEN_NODE_STORE_PROTOCOL = QName.createQName(NAMESPACE_URI, PROP_FROZEN_NODE_STORE_PROTOCOL);
|
||||
public static final QName PROP_QNAME_FROZEN_NODE_STORE_ID = QName.createQName(NAMESPACE_URI, PROP_FROZEN_NODE_STORE_ID);
|
||||
public static final QName PROP_QNAME_FROZEN_ASPECTS = QName.createQName(NAMESPACE_URI, PROP_FROZEN_ASPECTS);
|
||||
public static final QName ASSOC_SUCCESSOR = QName.createQName(NAMESPACE_URI, "successor");
|
||||
|
||||
public static final QName ASSOC_SUCCESSOR = QName.createQName(NAMESPACE_URI, "successor");
|
||||
|
||||
/**
|
||||
* Version Meta Data Value type
|
||||
*/
|
||||
public static final String TYPE_VERSION_META_DATA_VALUE = "versionMetaDataValue";
|
||||
public static final QName TYPE_QNAME_VERSION_META_DATA_VALUE = QName.createQName(NAMESPACE_URI, TYPE_VERSION_META_DATA_VALUE);
|
||||
|
||||
|
||||
/**
|
||||
* Version Meta Data Value attributes
|
||||
*/
|
||||
@@ -110,13 +110,13 @@ public interface VersionModel
|
||||
public static final QName PROP_QNAME_META_DATA_NAME = QName.createQName(NAMESPACE_URI, PROP_META_DATA_NAME);
|
||||
public static final String PROP_META_DATA_VALUE = "metaDataValue";
|
||||
public static final QName PROP_QNAME_META_DATA_VALUE = QName.createQName(NAMESPACE_URI, PROP_META_DATA_VALUE);
|
||||
|
||||
|
||||
/**
|
||||
* Versioned attribute type
|
||||
*/
|
||||
public static final String TYPE_VERSIONED_PROPERTY = "versionedProperty";
|
||||
public static final QName TYPE_QNAME_VERSIONED_PROPERTY = QName.createQName(NAMESPACE_URI, TYPE_VERSIONED_PROPERTY);
|
||||
|
||||
|
||||
/**
|
||||
* Versioned attribute properties
|
||||
*/
|
||||
@@ -128,13 +128,13 @@ public interface VersionModel
|
||||
public static final QName PROP_QNAME_VALUE = QName.createQName(NAMESPACE_URI, PROP_VALUE);
|
||||
public static final QName PROP_QNAME_MULTI_VALUE = QName.createQName(NAMESPACE_URI, PROP_MULTI_VALUE);
|
||||
public static final QName PROP_QNAME_IS_MULTI_VALUE = QName.createQName(NAMESPACE_URI, PROP_IS_MULTI_VALUE);
|
||||
|
||||
|
||||
/**
|
||||
* Versioned child assoc type
|
||||
*/
|
||||
public static final String TYPE_VERSIONED_CHILD_ASSOC = "versionedChildAssoc";
|
||||
public static final QName TYPE_QNAME_VERSIONED_CHILD_ASSOC = QName.createQName(NAMESPACE_URI, TYPE_VERSIONED_CHILD_ASSOC);
|
||||
|
||||
|
||||
/**
|
||||
* Versioned child assoc properties
|
||||
*/
|
||||
@@ -146,13 +146,13 @@ public interface VersionModel
|
||||
public static final QName PROP_QNAME_ASSOC_TYPE_QNAME = QName.createQName(NAMESPACE_URI, PROP_ASSOC_TYPE_QNAME);
|
||||
public static final QName PROP_QNAME_IS_PRIMARY = QName.createQName(NAMESPACE_URI, PROP_IS_PRIMARY);
|
||||
public static final QName PROP_QNAME_NTH_SIBLING = QName.createQName(NAMESPACE_URI, PROP_NTH_SIBLING);
|
||||
|
||||
|
||||
/**
|
||||
* Versioned assoc type
|
||||
*/
|
||||
public static final String TYPE_VERSIONED_ASSOC = "versionedAssoc";
|
||||
public static final QName TYPE_QNAME_VERSIONED_ASSOC = QName.createQName(NAMESPACE_URI, TYPE_VERSIONED_ASSOC);
|
||||
|
||||
|
||||
/**
|
||||
* Child relationship names
|
||||
*/
|
||||
@@ -162,11 +162,18 @@ public interface VersionModel
|
||||
public static final String CHILD_VERSIONED_CHILD_ASSOCS = "versionedChildAssocs";
|
||||
public static final String CHILD_VERSIONED_ASSOCS = "versionedAssocs";
|
||||
public static final String CHILD_VERSION_META_DATA = "versionMetaData";
|
||||
|
||||
|
||||
public static final QName CHILD_QNAME_VERSION_HISTORIES = QName.createQName(NAMESPACE_URI, CHILD_VERSION_HISTORIES);
|
||||
public static final QName CHILD_QNAME_VERSIONS = QName.createQName(NAMESPACE_URI, CHILD_VERSIONS);
|
||||
public static final QName CHILD_QNAME_VERSIONED_ATTRIBUTES = QName.createQName(NAMESPACE_URI, CHILD_VERSIONED_ATTRIBUTES);
|
||||
public static final QName CHILD_QNAME_VERSIONED_CHILD_ASSOCS = QName.createQName(NAMESPACE_URI, CHILD_VERSIONED_CHILD_ASSOCS);
|
||||
public static final QName CHILD_QNAME_VERSIONED_ASSOCS = QName.createQName(NAMESPACE_URI, CHILD_VERSIONED_ASSOCS);
|
||||
public static final QName CHILD_QNAME_VERSION_META_DATA = QName.createQName(NAMESPACE_URI, CHILD_VERSION_META_DATA);
|
||||
|
||||
/**
|
||||
* Created version associated to the deleted translations of an mlContainer
|
||||
*/
|
||||
public static final String PROP_TRANSLATION_VERIONS = "translationVersions";
|
||||
public static final QName PROP_QNAME_TRANSLATION_VERIONS = QName.createQName(VersionModel.NAMESPACE_URI, PROP_TRANSLATION_VERIONS);
|
||||
|
||||
}
|
||||
|
@@ -36,6 +36,7 @@ import org.alfresco.service.cmr.avmsync.AVMSyncService;
|
||||
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.lock.LockService;
|
||||
import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.CopyService;
|
||||
@@ -85,6 +86,7 @@ public interface ServiceRegistry
|
||||
static final QName NODE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "NodeService");
|
||||
static final QName CONTENT_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ContentService");
|
||||
static final QName MIMETYPE_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "MimetypeService");
|
||||
static final QName CONTENT_FILTER_LANGUAGES_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "ContentFilterLanguagesService");
|
||||
static final QName SEARCH_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "SearchService");
|
||||
static final QName CATEGORY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CategoryService");
|
||||
static final QName COPY_SERVICE = QName.createQName(NamespaceService.ALFRESCO_URI, "CopyService");
|
||||
@@ -179,6 +181,12 @@ public interface ServiceRegistry
|
||||
@NotAuditable
|
||||
MimetypeService getMimetypeService();
|
||||
|
||||
/**
|
||||
* @return the content filter languages service (or null, if one is not provided)
|
||||
*/
|
||||
@NotAuditable
|
||||
ContentFilterLanguagesService getContentFilterLanguagesService();
|
||||
|
||||
/**
|
||||
* @return the search service (or null, if one is not provided)
|
||||
*/
|
||||
|
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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.util.List;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.service.Auditable;
|
||||
import org.alfresco.service.NotAuditable;
|
||||
import org.alfresco.service.PublicService;
|
||||
|
||||
|
||||
/**
|
||||
* This service interface provides support for content filter languages .
|
||||
*
|
||||
* @author yanipig
|
||||
*
|
||||
*/
|
||||
@PublicService
|
||||
public interface ContentFilterLanguagesService
|
||||
{
|
||||
|
||||
/**
|
||||
* I18N message prefix to found the translation of a language label with a
|
||||
* given lang code.
|
||||
*/
|
||||
public static final String MESSAGE_PREFIX = "content_filter_lang.";
|
||||
|
||||
/**
|
||||
* Get the order of the specified language code
|
||||
*
|
||||
* @param code
|
||||
* @return
|
||||
* @throws AlfrescoRuntimeException if the code doesn't exist
|
||||
*/
|
||||
@NotAuditable
|
||||
public int getOrderByCode(String code);
|
||||
|
||||
/**
|
||||
* Get the language of the specified language code
|
||||
*
|
||||
* @param code
|
||||
* @return
|
||||
* @throws AlfrescoRuntimeException if the code doesn't exist
|
||||
*/
|
||||
@NotAuditable
|
||||
public String getLabelByCode(String code);
|
||||
|
||||
/**
|
||||
* Get ordered list of languages code
|
||||
*
|
||||
* @return the map of displays indexed by extension
|
||||
*/
|
||||
@Auditable
|
||||
public List<String> getFilterLanguages();
|
||||
|
||||
/**
|
||||
* Get the the odered filter which results form an extract of availableLanguages on the filterLanguages
|
||||
*
|
||||
* @param availableLanguages the languages list whose will be removed from the filterLanguages
|
||||
* @return
|
||||
*/
|
||||
@Auditable
|
||||
public List<String> getMissingLanguages(List<String> availableLanguages);
|
||||
|
||||
/**
|
||||
* @return the default content filter language, null if it's not set.
|
||||
*/
|
||||
@Auditable
|
||||
public String getDefaultLanguage();
|
||||
|
||||
/**
|
||||
* Since <code>java.util.Locale</code> uses and returns <b>old</b> ISO code and the content-filter-lang.xml
|
||||
* respects the <b>new ones</b>. This method convert new codes into old codes:
|
||||
* <p>(he, yi, and id) new codes to (iw, ji, and in) old codes </p>
|
||||
*
|
||||
* @param code the ISO language code to convert
|
||||
* @return the convertion of the codes he, yi, and id or the given code
|
||||
*/
|
||||
@NotAuditable
|
||||
public String convertToOldISOCode(String code);
|
||||
|
||||
/**
|
||||
* Since <code>java.util.Locale</code> uses and returns <b>old</b> ISO code and the content-filter-lang.xml
|
||||
* respects the <b>new ones</b>. This method convert old codes into new codes:
|
||||
* <p>(iw, ji, and in) old codes to (he, yi, and id) new codes </p>
|
||||
*
|
||||
* @param code the ISO language code to convert
|
||||
* @return the convertion of the codes iw, ji, and in or the given code
|
||||
*/
|
||||
@NotAuditable
|
||||
public String convertToNewISOCode(String code);
|
||||
}
|
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
package org.alfresco.service.cmr.ml;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -117,4 +118,38 @@ public interface MultilingualContentService
|
||||
*/
|
||||
@Auditable(key = Auditable.Key.ARG_0, parameters = {"translationNodeRef", "locale"})
|
||||
NodeRef getTranslationForLocale(NodeRef translationNodeRef, Locale locale);
|
||||
|
||||
|
||||
/**
|
||||
* Given <b>cm:mlDocument</b> or a <b>cm:mlContainer</b>, this node returns each
|
||||
* locale that the node hasn't a translation yet.
|
||||
*
|
||||
* @param localizedNodeRef the <b>cm:mlDocument</b> or the <b>cm:mlContainer</b>
|
||||
* @param addThisNodeLocale if true, add the locale of the given <b>cm:mlDocument</b> in the list.
|
||||
* @return
|
||||
*/
|
||||
@Auditable(key = Auditable.Key.ARG_0, parameters = {"localizedNodeRef", "addThisNodeLocale"})
|
||||
List<Locale> getMissingTranslations(NodeRef localizedNodeRef, boolean addThisNodeLocale);
|
||||
|
||||
/**
|
||||
* Given any node, this returns the pivot translation. The pivot translation is the translation
|
||||
* that its locale is referenced by the locale of the MLContainer. The translation can't be an
|
||||
* empty translation.
|
||||
*
|
||||
* @param nodeRef the node to test
|
||||
* @return the pivot translation
|
||||
*/
|
||||
@Auditable(key = Auditable.Key.ARG_0, parameters = {"nodeRef"})
|
||||
NodeRef getPivotTranslation(NodeRef nodeRef);
|
||||
|
||||
/**
|
||||
* Make a empty translation out of an existing document. The necessary translation structures will be created
|
||||
* as necessary.
|
||||
*
|
||||
* @param translationOfNodeRef An existing <b>cm:mlDocument</b> or <b>cm:mlContainer</b>
|
||||
* @param name The name of the translation to create
|
||||
* @return Returns the new created <b>cm:mlEmptyTranslation</b>
|
||||
*/
|
||||
@Auditable(key = Auditable.Key.ARG_0, parameters = {"translationOfNodeRef", "name", "locale"})
|
||||
NodeRef addEmptyTranslation(NodeRef translationOfNodeRef, String name, Locale locale);
|
||||
}
|
||||
|
Reference in New Issue
Block a user