package net.techreadiness.ui.tags.taskview; import java.beans.BeanInfo; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; import com.google.common.base.Predicate; import com.google.common.collect.Maps; import com.opensymphony.xwork2.util.TextParseUtil; import com.opensymphony.xwork2.util.ValueStack; public class RowInfo<T> { private T row; private T errorRow; private String fieldNamePrefix; private Map<String, List<String>> rowErrors; private boolean rowInError = false; @SuppressWarnings({ "unchecked", "rawtypes" }) public RowInfo(T row, ValueStack valueStack, String var, String fieldName) { this.row = row; try { valueStack.push(row); Map<String, Object> rowMap = Maps.newHashMap(); rowMap.put(var, row); try { valueStack.push(rowMap); fieldNamePrefix = TextParseUtil.translateVariables('%', fieldName, valueStack); } finally { valueStack.pop(); } } finally { valueStack.pop(); } Map<String, List<String>> errors = (Map<String, List<String>>) valueStack.findValue("fieldErrors"); rowErrors = getErrorsForCurrentRow(errors); rowInError = rowErrors != null && !rowErrors.isEmpty(); if (rowInError) { T target = (T) valueStack.findValue(fieldNamePrefix); if (row instanceof Map) { Map<?, ?> rowData = (Map<?, ?>) row; rowData.putAll((Map) target); errorRow = (T) rowData; } else { merge(target, row); errorRow = target; } } else { errorRow = row; } } private void merge(T target, T destination) { try { BeanInfo beanInfo = Introspector.getBeanInfo(target.getClass()); // Iterate over all the attributes for (PropertyDescriptor descriptor : beanInfo.getPropertyDescriptors()) { // Only copy writable attributes if (descriptor.getWriteMethod() != null) { Object originalValue = descriptor.getReadMethod().invoke(target); // Only copy values values where the destination values is null if (originalValue == null) { Object defaultValue = descriptor.getReadMethod().invoke(destination); descriptor.getWriteMethod().invoke(target, defaultValue); } } } } catch (Exception e) { throw new RuntimeException(e); } } public T getRow() { return row; } public T getErrorRow() { return errorRow; } public boolean isRowInError() { return rowInError; } protected Map<String, List<String>> getErrorsForCurrentRow(Map<String, List<String>> errors) { return Maps.filterKeys(errors, new FieldErrorFilter()); } class FieldErrorFilter implements Predicate<String> { @Override public boolean apply(String input) { return StringUtils.startsWith(input, fieldNamePrefix); } } }