Added the ability to use the Spring 3.0 ApplicationEvent mechanism for event handling internally within the mapping framework.

This commit is contained in:
Jon Brisbin
2011-03-16 15:37:49 -05:00
committed by J. Brisbin
parent 626d52e2c0
commit bc6e9d8f54
4 changed files with 92 additions and 60 deletions

View File

@@ -16,15 +16,38 @@
package org.springframework.data.mapping;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterRegistry;
import org.springframework.core.convert.support.ConversionServiceFactory;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.mapping.model.*;
import org.springframework.data.mapping.event.MappingContextEvent;
import org.springframework.data.mapping.model.Association;
import org.springframework.data.mapping.model.MappingConfigurationBuilder;
import org.springframework.data.mapping.model.MappingConfigurationException;
import org.springframework.data.mapping.model.MappingContext;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.model.PersistentEntity;
import org.springframework.data.mapping.model.PersistentProperty;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
@@ -32,26 +55,16 @@ import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.FieldCallback;
import org.springframework.validation.Validator;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListSet;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class BasicMappingContext implements MappingContext, InitializingBean {
public class BasicMappingContext implements MappingContext, InitializingBean, ApplicationContextAware {
protected Logger log = LoggerFactory.getLogger(getClass());
protected ApplicationContext applicationContext;
protected MappingConfigurationBuilder builder;
protected ConcurrentMap<TypeInformation, PersistentEntity<?>> persistentEntities = new ConcurrentHashMap<TypeInformation, PersistentEntity<?>>();
protected ConcurrentMap<PersistentEntity<?>, List<Validator>> validators = new ConcurrentHashMap<PersistentEntity<?>, List<Validator>>();
protected ConcurrentSkipListSet<Listener> listeners = new ConcurrentSkipListSet<Listener>();
protected GenericConversionService conversionService = ConversionServiceFactory.createDefaultConversionService();
public BasicMappingContext() {
@@ -67,6 +80,11 @@ public class BasicMappingContext implements MappingContext, InitializingBean {
this.conversionService = conversionService;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public Collection<PersistentEntity<?>> getPersistentEntities() {
return persistentEntities.values();
@@ -79,24 +97,24 @@ public class BasicMappingContext implements MappingContext, InitializingBean {
public <T> PersistentEntity<T> getPersistentEntity(Class<T> type) {
return getPersistentEntity(new ClassTypeInformation(type));
}
@SuppressWarnings({"unchecked"})
@Override
public <T> PersistentEntity<T> getPersistentEntity(TypeInformation type) {
return (PersistentEntity<T>) persistentEntities.get(type);
}
@SuppressWarnings("unchecked")
public <T> PersistentEntity<T> addPersistentEntity(TypeInformation typeInformation) {
PersistentEntity<?> persistentEntity = persistentEntities.get(typeInformation);
if (persistentEntity != null) {
return (PersistentEntity<T>) persistentEntity;
}
Class<T> type = (Class<T>) typeInformation.getType();
try {
final PersistentEntity<T> entity = builder.createPersistentEntity(typeInformation, this);
BeanInfo info = Introspector.getBeanInfo(type);
@@ -125,7 +143,7 @@ public class BasicMappingContext implements MappingContext, InitializingBean {
if (property.isIdProperty()) {
entity.setIdProperty(property);
}
if (property.isComplexType() && !property.isTransient()) {
addPersistentEntity(property.getTypeInformation());
}
@@ -139,16 +157,9 @@ public class BasicMappingContext implements MappingContext, InitializingBean {
entity.setPreferredConstructor(builder.getPreferredConstructor(type));
// Inform listeners
List<Listener> listenersToRemove = new ArrayList<Listener>();
for (Listener listener : listeners) {
if (!listener.persistentEntityAdded(entity)) {
listenersToRemove.add(listener);
}
}
for (Listener listener : listenersToRemove) {
listeners.remove(listener);
}
applicationContext.publishEvent(new MappingContextEvent(entity));
// Cache
persistentEntities.put(entity.getPropertyInformation(), entity);
return entity;
@@ -157,7 +168,7 @@ public class BasicMappingContext implements MappingContext, InitializingBean {
} catch (IntrospectionException e) {
throw new MappingException(e.getMessage(), e);
}
return null;
}
@@ -220,11 +231,6 @@ public class BasicMappingContext implements MappingContext, InitializingBean {
return false;
}
@Override
public void addContextListener(Listener listener) {
listeners.add(listener);
}
@Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(builder, "No mapping configuration provider configured.");

View File

@@ -16,14 +16,17 @@
package org.springframework.data.mapping;
import org.springframework.data.mapping.model.*;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.springframework.data.mapping.model.Association;
import org.springframework.data.mapping.model.MappingContext;
import org.springframework.data.mapping.model.PersistentEntity;
import org.springframework.data.mapping.model.PersistentProperty;
import org.springframework.data.mapping.model.PreferredConstructor;
import org.springframework.data.util.TypeInformation;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
@@ -37,8 +40,9 @@ public class BasicPersistentEntity<T> implements PersistentEntity<T> {
protected final TypeInformation information;
protected MappingContext mappingContext;
@SuppressWarnings({"unchecked"})
public BasicPersistentEntity(MappingContext mappingContext, TypeInformation information) {
this.mappingContext = mappingContext;
this.type = (Class<T>) information.getType();
@@ -98,7 +102,7 @@ public class BasicPersistentEntity<T> implements PersistentEntity<T> {
public Class<T> getType() {
return type;
}
@Override
public TypeInformation getPropertyInformation() {
return information;

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2011 by the original author(s).
*
* 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 org.springframework.data.mapping.event;
import org.springframework.context.ApplicationEvent;
import org.springframework.data.mapping.model.PersistentEntity;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class MappingContextEvent extends ApplicationEvent {
public MappingContextEvent(PersistentEntity source) {
super(source);
}
@Override
public PersistentEntity getSource() {
return (PersistentEntity) super.getSource();
}
}

View File

@@ -14,6 +14,9 @@
*/
package org.springframework.data.mapping.model;
import java.util.Collection;
import java.util.List;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.converter.Converter;
@@ -21,9 +24,6 @@ import org.springframework.core.convert.converter.ConverterRegistry;
import org.springframework.data.util.TypeInformation;
import org.springframework.validation.Validator;
import java.util.Collection;
import java.util.List;
/**
* <p>This interface defines the overall context including all known
* PersistentEntity instances and methods to obtain instances on demand</p>
@@ -47,7 +47,7 @@ public interface MappingContext extends InitializingBean {
* @return A list of PersistentEntity instances
*/
Collection<PersistentEntity<?>> getPersistentEntities();
<T> PersistentEntity<T> getPersistentEntity(Class<T> type);
<T> PersistentEntity<T> getPersistentEntity(TypeInformation type);
@@ -109,18 +109,4 @@ public interface MappingContext extends InitializingBean {
*/
boolean isPersistentEntity(Object value);
void addContextListener(Listener listener);
/**
* Listener interface to deal with newly-added persistent entities.
*/
public interface Listener {
/**
* Handle this new entity, return true or false, depending on whether this listener should continue listening.
*
* @param entity
* @return 'true' to leave listener attached, 'false' to remove this listener
*/
boolean persistentEntityAdded(PersistentEntity<?> entity);
}
}