package org.molgenis.data.meta.system;
import org.molgenis.data.meta.MetaDataService;
import org.molgenis.data.meta.SystemEntityType;
import org.molgenis.data.meta.SystemPackage;
import org.molgenis.data.meta.model.AttributeMetadata;
import org.molgenis.data.meta.model.EntityTypeMetadata;
import org.molgenis.data.meta.model.MetaPackage;
import org.molgenis.data.system.model.RootSystemPackage;
import org.molgenis.util.GenericDependencyResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import java.util.Map;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
/**
* Discovers and initializes {@link SystemEntityType} beans.
*/
@Component
public class SystemEntityTypeInitializer
{
private final MetaDataService metaDataService;
private final RootSystemPackage rootSystemPackage;
private final MetaPackage metaPackage;
private final GenericDependencyResolver genericDependencyResolver;
@Autowired
public SystemEntityTypeInitializer(MetaDataService metaDataService, RootSystemPackage rootSystemPackage,
MetaPackage metaPackage, GenericDependencyResolver genericDependencyResolver)
{
this.metaDataService = requireNonNull(metaDataService);
this.rootSystemPackage = requireNonNull(rootSystemPackage);
this.metaPackage = requireNonNull(metaPackage);
this.genericDependencyResolver = genericDependencyResolver;
}
public void initialize(ContextRefreshedEvent event)
{
ApplicationContext ctx = event.getApplicationContext();
ctx.getBeansOfType(SystemPackage.class).values().forEach(SystemPackage::bootstrap);
EntityTypeMetadata entityTypeMetaData = ctx.getBean(EntityTypeMetadata.class);
ctx.getBean(AttributeMetadata.class).bootstrap(entityTypeMetaData);
//TODO: doesn't this mean all attributes get added twice?
Map<String, SystemEntityType> systemEntityTypeMap = ctx.getBeansOfType(SystemEntityType.class);
genericDependencyResolver.resolve(systemEntityTypeMap.values(), SystemEntityType::getDependencies)
.forEach(systemEntityType -> initialize(systemEntityType, entityTypeMetaData));
}
private void initialize(SystemEntityType systemEntityType, EntityTypeMetadata entityTypeMetaData)
{
systemEntityType.bootstrap(entityTypeMetaData);
setDefaultBackend(systemEntityType);
setPackage(systemEntityType);
checkPackage(systemEntityType);
}
private void setDefaultBackend(SystemEntityType systemEntityType)
{
if (systemEntityType.getBackend() == null)
{
systemEntityType.setBackend(metaDataService.getDefaultBackend().getName());
}
}
private void checkPackage(SystemEntityType systemEntityType)
{
if (!systemEntityType.getPackage().getRootPackage().getName().equals(rootSystemPackage.getName()))
{
throw new RuntimeException(format("System entity [%s] must be in package [%s]", systemEntityType.getName(),
rootSystemPackage.getName()));
}
}
private void setPackage(SystemEntityType systemEntityType)
{
if (systemEntityType.getPackage() == null)
{
if (metaDataService.isMetaEntityType(systemEntityType))
{
systemEntityType.setPackage(metaPackage);
}
else
{
systemEntityType.setPackage(rootSystemPackage);
}
}
}
}