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    }