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
027 * provides type-save access to data specified by a class. The data is stored in
028 * a backing map.
029 *
030 * <p>
031 * As this class delegates to a <code>MapPropertyAccessor</code> for property
032 * access, there is full support for <b>nested properties</b> and collection
033 * types.
034 *
035 * @author Arne Limburg
036 * @see org.springframework.richclient.beans.DefaultMemberPropertyAccessor
037 */
038 public class ClassPropertyAccessStrategy extends AbstractPropertyAccessStrategy {
039
040 private final DefaultMemberPropertyAccessor propertyAccessor;
041
042 /**
043 * Creates a new instance of <tt>ClassPropertyAccessStrategy</tt>.
044 * @param targetClass the target class
045 */
046 public ClassPropertyAccessStrategy(Class targetClass) {
047 super(new ValueHolder());
048 propertyAccessor = new DefaultMemberPropertyAccessor(targetClass);
049 }
050
051 /**
052 * Creates a new instance of <tt>ClassPropertyAccessStrategy</tt>.
053 * @param target the domain object
054 */
055 public ClassPropertyAccessStrategy(Object target) {
056 this(new ValueHolder(target));
057 }
058
059 /**
060 * Creates a new instance of <tt>ClassPropertyAccessStrategy</tt>.
061 * @param domainObjectHolder the value model containing the domain object
062 */
063 public ClassPropertyAccessStrategy(final ValueModel domainObjectHolder) {
064 this(domainObjectHolder, false);
065 }
066
067 /**
068 * Creates a new instance of <tt>ClassPropertyAccessStrategy</tt>.
069 * @param domainObjectHolder the value model containing the domain object
070 * @param fieldAccessEnabled whether the fields of the objects should be
071 * accessed directly where possible instead of using methods
072 */
073 public ClassPropertyAccessStrategy(final ValueModel domainObjectHolder, boolean fieldAccessEnabled) {
074 this(domainObjectHolder, fieldAccessEnabled, true);
075 }
076
077 /**
078 * Creates a new instance of <tt>ClassPropertyAccessStrategy</tt>.
079 * @param domainObjectHolder the value model containing the domain object
080 * @param fieldAccessEnabled whether the fields of the objects should be
081 * accessed directly where possible instead of using methods
082 * @param strictNullValueHandling whether a
083 * <tt>NullValueInNestedPathException</tt> should be thrown on nested
084 * null-values or <tt>null</tt> should be returned
085 */
086 public ClassPropertyAccessStrategy(final ValueModel domainObjectHolder, boolean fieldAccessEnabled,
087 boolean strictNullValueHandling) {
088 super(domainObjectHolder);
089 propertyAccessor = new DefaultMemberPropertyAccessor(domainObjectHolder.getValue().getClass(),
090 domainObjectHolder.getValue(), fieldAccessEnabled, strictNullValueHandling);
091 }
092
093 /**
094 * Creates a child instance of <tt>ClassPropertyAccessStrategy<tt>
095 * that will delegate to its parent for property access.
096 *
097 * @param parent <tt>ClassPropertyAccessStrategy</tt> which will be used to provide property access
098 * @param basePropertyPath property path that will as a base when accessing
099 * the parent <tt>ClassPropertyAccessStrategy</tt>
100 */
101 public ClassPropertyAccessStrategy(ClassPropertyAccessStrategy parent, String basePropertyPath) {
102 super(parent, basePropertyPath);
103 propertyAccessor = parent.propertyAccessor;
104 }
105
106 protected PropertyAccessor getPropertyAccessor() {
107 return propertyAccessor;
108 }
109
110 public MutablePropertyAccessStrategy getPropertyAccessStrategyForPath(String propertyPath) throws BeansException {
111 return new ClassPropertyAccessStrategy(this, getFullPropertyPath(propertyPath));
112 }
113
114 public MutablePropertyAccessStrategy newPropertyAccessStrategy(ValueModel domainObjectHolder) {
115 return new ClassPropertyAccessStrategy(domainObjectHolder);
116 }
117
118 protected void domainObjectChanged() {
119 propertyAccessor.setTarget(getDomainObject());
120 }
121 }