001: /*
002: * Copyright (c) 2002-2006 by OpenSymphony
003: * All rights reserved.
004: */
005: package com.opensymphony.xwork.util;
006:
007: import com.opensymphony.xwork.ObjectFactory;
008: import com.opensymphony.xwork.XworkException;
009: import ognl.ListPropertyAccessor;
010: import ognl.OgnlException;
011:
012: import java.util.Collection;
013: import java.util.List;
014: import java.util.Map;
015:
016: /**
017: * Overrides the list property accessor so in the case of trying
018: * to add properties of a given bean and the JavaBean is not present,
019: * this class will create the necessary blank JavaBeans.
020: *
021: * @author Gabriel Zimmerman
022: */
023: public class XWorkListPropertyAccessor extends ListPropertyAccessor {
024:
025: private XWorkCollectionPropertyAccessor _sAcc = new XWorkCollectionPropertyAccessor();
026:
027: public Object getProperty(Map context, Object target, Object name)
028: throws OgnlException {
029:
030: if (OgnlContextState.isGettingByKeyProperty(context)
031: || name
032: .equals(XWorkCollectionPropertyAccessor.KEY_PROPERTY_FOR_CREATION)) {
033: return _sAcc.getProperty(context, target, name);
034: } else if (name instanceof String) {
035: return super .getProperty(context, target, name);
036: }
037: OgnlContextState.updateCurrentPropertyPath(context, name);
038: //System.out.println("Entering XWorkListPropertyAccessor. Name: " + name);
039: Class lastClass = (Class) context
040: .get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED);
041: String lastProperty = (String) context
042: .get(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED);
043:
044: if (name instanceof Number
045: && OgnlContextState.isCreatingNullObjects(context)
046: && XWorkConverter.getInstance()
047: .getObjectTypeDeterminer().shouldCreateIfNew(
048: lastClass, lastProperty, target, null,
049: true)) {
050:
051: //System.out.println("Getting index from List");
052: List list = (List) target;
053: int index = ((Number) name).intValue();
054: int listSize = list.size();
055:
056: if (lastClass == null || lastProperty == null) {
057: return super .getProperty(context, target, name);
058: }
059: Class beanClass = XWorkConverter.getInstance()
060: .getObjectTypeDeterminer().getElementClass(
061: lastClass, lastProperty, name);
062: if (listSize <= index) {
063: Object result = null;
064:
065: for (int i = listSize; i < index; i++) {
066:
067: list.add(null);
068:
069: }
070: try {
071: list.add(index, result = ObjectFactory
072: .getObjectFactory().buildBean(beanClass,
073: context));
074: } catch (Exception exc) {
075: throw new XworkException(exc);
076: }
077: return result;
078: } else if (list.get(index) == null) {
079: Object result = null;
080: try {
081: list.set(index, result = ObjectFactory
082: .getObjectFactory().buildBean(beanClass,
083: context));
084: } catch (Exception exc) {
085: throw new XworkException(exc);
086: }
087: return result;
088: }
089: }
090: return super .getProperty(context, target, name);
091: }
092:
093: public void setProperty(Map context, Object target, Object name,
094: Object value) throws OgnlException {
095:
096: Class lastClass = (Class) context
097: .get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED);
098: String lastProperty = (String) context
099: .get(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED);
100: Class convertToClass = XWorkConverter.getInstance()
101: .getObjectTypeDeterminer().getElementClass(lastClass,
102: lastProperty, name);
103:
104: if (name instanceof String && value.getClass().isArray()) {
105: // looks like the input game in the form of "someList.foo" and
106: // we are expected to define the index values ourselves.
107: // So let's do it:
108:
109: Collection c = (Collection) target;
110: Object[] values = (Object[]) value;
111: for (int i = 0; i < values.length; i++) {
112: Object v = values[i];
113: try {
114: Object o = ObjectFactory.getObjectFactory()
115: .buildBean(convertToClass, context);
116: OgnlUtil.setValue((String) name, context, o, v);
117: c.add(o);
118: } catch (Exception e) {
119: throw new OgnlException(
120: "Error converting given String values for Collection.",
121: e);
122: }
123: }
124:
125: // we don't want to do the normal list property setting now, since we've already done the work
126: // just return instead
127: return;
128: }
129:
130: Object realValue = getRealValue(context, value, convertToClass);
131:
132: if (target instanceof List && name instanceof Number) {
133: //make sure there are enough spaces in the List to set
134: List list = (List) target;
135: int listSize = list.size();
136: int count = ((Number) name).intValue();
137: if (count >= listSize) {
138: for (int i = listSize; i <= count; i++) {
139: list.add(null);
140: }
141: }
142: }
143:
144: super .setProperty(context, target, name, realValue);
145: }
146:
147: private Object getRealValue(Map context, Object value,
148: Class convertToClass) {
149: if (value == null || convertToClass == null) {
150: return value;
151: }
152: return XWorkConverter.getInstance().convertValue(context,
153: value, convertToClass);
154: }
155: }
|