Added mapping support to commons core. Will be used by other spring-data projects for multi-store mapping.

This commit is contained in:
Jon Brisbin
2011-03-11 14:15:00 -06:00
committed by J. Brisbin
parent 83f8306656
commit 158ee85d93
36 changed files with 2146 additions and 72 deletions

4
.gitignore vendored
View File

@@ -2,3 +2,7 @@ target
.springBeans
.ant-targets-build.xml
src/ant/.ant-targets-upload-dist.xml
.DS_Store
*.iml
*.ipr
*.iws

View File

@@ -1,79 +1,83 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons-parent</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<relativePath>../spring-data-commons-parent/pom.xml</relativePath>
</parent>
<artifactId>spring-data-commons-core</artifactId>
<packaging>jar</packaging>
<name>Spring Data Commons Core</name>
<dependencies>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons-parent</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<relativePath>../spring-data-commons-parent/pom.xml</relativePath>
</parent>
<artifactId>spring-data-commons-core</artifactId>
<packaging>jar</packaging>
<name>Spring Data Commons Core</name>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<optional>true</optional>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>1.6</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.springsource.bundlor</groupId>
<artifactId>com.springsource.bundlor.maven</artifactId>
</plugin>
</plugins>
</build>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>1.6</version>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.springsource.bundlor</groupId>
<artifactId>com.springsource.bundlor.maven</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,30 @@
/*
* 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.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author J. Brisbin <jbrisbin@vmware.com>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.FIELD})
public @interface Id {
}

View File

@@ -0,0 +1,30 @@
/*
* 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.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.CONSTRUCTOR)
public @interface PersistenceConstructor {
}

View File

@@ -0,0 +1,35 @@
/*
* 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.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author J. Brisbin <jbrisbin@vmware.com>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {
ElementType.TYPE,
ElementType.ANNOTATION_TYPE,
ElementType.FIELD,
ElementType.PARAMETER
})
public @interface Persistent {
}

View File

@@ -0,0 +1,33 @@
/*
* 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.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({
ElementType.ANNOTATION_TYPE,
ElementType.FIELD
})
public @interface Reference {
}

View File

@@ -0,0 +1,30 @@
/*
* 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.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author J. Brisbin <jbrisbin@vmware.com>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Transient {
}

View File

@@ -0,0 +1,27 @@
/*
* 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;
import org.springframework.data.mapping.model.Association;
import org.springframework.data.mapping.model.PersistentProperty;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public interface AssociationHandler {
void doWithAssociation(Association association);
}

View File

@@ -0,0 +1,212 @@
/*
* 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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.data.annotation.*;
import org.springframework.data.mapping.model.*;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.math.BigInteger;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class BasicMappingConfigurationBuilder implements MappingConfigurationBuilder {
protected static ConcurrentMap<Class<?>, BeanInfo> beanInfo = new ConcurrentHashMap<Class<?>, BeanInfo>();
protected Logger log = LoggerFactory.getLogger(getClass());
protected MappingContext mappingContext;
public BasicMappingConfigurationBuilder(MappingContext mappingContext) {
this.mappingContext = mappingContext;
}
@Override
public <T> boolean isPersistentEntity(Class<T> type) {
if (type.isAnnotationPresent(Persistent.class)) {
return true;
} else {
for (Annotation annotation : type.getDeclaredAnnotations()) {
if (annotation.annotationType().isAnnotationPresent(Persistent.class)) {
return true;
}
}
for (Field field : type.getDeclaredFields()) {
if (field.isAnnotationPresent(Id.class)) {
return true;
}
}
}
return false;
}
@SuppressWarnings({"unchecked"})
@Override
public <T> PersistentEntity<T> createPersistentEntity(Class<T> type) throws MappingConfigurationException {
return new BasicPersistentEntity<T>(mappingContext, type);
}
@Override
public boolean isPersistentProperty(Field field, PropertyDescriptor descriptor) throws MappingConfigurationException {
if ("class".equals(field.getName()) || isTransient(field)) {
return false;
}
return true;
}
@SuppressWarnings({"unchecked"})
@Override
public PersistentProperty<?> createPersistentProperty(Field field, PropertyDescriptor descriptor) throws MappingConfigurationException {
return new BasicPersistentProperty(field.getName(), field.getType(), field, descriptor);
}
@Override
public <T> PersistentProperty<?> getIdProperty(Class<T> type) throws MappingConfigurationException {
for (Field field : type.getDeclaredFields()) {
if (isIdField(field)) {
return createPersistentProperty(field, null);
}
}
return null;
}
@SuppressWarnings({"unchecked"})
@Override
public <T> PreferredConstructor<T> getPreferredConstructor(Class<T> type) throws MappingConfigurationException {
// Find the right constructor
PreferredConstructor<T> preferredConstructor = null;
for (Constructor<?> constructor : type.getConstructors()) {
if (constructor.getParameterTypes().length != 0) {
// Non-no-arg constructor
if (null == preferredConstructor || constructor.isAnnotationPresent(PersistenceConstructor.class)) {
preferredConstructor = new PreferredConstructor<T>((Constructor<T>) constructor);
String[] paramNames = new LocalVariableTableParameterNameDiscoverer().getParameterNames(constructor);
Type[] paramTypes = constructor.getGenericParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
Class<?> targetType = Object.class;
if (paramTypes[i] instanceof ParameterizedType) {
ParameterizedType ptype = (ParameterizedType) paramTypes[i];
Type[] types = ptype.getActualTypeArguments();
if (types.length == 1) {
if (types[0] instanceof TypeVariable) {
// Placeholder type
targetType = Object.class;
} else {
targetType = (Class<?>) types[0];
}
} else {
targetType = (Class<?>) ptype.getRawType();
}
} else {
if (paramTypes[i] instanceof TypeVariable) {
Type[] bounds = ((TypeVariable) paramTypes[i]).getBounds();
if (bounds.length > 0) {
targetType = (Class<?>) bounds[0];
}
} else if (paramTypes[i] instanceof Class<?>) {
targetType = (Class<?>) paramTypes[i];
}
}
preferredConstructor.addParameter(paramNames[i], targetType, targetType.getDeclaredAnnotations());
}
if (constructor.isAnnotationPresent(PersistenceConstructor.class)) {
// We're done
break;
}
}
}
}
return preferredConstructor;
}
@Override
public boolean isAssociation(Field field, PropertyDescriptor descriptor) throws MappingConfigurationException {
if (!isTransient(field)) {
if (field.isAnnotationPresent(Reference.class)) {
return true;
}
for (Annotation annotation : field.getDeclaredAnnotations()) {
if (annotation.annotationType().isAnnotationPresent(Reference.class)) {
return true;
}
}
}
return false;
}
@Override
public Association createAssociation(PersistentProperty<?> property) {
// Only support uni-directional associations in the Basic configuration
Association association = new Association(property, null);
property.setAssociation(association);
return association;
}
protected BeanInfo getBeanInfo(Class<?> type) {
BeanInfo info = beanInfo.get(type);
if (null == info) {
try {
info = Introspector.getBeanInfo(type);
} catch (IntrospectionException e) {
throw new MappingException(e.getMessage(), e);
}
beanInfo.put(type, info);
}
return info;
}
protected boolean isTransient(Field field) {
if (Modifier.isTransient(field.getModifiers())
|| null != field.getAnnotation(Transient.class)
|| null != field.getAnnotation(Value.class)) {
return true;
}
return false;
}
protected boolean isIdField(Field field) {
if (field.isAnnotationPresent(Id.class)) {
return true;
}
if (field.getType() == String.class || field.getType() == BigInteger.class) {
if ("id".equals(field.getName()) || "_id".equals(field.getName())) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,197 @@
/*
* 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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
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.util.Assert;
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 {
protected Logger log = LoggerFactory.getLogger(getClass());
protected MappingConfigurationBuilder builder;
protected ConcurrentMap<String, PersistentEntity<?>> persistentEntities = new ConcurrentHashMap<String, 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() {
builder = new BasicMappingConfigurationBuilder(this);
}
public BasicMappingContext(MappingConfigurationBuilder builder) {
this.builder = builder;
}
public BasicMappingContext(MappingConfigurationBuilder builder, GenericConversionService conversionService) {
this.builder = builder;
this.conversionService = conversionService;
}
@Override
public Collection<PersistentEntity<?>> getPersistentEntities() {
return persistentEntities.values();
}
@SuppressWarnings({"unchecked"})
@Override
public <T> PersistentEntity<T> getPersistentEntity(Class<T> type) {
return (PersistentEntity<T>) persistentEntities.get(type.getName());
}
@Override
public PersistentEntity<?> getPersistentEntity(String name) {
return persistentEntities.get(name);
}
@Override
public <T> PersistentEntity<T> addPersistentEntity(Class<T> type) {
if (null == persistentEntities.get(type.getName())) {
try {
PersistentEntity<T> entity = builder.createPersistentEntity(type);
BeanInfo info = Introspector.getBeanInfo(type);
Map<String, PropertyDescriptor> descriptors = new HashMap<String, PropertyDescriptor>();
for (PropertyDescriptor descriptor : info.getPropertyDescriptors()) {
descriptors.put(descriptor.getName(), descriptor);
}
for (Field field : type.getDeclaredFields()) {
PropertyDescriptor descriptor = descriptors.get(field.getName());
if (builder.isPersistentProperty(field, descriptor)) {
PersistentProperty<?> property = builder.createPersistentProperty(field, descriptor);
property.setOwner(entity);
entity.addPersistentProperty(property);
if (builder.isAssociation(field, descriptor)) {
Association association = builder.createAssociation(property);
entity.addAssociation(association);
}
}
}
entity.setIdProperty(builder.getIdProperty(type));
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);
}
persistentEntities.put(type.getName(), entity);
return entity;
} catch (MappingConfigurationException e) {
log.error(e.getMessage(), e);
} catch (IntrospectionException e) {
throw new MappingException(e.getMessage(), e);
}
}
return null;
}
@Override
public void addEntityValidator(PersistentEntity<?> entity, Validator validator) {
List<Validator> v = validators.get(entity);
if (null == v) {
v = new ArrayList<Validator>();
validators.put(entity, v);
}
v.add(validator);
}
@Override
public <S, T> void addTypeConverter(Converter<S, T> converter) {
conversionService.addConverter(converter);
}
@Override
public ConversionService getConversionService() {
return conversionService;
}
@Override
public ConverterRegistry getConverterRegistry() {
return conversionService;
}
@Override
public List<Validator> getEntityValidators(PersistentEntity<?> entity) {
return validators.get(entity);
}
@Override
public MappingConfigurationBuilder getMappingConfigurationBuilder() {
return builder;
}
@Override
public void setMappingConfigurationBuilder(MappingConfigurationBuilder builder) {
this.builder = builder;
}
@SuppressWarnings({"unchecked"})
@Override
public boolean isPersistentEntity(Object value) {
if (null != value) {
Class clazz;
if (value instanceof Class) {
clazz = ((Class) value);
} else {
clazz = value.getClass();
}
return builder.isPersistentEntity(clazz);
}
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

@@ -0,0 +1,127 @@
/*
* 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;
import org.springframework.data.mapping.model.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class BasicPersistentEntity<T> implements PersistentEntity {
protected final Class<T> type;
protected PreferredConstructor<T> preferredConstructor;
protected PersistentProperty<?> idProperty;
protected Map<String, PersistentProperty<?>> persistentProperties = new HashMap<String, PersistentProperty<?>>();
protected Map<String, Association> associations = new HashMap<String, Association>();
protected MappingContext mappingContext;
public BasicPersistentEntity(MappingContext mappingContext, Class<T> type) {
this.mappingContext = mappingContext;
this.type = type;
}
@Override
public PreferredConstructor getPreferredConstructor() {
return preferredConstructor;
}
@Override
public void setPreferredConstructor(PreferredConstructor constructor) {
this.preferredConstructor = constructor;
}
@Override
public String getName() {
return type.getName();
}
@Override
public PersistentProperty<?> getIdProperty() {
return idProperty;
}
@Override
public void setIdProperty(PersistentProperty property) {
idProperty = property;
}
@Override
public Collection<PersistentProperty<?>> getPersistentProperties() {
return persistentProperties.values();
}
@Override
public void addPersistentProperty(PersistentProperty property) {
persistentProperties.put(property.getName(), property);
}
@Override
public Collection<Association> getAssociations() {
return associations.values();
}
@Override
public void addAssociation(Association association) {
associations.put(association.getInverse().getName(), association);
}
public PersistentProperty getPersistentProperty(String name) {
return persistentProperties.get(name);
}
@Override
public Class<T> getType() {
return type;
}
@Override
public Collection<String> getPersistentPropertyNames() {
return persistentProperties.keySet();
}
@Override
public MappingContext getMappingContext() {
return mappingContext;
}
@Override
public void afterPropertiesSet() throws Exception {
}
@Override
public void doWithProperties(PropertyHandler handler) {
for (PersistentProperty<?> property : persistentProperties.values()) {
if (!property.isTransient() && !property.isAssociation()) {
handler.doWithPersistentProperty(property);
}
}
}
@Override
public void doWithAssociations(AssociationHandler handler) {
for (Association association : associations.values()) {
handler.doWithAssociation(association);
}
}
}

View File

@@ -0,0 +1,149 @@
/*
* 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;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mapping.model.Association;
import org.springframework.data.mapping.model.PersistentEntity;
import org.springframework.data.mapping.model.PersistentProperty;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class BasicPersistentProperty<T> implements PersistentProperty {
protected final String name;
protected final Class<T> type;
protected final PropertyDescriptor propertyDescriptor;
protected final Field field;
protected Association association;
protected Value value;
protected boolean isTransient = false;
protected PersistentEntity<?> owner;
public BasicPersistentProperty(String name,
Class<T> type,
Field field,
PropertyDescriptor propertyDescriptor) {
this.name = name;
this.type = type;
this.propertyDescriptor = propertyDescriptor;
this.field = field;
this.isTransient = Modifier.isTransient(field.getModifiers()) || field.isAnnotationPresent(Transient.class);
if (field.isAnnotationPresent(Value.class)) {
this.value = field.getAnnotation(Value.class);
// Fields with @Value annotations are considered the same as transient fields
this.isTransient = true;
}
if (field.isAnnotationPresent(Autowired.class)) {
this.isTransient = true;
}
}
@Override
public Object getOwner() {
return owner;
}
@Override
public void setOwner(Object owner) {
if (null != owner && owner.getClass().isAssignableFrom(PersistentEntity.class)) {
this.owner = (PersistentEntity<?>) owner;
}
}
@Override
public String getName() {
return name;
}
@Override
public Class<T> getType() {
return type;
}
@Override
public PropertyDescriptor getPropertyDescriptor() {
return propertyDescriptor;
}
@Override
public Field getField() {
return field;
}
@Override
public Value getValueAnnotation() {
return value;
}
@Override
public boolean isTransient() {
return isTransient;
}
@Override
public boolean isAssociation() {
return null != association;
}
@Override
public Association getAssociation() {
return association;
}
@Override
public void setAssociation(Association association) {
this.association = association;
}
@Override
public boolean isCollection() {
return type.isAssignableFrom(Collection.class) || type.isAssignableFrom(List.class);
}
@Override
public boolean isComplexType() {
return !MappingBeanHelper.getSimpleTypes().contains(field.getType().getName());
}
@Override
public Class<?> getComponentType() {
if (isCollection()) {
Type genericType = field.getGenericType();
if (genericType instanceof ParameterizedType) {
Type[] genericTypes = ((ParameterizedType) genericType).getActualTypeArguments();
for (Type t : genericTypes) {
if (t instanceof Class) {
return (Class<?>) t;
}
}
}
}
return type.getComponentType();
}
}

View File

@@ -0,0 +1,190 @@
/*
* 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;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.convert.support.ConversionServiceFactory;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.mapping.model.MappingInstantiationException;
import org.springframework.data.mapping.model.PersistentEntity;
import org.springframework.data.mapping.model.PersistentProperty;
import org.springframework.data.mapping.model.PreferredConstructor;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.ConcurrentSkipListSet;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public abstract class MappingBeanHelper {
protected static GenericConversionService conversionService = ConversionServiceFactory.createDefaultConversionService();
protected static SpelExpressionParser parser = new SpelExpressionParser();
protected static Set<String> simpleTypes = new ConcurrentSkipListSet<String>() {{
add(boolean.class.getName());
add(long.class.getName());
add(short.class.getName());
add(int.class.getName());
add(byte.class.getName());
add(float.class.getName());
add(double.class.getName());
add(char.class.getName());
add(Boolean.class.getName());
add(Long.class.getName());
add(Short.class.getName());
add(Integer.class.getName());
add(Byte.class.getName());
add(Float.class.getName());
add(Double.class.getName());
add(Character.class.getName());
add(String.class.getName());
add(java.util.Date.class.getName());
add(Locale.class.getName());
add(Class.class.getName());
}};
public static GenericConversionService getConversionService() {
return conversionService;
}
public static void setConversionService(GenericConversionService conversionService) {
MappingBeanHelper.conversionService = conversionService;
}
public static Set<String> getSimpleTypes() {
return simpleTypes;
}
public static <T> T constructInstance(PersistentEntity<T> entity,
PreferredConstructor.ParameterValueProvider provider) {
return constructInstance(entity, provider, new StandardEvaluationContext());
}
public static <T> T constructInstance(PersistentEntity<T> entity,
PreferredConstructor.ParameterValueProvider provider,
EvaluationContext spelCtx) {
PreferredConstructor<T> constructor = entity.getPreferredConstructor();
if (null == constructor) {
try {
return entity.getType().newInstance();
} catch (InstantiationException e) {
throw new MappingInstantiationException(e.getMessage(), e);
} catch (IllegalAccessException e) {
throw new MappingInstantiationException(e.getMessage(), e);
}
}
List<Object> params = new LinkedList<Object>();
if (null != provider && constructor.getParameters().size() > 0) {
for (PreferredConstructor.Parameter parameter : constructor.getParameters()) {
Value v = parameter.getValue();
Object obj;
if (null != v) {
Expression x = parser.parseExpression(v.value());
obj = x.getValue(spelCtx);
} else {
obj = provider.getParameterValue(parameter);
}
params.add(obj);
}
}
T obj = null;
try {
obj = constructor.getConstructor().newInstance(params.toArray());
} catch (InstantiationException e) {
throw new MappingInstantiationException(e.getMessage(), e);
} catch (IllegalAccessException e) {
throw new MappingInstantiationException(e.getMessage(), e);
} catch (InvocationTargetException e) {
throw new MappingInstantiationException(e.getMessage(), e);
}
return obj;
}
public static void setProperty(Object on,
PersistentProperty<?> property,
Object value)
throws IllegalAccessException, InvocationTargetException {
setProperty(on, property, value, false);
}
public static void setProperty(Object on,
PersistentProperty<?> property,
Object value,
boolean fieldAccessOnly)
throws IllegalAccessException, InvocationTargetException {
Field field = property.getField();
if (fieldAccessOnly || (null == property.getPropertyDescriptor() || null == property.getPropertyDescriptor().getWriteMethod())) {
field.setAccessible(true);
if (null != value && value.getClass().isAssignableFrom(field.getType())) {
field.set(on, value);
} else {
field.set(on, conversionService.convert(value, field.getType()));
}
return;
}
Method setter = property.getPropertyDescriptor().getWriteMethod();
Class<?>[] paramTypes = setter.getParameterTypes();
if (null != value && paramTypes.length > 0 && !value.getClass().isAssignableFrom(paramTypes[0])) {
setter.invoke(on, conversionService.convert(value, paramTypes[0]));
} else {
setter.invoke(on, value);
}
}
@SuppressWarnings({"unchecked"})
public static <T> T getProperty(Object from,
PersistentProperty<?> property,
Class<T> type,
boolean fieldAccessOnly)
throws IllegalAccessException, InvocationTargetException {
Field field = property.getField();
if (fieldAccessOnly || (null == property.getPropertyDescriptor() || null == property.getPropertyDescriptor().getReadMethod())) {
field.setAccessible(true);
Object obj = field.get(from);
if (null != obj && !obj.getClass().isAssignableFrom(type)) {
return conversionService.convert(obj, type);
} else {
return (T) obj;
}
}
Object obj = property.getPropertyDescriptor().getReadMethod().invoke(from);
if (null != obj && !obj.getClass().isAssignableFrom(type)) {
return conversionService.convert(obj, type);
} else {
return (T) obj;
}
}
}

View File

@@ -0,0 +1,26 @@
/*
* 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;
import org.springframework.data.mapping.model.PersistentProperty;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public interface PropertyHandler {
void doWithPersistentProperty(PersistentProperty<?> persistentProperty);
}

View File

@@ -0,0 +1,47 @@
/*
* 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.model;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class Association {
protected PersistentProperty<?> inverse;
protected PersistentProperty<?> obverse;
public Association(PersistentProperty<?> inverse, PersistentProperty<?> obverse) {
this.inverse = inverse;
this.obverse = obverse;
}
public PersistentProperty<?> getInverse() {
return inverse;
}
public void setInverse(PersistentProperty<?> inverse) {
this.inverse = inverse;
}
public PersistentProperty<?> getObverse() {
return obverse;
}
public void setObverse(PersistentProperty<?> obverse) {
this.obverse = obverse;
}
}

View File

@@ -0,0 +1,32 @@
/* Copyright (C) 2010 SpringSource
*
* 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.model;
/**
* Thrown when an error occurs reading the mapping between object and datastore
*
* @author Graeme Rocher
* @since 1.0
*/
public class IllegalMappingException extends RuntimeException {
public IllegalMappingException(String s, Throwable throwable) {
super(s, throwable);
}
public IllegalMappingException(String s) {
super(s);
}
}

