Browse Source
We now support generated PersistentPropertyAccessors when using Java 7 and if property/association name hashCodes are unique within a PersistentEntity. Generated PersistentPropertyAccessors provide optimized access to properties. They use either MethodHandles or direct property/field access, depending on the visibility/final modifiers of the entity type and its members. A generated PersistentPropertyAccessor is injected into the originating class loader of the entity class to enable optimizations for package-default/protected member access. Original pull request: #159.pull/160/head
10 changed files with 2509 additions and 28 deletions
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,45 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2016 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.PersistentEntity; |
||||||
|
import org.springframework.data.mapping.PersistentPropertyAccessor; |
||||||
|
|
||||||
|
/** |
||||||
|
* Default implementation of {@link PersistentPropertyAccessorFactory}. Accessors can access bean properties either via |
||||||
|
* reflection or use generated classes with direct field/method access. |
||||||
|
* |
||||||
|
* @author Mark Paluch |
||||||
|
* @since 1.13 |
||||||
|
*/ |
||||||
|
public class DefaultPersistentPropertyAccessorFactory implements PersistentPropertyAccessorFactory { |
||||||
|
|
||||||
|
private final ClassGeneratingPropertyAccessorFactory classGeneratingPropertyAccessorFactory = new ClassGeneratingPropertyAccessorFactory(); |
||||||
|
|
||||||
|
/* (non-Javadoc) |
||||||
|
* @see org.springframework.data.mapping.model.PersistentPropertyAccessorFactory#getPropertyAccessor(org.springframework.data.mapping.PersistentEntity, java.lang.Object) |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> entity, Object bean) { |
||||||
|
|
||||||
|
if (ClassGeneratingPropertyAccessorFactory.canGenerateAccessorClass(entity)) { |
||||||
|
return classGeneratingPropertyAccessorFactory.getPropertyAccessor(entity, bean); |
||||||
|
} |
||||||
|
return new BeanWrapper<Object>(bean); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,38 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2016 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.PersistentEntity; |
||||||
|
import org.springframework.data.mapping.PersistentPropertyAccessor; |
||||||
|
|
||||||
|
/** |
||||||
|
* Factory to create {@link PersistentPropertyAccessor} for a given {@link PersistentEntity} and {@code bean}. |
||||||
|
* |
||||||
|
* @author Mark Paluch |
||||||
|
* @since 1.13 |
||||||
|
*/ |
||||||
|
public interface PersistentPropertyAccessorFactory { |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns a {@link PersistentPropertyAccessor} for a given {@link PersistentEntity} and {@code bean}. |
||||||
|
* |
||||||
|
* @param bean |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> entity, Object bean); |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,247 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2016 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 static org.hamcrest.CoreMatchers.is; |
||||||
|
import static org.hamcrest.Matchers.equalTo; |
||||||
|
import static org.junit.Assert.*; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.junit.Test; |
||||||
|
import org.junit.runner.RunWith; |
||||||
|
import org.junit.runners.Parameterized; |
||||||
|
import org.junit.runners.Parameterized.Parameters; |
||||||
|
import org.springframework.data.annotation.AccessType; |
||||||
|
import org.springframework.data.annotation.AccessType.Type; |
||||||
|
import org.springframework.data.mapping.PersistentProperty; |
||||||
|
import org.springframework.data.mapping.PersistentPropertyAccessor; |
||||||
|
import org.springframework.data.mapping.context.SampleMappingContext; |
||||||
|
import org.springframework.data.mapping.context.SamplePersistentProperty; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
/** |
||||||
|
* Unit tests for {@link ClassGeneratingPropertyAccessorFactory} |
||||||
|
* |
||||||
|
* @author Mark Paluch |
||||||
|
* @see DATACMNS-809 |
||||||
|
*/ |
||||||
|
@RunWith(Parameterized.class) |
||||||
|
public class ClassGeneratingPropertyAccessorFactoryDatatypeTests { |
||||||
|
|
||||||
|
private final ClassGeneratingPropertyAccessorFactory factory = new ClassGeneratingPropertyAccessorFactory(); |
||||||
|
private final SampleMappingContext mappingContext = new SampleMappingContext(); |
||||||
|
|
||||||
|
private Object bean; |
||||||
|
private String propertyName; |
||||||
|
private Object value; |
||||||
|
|
||||||
|
public ClassGeneratingPropertyAccessorFactoryDatatypeTests(Object bean, String propertyName, Object value, |
||||||
|
String displayName) { |
||||||
|
|
||||||
|
this.bean = bean; |
||||||
|
this.propertyName = propertyName; |
||||||
|
this.value = value; |
||||||
|
} |
||||||
|
|
||||||
|
@Parameters(name = "{3}") |
||||||
|
public static List<Object[]> parameters() throws Exception { |
||||||
|
|
||||||
|
List<Object[]> parameters = new ArrayList<Object[]>(); |
||||||
|
|
||||||
|
List<Class<?>> types = Arrays.asList(FieldAccess.class, PropertyAccess.class); |
||||||
|
|
||||||
|
parameters.addAll(parameters(types, "primitiveInteger", Integer.valueOf(1))); |
||||||
|
parameters.addAll(parameters(types, "primitiveIntegerArray", new int[] { 1, 2, 3 })); |
||||||
|
parameters.addAll(parameters(types, "boxedInteger", Integer.valueOf(1))); |
||||||
|
parameters.addAll(parameters(types, "boxedIntegerArray", new Integer[] { Integer.valueOf(1) })); |
||||||
|
parameters.addAll(parameters(types, "primitiveShort", Short.valueOf("1"))); |
||||||
|
parameters.addAll(parameters(types, "primitiveShortArray", new short[] { 1, 2, 3 })); |
||||||
|
parameters.addAll(parameters(types, "boxedShort", Short.valueOf("1"))); |
||||||
|
parameters.addAll(parameters(types, "boxedShortArray", new Short[] { Short.valueOf("1") })); |
||||||
|
parameters.addAll(parameters(types, "primitiveByte", Byte.valueOf("1"))); |
||||||
|
parameters.addAll(parameters(types, "primitiveByteArray", new byte[] { 1, 2, 3 })); |
||||||
|
parameters.addAll(parameters(types, "boxedByte", Byte.valueOf("1"))); |
||||||
|
parameters.addAll(parameters(types, "boxedByteArray", new Byte[] { Byte.valueOf("1") })); |
||||||
|
parameters.addAll(parameters(types, "primitiveChar", Character.valueOf('c'))); |
||||||
|
parameters.addAll(parameters(types, "primitiveCharArray", new char[] { 'a', 'b', 'c' })); |
||||||
|
parameters.addAll(parameters(types, "boxedChar", Character.valueOf('c'))); |
||||||
|
parameters.addAll(parameters(types, "boxedCharArray", new Character[] { Character.valueOf('c') })); |
||||||
|
parameters.addAll(parameters(types, "primitiveBoolean", Boolean.valueOf(true))); |
||||||
|
parameters.addAll(parameters(types, "primitiveBooleanArray", new boolean[] { true, false })); |
||||||
|
parameters.addAll(parameters(types, "boxedBoolean", Boolean.valueOf(true))); |
||||||
|
parameters.addAll(parameters(types, "boxedBooleanArray", new Boolean[] { Boolean.valueOf(true) })); |
||||||
|
parameters.addAll(parameters(types, "primitiveFloat", Float.valueOf(1f))); |
||||||
|
parameters.addAll(parameters(types, "primitiveFloatArray", new float[] { 1f, 2f })); |
||||||
|
parameters.addAll(parameters(types, "boxedFloat", Float.valueOf(1f))); |
||||||
|
parameters.addAll(parameters(types, "boxedFloatArray", new Float[] { Float.valueOf(1f) })); |
||||||
|
parameters.addAll(parameters(types, "primitiveDouble", Double.valueOf(1d))); |
||||||
|
parameters.addAll(parameters(types, "primitiveDoubleArray", new double[] { 1d, 2d })); |
||||||
|
parameters.addAll(parameters(types, "boxedDouble", Double.valueOf(1d))); |
||||||
|
parameters.addAll(parameters(types, "boxedDoubleArray", new Double[] { Double.valueOf(1d) })); |
||||||
|
parameters.addAll(parameters(types, "primitiveLong", Long.valueOf(1L))); |
||||||
|
parameters.addAll(parameters(types, "primitiveLongArray", new long[] { 1L, 2L })); |
||||||
|
parameters.addAll(parameters(types, "boxedLong", Long.valueOf(1L))); |
||||||
|
parameters.addAll(parameters(types, "boxedLongArray", new Long[] { Long.valueOf(1L) })); |
||||||
|
parameters.addAll(parameters(types, "string", "hello")); |
||||||
|
parameters.addAll(parameters(types, "stringArray", new String[] { "hello", "world" })); |
||||||
|
|
||||||
|
return parameters; |
||||||
|
} |
||||||
|
|
||||||
|
private static List<Object[]> parameters(List<Class<?>> types, String propertyName, Object value) throws Exception { |
||||||
|
|
||||||
|
List<Object[]> parameters = new ArrayList<Object[]>(); |
||||||
|
|
||||||
|
for (Class<?> type : types) { |
||||||
|
parameters |
||||||
|
.add(new Object[] { type.newInstance(), propertyName, value, type.getSimpleName() + "/" + propertyName }); |
||||||
|
} |
||||||
|
|
||||||
|
return parameters; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see DATACMNS-809 |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
@Test |
||||||
|
public void shouldSetAndGetProperty() throws Exception { |
||||||
|
|
||||||
|
PersistentProperty<?> property = getProperty(bean, propertyName); |
||||||
|
PersistentPropertyAccessor persistentPropertyAccessor = getPersistentPropertyAccessor(bean); |
||||||
|
|
||||||
|
persistentPropertyAccessor.setProperty(property, value); |
||||||
|
assertThat(persistentPropertyAccessor.getProperty(property), is(equalTo((Object) value))); |
||||||
|
} |
||||||
|
|
||||||
|
private PersistentPropertyAccessor getPersistentPropertyAccessor(Object bean) { |
||||||
|
return factory.getPropertyAccessor(mappingContext.getPersistentEntity(bean.getClass()), bean); |
||||||
|
} |
||||||
|
|
||||||
|
private PersistentProperty<?> getProperty(Object bean, String name) { |
||||||
|
|
||||||
|
BasicPersistentEntity<Object, SamplePersistentProperty> persistentEntity = mappingContext |
||||||
|
.getPersistentEntity(bean.getClass()); |
||||||
|
return persistentEntity.getPersistentProperty(name); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see DATACMNS-809 |
||||||
|
*/ |
||||||
|
@AccessType(Type.FIELD) |
||||||
|
public static class FieldAccess { |
||||||
|
|
||||||
|
int primitiveInteger; |
||||||
|
int primitiveIntegerArray[]; |
||||||
|
Integer boxedInteger; |
||||||
|
Integer boxedIntegerArray[]; |
||||||
|
|
||||||
|
short primitiveShort; |
||||||
|
short primitiveShortArray[]; |
||||||
|
Short boxedShort; |
||||||
|
Short boxedShortArray[]; |
||||||
|
|
||||||
|
byte primitiveByte; |
||||||
|
byte primitiveByteArray[]; |
||||||
|
Byte boxedByte; |
||||||
|
Byte boxedByteArray[]; |
||||||
|
|
||||||
|
char primitiveChar; |
||||||
|
char primitiveCharArray[]; |
||||||
|
Character boxedChar; |
||||||
|
Character boxedCharArray[]; |
||||||
|
|
||||||
|
boolean primitiveBoolean; |
||||||
|
boolean primitiveBooleanArray[]; |
||||||
|
Boolean boxedBoolean; |
||||||
|
Boolean boxedBooleanArray[]; |
||||||
|
|
||||||
|
float primitiveFloat; |
||||||
|
float primitiveFloatArray[]; |
||||||
|
Float boxedFloat; |
||||||
|
Float boxedFloatArray[]; |
||||||
|
|
||||||
|
double primitiveDouble; |
||||||
|
double primitiveDoubleArray[]; |
||||||
|
Double boxedDouble; |
||||||
|
Double boxedDoubleArray[]; |
||||||
|
|
||||||
|
long primitiveLong; |
||||||
|
long primitiveLongArray[]; |
||||||
|
Long boxedLong; |
||||||
|
Long boxedLongArray[]; |
||||||
|
|
||||||
|
String string; |
||||||
|
String stringArray[]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see DATACMNS-809 |
||||||
|
*/ |
||||||
|
@AccessType(Type.PROPERTY) |
||||||
|
@Data |
||||||
|
public static class PropertyAccess { |
||||||
|
|
||||||
|
int primitiveInteger; |
||||||
|
int primitiveIntegerArray[]; |
||||||
|
Integer boxedInteger; |
||||||
|
Integer boxedIntegerArray[]; |
||||||
|
|
||||||
|
short primitiveShort; |
||||||
|
short primitiveShortArray[]; |
||||||
|
Short boxedShort; |
||||||
|
Short boxedShortArray[]; |
||||||
|
|
||||||
|
byte primitiveByte; |
||||||
|
byte primitiveByteArray[]; |
||||||
|
Byte boxedByte; |
||||||
|
Byte boxedByteArray[]; |
||||||
|
|
||||||
|
char primitiveChar; |
||||||
|
char primitiveCharArray[]; |
||||||
|
Character boxedChar; |
||||||
|
Character boxedCharArray[]; |
||||||
|
|
||||||
|
boolean primitiveBoolean; |
||||||
|
boolean primitiveBooleanArray[]; |
||||||
|
Boolean boxedBoolean; |
||||||
|
Boolean boxedBooleanArray[]; |
||||||
|
|
||||||
|
float primitiveFloat; |
||||||
|
float primitiveFloatArray[]; |
||||||
|
Float boxedFloat; |
||||||
|
Float boxedFloatArray[]; |
||||||
|
|
||||||
|
double primitiveDouble; |
||||||
|
double primitiveDoubleArray[]; |
||||||
|
Double boxedDouble; |
||||||
|
Double boxedDoubleArray[]; |
||||||
|
|
||||||
|
long primitiveLong; |
||||||
|
long primitiveLongArray[]; |
||||||
|
Long boxedLong; |
||||||
|
Long boxedLongArray[]; |
||||||
|
|
||||||
|
String string; |
||||||
|
String stringArray[]; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,433 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2016 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 static org.hamcrest.CoreMatchers.is; |
||||||
|
import static org.hamcrest.Matchers.equalTo; |
||||||
|
import static org.junit.Assert.*; |
||||||
|
|
||||||
|
import java.lang.reflect.Constructor; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.junit.Test; |
||||||
|
import org.junit.runner.RunWith; |
||||||
|
import org.junit.runners.Parameterized; |
||||||
|
import org.junit.runners.Parameterized.Parameters; |
||||||
|
import org.springframework.data.annotation.AccessType; |
||||||
|
import org.springframework.data.annotation.AccessType.Type; |
||||||
|
import org.springframework.data.mapping.PersistentProperty; |
||||||
|
import org.springframework.data.mapping.PersistentPropertyAccessor; |
||||||
|
import org.springframework.data.mapping.context.SampleMappingContext; |
||||||
|
import org.springframework.data.mapping.context.SamplePersistentProperty; |
||||||
|
import org.springframework.data.mapping.model.subpackage.TypeInOtherPackage; |
||||||
|
|
||||||
|
/** |
||||||
|
* Unit tests for {@link ClassGeneratingPropertyAccessorFactory} |
||||||
|
* |
||||||
|
* @author Mark Paluch |
||||||
|
* @see DATACMNS-809 |
||||||
|
*/ |
||||||
|
@RunWith(Parameterized.class) |
||||||
|
public class ClassGeneratingPropertyAccessorFactoryTests { |
||||||
|
|
||||||
|
private final ClassGeneratingPropertyAccessorFactory factory = new ClassGeneratingPropertyAccessorFactory(); |
||||||
|
private final SampleMappingContext mappingContext = new SampleMappingContext(); |
||||||
|
|
||||||
|
private Object bean; |
||||||
|
private String propertyName; |
||||||
|
private Class<?> expectedConstructorType; |
||||||
|
|
||||||
|
public ClassGeneratingPropertyAccessorFactoryTests(Object bean, String propertyName, Class<?> expectedConstructorType, |
||||||
|
String displayName) { |
||||||
|
|
||||||
|
this.bean = bean; |
||||||
|
this.propertyName = propertyName; |
||||||
|
this.expectedConstructorType = expectedConstructorType; |
||||||
|
} |
||||||
|
|
||||||
|
@Parameters(name = "{3}") |
||||||
|
public static List<Object[]> parameters() { |
||||||
|
|
||||||
|
List<Object[]> parameters = new ArrayList<Object[]>(); |
||||||
|
|
||||||
|
List<String> propertyNames = Arrays.asList("privateField", "packageDefaultField", "protectedField", "publicField", |
||||||
|
"privateProperty", "packageDefaultProperty", "protectedProperty", "publicProperty", "syntheticProperty"); |
||||||
|
parameters.addAll(parameters(new InnerPrivateType(), propertyNames, Object.class)); |
||||||
|
parameters.addAll(parameters(new InnerTypeWithPrivateAncesor(), propertyNames, InnerTypeWithPrivateAncesor.class)); |
||||||
|
parameters.addAll(parameters(new InnerPackageDefaultType(), propertyNames, InnerPackageDefaultType.class)); |
||||||
|
parameters.addAll(parameters(new InnerProtectedType(), propertyNames, InnerProtectedType.class)); |
||||||
|
parameters.addAll(parameters(new InnerPublicType(), propertyNames, InnerPublicType.class)); |
||||||
|
parameters.addAll(parameters(new ClassGeneratingPropertyAccessorPackageDefaultType(), propertyNames, |
||||||
|
ClassGeneratingPropertyAccessorPackageDefaultType.class)); |
||||||
|
parameters.addAll(parameters(new ClassGeneratingPropertyAccessorPublicType(), propertyNames, |
||||||
|
ClassGeneratingPropertyAccessorPublicType.class)); |
||||||
|
parameters.addAll(parameters(new SubtypeOfTypeInOtherPackage(), propertyNames, |
||||||
|
SubtypeOfTypeInOtherPackage.class)); |
||||||
|
|
||||||
|
return parameters; |
||||||
|
} |
||||||
|
|
||||||
|
private static List<Object[]> parameters(Object bean, List<String> propertyNames, Class<?> expectedConstructorType) { |
||||||
|
|
||||||
|
List<Object[]> parameters = new ArrayList<Object[]>(); |
||||||
|
|
||||||
|
for (String propertyName : propertyNames) { |
||||||
|
parameters.add(new Object[] { bean, propertyName, expectedConstructorType, |
||||||
|
bean.getClass().getSimpleName() + "/" + propertyName }); |
||||||
|
} |
||||||
|
|
||||||
|
return parameters; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see DATACMNS-809 |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
@Test |
||||||
|
public void shouldSetAndGetProperty() throws Exception { |
||||||
|
|
||||||
|
PersistentProperty<?> property = getProperty(bean, propertyName); |
||||||
|
PersistentPropertyAccessor persistentPropertyAccessor = getPersistentPropertyAccessor(bean); |
||||||
|
|
||||||
|
persistentPropertyAccessor.setProperty(property, "value"); |
||||||
|
assertThat(persistentPropertyAccessor.getProperty(property), is(equalTo((Object) "value"))); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see DATACMNS-809 |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
@Test |
||||||
|
public void accessorShouldDeclareConstructor() throws Exception { |
||||||
|
|
||||||
|
PersistentPropertyAccessor persistentPropertyAccessor = getPersistentPropertyAccessor(bean); |
||||||
|
|
||||||
|
Constructor<?>[] declaredConstructors = persistentPropertyAccessor.getClass().getDeclaredConstructors(); |
||||||
|
assertThat(declaredConstructors.length, is(1)); |
||||||
|
assertThat(declaredConstructors[0].getParameterTypes().length, is(1)); |
||||||
|
assertThat(declaredConstructors[0].getParameterTypes()[0], is(equalTo((Class) expectedConstructorType))); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see DATACMNS-809 |
||||||
|
*/ |
||||||
|
@Test(expected = IllegalArgumentException.class) |
||||||
|
public void shouldFailOnNullBean() { |
||||||
|
factory.getPropertyAccessor(mappingContext.getPersistentEntity(bean.getClass()), null); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see DATACMNS-809 |
||||||
|
*/ |
||||||
|
@Test(expected = UnsupportedOperationException.class) |
||||||
|
public void getPropertyShouldFailOnUnhandledProperty() { |
||||||
|
|
||||||
|
PersistentProperty<?> property = getProperty(new Dummy(), "dummy"); |
||||||
|
PersistentPropertyAccessor persistentPropertyAccessor = getPersistentPropertyAccessor(bean); |
||||||
|
|
||||||
|
persistentPropertyAccessor.getProperty(property); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see DATACMNS-809 |
||||||
|
*/ |
||||||
|
@Test(expected = UnsupportedOperationException.class) |
||||||
|
public void setPropertyShouldFailOnUnhandledProperty() { |
||||||
|
|
||||||
|
PersistentProperty<?> property = getProperty(new Dummy(), "dummy"); |
||||||
|
PersistentPropertyAccessor persistentPropertyAccessor = getPersistentPropertyAccessor(bean); |
||||||
|
|
||||||
|
persistentPropertyAccessor.setProperty(property, null); |
||||||
|
} |
||||||
|
|
||||||
|
private PersistentPropertyAccessor getPersistentPropertyAccessor(Object bean) { |
||||||
|
return factory.getPropertyAccessor(mappingContext.getPersistentEntity(bean.getClass()), bean); |
||||||
|
} |
||||||
|
|
||||||
|
private PersistentProperty<?> getProperty(Object bean, String name) { |
||||||
|
|
||||||
|
BasicPersistentEntity<Object, SamplePersistentProperty> persistentEntity = mappingContext |
||||||
|
.getPersistentEntity(bean.getClass()); |
||||||
|
return persistentEntity.getPersistentProperty(name); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see DATACMNS-809 |
||||||
|
*/ |
||||||
|
private static class InnerPrivateType { |
||||||
|
|
||||||
|
private String privateField; |
||||||
|
String packageDefaultField; |
||||||
|
protected String protectedField; |
||||||
|
public String publicField; |
||||||
|
private String backing; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String privateProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String packageDefaultProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String protectedProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String publicProperty; |
||||||
|
|
||||||
|
private String getPrivateProperty() { |
||||||
|
return privateProperty; |
||||||
|
} |
||||||
|
|
||||||
|
private void setPrivateProperty(String privateProperty) { |
||||||
|
this.privateProperty = privateProperty; |
||||||
|
} |
||||||
|
|
||||||
|
String getPackageDefaultProperty() { |
||||||
|
return packageDefaultProperty; |
||||||
|
} |
||||||
|
|
||||||
|
void setPackageDefaultProperty(String packageDefaultProperty) { |
||||||
|
this.packageDefaultProperty = packageDefaultProperty; |
||||||
|
} |
||||||
|
|
||||||
|
protected String getProtectedProperty() { |
||||||
|
return protectedProperty; |
||||||
|
} |
||||||
|
|
||||||
|
protected void setProtectedProperty(String protectedProperty) { |
||||||
|
this.protectedProperty = protectedProperty; |
||||||
|
} |
||||||
|
|
||||||
|
public String getPublicProperty() { |
||||||
|
return publicProperty; |
||||||
|
} |
||||||
|
|
||||||
|
public void setPublicProperty(String publicProperty) { |
||||||
|
this.publicProperty = publicProperty; |
||||||
|
} |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) |
||||||
|
public String getSyntheticProperty() { |
||||||
|
return backing; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSyntheticProperty(String syntheticProperty) { |
||||||
|
backing = syntheticProperty; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see DATACMNS-809 |
||||||
|
*/ |
||||||
|
public static class InnerTypeWithPrivateAncesor extends InnerPrivateType { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see DATACMNS-809 |
||||||
|
*/ |
||||||
|
static class InnerPackageDefaultType { |
||||||
|
|
||||||
|
private String privateField; |
||||||
|
String packageDefaultField; |
||||||
|
protected String protectedField; |
||||||
|
public String publicField; |
||||||
|
private String backing; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String privateProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String packageDefaultProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String protectedProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String publicProperty; |
||||||
|
|
||||||
|
private String getPrivateProperty() { |
||||||
|
return privateProperty; |
||||||
|
} |
||||||
|
|
||||||
|
private void setPrivateProperty(String privateProperty) { |
||||||
|
this.privateProperty = privateProperty; |
||||||
|
} |
||||||
|
|
||||||
|
String getPackageDefaultProperty() { |
||||||
|
return packageDefaultProperty; |
||||||
|
} |
||||||
|
|
||||||
|
void setPackageDefaultProperty(String packageDefaultProperty) { |
||||||
|
this.packageDefaultProperty = packageDefaultProperty; |
||||||
|
} |
||||||
|
|
||||||
|
protected String getProtectedProperty() { |
||||||
|
return protectedProperty; |
||||||
|
} |
||||||
|
|
||||||
|
protected void setProtectedProperty(String protectedProperty) { |
||||||
|
this.protectedProperty = protectedProperty; |
||||||
|
} |
||||||
|
|
||||||
|
public String getPublicProperty() { |
||||||
|
return publicProperty; |
||||||
|
} |
||||||
|
|
||||||
|
public void setPublicProperty(String publicProperty) { |
||||||
|
this.publicProperty = publicProperty; |
||||||
|
} |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) |
||||||
|
public String getSyntheticProperty() { |
||||||
|
return backing; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSyntheticProperty(String syntheticProperty) { |
||||||
|
backing = syntheticProperty; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see DATACMNS-809 |
||||||
|
*/ |
||||||
|
protected static class InnerProtectedType { |
||||||
|
|
||||||
|
private String privateField; |
||||||
|
String packageDefaultField; |
||||||
|
protected String protectedField; |
||||||
|
public String publicField; |
||||||
|
private String backing; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String privateProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String packageDefaultProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String protectedProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String publicProperty; |
||||||
|
|
||||||
|
private String getPrivateProperty() { |
||||||
|
return privateProperty; |
||||||
|
} |
||||||
|
|
||||||
|
private void setPrivateProperty(String privateProperty) { |
||||||
|
this.privateProperty = privateProperty; |
||||||
|
} |
||||||
|
|
||||||
|
String getPackageDefaultProperty() { |
||||||
|
return packageDefaultProperty; |
||||||
|
} |
||||||
|
|
||||||
|
void setPackageDefaultProperty(String packageDefaultProperty) { |
||||||
|
this.packageDefaultProperty = packageDefaultProperty; |
||||||
|
} |
||||||
|
|
||||||
|
protected String getProtectedProperty() { |
||||||
|
return protectedProperty; |
||||||
|
} |
||||||
|
|
||||||
|
protected void setProtectedProperty(String protectedProperty) { |
||||||
|
this.protectedProperty = protectedProperty; |
||||||
|
} |
||||||
|
|
||||||
|
public String getPublicProperty() { |
||||||
|
return publicProperty; |
||||||
|
} |
||||||
|
|
||||||
|
public void setPublicProperty(String publicProperty) { |
||||||
|
this.publicProperty = publicProperty; |
||||||
|
} |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) |
||||||
|
public String getSyntheticProperty() { |
||||||
|
return backing; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSyntheticProperty(String syntheticProperty) { |
||||||
|
backing = syntheticProperty; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see DATACMNS-809 |
||||||
|
*/ |
||||||
|
public static class InnerPublicType { |
||||||
|
|
||||||
|
private String privateField; |
||||||
|
String packageDefaultField; |
||||||
|
protected String protectedField; |
||||||
|
public String publicField; |
||||||
|
private String backing; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String privateProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String packageDefaultProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String protectedProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String publicProperty; |
||||||
|
|
||||||
|
private String getPrivateProperty() { |
||||||
|
return privateProperty; |
||||||
|
} |
||||||
|
|
||||||
|
private void setPrivateProperty(String privateProperty) { |
||||||
|
this.privateProperty = privateProperty; |
||||||
|
} |
||||||
|
|
||||||
|
String getPackageDefaultProperty() { |
||||||
|
return packageDefaultProperty; |
||||||
|
} |
||||||
|
|
||||||
|
void setPackageDefaultProperty(String packageDefaultProperty) { |
||||||
|
this.packageDefaultProperty = packageDefaultProperty; |
||||||
|
} |
||||||
|
|
||||||
|
protected String getProtectedProperty() { |
||||||
|
return protectedProperty; |
||||||
|
} |
||||||
|
|
||||||
|
protected void setProtectedProperty(String protectedProperty) { |
||||||
|
this.protectedProperty = protectedProperty; |
||||||
|
} |
||||||
|
|
||||||
|
public String getPublicProperty() { |
||||||
|
return publicProperty; |
||||||
|
} |
||||||
|
|
||||||
|
public void setPublicProperty(String publicProperty) { |
||||||
|
this.publicProperty = publicProperty; |
||||||
|
} |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) |
||||||
|
public String getSyntheticProperty() { |
||||||
|
return backing; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSyntheticProperty(String syntheticProperty) { |
||||||
|
backing = syntheticProperty; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static class SubtypeOfTypeInOtherPackage extends TypeInOtherPackage{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @see DATACMNS-809 |
||||||
|
*/ |
||||||
|
private static class Dummy { |
||||||
|
private String dummy; |
||||||
|
public String publicField; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,83 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2016 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.annotation.AccessType; |
||||||
|
import org.springframework.data.annotation.AccessType.Type; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Mark Paluch |
||||||
|
* @see DATACMNS-809 |
||||||
|
*/ |
||||||
|
class ClassGeneratingPropertyAccessorPackageDefaultType { |
||||||
|
|
||||||
|
private String privateField; |
||||||
|
String packageDefaultField; |
||||||
|
protected String protectedField; |
||||||
|
public String publicField; |
||||||
|
private String backing; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String privateProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String packageDefaultProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String protectedProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String publicProperty; |
||||||
|
|
||||||
|
private String getPrivateProperty() { |
||||||
|
return privateProperty; |
||||||
|
} |
||||||
|
|
||||||
|
private void setPrivateProperty(String privateProperty) { |
||||||
|
this.privateProperty = privateProperty; |
||||||
|
} |
||||||
|
|
||||||
|
String getPackageDefaultProperty() { |
||||||
|
return packageDefaultProperty; |
||||||
|
} |
||||||
|
|
||||||
|
void setPackageDefaultProperty(String packageDefaultProperty) { |
||||||
|
this.packageDefaultProperty = packageDefaultProperty; |
||||||
|
} |
||||||
|
|
||||||
|
protected String getProtectedProperty() { |
||||||
|
return protectedProperty; |
||||||
|
} |
||||||
|
|
||||||
|
protected void setProtectedProperty(String protectedProperty) { |
||||||
|
this.protectedProperty = protectedProperty; |
||||||
|
} |
||||||
|
|
||||||
|
public String getPublicProperty() { |
||||||
|
return publicProperty; |
||||||
|
} |
||||||
|
|
||||||
|
public void setPublicProperty(String publicProperty) { |
||||||
|
this.publicProperty = publicProperty; |
||||||
|
} |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) |
||||||
|
public String getSyntheticProperty() { |
||||||
|
return backing; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSyntheticProperty(String syntheticProperty) { |
||||||
|
backing = syntheticProperty; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,94 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2016 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.annotation.AccessType; |
||||||
|
import org.springframework.data.annotation.AccessType.Type; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Mark Paluch |
||||||
|
* @see DATACMNS-809 |
||||||
|
*/ |
||||||
|
public class ClassGeneratingPropertyAccessorPublicType { |
||||||
|
|
||||||
|
private String privateField; |
||||||
|
String packageDefaultField; |
||||||
|
protected String protectedField; |
||||||
|
public String publicField; |
||||||
|
private String backing; |
||||||
|
private Integer aa; |
||||||
|
private int bb; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String privateProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String packageDefaultProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String protectedProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String publicProperty; |
||||||
|
|
||||||
|
private String getPrivateProperty() { |
||||||
|
return privateProperty; |
||||||
|
} |
||||||
|
|
||||||
|
private void setPrivateProperty(String privateProperty) { |
||||||
|
this.privateProperty = privateProperty; |
||||||
|
} |
||||||
|
|
||||||
|
String getPackageDefaultProperty() { |
||||||
|
return packageDefaultProperty; |
||||||
|
} |
||||||
|
|
||||||
|
void setPackageDefaultProperty(String packageDefaultProperty) { |
||||||
|
this.packageDefaultProperty = packageDefaultProperty; |
||||||
|
} |
||||||
|
|
||||||
|
protected String getProtectedProperty() { |
||||||
|
return protectedProperty; |
||||||
|
} |
||||||
|
|
||||||
|
protected void setProtectedProperty(String protectedProperty) { |
||||||
|
this.protectedProperty = protectedProperty; |
||||||
|
} |
||||||
|
|
||||||
|
public String getPublicProperty() { |
||||||
|
return publicProperty; |
||||||
|
} |
||||||
|
|
||||||
|
public void setPublicProperty(String publicProperty) { |
||||||
|
this.publicProperty = publicProperty; |
||||||
|
} |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) |
||||||
|
public String getSyntheticProperty() { |
||||||
|
return backing; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSyntheticProperty(String syntheticProperty) { |
||||||
|
backing = syntheticProperty; |
||||||
|
} |
||||||
|
|
||||||
|
public Object set(Object e) { |
||||||
|
aa = (Integer) e; |
||||||
|
bb = (Integer) e; |
||||||
|
return bb; |
||||||
|
} |
||||||
|
|
||||||
|
public static void main(String[] args) { |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,82 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2016 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.subpackage; |
||||||
|
|
||||||
|
import org.springframework.data.annotation.AccessType; |
||||||
|
import org.springframework.data.annotation.AccessType.Type; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Mark Paluch |
||||||
|
* @see DATACMNS-809 |
||||||
|
*/ |
||||||
|
public class TypeInOtherPackage { |
||||||
|
|
||||||
|
private String privateField; |
||||||
|
String packageDefaultField; |
||||||
|
protected String protectedField; |
||||||
|
public String publicField; |
||||||
|
private String backing; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String privateProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String packageDefaultProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String protectedProperty; |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) private String publicProperty; |
||||||
|
|
||||||
|
private String getPrivateProperty() { |
||||||
|
return privateProperty; |
||||||
|
} |
||||||
|
|
||||||
|
private void setPrivateProperty(String privateProperty) { |
||||||
|
this.privateProperty = privateProperty; |
||||||
|
} |
||||||
|
|
||||||
|
String getPackageDefaultProperty() { |
||||||
|
return packageDefaultProperty; |
||||||
|
} |
||||||
|
|
||||||
|
void setPackageDefaultProperty(String packageDefaultProperty) { |
||||||
|
this.packageDefaultProperty = packageDefaultProperty; |
||||||
|
} |
||||||
|
|
||||||
|
protected String getProtectedProperty() { |
||||||
|
return protectedProperty; |
||||||
|
} |
||||||
|
|
||||||
|
protected void setProtectedProperty(String protectedProperty) { |
||||||
|
this.protectedProperty = protectedProperty; |
||||||
|
} |
||||||
|
|
||||||
|
public String getPublicProperty() { |
||||||
|
return publicProperty; |
||||||
|
} |
||||||
|
|
||||||
|
public void setPublicProperty(String publicProperty) { |
||||||
|
this.publicProperty = publicProperty; |
||||||
|
} |
||||||
|
|
||||||
|
@AccessType(Type.PROPERTY) |
||||||
|
public String getSyntheticProperty() { |
||||||
|
return backing; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSyntheticProperty(String syntheticProperty) { |
||||||
|
backing = syntheticProperty; |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue