
com.googlecode.jpattern.org.cojen.util.BeanPropertyMapFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jpattern-cojen Show documentation
Show all versions of jpattern-cojen Show documentation
This is a copy of the good Cojen project from http://cojen.sourceforge.net/ with package name changed
The newest version!
/*
* Copyright 2007-2010 Brian S O'Neill
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.jpattern.org.cojen.util;
import java.lang.ref.SoftReference;
import java.lang.reflect.Method;
import java.util.AbstractCollection;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
/**
* Provides a simple and efficient means of reading and writing bean properties
* via a map. Properties which declare throwing checked exceptions are
* excluded as are properties which are read-only or write-only.
*
* @author Brian S O'Neill
* @see BeanPropertyAccessor
* @since 2.1
*/
public abstract class BeanPropertyMapFactory {
private static final Map> cFactories =
new WeakIdentityMap>();
/**
* Returns a new or cached BeanPropertyMapFactory for the given class.
*/
public static BeanPropertyMapFactory forClass(Class clazz) {
synchronized (cFactories) {
BeanPropertyMapFactory factory;
SoftReference ref = cFactories.get(clazz);
if (ref != null) {
factory = ref.get();
if (factory != null) {
return factory;
}
}
final Map properties = BeanIntrospector.getAllProperties(clazz);
Map supportedProperties = properties;
// Determine which properties are to be excluded.
for (Map.Entry entry : properties.entrySet()) {
BeanProperty property = entry.getValue();
if (property.getReadMethod() == null ||
property.getWriteMethod() == null ||
BeanPropertyAccessor.throwsCheckedException(property.getReadMethod()) ||
BeanPropertyAccessor.throwsCheckedException(property.getWriteMethod()))
{
// Exclude property.
if (supportedProperties == properties) {
supportedProperties = new HashMap(properties);
}
supportedProperties.remove(entry.getKey());
}
}
if (supportedProperties.size() == 0) {
factory = Empty.INSTANCE;
} else {
factory = new Standard
(BeanPropertyAccessor.forClass
(clazz, BeanPropertyAccessor.PropertySet.READ_WRITE_UNCHECKED_EXCEPTIONS),
supportedProperties);
}
cFactories.put(clazz, new SoftReference(factory));
return factory;
}
}
/**
* Returns a fixed-size map backed by the given bean. Map remove operations
* are unsupported, as is access to excluded properties.
*
* @throws IllegalArgumentException if bean is null
*/
public static SortedMap asMap(Object bean) {
if (bean == null) {
throw new IllegalArgumentException();
}
BeanPropertyMapFactory factory = forClass(bean.getClass());
return factory.createMap(bean);
}
/**
* Returns a fixed-size map backed by the given bean. Map remove operations
* are unsupported, as are put operations on non-existent properties.
*
* @throws IllegalArgumentException if bean is null
*/
public abstract SortedMap createMap(B bean);
private static class Empty extends BeanPropertyMapFactory {
static final Empty INSTANCE = new Empty();
static final SortedMap EMPTY_MAP =
Collections.unmodifiableSortedMap(new TreeMap());
private Empty() {
}
public SortedMap createMap(Object bean) {
if (bean == null) {
throw new IllegalArgumentException();
}
return EMPTY_MAP;
}
}
private static class Standard extends BeanPropertyMapFactory {
final BeanPropertyAccessor mAccessor;
final SortedSet mPropertyNames;
public Standard(BeanPropertyAccessor accessor, Map properties) {
mAccessor = accessor;
// Only reveal readable properties.
SortedSet propertyNames = new TreeSet();
for (BeanProperty property : properties.values()) {
if (property.getReadMethod() != null) {
propertyNames.add(property.getName());
}
}
mPropertyNames = Collections.unmodifiableSortedSet(propertyNames);
}
public SortedMap createMap(B bean) {
if (bean == null) {
throw new IllegalArgumentException();
}
return new BeanMap(bean, mAccessor, mPropertyNames);
}
}
private static class BeanMap extends AbstractMap
implements SortedMap
{
final B mBean;
final BeanPropertyAccessor mAccessor;
final SortedSet mPropertyNames;
BeanMap(B bean, BeanPropertyAccessor accessor, SortedSet propertyNames) {
mBean = bean;
mAccessor = accessor;
mPropertyNames = propertyNames;
}
public Comparator super String> comparator() {
return null;
}
public SortedMap subMap(String fromKey, String toKey) {
return new SubMap(mBean, mAccessor, mPropertyNames.subSet(fromKey, toKey),
fromKey, toKey);
}
public SortedMap headMap(String toKey) {
return new SubMap(mBean, mAccessor, mPropertyNames.headSet(toKey),
null, toKey);
}
public SortedMap tailMap(String fromKey) {
return new SubMap(mBean, mAccessor, mPropertyNames.tailSet(fromKey),
fromKey, null);
}
public String firstKey() {
return mPropertyNames.first();
}
public String lastKey() {
return mPropertyNames.last();
}
@Override
public int size() {
return mPropertyNames.size();
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public boolean containsKey(Object key) {
return mAccessor.hasReadableProperty((String) key);
}
@Override
public boolean containsValue(Object value) {
return mAccessor.hasPropertyValue(mBean, value);
}
@Override
public Object get(Object key) {
return mAccessor.tryGetPropertyValue(mBean, (String) key);
}
@Override
public Object put(String key, Object value) {
Object old = mAccessor.tryGetPropertyValue(mBean, key);
mAccessor.setPropertyValue(mBean, key, value);
return old;
}
@Override
public Object remove(Object key) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public Set keySet() {
return mPropertyNames;
}
@Override
public Collection
© 2015 - 2025 Weber Informatics LLC | Privacy Policy