View File

@@ -0,0 +1,43 @@
/*
* 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.model;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public interface MappingConfigurationBuilder {
<T> boolean isPersistentEntity(Class<T> clazz);
<T> PersistentEntity<T> createPersistentEntity(Class<T> clazz) throws MappingConfigurationException;
boolean isPersistentProperty(Field field, PropertyDescriptor descriptor) throws MappingConfigurationException;
PersistentProperty<?> createPersistentProperty(Field field, PropertyDescriptor descriptor) throws MappingConfigurationException;
<T> PersistentProperty<?> getIdProperty(Class<T> clazz) throws MappingConfigurationException;
<T> PreferredConstructor<?> getPreferredConstructor(Class<T> clazz) throws MappingConfigurationException;
boolean isAssociation(Field field, PropertyDescriptor descriptor) throws MappingConfigurationException;
Association createAssociation(PersistentProperty<?> property);
}

View File

@@ -0,0 +1,30 @@
/*
* 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.model;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class MappingConfigurationException extends Throwable {
public MappingConfigurationException(String s) {
super(s);
}
public MappingConfigurationException(String s, Throwable throwable) {
super(s, throwable);
}
}

View File

@@ -0,0 +1,131 @@
/* Copyright 2004-2005 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 org.springframework.data.mapping.model;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterRegistry;
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>
* <p/>
* <p>This interface is used internally to establish associations
* between entities and also at runtime to obtain entities by name</p>
* <p/>
* <p>The generic type parameters T & R are used to specify the
* mapped form of a class (example Table) and property (example Column) respectively.</p>
* <p/>
*
* @author Graeme Rocher
* @since 1.0
*/
public interface MappingContext extends InitializingBean {
/**
* Obtains a list of PersistentEntity instances
*
* @return A list of PersistentEntity instances
*/
Collection<PersistentEntity<?>> getPersistentEntities();
/**
* Obtains a PersistentEntity by name
*
* @param name The name of the entity
* @return The entity or null
*/
PersistentEntity<?> getPersistentEntity(String name);
<T> PersistentEntity<T> getPersistentEntity(Class<T> type);
/**
* Adds a PersistentEntity instance
*
* @param type The Java class representing the entity
* @return The PersistentEntity instance
*/
<T> PersistentEntity<T> addPersistentEntity(Class<T> type);
/**
* Adds a validator to be used by the entity for validation
*
* @param entity The PersistentEntity
* @param validator The validator
*/
void addEntityValidator(PersistentEntity<?> entity, Validator validator);
/**
* Add a converter used to convert property values to and from the datastore
*
* @param converter The converter to add
*/
<S, T> void addTypeConverter(Converter<S, T> converter);
/**
* Obtains the ConversionService instance to use for type conversion
*
* @return The conversion service instance
*/
ConversionService getConversionService();
/**
* Obtains the converter registry
*
* @return The converter registry used for type conversion
*/
ConverterRegistry getConverterRegistry();
/**
* Obtains a validator for the given entity
*
* @param entity The entity
* @return A validator or null if none exists for the given entity
*/
List<Validator> getEntityValidators(PersistentEntity<?> entity);
MappingConfigurationBuilder getMappingConfigurationBuilder();
void setMappingConfigurationBuilder(MappingConfigurationBuilder builder);
/**
* Returns whether the specified value is a persistent entity
*
* @param value The value to check
* @return True if it is
*/
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);
}
}

