All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.twelvemonkeys.util.BeanMap Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2008, Harald Kuhr
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.twelvemonkeys.util;

import java.beans.IndexedPropertyDescriptor;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

/**
 * A {@code Map} adapter for a Java Bean.
 * 

* Ruthlessly stolen from * Binkley's Blog *

*/ public final class BeanMap extends AbstractMap implements Serializable, Cloneable { private final Object bean; private transient Set descriptors; public BeanMap(Object pBean) throws IntrospectionException { if (pBean == null) { throw new IllegalArgumentException("bean == null"); } bean = pBean; descriptors = initDescriptors(pBean); } private static Set initDescriptors(Object pBean) throws IntrospectionException { final Set descriptors = new HashSet(); PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(pBean.getClass()).getPropertyDescriptors(); for (PropertyDescriptor descriptor : propertyDescriptors) { // Skip Object.getClass(), as you probably never want it if ("class".equals(descriptor.getName()) && descriptor.getPropertyType() == Class.class) { continue; } // Only support simple setter/getters. if (!(descriptor instanceof IndexedPropertyDescriptor)) { descriptors.add(descriptor); } } return Collections.unmodifiableSet(descriptors); } public Set> entrySet() { return new BeanSet(); } public Object get(final Object pKey) { return super.get(pKey); } public Object put(final String pKey, final Object pValue) { checkKey(pKey); for (Entry entry : entrySet()) { if (entry.getKey().equals(pKey)) { return entry.setValue(pValue); } } return null; } public Object remove(final Object pKey) { return super.remove(checkKey(pKey)); } public int size() { return descriptors.size(); } private String checkKey(final Object pKey) { if (pKey == null) { throw new IllegalArgumentException("key == null"); } // NB - the cast forces CCE if key is the wrong type. final String name = (String) pKey; if (!containsKey(name)) { throw new IllegalArgumentException("Bad key: " + pKey); } return name; } private Object readResolve() throws IntrospectionException { // Initialize the property descriptors descriptors = initDescriptors(bean); return this; } private class BeanSet extends AbstractSet> { public Iterator> iterator() { return new BeanIterator(descriptors.iterator()); } public int size() { return descriptors.size(); } } private class BeanIterator implements Iterator> { private final Iterator mIterator; public BeanIterator(final Iterator pIterator) { mIterator = pIterator; } public boolean hasNext() { return mIterator.hasNext(); } public BeanEntry next() { return new BeanEntry(mIterator.next()); } public void remove() { mIterator.remove(); } } private class BeanEntry implements Entry { private final PropertyDescriptor mDescriptor; public BeanEntry(final PropertyDescriptor pDescriptor) { this.mDescriptor = pDescriptor; } public String getKey() { return mDescriptor.getName(); } public Object getValue() { return unwrap(new Wrapped() { public Object run() throws IllegalAccessException, InvocationTargetException { final Method method = mDescriptor.getReadMethod(); // A write-only bean. if (method == null) { throw new UnsupportedOperationException("No getter: " + mDescriptor.getName()); } return method.invoke(bean); } }); } public Object setValue(final Object pValue) { return unwrap(new Wrapped() { public Object run() throws IllegalAccessException, InvocationTargetException { final Method method = mDescriptor.getWriteMethod(); // A read-only bean. if (method == null) { throw new UnsupportedOperationException("No write method for property: " + mDescriptor.getName()); } final Object old = getValue(); method.invoke(bean, pValue); return old; } }); } public boolean equals(Object pOther) { if (!(pOther instanceof Map.Entry)) { return false; } Map.Entry entry = (Map.Entry) pOther; Object k1 = getKey(); Object k2 = entry.getKey(); if (k1 == k2 || (k1 != null && k1.equals(k2))) { Object v1 = getValue(); Object v2 = entry.getValue(); if (v1 == v2 || (v1 != null && v1.equals(v2))) { return true; } } return false; } public int hashCode() { return (getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode()); } public String toString() { return getKey() + "=" + getValue(); } } private static interface Wrapped { Object run() throws IllegalAccessException, InvocationTargetException; } private static Object unwrap(final Wrapped wrapped) { try { return wrapped.run(); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (final InvocationTargetException e) { // Javadocs for setValue indicate cast is ok. throw (RuntimeException) e.getCause(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy