package org.molgenis.data; import org.molgenis.data.meta.SystemEntityType; import org.molgenis.data.meta.model.EntityType; import org.molgenis.data.populate.EntityPopulator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import static java.util.Objects.requireNonNull; /** * Entity factory base class * * @param <E> entity type * @param <M> entity meta data type * @param <P> entity id type */ public abstract class AbstractSystemEntityFactory<E extends Entity, M extends SystemEntityType, P> implements EntityFactory<E, P> { private static final Logger LOG = LoggerFactory.getLogger(AbstractSystemEntityFactory.class); private final Class<E> entityClass; private final Constructor<E> entityConstructorWithEntity; private final Constructor<E> entityConstructorWithEntityType; private final M systemEntityType; private final EntityPopulator entityPopulator; /** * Constructs a new entity factory that creates entities of the given type, meta data type and id type * * @param entityClass entity type * @param systemEntityType entity meta data type * @param entityPopulator entity populator */ protected AbstractSystemEntityFactory(Class<E> entityClass, M systemEntityType, EntityPopulator entityPopulator) { this.entityClass = requireNonNull(entityClass); // determining constructors at creation time validates that required constructors exist on start-up this.entityConstructorWithEntity = getConstructorEntity(entityClass); this.entityConstructorWithEntityType = getConstructorEntityType(entityClass); this.systemEntityType = systemEntityType; this.entityPopulator = requireNonNull(entityPopulator); } public M getEntityType() { return systemEntityType; } @Override public String getEntityName() { return systemEntityType.getName(); } @Override public E create() { E entity; try { entity = entityConstructorWithEntityType.newInstance(systemEntityType); } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { throw new RuntimeException(e); } entityPopulator.populate(entity); return entity; } @Override public E create(P id) { E entity = create(); entity.setIdValue(id); return entity; } @SuppressWarnings("unchecked") @Override public E create(Entity entity) { if (entity == null) { return null; } if (entity.getClass().equals(entityClass)) { return (E) entity; } try { return entityConstructorWithEntity.newInstance(entity); } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { throw new RuntimeException(e); } } private Constructor<E> getConstructorEntity(Class<E> entityClass) { try { return entityClass.getConstructor(Entity.class); } catch (NoSuchMethodException e) { LOG.error("[{}] is missing the required constructor [public {}({})", entityClass.getName(), entityClass.getSimpleName(), Entity.class.getSimpleName()); throw new RuntimeException(e); } } private Constructor<E> getConstructorEntityType(Class<E> entityClass) { try { return entityClass.getConstructor(EntityType.class); } catch (NoSuchMethodException e) { LOG.error("[{}] is missing the required constructor [public {}({})", entityClass.getName(), entityClass.getSimpleName(), EntityType.class.getSimpleName()); throw new RuntimeException(e); } } }