package org.jboss.seam.remoting.model; import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.UUID; import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.BeanManager; import org.jboss.seam.remoting.AnnotationsParser; import org.jboss.seam.remoting.Call; import org.jboss.seam.remoting.CallContext; import org.jboss.seam.remoting.util.Strings; /** * Manages a model request * * @author Shane Bryzak */ public class Model implements Serializable { private static final long serialVersionUID = 8318288750036758325L; private BeanManager beanManager; private String id; private CallContext callContext; private Call action; public class BeanProperty implements Serializable { private static final long serialVersionUID = 540993772239615536L; private Bean<?> bean; private String propertyName; private Object value; public BeanProperty(Bean<?> bean, String propertyName) { this.bean = bean; this.propertyName = propertyName; } public Bean<?> getBean() { return bean; } public void evaluate(CreationalContext<?> ctx) { Object instance = beanManager.getReference(bean, bean.getBeanClass(), ctx); if (propertyName != null) { try { Field f = bean.getBeanClass().getField(propertyName); boolean accessible = f.isAccessible(); try { f.setAccessible(true); value = f.get(instance); } catch (Exception e) { throw new RuntimeException( "Exception reading model property " + propertyName + " from bean [" + bean + "]"); } finally { f.setAccessible(accessible); } } catch (NoSuchFieldException ex) { // Try the getter method String methodName = "get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1); try { Method m = bean.getBeanClass().getMethod(methodName); value = m.invoke(instance); } catch (Exception e) { throw new RuntimeException( "Exception reading model property " + propertyName + " from bean [" + bean + "]"); } } } else { this.value = instance; } } public Object getValue() { return value; } } private Map<String, BeanProperty> beanProperties; public Model(BeanManager beanManager) { this.beanManager = beanManager; id = UUID.randomUUID().toString(); callContext = new CallContext(beanManager); beanProperties = new HashMap<String, BeanProperty>(); } /** * Evaluate each of the model's bean properties, expressions, etc and * store the values in the BeanProperty map. */ public void evaluate() { for (String alias : beanProperties.keySet()) { BeanProperty property = beanProperties.get(alias); property.evaluate(beanManager.createCreationalContext(property.getBean())); } } public Map<String, BeanProperty> getBeanProperties() { return beanProperties; } public String getId() { return id; } public CallContext getCallContext() { return callContext; } public void addBean(String alias, String beanName, String qualifiers, String propertyName) { Set<Bean<?>> beans = beanManager.getBeans(beanName); if (beans.isEmpty()) { try { Class<?> beanType = Class.forName(beanName); Annotation[] q = qualifiers != null && !Strings.isEmpty(qualifiers) ? new AnnotationsParser(beanType, qualifiers, beanManager).getAnnotations() : Call.EMPTY_ANNOTATIONS; beans = beanManager.getBeans(beanType, q); } catch (ClassNotFoundException ex) { throw new IllegalArgumentException("Invalid bean class specified: " + beanName); } if (beans.isEmpty()) { throw new IllegalArgumentException( "Could not find bean with bean with type/name " + beanName + ", qualifiers [" + qualifiers + "]"); } } Bean<?> bean = beans.iterator().next(); beanProperties.put(alias, new BeanProperty(bean, propertyName)); } public void setAction(Call action) { this.action = action; } public Call getAction() { return action; } }