package edu.harvard.iq.dataverse.engine.command.impl;
import edu.harvard.iq.dataverse.DatasetFieldType;
import edu.harvard.iq.dataverse.Dataverse;
import edu.harvard.iq.dataverse.DataverseFacet;
import edu.harvard.iq.dataverse.DataverseFacetServiceBean;
import edu.harvard.iq.dataverse.DataverseFieldTypeInputLevel;
import edu.harvard.iq.dataverse.DataverseFieldTypeInputLevelServiceBean;
import edu.harvard.iq.dataverse.DataverseRoleServiceBean;
import edu.harvard.iq.dataverse.DataverseServiceBean;
import edu.harvard.iq.dataverse.DvObject;
import edu.harvard.iq.dataverse.RoleAssignment;
import edu.harvard.iq.dataverse.authorization.DataverseRole;
import edu.harvard.iq.dataverse.authorization.groups.impl.ipaddress.ip.IpAddress;
import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
import edu.harvard.iq.dataverse.authorization.users.GuestUser;
import edu.harvard.iq.dataverse.search.IndexServiceBean;
import org.junit.Before;
import org.junit.Test;
import static edu.harvard.iq.dataverse.mocks.MocksFactory.*;
import edu.harvard.iq.dataverse.engine.TestCommandContext;
import edu.harvard.iq.dataverse.engine.TestDataverseEngine;
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
import edu.harvard.iq.dataverse.engine.command.exception.CommandException;
import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
*
* @author michael
*/
public class CreateDataverseCommandTest {
boolean indexCalled = false;
Map<String, Dataverse> dvByAliasStore = new HashMap<>();
Map<Long, Dataverse> dvStore = new HashMap<>();
boolean isRootDvExists;
boolean facetsDeleted;
boolean dftilsDeleted;
List<DataverseFieldTypeInputLevel> createdDftils;
List<DataverseFacet> createdFacets;
DataverseServiceBean dataverses = new DataverseServiceBean(){
@Override
public boolean isRootDataverseExists() {
return isRootDvExists;
}
@Override
public Dataverse findByAlias(String anAlias) {
return dvByAliasStore.get(anAlias);
}
@Override
public Dataverse save(Dataverse dataverse) {
if ( dataverse.getId() == null ) {
dataverse.setId( nextId() );
}
dvStore.put( dataverse.getId(), dataverse);
if ( dataverse.getAlias() != null ) {
dvByAliasStore.put( dataverse.getAlias(), dataverse);
}
return dataverse;
}
};
DataverseRoleServiceBean roles = new DataverseRoleServiceBean(){
List<RoleAssignment> assignments = new LinkedList<>();
Map<String, DataverseRole> builtInRoles;
{
builtInRoles = new HashMap<>();
builtInRoles.put( DataverseRole.EDITOR, makeRole("default-editor"));
builtInRoles.put( DataverseRole.ADMIN, makeRole("default-admin"));
builtInRoles.put( DataverseRole.MANAGER, makeRole("default-manager"));
}
@Override
public DataverseRole findBuiltinRoleByAlias(String alias) {
return builtInRoles.get(alias);
}
@Override
public RoleAssignment save(RoleAssignment assignment) {
assignment.setId( nextId() );
assignments.add(assignment);
return assignment;
}
@Override
public List<RoleAssignment> directRoleAssignments(DvObject dvo) {
// works since there's only one dataverse involved in the context
// of this unit test.
return assignments;
}
};
IndexServiceBean index = new IndexServiceBean(){
@Override
public Future<String> indexDataverse(Dataverse dataverse) {
indexCalled = true;
return null;
}
};
DataverseFieldTypeInputLevelServiceBean dfils = new DataverseFieldTypeInputLevelServiceBean(){
@Override
public void create(DataverseFieldTypeInputLevel dataverseFieldTypeInputLevel) {
createdDftils.add( dataverseFieldTypeInputLevel );
}
@Override
public void deleteFacetsFor(Dataverse d) {
dftilsDeleted = true;
}
};
DataverseFacetServiceBean facets = new DataverseFacetServiceBean() {
@Override
public DataverseFacet create(int displayOrder, DatasetFieldType fieldType, Dataverse ownerDv) {
DataverseFacet df = new DataverseFacet();
df.setDatasetFieldType(fieldType);
df.setDataverse(ownerDv);
df.setDisplayOrder(displayOrder);
createdFacets.add(df);
return df;
}
@Override
public void deleteFacetsFor(Dataverse d) {
facetsDeleted = true;
}
};
TestDataverseEngine engine;
@Before
public void setUp() {
indexCalled = false;
dvStore.clear();
dvByAliasStore.clear();
isRootDvExists = true;
facetsDeleted = false;
createdDftils = new ArrayList<>();
createdFacets = new ArrayList<>();
engine = new TestDataverseEngine( new TestCommandContext(){
@Override
public IndexServiceBean index() {
return index;
}
@Override
public DataverseRoleServiceBean roles() {
return roles;
}
@Override
public DataverseServiceBean dataverses() {
return dataverses;
}
@Override
public DataverseFacetServiceBean facets() {
return facets;
}
@Override
public DataverseFieldTypeInputLevelServiceBean fieldTypeInputLevels() {
return dfils;
}
} );
}
@Test
public void testDefaultOptions() throws CommandException {
Dataverse dv = makeDataverse();
dv.setCreateDate(null);
dv.setId(null);
dv.setCreator(null);
dv.setDefaultContributorRole(null);
dv.setOwner( makeDataverse() );
final DataverseRequest request = makeRequest(makeAuthenticatedUser("jk", "rollin'"));
CreateDataverseCommand sut = new CreateDataverseCommand(dv, request, null, null);
Dataverse result = engine.submit(sut);
assertNotNull( result.getCreateDate() );
assertNotNull( result.getId() );
assertEquals( result.getCreator(), request.getUser() );
assertEquals( Dataverse.DataverseType.UNCATEGORIZED, result.getDataverseType() );
assertEquals( roles.findBuiltinRoleByAlias(DataverseRole.EDITOR), result.getDefaultContributorRole() );
// Assert that the creator is admin.
final RoleAssignment roleAssignment = roles.directRoleAssignments(dv).get(0);
assertEquals( roles.findBuiltinRoleByAlias(DataverseRole.ADMIN), roleAssignment.getRole() );
assertEquals( dv, roleAssignment.getDefinitionPoint() );
assertEquals( roleAssignment.getAssigneeIdentifier(), request.getUser().getIdentifier() );
// The following is a pretty wierd way to test that the create date defaults to
// now, but it works across date changes.
assertTrue( "When the supplied creation date is null, date shuld default to command execution time",
Math.abs(System.currentTimeMillis() - result.getCreateDate().toInstant().toEpochMilli()) < 1000 );
assertTrue( result.isPermissionRoot() );
assertTrue( result.isThemeRoot() );
assertTrue( indexCalled );
}
@Test
public void testCustomOptions() throws CommandException {
Dataverse dv = makeDataverse();
Timestamp creation = timestamp(1990,12,12);
AuthenticatedUser creator = makeAuthenticatedUser("Joe", "Walsh");
dv.setCreateDate(creation);
dv.setId(null);
dv.setCreator(creator);
dv.setDefaultContributorRole(null);
dv.setOwner( makeDataverse() );
dv.setDataverseType(Dataverse.DataverseType.JOURNALS);
dv.setDefaultContributorRole( roles.findBuiltinRoleByAlias(DataverseRole.MANAGER) );
final DataverseRequest request = makeRequest();
List<DatasetFieldType> expectedFacets = Arrays.asList( makeDatasetFieldType(), makeDatasetFieldType(), makeDatasetFieldType());
List<DataverseFieldTypeInputLevel> dftils = Arrays.asList( makeDataverseFieldTypeInputLevel(makeDatasetFieldType()),
makeDataverseFieldTypeInputLevel(makeDatasetFieldType()),
makeDataverseFieldTypeInputLevel(makeDatasetFieldType()));
CreateDataverseCommand sut = new CreateDataverseCommand(dv, request, new LinkedList(expectedFacets), new LinkedList(dftils) );
Dataverse result = engine.submit(sut);
assertEquals( creation, result.getCreateDate() );
assertNotNull( result.getId() );
assertEquals( creator, result.getCreator() );
assertEquals( Dataverse.DataverseType.JOURNALS, result.getDataverseType() );
assertEquals( roles.findBuiltinRoleByAlias(DataverseRole.MANAGER), result.getDefaultContributorRole() );
// Assert that the creator is admin.
final RoleAssignment roleAssignment = roles.directRoleAssignments(dv).get(0);
assertEquals( roles.findBuiltinRoleByAlias(DataverseRole.ADMIN), roleAssignment.getRole() );
assertEquals( dv, roleAssignment.getDefinitionPoint() );
assertEquals( roleAssignment.getAssigneeIdentifier(), request.getUser().getIdentifier() );
assertTrue( result.isPermissionRoot() );
assertTrue( result.isThemeRoot() );
assertTrue( indexCalled );
assertTrue( facetsDeleted );
int i=0;
for ( DataverseFacet df : createdFacets ) {
assertEquals( i, df.getDisplayOrder() );
assertEquals( result, df.getDataverse() );
assertEquals( expectedFacets.get(i), df.getDatasetFieldType() );
i++;
}
assertTrue( dftilsDeleted );
for ( DataverseFieldTypeInputLevel dftil : createdDftils ) {
assertEquals( result, dftil.getDataverse() );
}
}
@Test( expected=IllegalCommandException.class )
public void testCantCreateAdditionalRoot() throws Exception {
engine.submit( new CreateDataverseCommand(makeDataverse(), makeRequest(), null, null) );
}
@Test( expected=IllegalCommandException.class )
public void testGuestCantCreateDataverse() throws Exception {
final DataverseRequest request = new DataverseRequest( GuestUser.get(), IpAddress.valueOf("::") );
isRootDvExists = false;
engine.submit(new CreateDataverseCommand(makeDataverse(), request, null, null) );
}
@Test( expected=IllegalCommandException.class )
public void testCantCreateAnotherWithSameAlias() throws Exception {
String alias = "alias";
final Dataverse dvFirst = makeDataverse();
dvFirst.setAlias(alias);
dvFirst.setOwner( makeDataverse() );
engine.submit(new CreateDataverseCommand(dvFirst, makeRequest(), null, null) );
final Dataverse dv = makeDataverse();
dv.setOwner( makeDataverse() );
dv.setAlias(alias);
engine.submit(new CreateDataverseCommand(dv, makeRequest(), null, null) );
}
}