From bc6e9d8f540910bb180e687f3ce562ebaa5c6a54 Mon Sep 17 00:00:00 2001 From: Jon Brisbin Date: Wed, 16 Mar 2011 15:37:49 -0500 Subject: [PATCH] Added the ability to use the Spring 3.0 ApplicationEvent mechanism for event handling internally within the mapping framework. --- .../data/mapping/BasicMappingContext.java | 76 ++++++++++--------- .../data/mapping/BasicPersistentEntity.java | 18 +++-- .../mapping/event/MappingContextEvent.java | 36 +++++++++ .../data/mapping/model/MappingContext.java | 22 +----- 4 files changed, 92 insertions(+), 60 deletions(-) create mode 100644 spring-data-commons-core/src/main/java/org/springframework/data/mapping/event/MappingContextEvent.java diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/BasicMappingContext.java b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/BasicMappingContext.java index b52158830..d738072b6 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/BasicMappingContext.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/BasicMappingContext.java @@ -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 */ -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> persistentEntities = new ConcurrentHashMap>(); protected ConcurrentMap, List> validators = new ConcurrentHashMap, List>(); - protected ConcurrentSkipListSet listeners = new ConcurrentSkipListSet(); 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> getPersistentEntities() { return persistentEntities.values(); @@ -79,24 +97,24 @@ public class BasicMappingContext implements MappingContext, InitializingBean { public PersistentEntity getPersistentEntity(Class type) { return getPersistentEntity(new ClassTypeInformation(type)); } - + @SuppressWarnings({"unchecked"}) @Override public PersistentEntity getPersistentEntity(TypeInformation type) { return (PersistentEntity) persistentEntities.get(type); } - + @SuppressWarnings("unchecked") public PersistentEntity addPersistentEntity(TypeInformation typeInformation) { - + PersistentEntity persistentEntity = persistentEntities.get(typeInformation); - + if (persistentEntity != null) { return (PersistentEntity) persistentEntity; } - + Class type = (Class) typeInformation.getType(); - + try { final PersistentEntity 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 listenersToRemove = new ArrayList(); - 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."); diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/BasicPersistentEntity.java b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/BasicPersistentEntity.java index 80a4bed52..aa13cb156 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/BasicPersistentEntity.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/BasicPersistentEntity.java @@ -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 */ @@ -37,8 +40,9 @@ public class BasicPersistentEntity implements PersistentEntity { protected final TypeInformation information; protected MappingContext mappingContext; - - + + + @SuppressWarnings({"unchecked"}) public BasicPersistentEntity(MappingContext mappingContext, TypeInformation information) { this.mappingContext = mappingContext; this.type = (Class) information.getType(); @@ -98,7 +102,7 @@ public class BasicPersistentEntity implements PersistentEntity { public Class getType() { return type; } - + @Override public TypeInformation getPropertyInformation() { return information; diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/event/MappingContextEvent.java b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/event/MappingContextEvent.java new file mode 100644 index 000000000..eca62fba7 --- /dev/null +++ b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/event/MappingContextEvent.java @@ -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 + */ +public class MappingContextEvent extends ApplicationEvent { + + public MappingContextEvent(PersistentEntity source) { + super(source); + } + + @Override + public PersistentEntity getSource() { + return (PersistentEntity) super.getSource(); + } + +} diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/model/MappingContext.java b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/model/MappingContext.java index ab627ee91..562642aeb 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/model/MappingContext.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/model/MappingContext.java @@ -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; - /** *

This interface defines the overall context including all known * PersistentEntity instances and methods to obtain instances on demand

@@ -47,7 +47,7 @@ public interface MappingContext extends InitializingBean { * @return A list of PersistentEntity instances */ Collection> getPersistentEntities(); - + PersistentEntity getPersistentEntity(Class type); PersistentEntity 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); - } }