Merge branch 'master' of github.com:SpringSource/spring-data-commons

This commit is contained in:
J. Brisbin
2011-04-01 11:29:14 -05:00
11 changed files with 207 additions and 69 deletions

View File

@@ -115,6 +115,14 @@ public interface Page<T> extends Iterable<T> {
* @return
*/
List<T> getContent();
/**
* Returns whether the {@link Page} has content at all.
*
* @return
*/
boolean hasContent();
/**

View File

@@ -49,10 +49,7 @@ public class PageImpl<T> implements Page<T> {
this.content.addAll(content);
this.total = total;
this.pageable =
null == pageable ? new PageRequest(0, content.size())
: pageable;
this.pageable = pageable;
}
@@ -75,7 +72,7 @@ public class PageImpl<T> implements Page<T> {
*/
public int getNumber() {
return pageable.getPageNumber();
return pageable == null ? 0 : pageable.getPageNumber();
}
@@ -86,7 +83,7 @@ public class PageImpl<T> implements Page<T> {
*/
public int getSize() {
return pageable.getPageSize();
return pageable == null ? 0 : pageable.getPageSize();
}
@@ -97,7 +94,7 @@ public class PageImpl<T> implements Page<T> {
*/
public int getTotalPages() {
return (int) Math.ceil((double) total / (double) getSize());
return getSize() == 0 ? 0 : (int) Math.ceil((double) total / (double) getSize());
}
@@ -187,6 +184,17 @@ public class PageImpl<T> implements Page<T> {
return Collections.unmodifiableList(content);
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.domain.Page#hasContent()
*/
@Override
public boolean hasContent() {
return !content.isEmpty();
}
/*
@@ -196,7 +204,7 @@ public class PageImpl<T> implements Page<T> {
*/
public Sort getSort() {
return pageable.getSort();
return pageable == null ? null : pageable.getSort();
}
@@ -239,7 +247,7 @@ public class PageImpl<T> implements Page<T> {
boolean totalEqual = this.total == that.total;
boolean contentEqual = this.content.equals(that.content);
boolean pageableEqual = this.pageable.equals(that.pageable);
boolean pageableEqual = this.pageable == null ? that.pageable == null : this.pageable.equals(that.pageable);
return totalEqual && contentEqual && pageableEqual;
}
@@ -256,7 +264,7 @@ public class PageImpl<T> implements Page<T> {
int result = 17;
result = 31 * result + (int) (total ^ total >>> 32);
result = 31 * result + pageable.hashCode();
result = 31 * result + (pageable == null ? 0 : pageable.hashCode());
result = 31 * result + content.hashCode();
return result;

View File

@@ -295,7 +295,7 @@ public class BasicMappingContext implements MappingContext, InitializingBean, Ap
// Find the right constructor
PreferredConstructor<T> preferredConstructor = null;
for (Constructor<?> constructor : type.getConstructors()) {
for (Constructor<?> constructor : type.getDeclaredConstructors()) {
if (constructor.getParameterTypes().length != 0) {
// Non-no-arg constructor
if (null == preferredConstructor || constructor.isAnnotationPresent(PersistenceConstructor.class)) {

View File

@@ -1,47 +1,49 @@
package org.springframework.data.persistence;
import org.springframework.dao.DataAccessException;
/**
* Interface to be implemented by classes that can synchronize
* between data stores and ChangeSets.
* @author Rod Johnson
*
* @param <K> entity key
*/
public interface ChangeSetPersister<K> {
String ID_KEY = "_id";
String CLASS_KEY = "_class";
/**
* TODO how to tell when not found? throw exception?
*/
void getPersistentState(Class<? extends ChangeSetBacked> entityClass, K key, ChangeSet changeSet) throws DataAccessException, NotFoundException;
/**
* Return id
* @param cs
* @return
* @throws DataAccessException
*/
K getPersistentId(Class<? extends ChangeSetBacked> entityClass, ChangeSet cs) throws DataAccessException;
/**
* Return key
* @param cs Key may be null if not persistent
* @return
* @throws DataAccessException
*/
K persistState(Class<? extends ChangeSetBacked> entityClass, ChangeSet cs) throws DataAccessException;
/**
* Exception thrown in alternate control flow if getPersistentState
* finds no entity data.
*/
class NotFoundException extends Exception {
}
}
package org.springframework.data.persistence;
import org.springframework.dao.DataAccessException;
/**
* Interface to be implemented by classes that can synchronize
* between data stores and ChangeSets.
* @author Rod Johnson
*
* @param <K> entity key
*/
public interface ChangeSetPersister<K> {
String ID_KEY = "_id";
String CLASS_KEY = "_class";
/**
* TODO how to tell when not found? throw exception?
*/
void getPersistentState(Class<? extends ChangeSetBacked> entityClass, K key, ChangeSet changeSet) throws DataAccessException, NotFoundException;
/**
* Return id
* @param entity
* @param cs
* @return
* @throws DataAccessException
*/
K getPersistentId(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException;
/**
* Return key
* @param entity
* @param cs Key may be null if not persistent
* @return
* @throws DataAccessException
*/
K persistState(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException;
/**
* Exception thrown in alternate control flow if getPersistentState
* finds no entity data.
*/
class NotFoundException extends Exception {
}
}

View File

@@ -115,6 +115,18 @@ public class Property {
return name;
}
/**
* Returns the type of the property will return the plain resolved type for
* simple properties, the component type for any {@link Iterable} or the
* value type of a {@link java.util.Map} if the property is one.
*
* @return
*/
public Class<?> getType() {
return this.type.getType();
}
/**
* Returns the next nested {@link Property}.
@@ -285,7 +297,7 @@ public class Property {
IllegalArgumentException exception = null;
try {
return new Property(source, type);
return new Property(source, type, addTail);
} catch (IllegalArgumentException e) {
exception = e;
}
@@ -299,7 +311,7 @@ public class Property {
String head = source.substring(0, position);
String tail = source.substring(position);
return new Property(head, type, tail + addTail);
return create(head, type, tail + addTail);
}
throw exception;

View File

@@ -190,14 +190,15 @@ public abstract class RepositoryFactorySupport {
protected abstract Class<?> getRepositoryBaseClass(
Class<?> repositoryInterface);
/**
* Returns the {@link QueryLookupStrategy} for the given {@link Key}.
*
* @param key can be {@literal null}
* @return
*/
protected abstract QueryLookupStrategy getQueryLookupStrategy(Key key);
/**
* Returns the {@link QueryLookupStrategy} for the given {@link Key}.
*
* @param key can be {@literal null}
* @return the {@link QueryLookupStrategy} to use or {@literal null} if no queries should be looked up.
*/
protected QueryLookupStrategy getQueryLookupStrategy(Key key) {
return null;
}
/**
@@ -254,6 +255,18 @@ public abstract class RepositoryFactorySupport {
QueryLookupStrategy lookupStrategy =
getQueryLookupStrategy(queryLookupStrategyKey);
if (lookupStrategy == null) {
if (repositoryMetadata.hasCustomMethod()) {
throw new IllegalStateException(
"You have defined query method in the repository but " +
"you don't have no query lookup strategy defined. The " +
"infrastructure apparently does not support query methods!");
}
return;
}
for (Method method : metadata.getQueryMethods()) {
RepositoryQuery query =

View File

@@ -23,7 +23,7 @@ public class ChangeSetBackedTransactionSynchronization implements TransactionSyn
public void afterCommit() {
log.debug("After Commit called for " + entity);
changeSetPersister.persistState(entity.getClass(), entity.getChangeSet());
changeSetPersister.persistState(entity, entity.getChangeSet());
changeSetTxStatus = 0;
}

View File

@@ -16,9 +16,12 @@
package org.springframework.data.domain;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.springframework.data.domain.UnitTestUtils.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Test;
@@ -78,4 +81,22 @@ public class PageImplUnitTests {
new PageImpl<Object>(null, null, 0);
}
@Test
public void createsPageForEmptyContentCorrectly() {
List<String> list = Collections.emptyList();
Page<String> page = new PageImpl<String>(list);
assertThat(page.getContent(), is(list));
assertThat(page.getNumber(), is(0));
assertThat(page.getNumberOfElements(), is(0));
assertThat(page.getSize(), is(0));
assertThat(page.getSort(), is((Sort) null));
assertThat(page.getTotalElements(), is(0L));
assertThat(page.getTotalPages(), is(0));
assertThat(page.hasNextPage(), is(false));
assertThat(page.hasPreviousPage(), is(false));
assertThat(page.isFirstPage(), is(true));
assertThat(page.isLastPage(), is(true));
assertThat(page.hasContent(), is(false));
}
}

View File

@@ -123,6 +123,12 @@ public class PropertyUnitTests {
Property.from("userMapMame", Bar.class);
}
@Test
public void findsNested() {
Property from = Property.from("barUserName", Sample.class);
}
private class Foo {
@@ -146,6 +152,7 @@ public class PropertyUnitTests {
private String userName;
private FooBar user;
private Bar bar;
}
private class Sample2 {

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2011 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.repository.support;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
import org.springframework.data.repository.support.RepositoryFactorySupport.QueryExecuterMethodInterceptor;
/**
* Unit test for {@link QueryExecuterMethodInterceptor}.
*
* @author Oliver Gierke
*/
@RunWith(MockitoJUnitRunner.class)
public class QueryExecuterMethodInterceptorUnitTests {
@Mock
RepositoryFactorySupport factory;
@Mock
RepositoryMetadata metadata;
@Test(expected=IllegalStateException.class)
public void rejectsRepositoryInterfaceWithQueryMethodsIfNoQueryLookupStrategyIsDefined() {
when(metadata.hasCustomMethod()).thenReturn(true);
when(factory.getQueryLookupStrategy(any(Key.class))).thenReturn(null);
factory.new QueryExecuterMethodInterceptor(metadata, null, new Object());
}
@Test
public void skipsQueryLookupsIfQueryLookupStrategyIsNull() {
when(metadata.hasCustomMethod()).thenReturn(false);
when(factory.getQueryLookupStrategy(any(Key.class))).thenReturn(null);
factory.new QueryExecuterMethodInterceptor(metadata, null, new Object());
verify(metadata, times(0)).getQueryMethods();
}
}

View File

@@ -286,6 +286,14 @@
<showDeprecation>false</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<useDefaultManifestFile>true</useDefaultManifestFile>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>