blob: 67e6b687909bf3924c88a9bdb2cbfe7df8e0ee30 [file] [log] [blame]
package org.apache.struts2.uelplugin.elresolvers;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
import com.opensymphony.xwork2.XWorkException;
import javax.el.ELContext;
import java.util.List;
import java.util.Map;
import java.util.Collection;
public class XWorkListELResolver extends AbstractResolver {
public XWorkListELResolver(Container container) {
super(container);
}
public Object getValue(ELContext elContext, Object target, Object property) {
Map<String, Object> context = (Map) elContext.getContext(AccessorsContextKey.class);
if (target != null && property != null && target instanceof List) {
List list = (List) target;
Class lastClass = (Class) context.get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED);
String lastProperty = (String) context.get(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED);
Integer numericValue = null;
try {
numericValue = Integer.valueOf(property.toString());
} catch (NumberFormatException e) {
//ignore
}
if (numericValue != null
&& ReflectionContextState.isCreatingNullObjects(context)
&& objectTypeDeterminer.shouldCreateIfNew(lastClass, lastProperty, target, null, true)) {
int index = numericValue.intValue();
int listSize = list.size();
/*if (lastClass == null || lastProperty == null) {
return super.getProperty(context, target, name);
}*/
Class beanClass = objectTypeDeterminer.getElementClass(lastClass, lastProperty, property);
if (listSize <= index) {
Object result = null;
for (int i = listSize; i < index; i++) {
list.add(null);
}
try {
list.add(index, result = objectFactory.buildBean(beanClass, context));
} catch (Exception exc) {
throw new XWorkException(exc);
}
elContext.setPropertyResolved(true);
return result;
} else if (list.get(index) == null) {
Object result = null;
try {
list.set(index, result = objectFactory.buildBean(beanClass, context));
} catch (Exception exc) {
throw new XWorkException(exc);
}
elContext.setPropertyResolved(true);
return result;
} else {
elContext.setPropertyResolved(true);
return list.get(index);
}
} else {
//try normal list
if (numericValue < list.size()) {
elContext.setPropertyResolved(true);
return list.get(numericValue);
}
}
}
return null;
}
public void setValue(ELContext elContext, Object target, Object property, Object value) {
Map<String, Object> context = (Map) elContext.getContext(AccessorsContextKey.class);
if (target != null && property != null && target instanceof List) {
Class lastClass = (Class) context.get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED);
String lastProperty = (String) context.get(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED);
Class convertToClass = objectTypeDeterminer.getElementClass(lastClass, lastProperty, property);
if (property instanceof String && value.getClass().isArray()) {
// looks like the input game in the form of "someList.foo" and
// we are expected to define the index values ourselves.
// So let's do it:
Collection c = (Collection) value;
Object[] values = (Object[]) value;
for (Object v : values) {
try {
Object o = objectFactory.buildBean(convertToClass, context);
reflectionProvider.setProperty(property.toString(), value, target, context);
c.add(o);
} catch (Exception e) {
throw new XWorkException("Error converting given String values for Collection.", e);
}
}
}
Object realValue = getRealValue(context, value, convertToClass);
Long numericValue = null;
try {
numericValue = Long.valueOf(property.toString());
} catch (NumberFormatException e) {
//ignore
}
if (target instanceof List && numericValue != null) {
//make sure there are enough spaces in the List to set
List list = (List) target;
int listSize = list.size();
int count = numericValue.intValue();
if (count >= listSize) {
for (int i = listSize; i <= count; i++) {
list.add(null);
}
}
((List) target).set(numericValue.intValue(), realValue);
}
}
}
private Object getRealValue(Map context, Object value, Class convertToClass) {
if (value == null || convertToClass == null) {
return value;
}
return xworkConverter.convertValue(context, value, convertToClass);
}
}