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 */
016package org.joda.beans.impl.map;
017
018import java.util.HashMap;
019import java.util.NoSuchElementException;
020import java.util.Set;
021
022import org.joda.beans.DynamicBean;
023import org.joda.beans.MetaBean;
024import org.joda.beans.MetaProperty;
025import org.joda.beans.Property;
026import org.joda.beans.impl.BasicProperty;
027
028/**
029 * Implementation of a fully dynamic {@code Bean} based on an exposed {@code Map}.
030 * <p>
031 * Properties are dynamic, and can be added and removed at will from the map.
032 * 
033 * @author Stephen Colebourne
034 */
035public class MapBean extends HashMap<String, Object> implements DynamicBean {
036
037    /** Serialization version. */
038    private static final long serialVersionUID = 1L;
039
040    @Override
041    public MetaBean metaBean() {
042        return new MapMetaBean(this);
043    }
044
045    @Override
046    public Property<Object> property(String name) {
047        return BasicProperty.of(this, metaProperty(name));
048    }
049
050    MetaProperty<Object> metaProperty(String name) {
051        Object obj = get(name);
052        if (obj == null) {
053            throw new NoSuchElementException("Property not found: " + name);
054        }
055        return MapBeanMetaProperty.of(MapBean.this, name);
056    }
057
058    @Override
059    public Set<String> propertyNames() {
060        return keySet();
061    }
062
063    @Override
064    public void propertyDefine(String propertyName, Class<?> propertyType) {
065        // no need to define
066    }
067
068    @Override
069    public void propertyRemove(String propertyName) {
070        remove(propertyName);
071    }
072
073    //-----------------------------------------------------------------------
074    /**
075     * Returns a string that summarises the bean.
076     * <p>
077     * The string contains the class name and properties.
078     * 
079     * @return a summary string, not null
080     */
081    @Override
082    public String toString() {
083        return getClass().getSimpleName() + super.toString();
084    }
085
086}