View File

@@ -0,0 +1,30 @@
/*
* 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.model;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class MappingException extends RuntimeException {
public MappingException(String s) {
super(s);
}
public MappingException(String s, Throwable throwable) {
super(s, throwable);
}
}

View File

@@ -0,0 +1,30 @@
/*
* 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.model;
/**
* Created by IntelliJ IDEA.
* User: jbrisbin
* Date: 2/25/11
* Time: 9:07 AM
* To change this template use File | Settings | File Templates.
*/
public class MappingInstantiationException extends RuntimeException {
public MappingInstantiationException(String s, Throwable throwable) {
super(s, throwable);
}
}

View File

@@ -0,0 +1,87 @@
package org.springframework.data.mapping.model;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.mapping.AssociationHandler;
import org.springframework.data.mapping.PropertyHandler;
import java.util.Collection;
/**
* Represents a persistent entity
*
* @author Graeme Rocher
* @since 1.0
*/
public interface PersistentEntity<T> extends InitializingBean {
/**
* The entity name including any package prefix
*
* @return The entity name
*/
String getName();
PreferredConstructor<T> getPreferredConstructor();
void setPreferredConstructor(PreferredConstructor constructor);
/**
* Returns the identity of the instance
*
* @return The identity
*/
PersistentProperty<?> getIdProperty();
void setIdProperty(PersistentProperty<?> property);
/**
* A list of properties to be persisted
*
* @return A list of PersistentProperty instances
*/
Collection<PersistentProperty<?>> getPersistentProperties();
void addPersistentProperty(PersistentProperty<?> property);
/**
* A list of the associations for this entity. This is typically a subset of the list returned by {@link #getPersistentProperties()}
*
* @return A list of associations
*/
Collection<Association> getAssociations();
void addAssociation(Association association);
/**
* Obtains a PersistentProperty instance by name
*
* @param name The name of the property
* @return The PersistentProperty or null if it doesn't exist
*/
PersistentProperty<?> getPersistentProperty(String name);
/**
* @return The underlying Java class for this entity
*/
Class<T> getType();
/**
* A list of property names
*
* @return A List of strings
*/
Collection<String> getPersistentPropertyNames();
/**
* Obtains the MappingContext where this PersistentEntity is defined
*
* @return The MappingContext instance
*/
MappingContext getMappingContext();
void doWithProperties(PropertyHandler handler);
void doWithAssociations(AssociationHandler handler);
}

