package devopsdistilled.operp.server.data.service.impl;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.LinkedList;
import java.util.List;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.remoting.RemoteConnectFailureException;
import org.springframework.remoting.rmi.RmiProxyFactoryBean;
import devopsdistilled.operp.client.abstracts.EntityModel;
import devopsdistilled.operp.server.ServerApp;
import devopsdistilled.operp.server.data.entity.Entiti;
import devopsdistilled.operp.server.data.service.EntityService;
public abstract class AbstractEntityService<E extends Entiti<?>, ID extends Serializable, ER extends JpaRepository<E, ID>, EM extends EntityModel<E, ?, ?>>
implements EntityService<E, ID> {
private static final long serialVersionUID = 4892118695516828793L;
protected abstract ER getRepo();
protected List<EM> entityModels = new LinkedList<>();
public void registerEntityModel(EM entityModel) {
entityModels.add(entityModel);
}
public void removeEntityModel(EM entityModel) {
int i = entityModels.indexOf(entityModel);
if (i >= 0) {
entityModels.remove(i);
}
}
@Override
public void notifyClientsForUpdate() {
for (EM entityModel : entityModels) {
try {
entityModel.update();
} catch (RemoteConnectFailureException e) {
entityModels.remove(entityModel);
}
}
}
@Override
public boolean isEntityNameExists(String entityName) {
E entity = findByEntityName(entityName);
if (entity != null)
return true;
return false;
}
@Override
public boolean isEntityNameValidForTheEntity(ID id, String entityName) {
E entity = findByEntityName(entityName);
if (entity == null)
return true;
if (entity.id().equals(id))
return true;
return false;
}
protected abstract E findByEntityName(String entityName);
@Override
public List<E> findAll() {
return getRepo().findAll();
}
@Override
public List<E> findAll(Sort sort) {
return getRepo().findAll(sort);
}
@Override
public <S extends E> List<S> save(Iterable<S> entities) {
return getRepo().save(entities);
}
@Override
public void flush() {
getRepo().flush();
}
@Override
public E saveAndFlush(E entity) {
return getRepo().saveAndFlush(entity);
}
@Override
public void deleteInBatch(Iterable<E> entities) {
getRepo().deleteInBatch(entities);
}
@Override
public void deleteAllInBatch() {
getRepo().deleteAllInBatch();
}
@Override
public Page<E> findAll(Pageable pageable) {
return getRepo().findAll(pageable);
}
@Override
public <S extends E> S save(S entity) {
return getRepo().save(entity);
}
@Override
public E findOne(ID id) {
return getRepo().findOne(id);
}
@Override
public boolean exists(ID id) {
return getRepo().exists(id);
}
@Override
public long count() {
return getRepo().count();
}
@Override
public void delete(ID id) {
getRepo().delete(id);
}
@Override
public void delete(E entity) {
getRepo().delete(entity);
}
@Override
public void delete(Iterable<? extends E> entities) {
getRepo().delete(entities);
}
@Override
public void deleteAll() {
getRepo().deleteAll();
}
@Override
public Iterable<E> findAll(Iterable<ID> ids) {
return getRepo().findAll(ids);
}
@Override
public void registerClient(String clientAddress) {
System.out.println("Client from " + clientAddress);
ApplicationContext context = ServerApp.getApplicationContext();
AutowireCapableBeanFactory factory = context
.getAutowireCapableBeanFactory();
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) factory;
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(RmiProxyFactoryBean.class);
beanDefinition.setAutowireCandidate(true);
Class<EM> entityModelInterfaceClass = getEntityModelInterfaceClass();
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.addPropertyValue("serviceInterface",
entityModelInterfaceClass);
propertyValues.addPropertyValue("serviceUrl", "rmi://" + clientAddress
+ ":1099/" + entityModelInterfaceClass.getCanonicalName());
beanDefinition.setPropertyValues(propertyValues);
registry.registerBeanDefinition(
entityModelInterfaceClass.getCanonicalName(), beanDefinition);
EM entityModel = context.getBean(entityModelInterfaceClass);
registerEntityModel(entityModel);
System.out.println(entityModel);
}
@SuppressWarnings("unchecked")
protected Class<EM> getEntityModelInterfaceClass() {
Type superclass = getClass().getGenericSuperclass();
Type[] typeArguments = ((ParameterizedType) superclass)
.getActualTypeArguments();
Class<EM> observerClass = (Class<EM>) (typeArguments[typeArguments.length - 1]);
return observerClass;
}
}