001 /*
002 * Copyright 2007 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005 * use this file except in compliance with the License. You may obtain a copy of
006 * the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013 * License for the specific language governing permissions and limitations under
014 * the License.
015 */
016 package org.springframework.binding.support;
017
018 import org.springframework.beans.BeansException;
019 import org.springframework.beans.PropertyAccessor;
020 import org.springframework.binding.MutablePropertyAccessStrategy;
021 import org.springframework.binding.value.ValueModel;
022 import org.springframework.binding.value.support.ValueHolder;
023 import org.springframework.richclient.beans.DefaultMemberPropertyAccessor;
024
025 /**
026 * An implementation of <code>MutablePropertyAccessStrategy</code> that provides access
027 * to the properties of any object.
028 *
029 * <p>As this class delegates to a <code>DefaultMemberPropertyAccessor</code> for property access,
030 * there is full support for <b>nested properties</b> and collection types.
031 *
032 * @author Arne Limburg
033 * @see org.springframework.richclient.beans.DefaultMemberPropertyAccessor
034 */
035 public class ObjectPropertyAccessStrategy extends AbstractPropertyAccessStrategy {
036
037 private final DefaultMemberPropertyAccessor propertyAccessor;
038
039 /**
040 * Creates a new instance of <tt>ObjectPropertyAccessStrategy</tt>
041 * that will provide access to the properties of the provided object.
042 *
043 * @param target object to be accessed through this class.
044 */
045 public ObjectPropertyAccessStrategy(Object target) {
046 this(new ValueHolder(target));
047 }
048
049 /**
050 * Creates a new instance of <tt>ObjectPropertyAccessStrategy</tt>
051 * that will provide access to the object contained by the provided value model.
052 *
053 * @param domainObjectHolder value model that holds the object
054 * to be accessed through this class
055 */
056 public ObjectPropertyAccessStrategy(final ValueModel domainObjectHolder) {
057 this(domainObjectHolder, false);
058 }
059
060 /**
061 * Creates a new instance of <tt>ObjectPropertyAccessStrategy</tt>
062 * that will provide access to the object contained by the provided value model.
063 *
064 * @param domainObjectHolder value model that holds the object
065 * to be accessed through this class
066 * @param fieldAccessEnabled whether the fields of the objects
067 * should be accessed directly where possible
068 * instead of using methods
069 */
070 public ObjectPropertyAccessStrategy(final ValueModel domainObjectHolder, boolean fieldAccessEnabled) {
071 this(domainObjectHolder, fieldAccessEnabled, true);
072 }
073
074 /**
075 * Creates a new instance of <tt>ObjectPropertyAccessStrategy</tt>
076 * that will provide access to the object contained by the provided value model.
077 *
078 * @param domainObjectHolder value model that holds the object
079 * to be accessed through this class
080 * @param fieldAccessEnabled whether the fields of the objects
081 * should be accessed directly where possible
082 * instead of using methods
083 * @param strictNullValueHandling whether a <tt>NullValueInNestedPathException</tt>
084 * should be thrown on nested null-values or <tt>null</tt> should be returned
085 */
086 public ObjectPropertyAccessStrategy(final ValueModel domainObjectHolder, boolean fieldAccessEnabled, boolean strictNullValueHandling) {
087 super(domainObjectHolder);
088 propertyAccessor = new DefaultMemberPropertyAccessor(domainObjectHolder.getValue(), fieldAccessEnabled, strictNullValueHandling);
089 }
090
091 /**
092 * Creates a child instance of <tt>ObjectPropertyAccessStrategy<tt>
093 * that will delegate to its parent for property access.
094 *
095 * @param parent <tt>ObjectPropertyAccessStrategy</tt> which will be used to provide property access
096 * @param basePropertyPath property path that will as a base when accessing
097 * the parent <tt>ObjectPropertyAccessStrategy</tt>
098 */
099 protected ObjectPropertyAccessStrategy(ObjectPropertyAccessStrategy parent, String basePropertyPath) {
100 super(parent, basePropertyPath);
101 propertyAccessor = parent.propertyAccessor;
102 }
103
104 /**
105 * Provides <code>DefaultMemberPropertyAccessor</code> access to subclasses.
106 */
107 protected PropertyAccessor getPropertyAccessor() {
108 return propertyAccessor;
109 }
110
111 public MutablePropertyAccessStrategy getPropertyAccessStrategyForPath(String propertyPath) throws BeansException {
112 return new ObjectPropertyAccessStrategy(this, getFullPropertyPath(propertyPath));
113 }
114
115 public MutablePropertyAccessStrategy newPropertyAccessStrategy(ValueModel domainObjectHolder) {
116 return new ObjectPropertyAccessStrategy(domainObjectHolder);
117 }
118
119 protected void domainObjectChanged() {
120 propertyAccessor.setTarget(getDomainObject());
121 }
122 }