75 changed files with 935 additions and 4331 deletions
@ -0,0 +1,76 @@
@@ -0,0 +1,76 @@
|
||||
package org.springframework.persistence.document.test; |
||||
|
||||
import javax.persistence.Entity; |
||||
import javax.persistence.Id; |
||||
|
||||
import org.springframework.persistence.RelatedEntity; |
||||
|
||||
@Entity |
||||
public class Person { |
||||
|
||||
@Id Long id; |
||||
|
||||
private String name; |
||||
|
||||
private int age; |
||||
|
||||
private java.util.Date birthDate; |
||||
|
||||
// @Document // need to decide what the annotation here should be
|
||||
@RelatedEntity |
||||
public Resume resume; |
||||
|
||||
public Person() { |
||||
} |
||||
|
||||
public Person(String name, int age) { |
||||
this.name = name; |
||||
this.age = age; |
||||
this.birthDate = new java.util.Date(); |
||||
} |
||||
|
||||
public void birthday() { |
||||
++age; |
||||
} |
||||
|
||||
public Long getId() { |
||||
return id; |
||||
} |
||||
|
||||
public void setId(Long id) { |
||||
this.id = id; |
||||
} |
||||
|
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
public void setName(String name) { |
||||
this.name = name; |
||||
} |
||||
|
||||
public int getAge() { |
||||
return age; |
||||
} |
||||
|
||||
public void setAge(int age) { |
||||
this.age = age; |
||||
} |
||||
|
||||
public java.util.Date getBirthDate() { |
||||
return birthDate; |
||||
} |
||||
|
||||
public void setBirthDate(java.util.Date birthDate) { |
||||
this.birthDate = birthDate; |
||||
} |
||||
|
||||
public Resume getResume() { |
||||
return resume; |
||||
} |
||||
|
||||
public void setResume(Resume resume) { |
||||
this.resume = resume; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
package org.springframework.persistence.document.test; |
||||
|
||||
import org.springframework.persistence.document.DocumentEntity; |
||||
|
||||
@DocumentEntity |
||||
public class Resume { |
||||
|
||||
private String education = ""; |
||||
|
||||
private String jobs = ""; |
||||
|
||||
public String getEducation() { |
||||
return education; |
||||
} |
||||
|
||||
public void addEducation(String education) { |
||||
this.education = this.education + (this.education.length() > 0 ? "; " : "") + education; |
||||
} |
||||
|
||||
public String getJobs() { |
||||
return jobs; |
||||
} |
||||
|
||||
public void addJob(String job) { |
||||
this.jobs = this.jobs + (this.jobs.length() > 0 ? "; " : "") + job; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "Resume [education=" + education + ", jobs=" + jobs + "]"; |
||||
} |
||||
|
||||
} |
||||
@ -1,45 +0,0 @@
@@ -1,45 +0,0 @@
|
||||
/* |
||||
* 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.document.mongodb.mapping; |
||||
|
||||
/** |
||||
* @author Jon Brisbin <jbrisbin@vmware.com> |
||||
*/ |
||||
public class MappingException extends RuntimeException { |
||||
|
||||
private final Object source; |
||||
|
||||
public MappingException(String s) { |
||||
super(s); |
||||
this.source = null; |
||||
} |
||||
|
||||
public MappingException(String s, Object source) { |
||||
super(String.format("Error encountered mapping object: %s", source)); |
||||
this.source = source; |
||||
} |
||||
|
||||
public MappingException(String s, Throwable throwable, Object source) { |
||||
super(s, throwable); |
||||
this.source = source; |
||||
} |
||||
|
||||
public Object getSource() { |
||||
return source; |
||||
} |
||||
|
||||
} |
||||
@ -1,499 +0,0 @@
@@ -1,499 +0,0 @@
|
||||
/* |
||||
* 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.document.mongodb.mapping; |
||||
|
||||
import com.mongodb.DBRef; |
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import org.bson.types.CodeWScope; |
||||
import org.bson.types.ObjectId; |
||||
import org.springframework.beans.factory.InitializingBean; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.context.ApplicationContext; |
||||
import org.springframework.context.expression.BeanFactoryResolver; |
||||
import org.springframework.core.LocalVariableTableParameterNameDiscoverer; |
||||
import org.springframework.data.mapping.annotation.*; |
||||
import org.springframework.data.mapping.model.MappingInstantiationException; |
||||
import org.springframework.expression.Expression; |
||||
import org.springframework.expression.spel.standard.SpelExpressionParser; |
||||
import org.springframework.expression.spel.support.StandardEvaluationContext; |
||||
|
||||
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.*; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
import java.util.concurrent.ConcurrentMap; |
||||
import java.util.regex.Pattern; |
||||
|
||||
/** |
||||
* @author Jon Brisbin <jbrisbin@vmware.com> |
||||
*/ |
||||
public class MappingIntrospector<T> { |
||||
|
||||
private static final Log log = LogFactory.getLog(MappingIntrospector.class); |
||||
private static final ConcurrentMap<Class<?>, MappingIntrospector<?>> introspectors = new ConcurrentHashMap<Class<?>, MappingIntrospector<?>>(); |
||||
private static final Set<String> SIMPLE_TYPES; |
||||
|
||||
static { |
||||
Set<String> basics = new HashSet<String>(); |
||||
basics.add(boolean.class.getName()); |
||||
basics.add(long.class.getName()); |
||||
basics.add(short.class.getName()); |
||||
basics.add(int.class.getName()); |
||||
basics.add(byte.class.getName()); |
||||
basics.add(float.class.getName()); |
||||
basics.add(double.class.getName()); |
||||
basics.add(char.class.getName()); |
||||
basics.add(Boolean.class.getName()); |
||||
basics.add(Long.class.getName()); |
||||
basics.add(Short.class.getName()); |
||||
basics.add(Integer.class.getName()); |
||||
basics.add(Byte.class.getName()); |
||||
basics.add(Float.class.getName()); |
||||
basics.add(Double.class.getName()); |
||||
basics.add(Character.class.getName()); |
||||
basics.add(String.class.getName()); |
||||
basics.add(java.util.Date.class.getName()); |
||||
basics.add(Locale.class.getName()); |
||||
basics.add(Class.class.getName()); |
||||
basics.add(DBRef.class.getName()); |
||||
basics.add(Pattern.class.getName()); |
||||
basics.add(CodeWScope.class.getName()); |
||||
basics.add(ObjectId.class.getName()); |
||||
// TODO check on enums..
|
||||
basics.add(Enum.class.getName()); |
||||
SIMPLE_TYPES = Collections.unmodifiableSet(basics); |
||||
} |
||||
|
||||
private final Class<T> clazz; |
||||
private final BeanInfo beanInfo; |
||||
private final Map<String, PropertyDescriptor> properties; |
||||
private final Map<String, Field> fields; |
||||
private final Set<Association> associations; |
||||
private final Map<String, Method> setters; |
||||
private final Map<String, Method> getters; |
||||
private Field idField = null; |
||||
private PropertyDescriptor idPropertyDescriptor = null; |
||||
private List<String> ignoredProperties = new ArrayList<String>() {{ |
||||
add("class"); |
||||
}}; |
||||
private List<Class<?>> validIdTypes = new ArrayList<Class<?>>() {{ |
||||
add(ObjectId.class); |
||||
add(String.class); |
||||
add(BigInteger.class); |
||||
}}; |
||||
|
||||
private SpelExpressionParser parser = new SpelExpressionParser(); |
||||
private Map<String, Expression> expressions = new HashMap<String, Expression>(); |
||||
private PreferredConstructor preferredConstructor = null; |
||||
|
||||
@SuppressWarnings({"unchecked"}) |
||||
private MappingIntrospector(Class<T> clazz) throws MappingException { |
||||
this.clazz = clazz; |
||||
try { |
||||
this.beanInfo = Introspector.getBeanInfo(clazz); |
||||
} catch (IntrospectionException e) { |
||||
throw new MappingException(e.getMessage(), e, clazz); |
||||
} |
||||
Map<String, PropertyDescriptor> properties = new HashMap<String, PropertyDescriptor>(); |
||||
Map<String, Field> fields = new HashMap<String, Field>(); |
||||
Set<Association> associations = new HashSet<Association>(); |
||||
Map<String, Method> setters = new HashMap<String, Method>(); |
||||
Map<String, Method> getters = new HashMap<String, Method>(); |
||||
for (PropertyDescriptor descriptor : beanInfo.getPropertyDescriptors()) { |
||||
String name = descriptor.getName(); |
||||
if (!ignoredProperties.contains(name)) { |
||||
try { |
||||
Field fld = clazz.getDeclaredField(name); |
||||
Class<?> fldType = fld.getType(); |
||||
fld.setAccessible(true); |
||||
if (!isTransientField(fld)) { |
||||
if (fld.isAnnotationPresent(Id.class)) { |
||||
if (null == idField) { |
||||
idField = fld; |
||||
idPropertyDescriptor = descriptor; |
||||
} else { |
||||
log.warn("Only the first field found with the @Id annotation will be considered the ID. Ignoring " + idField); |
||||
} |
||||
continue; |
||||
} else if (null == idField |
||||
&& validIdTypes.contains(fldType) |
||||
&& ("id".equals(name) || "_id".equals(name))) { |
||||
idField = fld; |
||||
idPropertyDescriptor = descriptor; |
||||
continue; |
||||
} else if (fld.isAnnotationPresent(Reference.class) |
||||
|| fld.isAnnotationPresent(OneToMany.class) |
||||
|| fld.isAnnotationPresent(OneToOne.class) |
||||
|| fld.isAnnotationPresent(ManyToMany.class)) { |
||||
Class<?> targetClass = fld.getType(); |
||||
if (fld.isAnnotationPresent(Reference.class)) { |
||||
Reference ref = fld.getAnnotation(Reference.class); |
||||
if (ref.targetClass() != Object.class) { |
||||
targetClass = ref.targetClass(); |
||||
} |
||||
} |
||||
if (fldType.isAssignableFrom(Collection.class) || fldType.isAssignableFrom(List.class)) { |
||||
Type t = fld.getGenericType(); |
||||
if (t instanceof ParameterizedType) { |
||||
ParameterizedType ptype = (ParameterizedType) t; |
||||
Type[] paramTypes = ptype.getActualTypeArguments(); |
||||
if (paramTypes.length > 0) { |
||||
if (paramTypes[0] instanceof TypeVariable) { |
||||
targetClass = Object.class; |
||||
} else { |
||||
targetClass = (Class<?>) paramTypes[0]; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
associations.add(new Association(descriptor, fld, targetClass)); |
||||
continue; |
||||
} else if (fld.isAnnotationPresent(Value.class)) { |
||||
// @Value fields are evaluated at runtime and are the same transient fields
|
||||
continue; |
||||
} |
||||
fields.put(name, fld); |
||||
properties.put(name, descriptor); |
||||
setters.put(name, descriptor.getWriteMethod()); |
||||
getters.put(name, descriptor.getReadMethod()); |
||||
if (fld.isAnnotationPresent(Value.class)) { |
||||
expressions.put(name, parser.parseExpression(fld.getAnnotation(Value.class).value())); |
||||
} |
||||
} |
||||
} catch (NoSuchFieldException e) { |
||||
log.warn(e.getMessage()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (null == this.idField) { |
||||
// ID might be in a private field
|
||||
for (Field f : fields.values()) { |
||||
Class<?> type = f.getType(); |
||||
if (f.isAnnotationPresent(Id.class)) { |
||||
this.idField = f; |
||||
break; |
||||
} else if (validIdTypes.contains(type) && (f.getName().equals("id") || f.getName().equals("_id"))) { |
||||
this.idField = f; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
this.properties = Collections.unmodifiableMap(properties); |
||||
this.fields = Collections.unmodifiableMap(fields); |
||||
this.associations = Collections.unmodifiableSet(associations); |
||||
this.setters = Collections.unmodifiableMap(setters); |
||||
this.getters = Collections.unmodifiableMap(getters); |
||||
|
||||
// Find the right constructor
|
||||
for (Constructor<?> constructor : clazz.getConstructors()) { |
||||
if (constructor.getParameterTypes().length != 0) { |
||||
// Non-no-arg constructor
|
||||
if (null == preferredConstructor || constructor.isAnnotationPresent(PersistenceConstructor.class)) { |
||||
String[] paramNames = new LocalVariableTableParameterNameDiscoverer().getParameterNames(constructor); |
||||
Type[] paramTypes = constructor.getGenericParameterTypes(); |
||||
Class<?>[] paramClassTypes = new Class[paramTypes.length]; |
||||
for (int i = 0; i < paramTypes.length; i++) { |
||||
Class<?> targetType; |
||||
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 { |
||||
targetType = (Class<?>) paramTypes[i]; |
||||
} |
||||
paramClassTypes[i] = targetType; |
||||
} |
||||
preferredConstructor = new PreferredConstructor((Constructor<T>) constructor, paramNames, paramClassTypes); |
||||
if (constructor.isAnnotationPresent(PersistenceConstructor.class)) { |
||||
// We're done
|
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
@SuppressWarnings({"unchecked"}) |
||||
public static <C extends Object> MappingIntrospector<C> getInstance(Class<C> clazz) throws MappingException { |
||||
MappingIntrospector<C> introspector = (MappingIntrospector<C>) introspectors.get(clazz); |
||||
if (null == introspector) { |
||||
introspector = new MappingIntrospector<C>(clazz); |
||||
introspectors.put(clazz, introspector); |
||||
} |
||||
return introspector; |
||||
} |
||||
|
||||
public Class<T> getTargetClass() { |
||||
return clazz; |
||||
} |
||||
|
||||
public Field getField(String name) { |
||||
return fields.get(name); |
||||
} |
||||
|
||||
public PropertyDescriptor getPropertyDescriptor(String name) { |
||||
return properties.get(name); |
||||
} |
||||
|
||||
public boolean isMappable() { |
||||
return (null != clazz.getAnnotation(Persistent.class)); |
||||
} |
||||
|
||||
public Field getIdField() { |
||||
return idField; |
||||
} |
||||
|
||||
public PropertyDescriptor getIdPropertyDescriptor() { |
||||
return idPropertyDescriptor; |
||||
} |
||||
|
||||
public T createInstance() { |
||||
return createInstance(null); |
||||
} |
||||
|
||||
public T createInstance(ParameterValueProvider provider) { |
||||
try { |
||||
if (null == preferredConstructor || null == provider) { |
||||
return clazz.newInstance(); |
||||
} else { |
||||
List<Object> params = new LinkedList<Object>(); |
||||
for (ConstructorParameter<?> p : preferredConstructor.parameters) { |
||||
Expression x = null; |
||||
Value v = p.getValueAnnotation(); |
||||
if (null != v) { |
||||
x = parser.parseExpression(v.value()); |
||||
} |
||||
params.add(provider.getParameterValue(p.name, p.type, x)); |
||||
} |
||||
return preferredConstructor.constructor.newInstance(params.toArray()); |
||||
} |
||||
} catch (InvocationTargetException e) { |
||||
throw new MappingInstantiationException(e.getMessage(), e); |
||||
} catch (InstantiationException e) { |
||||
throw new MappingInstantiationException(e.getMessage(), e); |
||||
} catch (IllegalAccessException e) { |
||||
throw new MappingInstantiationException(e.getMessage(), e); |
||||
} |
||||
} |
||||
|
||||
public Object getFieldValue(String name, Object from) throws MappingException { |
||||
return getFieldValue(name, from, null); |
||||
} |
||||
|
||||
public Object getFieldValue(String name, Object from, Object defaultObj) throws MappingException { |
||||
try { |
||||
if (properties.containsKey(name) && null != getters.get(name)) { |
||||
return getters.get(name).invoke(from); |
||||
} else { |
||||
if (fields.containsKey(name)) { |
||||
Field f = fields.get(name); |
||||
return f.get(from); |
||||
} else { |
||||
for (Association assoc : associations) { |
||||
if (assoc.getField().getName().equals(name)) { |
||||
return assoc.getField().get(from); |
||||
} |
||||
} |
||||
for (Field f : clazz.getDeclaredFields()) { |
||||
// Lastly, check for any private fields
|
||||
if (f.getName().equals(name)) { |
||||
f.setAccessible(true); |
||||
return f.get(from); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} catch (IllegalAccessException e) { |
||||
throw new MappingException(e.getMessage(), e, from); |
||||
} catch (InvocationTargetException e) { |
||||
throw new MappingException(e.getMessage(), e, from); |
||||
} |
||||
return defaultObj; |
||||
} |
||||
|
||||
public void setValue(String name, Object on, Object value) throws MappingException { |
||||
Field f = fields.get(name); |
||||
try { |
||||
if (null != f) { |
||||
Method setter = setters.get(name); |
||||
if (null != setter) { |
||||
setter.invoke(on, value); |
||||
} else { |
||||
f.set(on, value); |
||||
} |
||||
} else { |
||||
for (Association assoc : associations) { |
||||
if (assoc.getField().getName().equals(name)) { |
||||
assoc.getField().set(on, value); |
||||
return; |
||||
} |
||||
} |
||||
for (Field privFld : clazz.getDeclaredFields()) { |
||||
if (privFld.getName().equals(name)) { |
||||
privFld.setAccessible(true); |
||||
privFld.set(on, value); |
||||
return; |
||||
} |
||||
} |
||||
} |
||||
} catch (IllegalAccessException e) { |
||||
throw new MappingException(e.getMessage(), e, value); |
||||
} catch (InvocationTargetException e) { |
||||
throw new MappingException(e.getMessage(), e, value); |
||||
} |
||||
} |
||||
|
||||
public void maybeAutowire(Object obj, ApplicationContext applicationContext, boolean autowire) throws MappingException { |
||||
StandardEvaluationContext evaluationContext = new StandardEvaluationContext(obj); |
||||
evaluationContext.setBeanResolver(new BeanFactoryResolver(applicationContext)); |
||||
|
||||
if (autowire) { |
||||
applicationContext.getAutowireCapableBeanFactory().autowireBean(obj); |
||||
if (obj instanceof InitializingBean) { |
||||
try { |
||||
((InitializingBean) obj).afterPropertiesSet(); |
||||
} catch (Exception e) { |
||||
throw new MappingException(e.getMessage(), e, obj); |
||||
} |
||||
} |
||||
} |
||||
|
||||
for (Map.Entry<String, Expression> entry : expressions.entrySet()) { |
||||
setValue(entry.getKey(), obj, entry.getValue().getValue(evaluationContext)); |
||||
} |
||||
} |
||||
|
||||
public void doWithProperties(PropertyHandler handler) { |
||||
for (Map.Entry<String, PropertyDescriptor> entry : properties.entrySet()) { |
||||
String name = entry.getKey(); |
||||
handler.doWithProperty(entry.getValue(), fields.get(name), expressions.get(name)); |
||||
} |
||||
} |
||||
|
||||
public void doWithAssociations(AssociationHandler handler) { |
||||
for (Association association : associations) { |
||||
handler.doWithAssociation(association); |
||||
} |
||||
} |
||||
|
||||
public static boolean isSimpleType(Class<?> propertyType) { |
||||
if (propertyType == null) { |
||||
return false; |
||||
} |
||||
if (propertyType.isArray()) { |
||||
return isSimpleType(propertyType.getComponentType()); |
||||
} |
||||
return SIMPLE_TYPES.contains(propertyType.getName()); |
||||
} |
||||
|
||||
public static boolean isTransientField(Field f) { |
||||
return (Modifier.isTransient(f.getModifiers()) || null != f.getAnnotation(Transient.class) || null != f.getAnnotation(Autowired.class)); |
||||
} |
||||
|
||||
public static class Association { |
||||
|
||||
private final PropertyDescriptor descriptor; |
||||
private final Field field; |
||||
private final Class<?> targetClass; |
||||
|
||||
public Association(PropertyDescriptor descriptor, Field field, Class<?> targetClass) { |
||||
this.descriptor = descriptor; |
||||
this.field = field; |
||||
this.targetClass = targetClass; |
||||
} |
||||
|
||||
public PropertyDescriptor getDescriptor() { |
||||
return descriptor; |
||||
} |
||||
|
||||
public Field getField() { |
||||
return field; |
||||
} |
||||
|
||||
public Class<?> getTargetClass() { |
||||
return targetClass; |
||||
} |
||||
} |
||||
|
||||
private class PreferredConstructor { |
||||
|
||||
Constructor<T> constructor; |
||||
ConstructorParameter<?>[] parameters; |
||||
|
||||
@SuppressWarnings({"unchecked"}) |
||||
public PreferredConstructor(Constructor<T> constructor, String[] names, Class<?>[] types) { |
||||
this.constructor = constructor; |
||||
Annotation[][] annos = constructor.getParameterAnnotations(); |
||||
parameters = new ConstructorParameter[names.length]; |
||||
for (int i = 0; i < names.length; i++) { |
||||
parameters[i] = new ConstructorParameter(names[i], types[i], annos[i]); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private class ConstructorParameter<V> { |
||||
String name; |
||||
Class<V> type; |
||||
Annotation[] annotations; |
||||
|
||||
private ConstructorParameter(String name, Class<V> type, Annotation[] annotations) { |
||||
this.name = name; |
||||
this.type = type; |
||||
this.annotations = annotations; |
||||
} |
||||
|
||||
private Value getValueAnnotation() { |
||||
for (Annotation anno : annotations) { |
||||
if (anno instanceof Value) { |
||||
return (Value) anno; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
public interface AssociationHandler { |
||||
void doWithAssociation(Association association); |
||||
} |
||||
|
||||
public interface PropertyHandler { |
||||
void doWithProperty(PropertyDescriptor descriptor, Field field, Expression spelExpr); |
||||
} |
||||
|
||||
public interface ParameterValueProvider { |
||||
<T> T getParameterValue(String name, Class<T> type, Expression spelExpr); |
||||
} |
||||
|
||||
} |
||||
@ -1,33 +0,0 @@
@@ -1,33 +0,0 @@
|
||||
/* |
||||
* 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.document.mongodb.mapping; |
||||
|
||||
import org.springframework.data.mapping.model.AbstractClassMapping; |
||||
import org.springframework.data.mapping.model.MappingContext; |
||||
import org.springframework.data.mapping.model.PersistentEntity; |
||||
|
||||
public class MongoClassMapping extends AbstractClassMapping<MongoCollection> { |
||||
|
||||
public MongoClassMapping(PersistentEntity entity, MappingContext context) { |
||||
super(entity, context); |
||||
} |
||||
|
||||
@Override |
||||
public MongoCollection getMappedForm() { |
||||
return (MongoCollection) context.getMappingFactory().createMappedForm(entity); |
||||
} |
||||
} |
||||
@ -1,37 +0,0 @@
@@ -1,37 +0,0 @@
|
||||
/* |
||||
* 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.document.mongodb.mapping; |
||||
|
||||
/** |
||||
* @author Jon Brisbin <jbrisbin@vmware.com> |
||||
*/ |
||||
public class MongoCollection { |
||||
|
||||
private String name; |
||||
|
||||
public MongoCollection(String name) { |
||||
this.name = name; |
||||
} |
||||
|
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
public void setName(String name) { |
||||
this.name = name; |
||||
} |
||||
} |
||||
@ -0,0 +1,167 @@
@@ -0,0 +1,167 @@
|
||||
/* |
||||
* 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.document.mongodb.mapping; |
||||
|
||||
import com.mongodb.BasicDBObject; |
||||
import com.mongodb.DBCollection; |
||||
import com.mongodb.DBObject; |
||||
import com.mongodb.MongoException; |
||||
import com.mongodb.util.JSON; |
||||
import org.bson.types.CodeWScope; |
||||
import org.bson.types.ObjectId; |
||||
import org.springframework.dao.DataAccessException; |
||||
import org.springframework.data.document.mongodb.CollectionCallback; |
||||
import org.springframework.data.document.mongodb.MongoTemplate; |
||||
import org.springframework.data.document.mongodb.index.CompoundIndex; |
||||
import org.springframework.data.document.mongodb.index.CompoundIndexes; |
||||
import org.springframework.data.document.mongodb.index.IndexDirection; |
||||
import org.springframework.data.document.mongodb.index.Indexed; |
||||
import org.springframework.data.mapping.BasicMappingConfigurationBuilder; |
||||
import org.springframework.data.mapping.MappingBeanHelper; |
||||
import org.springframework.data.mapping.model.*; |
||||
|
||||
import java.beans.PropertyDescriptor; |
||||
import java.lang.reflect.Field; |
||||
import java.math.BigInteger; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* @author Jon Brisbin <jbrisbin@vmware.com> |
||||
*/ |
||||
public class MongoMappingConfigurationBuilder extends BasicMappingConfigurationBuilder { |
||||
|
||||
protected Map<String, CompoundIndex> compoundIndexes = new HashMap<String, CompoundIndex>(); |
||||
protected Map<String, Indexed> fieldIndexes = new HashMap<String, Indexed>(); |
||||
protected MongoTemplate mongoTemplate; |
||||
|
||||
public MongoMappingConfigurationBuilder(MongoTemplate mongoTemplate) { |
||||
this.mongoTemplate = mongoTemplate; |
||||
// Augment simpleTypes with MongoDB-specific classes
|
||||
Set<String> simpleTypes = MappingBeanHelper.getSimpleTypes(); |
||||
simpleTypes.add(DBRef.class.getName()); |
||||
simpleTypes.add(ObjectId.class.getName()); |
||||
simpleTypes.add(CodeWScope.class.getName()); |
||||
} |
||||
|
||||
@Override |
||||
public PersistentProperty<?> createPersistentProperty(Field field, PropertyDescriptor descriptor) throws MappingConfigurationException { |
||||
PersistentProperty<?> property = super.createPersistentProperty(field, descriptor); |
||||
if (field.isAnnotationPresent(Indexed.class)) { |
||||
Indexed index = field.getAnnotation(Indexed.class); |
||||
String collection = index.collection(); |
||||
if ("".equals(collection)) { |
||||
collection = field.getName(); |
||||
} |
||||
if (!fieldIndexes.containsKey(collection)) { |
||||
ensureIndex(collection, index.name(), null, index.direction(), index.unique(), index.dropDups(), index.sparse()); |
||||
fieldIndexes.put(collection, index); |
||||
} |
||||
} |
||||
return property; |
||||
} |
||||
|
||||
@SuppressWarnings({"unchecked"}) |
||||
@Override |
||||
public <T> PersistentEntity<T> createPersistentEntity(Class<T> type, MappingContext mappingContext) throws MappingConfigurationException { |
||||
MongoPersistentEntity<T> entity = new MongoPersistentEntity<T>(mappingContext, type); |
||||
|
||||
// Check for special collection setting
|
||||
if (type.isAnnotationPresent(Document.class)) { |
||||
Document doc = type.getAnnotation(Document.class); |
||||
String collection = doc.collection(); |
||||
if ("".equals(collection)) { |
||||
collection = type.getSimpleName().toLowerCase(); |
||||
} |
||||
entity.setCollection(collection); |
||||
} |
||||
|
||||
// Make sure indexes get created
|
||||
if (type.isAnnotationPresent(CompoundIndexes.class)) { |
||||
CompoundIndexes indexes = type.getAnnotation(CompoundIndexes.class); |
||||
for (CompoundIndex index : indexes.value()) { |
||||
String indexColl = index.collection(); |
||||
if ("".equals(indexColl)) { |
||||
indexColl = type.getSimpleName().toLowerCase(); |
||||
} |
||||
if (!compoundIndexes.containsKey(indexColl)) { |
||||
ensureIndex(indexColl, index.name(), index.def(), index.direction(), index.unique(), index.dropDups(), index.sparse()); |
||||
compoundIndexes.put(indexColl, index); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return entity; |
||||
} |
||||
|
||||
@Override |
||||
public boolean isAssociation(Field field, PropertyDescriptor descriptor) throws MappingConfigurationException { |
||||
if (field.isAnnotationPresent(DBRef.class)) { |
||||
return true; |
||||
} |
||||
return super.isAssociation(field, descriptor); |
||||
} |
||||
|
||||
@Override |
||||
public Association createAssociation(PersistentProperty<?> property) { |
||||
return super.createAssociation(property); |
||||
} |
||||
|
||||
@Override |
||||
protected boolean isIdField(Field field) { |
||||
if (super.isIdField(field)) { |
||||
return true; |
||||
} |
||||
if (field.getType() == ObjectId.class || field.getType() == BigInteger.class) { |
||||
if ("id".equals(field.getName()) || "_id".equals(field.getName())) { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
protected void ensureIndex(String collection, |
||||
final String name, |
||||
final String def, |
||||
final IndexDirection direction, |
||||
final boolean unique, |
||||
final boolean dropDups, |
||||
final boolean sparse) { |
||||
mongoTemplate.execute(collection, new CollectionCallback<Object>() { |
||||
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException { |
||||
DBObject defObj; |
||||
if (null != def) { |
||||
defObj = (DBObject) JSON.parse(def); |
||||
} else { |
||||
defObj = new BasicDBObject(); |
||||
defObj.put(name, (direction == IndexDirection.ASCENDING ? 1 : -1)); |
||||
} |
||||
DBObject opts = new BasicDBObject(); |
||||
if (!"".equals(name)) { |
||||
opts.put("name", name); |
||||
} |
||||
opts.put("dropDups", dropDups); |
||||
opts.put("sparse", sparse); |
||||
opts.put("unique", unique); |
||||
collection.ensureIndex(defObj, opts); |
||||
return null; |
||||
} |
||||
}); |
||||
} |
||||
|
||||
} |
||||
@ -1,417 +0,0 @@
@@ -1,417 +0,0 @@
|
||||
package org.springframework.data.document.mongodb.mapping; |
||||
|
||||
import com.mongodb.BasicDBObject; |
||||
import com.mongodb.DBCollection; |
||||
import com.mongodb.DBObject; |
||||
import com.mongodb.MongoException; |
||||
import com.mongodb.util.JSON; |
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import org.springframework.dao.DataAccessException; |
||||
import org.springframework.data.document.mongodb.CollectionCallback; |
||||
import org.springframework.data.document.mongodb.MongoTemplate; |
||||
import org.springframework.data.document.mongodb.index.CompoundIndex; |
||||
import org.springframework.data.document.mongodb.index.CompoundIndexes; |
||||
import org.springframework.data.document.mongodb.index.IndexDirection; |
||||
import org.springframework.data.document.mongodb.index.Indexed; |
||||
import org.springframework.data.mapping.annotation.IdentifiedBy; |
||||
import org.springframework.data.mapping.annotation.OneToOne; |
||||
import org.springframework.data.mapping.annotation.PersistenceStrategy; |
||||
import org.springframework.data.mapping.annotation.Persistent; |
||||
import org.springframework.data.mapping.model.*; |
||||
import org.springframework.data.mapping.model.types.Association; |
||||
import org.springframework.expression.EvaluationContext; |
||||
import org.springframework.expression.Expression; |
||||
import org.springframework.expression.common.TemplateParserContext; |
||||
import org.springframework.expression.spel.standard.SpelExpressionParser; |
||||
import org.springframework.expression.spel.support.StandardEvaluationContext; |
||||
import org.springframework.util.Assert; |
||||
|
||||
import java.beans.IntrospectionException; |
||||
import java.beans.PropertyDescriptor; |
||||
import java.lang.annotation.Annotation; |
||||
import java.lang.reflect.Field; |
||||
import java.lang.reflect.Method; |
||||
import java.lang.reflect.ParameterizedType; |
||||
import java.lang.reflect.Type; |
||||
import java.util.*; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
/** |
||||
* @author J. Brisbin <jbrisbin@vmware.com> |
||||
*/ |
||||
public class MongoMappingConfigurationStrategy implements MappingConfigurationStrategy { |
||||
|
||||
protected static final Log log = LogFactory.getLog(MongoMappingConfigurationStrategy.class); |
||||
|
||||
protected MongoTemplate mongo; |
||||
protected MongoMappingFactory mappingFactory; |
||||
protected SpelExpressionParser expressionParser = new SpelExpressionParser(); |
||||
protected TemplateParserContext templateParserContext = new TemplateParserContext(); |
||||
protected Map<Class<?>, PersistenceDescriptor> descriptors = new ConcurrentHashMap<Class<?>, PersistenceDescriptor>(); |
||||
protected Map<Class<?>, Set<PersistentEntity>> owners = new LinkedHashMap<Class<?>, Set<PersistentEntity>>(); |
||||
|
||||
public MongoMappingConfigurationStrategy(MongoTemplate mongo) { |
||||
this.mongo = mongo; |
||||
} |
||||
|
||||
public MongoMappingConfigurationStrategy(MongoTemplate mongo, MongoMappingFactory mappingFactory) { |
||||
this.mongo = mongo; |
||||
this.mappingFactory = mappingFactory; |
||||
} |
||||
|
||||
public SpelExpressionParser getExpressionParser() { |
||||
return expressionParser; |
||||
} |
||||
|
||||
public void setExpressionParser(SpelExpressionParser expressionParser) { |
||||
this.expressionParser = expressionParser; |
||||
} |
||||
|
||||
public TemplateParserContext getTemplateParserContext() { |
||||
return templateParserContext; |
||||
} |
||||
|
||||
public void setTemplateParserContext(TemplateParserContext templateParserContext) { |
||||
this.templateParserContext = templateParserContext; |
||||
} |
||||
|
||||
@SuppressWarnings({"unchecked"}) |
||||
public boolean isPersistentEntity(Class aClass) { |
||||
if (null != aClass) { |
||||
return (null != aClass.getAnnotation(Persistent.class)); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public List<PersistentProperty> getPersistentProperties(Class aClass, MappingContext mappingContext) { |
||||
return getPersistentProperties(aClass, mappingContext, null); |
||||
} |
||||
|
||||
public List<PersistentProperty> getPersistentProperties(Class aClass, |
||||
MappingContext mappingContext, |
||||
ClassMapping classMapping) { |
||||
PersistenceDescriptor pd = null; |
||||
try { |
||||
pd = getPersistenceDescriptor(aClass, mappingContext, classMapping); |
||||
} catch (MappingException e) { |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
return (null != pd ? pd.getProperties() : null); |
||||
} |
||||
|
||||
public PersistentProperty getIdentity(Class aClass, MappingContext mappingContext) throws MappingException { |
||||
PersistenceDescriptor idPd = getPersistenceDescriptor(aClass, mappingContext, null); |
||||
return (null != idPd ? idPd.getIdProperty() : null); |
||||
} |
||||
|
||||
public IdentityMapping getDefaultIdentityMapping(final ClassMapping classMapping) throws MappingException { |
||||
final PersistentProperty<?> prop = getPersistenceDescriptor(classMapping.getEntity().getJavaClass(), |
||||
classMapping.getEntity().getMappingContext(), |
||||
classMapping).getIdProperty(); |
||||
|
||||
return new IdentityMapping() { |
||||
public String[] getIdentifierName() { |
||||
return new String[]{prop.getName()}; |
||||
} |
||||
|
||||
public ClassMapping getClassMapping() { |
||||
return classMapping; |
||||
} |
||||
|
||||
public Object getMappedForm() { |
||||
return classMapping.getMappedForm(); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
public Set getOwningEntities(Class aClass, MappingContext mappingContext) { |
||||
return owners.get(aClass); |
||||
} |
||||
|
||||
protected PersistenceDescriptor getPersistenceDescriptor(final Class<?> javaClass, |
||||
final MappingContext context, |
||||
final ClassMapping mapping) throws MappingException { |
||||
PersistenceDescriptor descriptor = descriptors.get(javaClass); |
||||
if (null == descriptor) { |
||||
final MappingIntrospector introspector = MappingIntrospector.getInstance(javaClass); |
||||
final PersistentEntity entity = getPersistentEntity(javaClass, context, mapping); |
||||
|
||||
final String collection = javaClass.getSimpleName().toLowerCase(); |
||||
for (Annotation anno : javaClass.getAnnotations()) { |
||||
if (anno instanceof Persistent) { |
||||
|
||||
} else if (anno instanceof CompoundIndexes) { |
||||
CompoundIndexes idxs = (CompoundIndexes) anno; |
||||
for (CompoundIndex idx : idxs.value()) { |
||||
String idxColl = collection; |
||||
if (!"".equals(idx.collection())) { |
||||
idxColl = idx.collection(); |
||||
} |
||||
String name = null; |
||||
if (!"".equals(idx.name())) { |
||||
name = idx.name(); |
||||
} |
||||
ensureIndex(idxColl, name, idx.def(), null, idx.unique(), idx.dropDups(), idx.sparse()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
EvaluationContext elContext = new StandardEvaluationContext(); |
||||
elContext.setVariable("class", javaClass); |
||||
|
||||
PropertyDescriptor idPropDesc = MappingIntrospector.getInstance(entity.getJavaClass()).getIdPropertyDescriptor(); |
||||
PersistentProperty<?> id = mappingFactory.createIdentity(entity, context, idPropDesc); |
||||
|
||||
final List<PersistentProperty> properties = new LinkedList<PersistentProperty>(); |
||||
introspector.doWithProperties(new MappingIntrospector.PropertyHandler() { |
||||
public void doWithProperty(PropertyDescriptor descriptor, Field field, Expression spelExpr) { |
||||
PersistentProperty<?> p = null; |
||||
try { |
||||
p = createPersistentProperty(entity, context, descriptor, mapping); |
||||
if (null != p) { |
||||
properties.add(p); |
||||
for (Annotation anno : field.getDeclaredAnnotations()) { |
||||
if (anno instanceof Indexed) { |
||||
Indexed idx = (Indexed) anno; |
||||
String idxColl = collection; |
||||
if (!"".equals(idx.collection())) { |
||||
idxColl = idx.collection(); |
||||
} |
||||
String name = p.getName(); |
||||
if (!"".equals(idx.name())) { |
||||
name = idx.name(); |
||||
} |
||||
ensureIndex(idxColl, name, null, idx.direction(), idx.unique(), idx.dropDups(), idx.sparse()); |
||||
} |
||||
} |
||||
} |
||||
} catch (MappingException e) { |
||||
throw new IllegalMappingException(e.getMessage(), e); |
||||
} |
||||
} |
||||
}); |
||||
|
||||
descriptor = new PersistenceDescriptor(entity, id, properties); |
||||
descriptors.put(javaClass, descriptor); |
||||
} |
||||
return descriptor; |
||||
} |
||||
|
||||
protected PersistentEntity getPersistentEntity(Class<?> javaClass, MappingContext context, ClassMapping mapping) { |
||||
Assert.notNull(javaClass); |
||||
if (null != mapping) { |
||||
return mapping.getEntity(); |
||||
} else { |
||||
return context.getPersistentEntity(javaClass.getName()); |
||||
} |
||||
} |
||||
|
||||
protected PersistentProperty<?> createPersistentProperty(PersistentEntity entity, |
||||
MappingContext mappingContext, |
||||
PropertyDescriptor descriptor, |
||||
ClassMapping mapping) throws MappingException { |
||||
MappingIntrospector introspector = MappingIntrospector.getInstance(entity.getJavaClass()); |
||||
Field f = introspector.getField(descriptor.getName()); |
||||
|
||||
if (null != f) { |
||||
// Handle associations and persistent types
|
||||
PersistentProperty<?> prop = extractChildType(entity, mappingContext, descriptor, mapping); |
||||
if (null == prop) { |
||||
// Must be a simple type
|
||||
prop = mappingFactory.createSimple(entity, mappingContext, descriptor); |
||||
} |
||||
return prop; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
protected PersistentProperty<?> extractChildType(PersistentEntity entity, |
||||
MappingContext mappingContext, |
||||
PropertyDescriptor descriptor, |
||||
ClassMapping mapping) throws MappingException { |
||||
MappingIntrospector introspector = MappingIntrospector.getInstance(entity.getJavaClass()); |
||||
Field f = introspector.getField(descriptor.getName()); |
||||
|
||||
Class<?> childClass = null; |
||||
Association<?> assoc = null; |
||||
if (f.getType().isAssignableFrom(List.class)) { |
||||
if (null != f.getAnnotation(org.springframework.data.mapping.annotation.OneToMany.class)) { |
||||
org.springframework.data.mapping.annotation.OneToMany otm = f.getAnnotation( |
||||
org.springframework.data.mapping.annotation.OneToMany.class); |
||||
if (Object.class != otm.targetClass()) { |
||||
childClass = otm.targetClass(); |
||||
} else { |
||||
childClass = extractType(f); |
||||
} |
||||
assoc = mappingFactory.createOneToMany(entity, mappingContext, descriptor); |
||||
} else if (null != f.getAnnotation(org.springframework.data.mapping.annotation.ManyToMany.class)) { |
||||
org.springframework.data.mapping.annotation.ManyToMany mtm = f.getAnnotation( |
||||
org.springframework.data.mapping.annotation.ManyToMany.class); |
||||
if (Object.class != mtm.targetClass()) { |
||||
childClass = mtm.targetClass(); |
||||
} else { |
||||
childClass = extractType(f); |
||||
} |
||||
assoc = mappingFactory.createManyToMany(entity, mappingContext, descriptor); |
||||
} |
||||
} else { |
||||
if (null != f.getAnnotation(OneToOne.class) || null != f.getType().getAnnotation(Persistent.class)) { |
||||
childClass = f.getType(); |
||||
assoc = mappingFactory.createOneToOne(entity, mappingContext, descriptor); |
||||
} |
||||
} |
||||
if (null != childClass && null != assoc) { |
||||
if (childClass != entity.getJavaClass()) { |
||||
PersistentEntity childEntity = getPersistentEntity(childClass, mappingContext, mapping); |
||||
addOwner(entity.getJavaClass(), childEntity); |
||||
assoc.setAssociatedEntity(childEntity); |
||||
} else { |
||||
addOwner(entity.getJavaClass(), entity); |
||||
assoc.setAssociatedEntity(entity); |
||||
} |
||||
} |
||||
|
||||
return assoc; |
||||
} |
||||
|
||||
protected Class<?> extractType(Field f) { |
||||
Type t = f.getGenericType(); |
||||
if (null != t && t instanceof ParameterizedType) { |
||||
Type[] types = ((ParameterizedType) t).getActualTypeArguments(); |
||||
return ((Class) types[0]); |
||||
} |
||||
return f.getType(); |
||||
} |
||||
|
||||
protected IdentifiedBy extractIdentifiedBy(Class<?> clazz, Field field) { |
||||
Persistent cAnno = clazz.getAnnotation(Persistent.class); |
||||
Persistent fldAnno = (null != field ? field.getAnnotation(Persistent.class) : null); |
||||
return (null != fldAnno ? fldAnno.identifiedBy() : cAnno.identifiedBy()); |
||||
} |
||||
|
||||
protected PersistenceStrategy extractPersistenceStrategy(Class<?> clazz, Field field) { |
||||
Persistent cAnno = clazz.getAnnotation(Persistent.class); |
||||
Persistent fldAnno = (null != field ? field.getAnnotation(Persistent.class) : null); |
||||
return (null != fldAnno ? fldAnno.strategy() : cAnno.strategy()); |
||||
} |
||||
|
||||
protected String extractId(Class<?> clazz, Field field) { |
||||
Persistent cAnno = clazz.getAnnotation(Persistent.class); |
||||
Persistent fldAnno = (null != field ? field.getAnnotation(Persistent.class) : null); |
||||
return (null != fldAnno ? fldAnno.id() : cAnno.id()); |
||||
} |
||||
|
||||
protected void addOwner(Class<?> javaClass, PersistentEntity parent) { |
||||
if (!owners.containsKey(javaClass)) { |
||||
Set<PersistentEntity> owningEntities = new HashSet<PersistentEntity>(); |
||||
owningEntities.add(parent); |
||||
owners.put(javaClass, owningEntities); |
||||
} |
||||
} |
||||
|
||||
protected void ensureIndex(String collection, |
||||
final String name, |
||||
final String def, |
||||
final IndexDirection direction, |
||||
final boolean unique, |
||||
final boolean dropDups, |
||||
final boolean sparse) { |
||||
mongo.execute(collection, new CollectionCallback<Object>() { |
||||
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException { |
||||
DBObject defObj; |
||||
if (null != def) { |
||||
defObj = (DBObject) JSON.parse(def); |
||||
} else { |
||||
defObj = new BasicDBObject(); |
||||
defObj.put(name, (direction == IndexDirection.ASCENDING ? 1 : -1)); |
||||
} |
||||
DBObject opts = new BasicDBObject(); |
||||
if (!"".equals(name)) { |
||||
opts.put("name", name); |
||||
} |
||||
opts.put("dropDups", dropDups); |
||||
opts.put("sparse", sparse); |
||||
opts.put("unique", unique); |
||||
collection.ensureIndex(defObj, opts); |
||||
return null; |
||||
} |
||||
}); |
||||
} |
||||
|
||||
protected class PersistenceDescriptor { |
||||
|
||||
PersistentEntity entity; |
||||
PersistentProperty idProperty = null; |
||||
List<PersistentProperty> properties = null; |
||||
|
||||
PersistenceDescriptor(PersistentEntity entity, PersistentProperty idProperty, List<PersistentProperty> properties) { |
||||
this.entity = entity; |
||||
this.idProperty = idProperty; |
||||
this.properties = properties; |
||||
} |
||||
|
||||
public PersistentEntity getEntity() { |
||||
return entity; |
||||
} |
||||
|
||||
public PersistentProperty getIdProperty() { |
||||
return idProperty; |
||||
} |
||||
|
||||
public List<PersistentProperty> getProperties() { |
||||
return properties; |
||||
} |
||||
|
||||
} |
||||
|
||||
protected class ValuePropertyDescriptor extends PropertyDescriptor { |
||||
|
||||
Object value; |
||||
|
||||
ValuePropertyDescriptor(String s, Class<?> aClass, Object value) throws IntrospectionException { |
||||
super(s, aClass); |
||||
this.value = value; |
||||
} |
||||
|
||||
public Object getValue() { |
||||
return value; |
||||
} |
||||
|
||||
public void setValue(Object value) { |
||||
this.value = value; |
||||
} |
||||
|
||||
@Override |
||||
public Method getReadMethod() { |
||||
try { |
||||
return getClass().getMethod("getValue", null); |
||||
} catch (NoSuchMethodException e) { |
||||
// IGNORED
|
||||
} |
||||
return super.getReadMethod(); |
||||
} |
||||
|
||||
@Override |
||||
public void setReadMethod(Method method) throws IntrospectionException { |
||||
// IGNORED
|
||||
} |
||||
|
||||
@Override |
||||
public Method getWriteMethod() { |
||||
try { |
||||
return getClass().getMethod("setValue", Object.class); |
||||
} catch (NoSuchMethodException e) { |
||||
// IGNORED
|
||||
} |
||||
return super.getWriteMethod(); |
||||
} |
||||
|
||||
@Override |
||||
public void setWriteMethod(Method method) throws IntrospectionException { |
||||
// IGNORED
|
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -1,59 +0,0 @@
@@ -1,59 +0,0 @@
|
||||
/* |
||||
* 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.document.mongodb.mapping; |
||||
|
||||
import org.springframework.data.document.mongodb.MongoTemplate; |
||||
import org.springframework.data.mapping.model.AbstractMappingContext; |
||||
import org.springframework.data.mapping.model.MappingConfigurationStrategy; |
||||
import org.springframework.data.mapping.model.MappingFactory; |
||||
import org.springframework.data.mapping.model.PersistentEntity; |
||||
|
||||
/** |
||||
* @author Jon Brisbin <jbrisbin@vmware.com> |
||||
*/ |
||||
public class MongoMappingContext extends AbstractMappingContext { |
||||
|
||||
private MongoTemplate mongo; |
||||
private MongoMappingFactory mappingFactory = null; |
||||
private MappingConfigurationStrategy strategy = null; |
||||
|
||||
public MongoMappingContext(MongoTemplate mongo) { |
||||
this.mongo = mongo; |
||||
this.mappingFactory = new MongoMappingFactory(); |
||||
strategy = new MongoMappingConfigurationStrategy(mongo, mappingFactory); |
||||
} |
||||
|
||||
public MongoMappingContext(MongoTemplate mongo, MongoMappingFactory mappingFactory) { |
||||
this.mongo = mongo; |
||||
this.mappingFactory = mappingFactory; |
||||
strategy = new MongoMappingConfigurationStrategy(mongo, mappingFactory); |
||||
} |
||||
|
||||
@Override |
||||
protected PersistentEntity createPersistentEntity(Class javaClass) { |
||||
MongoPersistentEntity entity = new MongoPersistentEntity(javaClass, this); |
||||
return entity; |
||||
} |
||||
|
||||
public MappingConfigurationStrategy getMappingSyntaxStrategy() { |
||||
return strategy; |
||||
} |
||||
|
||||
public MappingFactory getMappingFactory() { |
||||
return mappingFactory; |
||||
} |
||||
} |
||||
@ -1,43 +0,0 @@
@@ -1,43 +0,0 @@
|
||||
/* |
||||
* 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.document.mongodb.mapping; |
||||
|
||||
import org.springframework.data.document.mongodb.MongoTemplate; |
||||
import org.springframework.data.mapping.model.MappingFactory; |
||||
import org.springframework.data.mapping.model.PersistentEntity; |
||||
import org.springframework.data.mapping.model.PersistentProperty; |
||||
import org.springframework.data.mapping.reflect.ClassPropertyFetcher; |
||||
|
||||
import java.lang.reflect.Field; |
||||
|
||||
/** |
||||
* @author Jon Brisbin <jbrisbin@vmware.com> |
||||
*/ |
||||
public class MongoMappingFactory extends MappingFactory<MongoCollection, MongoProperty> { |
||||
|
||||
@Override |
||||
public MongoCollection createMappedForm(PersistentEntity entity) { |
||||
String name = entity.getJavaClass().getSimpleName().toLowerCase(); |
||||
return new MongoCollection(name); |
||||
} |
||||
|
||||
@Override |
||||
public MongoProperty createMappedForm(PersistentProperty property) { |
||||
String name = property.getName(); |
||||
return new MongoProperty(name, false); |
||||
} |
||||
} |
||||
@ -1,38 +0,0 @@
@@ -1,38 +0,0 @@
|
||||
/* |
||||
* 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.document.mongodb.mapping; |
||||
|
||||
/** |
||||
* @author Jon Brisbin <jbrisbin@vmware.com> |
||||
*/ |
||||
public class MongoProperty { |
||||
|
||||
private String name; |
||||
|
||||
public MongoProperty(String name, boolean indexed) { |
||||
this.name = name; |
||||
} |
||||
|
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
public void setName(String name) { |
||||
this.name = name; |
||||
} |
||||
|
||||
} |
||||
@ -1,14 +0,0 @@
@@ -1,14 +0,0 @@
|
||||
package org.springframework.data.mapping.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 { |
||||
} |
||||
@ -1,12 +0,0 @@
@@ -1,12 +0,0 @@
|
||||
package org.springframework.data.mapping.annotation; |
||||
|
||||
/** |
||||
* @author J. Brisbin <jbrisbin@vmware.com> |
||||
*/ |
||||
public enum IdentifiedBy { |
||||
DEFAULT, |
||||
ANNOTATION, |
||||
PROPERTY, |
||||
VALUE, |
||||
PARENT |
||||
} |
||||
@ -1,17 +0,0 @@
@@ -1,17 +0,0 @@
|
||||
package org.springframework.data.mapping.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 ManyToMany { |
||||
|
||||
Class<?> targetClass() default Object.class; |
||||
|
||||
} |
||||
@ -1,17 +0,0 @@
@@ -1,17 +0,0 @@
|
||||
package org.springframework.data.mapping.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 OneToMany { |
||||
|
||||
Class<?> targetClass() default Object.class; |
||||
|
||||
} |
||||
@ -1,14 +0,0 @@
@@ -1,14 +0,0 @@
|
||||
package org.springframework.data.mapping.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 OneToOne { |
||||
} |
||||
@ -1,30 +0,0 @@
@@ -1,30 +0,0 @@
|
||||
/* |
||||
* 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.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 { |
||||
} |
||||
@ -1,11 +0,0 @@
@@ -1,11 +0,0 @@
|
||||
package org.springframework.data.mapping.annotation; |
||||
|
||||
/** |
||||
* @author J. Brisbin <jbrisbin@vmware.com> |
||||
*/ |
||||
public enum PersistenceStrategy { |
||||
DEFAULT, |
||||
KEY_VALUE, |
||||
DOCUMENT, |
||||
SERIALIZED |
||||
} |
||||
@ -1,37 +0,0 @@
@@ -1,37 +0,0 @@
|
||||
/* |
||||
* 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.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.FIELD}) |
||||
public @interface Persistent { |
||||
|
||||
PersistenceStrategy strategy() default PersistenceStrategy.DOCUMENT; |
||||
|
||||
IdentifiedBy identifiedBy() default IdentifiedBy.DEFAULT; |
||||
|
||||
String id() default "id"; |
||||
|
||||
} |
||||
@ -1,14 +0,0 @@
@@ -1,14 +0,0 @@
|
||||
package org.springframework.data.mapping.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 { |
||||
} |
||||
@ -1,42 +0,0 @@
@@ -1,42 +0,0 @@
|
||||
/* 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; |
||||
|
||||
/** |
||||
* Abstract implementation of the ClassMapping interface
|
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public abstract class AbstractClassMapping<T> implements ClassMapping{ |
||||
protected PersistentEntity entity; |
||||
protected MappingContext context; |
||||
|
||||
public AbstractClassMapping(PersistentEntity entity, MappingContext context) { |
||||
super(); |
||||
this.entity = entity; |
||||
this.context = context; |
||||
} |
||||
|
||||
public PersistentEntity getEntity() { |
||||
return this.entity; |
||||
} |
||||
|
||||
public abstract T getMappedForm(); |
||||
|
||||
public IdentityMapping getIdentifier() { |
||||
return context.getMappingSyntaxStrategy().getDefaultIdentityMapping(this); |
||||
} |
||||
} |
||||
@ -1,156 +0,0 @@
@@ -1,156 +0,0 @@
|
||||
/* 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; |
||||
|
||||
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.GenericConversionService; |
||||
import org.springframework.validation.Validator; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.Map; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
import java.util.concurrent.ConcurrentLinkedQueue; |
||||
|
||||
/** |
||||
* Abstract implementation of the MappingContext interface
|
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public abstract class AbstractMappingContext implements MappingContext { |
||||
|
||||
protected Collection<PersistentEntity> persistentEntities = new ConcurrentLinkedQueue<PersistentEntity>(); |
||||
protected Map<String, PersistentEntity> persistentEntitiesByName = new ConcurrentHashMap<String, PersistentEntity>(); |
||||
protected Map<PersistentEntity, Map<String, PersistentEntity>> persistentEntitiesByDiscriminator = new ConcurrentHashMap<PersistentEntity, Map<String, PersistentEntity>>(); |
||||
protected Map<PersistentEntity, Validator> entityValidators = new ConcurrentHashMap<PersistentEntity, Validator>(); |
||||
protected Collection<Listener> eventListeners = new ConcurrentLinkedQueue<Listener>(); |
||||
protected GenericConversionService conversionService = new GenericConversionService(); |
||||
|
||||
public ConversionService getConversionService() { |
||||
return conversionService; |
||||
} |
||||
|
||||
public ConverterRegistry getConverterRegistry() { |
||||
return conversionService; |
||||
} |
||||
|
||||
public void addMappingContextListener(Listener listener) { |
||||
if (listener != null) |
||||
eventListeners.add(listener); |
||||
} |
||||
|
||||
public void addTypeConverter(Converter converter) { |
||||
conversionService.addConverter(converter); |
||||
} |
||||
|
||||
public Validator getEntityValidator(PersistentEntity entity) { |
||||
if (entity != null) { |
||||
return entityValidators.get(entity); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public void addEntityValidator(PersistentEntity entity, Validator validator) { |
||||
if (entity != null && validator != null) { |
||||
entityValidators.put(entity, validator); |
||||
} |
||||
} |
||||
|
||||
public PersistentEntity addExternalPersistentEntity(Class javaClass) { |
||||
if (javaClass == null) throw new IllegalArgumentException("PersistentEntity class cannot be null"); |
||||
|
||||
PersistentEntity entity = persistentEntitiesByName.get(javaClass.getName()); |
||||
|
||||
if (entity == null) { |
||||
entity = addPersistentEntityInternal(javaClass, true); |
||||
} |
||||
|
||||
return entity; |
||||
} |
||||
|
||||
public final PersistentEntity addPersistentEntity(Class javaClass) { |
||||
if (javaClass == null) throw new IllegalArgumentException("PersistentEntity class cannot be null"); |
||||
|
||||
PersistentEntity entity = persistentEntitiesByName.get(javaClass.getName()); |
||||
|
||||
if (entity == null) { |
||||
entity = addPersistentEntityInternal(javaClass, false); |
||||
} |
||||
|
||||
return entity; |
||||
} |
||||
|
||||
private PersistentEntity addPersistentEntityInternal(Class javaClass, boolean isExternal) { |
||||
PersistentEntity entity; |
||||
entity = createPersistentEntity(javaClass); |
||||
entity.setExternal(isExternal); |
||||
|
||||
persistentEntities.remove(entity); |
||||
persistentEntities.add(entity); |
||||
persistentEntitiesByName.put(entity.getName(), entity); |
||||
try { |
||||
entity.afterPropertiesSet(); |
||||
} catch (Exception e) { |
||||
throw new RuntimeException(String.format("Error initializing PersistentEntity: %s", entity), e); |
||||
} |
||||
if (!entity.isRoot()) { |
||||
PersistentEntity root = entity.getRootEntity(); |
||||
Map<String, PersistentEntity> children = persistentEntitiesByDiscriminator.get(root); |
||||
if (children == null) { |
||||
children = new ConcurrentHashMap<String, PersistentEntity>(); |
||||
persistentEntitiesByDiscriminator.put(root, children); |
||||
} |
||||
children.put(entity.getDiscriminator(), entity); |
||||
} |
||||
for (Listener eventListener : eventListeners) { |
||||
eventListener.persistentEntityAdded(entity); |
||||
} |
||||
return entity; |
||||
} |
||||
|
||||
public PersistentEntity getChildEntityByDiscriminator(PersistentEntity root, String discriminator) { |
||||
final Map<String, PersistentEntity> children = persistentEntitiesByDiscriminator.get(root); |
||||
if (children != null) { |
||||
return children.get(discriminator); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
protected abstract PersistentEntity createPersistentEntity(Class javaClass); |
||||
|
||||
public Collection<PersistentEntity> getPersistentEntities() { |
||||
return persistentEntities; |
||||
} |
||||
|
||||
public boolean isPersistentEntity(Class type) { |
||||
return type != null && getPersistentEntity(type.getName()) != null; |
||||
|
||||
} |
||||
|
||||
public boolean isPersistentEntity(Object value) { |
||||
return value != null && isPersistentEntity(value.getClass()); |
||||
} |
||||
|
||||
public PersistentEntity getPersistentEntity(String name) { |
||||
final int proxyIndicator = name.indexOf("_$$_"); |
||||
if (proxyIndicator > -1) { |
||||
name = name.substring(0, proxyIndicator); |
||||
} |
||||
|
||||
return persistentEntitiesByName.get(name); |
||||
} |
||||
} |
||||
@ -1,193 +0,0 @@
@@ -1,193 +0,0 @@
|
||||
/* 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.BeanUtils; |
||||
import org.springframework.data.mapping.model.types.Association; |
||||
import org.springframework.data.mapping.model.types.OneToMany; |
||||
|
||||
import java.beans.Introspector; |
||||
import java.beans.PropertyDescriptor; |
||||
import java.lang.reflect.Modifier; |
||||
import java.util.*; |
||||
|
||||
/** |
||||
* Abstract implementation to be subclasses on a per datastore basis |
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public abstract class AbstractPersistentEntity<T> implements PersistentEntity<T> { |
||||
|
||||
protected Class<T> javaClass; |
||||
protected List<PersistentProperty> persistentProperties; |
||||
protected List<Association> associations; |
||||
protected Map<String, PersistentProperty> propertiesByName = new HashMap<String, PersistentProperty>(); |
||||
protected MappingContext context; |
||||
protected PersistentProperty identity; |
||||
protected List<String> persistentPropertyNames; |
||||
private String decapitalizedName; |
||||
protected Set owners; |
||||
private PersistentEntity parentEntity = null; |
||||
private boolean external; |
||||
|
||||
public AbstractPersistentEntity(Class<T> javaClass, MappingContext context) { |
||||
if (javaClass == null) throw new IllegalArgumentException("The argument [javaClass] cannot be null"); |
||||
this.javaClass = javaClass; |
||||
this.context = context; |
||||
this.decapitalizedName = Introspector.decapitalize(javaClass.getSimpleName()); |
||||
} |
||||
|
||||
public boolean isExternal() { |
||||
return external; |
||||
} |
||||
|
||||
|
||||
public void setExternal(boolean external) { |
||||
this.external = external; |
||||
} |
||||
|
||||
public MappingContext getMappingContext() { |
||||
return this.context; |
||||
} |
||||
|
||||
public void afterPropertiesSet() throws Exception { |
||||
this.identity = context.getMappingSyntaxStrategy().getIdentity(javaClass, context); |
||||
this.owners = context.getMappingSyntaxStrategy().getOwningEntities(javaClass, context); |
||||
this.persistentProperties = context.getMappingSyntaxStrategy().getPersistentProperties(javaClass, context); |
||||
persistentPropertyNames = new ArrayList<String>(); |
||||
associations = new ArrayList(); |
||||
for (PersistentProperty persistentProperty : persistentProperties) { |
||||
if (!(persistentProperty instanceof OneToMany)) |
||||
persistentPropertyNames.add(persistentProperty.getName()); |
||||
if (persistentProperty instanceof Association) { |
||||
associations.add((Association) persistentProperty); |
||||
} |
||||
} |
||||
for (PersistentProperty persistentProperty : persistentProperties) { |
||||
propertiesByName.put(persistentProperty.getName(), persistentProperty); |
||||
} |
||||
|
||||
Class<?> superClass = javaClass.getSuperclass(); |
||||
if (superClass != null |
||||
&& !superClass.equals(Object.class) |
||||
&& !Modifier.isAbstract(superClass.getModifiers())) { |
||||
this.parentEntity = context.addPersistentEntity(superClass); |
||||
} |
||||
|
||||
|
||||
getMapping().getMappedForm(); // initialize mapping
|
||||
} |
||||
|
||||
public boolean hasProperty(String name, Class type) { |
||||
final PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(getJavaClass(), name); |
||||
return pd != null && pd.getPropertyType().equals(type); |
||||
} |
||||
|
||||
public boolean isIdentityName(String propertyName) { |
||||
return getIdentity().getName().equals(propertyName); |
||||
} |
||||
|
||||
public PersistentEntity getParentEntity() { |
||||
return parentEntity; |
||||
} |
||||
|
||||
public String getDiscriminator() { |
||||
return getJavaClass().getSimpleName(); |
||||
} |
||||
|
||||
public PersistentEntity getRootEntity() { |
||||
PersistentEntity root = this; |
||||
PersistentEntity parent = getParentEntity(); |
||||
while (parent != null) { |
||||
root = parent; |
||||
parent = parent.getParentEntity(); |
||||
} |
||||
return root; |
||||
} |
||||
|
||||
public boolean isRoot() { |
||||
return getParentEntity() == null; |
||||
} |
||||
|
||||
public boolean isOwningEntity(PersistentEntity owner) { |
||||
return owner != null && owners.contains(owner.getJavaClass()); |
||||
} |
||||
|
||||
public String getDecapitalizedName() { |
||||
return this.decapitalizedName; |
||||
} |
||||
|
||||
public List<String> getPersistentPropertyNames() { |
||||
return this.persistentPropertyNames; |
||||
} |
||||
|
||||
public T newInstance() { |
||||
try { |
||||
return getJavaClass().newInstance(); |
||||
} catch (InstantiationException e) { |
||||
throw new MappingInstantiationException("Unable to create entity of type [" + getJavaClass() + "]: " + e.getMessage(), e); |
||||
} catch (IllegalAccessException e) { |
||||
throw new MappingInstantiationException("Unable to create entity of type [" + getJavaClass() + "]: " + e.getMessage(), e); |
||||
} |
||||
} |
||||
|
||||
public String getName() { |
||||
return javaClass.getName(); |
||||
} |
||||
|
||||
public PersistentProperty getIdentity() { |
||||
return this.identity; |
||||
} |
||||
|
||||
public Class<T> getJavaClass() { |
||||
return this.javaClass; |
||||
} |
||||
|
||||
public boolean isInstance(Object obj) { |
||||
return getJavaClass().isInstance(obj); |
||||
} |
||||
|
||||
public List<PersistentProperty> getPersistentProperties() { |
||||
return persistentProperties; |
||||
} |
||||
|
||||
public List<Association> getAssociations() { |
||||
return associations; |
||||
} |
||||
|
||||
public PersistentProperty getPropertyByName(String name) { |
||||
return propertiesByName.get(name); |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return javaClass.hashCode(); |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object o) { |
||||
if (o == null || !(o instanceof PersistentEntity)) return false; |
||||
if (this == o) return true; |
||||
|
||||
PersistentEntity other = (PersistentEntity) o; |
||||
return javaClass.equals(other.getJavaClass()); |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "PersistentEntity[" + javaClass.getName() + "]"; |
||||
} |
||||
} |
||||
@ -1,77 +0,0 @@
@@ -1,77 +0,0 @@
|
||||
/* 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 java.beans.PropertyDescriptor; |
||||
|
||||
/** |
||||
* Abstract implementation of the PersistentProperty interface that |
||||
* uses the PropertyDescriptor instance to establish name and type |
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public abstract class AbstractPersistentProperty implements PersistentProperty { |
||||
protected PersistentEntity owner; |
||||
protected MappingContext context; |
||||
protected String name; |
||||
protected Class type; |
||||
private boolean nullable = false; |
||||
|
||||
public AbstractPersistentProperty(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { |
||||
this.owner = owner; |
||||
this.context = context; |
||||
this.name = descriptor.getName(); |
||||
this.type = descriptor.getPropertyType(); |
||||
} |
||||
|
||||
public AbstractPersistentProperty(PersistentEntity owner, MappingContext context, String name, Class type) { |
||||
this.owner = owner; |
||||
this.context = context; |
||||
this.name = name; |
||||
this.type = type; |
||||
} |
||||
|
||||
|
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
public String getCapitilizedName() { |
||||
String name = getName(); |
||||
return name.substring(0, 1).toUpperCase() + name.substring(1); |
||||
} |
||||
|
||||
public Class getType() { |
||||
return type; |
||||
} |
||||
|
||||
public PersistentEntity getOwner() { |
||||
return owner; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return getName() + ":" + getType().getName(); |
||||
} |
||||
|
||||
public boolean isNullable() { |
||||
return nullable; |
||||
} |
||||
|
||||
public void setNullable(boolean nullable) { |
||||
this.nullable = nullable; |
||||
} |
||||
} |
||||
@ -1,31 +0,0 @@
@@ -1,31 +0,0 @@
|
||||
package org.springframework.data.mapping.model; |
||||
|
||||
/** |
||||
* A class mapping is a mapping between a class and some external |
||||
* form such as a table, column family, or document (depending on the underlying data store) |
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public interface ClassMapping<T> { |
||||
/** |
||||
* Obtains the PersistentEntity for this class mapping |
||||
* |
||||
* @return The PersistentEntity |
||||
*/ |
||||
PersistentEntity getEntity(); |
||||
|
||||
/** |
||||
* Returns the mapped form of the class such as a Table, a Key Space, Document etc. |
||||
* |
||||
* @return The mapped representation |
||||
*/ |
||||
T getMappedForm(); |
||||
|
||||
/** |
||||
* Returns details of the identifier used for this class
|
||||
* |
||||
* @return The Identity |
||||
*/ |
||||
IdentityMapping getIdentifier(); |
||||
} |
||||
@ -1,18 +0,0 @@
@@ -1,18 +0,0 @@
|
||||
package org.springframework.data.mapping.model; |
||||
|
||||
/** |
||||
* Exception thrown when something goes wrong configuring a datastore |
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public class DatastoreConfigurationException extends RuntimeException{ |
||||
|
||||
public DatastoreConfigurationException(String message) { |
||||
super(message); |
||||
} |
||||
|
||||
public DatastoreConfigurationException(String message, Throwable cause) { |
||||
super(message, cause); |
||||
} |
||||
} |
||||
@ -1,31 +0,0 @@
@@ -1,31 +0,0 @@
|
||||
/* 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; |
||||
|
||||
/** |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public interface IdentityMapping extends PropertyMapping{ |
||||
|
||||
/** |
||||
* The identifier property name(s) as an array. Usually there is just one identifier |
||||
* name, however in the case of a composite or natural identifier there |
||||
* may be serveral names |
||||
* |
||||
* @return A String[] of identifier names that make up the key |
||||
*/ |
||||
String[] getIdentifierName(); |
||||
} |
||||
@ -1,32 +0,0 @@
@@ -1,32 +0,0 @@
|
||||
/* 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); |
||||
} |
||||
} |
||||
@ -1,72 +0,0 @@
@@ -1,72 +0,0 @@
|
||||
package org.springframework.data.mapping.model; |
||||
|
||||
import org.springframework.data.document.mongodb.mapping.MappingException; |
||||
|
||||
import java.util.List; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* <p>This interface defines a strategy for reading how |
||||
* persistent properties are defined in a persistent entity.</p> |
||||
* <p/> |
||||
* <p>Subclasses can implement this interface in order to provide |
||||
* a different mechanism for mapping entities such as annotations or XML.</p> |
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public interface MappingConfigurationStrategy { |
||||
|
||||
/** |
||||
* Tests whether the given class is a persistent entity |
||||
* |
||||
* @param javaClass The java class
|
||||
* @return true if it is a persistent entity |
||||
*/ |
||||
<T> boolean isPersistentEntity(Class<T> javaClass); |
||||
|
||||
/** |
||||
* @see #getPersistentProperties(Class, MappingContext, ClassMapping) |
||||
*/ |
||||
<T> List<PersistentProperty> getPersistentProperties(Class<T> javaClass, MappingContext context); |
||||
|
||||
/** |
||||
* Obtains a List of PersistentProperty instances for the given Mapped class
|
||||
* |
||||
* @param javaClass The Java class
|
||||
* @param context The MappingContext instance |
||||
* @param mapping The mapping for this class
|
||||
* @return The PersistentProperty instances |
||||
*/ |
||||
<T> List<PersistentProperty> getPersistentProperties(Class<T> javaClass, MappingContext context, ClassMapping mapping); |
||||
|
||||
/** |
||||
* Obtains the identity of a persistent entity |
||||
* |
||||
* @param javaClass The Java class
|
||||
* @param context The MappingContext |
||||
* @return A PersistentProperty instance |
||||
*/ |
||||
<T> PersistentProperty getIdentity(Class<T> javaClass, MappingContext context); |
||||
|
||||
/** |
||||
* Obtains the default manner in which identifiers are mapped. In GORM |
||||
* this is just using a property called 'id', but in other frameworks this |
||||
* may differ. For example JPA expects an annotated @Id property |
||||
* |
||||
* @param classMapping The ClassMapping instance |
||||
* @return The default identifier mapping |
||||
*/ |
||||
IdentityMapping getDefaultIdentityMapping(ClassMapping classMapping) throws MappingException; |
||||
|
||||
/** |
||||
* Returns a set of entities that "own" the given entity. Ownership |
||||
* dictates default cascade strategies. So if entity A owns entity B |
||||
* then saves, updates and deletes will cascade from A to B |
||||
* |
||||
* @param javaClass The Java class
|
||||
* @param context The MappingContext |
||||
* @return A Set of owning classes |
||||
*/ |
||||
<T> Set getOwningEntities(Class<T> javaClass, MappingContext context); |
||||
} |
||||
@ -1,169 +0,0 @@
@@ -1,169 +0,0 @@
|
||||
/* 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.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; |
||||
|
||||
/** |
||||
* <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 { |
||||
|
||||
|
||||
/** |
||||
* 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); |
||||
|
||||
/** |
||||
* Obtains a child of the given root entity using the given discriminator |
||||
* |
||||
* @param root The root entity |
||||
* @param discriminator The discriminator |
||||
* @return The child entity or null if non exists |
||||
*/ |
||||
PersistentEntity getChildEntityByDiscriminator(PersistentEntity root, String discriminator); |
||||
|
||||
/** |
||||
* Adds a PersistentEntity instance |
||||
* |
||||
* @param javaClass The Java class representing the entity |
||||
* @return The PersistentEntity instance |
||||
*/ |
||||
PersistentEntity addPersistentEntity(Class javaClass); |
||||
|
||||
/** |
||||
* Adds a persistent entity that is not mapped by this MappingContext instance. |
||||
* Used for cross store persistence |
||||
* |
||||
* @param javaClass The Java class
|
||||
* @return The persistent entity |
||||
*/ |
||||
PersistentEntity addExternalPersistentEntity(Class javaClass); |
||||
|
||||
/** |
||||
* 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 |
||||
*/ |
||||
void addTypeConverter(Converter 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 |
||||
*/ |
||||
Validator getEntityValidator(PersistentEntity entity); |
||||
|
||||
/** |
||||
* Returns the syntax reader used to interpret the entity |
||||
* mapping syntax |
||||
* |
||||
* @return The SyntaxReader |
||||
*/ |
||||
MappingConfigurationStrategy getMappingSyntaxStrategy(); |
||||
|
||||
/** |
||||
* Obtains the MappingFactory instance |
||||
* |
||||
* @return The mapping factory instance |
||||
*/ |
||||
MappingFactory getMappingFactory(); |
||||
|
||||
/** |
||||
* Returns whether the specified class is a persistent entity |
||||
* |
||||
* @param type The type to check |
||||
* @return True if it is |
||||
*/ |
||||
boolean isPersistentEntity(Class<?> type); |
||||
|
||||
/** |
||||
* Returns whether the specified value is a persistent entity |
||||
* |
||||
* @param value The value to check |
||||
* @return True if it is |
||||
*/ |
||||
boolean isPersistentEntity(Object value); |
||||
|
||||
/** |
||||
* Adds a new mapping context listener instance |
||||
* |
||||
* @param listener The listener |
||||
*/ |
||||
void addMappingContextListener(Listener listener); |
||||
|
||||
/** |
||||
* Implementors can register for events when the mapping context changes |
||||
*/ |
||||
public static interface Listener { |
||||
|
||||
/** |
||||
* Fired when a new entity is added |
||||
* |
||||
* @param entity The entity |
||||
*/ |
||||
void persistentEntityAdded(PersistentEntity entity); |
||||
} |
||||
} |
||||
@ -1,278 +0,0 @@
@@ -1,278 +0,0 @@
|
||||
/* 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.data.mapping.model.types.*; |
||||
|
||||
import java.beans.PropertyDescriptor; |
||||
import java.io.Serializable; |
||||
import java.math.BigDecimal; |
||||
import java.math.BigInteger; |
||||
import java.net.URI; |
||||
import java.net.URL; |
||||
import java.sql.Blob; |
||||
import java.sql.Clob; |
||||
import java.sql.Time; |
||||
import java.sql.Timestamp; |
||||
import java.util.*; |
||||
|
||||
/** |
||||
* <p>An abstract factory for creating persistent property instances.</p> |
||||
* <p/> |
||||
* <p>Subclasses should implement the createMappedForm method in order to |
||||
* provide a mechanisms for representing the property in a form appropriate |
||||
* for mapping to the underlying datastore. Example:</p> |
||||
* <p/> |
||||
* <pre> |
||||
* <code> |
||||
* class RelationalPropertyFactory<Column> extends PropertyFactory { |
||||
* public Column createMappedForm(PersistentProperty mpp) { |
||||
* return new Column(mpp) |
||||
* } |
||||
* } |
||||
* </code> |
||||
* </pre> |
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public abstract class MappingFactory<R, T> { |
||||
public static final Set<String> SIMPLE_TYPES; |
||||
|
||||
static { |
||||
Set<String> basics = new HashSet<String>(); |
||||
basics.add(boolean.class.getName()); |
||||
basics.add(long.class.getName()); |
||||
basics.add(short.class.getName()); |
||||
basics.add(int.class.getName()); |
||||
basics.add(byte.class.getName()); |
||||
basics.add(float.class.getName()); |
||||
basics.add(double.class.getName()); |
||||
basics.add(char.class.getName()); |
||||
basics.add(Boolean.class.getName()); |
||||
basics.add(Long.class.getName()); |
||||
basics.add(Short.class.getName()); |
||||
basics.add(Integer.class.getName()); |
||||
basics.add(Byte.class.getName()); |
||||
basics.add(Float.class.getName()); |
||||
basics.add(Double.class.getName()); |
||||
basics.add(Character.class.getName()); |
||||
basics.add(String.class.getName()); |
||||
basics.add(java.util.Date.class.getName()); |
||||
basics.add(Time.class.getName()); |
||||
basics.add(Timestamp.class.getName()); |
||||
basics.add(java.sql.Date.class.getName()); |
||||
basics.add(BigDecimal.class.getName()); |
||||
basics.add(BigInteger.class.getName()); |
||||
basics.add(Locale.class.getName()); |
||||
basics.add(Calendar.class.getName()); |
||||
basics.add(GregorianCalendar.class.getName()); |
||||
basics.add(java.util.Currency.class.getName()); |
||||
basics.add(TimeZone.class.getName()); |
||||
basics.add(Object.class.getName()); |
||||
basics.add(Class.class.getName()); |
||||
basics.add(byte[].class.getName()); |
||||
basics.add(Byte[].class.getName()); |
||||
basics.add(char[].class.getName()); |
||||
basics.add(Character[].class.getName()); |
||||
basics.add(Blob.class.getName()); |
||||
basics.add(Clob.class.getName()); |
||||
basics.add(Serializable.class.getName()); |
||||
basics.add(URI.class.getName()); |
||||
basics.add(URL.class.getName()); |
||||
|
||||
SIMPLE_TYPES = Collections.unmodifiableSet(basics); |
||||
} |
||||
|
||||
|
||||
public MappingFactory() { |
||||
super(); |
||||
} |
||||
|
||||
public static boolean isSimpleType(Class propType) { |
||||
if (propType == null) return false; |
||||
if (propType.isArray()) { |
||||
return isSimpleType(propType.getComponentType()); |
||||
} |
||||
final String typeName = propType.getName(); |
||||
return isSimpleType(typeName); |
||||
} |
||||
|
||||
public static boolean isSimpleType(final String typeName) { |
||||
return SIMPLE_TYPES.contains(typeName); |
||||
} |
||||
|
||||
/** |
||||
* Creates the mapped form of a persistent entity |
||||
* |
||||
* @param entity The entity |
||||
* @return The mapped form |
||||
*/ |
||||
public abstract R createMappedForm(PersistentEntity entity); |
||||
|
||||
/** |
||||
* Creates the mapped form of a PersistentProperty instance |
||||
* |
||||
* @param mpp The PersistentProperty instance |
||||
* @return The mapped form |
||||
*/ |
||||
public abstract T createMappedForm(PersistentProperty mpp); |
||||
|
||||
/** |
||||
* Creates an identifier property |
||||
* |
||||
* @param owner The owner |
||||
* @param context The context |
||||
* @param pd The PropertyDescriptor |
||||
* @return An Identity instance |
||||
*/ |
||||
public Identity<T> createIdentity(PersistentEntity owner, MappingContext context, PropertyDescriptor pd) { |
||||
return new Identity<T>(owner, context, pd) { |
||||
public PropertyMapping<T> getMapping() { |
||||
return createPropertyMapping(this, owner); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* Creates a simple property type used for mapping basic types such as String, long, integer etc. |
||||
* |
||||
* @param owner The owner |
||||
* @param context The MappingContext |
||||
* @param pd The PropertyDescriptor |
||||
* @return A Simple property type |
||||
*/ |
||||
public Simple<T> createSimple(PersistentEntity owner, MappingContext context, PropertyDescriptor pd) { |
||||
return new Simple<T>(owner, context, pd) { |
||||
public PropertyMapping<T> getMapping() { |
||||
return createPropertyMapping(this, owner); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
protected PropertyMapping<T> createPropertyMapping(final PersistentProperty<T> property, final PersistentEntity owner) { |
||||
return new PropertyMapping<T>() { |
||||
public ClassMapping getClassMapping() { |
||||
return owner.getMapping(); |
||||
} |
||||
|
||||
public T getMappedForm() { |
||||
return createMappedForm(property); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* Creates a one-to-one association type used for mapping a one-to-one association between entities |
||||
* |
||||
* @param entity The entity |
||||
* @param context The context |
||||
* @param property The property |
||||
* @return The ToOne instance |
||||
*/ |
||||
public ToOne createOneToOne(PersistentEntity entity, MappingContext context, PropertyDescriptor property) { |
||||
return new OneToOne<T>(entity, context, property) { |
||||
public PropertyMapping getMapping() { |
||||
return createPropertyMapping(this, owner); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* Creates a many-to-one association type used for a mapping a many-to-one association between entities |
||||
* |
||||
* @param entity The entity |
||||
* @param context The context |
||||
* @param property The property |
||||
* @return The ToOne instance |
||||
*/ |
||||
public ToOne createManyToOne(PersistentEntity entity, MappingContext context, PropertyDescriptor property) { |
||||
return new ManyToOne<T>(entity, context, property) { |
||||
public PropertyMapping getMapping() { |
||||
return createPropertyMapping(this, owner); |
||||
} |
||||
}; |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Creates a {@link OneToMany} type used to model a one-to-many association between entities |
||||
* |
||||
* @param entity The entity |
||||
* @param context The context |
||||
* @param property The property |
||||
* @return The {@link OneToMany} instance |
||||
*/ |
||||
public OneToMany createOneToMany(PersistentEntity entity, MappingContext context, PropertyDescriptor property) { |
||||
return new OneToMany<T>(entity, context, property) { |
||||
public PropertyMapping getMapping() { |
||||
return createPropertyMapping(this, owner); |
||||
} |
||||
}; |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Creates a {@link ManyToMany} type used to model a many-to-many association between entities |
||||
* |
||||
* @param entity The entity |
||||
* @param context The context |
||||
* @param property The property |
||||
* @return The {@link ManyToMany} instance |
||||
*/ |
||||
public ManyToMany createManyToMany(PersistentEntity entity, MappingContext context, PropertyDescriptor property) { |
||||
return new ManyToMany<T>(entity, context, property) { |
||||
public PropertyMapping getMapping() { |
||||
return createPropertyMapping(this, owner); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* Creates an {@link Embedded} type used to model an embedded association (composition) |
||||
* |
||||
* @param entity The entity |
||||
* @param context The context |
||||
* @param property The property |
||||
* @return The {@link Embedded} instance |
||||
*/ |
||||
public Embedded createEmbedded(PersistentEntity entity, |
||||
MappingContext context, PropertyDescriptor property) { |
||||
return new Embedded<T>(entity, context, property) { |
||||
public PropertyMapping getMapping() { |
||||
return createPropertyMapping(this, owner); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* Creates a {@link Basic} collection type |
||||
* |
||||
* @param entity The entity |
||||
* @param context The context |
||||
* @param property The property |
||||
* @return The Basic collection type |
||||
*/ |
||||
public Basic createBasicCollection(PersistentEntity entity, |
||||
MappingContext context, PropertyDescriptor property) { |
||||
return new Basic(entity, context, property) { |
||||
public PropertyMapping getMapping() { |
||||
return createPropertyMapping(this, owner); |
||||
} |
||||
|
||||
}; |
||||
} |
||||
} |
||||
|
||||
@ -1,30 +0,0 @@
@@ -1,30 +0,0 @@
|
||||
/* |
||||
* 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); |
||||
} |
||||
} |
||||
@ -1,167 +0,0 @@
@@ -1,167 +0,0 @@
|
||||
package org.springframework.data.mapping.model; |
||||
|
||||
import org.springframework.beans.factory.InitializingBean; |
||||
import org.springframework.data.mapping.model.types.Association; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 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(); |
||||
|
||||
/** |
||||
* Whether this PersistentEntity is mapped using a different store. Used for cross store persistence |
||||
* |
||||
* @return True if this entity is externally mapped |
||||
*/ |
||||
boolean isExternal(); |
||||
|
||||
/** |
||||
* Whether this PersistentEntity is mapped using a different store. Used for cross store persistence |
||||
* |
||||
* @return True if this entity is externally mapped |
||||
*/ |
||||
void setExternal(boolean external); |
||||
|
||||
/** |
||||
* Returns the identity of the instance |
||||
* |
||||
* @return The identity |
||||
*/ |
||||
PersistentProperty getIdentity(); |
||||
|
||||
/** |
||||
* A list of properties to be persisted |
||||
* |
||||
* @return A list of PersistentProperty instances |
||||
*/ |
||||
List<PersistentProperty> getPersistentProperties(); |
||||
|
||||
/** |
||||
* 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 |
||||
*/ |
||||
List<Association> getAssociations(); |
||||
|
||||
/** |
||||
* Obtains a PersistentProperty instance by name |
||||
* |
||||
* @param name The name of the property |
||||
* @return The PersistentProperty or null if it doesn't exist |
||||
*/ |
||||
PersistentProperty getPropertyByName(String name); |
||||
|
||||
/** |
||||
* @return The underlying Java class for this entity |
||||
*/ |
||||
Class<T> getJavaClass(); |
||||
|
||||
/** |
||||
* Tests whether the given instance is an instance of this persistent entity |
||||
* |
||||
* @param obj The object |
||||
* @return True if it is |
||||
*/ |
||||
boolean isInstance(Object obj); |
||||
|
||||
/** |
||||
* Defines the mapping between this persistent entity |
||||
* and an external form |
||||
* |
||||
* @return The ClassMapping instance |
||||
*/ |
||||
<M> ClassMapping<M> getMapping(); |
||||
|
||||
/** |
||||
* Constructs a new instance |
||||
* |
||||
* @return The new instnace |
||||
*/ |
||||
T newInstance(); |
||||
|
||||
/** |
||||
* A list of property names that a persistent |
||||
* |
||||
* @return A List of strings |
||||
*/ |
||||
List<String> getPersistentPropertyNames(); |
||||
|
||||
/** |
||||
* @return Returns the name of the class decapitalized form |
||||
*/ |
||||
String getDecapitalizedName(); |
||||
|
||||
/** |
||||
* Returns whether the specified entity asserts ownership over this |
||||
* entity |
||||
* |
||||
* @param owner The owning entity |
||||
* @return True if it does own this entity |
||||
*/ |
||||
boolean isOwningEntity(PersistentEntity<?> owner); |
||||
|
||||
/** |
||||
* Returns the parent entity of this entity |
||||
* |
||||
* @return The ParentEntity instance |
||||
*/ |
||||
PersistentEntity<?> getParentEntity(); |
||||
|
||||
/** |
||||
* Obtains the root entity of an inheritance hierarchy |
||||
* |
||||
* @return The root entity |
||||
*/ |
||||
PersistentEntity<?> getRootEntity(); |
||||
|
||||
/** |
||||
* Whether this entity is a root entity |
||||
* |
||||
* @return True if it is a root entity |
||||
*/ |
||||
boolean isRoot(); |
||||
|
||||
/** |
||||
* The discriminator used when persisting subclasses of an inheritance hierarchy |
||||
* |
||||
* @return The discriminator |
||||
*/ |
||||
String getDiscriminator(); |
||||
|
||||
/** |
||||
* Obtains the MappingContext where this PersistentEntity is defined |
||||
* |
||||
* @return The MappingContext instance |
||||
*/ |
||||
MappingContext getMappingContext(); |
||||
|
||||
/** |
||||
* Checks whether an entity has a bean property of the given name and type |
||||
* |
||||
* @param name The name |
||||
* @param type The type |
||||
* @return True if it does |
||||
*/ |
||||
boolean hasProperty(String name, Class<?> type); |
||||
|
||||
/** |
||||
* True if the given property is the identifier |
||||
* |
||||
* @param propertyName the property name |
||||
* @return True if it is the identifier |
||||
*/ |
||||
boolean isIdentityName(String propertyName); |
||||
} |
||||
@ -1,51 +0,0 @@
@@ -1,51 +0,0 @@
|
||||
package org.springframework.data.mapping.model; |
||||
|
||||
/** |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public interface PersistentProperty<T> { |
||||
|
||||
/** |
||||
* The name of the property |
||||
* |
||||
* @return The property name |
||||
*/ |
||||
String getName(); |
||||
|
||||
/** |
||||
* The name with the first letter in upper case as per Java bean conventions |
||||
* |
||||
* @return The capitilized name |
||||
*/ |
||||
String getCapitilizedName(); |
||||
|
||||
/** |
||||
* The type of the property |
||||
* |
||||
* @return The property type |
||||
*/ |
||||
Class<T> getType(); |
||||
|
||||
/** |
||||
* Specifies the mapping between this property and an external form |
||||
* such as a column, key/value pair etc. |
||||
* |
||||
* @return The PropertyMapping instance |
||||
*/ |
||||
PropertyMapping<T> getMapping(); |
||||
|
||||
/** |
||||
* Obtains the owner of this persistent property |
||||
* |
||||
* @return The owner |
||||
*/ |
||||
PersistentEntity<?> getOwner(); |
||||
|
||||
/** |
||||
* Whether the property can be set to null |
||||
* |
||||
* @return True if it can |
||||
*/ |
||||
boolean isNullable(); |
||||
} |
||||
@ -1,25 +0,0 @@
@@ -1,25 +0,0 @@
|
||||
package org.springframework.data.mapping.model; |
||||
|
||||
/** |
||||
* A marker interface for a property mapping which specifies |
||||
* what or where a particular property is mapped to |
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public interface PropertyMapping<T> { |
||||
|
||||
/** |
||||
* Retrieves the ClassMapping instance of the owning class
|
||||
* |
||||
* @return The ClassMapping instance |
||||
*/ |
||||
ClassMapping getClassMapping(); |
||||
|
||||
/** |
||||
* Returns the mapped form of the property such as a Column, a Key/Value pair, attribute etc. |
||||
* @return The mapped representation |
||||
*/ |
||||
T getMappedForm(); |
||||
|
||||
} |
||||
@ -1,146 +0,0 @@
@@ -1,146 +0,0 @@
|
||||
/* 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.types; |
||||
|
||||
import org.springframework.data.mapping.model.*; |
||||
|
||||
import javax.persistence.CascadeType; |
||||
import javax.persistence.FetchType; |
||||
import java.beans.PropertyDescriptor; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Models an association between one class and another |
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public abstract class Association<T> extends AbstractPersistentProperty { |
||||
|
||||
public static final List<CascadeType> DEFAULT_OWNER_CASCADE = new ArrayList<CascadeType>() {{ |
||||
add(CascadeType.ALL); |
||||
}}; |
||||
|
||||
public static final List<CascadeType> DEFAULT_CHILD_CASCADE = new ArrayList<CascadeType>() {{ |
||||
add(CascadeType.PERSIST); |
||||
}}; |
||||
|
||||
private PersistentEntity associatedEntity; |
||||
private String referencedPropertyName; |
||||
private boolean owningSide; |
||||
private List<CascadeType> cascadeOperations = new ArrayList<CascadeType>(); |
||||
private FetchType fetchStrategy = FetchType.EAGER; |
||||
|
||||
public Association(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { |
||||
super(owner, context, descriptor); |
||||
} |
||||
|
||||
public Association(PersistentEntity owner, MappingContext context, String name, Class type) { |
||||
super(owner, context, name, type); |
||||
} |
||||
|
||||
public FetchType getFetchStrategy() { |
||||
return fetchStrategy; |
||||
} |
||||
|
||||
public void setFetchStrategy(FetchType fetchStrategy) { |
||||
this.fetchStrategy = fetchStrategy; |
||||
} |
||||
|
||||
public boolean isBidirectional() { |
||||
return getInverseSide() != null; |
||||
} |
||||
|
||||
public Association getInverseSide() { |
||||
final PersistentProperty associatedProperty = associatedEntity.getPropertyByName(referencedPropertyName); |
||||
if(associatedProperty == null) return null; |
||||
if(associatedProperty instanceof Association) { |
||||
return (Association) associatedProperty; |
||||
} |
||||
else { |
||||
throw new IllegalMappingException("The inverse side ["+associatedEntity.getName()+"." + associatedProperty.getName() +"] of the association ["+getOwner().getName()+"." + this.getName() +"] is not valid. Associations can only map to other entities and collection types."); |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Returns true if the this association cascade for the given cascade operation |
||||
* |
||||
* @param cascadeOperation The cascadeOperation |
||||
* @return True if it does |
||||
*/ |
||||
public boolean doesCascade(CascadeType cascadeOperation) { |
||||
List<CascadeType> cascades = getCascadeOperations(); |
||||
return cascadeOperation != null && (cascades.contains(CascadeType.ALL) || cascades.contains(cascadeOperation)); |
||||
} |
||||
|
||||
protected List<CascadeType> getCascadeOperations() { |
||||
List<CascadeType> cascades; |
||||
if(cascadeOperations.isEmpty()) { |
||||
if(isOwningSide()) cascades = DEFAULT_OWNER_CASCADE; |
||||
else { |
||||
cascades = DEFAULT_CHILD_CASCADE; |
||||
} |
||||
} |
||||
else { |
||||
cascades = this.cascadeOperations; |
||||
} |
||||
return cascades; |
||||
} |
||||
|
||||
/** |
||||
* Returns whether this side owns the relationship. This controls |
||||
* the default cascading behavior if none is specified |
||||
* |
||||
* @return True if this property is the owning side |
||||
*/ |
||||
public boolean isOwningSide() { |
||||
return owningSide; |
||||
} |
||||
|
||||
public void setOwningSide(boolean owningSide) { |
||||
this.owningSide = owningSide; |
||||
} |
||||
|
||||
public void setAssociatedEntity(PersistentEntity associatedEntity) { |
||||
this.associatedEntity = associatedEntity; |
||||
} |
||||
|
||||
public PersistentEntity getAssociatedEntity() { |
||||
return associatedEntity; |
||||
} |
||||
|
||||
public void setReferencedPropertyName(String referencedPropertyName) { |
||||
this.referencedPropertyName = referencedPropertyName; |
||||
} |
||||
|
||||
public String getReferencedPropertyName() { |
||||
return referencedPropertyName; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return getOwner().getName() + "->" + getName(); |
||||
} |
||||
|
||||
public boolean isList() { |
||||
return List.class.isAssignableFrom(getType()); |
||||
} |
||||
|
||||
public boolean isCircular() { |
||||
return isBidirectional() && getAssociatedEntity().equals(getOwner()); |
||||
} |
||||
} |
||||
@ -1,65 +0,0 @@
@@ -1,65 +0,0 @@
|
||||
/* Copyright (C) 2011 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.types; |
||||
|
||||
import java.beans.PropertyDescriptor; |
||||
|
||||
import org.springframework.data.mapping.model.MappingContext; |
||||
import org.springframework.data.mapping.model.PersistentEntity; |
||||
import org.springframework.data.mapping.model.PropertyMapping; |
||||
|
||||
/** |
||||
* Models a basic collection type such as a list of Strings |
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
* |
||||
*/ |
||||
public abstract class Basic extends Association { |
||||
|
||||
public Basic(PersistentEntity owner, MappingContext context, |
||||
PropertyDescriptor descriptor) { |
||||
super(owner, context, descriptor); |
||||
} |
||||
|
||||
public Basic(PersistentEntity owner, MappingContext context, String name, Class type) { |
||||
super(owner, context, name, type); |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public Association getInverseSide() { |
||||
return null; // basic collection types have no inverse side
|
||||
} |
||||
|
||||
@Override |
||||
public boolean isOwningSide() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public void setOwningSide(boolean owningSide) { |
||||
// noop
|
||||
} |
||||
|
||||
@Override |
||||
public PersistentEntity getAssociatedEntity() { |
||||
return null; // basic collection types have no associated entity
|
||||
} |
||||
|
||||
|
||||
} |
||||
@ -1,133 +0,0 @@
@@ -1,133 +0,0 @@
|
||||
/* 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.types; |
||||
|
||||
import org.springframework.core.convert.converter.Converter; |
||||
import org.springframework.core.convert.converter.ConverterRegistry; |
||||
|
||||
import java.util.Calendar; |
||||
import java.util.Date; |
||||
import java.util.GregorianCalendar; |
||||
|
||||
/** |
||||
* A registrar that registers basic type converters |
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public class BasicTypeConverterRegistrar { |
||||
|
||||
public void register(ConverterRegistry registry) { |
||||
registry.addConverter(new Converter<Date, String>() { |
||||
public String convert(Date date) { |
||||
return String.valueOf(date.getTime()); |
||||
} |
||||
}); |
||||
registry.addConverter(new Converter<Date, Calendar>() { |
||||
public Calendar convert(Date date) { |
||||
final GregorianCalendar calendar = new GregorianCalendar(); |
||||
calendar.setTime(date); |
||||
return calendar; |
||||
} |
||||
}); |
||||
|
||||
registry.addConverter(new Converter<Integer, Long>() { |
||||
public Long convert(Integer integer) { |
||||
return integer.longValue(); |
||||
} |
||||
}); |
||||
|
||||
registry.addConverter(new Converter<Integer, Double>() { |
||||
public Double convert(Integer integer) { |
||||
return integer.doubleValue(); |
||||
} |
||||
}); |
||||
|
||||
|
||||
registry.addConverter(new Converter<CharSequence, Date>() { |
||||
|
||||
public Date convert(CharSequence s) { |
||||
try { |
||||
final Long time = Long.valueOf(s.toString()); |
||||
return new Date(time); |
||||
} catch (NumberFormatException e) { |
||||
// ignore
|
||||
} |
||||
return null; |
||||
} |
||||
}); |
||||
|
||||
registry.addConverter(new Converter<CharSequence, Double>() { |
||||
|
||||
public Double convert(CharSequence s) { |
||||
try { |
||||
return Double.valueOf(s.toString()); |
||||
} catch (NumberFormatException e) { |
||||
return (double) 0; |
||||
} |
||||
} |
||||
}); |
||||
|
||||
registry.addConverter(new Converter<CharSequence, Integer>() { |
||||
|
||||
public Integer convert(CharSequence s) { |
||||
try { |
||||
return Integer.valueOf(s.toString()); |
||||
} catch (NumberFormatException e) { |
||||
// ignore
|
||||
} |
||||
return 0; |
||||
} |
||||
}); |
||||
registry.addConverter(new Converter<CharSequence, Long>() { |
||||
|
||||
public Long convert(CharSequence s) { |
||||
try { |
||||
return Long.valueOf(s.toString()); |
||||
} catch (NumberFormatException e) { |
||||
// ignore
|
||||
} |
||||
return 0L; |
||||
} |
||||
}); |
||||
|
||||
|
||||
registry.addConverter(new Converter<Object, String>() { |
||||
public String convert(Object o) { |
||||
return o.toString(); |
||||
} |
||||
}); |
||||
|
||||
registry.addConverter(new Converter<Calendar, String>() { |
||||
public String convert(Calendar calendar) { |
||||
return String.valueOf(calendar.getTime().getTime()); |
||||
} |
||||
}); |
||||
|
||||
registry.addConverter(new Converter<CharSequence, Calendar>() { |
||||
|
||||
public Calendar convert(CharSequence s) { |
||||
try { |
||||
Date date = new Date(Long.valueOf(s.toString())); |
||||
Calendar c = new GregorianCalendar(); |
||||
c.setTime(date); |
||||
return c; |
||||
} catch (NumberFormatException e) { |
||||
return null; |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
@ -1,43 +0,0 @@
@@ -1,43 +0,0 @@
|
||||
/* 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.types; |
||||
|
||||
import org.springframework.data.mapping.model.MappingContext; |
||||
import org.springframework.data.mapping.model.PersistentEntity; |
||||
|
||||
import java.beans.PropertyDescriptor; |
||||
|
||||
/** |
||||
* Models an embedded component |
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public abstract class Embedded<T> extends ToOne<T> { |
||||
|
||||
public Embedded(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { |
||||
super(owner, context, descriptor); |
||||
} |
||||
|
||||
public Embedded(PersistentEntity owner, MappingContext context, String name, Class type) { |
||||
super(owner, context, name, type); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isOwningSide() { |
||||
return true; // embedded instances are always owned
|
||||
} |
||||
|
||||
} |
||||
@ -1,36 +0,0 @@
@@ -1,36 +0,0 @@
|
||||
/* 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.types; |
||||
|
||||
import org.springframework.data.mapping.model.AbstractPersistentProperty; |
||||
import org.springframework.data.mapping.model.MappingContext; |
||||
import org.springframework.data.mapping.model.PersistentEntity; |
||||
|
||||
import java.beans.PropertyDescriptor; |
||||
|
||||
/** |
||||
* Represents the identity of a persistent entity |
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public abstract class Identity<T> extends AbstractPersistentProperty { |
||||
public Identity(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { |
||||
super(owner, context, descriptor); |
||||
} |
||||
public Identity(PersistentEntity owner, MappingContext context, String name, Class type) { |
||||
super(owner, context, name, type); |
||||
} |
||||
} |
||||
@ -1,36 +0,0 @@
@@ -1,36 +0,0 @@
|
||||
/* 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.types; |
||||
|
||||
import org.springframework.data.mapping.model.MappingContext; |
||||
import org.springframework.data.mapping.model.PersistentEntity; |
||||
|
||||
import java.beans.PropertyDescriptor; |
||||
|
||||
/** |
||||
* Models a many-to-many association between one class and another |
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public abstract class ManyToMany<T> extends Association<T> { |
||||
public ManyToMany(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { |
||||
super(owner, context, descriptor); |
||||
} |
||||
|
||||
public ManyToMany(PersistentEntity owner, MappingContext context, String name, Class type) { |
||||
super(owner, context, name, type); |
||||
} |
||||
} |
||||
@ -1,37 +0,0 @@
@@ -1,37 +0,0 @@
|
||||
/* 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.types; |
||||
|
||||
import org.springframework.data.mapping.model.MappingContext; |
||||
import org.springframework.data.mapping.model.PersistentEntity; |
||||
|
||||
import java.beans.PropertyDescriptor; |
||||
|
||||
/** |
||||
* Models a many-to-one association |
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public abstract class ManyToOne<T> extends ToOne<T> { |
||||
public ManyToOne(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { |
||||
super(owner, context, descriptor); |
||||
} |
||||
|
||||
public ManyToOne(PersistentEntity owner, MappingContext context, String name, Class type) { |
||||
super(owner, context, name, type); |
||||
} |
||||
|
||||
} |
||||
@ -1,36 +0,0 @@
@@ -1,36 +0,0 @@
|
||||
/* 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.types; |
||||
|
||||
import org.springframework.data.mapping.model.MappingContext; |
||||
import org.springframework.data.mapping.model.PersistentEntity; |
||||
|
||||
import java.beans.PropertyDescriptor; |
||||
|
||||
/** |
||||
* Models a one-to-many association |
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public abstract class OneToMany<T> extends Association<T> { |
||||
public OneToMany(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { |
||||
super(owner, context, descriptor); |
||||
} |
||||
|
||||
public OneToMany(PersistentEntity owner, MappingContext context, String name, Class type) { |
||||
super(owner, context, name, type); |
||||
} |
||||
} |
||||
@ -1,36 +0,0 @@
@@ -1,36 +0,0 @@
|
||||
/* 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.types; |
||||
|
||||
import org.springframework.data.mapping.model.MappingContext; |
||||
import org.springframework.data.mapping.model.PersistentEntity; |
||||
|
||||
import java.beans.PropertyDescriptor; |
||||
|
||||
/** |
||||
* Models a one-to-one association |
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public abstract class OneToOne<T> extends ToOne<T> { |
||||
public OneToOne(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { |
||||
super(owner, context, descriptor); |
||||
} |
||||
|
||||
public OneToOne(PersistentEntity owner, MappingContext context, String name, Class type) { |
||||
super(owner, context, name, type); |
||||
} |
||||
} |
||||
@ -1,37 +0,0 @@
@@ -1,37 +0,0 @@
|
||||
/* 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.types; |
||||
|
||||
import org.springframework.data.mapping.model.AbstractPersistentProperty; |
||||
import org.springframework.data.mapping.model.MappingContext; |
||||
import org.springframework.data.mapping.model.PersistentEntity; |
||||
|
||||
import java.beans.PropertyDescriptor; |
||||
|
||||
/** |
||||
* Models a simple property type |
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public abstract class Simple<T> extends AbstractPersistentProperty { |
||||
public Simple(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { |
||||
super(owner, context, descriptor); |
||||
} |
||||
|
||||
public Simple(PersistentEntity owner, MappingContext context, String name, Class type) { |
||||
super(owner, context, name, type); |
||||
} |
||||
} |
||||
@ -1,47 +0,0 @@
@@ -1,47 +0,0 @@
|
||||
/* 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.types; |
||||
|
||||
import org.springframework.data.mapping.model.MappingContext; |
||||
import org.springframework.data.mapping.model.PersistentEntity; |
||||
|
||||
import java.beans.PropertyDescriptor; |
||||
|
||||
/** |
||||
* @author Graeme Rocher |
||||
* @since 1.1 |
||||
*/ |
||||
public abstract class ToOne<T> extends Association<T> { |
||||
|
||||
private boolean foreignKeyInChild; |
||||
|
||||
public ToOne(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { |
||||
super(owner, context, descriptor); |
||||
} |
||||
|
||||
public ToOne(PersistentEntity owner, MappingContext context, String name, Class type) { |
||||
super(owner, context, name, type); |
||||
} |
||||
|
||||
public void setForeignKeyInChild(boolean foreignKeyInChild) { |
||||
this.foreignKeyInChild = foreignKeyInChild; |
||||
} |
||||
|
||||
public boolean isForeignKeyInChild() { |
||||
return foreignKeyInChild; |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -1,372 +0,0 @@
@@ -1,372 +0,0 @@
|
||||
/* 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.reflect; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import org.springframework.data.mapping.annotation.PersistenceConstructor; |
||||
|
||||
import java.beans.IntrospectionException; |
||||
import java.beans.Introspector; |
||||
import java.beans.PropertyDescriptor; |
||||
import java.lang.reflect.*; |
||||
import java.util.*; |
||||
|
||||
/** |
||||
* Reads the properties of a class in an optimized manner avoiding |
||||
* exceptions |
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public class ClassPropertyFetcher { |
||||
|
||||
private static final Log log = LogFactory.getLog(ClassPropertyFetcher.class); |
||||
|
||||
private final Class clazz; |
||||
final Map<String, PropertyFetcher> staticFetchers = new HashMap<String, PropertyFetcher>(); |
||||
final Map<String, PropertyFetcher> instanceFetchers = new HashMap<String, PropertyFetcher>(); |
||||
private final ReferenceInstanceCallback callback; |
||||
private PropertyDescriptor[] propertyDescriptors; |
||||
private Constructor preferredConstructor; |
||||
private Map<String, PropertyDescriptor> propertyDescriptorsByName = new HashMap<String, PropertyDescriptor>(); |
||||
private Map<String, Field> fieldsByName = new HashMap<String, Field>(); |
||||
private Map<Class, List<PropertyDescriptor>> typeToPropertyMap = new HashMap<Class, List<PropertyDescriptor>>(); |
||||
|
||||
private static Map<Class, ClassPropertyFetcher> cachedClassPropertyFetchers = new WeakHashMap<Class, ClassPropertyFetcher>(); |
||||
|
||||
public static ClassPropertyFetcher forClass(final Class c) { |
||||
ClassPropertyFetcher cpf = cachedClassPropertyFetchers.get(c); |
||||
if (cpf == null) { |
||||
cpf = new ClassPropertyFetcher(c); |
||||
cachedClassPropertyFetchers.put(c, cpf); |
||||
} |
||||
return cpf; |
||||
} |
||||
|
||||
ClassPropertyFetcher(final Class clazz) { |
||||
this.clazz = clazz; |
||||
this.callback = new ReferenceInstanceCallback() { |
||||
public Object getReferenceInstance() { |
||||
try { |
||||
return ReflectionUtils.instantiate(clazz); |
||||
} catch (InstantiationException e) { |
||||
throw new IllegalStateException(e); |
||||
} |
||||
} |
||||
}; |
||||
init(); |
||||
} |
||||
|
||||
/** |
||||
* @return The Java that this ClassPropertyFetcher was constructor for |
||||
*/ |
||||
public Class getJavaClass() { |
||||
return this.clazz; |
||||
} |
||||
|
||||
public Object getReference() { |
||||
if (callback != null) |
||||
return this.callback.getReferenceInstance(); |
||||
return null; |
||||
} |
||||
|
||||
public PropertyDescriptor[] getPropertyDescriptors() { |
||||
return propertyDescriptors; |
||||
} |
||||
|
||||
public boolean isReadableProperty(String name) { |
||||
return staticFetchers.containsKey(name) || instanceFetchers.containsKey(name); |
||||
} |
||||
|
||||
private void init() { |
||||
|
||||
List<Class> allClasses = resolveAllClasses(clazz); |
||||
for (Class c : allClasses) { |
||||
Field[] fields = c.getDeclaredFields(); |
||||
for (Field field : fields) { |
||||
processField(field); |
||||
} |
||||
Method[] methods = c.getDeclaredMethods(); |
||||
for (Method method : methods) { |
||||
processMethod(method); |
||||
} |
||||
} |
||||
|
||||
try { |
||||
this.propertyDescriptors = Introspector.getBeanInfo(clazz).getPropertyDescriptors(); |
||||
} catch (IntrospectionException e) { |
||||
// ignore
|
||||
} |
||||
if (propertyDescriptors != null) { |
||||
for (PropertyDescriptor desc : propertyDescriptors) { |
||||
propertyDescriptorsByName.put(desc.getName(), desc); |
||||
final Class<?> propertyType = desc.getPropertyType(); |
||||
List<PropertyDescriptor> pds = typeToPropertyMap.get(propertyType); |
||||
if (pds == null) { |
||||
pds = new ArrayList<PropertyDescriptor>(); |
||||
typeToPropertyMap.put(propertyType, pds); |
||||
} |
||||
pds.add(desc); |
||||
|
||||
Method readMethod = desc.getReadMethod(); |
||||
if (readMethod != null) { |
||||
boolean staticReadMethod = Modifier.isStatic(readMethod.getModifiers()); |
||||
if (staticReadMethod) { |
||||
staticFetchers.put(desc.getName(), new GetterPropertyFetcher(readMethod, staticReadMethod)); |
||||
} else { |
||||
instanceFetchers.put(desc.getName(), new GetterPropertyFetcher(readMethod, staticReadMethod)); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
Constructor[] constructors = clazz.getConstructors(); |
||||
if (constructors.length == 1 && constructors[0].getGenericParameterTypes().length > 0) { |
||||
preferredConstructor = constructors[0]; |
||||
} else { |
||||
for (Constructor<?> c : constructors) { |
||||
if (c.isAnnotationPresent(PersistenceConstructor.class)) { |
||||
preferredConstructor = c; |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
public <T> Constructor<T> getPreferredConstructor() { |
||||
return preferredConstructor; |
||||
} |
||||
|
||||
private void processMethod(Method method) { |
||||
if (method.isSynthetic()) |
||||
return; |
||||
if (!Modifier.isPublic(method.getModifiers())) |
||||
return; |
||||
if (Modifier.isStatic(method.getModifiers()) |
||||
&& method.getReturnType() != Void.class) { |
||||
if (method.getParameterTypes().length == 0) { |
||||
String name = method.getName(); |
||||
if (name.indexOf('$') == -1) { |
||||
if (name.length() > 3 && name.startsWith("get") && Character.isUpperCase(name.charAt(3))) { |
||||
name = name.substring(3); |
||||
} else if (name.length() > 2 |
||||
&& name.startsWith("is") |
||||
&& Character.isUpperCase(name.charAt(2)) |
||||
&& (method.getReturnType() == Boolean.class || method.getReturnType() == boolean.class)) { |
||||
name = name.substring(2); |
||||
} |
||||
PropertyFetcher fetcher = new GetterPropertyFetcher(method, true); |
||||
staticFetchers.put(name, fetcher); |
||||
staticFetchers.put(Introspector.decapitalize(name), fetcher); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void processField(Field field) { |
||||
if (field.isSynthetic()) |
||||
return; |
||||
final int modifiers = field.getModifiers(); |
||||
final String name = field.getName(); |
||||
if (!Modifier.isPublic(modifiers)) { |
||||
if (name.indexOf('$') == -1) { |
||||
fieldsByName.put(name, field); |
||||
} |
||||
} else { |
||||
if (name.indexOf('$') == -1) { |
||||
boolean staticField = Modifier.isStatic(modifiers); |
||||
if (staticField) { |
||||
staticFetchers.put(name, new FieldReaderFetcher(field, staticField)); |
||||
} else { |
||||
instanceFetchers.put(name, new FieldReaderFetcher(field, staticField)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
private List<Class> resolveAllClasses(Class c) { |
||||
List<Class> list = new ArrayList<Class>(); |
||||
Class currentClass = c; |
||||
while (currentClass != null) { |
||||
list.add(currentClass); |
||||
currentClass = currentClass.getSuperclass(); |
||||
} |
||||
Collections.reverse(list); |
||||
return list; |
||||
} |
||||
|
||||
public Object getPropertyValue(String name) { |
||||
return getPropertyValue(name, false); |
||||
} |
||||
|
||||
public Object getPropertyValue(String name, boolean onlyInstanceProperties) { |
||||
PropertyFetcher fetcher = resolveFetcher(name, onlyInstanceProperties); |
||||
return getPropertyValueWithFetcher(name, fetcher); |
||||
} |
||||
|
||||
private Object getPropertyValueWithFetcher(String name, PropertyFetcher fetcher) { |
||||
if (fetcher != null) { |
||||
try { |
||||
return fetcher.get(callback); |
||||
} catch (Exception e) { |
||||
log.warn("Error fetching property's " + name + " value from class " + clazz.getName(), e); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public <T> T getStaticPropertyValue(String name, Class<T> c) { |
||||
PropertyFetcher fetcher = staticFetchers.get(name); |
||||
if (fetcher != null) { |
||||
Object v = getPropertyValueWithFetcher(name, fetcher); |
||||
return returnOnlyIfInstanceOf(v, c); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public <T> T getPropertyValue(String name, Class<T> c) { |
||||
return returnOnlyIfInstanceOf(getPropertyValue(name, false), c); |
||||
} |
||||
|
||||
private <T> T returnOnlyIfInstanceOf(Object value, Class<T> type) { |
||||
if ((value != null) && (type == Object.class || ReflectionUtils.isAssignableFrom(type, value.getClass()))) { |
||||
return (T) value; |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
|
||||
private PropertyFetcher resolveFetcher(String name, |
||||
boolean onlyInstanceProperties) { |
||||
PropertyFetcher fetcher = null; |
||||
if (!onlyInstanceProperties) { |
||||
fetcher = staticFetchers.get(name); |
||||
} |
||||
if (fetcher == null) { |
||||
fetcher = instanceFetchers.get(name); |
||||
} |
||||
return fetcher; |
||||
} |
||||
|
||||
public Class getPropertyType(String name) { |
||||
return getPropertyType(name, false); |
||||
} |
||||
|
||||
public Class getPropertyType(String name, boolean onlyInstanceProperties) { |
||||
PropertyFetcher fetcher = resolveFetcher(name, onlyInstanceProperties); |
||||
if (fetcher != null) { |
||||
return fetcher.getPropertyType(name); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public PropertyDescriptor getPropertyDescriptor(String name) { |
||||
return propertyDescriptorsByName.get(name); |
||||
} |
||||
|
||||
public List<PropertyDescriptor> getPropertiesOfType(Class javaClass) { |
||||
final List<PropertyDescriptor> propertyDescriptorList = typeToPropertyMap.get(javaClass); |
||||
if (propertyDescriptorList == null) return Collections.emptyList(); |
||||
return propertyDescriptorList; |
||||
} |
||||
|
||||
public List<PropertyDescriptor> getPropertiesAssignableToType(Class assignableType) { |
||||
List<PropertyDescriptor> properties = new ArrayList<PropertyDescriptor>(); |
||||
for (Class type : typeToPropertyMap.keySet()) { |
||||
if (assignableType.isAssignableFrom(type)) { |
||||
properties.addAll(typeToPropertyMap.get(type)); |
||||
} |
||||
} |
||||
return properties; |
||||
} |
||||
|
||||
public static interface ReferenceInstanceCallback { |
||||
public Object getReferenceInstance(); |
||||
} |
||||
|
||||
static interface PropertyFetcher { |
||||
public Object get(ReferenceInstanceCallback callback) |
||||
throws IllegalArgumentException, IllegalAccessException, |
||||
InvocationTargetException; |
||||
|
||||
public Class getPropertyType(String name); |
||||
} |
||||
|
||||
static class GetterPropertyFetcher implements PropertyFetcher { |
||||
private final Method readMethod; |
||||
private final boolean staticMethod; |
||||
|
||||
GetterPropertyFetcher(Method readMethod, boolean staticMethod) { |
||||
this.readMethod = readMethod; |
||||
this.staticMethod = staticMethod; |
||||
ReflectionUtils.makeAccessible(readMethod); |
||||
} |
||||
|
||||
public Object get(ReferenceInstanceCallback callback) |
||||
throws IllegalArgumentException, IllegalAccessException, |
||||
InvocationTargetException { |
||||
if (staticMethod) { |
||||
return readMethod.invoke(null, (Object[]) null); |
||||
} else { |
||||
if (callback != null) { |
||||
return readMethod.invoke(callback.getReferenceInstance(), |
||||
(Object[]) null); |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public Class getPropertyType(String name) { |
||||
return readMethod.getReturnType(); |
||||
} |
||||
} |
||||
|
||||
static class FieldReaderFetcher implements PropertyFetcher { |
||||
private final Field field; |
||||
private final boolean staticField; |
||||
|
||||
public FieldReaderFetcher(Field field, boolean staticField) { |
||||
this.field = field; |
||||
this.staticField = staticField; |
||||
ReflectionUtils.makeAccessible(field); |
||||
} |
||||
|
||||
public Object get(ReferenceInstanceCallback callback) |
||||
throws IllegalArgumentException, IllegalAccessException, |
||||
InvocationTargetException { |
||||
if (staticField) { |
||||
return field.get(null); |
||||
} else { |
||||
if (callback != null) { |
||||
return field.get(callback.getReferenceInstance()); |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public Class getPropertyType(String name) { |
||||
return field.getType(); |
||||
} |
||||
} |
||||
|
||||
public Field getDeclaredField(String name) { |
||||
return fieldsByName.get(name); |
||||
} |
||||
} |
||||
@ -1,209 +0,0 @@
@@ -1,209 +0,0 @@
|
||||
/* 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.reflect; |
||||
|
||||
import org.springframework.beans.BeanUtils; |
||||
|
||||
import java.beans.PropertyDescriptor; |
||||
import java.lang.Boolean; |
||||
import java.lang.Byte; |
||||
import java.lang.Character; |
||||
import java.lang.Class; |
||||
import java.lang.Double; |
||||
import java.lang.Exception; |
||||
import java.lang.Float; |
||||
import java.lang.IllegalAccessException; |
||||
import java.lang.InstantiationException; |
||||
import java.lang.Integer; |
||||
import java.lang.Long; |
||||
import java.lang.NoSuchMethodException; |
||||
import java.lang.NullPointerException; |
||||
import java.lang.Object; |
||||
import java.lang.Short; |
||||
import java.lang.reflect.Field; |
||||
import java.lang.reflect.InvocationTargetException; |
||||
import java.lang.reflect.Method; |
||||
import java.lang.reflect.Modifier; |
||||
import java.util.HashMap; |
||||
import java.util.HashSet; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* Provides methods to help with reflective operations |
||||
* |
||||
* @author Graeme Rocher |
||||
* @since 1.0 |
||||
*/ |
||||
public class ReflectionUtils { |
||||
|
||||
public static final Map<Class<?>, Class<?>> PRIMITIVE_TYPE_COMPATIBLE_CLASSES = new HashMap<Class<?>, Class<?>>(); |
||||
private static final Class[] EMPTY_CLASS_ARRAY = new Class[0]; |
||||
|
||||
/** |
||||
* Just add two entries to the class compatibility map |
||||
* |
||||
* @param left |
||||
* @param right |
||||
*/ |
||||
private static void registerPrimitiveClassPair(Class<?> left, Class<?> right) { |
||||
PRIMITIVE_TYPE_COMPATIBLE_CLASSES.put(left, right); |
||||
PRIMITIVE_TYPE_COMPATIBLE_CLASSES.put(right, left); |
||||
} |
||||
|
||||
static { |
||||
registerPrimitiveClassPair(Boolean.class, boolean.class); |
||||
registerPrimitiveClassPair(Integer.class, int.class); |
||||
registerPrimitiveClassPair(Short.class, short.class); |
||||
registerPrimitiveClassPair(Byte.class, byte.class); |
||||
registerPrimitiveClassPair(Character.class, char.class); |
||||
registerPrimitiveClassPair(Long.class, long.class); |
||||
registerPrimitiveClassPair(Float.class, float.class); |
||||
registerPrimitiveClassPair(Double.class, double.class); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Make the given field accessible, explicitly setting it accessible if necessary. |
||||
* The <code>setAccessible(true)</code> method is only called when actually necessary, |
||||
* to avoid unnecessary conflicts with a JVM SecurityManager (if active). |
||||
* <p/> |
||||
* Based on the same method in Spring core. |
||||
* |
||||
* @param field the field to make accessible |
||||
* @see java.lang.reflect.Field#setAccessible |
||||
*/ |
||||
public static void makeAccessible(Field field) { |
||||
if (!Modifier.isPublic(field.getModifiers()) || |
||||
!Modifier.isPublic(field.getDeclaringClass().getModifiers())) { |
||||
field.setAccessible(true); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Make the given method accessible, explicitly setting it accessible if necessary. |
||||
* The <code>setAccessible(true)</code> method is only called when actually necessary, |
||||
* to avoid unnecessary conflicts with a JVM SecurityManager (if active). |
||||
* <p/> |
||||
* Based on the same method in Spring core. |
||||
* |
||||
* @param method the method to make accessible |
||||
* @see java.lang.reflect.Method#setAccessible |
||||
*/ |
||||
public static void makeAccessible(Method method) { |
||||
if (!Modifier.isPublic(method.getModifiers()) || |
||||
!Modifier.isPublic(method.getDeclaringClass().getModifiers())) { |
||||
method.setAccessible(true); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* <p>Tests whether or not the left hand type is compatible with the right hand type in Groovy |
||||
* terms, i.e. can the left type be assigned a value of the right hand type in Groovy.</p> |
||||
* <p>This handles Java primitive type equivalence and uses isAssignableFrom for all other types, |
||||
* with a bit of magic for native types and polymorphism i.e. Number assigned an int. |
||||
* If either parameter is null an exception is thrown</p> |
||||
* |
||||
* @param leftType The type of the left hand part of a notional assignment |
||||
* @param rightType The type of the right hand part of a notional assignment |
||||
* @return True if values of the right hand type can be assigned in Groovy to variables of the left hand type. |
||||
*/ |
||||
public static boolean isAssignableFrom(final Class<?> leftType, final Class<?> rightType) { |
||||
if (leftType == null) { |
||||
throw new NullPointerException("Left type is null!"); |
||||
} |
||||
if (rightType == null) { |
||||
throw new NullPointerException("Right type is null!"); |
||||
} |
||||
if (leftType == Object.class) { |
||||
return true; |
||||
} |
||||
if (leftType == rightType) { |
||||
return true; |
||||
} |
||||
// check for primitive type equivalence
|
||||
Class<?> r = PRIMITIVE_TYPE_COMPATIBLE_CLASSES.get(leftType); |
||||
boolean result = r == rightType; |
||||
|
||||
if (!result) { |
||||
// If no primitive <-> wrapper match, it may still be assignable
|
||||
// from polymorphic primitives i.e. Number -> int (AKA Integer)
|
||||
if (rightType.isPrimitive()) { |
||||
// see if incompatible
|
||||
r = PRIMITIVE_TYPE_COMPATIBLE_CLASSES.get(rightType); |
||||
if (r != null) { |
||||
result = leftType.isAssignableFrom(r); |
||||
} |
||||
} else { |
||||
// Otherwise it may just be assignable using normal Java polymorphism
|
||||
result = leftType.isAssignableFrom(rightType); |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* Instantiates an object catching any relevant exceptions and rethrowing as a runtime exception |
||||
* |
||||
* @param clazz The class
|
||||
* @return The instantiated object or null if the class parameter was null |
||||
*/ |
||||
public static Object instantiate(Class clazz) throws InstantiationException { |
||||
if (clazz == null) return null; |
||||
try { |
||||
return clazz.getConstructor(EMPTY_CLASS_ARRAY).newInstance(); |
||||
} catch (IllegalAccessException e) { |
||||
throw new InstantiationException(e.getClass().getName() + " error creating instance of class [" + e.getMessage() + "]: " + e.getMessage()); |
||||
} catch (InvocationTargetException e) { |
||||
throw new InstantiationException(e.getClass().getName() + " error creating instance of class [" + e.getMessage() + "]: " + e.getMessage()); |
||||
} catch (NoSuchMethodException e) { |
||||
throw new InstantiationException(e.getClass().getName() + " error creating instance of class [" + e.getMessage() + "]: " + e.getMessage()); |
||||
} catch (java.lang.InstantiationException e) { |
||||
throw new InstantiationException(e.getClass().getName() + " error creating instance of class [" + e.getMessage() + "]: " + e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Retrieves all the properties of the given class for the given type |
||||
* |
||||
* @param clazz The class to retrieve the properties from |
||||
* @param propertyType The type of the properties you wish to retrieve |
||||
* @return An array of PropertyDescriptor instances |
||||
*/ |
||||
public static PropertyDescriptor[] getPropertiesOfType(Class<?> clazz, Class<?> propertyType) { |
||||
if (clazz == null || propertyType == null) { |
||||
return new PropertyDescriptor[0]; |
||||
} |
||||
|
||||
Set<PropertyDescriptor> properties = new HashSet<PropertyDescriptor>(); |
||||
try { |
||||
for (PropertyDescriptor descriptor : BeanUtils.getPropertyDescriptors(clazz)) { |
||||
Class<?> currentPropertyType = descriptor.getPropertyType(); |
||||
if (isTypeInstanceOfPropertyType(propertyType, currentPropertyType)) { |
||||
properties.add(descriptor); |
||||
} |
||||
} |
||||
} catch (Exception e) { |
||||
// if there are any errors in instantiating just return null for the moment
|
||||
return new PropertyDescriptor[0]; |
||||
} |
||||
return properties.toArray(new PropertyDescriptor[properties.size()]); |
||||
} |
||||
|
||||
private static boolean isTypeInstanceOfPropertyType(Class<?> type, Class<?> propertyType) { |
||||
return propertyType.isAssignableFrom(type) && !propertyType.equals(Object.class); |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue