001 /*
002 * Copyright 2001-2013 Stephen Colebourne
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of 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,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.joda.beans.impl;
017
018 import java.util.Map;
019 import java.util.Map.Entry;
020
021 import org.joda.beans.Bean;
022 import org.joda.beans.BeanBuilder;
023 import org.joda.beans.MetaProperty;
024
025 /**
026 * Basic implementation of {@code BeanBuilder} that wraps a real bean.
027 * <p>
028 * This approach saves creating a temporary map, but is only suitable if the
029 * bean has a no-arg constructor and allows properties to be set.
030 *
031 * @author Stephen Colebourne
032 */
033 public class BasicBeanBuilder<T extends Bean> implements BeanBuilder<T> {
034
035 /**
036 * The actual target bean.
037 */
038 private final T bean;
039
040 /**
041 * Constructs the builder wrapping the target bean.
042 *
043 * @param bean the target bean, not null
044 */
045 public BasicBeanBuilder(T bean) {
046 if (bean == null) {
047 throw new NullPointerException("Bean must not be null");
048 }
049 this.bean = bean;
050 }
051
052 //-----------------------------------------------------------------------
053 /**
054 * Gets the target bean.
055 *
056 * @return the target bean, not null
057 */
058 protected T getTargetBean() {
059 return bean;
060 }
061
062 /**
063 * Gets the current value of the property.
064 *
065 * @param propertyName the property name, not null
066 * @return the current value in the builder, null if not found or value is null
067 */
068 protected BeanBuilder<T> get(String propertyName) {
069 bean.property(propertyName).get();
070 return this;
071 }
072
073 //-----------------------------------------------------------------------
074 @Override
075 public BeanBuilder<T> set(String propertyName, Object value) {
076 return set(bean.metaBean().metaProperty(propertyName), value);
077 }
078
079 @Override
080 public BeanBuilder<T> set(MetaProperty<?> property, Object value) {
081 property.set(bean, value);
082 return this;
083 }
084
085 @Override
086 public BeanBuilder<T> setString(String propertyName, String value) {
087 return setString(bean.metaBean().metaProperty(propertyName), value);
088 }
089
090 @Override
091 public BeanBuilder<T> setString(MetaProperty<?> property, String value) {
092 property.setString(bean, value);
093 return this;
094 }
095
096 @Override
097 public BeanBuilder<T> setAll(Map<String, ? extends Object> propertyValueMap) {
098 for (Entry<String, ? extends Object> entry : propertyValueMap.entrySet()) {
099 set(entry.getKey(), entry.getValue());
100 }
101 return this;
102 }
103
104 @Override
105 public T build() {
106 validate(bean);
107 return bean;
108 }
109
110 /**
111 * Hook to allow a subclass to validate the bean.
112 *
113 * @param bean the bean to validate, not null
114 */
115 protected void validate(T bean) {
116 // override to validate the bean
117 }
118
119 //-----------------------------------------------------------------------
120 /**
121 * Returns a string that summarises the builder.
122 *
123 * @return a summary string, not null
124 */
125 @Override
126 public String toString() {
127 return "BeanBuilder for " + bean.metaBean().beanName();
128 }
129
130 }