package org.molgenis.data.meta.system;
import com.google.common.collect.Maps;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.molgenis.data.DataService;
import org.molgenis.data.Entity;
import org.molgenis.data.RepositoryCollection;
import org.molgenis.data.meta.EntityTypeDependencyResolver;
import org.molgenis.data.meta.MetaDataService;
import org.molgenis.data.meta.model.Attribute;
import org.molgenis.data.meta.model.AttributeMetadata;
import org.molgenis.data.meta.model.EntityType;
import org.molgenis.data.meta.model.Package;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.util.Map;
import java.util.stream.Stream;
import static com.google.common.collect.Lists.newArrayList;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static java.util.stream.Collectors.toList;
import static org.mockito.Mockito.*;
import static org.molgenis.data.meta.model.AttributeMetadata.REF_ENTITY_TYPE;
import static org.molgenis.data.meta.model.EntityTypeMetadata.ENTITY_TYPE_META_DATA;
import static org.molgenis.data.meta.model.PackageMetadata.PACKAGE;
import static org.molgenis.data.system.model.RootSystemPackage.PACKAGE_SYSTEM;
import static org.testng.Assert.assertEquals;
public class SystemEntityTypePersisterTest
{
private DataService dataService;
private SystemEntityTypeRegistry systemEntityTypeRegistry;
private SystemEntityTypePersister systemEntityTypePersister;
private AttributeMetadata attrMetaMeta;
private MetaDataService metaDataService;
@Captor
ArgumentCaptor<Stream<Object>> objectIdCaptor;
@BeforeMethod
public void setUpBeforeMethod()
{
MockitoAnnotations.initMocks(this);
attrMetaMeta = mock(AttributeMetadata.class);
metaDataService = mock(MetaDataService.class);
RepositoryCollection defaultRepoCollection = mock(RepositoryCollection.class);
when(metaDataService.getDefaultBackend()).thenReturn(defaultRepoCollection);
dataService = mock(DataService.class);
when(dataService.getMeta()).thenReturn(metaDataService);
systemEntityTypeRegistry = mock(SystemEntityTypeRegistry.class);
EntityTypeDependencyResolver entityTypeDependencyResolver = mock(EntityTypeDependencyResolver.class);
systemEntityTypePersister = new SystemEntityTypePersister(dataService, systemEntityTypeRegistry,
entityTypeDependencyResolver);
}
@Test
public void removeNonExistingSystemEntities() throws Exception
{
Package systemPackage = mock(Package.class);
when(systemPackage.getName()).thenReturn(PACKAGE_SYSTEM);
EntityType refRemovedMeta = when(mock(EntityType.class).getName()).thenReturn("refRemoved").getMock();
when(refRemovedMeta.getPackage()).thenReturn(systemPackage);
when(refRemovedMeta.toString()).thenReturn("refRemoved");
when(refRemovedMeta.getAtomicAttributes()).thenReturn(emptyList());
EntityType removedMeta = when(mock(EntityType.class).getName()).thenReturn("removed").getMock();
when(removedMeta.getPackage()).thenReturn(systemPackage);
when(removedMeta.toString()).thenReturn("removed");
Attribute refAttr = when(mock(Attribute.class).getRefEntity()).thenReturn(refRemovedMeta).getMock();
when(removedMeta.getAtomicAttributes()).thenReturn(singletonList(refAttr));
EntityType refEntityType = when(mock(EntityType.class).getName()).thenReturn("refEntity").getMock();
when(refEntityType.getPackage()).thenReturn(systemPackage);
when(refEntityType.toString()).thenReturn("refEntity");
when(refEntityType.getAtomicAttributes()).thenReturn(emptyList());
EntityType entityType = when(mock(EntityType.class).getName()).thenReturn("entity").getMock();
when(entityType.getPackage()).thenReturn(systemPackage);
when(entityType.toString()).thenReturn("entity");
when(entityType.getAtomicAttributes()).thenReturn(emptyList());
when(systemEntityTypeRegistry.hasSystemEntityType("removed")).thenReturn(false);
when(systemEntityTypeRegistry.hasSystemEntityType("refRemoved")).thenReturn(false);
when(systemEntityTypeRegistry.hasSystemEntityType("entity")).thenReturn(true);
when(systemEntityTypeRegistry.hasSystemEntityType("refEntity")).thenReturn(true);
when(dataService.findAll(ENTITY_TYPE_META_DATA, EntityType.class))
.thenReturn(Stream.of(refEntityType, entityType, refRemovedMeta, removedMeta));
systemEntityTypePersister.removeNonExistingSystemEntities();
verify(metaDataService).deleteEntityType(newArrayList(refRemovedMeta, removedMeta));
}
@Test
public void persistSystemPackageChange()
{
Attribute attr = mock(Attribute.class);
when(attrMetaMeta.getAttribute(REF_ENTITY_TYPE)).thenReturn(attr);
when(attr.setDataType(any())).thenReturn(attr);
when(dataService.findAll(ENTITY_TYPE_META_DATA, EntityType.class)).thenReturn(Stream.empty());
when(dataService.findAll(eq(ENTITY_TYPE_META_DATA), objectIdCaptor.capture(), eq(EntityType.class)))
.thenReturn(Stream.empty());
when(systemEntityTypeRegistry.getSystemEntityTypes()).thenAnswer(new EmptyStreamAnswer());
ContextRefreshedEvent event = mock(ContextRefreshedEvent.class);
ApplicationContext applicationContext = mock(ApplicationContext.class);
String packageName0 = "packageName0";
Package package0 = when(mock(Package.class).getIdValue()).thenReturn(packageName0).getMock();
String packageName1 = "packageName1";
Package package1 = when(mock(Package.class).getIdValue()).thenReturn(packageName1).getMock();
Map<String, Package> packageMap = Maps.newHashMap();
packageMap.put(packageName0, package0);
packageMap.put(packageName1, package1);
when(applicationContext.getBeansOfType(Package.class)).thenReturn(packageMap);
when(event.getApplicationContext()).thenReturn(applicationContext);
when(dataService.findOneById(PACKAGE, packageName0, Package.class)).thenReturn(package0);
when(dataService.findOneById(PACKAGE, packageName1, Package.class)).thenReturn(null);
systemEntityTypePersister.persist(event);
@SuppressWarnings("unchecked")
ArgumentCaptor<Stream<Entity>> captor = ArgumentCaptor.forClass((Class) Stream.class);
verify(dataService).add(eq(PACKAGE), captor.capture());
assertEquals(captor.getValue().collect(toList()), newArrayList(package1));
}
// regression test for https://github.com/molgenis/molgenis/issues/5168
@SuppressWarnings("unchecked")
@Test
public void persistSystemPackageNoChange()
{
Attribute attr = mock(Attribute.class);
when(attrMetaMeta.getAttribute(REF_ENTITY_TYPE)).thenReturn(attr);
when(attr.setDataType(any())).thenReturn(attr);
when(dataService.findAll(ENTITY_TYPE_META_DATA, EntityType.class)).thenReturn(Stream.empty());
when(dataService.findAll(eq(ENTITY_TYPE_META_DATA), objectIdCaptor.capture(), eq(EntityType.class)))
.thenReturn(Stream.empty());
when(systemEntityTypeRegistry.getSystemEntityTypes()).thenAnswer(new EmptyStreamAnswer());
ContextRefreshedEvent event = mock(ContextRefreshedEvent.class);
ApplicationContext applicationContext = mock(ApplicationContext.class);
String packageName0 = "packageName0";
Package package0 = when(mock(Package.class).getIdValue()).thenReturn(packageName0).getMock();
String packageName1 = "packageName1";
Package package1 = when(mock(Package.class).getIdValue()).thenReturn(packageName1).getMock();
Map<String, Package> packageMap = Maps.newHashMap();
packageMap.put(packageName0, package0);
packageMap.put(packageName1, package1);
when(applicationContext.getBeansOfType(Package.class)).thenReturn(packageMap);
when(event.getApplicationContext()).thenReturn(applicationContext);
when(dataService.findOneById(PACKAGE, packageName0, Package.class)).thenReturn(package0);
when(dataService.findOneById(PACKAGE, packageName1, Package.class)).thenReturn(package1);
systemEntityTypePersister.persist(event);
verify(dataService, times(0)).add(eq(PACKAGE), any(Stream.class));
}
private static class EmptyStreamAnswer implements Answer<Stream<EntityType>>
{
@Override
public Stream<EntityType> answer(InvocationOnMock invocation) throws Throwable
{
return Stream.empty();
}
}
}