001: /*
002: * Copyright (c) 2002-2006 by OpenSymphony
003: * All rights reserved.
004: */
005:
006: package com.opensymphony.xwork.util;
007:
008: import com.opensymphony.xwork.ObjectFactory;
009: import ognl.MapPropertyAccessor;
010: import ognl.OgnlException;
011:
012: import java.util.Map;
013:
014: import org.apache.commons.logging.Log;
015: import org.apache.commons.logging.LogFactory;
016:
017: /**
018: * Implementation of PropertyAccessor that sets and gets properties by storing and looking
019: * up values in Maps.
020: *
021: * @author Gabriel Zimmerman
022: */
023: public class XWorkMapPropertyAccessor extends MapPropertyAccessor {
024:
025: private static final Log _log = LogFactory
026: .getLog(XWorkMapPropertyAccessor.class);
027:
028: private static final String[] INDEX_ACCESS_PROPS = new String[] {
029: "size", "isEmpty", "keys", "values" };
030:
031: private static final XWorkConverter _converter = XWorkConverter
032: .getInstance();
033:
034: public Object getProperty(Map context, Object target, Object name)
035: throws OgnlException {
036:
037: if (_log.isDebugEnabled()) {
038: _log.debug("Entering getProperty (" + context + ","
039: + target + "," + name + ")");
040: }
041:
042: OgnlContextState.updateCurrentPropertyPath(context, name);
043: // if this is one of the regular index access
044: // properties then just let the superclass deal with the
045: // get.
046: if (name instanceof String
047: && contains(INDEX_ACCESS_PROPS, (String) name)) {
048: return super .getProperty(context, target, name);
049: }
050:
051: Object result = null;
052:
053: try {
054: result = super .getProperty(context, target, name);
055: } catch (ClassCastException ex) {
056: }
057:
058: if (result == null) {
059: //find the key class and convert the name to that class
060: Class lastClass = (Class) context
061: .get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED);
062:
063: String lastProperty = (String) context
064: .get(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED);
065: if (lastClass == null || lastProperty == null) {
066: return super .getProperty(context, target, name);
067: }
068: Class keyClass = _converter.getObjectTypeDeterminer()
069: .getKeyClass(lastClass, lastProperty);
070:
071: if (keyClass == null) {
072:
073: keyClass = java.lang.String.class;
074: }
075: Object key = getKey(context, name);
076: Map map = (Map) target;
077: result = map.get(key);
078:
079: if (result == null
080: && context
081: .get(InstantiatingNullHandler.CREATE_NULL_OBJECTS) != null
082: && XWorkConverter.getInstance()
083: .getObjectTypeDeterminer()
084: .shouldCreateIfNew(lastClass, lastProperty,
085: target, null, false)) {
086: Class valueClass = _converter.getObjectTypeDeterminer()
087: .getElementClass(lastClass, lastProperty, key);
088:
089: try {
090: result = ObjectFactory.getObjectFactory()
091: .buildBean(valueClass, context);
092: map.put(key, result);
093: } catch (Exception exc) {
094:
095: }
096:
097: }
098: }
099: return result;
100: }
101:
102: /**
103: * @param array
104: * @param name
105: */
106: private boolean contains(String[] array, String name) {
107: for (int i = 0; i < array.length; i++) {
108: if (array[i].equals(name)) {
109: return true;
110: }
111: }
112:
113: return false;
114: }
115:
116: public void setProperty(Map context, Object target, Object name,
117: Object value) throws OgnlException {
118: if (_log.isDebugEnabled()) {
119: _log.debug("Entering setProperty(" + context + "," + target
120: + "," + name + "," + value + ")");
121: }
122:
123: Object key = getKey(context, name);
124: Map map = (Map) target;
125: map.put(key, getValue(context, value));
126: }
127:
128: private Object getValue(Map context, Object value) {
129: Class lastClass = (Class) context
130: .get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED);
131: String lastProperty = (String) context
132: .get(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED);
133: if (lastClass == null || lastProperty == null) {
134: return value;
135: }
136: Class elementClass = _converter.getObjectTypeDeterminer()
137: .getElementClass(lastClass, lastProperty, null);
138: if (elementClass == null) {
139: return value; // nothing is specified, we assume it will be the value passed in.
140: }
141: return _converter.convertValue(context, value, elementClass);
142: }
143:
144: private Object getKey(Map context, Object name) {
145: Class lastClass = (Class) context
146: .get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED);
147: String lastProperty = (String) context
148: .get(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED);
149: if (lastClass == null || lastProperty == null) {
150: // return java.lang.String.class;
151: // commented out the above -- it makes absolutely no sense for when setting basic maps!
152: return name;
153: }
154: Class keyClass = _converter.getObjectTypeDeterminer()
155: .getKeyClass(lastClass, lastProperty);
156: if (keyClass == null) {
157: keyClass = java.lang.String.class;
158: }
159:
160: return _converter.convertValue(context, name, keyClass);
161:
162: }
163: }
|