package devopsdistilled.operp.client.abstracts;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
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.remoting.rmi.RmiServiceExporter;
import devopsdistilled.operp.server.data.entity.Entiti;
import devopsdistilled.operp.server.data.service.EntityService;
public abstract class AbstractEntityModel<E extends Entiti<?>, ES extends EntityService<E, ?>, EO extends EntityModelObserver>
extends AbstractModel<EO> implements EntityModel<E, ES, EO> {
@Inject
private ApplicationContext context;
protected List<E> entities;
public AbstractEntityModel() {
entities = new LinkedList<>();
}
@Override
public List<E> getEntities() {
return entities;
}
@Override
public void setEntities(List<E> entities) {
this.entities = entities;
notifyObservers();
}
@Override
public void update() {
setEntities(getService().findAll());
}
@Override
public void notifyObservers() {
for (EO observer : observers) {
Method updateMethod = getUpdateMethod();
try {
updateMethod.invoke(observer, getEntities());
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
e.printStackTrace();
}
}
}
@SuppressWarnings("unchecked")
protected Class<EO> getObserverClass() {
Type superclass = getClass().getGenericSuperclass();
Type[] typeArguments = ((ParameterizedType) superclass)
.getActualTypeArguments();
Class<EO> observerClass = (Class<EO>) (typeArguments[2]);
return observerClass;
}
private Method getUpdateMethod() {
Method[] methods = getObserverClass().getMethods();
return methods[0];
}
@Override
public E saveAndUpdateModel(E entity) {
E savedEntity = getService().save(entity);
getService().notifyClientsForUpdate();
return savedEntity;
}
@Override
public void deleteAndUpdateModel(E entity) {
getService().delete(entity);
getService().notifyClientsForUpdate();
}
@PostConstruct
public void registerWithServer() {
AutowireCapableBeanFactory factory = context
.getAutowireCapableBeanFactory();
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) factory;
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(RmiServiceExporter.class);
beanDefinition.setAutowireCandidate(true);
MutablePropertyValues propertyValues = new MutablePropertyValues();
Class<?> serviceInterface = this.getClass().getInterfaces()[0];
propertyValues.addPropertyValue("serviceInterface", serviceInterface);
String serviceName = serviceInterface.getCanonicalName();
propertyValues.addPropertyValue("serviceName", serviceName);
propertyValues.addPropertyValue("service", this);
propertyValues.addPropertyValue("registryPort", "1099");
beanDefinition.setPropertyValues(propertyValues);
registry.registerBeanDefinition(serviceName, beanDefinition);
context.getBean(serviceName); // Need this else
// NotBoundException
getService().registerClient(getHostAddress());
}
public String getHostAddress() {
try {
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface
.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface network = networkInterfaces.nextElement();
if (!network.isUp() || network.isLoopback()
|| network.isVirtual())
continue;
Enumeration<InetAddress> addresses = network.getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress netAddr = addresses.nextElement();
if (!netAddr.isLoopbackAddress()
&& (netAddr instanceof Inet4Address)) {
return netAddr.getHostAddress();
}
}
}
} catch (SocketException e) {
e.printStackTrace();
}
return "localhost";
}
}