mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged HEAD-QA to HEAD (4.2) (including moving test classes into separate folders)
51903 to 54309 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@54310 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
56
source/test-java/org/alfresco/repo/model/ModelTestSuite.java
Normal file
56
source/test-java/org/alfresco/repo/model/ModelTestSuite.java
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.model;
|
||||
|
||||
import org.alfresco.repo.model.filefolder.FileFolderDuplicateChildTest;
|
||||
import org.alfresco.repo.model.filefolder.FileFolderServiceImplTest;
|
||||
import org.alfresco.repo.model.filefolder.HiddenAspectTest;
|
||||
import org.alfresco.repo.model.ml.tools.ContentFilterLanguagesMapTest;
|
||||
import org.alfresco.repo.model.ml.tools.EditionServiceImplTest;
|
||||
import org.alfresco.repo.model.ml.tools.EmptyTranslationAspectTest;
|
||||
import org.alfresco.repo.model.ml.tools.MLContainerTypeTest;
|
||||
import org.alfresco.repo.model.ml.tools.MultilingualContentServiceImplTest;
|
||||
import org.alfresco.repo.model.ml.tools.MultilingualDocumentAspectTest;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
|
||||
/**
|
||||
* Model test suite
|
||||
*/
|
||||
@RunWith(Suite.class)
|
||||
@SuiteClasses({
|
||||
ContentFilterLanguagesMapTest.class,
|
||||
EmptyTranslationAspectTest.class,
|
||||
MLContainerTypeTest.class,
|
||||
MultilingualContentServiceImplTest.class,
|
||||
MultilingualDocumentAspectTest.class,
|
||||
EditionServiceImplTest.class,
|
||||
|
||||
HiddenAspectTest.class,
|
||||
|
||||
// Add the file folder tests
|
||||
// These need to come afterwards, as they insert extra
|
||||
// interceptors which would otherwise confuse things
|
||||
FileFolderServiceImplTest.class,
|
||||
FileFolderDuplicateChildTest.class,
|
||||
})
|
||||
public class ModelTestSuite
|
||||
{
|
||||
}
|
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.model.filefolder;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.model.FileExistsException;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
/**
|
||||
* Checks that the duplicate child handling is done correctly.
|
||||
*
|
||||
* @see org.alfresco.repo.model.filefolder.FileFolderServiceImpl
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @since 2.1.0
|
||||
*/
|
||||
public class FileFolderDuplicateChildTest extends TestCase
|
||||
{
|
||||
private static final ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
|
||||
|
||||
private AuthenticationComponent authenticationComponent;
|
||||
private TransactionService transactionService;
|
||||
private RetryingTransactionHelper retryingTransactionHelper;
|
||||
private NodeService nodeService;
|
||||
private FileFolderService fileFolderService;
|
||||
private NodeRef rootNodeRef;
|
||||
private NodeRef workingRootNodeRef;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean("ServiceRegistry");
|
||||
transactionService = serviceRegistry.getTransactionService();
|
||||
retryingTransactionHelper = transactionService.getRetryingTransactionHelper();
|
||||
nodeService = serviceRegistry.getNodeService();
|
||||
fileFolderService = serviceRegistry.getFileFolderService();
|
||||
authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
|
||||
|
||||
RetryingTransactionCallback<NodeRef> callback = new RetryingTransactionCallback<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
// authenticate
|
||||
authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName());
|
||||
|
||||
// create a test store
|
||||
StoreRef storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, getName() + System.currentTimeMillis());
|
||||
rootNodeRef = nodeService.getRootNode(storeRef);
|
||||
|
||||
// create a folder to import into
|
||||
NodeRef nodeRef = nodeService.createNode(
|
||||
rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "working root"),
|
||||
ContentModel.TYPE_FOLDER).getChildRef();
|
||||
// Done
|
||||
return nodeRef;
|
||||
}
|
||||
};
|
||||
workingRootNodeRef = retryingTransactionHelper.doInTransaction(callback, false, true);
|
||||
}
|
||||
|
||||
public void tearDown() throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
public void testDuplicateChildNameDetection() throws Exception
|
||||
{
|
||||
// First create a file name F1
|
||||
RetryingTransactionCallback<FileInfo> callback = new CreateFileCallback(0);
|
||||
FileInfo fileInfo = retryingTransactionHelper.doInTransaction(callback, false, true);
|
||||
// Check that the filename is F0
|
||||
assertEquals("Incorrect initial filename", "F0", fileInfo.getName());
|
||||
|
||||
// Now create a whole lot of threads that attempt file creation
|
||||
int threadCount = 10;
|
||||
CountDownLatch endLatch = new CountDownLatch(threadCount);
|
||||
WorkerThread[] workers = new WorkerThread[threadCount];
|
||||
for (int i = 0; i < threadCount; i++)
|
||||
{
|
||||
workers[i] = new WorkerThread(endLatch);
|
||||
workers[i].start();
|
||||
}
|
||||
// Wait at the end gate
|
||||
endLatch.await(300L, TimeUnit.SECONDS);
|
||||
|
||||
// Analyse
|
||||
int failureCount = 0;
|
||||
int didNotCompleteCount = 0;
|
||||
for (int i = 0; i < threadCount; i++)
|
||||
{
|
||||
if (workers[i].error != null)
|
||||
{
|
||||
failureCount++;
|
||||
}
|
||||
else if (workers[i].success == null)
|
||||
{
|
||||
didNotCompleteCount++;
|
||||
}
|
||||
}
|
||||
System.out.println("" + failureCount + " of the " + threadCount + " threads failed and " + didNotCompleteCount + " did not finish.");
|
||||
assertEquals("Some failures", 0, failureCount);
|
||||
assertEquals("Some non-finishes", 0, didNotCompleteCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to create a file "Fn" where n is the number supplied to the constructor.
|
||||
*/
|
||||
private class CreateFileCallback implements RetryingTransactionCallback<FileInfo>
|
||||
{
|
||||
private final int number;
|
||||
public CreateFileCallback(int number)
|
||||
{
|
||||
this.number = number;
|
||||
}
|
||||
public FileInfo execute() throws Throwable
|
||||
{
|
||||
authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName());
|
||||
return fileFolderService.create(
|
||||
workingRootNodeRef,
|
||||
"F" + number,
|
||||
ContentModel.TYPE_CONTENT);
|
||||
}
|
||||
}
|
||||
|
||||
private static ThreadGroup threadGroup = new ThreadGroup("FileFolderDuplicateChildTest");
|
||||
private static int threadNumber = -1;
|
||||
private class WorkerThread extends Thread
|
||||
{
|
||||
private CountDownLatch endLatch;
|
||||
private Throwable error;
|
||||
private FileInfo success;
|
||||
|
||||
public WorkerThread(CountDownLatch endLatch)
|
||||
{
|
||||
super(threadGroup, "Worker " + ++threadNumber);
|
||||
this.endLatch = endLatch;
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
FileInfo fileInfo = null;
|
||||
// Start the count with a guaranteed failure
|
||||
int number = 0;
|
||||
while(true)
|
||||
{
|
||||
RetryingTransactionCallback<FileInfo> callback = new CreateFileCallback(number);
|
||||
try
|
||||
{
|
||||
System.out.println("Thread " + getName() + " attempting file: " + number);
|
||||
System.out.flush();
|
||||
|
||||
fileInfo = retryingTransactionHelper.doInTransaction(callback, false, true);
|
||||
// It worked
|
||||
success = fileInfo;
|
||||
break;
|
||||
}
|
||||
catch (FileExistsException e)
|
||||
{
|
||||
// Try another number
|
||||
number++;
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// Oops
|
||||
error = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Done
|
||||
if (error != null)
|
||||
{
|
||||
System.err.println("Thread " + getName() + " failed to create file " + number + ":");
|
||||
System.err.flush();
|
||||
error.printStackTrace();
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.println("\t\t\tThread " + getName() + " created file: " + success.getName());
|
||||
System.out.flush();
|
||||
}
|
||||
// Tick the latch
|
||||
endLatch.countDown();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,742 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.model.filefolder;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.content.transform.AbstractContentTransformerTest;
|
||||
import org.alfresco.repo.dictionary.DictionaryDAO;
|
||||
import org.alfresco.repo.dictionary.M2Model;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
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.search.ResultSet;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.cmr.security.MutableAuthenticationService;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
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.alfresco.util.ArgumentHelper;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
/**
|
||||
* Tests around some of the data structures that lead to performance
|
||||
* degradation. We use the {@link org.alfresco.service.cmr.model.FileFolderService FileFolderService}
|
||||
* as it provides the most convenient and most common test scenarios.
|
||||
* <p>
|
||||
* Note that this test is not designed to validate performance figures, but is
|
||||
* rather a handy tool for doing benchmarking. It is therefore not named <i>*Test</i> as is the
|
||||
* pattern for getting tests run by the continuous build.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class FileFolderPerformanceTester extends TestCase
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(FileFolderPerformanceTester.class);
|
||||
|
||||
protected static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
|
||||
|
||||
protected RetryingTransactionHelper retryingTransactionHelper;
|
||||
protected NodeService nodeService;
|
||||
|
||||
private AuthenticationComponent authenticationComponent;
|
||||
private FileFolderService fileFolderService;
|
||||
private SearchService searchService;
|
||||
private NamespaceService namespaceService;
|
||||
private NodeRef rootFolderRef;
|
||||
private File dataFile;
|
||||
|
||||
private String USERNAME = AuthenticationUtil.getAdminUserName(); // as admin
|
||||
//private String USERNAME = AuthenticationUtil.getSystemUserName(); // as system (bypass permissions)
|
||||
|
||||
|
||||
protected NodeService getNodeService()
|
||||
{
|
||||
return (NodeService)ctx.getBean("NodeService");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||
retryingTransactionHelper = (RetryingTransactionHelper) ctx.getBean("retryingTransactionHelper");
|
||||
authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
|
||||
|
||||
fileFolderService = serviceRegistry.getFileFolderService();
|
||||
searchService = serviceRegistry.getSearchService();
|
||||
namespaceService = serviceRegistry.getNamespaceService();
|
||||
nodeService = getNodeService();
|
||||
|
||||
authenticate(USERNAME);
|
||||
|
||||
rootFolderRef = getOrCreateRootFolder();
|
||||
|
||||
dataFile = AbstractContentTransformerTest.loadQuickTestFile("txt");
|
||||
}
|
||||
|
||||
|
||||
private void authenticate(String userName)
|
||||
{
|
||||
if (AuthenticationUtil.getSystemUserName().equals(userName))
|
||||
{
|
||||
authenticationComponent.setSystemUserAsCurrentUser();
|
||||
}
|
||||
else
|
||||
{
|
||||
authenticationComponent.setCurrentUser(userName);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSetUp() throws Exception
|
||||
{
|
||||
assertNotNull(dataFile);
|
||||
}
|
||||
|
||||
protected NodeRef getOrCreateRootFolder()
|
||||
{
|
||||
// find the company home folder
|
||||
StoreRef storeRef = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore");
|
||||
NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
|
||||
List<NodeRef> results = searchService.selectNodes(
|
||||
storeRootNodeRef,
|
||||
"/app:company_home",
|
||||
null,
|
||||
namespaceService,
|
||||
false,
|
||||
SearchService.LANGUAGE_XPATH);
|
||||
if (results.size() == 0)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Didn't find Company Home");
|
||||
}
|
||||
NodeRef companyHomeNodeRef = results.get(0);
|
||||
return fileFolderService.create(
|
||||
companyHomeNodeRef,
|
||||
getName() + "_" + System.currentTimeMillis(),
|
||||
ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates <code>folderCount</code> folders below the given parent and populates each folder with
|
||||
* <code>fileCount</code> files. The folders will be created as siblings in one go, but the files
|
||||
* are added one to each folder until each folder has the presribed number of files within it.
|
||||
* This can therefore be used to test the performance when the L2 cache sizes are exceeded.
|
||||
* <p>
|
||||
* Each creation (file or folder) uses the <b>PROPAGATION REQUIRED</b> transaction declaration.
|
||||
*
|
||||
* @param parentNodeRef the level zero parent
|
||||
* @param randomOrder true if each thread must put the children into the folders in a random order
|
||||
* @return Returns the average time (ms) to create the <b>files only</b>
|
||||
*/
|
||||
private void buildStructure(
|
||||
final NodeRef parentNodeRef,
|
||||
final int threadCount,
|
||||
final boolean randomOrder,
|
||||
final int folderCount,
|
||||
final int batchCount,
|
||||
final int filesPerBatch,
|
||||
final double[] dumpPoints)
|
||||
{
|
||||
RetryingTransactionCallback<NodeRef[]> createFoldersCallback = new RetryingTransactionCallback<NodeRef[]>()
|
||||
{
|
||||
public NodeRef[] execute() throws Exception
|
||||
{
|
||||
NodeRef[] folders = new NodeRef[folderCount];
|
||||
for (int i = 0; i < folderCount; i++)
|
||||
{
|
||||
FileInfo folderInfo = fileFolderService.create(
|
||||
parentNodeRef,
|
||||
GUID.generate(),
|
||||
ContentModel.TYPE_FOLDER);
|
||||
// keep the reference
|
||||
folders[i] = folderInfo.getNodeRef();
|
||||
}
|
||||
return folders;
|
||||
}
|
||||
};
|
||||
final NodeRef[] folders = retryingTransactionHelper.doInTransaction(createFoldersCallback);
|
||||
// the worker that will load the files into the folders
|
||||
Runnable runnable = new Runnable()
|
||||
{
|
||||
private long start;
|
||||
public void run()
|
||||
{
|
||||
// authenticate
|
||||
authenticate(USERNAME);
|
||||
|
||||
// progress around the folders until they have been populated
|
||||
start = System.currentTimeMillis();
|
||||
int nextDumpNumber = 0;
|
||||
for (int i = 0; i < batchCount; i++)
|
||||
{
|
||||
// must we dump results
|
||||
double completedCount = (double) i;
|
||||
double nextDumpCount = (dumpPoints == null || dumpPoints.length == 0 || nextDumpNumber >= dumpPoints.length)
|
||||
? -1.0
|
||||
: (double) batchCount * dumpPoints[nextDumpNumber];
|
||||
if ((nextDumpCount - 0.5) < completedCount && completedCount < (nextDumpCount + 0.5))
|
||||
{
|
||||
dumpResults(i);
|
||||
nextDumpNumber++;
|
||||
}
|
||||
// shuffle folders if required
|
||||
List<NodeRef> foldersList = Arrays.asList(folders);
|
||||
if (randomOrder)
|
||||
{
|
||||
// shuffle folder list
|
||||
Collections.shuffle(foldersList);
|
||||
}
|
||||
for (int j = 0; j < folders.length; j++)
|
||||
{
|
||||
final NodeRef folderRef = folders[j];
|
||||
RetryingTransactionCallback<Void> createFileCallback = new RetryingTransactionCallback<Void>()
|
||||
{
|
||||
public Void execute() throws Exception
|
||||
{
|
||||
for (int i = 0; i < filesPerBatch; i++)
|
||||
{
|
||||
FileInfo fileInfo = fileFolderService.create(
|
||||
folderRef,
|
||||
GUID.generate(),
|
||||
ContentModel.TYPE_CONTENT);
|
||||
NodeRef nodeRef = fileInfo.getNodeRef();
|
||||
// write the content
|
||||
ContentWriter writer = fileFolderService.getWriter(nodeRef);
|
||||
writer.setEncoding("UTF-8");
|
||||
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
|
||||
writer.putContent(dataFile);
|
||||
}
|
||||
// done
|
||||
return null;
|
||||
}
|
||||
};
|
||||
retryingTransactionHelper.doInTransaction(createFileCallback);
|
||||
}
|
||||
}
|
||||
dumpResults(batchCount);
|
||||
}
|
||||
private void dumpResults(int currentBatchCount)
|
||||
{
|
||||
long end = System.currentTimeMillis();
|
||||
long time = (end - start);
|
||||
double average = (double) time / (double) (folderCount * currentBatchCount * filesPerBatch);
|
||||
double percentComplete = (double) currentBatchCount / (double) batchCount * 100.0;
|
||||
|
||||
if (percentComplete > 0)
|
||||
{
|
||||
logger.debug("\n" +
|
||||
"[" + Thread.currentThread().getName() + "] \n" +
|
||||
" Created " + (currentBatchCount*filesPerBatch) + " files in each of " + folderCount +
|
||||
" folders (" + (randomOrder ? "shuffled" : "in order") + "): \n" +
|
||||
" Progress: " + String.format("%9.2f", percentComplete) + " percent complete \n" +
|
||||
" Average: " + String.format("%10.2f", average) + " ms per file \n" +
|
||||
" Average: " + String.format("%10.2f", 1000.0/average) + " files per second");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// kick off the required number of threads
|
||||
logger.debug("\n" +
|
||||
"Starting " + threadCount +
|
||||
" threads loading " + (batchCount * filesPerBatch) +
|
||||
" files in each of " + folderCount +
|
||||
" folders (" +
|
||||
(randomOrder ? "shuffled" : "in order") +
|
||||
(filesPerBatch > 1 ? (" and " + filesPerBatch + " files per txn") : "") +
|
||||
").");
|
||||
ThreadGroup threadGroup = new ThreadGroup(getName());
|
||||
Thread[] threads = new Thread[threadCount];
|
||||
for (int i = 0; i < threadCount; i++)
|
||||
{
|
||||
threads[i] = new Thread(threadGroup, runnable, String.format("FileLoader-%02d", i));
|
||||
threads[i].start();
|
||||
}
|
||||
// join each thread so that we wait for them all to finish
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
threads[i].join();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
// not too serious - the worker threads are non-daemon
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readStructure(
|
||||
final NodeRef parentNodeRef,
|
||||
final int threadCount,
|
||||
final int repetitions,
|
||||
final double[] dumpPoints)
|
||||
{
|
||||
final List<FileInfo> children = fileFolderService.list(parentNodeRef);
|
||||
Runnable runnable = new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
// authenticate
|
||||
authenticate(USERNAME);
|
||||
|
||||
for (int i = 0; i < repetitions; i++)
|
||||
{
|
||||
// read the contents of each folder
|
||||
for (final FileInfo fileInfo : children)
|
||||
{
|
||||
final NodeRef folderRef = fileInfo.getNodeRef();
|
||||
RetryingTransactionCallback<Object> readCallback = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public Object execute() throws Exception
|
||||
{
|
||||
List<FileInfo> tmp = null;
|
||||
if (fileInfo.isFolder())
|
||||
{
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
// read the children of the folder
|
||||
tmp = fileFolderService.list(folderRef);
|
||||
|
||||
logger.debug("List "+tmp.size()+" items in "+(System.currentTimeMillis()-start)+" msecs");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not a folder: "+folderRef);
|
||||
}
|
||||
// done
|
||||
return null;
|
||||
};
|
||||
};
|
||||
retryingTransactionHelper.doInTransaction(readCallback, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// kick off the required number of threads
|
||||
logger.debug("\n" +
|
||||
"Starting " + threadCount +
|
||||
" threads reading properties and children of " + children.size() +
|
||||
" folders " + repetitions +
|
||||
" times.");
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
ThreadGroup threadGroup = new ThreadGroup(getName());
|
||||
Thread[] threads = new Thread[threadCount];
|
||||
for (int i = 0; i < threadCount; i++)
|
||||
{
|
||||
threads[i] = new Thread(threadGroup, runnable, String.format("FileReader-%02d", i));
|
||||
threads[i].start();
|
||||
}
|
||||
// join each thread so that we wait for them all to finish
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
threads[i].join();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
// not too serious - the worker threads are non-daemon
|
||||
}
|
||||
}
|
||||
logger.debug("\nFinished reading in "+(System.currentTimeMillis()-start)+" msecs");
|
||||
}
|
||||
|
||||
/*
|
||||
// Load and read: 100 ordered files (into 1 folder) using 1 thread
|
||||
public void test_1_ordered_1_1_100() throws Exception
|
||||
{
|
||||
buildStructure(rootFolderRef, 1, false, 1, 1, 100, new double[] {0.25, 0.50, 0.75});
|
||||
readStructure(rootFolderRef, 1, 3, new double[] {0.25, 0.50, 0.75});
|
||||
}
|
||||
|
||||
// Load and read: 300 ordered files per folder (into 2 folders) using 1 thread
|
||||
public void test_1_ordered_2_3_100() throws Exception
|
||||
{
|
||||
buildStructure(rootFolderRef, 1, false, 2, 3, 100, new double[] {0.25, 0.50, 0.75});
|
||||
readStructure(rootFolderRef, 1, 3, new double[] {0.25, 0.50, 0.75});
|
||||
}
|
||||
|
||||
// Load and read: 5000 files per folder (into 1 folder) using 2 threads
|
||||
public void test_2_ordered_1_2500_1() throws Exception
|
||||
{
|
||||
buildStructure(rootFolderRef, 2, false, 1, 2500, 1, new double[] {0.25, 0.50, 0.75});
|
||||
readStructure(rootFolderRef, 2, 3, new double[] {0.25, 0.50, 0.75});
|
||||
}
|
||||
|
||||
// Load and read: 10000 files per folder (into 1 folder) using 2 threads
|
||||
public void test_2_ordered_1_10_500() throws Exception
|
||||
{
|
||||
buildStructure(rootFolderRef, 2, false, 1, 10, 500, new double[] {0.25, 0.50, 0.75});
|
||||
readStructure(rootFolderRef, 2, 3, new double[] {0.25, 0.50, 0.75}); // note: will list each folder up to configured max items (eg. default 5000)
|
||||
}
|
||||
|
||||
// Load and read: 1000 ordered files per folder (into 10 folders) using 4 threads
|
||||
public void test_1_ordered_10_1_100() throws Exception
|
||||
{
|
||||
buildStructure(rootFolderRef, 1, false, 10, 1, 100, new double[] {0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90});
|
||||
readStructure(rootFolderRef, 1, 3, new double[] {0.25, 0.50, 0.75});
|
||||
}
|
||||
|
||||
// Load and read: 4000 ordered files per folder (into 10 folders) using 4 threads
|
||||
public void test_4_ordered_10_1_100() throws Exception
|
||||
{
|
||||
buildStructure(rootFolderRef, 4, false, 10, 1, 100, new double[] {0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90});
|
||||
readStructure(rootFolderRef, 4, 3, new double[] {0.25, 0.50, 0.75});
|
||||
}
|
||||
|
||||
// Load and read: 4000 shuffled files per folder (into 10 folders) using 4 threads
|
||||
public void test_4_shuffled_10_1_100() throws Exception
|
||||
{
|
||||
buildStructure(rootFolderRef, 4, true, 10, 1, 100, new double[] {0.25, 0.50, 0.75});
|
||||
readStructure(rootFolderRef, 4, 1, new double[] {0.25, 0.50, 0.75});
|
||||
}
|
||||
|
||||
// Load: 100 shuffled files per folder (into 100 folders) using 1 thread
|
||||
public void test_1_ordered_100_1_100() throws Exception
|
||||
{
|
||||
buildStructure(
|
||||
rootFolderRef,
|
||||
1,
|
||||
false,
|
||||
100,
|
||||
1,
|
||||
100,
|
||||
new double[] {0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90});
|
||||
readStructure(rootFolderRef, 1, 1, new double[] {0.25, 0.50, 0.75});
|
||||
}
|
||||
|
||||
// Load: 400 shuffled files per folder (into 10 folders) using 1 thread
|
||||
public void test_1_shuffled_10_1_400() throws Exception
|
||||
{
|
||||
buildStructure(
|
||||
rootFolderRef,
|
||||
1,
|
||||
true,
|
||||
10,
|
||||
1,
|
||||
400,
|
||||
new double[] {0.05, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90});
|
||||
|
||||
readStructure(rootFolderRef, 1, 1, new double[] {0.25, 0.50, 0.75});
|
||||
}
|
||||
*/
|
||||
// Load: 800 ordered files per folder (into 3 folders) using 4 threads
|
||||
public void test_4_ordered_3_2_100() throws Exception
|
||||
{
|
||||
buildStructure(
|
||||
rootFolderRef,
|
||||
4,
|
||||
false,
|
||||
3,
|
||||
2,
|
||||
100,
|
||||
new double[] {0.05, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90});
|
||||
|
||||
System.out.println("rootFolderRef: "+rootFolderRef);
|
||||
|
||||
readStructure(rootFolderRef, 4, 5, new double[] {0.25, 0.50, 0.75});
|
||||
}
|
||||
|
||||
// Load: 800 shuffled files per folder (into 3 folders) using 4 threads
|
||||
public void test_4_shuffled_3_2_100() throws Exception
|
||||
{
|
||||
buildStructure(
|
||||
rootFolderRef,
|
||||
4,
|
||||
true,
|
||||
3,
|
||||
2,
|
||||
100,
|
||||
new double[] {0.05, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90});
|
||||
|
||||
System.out.println("rootFolderRef: "+rootFolderRef);
|
||||
|
||||
readStructure(rootFolderRef, 4, 5, new double[] {0.25, 0.50, 0.75});
|
||||
}
|
||||
|
||||
/*
|
||||
// Load: 50000 ordered files per folder (into 1 folder) using 1 thread
|
||||
public void test_1_ordered_1_5000_10() throws Exception
|
||||
{
|
||||
buildStructure(
|
||||
rootFolderRef,
|
||||
1,
|
||||
false,
|
||||
1,
|
||||
5000,
|
||||
10,
|
||||
new double[] {0.01, 0.02, 0.03, 0.04, 0.05, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90});
|
||||
|
||||
readStructure(rootFolderRef, 1, 1, new double[] {0.25, 0.50, 0.75});
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a bunch of files and folders in a folder and then run multi-threaded directory
|
||||
* listings against it.
|
||||
*
|
||||
* @param args <x> <y> where 'x' is the number of files in a folder and 'y' is the
|
||||
* number of threads to list
|
||||
*/
|
||||
public static void main(String ... args)
|
||||
{
|
||||
ConfigurableApplicationContext ctx = (ConfigurableApplicationContext) ApplicationContextHelper.getApplicationContext();
|
||||
|
||||
try
|
||||
{
|
||||
run(ctx, args);
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
System.out.println("Failed to run FileFolder performance test");
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally
|
||||
{
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static void run(final ApplicationContext ctx, String ... args) throws Throwable
|
||||
{
|
||||
ArgumentHelper argHelper = new ArgumentHelper(getUsage(), args);
|
||||
final int fileCount = argHelper.getIntegerValue("files", true, 1, 10000);
|
||||
final String folderRefStr = argHelper.getStringValue("folder", false, true);
|
||||
final int threadCount = argHelper.getIntegerValue("threads", false, 1, 100);
|
||||
final NodeRef selectedFolderNodeRef = folderRefStr == null ? null : new NodeRef(folderRefStr);
|
||||
|
||||
ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||
final MutableAuthenticationService authenticationService = serviceRegistry.getAuthenticationService();
|
||||
final PermissionService permissionService = serviceRegistry.getPermissionService();
|
||||
final NodeService nodeService = serviceRegistry.getNodeService();
|
||||
final SearchService searchService = serviceRegistry.getSearchService();
|
||||
final TransactionService transactionService = serviceRegistry.getTransactionService();
|
||||
final FileFolderService fileFolderService = serviceRegistry.getFileFolderService();
|
||||
|
||||
RunAsWork<String> createUserRunAs = new RunAsWork<String>()
|
||||
{
|
||||
public String doWork() throws Exception
|
||||
{
|
||||
String user = GUID.generate();
|
||||
authenticationService.createAuthentication(user, user.toCharArray());
|
||||
return user;
|
||||
}
|
||||
};
|
||||
final String user = AuthenticationUtil.runAs(createUserRunAs, AuthenticationUtil.getSystemUserName());
|
||||
|
||||
// Create the files
|
||||
final RetryingTransactionCallback<NodeRef> createCallback = new RetryingTransactionCallback<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
AuthenticationUtil.pushAuthentication();
|
||||
|
||||
DictionaryDAO dictionaryDao = (DictionaryDAO) ctx.getBean("dictionaryDAO");
|
||||
M2Model model = M2Model.createModel("tempModel");
|
||||
model.createNamespace("test", "t");
|
||||
model.createNamespace("testx", "");
|
||||
for (int m = 0; m < 30; m++)
|
||||
{
|
||||
model.createAspect("t:aspect_" + m);
|
||||
}
|
||||
dictionaryDao.putModel(model);
|
||||
|
||||
NodeRef folderNodeRef = null;
|
||||
try
|
||||
{
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
|
||||
if (selectedFolderNodeRef == null)
|
||||
{
|
||||
// find the guest folder
|
||||
StoreRef storeRef = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore");
|
||||
ResultSet rs = searchService.query(storeRef, SearchService.LANGUAGE_XPATH, "/app:company_home");
|
||||
try
|
||||
{
|
||||
if (rs.length() == 0)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Didn't find Company Home");
|
||||
}
|
||||
NodeRef companyHomeNodeRef = rs.getNodeRef(0);
|
||||
folderNodeRef = fileFolderService.create(
|
||||
companyHomeNodeRef,
|
||||
"TOP_FOLDER_" + System.currentTimeMillis(),
|
||||
ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
System.out.println("Created folder " + folderNodeRef + " with user " + user);
|
||||
}
|
||||
finally
|
||||
{
|
||||
rs.close();
|
||||
}
|
||||
// Grant permissions
|
||||
permissionService.setPermission(folderNodeRef, user, PermissionService.ALL_PERMISSIONS, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
folderNodeRef = selectedFolderNodeRef;
|
||||
// Grant permissions
|
||||
permissionService.setPermission(folderNodeRef, user, PermissionService.ALL_PERMISSIONS, true);
|
||||
System.out.println("Reusing folder " + folderNodeRef + " with user " + user);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
AuthenticationUtil.popAuthentication();
|
||||
}
|
||||
if (selectedFolderNodeRef == null)
|
||||
{
|
||||
List<String> largeCollection = new ArrayList<String>(1000);
|
||||
for (int i = 0; i < 50; i++)
|
||||
{
|
||||
largeCollection.add(String.format("Large-collection-value-%05d", i));
|
||||
}
|
||||
|
||||
// Create the files
|
||||
for (int i = 0; i < fileCount; i++)
|
||||
{
|
||||
FileInfo fileInfo = fileFolderService.create(
|
||||
folderNodeRef,
|
||||
String.format("FILE-%4d", i),
|
||||
ContentModel.TYPE_CONTENT);
|
||||
NodeRef nodeRef = fileInfo.getNodeRef();
|
||||
nodeService.setProperty(
|
||||
nodeRef,
|
||||
QName.createQName("{test}mv"),
|
||||
(Serializable) largeCollection);
|
||||
for (int m = 0; m < 30; m++)
|
||||
{
|
||||
nodeService.addAspect(
|
||||
nodeRef,
|
||||
QName.createQName("{test}aspect_"+m), null);
|
||||
}
|
||||
// write the content
|
||||
ContentWriter writer = fileFolderService.getWriter(nodeRef);
|
||||
writer.setEncoding("UTF-8");
|
||||
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
|
||||
writer.putContent("Some small text data");
|
||||
}
|
||||
System.out.println("Created " + fileCount + " files in folder " + folderNodeRef);
|
||||
|
||||
}
|
||||
// Done
|
||||
return folderNodeRef;
|
||||
}
|
||||
};
|
||||
|
||||
RunAsWork<NodeRef> createRunAs = new RunAsWork<NodeRef>()
|
||||
{
|
||||
public NodeRef doWork() throws Exception
|
||||
{
|
||||
return transactionService.getRetryingTransactionHelper().doInTransaction(createCallback);
|
||||
}
|
||||
};
|
||||
final NodeRef folderNodeRef = AuthenticationUtil.runAs(createRunAs, user);
|
||||
|
||||
// Now wait for some input before commencing the read run
|
||||
System.out.print("Hit any key to commence directory listing ...");
|
||||
System.in.read();
|
||||
final RunAsWork<List<FileInfo>> readRunAs = new RunAsWork<List<FileInfo>>()
|
||||
{
|
||||
public List<FileInfo> doWork() throws Exception
|
||||
{
|
||||
return fileFolderService.list(folderNodeRef);
|
||||
}
|
||||
};
|
||||
|
||||
Thread[] threads = new Thread[threadCount];
|
||||
for (int i = 0; i < threadCount; i++)
|
||||
{
|
||||
Thread readThread = new Thread("FolderList-" + i)
|
||||
{
|
||||
int iteration = 0;
|
||||
public void run()
|
||||
{
|
||||
while(++iteration <= 2)
|
||||
{
|
||||
runImpl();
|
||||
}
|
||||
}
|
||||
private void runImpl()
|
||||
{
|
||||
String threadName = Thread.currentThread().getName();
|
||||
long start = System.currentTimeMillis();
|
||||
List<FileInfo> nodeRefs = AuthenticationUtil.runAs(readRunAs, user);
|
||||
long time = System.currentTimeMillis() - start;
|
||||
double average = (double) time / (double) (fileCount);
|
||||
|
||||
// Make sure that we have the correct number of entries
|
||||
if (folderRefStr != null && nodeRefs.size() != fileCount)
|
||||
{
|
||||
System.err.println(
|
||||
"WARNING: Thread " + threadName + " got " + nodeRefs.size() +
|
||||
" but expected " + fileCount);
|
||||
}
|
||||
System.out.print("\n" +
|
||||
"Thread " + threadName + ": \n" +
|
||||
" Read " + String.format("%4d", fileCount) + " files \n" +
|
||||
" Average: " + String.format("%10.2f", average) + " ms per file \n" +
|
||||
" Average: " + String.format("%10.2f", 1000.0/average) + " files per second");
|
||||
}
|
||||
};
|
||||
readThread.start();
|
||||
threads[i] = readThread;
|
||||
}
|
||||
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
{
|
||||
threads[i].join();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getUsage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("FileFolderPerformanceTester usage: ").append("\n");
|
||||
sb.append(" FileFolderPerformanceTester --files=<filecount> --threads=<threadcount> --folder=<folderref>").append("\n");
|
||||
sb.append(" filecount: number of files in the folder").append("\n");
|
||||
sb.append(" threadcount: number of threads to do the directory listing").append("\n");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,853 @@
|
||||
package org.alfresco.repo.model.filefolder;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.transaction.NotSupportedException;
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.SystemException;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.dictionary.DictionaryNamespaceComponent;
|
||||
import org.alfresco.repo.domain.node.NodeDAO;
|
||||
import org.alfresco.repo.domain.node.NodeDAO.NodeRefQueryCallback;
|
||||
import org.alfresco.repo.imap.AlfrescoImapFolder;
|
||||
import org.alfresco.repo.imap.AlfrescoImapUser;
|
||||
import org.alfresco.repo.imap.ImapService;
|
||||
import org.alfresco.repo.model.filefolder.HiddenAspect.Visibility;
|
||||
import org.alfresco.repo.search.impl.lucene.LuceneQueryParser;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.model.FileExistsException;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
|
||||
import org.alfresco.service.cmr.repository.MLText;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.search.ResultSet;
|
||||
import org.alfresco.service.cmr.search.SearchParameters;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.cmr.security.MutableAuthenticationService;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
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.alfresco.util.FileFilterMode;
|
||||
import org.alfresco.util.FileFilterMode.Client;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.PropertyMap;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestName;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
public class HiddenAspectTest
|
||||
{
|
||||
@Rule public TestName name = new TestName();
|
||||
|
||||
private static final ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
|
||||
|
||||
private HiddenAspect hiddenAspect;
|
||||
private TransactionService transactionService;
|
||||
private NodeDAO nodeDAO;
|
||||
private NodeService nodeService;
|
||||
private FileFolderService fileFolderService;
|
||||
private MutableAuthenticationService authenticationService;
|
||||
private PermissionService permissionService;
|
||||
private UserTransaction txn;
|
||||
|
||||
private SearchService searchService;
|
||||
private DictionaryNamespaceComponent namespacePrefixResolver;
|
||||
private ImapService imapService;
|
||||
private PersonService personService;
|
||||
private FilenameFilteringInterceptor interceptor;
|
||||
|
||||
private StoreRef storeRef;
|
||||
private NodeRef rootNodeRef;
|
||||
private NodeRef topNodeRef;
|
||||
|
||||
private boolean imapEnabled;
|
||||
|
||||
private final String MAILBOX_NAME_A = "mailbox_a";
|
||||
private final String MAILBOX_NAME_B = ".mailbox_a";
|
||||
private String username;
|
||||
private AlfrescoImapUser user;
|
||||
|
||||
@Before
|
||||
public void setup() throws SystemException, NotSupportedException
|
||||
{
|
||||
ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean("ServiceRegistry");
|
||||
transactionService = serviceRegistry.getTransactionService();
|
||||
nodeService = serviceRegistry.getNodeService();
|
||||
fileFolderService = serviceRegistry.getFileFolderService();
|
||||
authenticationService = (MutableAuthenticationService) ctx.getBean("AuthenticationService");
|
||||
hiddenAspect = (HiddenAspect) ctx.getBean("hiddenAspect");
|
||||
interceptor = (FilenameFilteringInterceptor) ctx.getBean("filenameFilteringInterceptor");
|
||||
namespacePrefixResolver = (DictionaryNamespaceComponent) ctx.getBean("namespaceService");
|
||||
imapService = serviceRegistry.getImapService();
|
||||
personService = serviceRegistry.getPersonService();
|
||||
searchService = serviceRegistry.getSearchService();
|
||||
permissionService = serviceRegistry.getPermissionService();
|
||||
imapEnabled = serviceRegistry.getImapService().getImapServerEnabled();
|
||||
|
||||
nodeDAO = (NodeDAO)ctx.getBean("nodeDAO");
|
||||
|
||||
// start the transaction
|
||||
txn = transactionService.getUserTransaction();
|
||||
txn.begin();
|
||||
|
||||
username = "user" + System.currentTimeMillis();
|
||||
|
||||
PropertyMap testUser = new PropertyMap();
|
||||
testUser.put(ContentModel.PROP_USERNAME, username);
|
||||
testUser.put(ContentModel.PROP_FIRSTNAME, username);
|
||||
testUser.put(ContentModel.PROP_LASTNAME, username);
|
||||
testUser.put(ContentModel.PROP_EMAIL, username + "@alfresco.com");
|
||||
testUser.put(ContentModel.PROP_JOBTITLE, "jobTitle");
|
||||
|
||||
// authenticate
|
||||
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
|
||||
|
||||
personService.createPerson(testUser);
|
||||
|
||||
// create the ACEGI Authentication instance for the new user
|
||||
authenticationService.createAuthentication(username, username.toCharArray());
|
||||
|
||||
user = new AlfrescoImapUser(username + "@alfresco.com", username, username);
|
||||
|
||||
// create a test store
|
||||
storeRef = nodeService
|
||||
.createStore(StoreRef.PROTOCOL_WORKSPACE, getName() + System.currentTimeMillis());
|
||||
rootNodeRef = nodeService.getRootNode(storeRef);
|
||||
permissionService.setPermission(rootNodeRef, username, PermissionService.CREATE_CHILDREN, true);
|
||||
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(username);
|
||||
|
||||
topNodeRef = nodeService.createNode(
|
||||
rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "working root"),
|
||||
ContentModel.TYPE_FOLDER).getChildRef();
|
||||
|
||||
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
|
||||
}
|
||||
|
||||
private String getName()
|
||||
{
|
||||
return name.getMethodName();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
if (txn.getStatus() != Status.STATUS_ROLLEDBACK && txn.getStatus() != Status.STATUS_COMMITTED)
|
||||
{
|
||||
txn.commit();
|
||||
}
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHiddenFilesEnhancedClient()
|
||||
{
|
||||
FileFilterMode.setClient(Client.webdav);
|
||||
|
||||
try
|
||||
{
|
||||
// check temporary file
|
||||
NodeRef parent = fileFolderService.create(topNodeRef, "New Folder", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
NodeRef child = fileFolderService.create(parent, "file.tmp", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
assertTrue(nodeService.hasAspect(child, ContentModel.ASPECT_TEMPORARY));
|
||||
assertFalse(nodeService.hasAspect(child, ContentModel.ASPECT_HIDDEN));
|
||||
List<FileInfo> children = fileFolderService.list(parent);
|
||||
assertEquals(1, children.size());
|
||||
|
||||
// check hidden files - should be hidden for an enhanced client
|
||||
parent = fileFolderService.create(topNodeRef, "abc", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
child = fileFolderService.create(parent, ".TemporaryItems", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
NodeRef child1 = fileFolderService.create(child, "inTemporaryItems", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
assertTrue(nodeService.hasAspect(child, ContentModel.ASPECT_TEMPORARY));
|
||||
assertTrue(nodeService.hasAspect(child, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(child, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertTrue(nodeService.hasAspect(child1, ContentModel.ASPECT_TEMPORARY));
|
||||
assertTrue(nodeService.hasAspect(child1, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(child1, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
ResultSet results = searchForName(".TemporaryItems");
|
||||
assertEquals("", 0, results.length());
|
||||
|
||||
children = fileFolderService.list(parent);
|
||||
assertEquals(1, children.size());
|
||||
|
||||
Client saveClient = FileFilterMode.setClient(Client.script);
|
||||
try
|
||||
{
|
||||
children = fileFolderService.list(parent);
|
||||
}
|
||||
finally
|
||||
{
|
||||
FileFilterMode.setClient(saveClient);
|
||||
}
|
||||
assertEquals(0, children.size());
|
||||
|
||||
parent = fileFolderService.create(topNodeRef, "Folder 2", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
child = fileFolderService.create(parent, "Thumbs.db", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
assertFalse(nodeService.hasAspect(child, ContentModel.ASPECT_TEMPORARY));
|
||||
assertTrue(nodeService.hasAspect(child, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(child, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
results = searchForName("Thumbs.db");
|
||||
assertEquals("", 0, results.length());
|
||||
children = fileFolderService.list(parent);
|
||||
assertEquals(1, children.size());
|
||||
// set hidden attribute for cifs, webdav. ftp, nfs should be able to see, other clients not
|
||||
assertEquals(Visibility.Visible, hiddenAspect.getVisibility(Client.ftp, child));
|
||||
assertEquals(Visibility.Visible, hiddenAspect.getVisibility(Client.nfs, child));
|
||||
assertEquals(Visibility.Visible, hiddenAspect.getVisibility(Client.webdav, child));
|
||||
assertEquals(Visibility.HiddenAttribute, hiddenAspect.getVisibility(Client.cifs, child));
|
||||
assertEquals(Visibility.NotVisible, hiddenAspect.getVisibility(Client.script, child));
|
||||
assertEquals(Visibility.NotVisible, hiddenAspect.getVisibility(Client.webclient, child));
|
||||
|
||||
// surf-config should not be visible to any client
|
||||
NodeRef node = fileFolderService.create(topNodeRef, "surf-config", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
assertTrue(nodeService.hasAspect(node, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(node, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
results = searchForName("surf-config");
|
||||
assertEquals("", 0, results.length());
|
||||
for(Client client : hiddenAspect.getClients())
|
||||
{
|
||||
if(!client.equals(Client.admin))
|
||||
{
|
||||
assertEquals(Visibility.NotVisible, hiddenAspect.getVisibility(client, node));
|
||||
}
|
||||
}
|
||||
|
||||
// .DS_Store is a system path and so is visible in nfs and webdav, as a hidden file in cifs and hidden to all other clients
|
||||
node = fileFolderService.create(topNodeRef, ".DS_Store", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
assertTrue(nodeService.hasAspect(node, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(node, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
results = searchForName(".DS_Store");
|
||||
assertEquals("", 0, results.length());
|
||||
for(Client client : hiddenAspect.getClients())
|
||||
{
|
||||
if(client == Client.cifs)
|
||||
{
|
||||
assertEquals("Should have hidden attribute set for client " + client, Visibility.HiddenAttribute, hiddenAspect.getVisibility(client, node));
|
||||
}
|
||||
else if(client == Client.webdav || client == Client.nfs || client == Client.ftp)
|
||||
{
|
||||
assertEquals("Should be visible for client " + client, Visibility.Visible, hiddenAspect.getVisibility(client, node));
|
||||
}
|
||||
else if(client != Client.admin)
|
||||
{
|
||||
assertEquals("Should not be visible for client " + client, Visibility.NotVisible, hiddenAspect.getVisibility(client, node));
|
||||
}
|
||||
}
|
||||
|
||||
// Resource fork should not be visible to any client
|
||||
node = fileFolderService.create(topNodeRef, "._resourceFork", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
assertTrue(nodeService.hasAspect(node, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(node, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
results = searchForName("._resourceFork");
|
||||
assertEquals("", 0, results.length());
|
||||
for(Client client : hiddenAspect.getClients())
|
||||
{
|
||||
if(client != Client.admin)
|
||||
{
|
||||
assertEquals("Client " + client.toString(), Visibility.NotVisible, hiddenAspect.getVisibility(client, node));
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
FileFilterMode.clearClient();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientControlled() throws Exception
|
||||
{
|
||||
// test that a client controlled hidden node is not subject to hidden file patterns
|
||||
{
|
||||
// node does not match a hidden file pattern
|
||||
String nodeName = GUID.generate();
|
||||
String hiddenNodeName = nodeName;
|
||||
Map<QName, Serializable> properties = new HashMap<QName, Serializable>(11);
|
||||
properties.put(ContentModel.PROP_NAME, hiddenNodeName);
|
||||
|
||||
// create the node
|
||||
QName assocQName = QName.createQName(
|
||||
NamespaceService.CONTENT_MODEL_1_0_URI,
|
||||
QName.createValidLocalName(hiddenNodeName));
|
||||
ChildAssociationRef assocRef = null;
|
||||
try
|
||||
{
|
||||
assocRef = nodeService.createNode(
|
||||
topNodeRef,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
assocQName,
|
||||
ContentModel.TYPE_FOLDER,
|
||||
properties);
|
||||
}
|
||||
catch (DuplicateChildNodeNameException e)
|
||||
{
|
||||
throw new FileExistsException(topNodeRef, hiddenNodeName);
|
||||
}
|
||||
|
||||
NodeRef parent = assocRef.getChildRef();
|
||||
NodeRef child = null;
|
||||
NodeRef child1 = null;
|
||||
|
||||
Client saveClient = FileFilterMode.setClient(Client.cmis);
|
||||
try
|
||||
{
|
||||
hiddenAspect.hideNode(parent, true, true, true);
|
||||
|
||||
child = fileFolderService.create(parent, "folder11", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
child1 = fileFolderService.create(child, "folder21", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
assertTrue(nodeService.hasAspect(child, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(child, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertTrue(nodeService.hasAspect(child1, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(child1, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
|
||||
// renaming from a hidden file pattern to a non-hidden file pattern should leave the node as hidden
|
||||
// because it is client-controlled.
|
||||
fileFolderService.rename(parent, nodeName);
|
||||
|
||||
assertTrue(nodeService.hasAspect(parent, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(parent, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertTrue(nodeService.hasAspect(child, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(child, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertTrue(nodeService.hasAspect(child1, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(child1, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
}
|
||||
finally
|
||||
{
|
||||
FileFilterMode.setClient(saveClient);
|
||||
}
|
||||
|
||||
List<FileInfo> children = fileFolderService.list(parent);
|
||||
assertEquals(0, children.size());
|
||||
|
||||
saveClient = FileFilterMode.setClient(Client.script);
|
||||
try
|
||||
{
|
||||
children = fileFolderService.list(parent);
|
||||
}
|
||||
finally
|
||||
{
|
||||
FileFilterMode.setClient(saveClient);
|
||||
}
|
||||
assertEquals(0, children.size());
|
||||
|
||||
saveClient = FileFilterMode.setClient(Client.cmis);
|
||||
try
|
||||
{
|
||||
children = fileFolderService.list(parent);
|
||||
}
|
||||
finally
|
||||
{
|
||||
FileFilterMode.setClient(saveClient);
|
||||
}
|
||||
assertEquals(0, children.size());
|
||||
|
||||
// remove the client-controlled hidden aspect from the parent and check that it is no longer hidden
|
||||
saveClient = FileFilterMode.setClient(Client.cmis);
|
||||
try
|
||||
{
|
||||
nodeService.removeAspect(parent, ContentModel.ASPECT_HIDDEN);
|
||||
|
||||
assertFalse(nodeService.hasAspect(parent, ContentModel.ASPECT_HIDDEN));
|
||||
}
|
||||
finally
|
||||
{
|
||||
FileFilterMode.setClient(saveClient);
|
||||
}
|
||||
}
|
||||
|
||||
// test that a cascading hidden pattern defined in model-specific-services-content.xml results in hidden files
|
||||
// (node is not client-controlled hidden)
|
||||
{
|
||||
NodeRef parent = null;
|
||||
NodeRef child = null;
|
||||
NodeRef child1 = null;
|
||||
|
||||
Client saveClient = FileFilterMode.setClient(Client.cmis);
|
||||
try
|
||||
{
|
||||
parent = fileFolderService.create(topNodeRef, "." + GUID.generate(), ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
child = fileFolderService.create(parent, "folder11", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
child1 = fileFolderService.create(child, "folder21", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
}
|
||||
finally
|
||||
{
|
||||
FileFilterMode.setClient(saveClient);
|
||||
}
|
||||
|
||||
assertTrue(nodeService.hasAspect(child, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(child, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertTrue(nodeService.hasAspect(child1, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(child1, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
|
||||
List<FileInfo> children = fileFolderService.list(parent);
|
||||
assertEquals(0, children.size());
|
||||
|
||||
saveClient = FileFilterMode.setClient(Client.script);
|
||||
try
|
||||
{
|
||||
children = fileFolderService.list(parent);
|
||||
}
|
||||
finally
|
||||
{
|
||||
FileFilterMode.setClient(saveClient);
|
||||
}
|
||||
assertEquals(0, children.size());
|
||||
|
||||
saveClient = FileFilterMode.setClient(Client.cmis);
|
||||
try
|
||||
{
|
||||
children = fileFolderService.list(parent);
|
||||
}
|
||||
finally
|
||||
{
|
||||
FileFilterMode.setClient(saveClient);
|
||||
}
|
||||
assertEquals(0, children.size());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImap()
|
||||
{
|
||||
if(imapEnabled)
|
||||
{
|
||||
FileFilterMode.setClient(Client.webdav);
|
||||
|
||||
try
|
||||
{
|
||||
// Test that hidden files don't apply to imap service
|
||||
imapService.getOrCreateMailbox(user, MAILBOX_NAME_A, false, true);
|
||||
imapService.renameMailbox(user, MAILBOX_NAME_A, MAILBOX_NAME_B);
|
||||
assertFalse("Can't rename mailbox", checkMailbox(user, MAILBOX_NAME_A));
|
||||
assertTrue("Can't rename mailbox", checkMailbox(user, MAILBOX_NAME_B));
|
||||
assertEquals("Can't rename mailbox", 0, numMailboxes(user, MAILBOX_NAME_A));
|
||||
assertEquals("Can't rename mailbox", 1, numMailboxes(user, MAILBOX_NAME_B));
|
||||
}
|
||||
finally
|
||||
{
|
||||
FileFilterMode.clearClient();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRename()
|
||||
{
|
||||
FileFilterMode.setClient(Client.webdav);
|
||||
|
||||
try
|
||||
{
|
||||
// Test renaming
|
||||
String nodeName = GUID.generate();
|
||||
NodeRef node = fileFolderService.create(topNodeRef, nodeName, ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
NodeRef node11 = fileFolderService.create(node, nodeName + ".11", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
NodeRef node12 = fileFolderService.create(node, nodeName + ".12", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
NodeRef node21 = fileFolderService.create(node11, nodeName + ".21", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
NodeRef node22 = fileFolderService.create(node11, nodeName + ".22", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
NodeRef node31 = fileFolderService.create(node21, ".31", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
NodeRef node41 = fileFolderService.create(node31, nodeName + ".41", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
assertFalse(nodeService.hasAspect(node, ContentModel.ASPECT_HIDDEN));
|
||||
assertFalse(nodeService.hasAspect(node, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertFalse(nodeService.hasAspect(node11, ContentModel.ASPECT_HIDDEN));
|
||||
assertFalse(nodeService.hasAspect(node11, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertFalse(nodeService.hasAspect(node12, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertFalse(nodeService.hasAspect(node12, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertFalse(nodeService.hasAspect(node21, ContentModel.ASPECT_HIDDEN));
|
||||
assertFalse(nodeService.hasAspect(node21, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertFalse(nodeService.hasAspect(node22, ContentModel.ASPECT_HIDDEN));
|
||||
assertFalse(nodeService.hasAspect(node22, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertTrue(nodeService.hasAspect(node31, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(node31, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertTrue(nodeService.hasAspect(node41, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(node41, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
|
||||
ResultSet results = searchForName(nodeName);
|
||||
assertEquals("", 1, results.length());
|
||||
|
||||
try
|
||||
{
|
||||
fileFolderService.rename(node, "." + nodeName);
|
||||
}
|
||||
catch (FileExistsException e)
|
||||
{
|
||||
fail();
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
fail();
|
||||
}
|
||||
|
||||
assertTrue(nodeService.hasAspect(node, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(node, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertTrue(nodeService.hasAspect(node11, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(node11, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertTrue(nodeService.hasAspect(node12, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertTrue(nodeService.hasAspect(node12, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertTrue(nodeService.hasAspect(node21, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(node21, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertTrue(nodeService.hasAspect(node22, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(node22, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertTrue(nodeService.hasAspect(node31, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(node31, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertTrue(nodeService.hasAspect(node41, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(node41, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
|
||||
results = searchForName(nodeName);
|
||||
assertEquals("", 0, results.length());
|
||||
|
||||
results = searchForName("." + nodeName);
|
||||
assertEquals("", 0, results.length());
|
||||
|
||||
try
|
||||
{
|
||||
fileFolderService.rename(node, nodeName);
|
||||
}
|
||||
catch (FileExistsException e)
|
||||
{
|
||||
fail();
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
fail();
|
||||
}
|
||||
|
||||
assertFalse(nodeService.hasAspect(node, ContentModel.ASPECT_HIDDEN));
|
||||
assertFalse(nodeService.hasAspect(node, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertFalse(nodeService.hasAspect(node11, ContentModel.ASPECT_HIDDEN));
|
||||
assertFalse(nodeService.hasAspect(node11, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertFalse(nodeService.hasAspect(node12, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertFalse(nodeService.hasAspect(node12, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertFalse(nodeService.hasAspect(node21, ContentModel.ASPECT_HIDDEN));
|
||||
assertFalse(nodeService.hasAspect(node21, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertFalse(nodeService.hasAspect(node22, ContentModel.ASPECT_HIDDEN));
|
||||
assertFalse(nodeService.hasAspect(node22, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertTrue(nodeService.hasAspect(node31, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(node31, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertTrue(nodeService.hasAspect(node41, ContentModel.ASPECT_HIDDEN));
|
||||
assertTrue(nodeService.hasAspect(node41, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
|
||||
results = searchForName(nodeName);
|
||||
assertEquals("", 1, results.length());
|
||||
}
|
||||
finally
|
||||
{
|
||||
FileFilterMode.clearClient();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHiddenFilesBasicClient()
|
||||
{
|
||||
if(imapEnabled)
|
||||
{
|
||||
FileFilterMode.setClient(Client.imap);
|
||||
|
||||
try
|
||||
{
|
||||
// check temporary file
|
||||
NodeRef parent = fileFolderService.create(topNodeRef, "New Folder", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
NodeRef child = fileFolderService.create(parent, "file.tmp", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
assertTrue(nodeService.hasAspect(child, ContentModel.ASPECT_TEMPORARY));
|
||||
assertFalse(nodeService.hasAspect(child, ContentModel.ASPECT_HIDDEN));
|
||||
assertFalse(nodeService.hasAspect(child, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
ResultSet results = searchForName("file.tmp");
|
||||
assertEquals("", 1, results.length());
|
||||
List<FileInfo> children = fileFolderService.list(parent);
|
||||
assertEquals(1, children.size());
|
||||
|
||||
// check hidden files - should not be hidden for a basic client
|
||||
parent = fileFolderService.create(topNodeRef, ".TemporaryItems", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
child = fileFolderService.create(parent, "inTemporaryItems", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
assertFalse(nodeService.hasAspect(parent, ContentModel.ASPECT_TEMPORARY));
|
||||
assertFalse(nodeService.hasAspect(parent, ContentModel.ASPECT_HIDDEN));
|
||||
assertFalse(nodeService.hasAspect(parent, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
assertFalse(nodeService.hasAspect(child, ContentModel.ASPECT_TEMPORARY));
|
||||
assertFalse(nodeService.hasAspect(child, ContentModel.ASPECT_HIDDEN));
|
||||
assertFalse(nodeService.hasAspect(child, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
results = searchForName(".TemporaryItems");
|
||||
assertEquals("", 1, results.length());
|
||||
children = fileFolderService.list(parent);
|
||||
assertEquals(1, children.size());
|
||||
|
||||
parent = fileFolderService.create(topNodeRef, "Folder 2", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
child = fileFolderService.create(parent, "Thumbs.db", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
assertFalse(nodeService.hasAspect(child, ContentModel.ASPECT_TEMPORARY));
|
||||
assertFalse(nodeService.hasAspect(child, ContentModel.ASPECT_HIDDEN));
|
||||
assertFalse(nodeService.hasAspect(child, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
results = searchForName("Thumbs.db");
|
||||
assertEquals("", 1, results.length());
|
||||
children = fileFolderService.list(parent);
|
||||
assertEquals(1, children.size());
|
||||
|
||||
NodeRef node = fileFolderService.create(topNodeRef, "surf-config", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
assertFalse(nodeService.hasAspect(node, ContentModel.ASPECT_HIDDEN));
|
||||
assertFalse(nodeService.hasAspect(node, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
results = searchForName("surf-config");
|
||||
assertEquals("", 1, results.length());
|
||||
|
||||
node = fileFolderService.create(topNodeRef, ".DS_Store", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
assertFalse(nodeService.hasAspect(node, ContentModel.ASPECT_HIDDEN));
|
||||
assertFalse(nodeService.hasAspect(node, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
results = searchForName(".DS_Store");
|
||||
assertEquals("", 1, results.length());
|
||||
for(Client client : hiddenAspect.getClients())
|
||||
{
|
||||
assertEquals("Should be visible for client " + client, Visibility.Visible, hiddenAspect.getVisibility(client, node));
|
||||
}
|
||||
|
||||
node = fileFolderService.create(topNodeRef, "._resourceFork", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
assertFalse(nodeService.hasAspect(node, ContentModel.ASPECT_HIDDEN));
|
||||
assertFalse(nodeService.hasAspect(node, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
results = searchForName("._resourceFork");
|
||||
assertEquals("", 1, results.length());
|
||||
|
||||
children = fileFolderService.list(parent);
|
||||
assertEquals(1, children.size());
|
||||
|
||||
|
||||
String nodeName = "Node" + System.currentTimeMillis();
|
||||
node = fileFolderService.create(topNodeRef, nodeName, ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
assertFalse(nodeService.hasAspect(node, ContentModel.ASPECT_HIDDEN));
|
||||
assertFalse(nodeService.hasAspect(node, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
results = searchForName(nodeName);
|
||||
assertEquals("", 1, results.length());
|
||||
try
|
||||
{
|
||||
fileFolderService.rename(node, "." + nodeName);
|
||||
}
|
||||
catch (FileExistsException e)
|
||||
{
|
||||
fail();
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
fail();
|
||||
}
|
||||
assertFalse(nodeService.hasAspect(node, ContentModel.ASPECT_HIDDEN));
|
||||
assertFalse(nodeService.hasAspect(node, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
|
||||
results = searchForName(nodeName);
|
||||
assertEquals("", 1, results.length());
|
||||
|
||||
results = searchForName("." + nodeName);
|
||||
assertEquals("", 1, results.length());
|
||||
|
||||
try
|
||||
{
|
||||
fileFolderService.rename(node, nodeName);
|
||||
}
|
||||
catch (FileExistsException e)
|
||||
{
|
||||
fail();
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
fail();
|
||||
}
|
||||
assertFalse(nodeService.hasAspect(node, ContentModel.ASPECT_HIDDEN));
|
||||
assertFalse(nodeService.hasAspect(node, ContentModel.ASPECT_INDEX_CONTROL));
|
||||
|
||||
results = searchForName("." + nodeName);
|
||||
assertEquals("", 1, results.length());
|
||||
|
||||
imapService.getOrCreateMailbox(user, MAILBOX_NAME_A, false, true);
|
||||
imapService.renameMailbox(user, MAILBOX_NAME_A, MAILBOX_NAME_B);
|
||||
assertFalse("Can't rename mailbox", checkMailbox(user, MAILBOX_NAME_A));
|
||||
assertTrue("Can't rename mailbox", checkMailbox(user, MAILBOX_NAME_B));
|
||||
assertEquals("Can't rename mailbox", 0, numMailboxes(user, MAILBOX_NAME_A));
|
||||
assertEquals("Can't rename mailbox", 1, numMailboxes(user, MAILBOX_NAME_B));
|
||||
}
|
||||
finally
|
||||
{
|
||||
FileFilterMode.clearClient();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Test
|
||||
public void testCheckHidden() throws Exception
|
||||
{
|
||||
String nodeName = GUID.generate();
|
||||
|
||||
interceptor.setEnabled(false);
|
||||
|
||||
try
|
||||
{
|
||||
// Create some nodes that should be hidden but aren't
|
||||
NodeRef node = fileFolderService.create(topNodeRef, nodeName, ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
NodeRef node11 = fileFolderService.create(node, nodeName + ".11", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
NodeRef node12 = fileFolderService.create(node, ".12", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
NodeRef node21 = fileFolderService.create(node11, nodeName + ".21", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
NodeRef node22 = fileFolderService.create(node11, nodeName + ".22", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
NodeRef node31 = fileFolderService.create(node21, ".31", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
NodeRef node41 = fileFolderService.create(node31, nodeName + ".41", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
|
||||
assertEquals(1, searchForName(".12").length());
|
||||
assertEquals(1, searchForName(".31").length());
|
||||
assertEquals(1, searchForName(nodeName + ".41").length());
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
finally
|
||||
{
|
||||
interceptor.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testHideNodeExplicit() throws Exception
|
||||
{
|
||||
FileFilterMode.setClient(Client.cifs);
|
||||
try
|
||||
{
|
||||
// check temporary file
|
||||
NodeRef parent = fileFolderService.create(topNodeRef, "New Folder", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
NodeRef childA = fileFolderService.create(parent, "fileA", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
NodeRef childB = fileFolderService.create(parent, "Thumbs.db", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
hiddenAspect.hideNodeExplicit(childA);
|
||||
|
||||
// Nodes A and B should be hidden, one by pattern, one explicit
|
||||
assertTrue("node a should be hidden", nodeService.hasAspect(childA, ContentModel.ASPECT_HIDDEN));
|
||||
// assertFalse("node b should be hidden", nodeService.hasAspect(childB, ContentModel.ASPECT_HIDDEN));
|
||||
|
||||
{
|
||||
List<FileInfo> children = fileFolderService.list(parent);
|
||||
assertEquals(2, children.size());
|
||||
}
|
||||
|
||||
hiddenAspect.unhideExplicit(childA);
|
||||
hiddenAspect.unhideExplicit(childB);
|
||||
|
||||
// Node B should still be hidden, A should not
|
||||
assertFalse(nodeService.hasAspect(childA, ContentModel.ASPECT_HIDDEN));
|
||||
// assertTrue(nodeService.hasAspect(childB, ContentModel.ASPECT_HIDDEN));
|
||||
|
||||
|
||||
// call checkHidden to maks sure it does not make a mistake
|
||||
hiddenAspect.checkHidden(childA, true, false);
|
||||
// hiddenAspect.checkHidden(childB, true);
|
||||
|
||||
{
|
||||
List<FileInfo> children = fileFolderService.list(parent);
|
||||
assertEquals(2, children.size());
|
||||
}
|
||||
|
||||
// Node B should still be hidden, A should not
|
||||
assertFalse(nodeService.hasAspect(childA, ContentModel.ASPECT_HIDDEN));
|
||||
// assertTrue(nodeService.hasAspect(childB, ContentModel.ASPECT_HIDDEN));
|
||||
|
||||
{
|
||||
List<FileInfo> children = fileFolderService.list(parent);
|
||||
assertEquals(2, children.size());
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
FileFilterMode.clearClient();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private List<NodeRef> getHiddenNodes(final StoreRef storeRef)
|
||||
{
|
||||
final List<NodeRef> nodes = new ArrayList<NodeRef>(20);
|
||||
|
||||
NodeRefQueryCallback resultsCallback = new NodeRefQueryCallback()
|
||||
{
|
||||
@Override
|
||||
public boolean handle(Pair<Long, NodeRef> nodePair)
|
||||
{
|
||||
if(storeRef == null || nodePair.getSecond().getStoreRef().equals(storeRef))
|
||||
{
|
||||
nodes.add(nodePair.getSecond());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
nodeDAO.getNodesWithAspects(Collections.singleton(ContentModel.ASPECT_HIDDEN), 0l, Long.MAX_VALUE, resultsCallback);
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private int numMailboxes(AlfrescoImapUser user, String mailboxName)
|
||||
{
|
||||
int numMailboxes = 0;
|
||||
|
||||
try
|
||||
{
|
||||
List<AlfrescoImapFolder> folders = imapService.listMailboxes(user, mailboxName, false);
|
||||
numMailboxes = folders.size();
|
||||
}
|
||||
catch (AlfrescoRuntimeException e)
|
||||
{
|
||||
fail("Unexpected exception: " + e.getMessage());
|
||||
}
|
||||
|
||||
return numMailboxes;
|
||||
}
|
||||
|
||||
private boolean checkMailbox(AlfrescoImapUser user, String mailboxName)
|
||||
{
|
||||
try
|
||||
{
|
||||
imapService.getOrCreateMailbox(user, mailboxName, true, false);
|
||||
}
|
||||
catch (AlfrescoRuntimeException e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private ResultSet searchForName(String name)
|
||||
{
|
||||
SearchParameters sp = new SearchParameters();
|
||||
sp.addStore(rootNodeRef.getStoreRef());
|
||||
sp.setLanguage("lucene");
|
||||
sp.setQuery("@" + LuceneQueryParser.escape(ContentModel.PROP_NAME.toString()) + ":\"" + name + "\"");
|
||||
sp.addLocale(new Locale("en"));
|
||||
return searchService.query(sp);
|
||||
}
|
||||
}
|
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.ml.ContentFilterLanguagesService;
|
||||
import org.alfresco.service.cmr.ml.EditionService;
|
||||
import org.alfresco.service.cmr.ml.MultilingualContentService;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.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;
|
||||
protected EditionService editionService;
|
||||
|
||||
@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");
|
||||
editionService = (EditionService) ctx.getBean("EditionService");
|
||||
|
||||
// Run as admin
|
||||
authenticationComponent.setCurrentUser(AuthenticationUtil.getAdminUserName());
|
||||
|
||||
// Create a folder to work in
|
||||
RetryingTransactionCallback<NodeRef> createFolderCallback = new RetryingTransactionCallback<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() 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 = transactionService.getRetryingTransactionHelper().doInTransaction(createFolderCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception
|
||||
{
|
||||
// Clear authentication
|
||||
try
|
||||
{
|
||||
authenticationComponent.clearCurrentSecurityContext();
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
protected NodeRef createContent()
|
||||
{
|
||||
String name = "" + System.currentTimeMillis();
|
||||
return createContent(name);
|
||||
}
|
||||
|
||||
protected NodeRef createContent(String name)
|
||||
{
|
||||
NodeRef contentNodeRef = fileFolderService.create(
|
||||
folderNodeRef,
|
||||
name,
|
||||
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,140 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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 Yannick Pignot
|
||||
*/
|
||||
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,579 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.model.ml.tools;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.version.VersionModel;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
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.cmr.version.Version;
|
||||
import org.alfresco.service.cmr.version.VersionHistory;
|
||||
import org.alfresco.service.cmr.version.VersionType;
|
||||
|
||||
/**
|
||||
* Edition Service test cases
|
||||
*
|
||||
* @since 2.1
|
||||
* @author Yannick Pignot
|
||||
*/
|
||||
public class EditionServiceImplTest extends AbstractMultilingualTestCases
|
||||
{
|
||||
private static String FRENCH_CONTENT = "FRENCH_CONTENT";
|
||||
private static String CHINESE_CONTENT = "CHINESE_CONTENT";
|
||||
private static String JAPANESE_CONTENT = "JAPANESE_CONTENT";
|
||||
|
||||
private ContentService contentService;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
contentService = serviceRegistry.getContentService();
|
||||
}
|
||||
|
||||
public void testAutoEdition() throws Exception
|
||||
{
|
||||
// create a mlContainer with some content
|
||||
checkFirstVersion(this.createMLContainerWithContent());
|
||||
}
|
||||
|
||||
public void testEditionLabels()
|
||||
{
|
||||
// create a mlContainer with some content
|
||||
NodeRef mlContainerNodeRef = createMLContainerWithContent();
|
||||
Map<String, Serializable> versionProperties = null;
|
||||
List<Version> editions = null;
|
||||
NodeRef pivot = multilingualContentService.getPivotTranslation(mlContainerNodeRef);
|
||||
|
||||
checkFirstVersion(mlContainerNodeRef);
|
||||
|
||||
/*
|
||||
* at the creation (1.0)
|
||||
*/
|
||||
|
||||
Version rootEdition = editionService.getEditions(mlContainerNodeRef).getAllVersions().iterator().next();
|
||||
// Ensure that the version label is 1.0
|
||||
assertTrue("The edition label would be 1.0 and not " + rootEdition.getVersionLabel(), rootEdition.getVersionLabel().equals("1.0"));
|
||||
|
||||
/*
|
||||
* default (1.1)
|
||||
*/
|
||||
|
||||
pivot = editionService.createEdition(pivot, versionProperties);
|
||||
editions = new ArrayList<Version>(editionService.getEditions(mlContainerNodeRef).getAllVersions());
|
||||
Version firstEdition = editions.get(0);
|
||||
// Ensure that the version label is 1.1
|
||||
assertTrue("The edition label would be 1.1 and not " + firstEdition.getVersionLabel(), firstEdition.getVersionLabel().equals("1.1"));
|
||||
|
||||
/*
|
||||
* major (2.0)
|
||||
*/
|
||||
|
||||
versionProperties = new HashMap<String, Serializable>();
|
||||
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR);
|
||||
pivot = editionService.createEdition(pivot, versionProperties);
|
||||
editions = new ArrayList<Version>(editionService.getEditions(mlContainerNodeRef).getAllVersions());
|
||||
Version secondEdition = editions.get(0);
|
||||
// Ensure that the version label is 2.0
|
||||
assertTrue("The edition label would be 2.0 and not " + secondEdition.getVersionLabel(), secondEdition.getVersionLabel().equals("2.0"));
|
||||
|
||||
/*
|
||||
* minor (2.1)
|
||||
*/
|
||||
|
||||
versionProperties = new HashMap<String, Serializable>();
|
||||
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
|
||||
pivot = editionService.createEdition(pivot, versionProperties);
|
||||
editions = new ArrayList<Version>(editionService.getEditions(mlContainerNodeRef).getAllVersions());
|
||||
Version thirdEdition = editions.get(0);
|
||||
// Ensure that the version label is 2.1
|
||||
assertTrue("The edition label would be 2.1 and not " + thirdEdition.getVersionLabel(), thirdEdition.getVersionLabel().equals("2.1"));
|
||||
}
|
||||
|
||||
public void testCreateEdition() throws Exception
|
||||
{
|
||||
// create a mlContainer with some content
|
||||
NodeRef mlContainerNodeRef = createMLContainerWithContent();
|
||||
// get the french translation
|
||||
NodeRef frenchContentNodeRef = multilingualContentService.getTranslationForLocale(mlContainerNodeRef, Locale.FRENCH);
|
||||
|
||||
checkFirstVersion(mlContainerNodeRef);
|
||||
|
||||
// create a new edition form the french translation
|
||||
NodeRef newStartingPoint = editionService.createEdition(frenchContentNodeRef, null);
|
||||
// get the edition history
|
||||
VersionHistory editionHistory = editionService.getEditions(mlContainerNodeRef);
|
||||
|
||||
// Ensure that the edition history contains two versions
|
||||
assertTrue("The edition history must contain two versions", editionHistory.getAllVersions().size() == 2);
|
||||
|
||||
// Ensure that the locale of the container is changer
|
||||
assertTrue("The locale of the conatiner should be changed", nodeService.getProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE).equals(Locale.FRENCH));
|
||||
|
||||
// get the two editions
|
||||
Version rootEdition = editionHistory.getVersion("1.0");
|
||||
Version actualEdition = editionHistory.getVersion("1.1");
|
||||
|
||||
// get the translations of the root versions
|
||||
List<VersionHistory> rootVersionTranslations = editionService.getVersionedTranslations(rootEdition);
|
||||
|
||||
// Ensure that the editions are not null
|
||||
assertNotNull("The root edition can't be null", rootEdition);
|
||||
assertNotNull("The actual edition can't be null", actualEdition);
|
||||
assertNotNull("The translations list of the root edition can't be null", rootVersionTranslations);
|
||||
|
||||
// Ensure that the new starting document noderef is different that the initial one
|
||||
assertFalse("The created starting document must be different that the starting document of the edition", frenchContentNodeRef.equals(newStartingPoint));
|
||||
// Ensure that the new starting document is the pivot of the current translation
|
||||
assertTrue("The new pivot must be equal to the created starting document", newStartingPoint.equals(multilingualContentService.getPivotTranslation(mlContainerNodeRef)));
|
||||
|
||||
int numberOfTranslations;
|
||||
|
||||
// Ensure that the current translations size is 1
|
||||
numberOfTranslations = multilingualContentService.getTranslations(mlContainerNodeRef).size();
|
||||
assertEquals("The number of translations must be 1 and not " + numberOfTranslations, 1, numberOfTranslations);
|
||||
// Ensure that the number of translations of the current edition is 0
|
||||
numberOfTranslations = editionService.getVersionedTranslations(actualEdition).size();
|
||||
assertEquals("The number of translations must be 0 and not " + numberOfTranslations, 0, numberOfTranslations);
|
||||
// Ensure that the number of translations of the root verions is 3
|
||||
numberOfTranslations = rootVersionTranslations.size();
|
||||
assertEquals("The number of translations must be 3 and not " + numberOfTranslations, 3, numberOfTranslations);
|
||||
}
|
||||
|
||||
public void testReadVersionedContent() throws Exception
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void testReadVersionedProperties() throws Exception
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//ALF-6275
|
||||
public void testEditionServiceWithContent()
|
||||
{
|
||||
// create a mlContainer with some content
|
||||
NodeRef mlContainerNodeRef = createMLContainerWithContent("1.0");
|
||||
// get the french translation
|
||||
NodeRef frenchContentNodeRef = multilingualContentService.getTranslationForLocale(mlContainerNodeRef,
|
||||
Locale.FRENCH);
|
||||
checkContentVersionValuesForEditions(mlContainerNodeRef);
|
||||
// create a new edition starting from the french translation
|
||||
NodeRef newStartingPoint = editionService.createEdition(frenchContentNodeRef, null);
|
||||
frenchContentNodeRef = multilingualContentService.getTranslationForLocale(mlContainerNodeRef, Locale.FRENCH);
|
||||
modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "1.1" + "-" + "0.2");
|
||||
checkContentVersionValuesForEditions(mlContainerNodeRef);
|
||||
modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "1.1" + "-" + "0.3");
|
||||
checkContentVersionValuesForEditions(mlContainerNodeRef);
|
||||
modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "1.1" + "-" + "0.4");
|
||||
// checkContentVersionValuesForEditions(mlContainerNodeRef);
|
||||
frenchContentNodeRef = multilingualContentService.getTranslationForLocale(mlContainerNodeRef, Locale.FRENCH);
|
||||
|
||||
newStartingPoint = editionService.createEdition(frenchContentNodeRef, null);
|
||||
frenchContentNodeRef = multilingualContentService.getTranslationForLocale(mlContainerNodeRef, Locale.FRENCH);
|
||||
modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "1.2" + "-" + "0.2");
|
||||
checkContentVersionValuesForEditions(mlContainerNodeRef);
|
||||
modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "1.2" + "-" + "0.3");
|
||||
checkContentVersionValuesForEditions(mlContainerNodeRef);
|
||||
NodeRef chineseContentNodeRef = createContent(CHINESE_CONTENT + "-" + Locale.CHINESE + "-" + "1.2" + "-1.0");
|
||||
multilingualContentService.addTranslation(chineseContentNodeRef, mlContainerNodeRef, Locale.CHINESE);
|
||||
checkContentVersionValuesForEditions(mlContainerNodeRef);
|
||||
NodeRef japaneseContentNodeRef = createContent(JAPANESE_CONTENT + "-" + Locale.JAPANESE + "-" + "1.2" + "-1.0");
|
||||
multilingualContentService.addTranslation(japaneseContentNodeRef, mlContainerNodeRef, Locale.JAPANESE);
|
||||
checkContentVersionValuesForEditions(mlContainerNodeRef);
|
||||
|
||||
japaneseContentNodeRef = multilingualContentService
|
||||
.getTranslationForLocale(mlContainerNodeRef, Locale.JAPANESE);
|
||||
japaneseContentNodeRef = editionService.createEdition(japaneseContentNodeRef, null);
|
||||
checkContentVersionValuesForEditions(mlContainerNodeRef);
|
||||
japaneseContentNodeRef = multilingualContentService
|
||||
.getTranslationForLocale(mlContainerNodeRef, Locale.JAPANESE);
|
||||
modifyContent(japaneseContentNodeRef, JAPANESE_CONTENT + "-" + Locale.JAPANESE + "-" + "1.3" + "-0.2");
|
||||
chineseContentNodeRef = createContent(CHINESE_CONTENT + "-" + Locale.CHINESE + "-" + "1.3" + "-1.0");
|
||||
|
||||
multilingualContentService.addTranslation(chineseContentNodeRef, mlContainerNodeRef, Locale.CHINESE);
|
||||
checkContentVersionValuesForEditions(mlContainerNodeRef);
|
||||
frenchContentNodeRef = createContent(FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "1.3" + "-1.0");
|
||||
multilingualContentService.addTranslation(frenchContentNodeRef, mlContainerNodeRef, Locale.FRENCH);
|
||||
checkContentVersionValuesForEditions(mlContainerNodeRef);
|
||||
|
||||
frenchContentNodeRef = multilingualContentService.getTranslationForLocale(mlContainerNodeRef, Locale.FRENCH);
|
||||
newStartingPoint = editionService.createEdition(frenchContentNodeRef, null);
|
||||
frenchContentNodeRef = multilingualContentService.getTranslationForLocale(mlContainerNodeRef, Locale.FRENCH);
|
||||
modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "1.4" + "-" + "0.2");
|
||||
checkContentVersionValuesForEditions(mlContainerNodeRef);
|
||||
|
||||
|
||||
japaneseContentNodeRef = multilingualContentService.getTranslationForLocale(mlContainerNodeRef, Locale.JAPANESE);
|
||||
HashMap<String, Serializable> versionProperties = new HashMap<String, Serializable>();
|
||||
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR);
|
||||
japaneseContentNodeRef = editionService.createEdition(japaneseContentNodeRef, versionProperties);
|
||||
|
||||
Collection<Version> editions = editionService.getEditions(mlContainerNodeRef).getAllVersions();
|
||||
Version secondEdition = editions.iterator().next();
|
||||
// Ensure that the version label is 2.0
|
||||
assertTrue("The edition label would be 2.0 and not " + secondEdition.getVersionLabel(), secondEdition
|
||||
.getVersionLabel().equals("2.0"));
|
||||
frenchContentNodeRef = createContent(FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "1.0" + "-1.0");
|
||||
modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "1.0" + "-" + "1.1");
|
||||
checkContentVersionValuesForEditions(mlContainerNodeRef);
|
||||
|
||||
frenchContentNodeRef = multilingualContentService.getTranslationForLocale(mlContainerNodeRef, Locale.FRENCH);
|
||||
|
||||
versionProperties = new HashMap<String, Serializable>();
|
||||
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR);
|
||||
frenchContentNodeRef = editionService.createEdition(frenchContentNodeRef, versionProperties);
|
||||
|
||||
editions = editionService.getEditions(mlContainerNodeRef).getAllVersions();
|
||||
secondEdition = editions.iterator().next();
|
||||
// Ensure that the version label is 3.0
|
||||
assertTrue("The edition label would be 3.0 and not " + secondEdition.getVersionLabel(), secondEdition
|
||||
.getVersionLabel().equals("3.0"));
|
||||
modifyContent(frenchContentNodeRef, FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + "3.0" + "-" + "0.2");
|
||||
checkContentVersionValuesForEditions(mlContainerNodeRef);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void checkFirstVersion(NodeRef mlContainerNodeRef)
|
||||
{
|
||||
// get the edition list of edition
|
||||
VersionHistory editionHistory = editionService.getEditions(mlContainerNodeRef);
|
||||
|
||||
// Ensure that the first edition of the mlContainer is created
|
||||
assertNotNull("The edition history can't be null", editionHistory);
|
||||
// Ensure that it contains only one version
|
||||
assertTrue("The edition history must contain only one edition", editionHistory.getAllVersions().size() == 1);
|
||||
|
||||
// get the edition
|
||||
Version currentEdition = editionHistory.getAllVersions().iterator().next();
|
||||
|
||||
// Ensure that this version is the edition of the mlContainer
|
||||
assertTrue("The versioned mlContainer noderef of the editon must be the noderef of the created mlContainer", currentEdition.getVersionedNodeRef().equals(mlContainerNodeRef));
|
||||
|
||||
// get the list of translations
|
||||
List<VersionHistory> translations = editionService.getVersionedTranslations(currentEdition);
|
||||
|
||||
// Ensure that the get versioned translations is empty
|
||||
assertNotNull("The translations list of the current edition can't be null", translations);
|
||||
// Ensure that the list is empty
|
||||
assertTrue("The translations list of the current edition would be empty", translations.size() == 0);
|
||||
}
|
||||
|
||||
private NodeRef createMLContainerWithContent()
|
||||
{
|
||||
NodeRef chineseContentNodeRef = createContent(CHINESE_CONTENT + "_1.0");
|
||||
NodeRef frenchContentNodeRef = createContent(FRENCH_CONTENT + "_1.0");
|
||||
NodeRef japaneseContentNodeRef = createContent(JAPANESE_CONTENT + "_1.0");
|
||||
|
||||
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
|
||||
multilingualContentService.addTranslation(japaneseContentNodeRef, chineseContentNodeRef, Locale.JAPANESE);
|
||||
|
||||
return multilingualContentService.getTranslationContainer(chineseContentNodeRef);
|
||||
}
|
||||
|
||||
private void checkContentVersionValuesForEditions(NodeRef mlContainerNodeRef)
|
||||
{
|
||||
// the convention applied for this test is that the content MUST end up with
|
||||
// _LOCALE_EDITION-VERION_INDIVIDUAL-VERSION
|
||||
// get the edition list of edition
|
||||
VersionHistory editionHistory = editionService.getEditions(mlContainerNodeRef);
|
||||
|
||||
// Ensure that the first edition of the mlContainer is created
|
||||
assertNotNull("The edition history can't be null", editionHistory);
|
||||
// Ensure that it contains only one version
|
||||
assertTrue("The edition history must contain only one edition", editionHistory.getAllVersions().size() >= 1);
|
||||
|
||||
// iterate on editions
|
||||
for (Version editionVersion : editionHistory.getAllVersions())
|
||||
{
|
||||
// getting the edition label
|
||||
String editionLabel = editionVersion.getVersionLabel();
|
||||
// check if it is the head version
|
||||
if (editionHistory.getHeadVersion() == editionVersion)
|
||||
{
|
||||
// this is the living edition
|
||||
System.out.println("Head version edition:" + editionLabel);
|
||||
// dump content of head edition
|
||||
Map<Locale, NodeRef> translations = multilingualContentService.getTranslations(mlContainerNodeRef);
|
||||
Locale pivotLocale = (Locale) nodeService.getProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE);
|
||||
Set<Locale> keySet = translations.keySet();
|
||||
for (Locale locale : keySet)
|
||||
{
|
||||
NodeRef translatedNode = translations.get(locale);
|
||||
// get content as string and compare
|
||||
ContentReader reader = contentService.getReader(translatedNode, ContentModel.PROP_CONTENT);
|
||||
String liveContent = reader.getContentString();
|
||||
Triplet parsedTriplet = new Triplet(liveContent);
|
||||
System.out.println("Content:" + liveContent);
|
||||
|
||||
// get all the version of current translation
|
||||
VersionHistory versionHistory = versionService.getVersionHistory(translatedNode);
|
||||
for (Version version : versionHistory.getAllVersions())
|
||||
{
|
||||
NodeRef frozenNodeRef = version.getFrozenStateNodeRef();
|
||||
String versionLabel = version.getVersionLabel();
|
||||
Locale versionLocale = (Locale) nodeService
|
||||
.getProperty(frozenNodeRef, ContentModel.PROP_LOCALE);
|
||||
// get content as string and compare
|
||||
reader = contentService.getReader(frozenNodeRef, ContentModel.PROP_CONTENT);
|
||||
String versionnedContent = reader.getContentString();
|
||||
System.out.println("Individual version " + versionLabel + ":" + versionnedContent);
|
||||
if (versionService.getCurrentVersion(translatedNode).getFrozenStateNodeRef().equals(
|
||||
version.getFrozenStateNodeRef()))
|
||||
{
|
||||
// this is the head version of the translation therefore content should be equal
|
||||
assertTrue(
|
||||
"The content in head version should be equal to the content of the translation:",
|
||||
versionnedContent.equals(liveContent));
|
||||
}
|
||||
// checking if content respects conventions XXX*locale*edition_version_*document_version
|
||||
// the exception should be the version used to start the new edition with
|
||||
// exception exist for root version because root version can be the first created
|
||||
// and if is the pivot language then its content is a copy of the previous edition.
|
||||
// This breaks the conventions and other checks must be done
|
||||
if ((versionHistory.getRootVersion().getFrozenStateNodeRef().equals(version
|
||||
.getFrozenStateNodeRef()))
|
||||
&& (pivotLocale.equals(versionLocale)))
|
||||
{
|
||||
System.out.println("Some special on live version has to be done:" + versionnedContent);
|
||||
// get previous edition
|
||||
Version previousEditionVersion = editionHistory.getPredecessor(editionVersion);
|
||||
|
||||
if (previousEditionVersion != null)
|
||||
{
|
||||
String previousEditionLabel = previousEditionVersion.getVersionLabel();
|
||||
System.out.println("Current edition Label:" + editionLabel + " Previous edition label:"
|
||||
+ previousEditionLabel);
|
||||
List<VersionHistory> versionTranslations = editionService
|
||||
.getVersionedTranslations(previousEditionVersion);
|
||||
// for all languages iterate to find the corresponding language
|
||||
for (VersionHistory versionTranslation : versionTranslations)
|
||||
{
|
||||
// most recent first
|
||||
Version newestVersion = versionTranslation.getHeadVersion();
|
||||
NodeRef newestVersionFrozenNodeRef = newestVersion.getFrozenStateNodeRef();
|
||||
String newestVersionVersionLabel = newestVersion.getVersionLabel();
|
||||
ContentReader readerContentWeStartedWith = contentService.getReader(
|
||||
newestVersionFrozenNodeRef, ContentModel.PROP_CONTENT);
|
||||
Locale oldestVersionLocale = (Locale) nodeService.getProperty(
|
||||
newestVersionFrozenNodeRef, ContentModel.PROP_LOCALE);
|
||||
String contentWeStartedWith = readerContentWeStartedWith.getContentString();
|
||||
System.out.println("CONTENT:" + contentWeStartedWith);
|
||||
if (versionLocale.equals(oldestVersionLocale))
|
||||
{
|
||||
// content should match
|
||||
assertTrue(
|
||||
"The content in head version should be equal to the content we started with:",
|
||||
contentWeStartedWith.equals(versionnedContent));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// it is not a root version therefore it should respect the conventions
|
||||
Triplet testTriplet = new Triplet(versionnedContent);
|
||||
assertEquals(testTriplet.locale, versionLocale.toString());
|
||||
assertEquals(testTriplet.edition, editionLabel);
|
||||
assertEquals(testTriplet.version, versionLabel);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// get pivot language of the current versionned edition
|
||||
// This is not the current/head edition
|
||||
Version nextEditionVersion = editionHistory.getSuccessors(editionVersion).iterator().next();
|
||||
|
||||
//get Next verion label
|
||||
String nextEditionLabel = nextEditionVersion.getVersionLabel();
|
||||
System.out.println("Edition:" + editionLabel + " Next edition label:" + nextEditionLabel);
|
||||
// get the translations of the version
|
||||
List<VersionHistory> versionTranslations = editionService.getVersionedTranslations(editionVersion);
|
||||
// iterate on versionTranslations (all languages)
|
||||
|
||||
//strange that we have to go to the next edition to find the current pivot language.
|
||||
//maybe there is a reason for that but not logical logical
|
||||
dumpFrozenMetaData(editionVersion);
|
||||
Locale editionPivotlanguage = (Locale) (editionService.getVersionedMetadatas(editionVersion)
|
||||
.get(ContentModel.PROP_LOCALE));
|
||||
System.out.println("Edition:" + editionLabel + " Previous pivot language:" + editionPivotlanguage + " Current pivot language:" + editionPivotlanguage);
|
||||
for (VersionHistory versionTranslation : versionTranslations)
|
||||
{
|
||||
Collection<Version> versions = versionTranslation.getAllVersions();
|
||||
// for a language, iterate on all versions
|
||||
for (Version version : versions)
|
||||
{
|
||||
NodeRef frozenNodeRef = version.getFrozenStateNodeRef();
|
||||
String versionLabel = version.getVersionLabel();
|
||||
// get content language
|
||||
Locale currentVersionLocale = (Locale) nodeService.getProperty(frozenNodeRef,
|
||||
ContentModel.PROP_LOCALE);
|
||||
System.out.println("Current version locale:" + currentVersionLocale
|
||||
+ " Previous edition locale:" + editionPivotlanguage);
|
||||
// get content as string and compare
|
||||
ContentReader reader = contentService.getReader(frozenNodeRef, ContentModel.PROP_CONTENT);
|
||||
String content = reader.getContentString();
|
||||
System.out.println("Content:" + content);
|
||||
// checking content respects conventions XXX*locale*edition_version_*document_version
|
||||
// the exception should be the version used to start the new edition with
|
||||
Version initialVersion = versionTranslation.getRootVersion();
|
||||
if (initialVersion.equals(version) && currentVersionLocale.equals(editionPivotlanguage))
|
||||
{
|
||||
System.out.println("Some special test has to be done:" + content);
|
||||
Version previousEditionVersion = editionHistory.getPredecessor(editionVersion);
|
||||
|
||||
if (previousEditionVersion != null)
|
||||
{
|
||||
String previousEditionLabel = previousEditionVersion.getVersionLabel();
|
||||
System.out.println("Current edition Label:" + editionLabel + " Previous edition label:"
|
||||
+ previousEditionLabel);
|
||||
List<VersionHistory> versionTranslations2 = editionService
|
||||
.getVersionedTranslations(previousEditionVersion);
|
||||
// for all languages iterate to find the corresponding language
|
||||
for (VersionHistory versionTranslation2 : versionTranslations2)
|
||||
{
|
||||
// most recent first
|
||||
Version newestVersion = versionTranslation2.getHeadVersion();
|
||||
NodeRef newestVersionFrozenNodeRef = newestVersion.getFrozenStateNodeRef();
|
||||
String newestVersionVersionLabel = newestVersion.getVersionLabel();
|
||||
ContentReader readerContentWeStartedWith = contentService.getReader(
|
||||
newestVersionFrozenNodeRef, ContentModel.PROP_CONTENT);
|
||||
Locale oldestVersionLocale = (Locale) nodeService.getProperty(
|
||||
newestVersionFrozenNodeRef, ContentModel.PROP_LOCALE);
|
||||
String contentWeStartedWith = readerContentWeStartedWith.getContentString();
|
||||
System.out.println("CONTENT:" + contentWeStartedWith);
|
||||
if (currentVersionLocale.equals(oldestVersionLocale))
|
||||
{
|
||||
// content should match
|
||||
assertTrue(
|
||||
"The content in head version should be equal to the content we started with:",
|
||||
contentWeStartedWith.equals(content));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// normal invariant here because it is not the initial version
|
||||
Triplet testTriplet = new Triplet(content);
|
||||
assertTrue(testTriplet.locale.equals(currentVersionLocale.toString()));
|
||||
assertTrue(testTriplet.edition.equals(editionLabel));
|
||||
assertTrue(testTriplet.version.equals(versionLabel));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
private
|
||||
NodeRef createMLContainerWithContent(String editionSuffix)
|
||||
{
|
||||
NodeRef chineseContentNodeRef = createContent(CHINESE_CONTENT + "-" + Locale.CHINESE + "-" + editionSuffix
|
||||
+ "-1.0");
|
||||
NodeRef frenchContentNodeRef = createContent(FRENCH_CONTENT + "-" + Locale.FRENCH + "-" + editionSuffix
|
||||
+ "-1.0");
|
||||
NodeRef japaneseContentNodeRef = createContent(JAPANESE_CONTENT + "-" + Locale.JAPANESE + "-" + editionSuffix
|
||||
+ "-1.0");
|
||||
|
||||
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
|
||||
multilingualContentService.addTranslation(japaneseContentNodeRef, chineseContentNodeRef, Locale.JAPANESE);
|
||||
|
||||
return multilingualContentService.getTranslationContainer(chineseContentNodeRef);
|
||||
}
|
||||
|
||||
private void modifyContent(NodeRef nodeRef, String value)
|
||||
{
|
||||
ContentWriter contentWriter = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
|
||||
contentWriter.putContent(value);
|
||||
}
|
||||
|
||||
private void dumpFrozenMetaData(Version editionVersion)
|
||||
{
|
||||
System.out.println("---------------------------------------------------");
|
||||
//Get current version label
|
||||
System.out.println("Version Label: " + editionVersion.getVersionLabel());
|
||||
System.out.println("---------------------------------------------------");
|
||||
//Map<QName,Serializable> mapOfFrozenProps = editionService.getVersionedMetadatas(editionVersion);
|
||||
Map<String,Serializable> mapOfFrozenProps = editionVersion.getVersionProperties();
|
||||
if(mapOfFrozenProps == null )
|
||||
{
|
||||
System.out.println("Nul... ");
|
||||
return;
|
||||
}
|
||||
|
||||
for(String q: mapOfFrozenProps.keySet())
|
||||
{
|
||||
String val = mapOfFrozenProps.get(q)==null?"null":mapOfFrozenProps.get(q).toString();
|
||||
System.out.println("QName:" + q + ":" + val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse the content to extract the local,edition lablel,version label
|
||||
*
|
||||
* @author Philippe Dubois
|
||||
*/
|
||||
private class Triplet
|
||||
{
|
||||
public String locale;
|
||||
public String edition;
|
||||
public String version;
|
||||
|
||||
public Triplet(String content)
|
||||
{
|
||||
String[] tokens = content.split("-");
|
||||
locale = tokens[1];
|
||||
edition = tokens[2];
|
||||
version = tokens[3];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected NodeRef createContent(String name)
|
||||
{
|
||||
NodeRef contentNodeRef = fileFolderService.create(folderNodeRef, name+".txt", ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
// add some content
|
||||
ContentWriter contentWriter = fileFolderService.getWriter(contentNodeRef);
|
||||
contentWriter.putContent(name);
|
||||
// done
|
||||
return contentNodeRef;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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 Yannick Pignot
|
||||
*/
|
||||
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.getParentAssocs(empty);
|
||||
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;
|
||||
|
||||
multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||
NodeRef mlContainer = multilingualContentService.getTranslationContainer(pivot);
|
||||
multilingualContentService.addTranslation(otherTranslation, pivot, Locale.KOREAN);
|
||||
|
||||
empty = multilingualContentService.addEmptyTranslation(pivot, "empty_" + System.currentTimeMillis(), Locale.CHINESE);
|
||||
|
||||
// Modify the content of the pivot
|
||||
String contentString = fileFolderService.getReader(pivot).getContentString();
|
||||
contentString += "_TEST_";
|
||||
|
||||
fileFolderService.getWriter(pivot).putContent(contentString);
|
||||
|
||||
// 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());
|
||||
}
|
||||
}
|
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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 Yannick Pignot
|
||||
*/
|
||||
public class MLContainerTypeTest extends AbstractMultilingualTestCases
|
||||
{
|
||||
@SuppressWarnings("unused")
|
||||
public void testEditLocale() throws Exception
|
||||
{
|
||||
NodeRef trans1 = createContent();
|
||||
NodeRef trans2 = createContent();
|
||||
NodeRef trans3 = createContent();
|
||||
NodeRef empty = null;
|
||||
|
||||
multilingualContentService.makeTranslation(trans1, Locale.FRENCH);
|
||||
NodeRef mlContainer = multilingualContentService.getTranslationContainer(trans1);
|
||||
multilingualContentService.addTranslation(trans2, trans1, Locale.GERMAN);
|
||||
multilingualContentService.addTranslation(trans3, trans1, Locale.ITALIAN);
|
||||
empty = multilingualContentService.addEmptyTranslation(trans1, "EMPTY_" + System.currentTimeMillis(), Locale.JAPANESE);
|
||||
|
||||
// 1. Locale as null
|
||||
|
||||
// Setting a null locale has no effect on any node
|
||||
assertFalse("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,666 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.model.ml.tools;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.service.cmr.model.FileExistsException;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.ml.MultilingualContentServiceImpl
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @author Philippe Dubois
|
||||
*/
|
||||
public class MultilingualContentServiceImplTest extends AbstractMultilingualTestCases
|
||||
{
|
||||
|
||||
public void testMakeTranslation() throws Exception
|
||||
{
|
||||
NodeRef chineseContentNodeRef = createContent();
|
||||
// Turn the content into a translation with the appropriate structures
|
||||
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(chineseContentNodeRef);
|
||||
// Check it
|
||||
assertNotNull("Container not created", mlContainerNodeRef);
|
||||
// Check the container child count
|
||||
assertEquals("Incorrect number of child nodes", 1, nodeService.getChildAssocs(mlContainerNodeRef).size());
|
||||
}
|
||||
|
||||
public void testAddTranslationUsingContent() throws Exception
|
||||
{
|
||||
// Make a container with a single translation
|
||||
NodeRef chineseContentNodeRef = createContent();
|
||||
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(chineseContentNodeRef);
|
||||
// Create some more content
|
||||
NodeRef frenchContentNodeRef = createContent();
|
||||
// Make this a translation of the Chinese
|
||||
multilingualContentService.addTranslation(
|
||||
frenchContentNodeRef,
|
||||
chineseContentNodeRef,
|
||||
Locale.FRENCH);
|
||||
NodeRef newMLContainerNodeRef = multilingualContentService.getTranslationContainer(frenchContentNodeRef);
|
||||
// Make sure that the original container was used
|
||||
assertEquals("Existing container should have been used", mlContainerNodeRef, newMLContainerNodeRef);
|
||||
// Check the container child count
|
||||
assertEquals("Incorrect number of child nodes", 2, nodeService.getChildAssocs(mlContainerNodeRef).size());
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
multilingualContentService.makeTranslation(nodeRef1, loc1);
|
||||
|
||||
List<Locale> missing = multilingualContentService.getMissingTranslations(nodeRef1, 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, nodeRef1, loc2);
|
||||
multilingualContentService.addTranslation(nodeRef3, nodeRef1, loc3);
|
||||
|
||||
// Add the missing translations in
|
||||
missing = multilingualContentService.getMissingTranslations(nodeRef1, 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.toString() + " or " + loc3.toString() + " found", missing.contains(loc2) || missing.contains(loc3));
|
||||
}
|
||||
|
||||
public void testGetTranslationForLocale() throws Exception
|
||||
{
|
||||
NodeRef chineseContentNodeRef = createContent();
|
||||
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||
NodeRef frenchContentNodeRef = createContent();
|
||||
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
|
||||
|
||||
// Get the chinese translation
|
||||
assertEquals("Chinese translation should be present",
|
||||
chineseContentNodeRef,
|
||||
multilingualContentService.getTranslationForLocale(chineseContentNodeRef, Locale.CHINESE));
|
||||
// Get the french translation
|
||||
assertEquals("French translation should be present",
|
||||
frenchContentNodeRef,
|
||||
multilingualContentService.getTranslationForLocale(chineseContentNodeRef, Locale.FRENCH));
|
||||
// The Italian should return the pivot
|
||||
assertEquals("French translation should be present",
|
||||
chineseContentNodeRef,
|
||||
multilingualContentService.getTranslationForLocale(chineseContentNodeRef, Locale.ITALIAN));
|
||||
}
|
||||
|
||||
public void testGetPivotTranslation() throws Exception
|
||||
{
|
||||
NodeRef chineseContentNodeRef = createContent();
|
||||
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(chineseContentNodeRef);
|
||||
|
||||
// make sure that the pivot language is set
|
||||
assertNotNull("Pivot language not set", nodeService.getProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE));
|
||||
|
||||
// make sure that the pivot language is correctly set
|
||||
assertEquals("Pivot language not correctly set", Locale.CHINESE, nodeService.getProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE));
|
||||
|
||||
NodeRef frenchContentNodeRef = createContent();
|
||||
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
|
||||
|
||||
// make sure that the pivot noderef is correct
|
||||
assertEquals("Unable to get pivot from container", chineseContentNodeRef, multilingualContentService.getPivotTranslation(mlContainerNodeRef));
|
||||
assertEquals("Unable to get pivot from translation", chineseContentNodeRef, multilingualContentService.getPivotTranslation(frenchContentNodeRef));
|
||||
|
||||
// modify the pivot language
|
||||
nodeService.setProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE, Locale.FRENCH);
|
||||
|
||||
// make sure that the modified pivot noderef is correct
|
||||
assertEquals("Pivot node ref not correct", frenchContentNodeRef, multilingualContentService.getPivotTranslation(mlContainerNodeRef));
|
||||
}
|
||||
|
||||
/**
|
||||
* Testing unmakeTranslation
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testUnmakeTranslation() throws Exception
|
||||
{
|
||||
NodeRef frenchContentNodeRef = createContent();
|
||||
multilingualContentService.makeTranslation(frenchContentNodeRef, Locale.FRENCH);
|
||||
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(frenchContentNodeRef);
|
||||
|
||||
NodeRef englishContentNodeRef = createContent();
|
||||
multilingualContentService.addTranslation(englishContentNodeRef, frenchContentNodeRef, Locale.ENGLISH);
|
||||
|
||||
NodeRef germanContentNodeRef = createContent();
|
||||
multilingualContentService.addTranslation(germanContentNodeRef, frenchContentNodeRef, Locale.GERMAN);
|
||||
|
||||
multilingualContentService.unmakeTranslation(englishContentNodeRef);
|
||||
multilingualContentService.unmakeTranslation(germanContentNodeRef);
|
||||
//multilingualContentService.unmakeTranslation(frenchContentNodeRef);
|
||||
|
||||
//calling unmakeTranslation() dissolves the multiligual document.
|
||||
//none of the documents composing the multilingual document
|
||||
assertTrue("The document should not be multilingual!",
|
||||
!multilingualContentService.isTranslation(englishContentNodeRef) &&
|
||||
!multilingualContentService.isTranslation(germanContentNodeRef));
|
||||
}
|
||||
|
||||
/**
|
||||
* Testing unmakeTranslation() on pivot
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testUnmakeTranslationOnPivot() throws Exception
|
||||
{
|
||||
NodeRef frenchContentNodeRef = createContent();
|
||||
multilingualContentService.makeTranslation(frenchContentNodeRef, Locale.FRENCH);
|
||||
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(frenchContentNodeRef);
|
||||
|
||||
NodeRef englishContentNodeRef = createContent();
|
||||
multilingualContentService.addTranslation(englishContentNodeRef, frenchContentNodeRef, Locale.ENGLISH);
|
||||
|
||||
NodeRef germanContentNodeRef = createContent();
|
||||
multilingualContentService.addTranslation(germanContentNodeRef, frenchContentNodeRef, Locale.GERMAN);
|
||||
|
||||
multilingualContentService.unmakeTranslation(frenchContentNodeRef);
|
||||
|
||||
//calling unmakeTranslation() dissolves the multiligual document.
|
||||
//none of the documents composing the multilingual document
|
||||
assertTrue("The document should not be multilingual!",
|
||||
!multilingualContentService.isTranslation(frenchContentNodeRef) &&
|
||||
!multilingualContentService.isTranslation(englishContentNodeRef) &&
|
||||
!multilingualContentService.isTranslation(germanContentNodeRef));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void testCreateEmptyTranslation() throws Exception
|
||||
{
|
||||
NodeRef chineseContentNodeRef = createContent("Document.txt");
|
||||
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||
|
||||
// This should use the pivot language
|
||||
NodeRef emptyNodeRef = multilingualContentService.addEmptyTranslation(chineseContentNodeRef, "Document.txt", Locale.CANADA);
|
||||
|
||||
// Ensure that the empty translation is not null
|
||||
assertNotNull("The creation of the empty document failed ", emptyNodeRef);
|
||||
// Ensure that the empty translation has the mlDocument aspect
|
||||
assertTrue("The empty document must have the mlDocument aspect",
|
||||
nodeService.hasAspect(emptyNodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
|
||||
// Ensure that the empty translation has the mlEmptyTranslation aspect
|
||||
assertTrue("The empty document must have the mlEmptyTranslation aspect",
|
||||
nodeService.hasAspect(emptyNodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION));
|
||||
// Check that the auto renaming worked
|
||||
String emptyName = DefaultTypeConverter.INSTANCE.convert(String.class,
|
||||
nodeService.getProperty(emptyNodeRef, ContentModel.PROP_NAME));
|
||||
assertEquals("Empty auto-rename didn't work for same-named document", "Document_en_CA.txt", emptyName);
|
||||
|
||||
// Check that the content is identical
|
||||
ContentData chineseContentData = fileFolderService.getReader(chineseContentNodeRef).getContentData();
|
||||
ContentData emptyContentData = fileFolderService.getReader(emptyNodeRef).getContentData();
|
||||
}
|
||||
|
||||
public void testCreateEmptyTranslationNames() throws Exception
|
||||
{
|
||||
NodeRef chineseContentNodeRef = createContent("Document.txt");
|
||||
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||
NodeRef koreanContentNodeRef = createContent("Document_ko.txt");
|
||||
multilingualContentService.addTranslation(koreanContentNodeRef, chineseContentNodeRef, Locale.KOREAN);
|
||||
|
||||
|
||||
// The pivot translation (base language) is Chinese
|
||||
// (It won't matter which language we query to check this)
|
||||
assertEquals(
|
||||
"The wrong language was set as the pivot translation",
|
||||
chineseContentNodeRef,
|
||||
multilingualContentService.getPivotTranslation(chineseContentNodeRef)
|
||||
);
|
||||
assertEquals(
|
||||
"The wrong language was set as the pivot translation",
|
||||
chineseContentNodeRef,
|
||||
multilingualContentService.getPivotTranslation(koreanContentNodeRef)
|
||||
);
|
||||
|
||||
|
||||
// Create with a null name, and off a non-pivot just to be sure
|
||||
// The locale will be added to the pivot's file name to create a unique one
|
||||
NodeRef nullNameNodeRef = multilingualContentService.addEmptyTranslation(
|
||||
koreanContentNodeRef,
|
||||
null,
|
||||
Locale.CANADA);
|
||||
String nullName = fileFolderService.getFileInfo(nullNameNodeRef).getName();
|
||||
assertEquals("Empty translation name not generated correctly.", "Document_en_CA.txt", nullName);
|
||||
|
||||
// This will be referencing the same pivot still
|
||||
assertEquals(
|
||||
"The wrong language was set as the pivot translation",
|
||||
chineseContentNodeRef,
|
||||
multilingualContentService.getPivotTranslation(nullNameNodeRef)
|
||||
);
|
||||
|
||||
|
||||
// Create with the same name as the document we're the translation of
|
||||
// The locale will be added to the supplied file name to create a unique one
|
||||
NodeRef sameNameNodeRef = multilingualContentService.addEmptyTranslation(
|
||||
chineseContentNodeRef,
|
||||
"Document.txt",
|
||||
Locale.CANADA_FRENCH);
|
||||
String sameName = fileFolderService.getFileInfo(sameNameNodeRef).getName();
|
||||
assertEquals("Empty translation name not generated correctly.", "Document_fr_CA.txt", sameName);
|
||||
|
||||
// Still correctly referencing the pivot
|
||||
assertEquals(
|
||||
"The wrong language was set as the pivot translation",
|
||||
chineseContentNodeRef,
|
||||
multilingualContentService.getPivotTranslation(sameNameNodeRef)
|
||||
);
|
||||
|
||||
|
||||
// Create with a different name
|
||||
// As there's no clash, the locale won't be added
|
||||
NodeRef differentNameNodeRef = multilingualContentService.addEmptyTranslation(
|
||||
chineseContentNodeRef,
|
||||
"Document2.txt",
|
||||
Locale.JAPANESE);
|
||||
String differentName = fileFolderService.getFileInfo(differentNameNodeRef).getName();
|
||||
assertEquals("Empty translation name not generated correctly.", "Document2.txt", differentName);
|
||||
|
||||
// If we tried to add a 2nd language with the different name,
|
||||
// it would fail as the name isn't used
|
||||
// (The automatic appending of the locale to avoid duplicates only
|
||||
// works on the Pivot version's name, it isn't allowed for
|
||||
// the names of non-pivot versions)
|
||||
try {
|
||||
multilingualContentService.addEmptyTranslation(
|
||||
chineseContentNodeRef,
|
||||
"Document2.txt",
|
||||
Locale.FRENCH);
|
||||
fail("A duplicate translation filename was created");
|
||||
} catch(FileExistsException e) {
|
||||
// Good, this was spotted
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetTranslationContainerPermissions() throws Exception
|
||||
{
|
||||
// Grant the guest user rights to our working folder
|
||||
PermissionService permissionService = serviceRegistry.getPermissionService();
|
||||
AuthenticationComponent authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
|
||||
permissionService.setPermission(
|
||||
folderNodeRef,
|
||||
AuthenticationUtil.getGuestUserName(),
|
||||
PermissionService.ALL_PERMISSIONS,
|
||||
true);
|
||||
// Get the current authentication
|
||||
AuthenticationUtil.pushAuthentication();
|
||||
try
|
||||
{
|
||||
authenticationComponent.setGuestUserAsCurrentUser();
|
||||
// Create some documents
|
||||
NodeRef chineseContentNodeRef = createContent();
|
||||
// Make a translation
|
||||
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||
multilingualContentService.getTranslationContainer(chineseContentNodeRef);
|
||||
}
|
||||
finally
|
||||
{
|
||||
AuthenticationUtil.popAuthentication();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether non-admin users can take part in ML document manipulation
|
||||
*/
|
||||
public void testPermissions() throws Exception
|
||||
{
|
||||
// Grant the guest user rights to our working folder
|
||||
PermissionService permissionService = serviceRegistry.getPermissionService();
|
||||
AuthenticationComponent authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
|
||||
permissionService.setPermission(
|
||||
folderNodeRef,
|
||||
AuthenticationUtil.getGuestUserName(),
|
||||
PermissionService.ALL_PERMISSIONS,
|
||||
true);
|
||||
// Push the current authentication
|
||||
AuthenticationUtil.pushAuthentication();
|
||||
try
|
||||
{
|
||||
authenticationComponent.setGuestUserAsCurrentUser();
|
||||
// Create some documents
|
||||
NodeRef chineseContentNodeRef = createContent();
|
||||
NodeRef frenchContentNodeRef = createContent();
|
||||
// Do ML work
|
||||
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
|
||||
multilingualContentService.addEmptyTranslation(chineseContentNodeRef, null, Locale.JAPANESE);
|
||||
}
|
||||
finally
|
||||
{
|
||||
AuthenticationUtil.popAuthentication();
|
||||
}
|
||||
}
|
||||
|
||||
public void testDeleteMultilingualContent() throws Exception
|
||||
{
|
||||
NodeRef chineseContentNodeRef = createContent();
|
||||
NodeRef frenchContentNodeRef = createContent();
|
||||
NodeRef japaneseContentNodeRef = createContent();
|
||||
NodeRef emptyGermanContentNodeRef = null;
|
||||
|
||||
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
|
||||
multilingualContentService.addTranslation(japaneseContentNodeRef, chineseContentNodeRef, Locale.JAPANESE);
|
||||
emptyGermanContentNodeRef = multilingualContentService.addEmptyTranslation(chineseContentNodeRef, null, Locale.GERMAN);
|
||||
|
||||
// the mlContainer to remove
|
||||
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(chineseContentNodeRef);
|
||||
|
||||
// Ensure that the the mlContainer is correctly created
|
||||
assertEquals("Incorrect number of translations", 4, multilingualContentService.getTranslations(mlContainerNodeRef).size());
|
||||
|
||||
// remove the mlContainer
|
||||
multilingualContentService.deleteTranslationContainer(mlContainerNodeRef);
|
||||
|
||||
// get the archived node ref
|
||||
NodeRef archivedChineseContentNodeRef = nodeArchiveService.getArchivedNode(chineseContentNodeRef);
|
||||
NodeRef archivedFrenchContentNodeRef = nodeArchiveService.getArchivedNode(frenchContentNodeRef);
|
||||
NodeRef archivedJapaneseContentNodeRef = nodeArchiveService.getArchivedNode(japaneseContentNodeRef);
|
||||
NodeRef archivedEmptyGermanContentNodeRef = nodeArchiveService.getArchivedNode(emptyGermanContentNodeRef);
|
||||
NodeRef archivedMlContainerNodeRef = nodeArchiveService.getArchivedNode(mlContainerNodeRef);
|
||||
|
||||
// Ensure that the mlContainer is removed
|
||||
assertFalse("The multilingual container must be removed", nodeService.exists(mlContainerNodeRef));
|
||||
// Ensure that the mlContainer IS NOT archived
|
||||
assertFalse("The multilingual container can't be archived", nodeService.exists(archivedMlContainerNodeRef));
|
||||
// Ensure that the translations are removed
|
||||
assertFalse("The translation must be removed: " + Locale.CHINESE, nodeService.exists(chineseContentNodeRef));
|
||||
assertFalse("The translation must be removed: " + Locale.JAPANESE, nodeService.exists(japaneseContentNodeRef));
|
||||
assertFalse("The translation must be removed: " + Locale.FRENCH, nodeService.exists(frenchContentNodeRef));
|
||||
assertFalse("The empty translation must be removed: " + Locale.GERMAN, nodeService.exists(emptyGermanContentNodeRef));
|
||||
|
||||
// Ensure that the translations ARE archived
|
||||
assertTrue("The translation must be archived: " + Locale.CHINESE, nodeService.exists(archivedChineseContentNodeRef));
|
||||
assertTrue("The translation must be archived: " + Locale.JAPANESE, nodeService.exists(archivedJapaneseContentNodeRef));
|
||||
assertTrue("The translation must be archived: " + Locale.FRENCH, nodeService.exists(archivedFrenchContentNodeRef));
|
||||
|
||||
// Ensure that the empty translation IS NOT archived
|
||||
assertFalse("The empty document can't be archived: " + Locale.GERMAN, nodeService.exists(archivedEmptyGermanContentNodeRef));
|
||||
|
||||
// Ensure that the mlDocument aspect is removed
|
||||
assertFalse("The " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT + " aspect must be removed for " + Locale.CHINESE, nodeService.hasAspect(archivedChineseContentNodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
|
||||
assertFalse("The " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT + " aspect must be removed for " + Locale.JAPANESE, nodeService.hasAspect(archivedJapaneseContentNodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
|
||||
assertFalse("The " + ContentModel.ASPECT_MULTILINGUAL_DOCUMENT + " aspect must be removed for " + Locale.FRENCH, nodeService.hasAspect(archivedFrenchContentNodeRef, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void testCopyMLContainerInNewSpace() throws Exception
|
||||
{
|
||||
NodeRef chineseContentNodeRef = createContent();
|
||||
NodeRef frenchContentNodeRef = createContent();
|
||||
NodeRef japaneseContentNodeRef = createContent();
|
||||
NodeRef emptyGermanContentNodeRef = null;
|
||||
|
||||
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
|
||||
multilingualContentService.addTranslation(japaneseContentNodeRef, chineseContentNodeRef, Locale.JAPANESE);
|
||||
emptyGermanContentNodeRef = multilingualContentService.addEmptyTranslation(chineseContentNodeRef, null, Locale.GERMAN);
|
||||
|
||||
// the mlContainer to copy
|
||||
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(chineseContentNodeRef);
|
||||
|
||||
// Ensure that the the mlContainer is correctly created
|
||||
assertEquals("Incorrect number of translations", 4, multilingualContentService.getTranslations(mlContainerNodeRef).size());
|
||||
|
||||
// get the actual space
|
||||
NodeRef actualSpace = folderNodeRef;
|
||||
// create a new space
|
||||
NodeRef destinationSpace = fileFolderService.create(folderNodeRef, "testCopyMLContainerInNewSpace" + GUID.generate(), ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
|
||||
// Ensure that the new space is created
|
||||
assertTrue("The destiation space is not created " + destinationSpace, nodeService.exists(destinationSpace));
|
||||
|
||||
// copy the mlContainer
|
||||
NodeRef newMLContainer = multilingualContentService.copyTranslationContainer(mlContainerNodeRef, destinationSpace, "");
|
||||
|
||||
assertEquals("Incorrect number of translations for the new mlContainer", 4, multilingualContentService.getTranslations(newMLContainer).size());
|
||||
|
||||
// Ensure that a new mlContainer is created
|
||||
assertTrue("The new mlContainer is not created ", nodeService.exists(newMLContainer));
|
||||
// Ensure that the newMLContainer is a copy of the source mlContainer
|
||||
assertFalse("The newMLContainer is not a copy of the source mlContainer, the ref is the same " + newMLContainer , newMLContainer.equals(mlContainerNodeRef));
|
||||
assertEquals("The newMLContainer is not a copy of the source mlContainer, the locales are not the same " + newMLContainer ,
|
||||
nodeService.getProperty(mlContainerNodeRef, ContentModel.PROP_LOCALE),
|
||||
nodeService.getProperty(newMLContainer, ContentModel.PROP_LOCALE));
|
||||
assertEquals("The newMLContainer is not a copy of the source mlContainer, the authors are not the same " + newMLContainer ,
|
||||
nodeService.getProperty(mlContainerNodeRef, ContentModel.PROP_AUTHOR),
|
||||
nodeService.getProperty(newMLContainer, ContentModel.PROP_AUTHOR));
|
||||
|
||||
// get the source translations
|
||||
Map<Locale, NodeRef> sourceTranslations = multilingualContentService.getTranslations(mlContainerNodeRef);
|
||||
// get the copies
|
||||
Map<Locale, NodeRef> copyTranslations = multilingualContentService.getTranslations(newMLContainer);
|
||||
|
||||
// Ensure that the translations are copies from the source translations
|
||||
assertEquals("They are not the same number of translation in the source mlContainer and in its copy", sourceTranslations.size(), copyTranslations.size());
|
||||
|
||||
for(Map.Entry<Locale, NodeRef> entry : sourceTranslations.entrySet())
|
||||
{
|
||||
Locale locale = entry.getKey();
|
||||
|
||||
NodeRef sourceNodeRef = entry.getValue();
|
||||
NodeRef sourceParent = nodeService.getPrimaryParent(sourceNodeRef).getParentRef();
|
||||
|
||||
NodeRef copyTranslation = multilingualContentService.getTranslationForLocale(newMLContainer, locale);
|
||||
NodeRef copyParent = nodeService.getPrimaryParent(copyTranslation).getParentRef();
|
||||
|
||||
// Ensure that the copy exists
|
||||
assertNotNull("No copy found for the locale " + locale, copyTranslation);
|
||||
assertTrue("No copy exists for the locale " + locale, nodeService.exists(copyTranslation));
|
||||
|
||||
// Ensure that the copy has the mlDocument aspect
|
||||
assertTrue("The copy must have the mlDocument aspect",
|
||||
nodeService.hasAspect(copyTranslation, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
|
||||
|
||||
// Ensure that the copy is an empty translation if the source too
|
||||
assertEquals("The call of nodeService.hasAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION) must return the same result for the source and the copy",
|
||||
nodeService.hasAspect(sourceNodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION),
|
||||
nodeService.hasAspect(copyTranslation, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION));
|
||||
|
||||
|
||||
// Ensure that the copy and the source are different
|
||||
assertNotSame("The copy has the same ref as the source", sourceNodeRef, copyTranslation);
|
||||
|
||||
// Ensure that the parent of the source is correct
|
||||
assertEquals("The source would not be moved", sourceParent, actualSpace);
|
||||
// Ensure that the parent of the copy is correct
|
||||
assertEquals("The copy is not in the right space", copyParent, destinationSpace);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void testCopyMLContainerInSameSpace() throws Exception
|
||||
{
|
||||
NodeRef chineseContentNodeRef = createContent();
|
||||
NodeRef frenchContentNodeRef = createContent();
|
||||
NodeRef japaneseContentNodeRef = createContent();
|
||||
NodeRef emptyGermanContentNodeRef = null;
|
||||
|
||||
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
|
||||
multilingualContentService.addTranslation(japaneseContentNodeRef, chineseContentNodeRef, Locale.JAPANESE);
|
||||
emptyGermanContentNodeRef = multilingualContentService.addEmptyTranslation(chineseContentNodeRef, null, Locale.GERMAN);
|
||||
|
||||
// the mlContainer to copy
|
||||
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(chineseContentNodeRef);
|
||||
|
||||
// Ensure that the the mlContainer is correctly created
|
||||
assertEquals("Incorrect number of translations", 4, multilingualContentService.getTranslations(mlContainerNodeRef).size());
|
||||
|
||||
// get the actual space
|
||||
NodeRef actualSpace = folderNodeRef;
|
||||
|
||||
try
|
||||
{
|
||||
// copy the mlContainer
|
||||
NodeRef newMLContainer = multilingualContentService.copyTranslationContainer(mlContainerNodeRef, actualSpace, "");
|
||||
|
||||
fail("The copy of the mlContainer in the same space would faile");
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// test asserted
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void testCopyAndRenameMLContainer() throws Exception
|
||||
{
|
||||
NodeRef chineseContentNodeRef = createContent();
|
||||
NodeRef frenchContentNodeRef = createContent();
|
||||
NodeRef japaneseContentNodeRef = createContent();
|
||||
NodeRef emptyGermanContentNodeRef = null;
|
||||
|
||||
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
|
||||
multilingualContentService.addTranslation(japaneseContentNodeRef, chineseContentNodeRef, Locale.JAPANESE);
|
||||
emptyGermanContentNodeRef = multilingualContentService.addEmptyTranslation(chineseContentNodeRef, null, Locale.GERMAN);
|
||||
|
||||
// the mlContainer to copy
|
||||
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(chineseContentNodeRef);
|
||||
|
||||
// Ensure that the the mlContainer is correctly created
|
||||
assertEquals("Incorrect number of translations", 4, multilingualContentService.getTranslations(mlContainerNodeRef).size());
|
||||
|
||||
// get the actual space
|
||||
NodeRef actualSpace = folderNodeRef;
|
||||
|
||||
// create a new space
|
||||
NodeRef destinationSpace = fileFolderService.create(folderNodeRef, "testCopyMLContainerInNewSpace" + GUID.generate(), ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
|
||||
// Ensure that the new space is created
|
||||
assertTrue("The destiation space is not created " + destinationSpace, nodeService.exists(destinationSpace));
|
||||
|
||||
String PREFIX = "COPY OF " ;
|
||||
|
||||
NodeRef newMLContainer = multilingualContentService.copyTranslationContainer(mlContainerNodeRef, destinationSpace, PREFIX);
|
||||
|
||||
// Ensure that a new mlContainer is created
|
||||
assertTrue("The new mlContainer is not created ", nodeService.exists(newMLContainer));
|
||||
// Ensure that the newMLContainer is a copy of the source mlContainer
|
||||
assertFalse("The newMLContainer is not a copy of the source mlContainer, the ref is the same " + newMLContainer , newMLContainer.equals(mlContainerNodeRef));
|
||||
|
||||
// get the source translations
|
||||
Map<Locale, NodeRef> sourceTranslations = multilingualContentService.getTranslations(mlContainerNodeRef);
|
||||
// get the copies
|
||||
Map<Locale, NodeRef> copyTranslations = multilingualContentService.getTranslations(newMLContainer);
|
||||
|
||||
// Ensure that the translations are copies from the source translations
|
||||
assertEquals("They are not the same number of translation in the source mlContainer and in its copy", sourceTranslations.size(), copyTranslations.size());
|
||||
|
||||
for(Map.Entry<Locale, NodeRef> entry : sourceTranslations.entrySet())
|
||||
{
|
||||
Locale locale = entry.getKey();
|
||||
|
||||
NodeRef sourceNodeRef = entry.getValue();
|
||||
NodeRef copyNodeRef = multilingualContentService.getTranslationForLocale(newMLContainer, locale);
|
||||
|
||||
String sourceName = (String) nodeService.getProperty(sourceNodeRef, ContentModel.PROP_NAME);
|
||||
String copyName = (String) nodeService.getProperty(copyNodeRef, ContentModel.PROP_NAME);
|
||||
|
||||
String theoricalCopyName = PREFIX + sourceName;
|
||||
|
||||
// Ensure that the name of the copy is correct
|
||||
assertTrue("The name of the copied translation is incorect: " + copyName + " and should be " + theoricalCopyName, theoricalCopyName.equals(copyName));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void testMoveMLContainer() throws Exception
|
||||
{
|
||||
NodeRef chineseContentNodeRef = createContent();
|
||||
NodeRef frenchContentNodeRef = createContent();
|
||||
NodeRef japaneseContentNodeRef = createContent();
|
||||
NodeRef emptyGermanContentNodeRef = null;
|
||||
|
||||
multilingualContentService.makeTranslation(chineseContentNodeRef, Locale.CHINESE);
|
||||
multilingualContentService.addTranslation(frenchContentNodeRef, chineseContentNodeRef, Locale.FRENCH);
|
||||
multilingualContentService.addTranslation(japaneseContentNodeRef, chineseContentNodeRef, Locale.JAPANESE);
|
||||
emptyGermanContentNodeRef = multilingualContentService.addEmptyTranslation(chineseContentNodeRef, null, Locale.GERMAN);
|
||||
|
||||
// the mlContainer to copy
|
||||
NodeRef mlContainerNodeRef = multilingualContentService.getTranslationContainer(chineseContentNodeRef);
|
||||
|
||||
// Ensure that the the mlContainer is correctly created
|
||||
assertEquals("Incorrect number of translations", 4, multilingualContentService.getTranslations(mlContainerNodeRef).size());
|
||||
|
||||
// get the actual space
|
||||
NodeRef actualSpace = folderNodeRef;
|
||||
// create a new space
|
||||
NodeRef destinationSpace = fileFolderService.create(folderNodeRef, "testCopyMLContainerInNewSpace", ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
|
||||
// Ensure that the new space is created
|
||||
assertTrue("The destiation space is not created " + destinationSpace, nodeService.exists(destinationSpace));
|
||||
|
||||
// move the mlContainer
|
||||
multilingualContentService.moveTranslationContainer(mlContainerNodeRef, destinationSpace);
|
||||
|
||||
// Esure that the nodes are moved
|
||||
assertEquals("The node should be moved", destinationSpace, nodeService.getPrimaryParent(chineseContentNodeRef).getParentRef());
|
||||
assertEquals("The node should be moved", destinationSpace, nodeService.getPrimaryParent(frenchContentNodeRef).getParentRef());
|
||||
assertEquals("The node should be moved", destinationSpace, nodeService.getPrimaryParent(japaneseContentNodeRef).getParentRef());
|
||||
assertEquals("The node should be moved", destinationSpace, nodeService.getPrimaryParent(emptyGermanContentNodeRef).getParentRef());
|
||||
|
||||
// Ensure the mlContainer is not changed
|
||||
assertEquals("The mlContainer should not be changed", mlContainerNodeRef, multilingualContentService.getTranslationContainer(chineseContentNodeRef));
|
||||
assertEquals("The mlContainer should not be changed", mlContainerNodeRef, multilingualContentService.getTranslationContainer(frenchContentNodeRef));
|
||||
assertEquals("The mlContainer should not be changed", mlContainerNodeRef, multilingualContentService.getTranslationContainer(japaneseContentNodeRef));
|
||||
assertEquals("The mlContainer should not be changed", mlContainerNodeRef, multilingualContentService.getTranslationContainer(emptyGermanContentNodeRef));
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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 Yannick Pignot
|
||||
*/
|
||||
public class MultilingualDocumentAspectTest extends AbstractMultilingualTestCases
|
||||
{
|
||||
public void testCopy() throws Exception
|
||||
{
|
||||
NodeRef original = createContent();
|
||||
multilingualContentService.makeTranslation(original, Locale.FRENCH);
|
||||
NodeRef mlContainer = multilingualContentService.getTranslationContainer(original);
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
public void testDeleteNode() throws Exception
|
||||
{
|
||||
NodeRef trad1 = createContent();
|
||||
NodeRef trad2 = createContent();
|
||||
NodeRef trad3 = createContent();
|
||||
|
||||
NodeRef parent = nodeService.getPrimaryParent(trad1).getParentRef();
|
||||
|
||||
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(trad1).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 restored node must be restaured to the the space", 3, nodeService.getChildAssocs(parent).size());
|
||||
// Ensure that the restored node is not linked to the mlContainer
|
||||
assertEquals("The restored node would not be restaured to the mlContainer", 2, multilingualContentService.getTranslations(trad1).size());
|
||||
// Ensure that the restored node doesn't keep the mlDocument aspect
|
||||
assertFalse("The restored node can't keep the multilingual aspect", nodeService.hasAspect(restoredNode, ContentModel.ASPECT_MULTILINGUAL_DOCUMENT));
|
||||
}
|
||||
|
||||
public void testDeletePivot() throws Exception
|
||||
{
|
||||
NodeRef pivot = createContent();
|
||||
NodeRef trans1 = createContent();
|
||||
multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||
NodeRef mlContainer = multilingualContentService.getTranslationContainer(pivot);
|
||||
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));
|
||||
}
|
||||
|
||||
public void testDeleteLastNode() throws Exception
|
||||
{
|
||||
NodeRef pivot = createContent();
|
||||
multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||
NodeRef mlContainer = multilingualContentService.getTranslationContainer(pivot);
|
||||
|
||||
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();
|
||||
multilingualContentService.makeTranslation(pivot, Locale.FRENCH);
|
||||
NodeRef mlContainer = multilingualContentService.getTranslationContainer(pivot);
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user