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