View File

@@ -0,0 +1,52 @@
package org.springframework.data.mapping.model;
import org.springframework.beans.factory.annotation.Value;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
/**
* @author Graeme Rocher
* @since 1.0
*/
public interface PersistentProperty<T> {
Object getOwner();
void setOwner(Object owner);
/**
* The name of the property
*
* @return The property name
*/
String getName();
/**
* The type of the property
*
* @return The property type
*/
Class<T> getType();
PropertyDescriptor getPropertyDescriptor();
Field getField();
Value getValueAnnotation();
boolean isTransient();
boolean isAssociation();
Association getAssociation();
void setAssociation(Association association);
boolean isCollection();
boolean isComplexType();
Class<?> getComponentType();
}

View File

@@ -0,0 +1,90 @@
/*
* 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.model;
import org.springframework.beans.factory.annotation.Value;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.util.LinkedList;
import java.util.List;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class PreferredConstructor<T> {
protected Constructor<T> constructor;
protected List<Parameter> parameters = new LinkedList<Parameter>();
public PreferredConstructor(Constructor<T> constructor) {
this.constructor = constructor;
this.parameters = parameters;
}
public Constructor<T> getConstructor() {
return constructor;
}
public List<Parameter> getParameters() {
return parameters;
}
public void addParameter(String name, Class<?> type, Annotation[] annotations) {
parameters.add(new Parameter(name, type, annotations));
}
public static class Parameter {
protected final String name;
protected final Class<?> type;
protected final Annotation[] annotations;
protected Value value;
public Parameter(String name, Class<?> type, Annotation[] annotations) {
this.name = name;
this.type = type;
this.annotations = annotations;
for (Annotation anno : annotations) {
if (anno.annotationType() == Value.class) {
this.value = (Value) anno;
break;
}
}
}
public String getName() {
return name;
}
public Class<?> getType() {
return type;
}
public Annotation[] getAnnotations() {
return annotations;
}
public Value getValue() {
return value;
}
}
public static interface ParameterValueProvider {
Object getParameterValue(Parameter parameter);
}
}

View File

@@ -0,0 +1,31 @@
/*
* 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;
import org.springframework.data.annotation.Persistent;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
@Persistent
public class Child extends PersonWithId {
public Child(Integer ssn, String firstName, String lastName) {
super(ssn, firstName, lastName);
}
}

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;
import org.springframework.data.annotation.Persistent;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({
ElementType.TYPE,
ElementType.FIELD
})
@Persistent
public @interface Document {
}

View File

@@ -0,0 +1,82 @@
/*
* 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;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.data.mapping.model.Association;
import org.springframework.data.mapping.model.PersistentEntity;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static junit.framework.Assert.*;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:mapping.xml")
public class MappingMetadataTests {
BasicMappingContext ctx;
@Before
public void setup() {
ctx = new BasicMappingContext();
}
@Test
public void testDoesRecognizePersistentEntities() {
boolean persistentEntity = ctx.isPersistentEntity(PersonNoId.class);
assertFalse(persistentEntity);
persistentEntity = ctx.isPersistentEntity(PersonPersistent.class);
assertTrue(persistentEntity);
}
@Test
public void testPojoWithId() {
PersistentEntity<PersonWithId> person = ctx.addPersistentEntity(PersonWithId.class);
assertNotNull(person.getIdProperty());
assertEquals(String.class, person.getIdProperty().getType());
}
@Test
public void testPojoWithoutId() {
PersistentEntity<PersonNoId> person = ctx.addPersistentEntity(PersonNoId.class);
assertNull(person.getIdProperty());
}
@Test
public void testAssociations() {
PersistentEntity<PersonWithChildren> person = ctx.addPersistentEntity(PersonWithChildren.class);
assertNotNull(person.getAssociations());
for (Association association : person.getAssociations()) {
assertEquals(Child.class, association.getInverse().getComponentType());
}
}
@Test
public void testDoesRecognizeDocumentEntities() {
// PersistentEntity<PersonDocument> person = ctx.addPersistentEntity(PersonDocument.class);
boolean persistentEntity = ctx.isPersistentEntity(PersonDocument.class);
assertTrue(persistentEntity);
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public abstract class Person {
private Integer ssn;
private String firstName;
private String lastName;
protected Person(Integer ssn, String firstName, String lastName) {
this.ssn = ssn;
this.firstName = firstName;
this.lastName = lastName;
}
public Integer getSsn() {
return ssn;
}
public void setSsn(Integer ssn) {
this.ssn = ssn;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}

View File

@@ -0,0 +1,29 @@
/*
* 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;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
@Document
public class PersonDocument extends Person {
public PersonDocument(Integer ssn, String firstName, String lastName) {
super(ssn, firstName, lastName);
}
}

View File

@@ -0,0 +1,28 @@
/*
* 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;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class PersonNoId extends Person {
public PersonNoId(Integer ssn, String firstName, String lastName) {
super(ssn, firstName, lastName);
}
}

View File

@@ -0,0 +1,31 @@
/*
* 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;
import org.springframework.data.annotation.Persistent;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
@Persistent
public class PersonPersistent extends PersonWithId {
public PersonPersistent(Integer ssn, String firstName, String lastName) {
super(ssn, firstName, lastName);
}
}

View File

@@ -0,0 +1,43 @@
/*
* 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;
import org.springframework.data.annotation.Reference;
import java.util.List;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class PersonWithChildren extends Person {
@Reference
private List<Child> children;
public PersonWithChildren(Integer ssn, String firstName, String lastName) {
super(ssn, firstName, lastName);
}
public List<Child> getChildren() {
return children;
}
public void setChildren(List<Child> children) {
this.children = children;
}
}

View File

@@ -0,0 +1,37 @@
/*
* 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;
import org.springframework.data.annotation.Id;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class PersonWithId extends Person {
@Id
private String id;
public PersonWithId(Integer ssn, String firstName, String lastName) {
super(ssn, firstName, lastName);
}
public String getId() {
return id;
}
}

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p %c{1} - %m%n"/>
</layout>
</appender>
<category name="org.springframework.data.mapping">
<level value="DEBUG"/>
</category>
<category name="org.springframework">
<level value="WARN"/>
</category>
<root>
<appender-ref ref="console"/>
</root>
</log4j:configuration>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>

View File

@@ -11,7 +11,11 @@ Import-Template:
org.springframework.context.*;version="[3.0.0, 4.0.0)",
org.springframework.dao.*;version="[3.0.0, 4.0.0)",
org.springframework.util.*;version="[3.0.0, 4.0.0)",
org.springframework.expression.*;version="[3.0.0, 4.0.0)",
org.springframework.expression.spel.standard.*;version="[3.0.0, 4.0.0)",
org.springframework.expression.spel.support.*;version="[3.0.0, 4.0.0)",
org.springframework.transaction.*;version="[3.0.0, 4.0.0)",
org.springframework.validation.*;version="[3.0.0, 4.0.0)",
org.springframework.data.core.*;version="[1.0.0, 2.0.0)",
org.springframework.data.persistence.*;version="[1.0.0, 2.0.0)",
org.aopalliance.*;version="[1.0.0, 2.0.0)";resolution:=optional,