/*
* (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* Nicolas Chapurlat <nchapurlat@nuxeo.com>
*/
package org.nuxeo.ecm.directory;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.nuxeo.ecm.directory.DirectoryEntryResolver.NAME;
import static org.nuxeo.ecm.directory.DirectoryEntryResolver.PARAM_DIRECTORY;
import static org.nuxeo.ecm.directory.DirectoryEntryResolver.PARAM_PARENT_FIELD;
import static org.nuxeo.ecm.directory.DirectoryEntryResolver.PARAM_SEPARATOR;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.inject.Inject;
import org.apache.commons.lang.SerializationUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.validation.DocumentValidationService;
import org.nuxeo.ecm.core.schema.types.SimpleType;
import org.nuxeo.ecm.core.test.CoreFeature;
import org.nuxeo.ecm.core.test.annotations.Granularity;
import org.nuxeo.ecm.core.test.annotations.RepositoryConfig;
import org.nuxeo.ecm.directory.api.DirectoryEntry;
import org.nuxeo.ecm.directory.api.DirectoryService;
import org.nuxeo.ecm.directory.sql.SQLDirectoryFeature;
import org.nuxeo.runtime.test.runner.Features;
import org.nuxeo.runtime.test.runner.FeaturesRunner;
import org.nuxeo.runtime.test.runner.LocalDeploy;
@RunWith(FeaturesRunner.class)
@Features({ SQLDirectoryFeature.class, CoreFeature.class })
@RepositoryConfig(cleanup = Granularity.METHOD)
@LocalDeploy("org.nuxeo.ecm.directory.sql.tests:test-directory-resolver-contrib.xml")
public class TestDirectoryEntryResolver {
private static final String REFERENCED_DIRECTORY2 = "referencedDirectory2";
private static final String REFERENCED_DIRECTORY1 = "referencedDirectory1";
private static final String HIERARCHICAL_DIRECTORY = "hierarchicalDirectory";
private static final String REF1_XPATH = "dr:directory1Ref";
private static final String REF2_XPATH = "dr:directory2Ref";
private static final String HIERARCHICAL_REF_XPATH = "dr:hierarchicalDirectoryRef";
private static final String ENTRY_ID = "123";
private static final String ENTRY_LABEL = "Label123";
@Inject
protected CoreSession coreSession;
@Inject
protected DocumentValidationService validator;
@Inject
protected DirectoryService directoryService;
protected DocumentModel doc;
protected DocumentModel entry1;
@Before
public void setup() throws Exception {
try (Session session1 = directoryService.open(REFERENCED_DIRECTORY1)) {
entry1 = session1.getEntry(ENTRY_ID);
}
doc = coreSession.createDocumentModel("/", "doc1", "DirectoryReferencer");
}
@Test
public void supportedClasses() throws Exception {
List<Class<?>> classes = new DirectoryEntryResolver().getManagedClasses();
assertEquals(1, classes.size());
assertTrue(classes.contains(DirectoryEntry.class));
}
@Test(expected = IllegalStateException.class)
public void testLifecycleNoConfigurationFetch() {
new DirectoryEntryResolver().fetch(ENTRY_ID);
}
@Test(expected = IllegalStateException.class)
public void testLifecycleNoConfigurationFetchCast() {
new DirectoryEntryResolver().fetch(DocumentModel.class, ENTRY_ID);
}
@Test(expected = IllegalStateException.class)
public void testLifecycleNoConfigurationGetReference() {
new DirectoryEntryResolver().getReference(entry1);
}
@Test(expected = IllegalStateException.class)
public void testLifecycleNoConfigurationGetParameters() {
new DirectoryEntryResolver().getParameters();
}
@Test(expected = IllegalStateException.class)
public void testLifecycleNoConfigurationGetConstraintErrorMessage() {
new DirectoryEntryResolver().getConstraintErrorMessage(null, Locale.ENGLISH);
}
@Test(expected = IllegalStateException.class)
public void testLifecycleConfigurationTwice() {
DirectoryEntryResolver derr = new DirectoryEntryResolver();
HashMap<String, String> parameters = new HashMap<String, String>();
parameters.put(PARAM_DIRECTORY, REFERENCED_DIRECTORY1);
derr.configure(parameters);
derr.configure(parameters);
}
@Test
public void testConfigurationDir1() {
DirectoryEntryResolver derr = new DirectoryEntryResolver();
HashMap<String, String> parameters = new HashMap<String, String>();
parameters.put(PARAM_DIRECTORY, REFERENCED_DIRECTORY1);
derr.configure(parameters);
assertEquals(REFERENCED_DIRECTORY1, derr.getDirectory().getName());
Map<String, Serializable> outputParameters = derr.getParameters();
assertEquals(REFERENCED_DIRECTORY1, outputParameters.get(PARAM_DIRECTORY));
}
@Test(expected = IllegalArgumentException.class)
public void testConfigurationMissingDirectory() {
DirectoryEntryResolver derr = new DirectoryEntryResolver();
derr.configure(new HashMap<String, String>());
}
@Test(expected = IllegalArgumentException.class)
public void testConfigurationNonExistingDirectory() {
DirectoryEntryResolver derr = new DirectoryEntryResolver();
HashMap<String, String> parameters = new HashMap<String, String>();
parameters.put(PARAM_DIRECTORY, "aBadDirectoryName");
derr.configure(parameters);
}
@Test
public void testName() {
DirectoryEntryResolver derr = new DirectoryEntryResolver();
HashMap<String, String> parameters = new HashMap<String, String>();
parameters.put(PARAM_DIRECTORY, REFERENCED_DIRECTORY1);
derr.configure(parameters);
assertEquals(NAME, derr.getName());
}
@Test
public void testValidateGoodDir1Ref() {
DirectoryEntryResolver derr = new DirectoryEntryResolver();
HashMap<String, String> parameters = new HashMap<String, String>();
parameters.put(PARAM_DIRECTORY, REFERENCED_DIRECTORY1);
derr.configure(parameters);
assertTrue(derr.validate(ENTRY_ID));
}
@Test
public void testValidateDir1RefFailedWithBadValue() {
DirectoryEntryResolver derr = new DirectoryEntryResolver();
HashMap<String, String> parameters = new HashMap<String, String>();
parameters.put(PARAM_DIRECTORY, REFERENCED_DIRECTORY1);
derr.configure(parameters);
assertFalse(derr.validate("BAD id !"));
}
@Test
public void testFetchGoodDir1Ref() {
DirectoryEntryResolver derr = new DirectoryEntryResolver();
HashMap<String, String> parameters = new HashMap<String, String>();
parameters.put(PARAM_DIRECTORY, REFERENCED_DIRECTORY1);
derr.configure(parameters);
Object entity = derr.fetch(ENTRY_ID);
assertTrue(entity instanceof DirectoryEntry);
assertEquals(ENTRY_LABEL, ((DirectoryEntry) entity).getDocumentModel().getPropertyValue("drs:label"));
}
@Test
public void testFetchDir1RefFailedWithBadValue() {
DirectoryEntryResolver derr = new DirectoryEntryResolver();
Map<String, String> parameters = new HashMap<String, String>();
parameters.put(PARAM_DIRECTORY, REFERENCED_DIRECTORY1);
derr.configure(parameters);
assertNull(derr.fetch("BAD id !"));
}
@Test
public void testFetchCastDocumentModel() {
DirectoryEntryResolver derr = new DirectoryEntryResolver();
Map<String, String> parameters = new HashMap<String, String>();
parameters.put(PARAM_DIRECTORY, REFERENCED_DIRECTORY1);
derr.configure(parameters);
DocumentModel document = derr.fetch(DocumentModel.class, ENTRY_ID);
assertNotNull(document);
assertEquals(ENTRY_LABEL, document.getPropertyValue("drs:label"));
assertNull(derr.fetch(DocumentModel.class, "toto"));
}
@Test
public void testFetchCastDoesntSupportReferenceType() {
DirectoryEntryResolver derr = new DirectoryEntryResolver();
Map<String, String> parameters = new HashMap<String, String>();
parameters.put(PARAM_DIRECTORY, REFERENCED_DIRECTORY1);
derr.configure(parameters);
assertNull(derr.fetch(Reference.class, ENTRY_ID));
}
@Test
public void testFetchCastDoesntSupportStupidTypes() {
DirectoryEntryResolver derr = new DirectoryEntryResolver();
Map<String, String> parameters = new HashMap<String, String>();
parameters.put(PARAM_DIRECTORY, REFERENCED_DIRECTORY1);
derr.configure(parameters);
assertNull(derr.fetch(List.class, ENTRY_ID));
}
@Test
public void testGetReferenceDir1Ref() {
DirectoryEntryResolver derr = new DirectoryEntryResolver();
Map<String, String> parameters = new HashMap<String, String>();
parameters.put(PARAM_DIRECTORY, REFERENCED_DIRECTORY1);
derr.configure(parameters);
assertEquals(ENTRY_ID, derr.getReference(entry1));
}
@Test
public void testGetReferenceInvalid() {
DirectoryEntryResolver derr = new DirectoryEntryResolver();
Map<String, String> parameters = new HashMap<String, String>();
parameters.put(PARAM_DIRECTORY, REFERENCED_DIRECTORY1);
derr.configure(parameters);
assertNull(derr.getReference("nothing"));
}
@Test
public void testGetHierarchicalReference() {
DirectoryEntryResolver derr = new DirectoryEntryResolver();
Map<String, String> parameters = new HashMap<>();
parameters.put(PARAM_DIRECTORY, HIERARCHICAL_DIRECTORY);
parameters.put(PARAM_PARENT_FIELD, "parent");
parameters.put(PARAM_SEPARATOR, "/");
derr.configure(parameters);
try (Session session = directoryService.open(HIERARCHICAL_DIRECTORY)) {
// root reference returns its id
DocumentModel root = session.getEntry("level0");
assertEquals("level0", derr.getReference(root));
// leaf reference returns complete id chain
DocumentModel leaf = session.getEntry("level2");
assertEquals("level0/level1/level2", derr.getReference(leaf));
}
}
@Test
public void testConfigurationIsLoaded() {
DirectoryEntryResolver idResolver = (DirectoryEntryResolver) ((SimpleType) doc.getProperty(REF1_XPATH).getType()).getObjectResolver();
assertEquals(REFERENCED_DIRECTORY1, idResolver.getDirectory().getName());
assertEquals(REFERENCED_DIRECTORY1, idResolver.getParameters().get(PARAM_DIRECTORY));
DirectoryEntryResolver pathResolver = (DirectoryEntryResolver) ((SimpleType) doc.getProperty(REF2_XPATH).getType()).getObjectResolver();
assertEquals(REFERENCED_DIRECTORY2, pathResolver.getDirectory().getName());
assertEquals(REFERENCED_DIRECTORY2, pathResolver.getParameters().get(PARAM_DIRECTORY));
}
@Test
public void testNullValueReturnNull() {
assertNull(doc.getObjectResolver(REF1_XPATH).fetch());
assertNull(doc.getObjectResolver(REF1_XPATH).fetch(DocumentModel.class));
assertNull(doc.getProperty(REF1_XPATH).getObjectResolver().fetch());
assertNull(doc.getProperty(REF1_XPATH).getObjectResolver().fetch(DocumentModel.class));
assertNull(doc.getObjectResolver(REF2_XPATH).fetch());
assertNull(doc.getObjectResolver(REF2_XPATH).fetch(DocumentModel.class));
assertNull(doc.getProperty(REF2_XPATH).getObjectResolver().fetch());
assertNull(doc.getProperty(REF2_XPATH).getObjectResolver().fetch(DocumentModel.class));
}
@Test
public void testBadValuesValidationFailed() {
doc.setPropertyValue(REF1_XPATH, "BAD id !");
assertNull(doc.getProperty(REF1_XPATH).getObjectResolver().fetch());
assertFalse(doc.getProperty(REF1_XPATH).getObjectResolver().validate());
doc.setPropertyValue(REF2_XPATH, "BAD path !");
assertNull(doc.getProperty(REF2_XPATH).getObjectResolver().fetch());
assertFalse(doc.getProperty(REF2_XPATH).getObjectResolver().validate());
assertEquals(2, validator.validate(doc).numberOfErrors());
}
@Test
public void testRefCorrectValues() {
doc.setPropertyValue(REF1_XPATH, ENTRY_ID);
DirectoryEntry entry = (DirectoryEntry) doc.getProperty(REF1_XPATH).getObjectResolver().fetch();
DocumentModel document = entry.getDocumentModel();
assertNotNull(document);
assertEquals(ENTRY_LABEL, document.getPropertyValue("drs:label"));
entry = (DirectoryEntry) doc.getObjectResolver(REF1_XPATH).fetch();
document = entry.getDocumentModel();
assertNotNull(document);
assertEquals(ENTRY_LABEL, document.getPropertyValue("drs:label"));
document = doc.getProperty(REF1_XPATH).getObjectResolver().fetch(DocumentModel.class);
assertNotNull(document);
assertEquals(ENTRY_LABEL, document.getPropertyValue("drs:label"));
document = doc.getObjectResolver(REF1_XPATH).fetch(DocumentModel.class);
assertNotNull(document);
assertEquals(ENTRY_LABEL, document.getPropertyValue("drs:label"));
}
@Test
public void testDocumentHierarchicalRef() {
// test the resolving
doc.setPropertyValue(HIERARCHICAL_REF_XPATH, "level0/level1/level2");
DirectoryEntry level2Entry = (DirectoryEntry) doc.getProperty(HIERARCHICAL_REF_XPATH).getObjectResolver().fetch();
DocumentModel document = level2Entry.getDocumentModel();
assertNotNull(document);
assertEquals("level2", document.getPropertyValue("hd:id"));
// test the edit
DocumentModel newDoc = coreSession.createDocumentModel("/", "doc2", "DirectoryReferencer");
newDoc.getProperty(HIERARCHICAL_REF_XPATH).getObjectResolver().setObject(level2Entry);
assertEquals("level0/level1/level2", newDoc.getPropertyValue(HIERARCHICAL_REF_XPATH));
}
@Test
public void testTranslation() {
DirectoryEntryResolver idderr = new DirectoryEntryResolver();
Map<String, String> userParams = new HashMap<String, String>();
userParams.put(PARAM_DIRECTORY, REFERENCED_DIRECTORY1);
idderr.configure(userParams);
checkMessage(idderr);
DirectoryEntryResolver pathderr = new DirectoryEntryResolver();
Map<String, String> groupParams = new HashMap<String, String>();
groupParams.put(PARAM_DIRECTORY, REFERENCED_DIRECTORY2);
pathderr.configure(groupParams);
checkMessage(pathderr);
}
@Test
public void testSerialization() throws Exception {
// create it
DirectoryEntryResolver derr = new DirectoryEntryResolver();
HashMap<String, String> parameters = new HashMap<String, String>();
parameters.put(PARAM_DIRECTORY, REFERENCED_DIRECTORY1);
derr.configure(parameters);
// write it
byte[] buffer = SerializationUtils.serialize(derr);
// forget the resolver
derr = null;
// read it
Object readObject = SerializationUtils.deserialize(buffer);
// check it's a dir resolver
assertTrue(readObject instanceof DirectoryEntryResolver);
DirectoryEntryResolver readDerr = (DirectoryEntryResolver) readObject;
// check the configuration
assertEquals(REFERENCED_DIRECTORY1, readDerr.getDirectory().getName());
Map<String, Serializable> outputParameters = readDerr.getParameters();
assertEquals(REFERENCED_DIRECTORY1, outputParameters.get(PARAM_DIRECTORY));
// test it works: validate
assertTrue(readDerr.validate(ENTRY_ID));
// test it works: fetch
Object entity = readDerr.fetch(ENTRY_ID);
assertTrue(entity instanceof DirectoryEntry);
assertEquals(ENTRY_LABEL, ((DirectoryEntry) entity).getDocumentModel().getPropertyValue("drs:label"));
// test it works: getReference
assertEquals(ENTRY_ID, readDerr.getReference(entry1));
}
private void checkMessage(DirectoryEntryResolver derr) {
for (Locale locale : Arrays.asList(Locale.FRENCH, Locale.ENGLISH)) {
String message = derr.getConstraintErrorMessage("abc123", locale);
assertNotNull(message);
assertFalse(message.trim().isEmpty());
System.out.println(message);
}
}
}