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

grails.beans.util.LazyBeanMap.groovy Maven / Gradle / Ivy

There is a newer version: 6.2.0
Show newest version
/*
 * Copyright 2012 the original author or authors.
 *
 * 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 grails.beans.util

import groovy.transform.CompileStatic
import org.grails.core.util.ClassPropertyFetcher

import java.beans.PropertyDescriptor

/**
 * 

A map that backs onto a bean. The map is not initialized from the beans property values on creation, but instead lazily reads the values on demand. * No caching is applied, so each read results in a reflective call to retrieve the property. Users of this API should apply their own caching strategy if necessary. *

*

* Note that the {@link Map#values()} and {@link Map#entrySet()} implementations are expensive operations as they will read all properties of the target bean and should be used with caution. *

*

* Additionally the {@link Map#remove(java.lang.Object)} and {@link Map#clear()} methods are not implemented and will throw {@link UnsupportedOperationException}. *

* @since 2.4 * @author Graeme Rocher */ @CompileStatic class LazyBeanMap implements Map{ final private ClassPropertyFetcher cpf final Object target /** * Creates a bean map * * @param target The target bean */ LazyBeanMap(Object target) { this.target = target if(target != null) { this.cpf = ClassPropertyFetcher.forClass(target.getClass()) } } @Override int size() { return cpf ? cpf.getPropertyDescriptors().size() : 0 } @Override boolean isEmpty() { cpf ? false : true} @Override boolean containsKey(Object key) { cpf != null && cpf.getPropertyType(key.toString(), true) != null } @Override boolean containsValue(Object value) { cpf != null && values().contains(value) } @Override def get(Object key) { if(!cpf) return null def property = key.toString() if(cpf.isReadableProperty(property)) cpf.getPropertyValue target, property else return null } @Override def put(String key, def value) { if(!cpf) return null def old = get(key) def mc = GroovySystem.metaClassRegistry.getMetaClass(target.getClass()) mc.setProperty(target, key, value) return old } @Override Object remove(Object key) { throw new UnsupportedOperationException("Method remove(key) not implemented") } @Override void putAll(Map m) { if(!cpf) return for(String property in m.keySet()) { put(property, m.get(property)) } } @Override void clear() { throw new UnsupportedOperationException("Method clear() not implemented") } @Override Set keySet() { if(!cpf) return [] as Set else { return new HashSet( cpf.getPropertyDescriptors().collect { PropertyDescriptor pd -> pd.name} ) } } @Override Collection values() { if(!cpf) return [] else { keySet().collect() { String property -> cpf.getPropertyValue(property) } } } @Override Set> entrySet() { if(!cpf) return [] as Set> else { return new HashSet>( keySet().collect() { String property -> new AbstractMap.SimpleEntry(property, cpf.getPropertyValue(property)) } ) } } }