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.map;
017    
018    import java.util.AbstractMap;
019    import java.util.AbstractSet;
020    import java.util.Collections;
021    import java.util.HashMap;
022    import java.util.Iterator;
023    import java.util.Map;
024    import java.util.Set;
025    
026    import org.joda.beans.Property;
027    import org.joda.beans.PropertyMap;
028    import org.joda.beans.impl.BasicProperty;
029    
030    /**
031     * A map of properties for a {@code MapBean}.
032     * 
033     * @author Stephen Colebourne
034     */
035    public final class MapBeanPropertyMap
036            extends AbstractMap<String, Property<?>> implements PropertyMap {
037    
038        /** The bean. */
039        private final MapBean bean;
040    
041        /**
042         * Factory to create a property map avoiding duplicate generics.
043         * 
044         * @param bean  the bean
045         */
046        public static MapBeanPropertyMap of(MapBean bean) {
047            return new MapBeanPropertyMap(bean);
048        }
049    
050        /**
051         * Creates a property map.
052         * 
053         * @param bean  the bean that the property is bound to, not null
054         */
055        private MapBeanPropertyMap(MapBean bean) {
056            if (bean == null) {
057                throw new NullPointerException("Bean must not be null");
058            }
059            this.bean = bean;
060        }
061    
062        //-----------------------------------------------------------------------
063        @Override
064        public int size() {
065            return bean.size();
066        }
067    
068        @Override
069        public boolean containsKey(Object obj) {
070            return bean.containsKey(obj);
071        }
072    
073        @Override
074        public Property<?> get(Object obj) {
075            return containsKey(obj) ? bean.property(obj.toString()) : null;
076        }
077    
078        @Override
079        public Set<String> keySet() {
080            return bean.keySet();
081        }
082    
083        @Override
084        public Set<Entry<String, Property<?>>> entrySet() {
085            return new AbstractSet<Entry<String,Property<?>>>() {
086                // TODO: possibly override contains()
087                @Override
088                public int size() {
089                    return bean.size();
090                }
091                @Override
092                public Iterator<Entry<String, Property<?>>> iterator() {
093                    final Iterator<String> it = bean.keySet().iterator();
094                    return new Iterator<Entry<String, Property<?>>>() {
095                        @Override
096                        public boolean hasNext() {
097                            return it.hasNext();
098                        }
099                        @Override
100                        public Entry<String, Property<?>> next() {
101                            String name = it.next();
102                            Property<?> prop = BasicProperty.of(bean, MapBeanMetaProperty.of(bean, name));
103                            return new SimpleImmutableEntry<String, Property<?>>(name, prop);
104                        }
105                        @Override
106                        public void remove() {
107                            throw new UnsupportedOperationException("Unmodifiable");
108                        }
109                    };
110                }
111            };
112        }
113    
114        //-----------------------------------------------------------------------
115        @Override
116        public Map<String, Object> flatten() {
117            Map<String, Object> copy = new HashMap<String, Object>(bean);
118            return Collections.unmodifiableMap(copy);
119        }
120    
121    }