Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>1.9.0.BUILD-SNAPSHOT</version>
<version>1.9.0.DATACMNS-534-SNAPSHOT</version>

<name>Spring Data Core</name>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2014 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.annotation;

import static java.lang.annotation.ElementType.*;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Marks a field to be {@literal read-only} for the mapping framework and will therefore not be persisted.
*
* @author Christoph Strobl
* @since 1.9
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(value = { FIELD, METHOD, ANNOTATION_TYPE })
public @interface ReadOnlyProperty {

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
* @author Graeme Rocher
* @author Jon Brisbin
* @author Patryk Wasik
* @author Christoph Strobl
*/
public interface PersistentEntity<T, P extends PersistentProperty<P>> {

Expand Down Expand Up @@ -153,6 +154,14 @@ public interface PersistentEntity<T, P extends PersistentProperty<P>> {

void doWithProperties(SimplePropertyHandler handler);

/**
* Applies the given {@link PropertyHandler} to all {@link PersistentProperty}s that shall be written to the store.
*
* @param handler
* @since 1.9
*/
void doWithWritingProperties(PropertyHandler<P> handler);

/**
* Applies the given {@link AssociationHandler} to all {@link Association} contained in this {@link PersistentEntity}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.Map;

import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.annotation.ReadOnlyProperty;
import org.springframework.data.util.TypeInformation;

/**
Expand Down Expand Up @@ -147,8 +148,21 @@ public interface PersistentProperty<P extends PersistentProperty<P>> {
*/
boolean isTransient();

/**
* see {@link #isWriting()}
*
* @return
*/
boolean shallBePersisted();

/**
* Returns whether the property is considered to be a {@link ReadOnlyProperty}.
*
* @return
* @since 1.9
*/
boolean isReadOnly();

/**
* Returns whether the property is an {@link Association}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
*
* @author Jon Brisbin
* @author Oliver Gierke
* @author Christoph Strobl
*/
public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>> implements PersistentProperty<P> {

Expand Down Expand Up @@ -204,7 +205,7 @@ public boolean isTransient() {
* @see org.springframework.data.mapping.PersistentProperty#shallBePersisted()
*/
public boolean shallBePersisted() {
return !isTransient();
return !isTransient() && !isReadOnly();
}

/*
Expand All @@ -215,6 +216,15 @@ public boolean isAssociation() {
return field == null ? false : AnnotationUtils.getAnnotation(field, Reference.class) != null;
}

/*
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentProperty#isReading()
*/
@Override
public boolean isReadOnly() {
return isTransient();
}

public Association<P> getAssociation() {
return association;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.springframework.data.annotation.AccessType;
import org.springframework.data.annotation.AccessType.Type;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.ReadOnlyProperty;
import org.springframework.data.annotation.Reference;
import org.springframework.data.annotation.Transient;
import org.springframework.data.annotation.Version;
Expand All @@ -41,6 +42,7 @@
* Special {@link PersistentProperty} that takes annotations at a property into account.
*
* @author Oliver Gierke
* @author Christoph Strobl
*/
public abstract class AnnotationBasedPersistentProperty<P extends PersistentProperty<P>> extends
AbstractPersistentProperty<P> {
Expand Down Expand Up @@ -169,6 +171,20 @@ public boolean isAssociation() {
return !isTransient() && isAnnotationPresent(Reference.class);
}

/*
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentProperty#isReading()
*/
@Override
public boolean isReadOnly() {

if (isTransient() || isAnnotationPresent(ReadOnlyProperty.class)) {
return true;
}

return false;
}

/**
* Returns the annotation found for the current {@link AnnotationBasedPersistentProperty}. Will prefer field
* annotations over ones found at getters or setters.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,21 @@ public void doWithProperties(PropertyHandler<P> handler) {
}
}

/*
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentEntity#doWithWritingProperties(org.springframework.data.mapping.PropertyHandler)
*/
@Override
public void doWithWritingProperties(PropertyHandler<P> handler) {

Assert.notNull(handler, "PropertyHandler must not be 'null'.");
for (P property : properties) {
if (property.shallBePersisted()) {
handler.doWithPersistentProperty(property);
}
}
}

/*
* (non-Javadoc)
* @see org.springframework.data.mapping.PersistentEntity#doWithProperties(org.springframework.data.mapping.PropertyHandler.Simple)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
import org.springframework.data.annotation.AccessType;
import org.springframework.data.annotation.AccessType.Type;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.ReadOnlyProperty;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mapping.context.SampleMappingContext;
import org.springframework.data.mapping.context.SamplePersistentProperty;
import org.springframework.test.util.ReflectionTestUtils;
Expand All @@ -38,6 +40,7 @@
* Unit tests for {@link AnnotationBasedPersistentProperty}.
*
* @author Oliver Gierke
* @author Christoph Strobl
*/
public class AnnotationBasedPersistentPropertyUnitTests<P extends AnnotationBasedPersistentProperty<P>> {

Expand Down Expand Up @@ -158,6 +161,40 @@ public void detectsAmbiguityCausedByFieldAnAccessorAnnotation() {
context.getPersistentEntity(AnotherInvalidSample.class);
}

/**
* @see DATACMNS-534
*/
@Test
public void treatsNoAnnotationCorrectly() {
assertThat(getProperty(ClassWithReadOnlyProperties.class, "noAnnotations").isReadOnly(), is(false));
}

/**
* @see DATACMNS-534
*/
@Test
public void treatsTransientAsNotExisting() {
assertThat(getProperty(ClassWithReadOnlyProperties.class, "transientProperty"), nullValue());
}

/**
* @see DATACMNS-534
*/
@Test
public void treatsReadOnlyPropertyCorrectly() {

SamplePersistentProperty property = getProperty(ClassWithReadOnlyProperties.class, "readOnlyProperty");
assertThat(property.isReadOnly(), is(true));
}

/**
* @see DATACMNS-534
*/
@Test
public void shallBePersistedShouldReturnFalseWhenPropertyIsReadOnlyProperty() {
assertThat(getProperty(ClassWithReadOnlyProperties.class, "readOnlyProperty").shallBePersisted(), is(false));
}

@SuppressWarnings("unchecked")
private Map<Class<? extends Annotation>, Annotation> getAnnotationCache(SamplePersistentProperty property) {
return (Map<Class<? extends Annotation>, Annotation>) ReflectionTestUtils.getField(property, "annotationCache");
Expand Down Expand Up @@ -270,4 +307,13 @@ public String getLastname() {
return lastname;
}
}

static class ClassWithReadOnlyProperties {

String noAnnotations;

@Transient String transientProperty;

@ReadOnlyProperty String readOnlyProperty;
}
}