![JAR search and dependency download from the Maven repository](/logo.png)
de.tsl2.nano.h5.collector.Controller Maven / Gradle / Ivy
/*
* File: $HeadURL$
* Id : $Id$
*
* created by: Tom, Thomas Schneider
* created on: 26.02.2014
*
* Copyright: (c) Thomas Schneider 2014, all rights reserved
*/
package de.tsl2.nano.h5.collector;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.simpleframework.xml.Transient;
import de.tsl2.nano.action.IAction;
import de.tsl2.nano.bean.BeanUtil;
import de.tsl2.nano.bean.def.Bean;
import de.tsl2.nano.bean.def.BeanCollector;
import de.tsl2.nano.bean.def.BeanDefinition;
import de.tsl2.nano.bean.def.ValueExpression;
import de.tsl2.nano.core.cls.IAttribute;
import de.tsl2.nano.core.util.NumberUtil;
import de.tsl2.nano.core.util.StringUtil;
/**
* Special {@link BeanCollector} to show a list of beans providing their actions. the defined bean should have some
* actions to change attributes in an easy way - like de- or increasing a value. The best use-case is to show a set of
* buttons with pictures on a touch-screen.
*
* Through the bean-definition of {@link #name}, a special bean, holding the actions, can start a selected action
* through {@link #doAction(String)}.
* The super class Compositor tries to build actions given by baseAttribute and targetAttribute.
* The second possibility for creating actions is to set an itemProvider through {@link #setItemProvider(Increaser)}.
*
* @author Tom, Thomas Schneider
* @version $Revision$
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public class Controller, T> extends Compositor {
/** serialVersionUID */
private static final long serialVersionUID = 1L;
public static final String PREFIX_CTRLACTION = "CTRLROW(";
public static final String POSTFIX_CTRLACTION = ")";
private static final String PREFIX_CONTROLLER = "controller";
/** the special bean-implementation holding all desired actions */
@Transient
Increaser itemProvider;
@Transient
boolean showText;
@Transient
boolean isTransparent=true;
/** if you want only one creation button/action per parent-instance, this should be true.
* if you want to provide different actions on one bean, this should be false */
@Transient
boolean creationOnly=false;
transient List attributes;
/**
* constructor
*/
protected Controller() {
super();
}
public Controller(String beanName) {
this(beanName, null, null, null, null);
}
/**
* constructor
*
* @param beanType
* @param workingMode
*/
public Controller(String beanName, String baseType, String baseAttribute, String targetAttribute, String iconAttribute) {
this((BeanDefinition) BeanDefinition.getBeanDefinition(beanName), (BeanDefinition) (baseType != null ? BeanDefinition.getBeanDefinition(baseType) : null), baseAttribute, targetAttribute, iconAttribute);
}
/**
* constructor
*
* @param beanType
* @param workingMode
*/
public Controller(BeanDefinition beanDef, BeanDefinition baseType, String baseAttribute, String targetAttribute, String iconAttribute) {
this(beanDef.getDeclaringClass(), baseType != null ? baseType.getDeclaringClass() : null, baseAttribute, targetAttribute, iconAttribute);
}
public Controller(Class beanDef, Class baseType, String baseAttribute, String targetAttribute, String iconAttribute) {
super(beanDef, baseType, baseAttribute, targetAttribute, iconAttribute);
this.name = createName(beanDef, baseType);
}
public String createName(Class> beanDef, Class> baseType) {
return createBeanDefName(beanDef, baseType);
}
public static String createBeanDefName(Class> beanDef, Class> baseType) {
return createBeanDefName("Controller", beanDef, baseType);
}
public Bean getBean(T instance) {
return getBean(instance, null);
}
/**
* gets the defined bean (see {@link #name} for the given instance.
*
* @param instance
* @param collected (optional) to add actions only once per instance
* @return bean holding instance
*/
public Bean getBean(T instance, Collection collected) {
Bean bean = BeanUtil.copy((Bean) Bean.getBean(name));
bean.setValueExpression(getValueExpression());
bean.setInstance(instance);
bean.setAddSaveAction(false);
//if controlling from baseType (annotation on baseType), we want exactly one creation-action
if (getDeclaringClass().equals(parentType) || isCreationOnly()) {
if (parentType != null && !getDeclaringClass().equals(parentType)) {
instance = getParentInstance(instance);
}
if (collected == null || !collected.contains(instance)) {
if (collected != null) //only to avoid adding the same actions on several instances!
collected.add(instance);
Collection compActions = super.getActions();
String compositorActionId = createCompositorActionId(instance);
for (IAction a : compActions) {
if (a.getId().equals(compositorActionId)) {
bean.setActions(Arrays.asList(a));
break;
}
}
}
} else {//on each row get all compositor actions
bean.setActions(super.getActions());
//filter collector actions
for (Iterator it = bean.getActions().iterator(); it.hasNext();) {
IAction a = (IAction) it.next();
//TODO: internal name convention - is there a better way?
if (!a.getId().startsWith(PREFIX_CONTROLLER))
it.remove();
}
}
return bean;
}
@Override
public Collection getActions() {
return new LinkedList<>(); //don't show the actions in the action panel again!
}
/**
* extracts the bean-instance and the action id and starts it.
*
* @param actionIdWithRowNumber the row-number has to be one-based!
* @param session
* @return result of given action
*/
public Object doAction(String actionIdWithRowNumber, Map context) {
String strRow = StringUtil.substring(actionIdWithRowNumber, PREFIX_CTRLACTION, POSTFIX_CTRLACTION);
Number row = NumberUtil.extractNumber(strRow);
assert row.intValue() > 0 : "row must be one-based!";
ArrayList list = new ArrayList(getCurrentData());
assert row.intValue() <= list.size() : "row=" + row + " (one-based) is outside of list size=" + list.size();
String id = StringUtil.substring(actionIdWithRowNumber, POSTFIX_CTRLACTION, null);
IAction> action = getBean(list.get(row.intValue() - 1)).getAction(id);
assert action != null : "no action with id=" + id + " found on (one-based) row " + row + "! see: " + StringUtil.toString(list, 120);
action.setParameter(context);
return action.activate();
}
@Override
public boolean isVirtual() {
return true;
}
@Override
public ValueExpression getValueExpression() {
if (valueExpression == null) {
//use the expression of the standard definition
valueExpression = BeanDefinition.getBeanDefinition(getType()).getValueExpression();
}
return valueExpression;
}
@Override
public Compositor refreshed() {
if (isStale())
return new Controller(clazz, parentType, baseAttribute, targetAttribute, iconAttribute);
return this;
}
@Override
public > B onActivation(Map context) {
if (itemProvider != null && itemProvider.getCount() > getCurrentData().size()) {
//TODO: create only missing items
getCurrentData().addAll(provideTransientData(context));
}
return super.onActivation(context);
}
private Collection extends T> provideTransientData(Map context) {
T item = createItem(null);
if (context != null)
fillContext(item, context.values().toArray());
return itemProvider.createItems(item, context);
}
/**
* @return Returns the itemProvider.
*/
public Increaser getItemProvider() {
return itemProvider;
}
/**
* @param itemProvider The itemProvider to set.
*/
public Controller setItemProvider(Increaser itemProvider) {
this.itemProvider = itemProvider;
setValueExpression(new ValueExpression("{" + itemProvider.getName() + "}"));
return this;
}
public static String createActionName(int row, String id) {
assert row > 0 : "row must be one-based!";
return PREFIX_CTRLACTION + row + POSTFIX_CTRLACTION + id;
}
public boolean showText() {
return showText;
}
public boolean isTransparent() {
return isTransparent;
}
public boolean isCreationOnly() {
return creationOnly;
}
public void setShowText(boolean showText) {
this.showText = showText;
}
public void setTransparent(boolean isTransparent) {
this.isTransparent = isTransparent;
}
public void setCreationOnly(boolean creationOnly) {
this.creationOnly = creationOnly;
}
public void setPresentationValues(boolean showText, boolean transparent, boolean creationOnly) {
setShowText(showText);
setTransparent(transparent);
setCreationOnly(creationOnly);
}
@Override
protected long count() {
//to guarantee an automatic search in onActivation()
return 0;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy