DATACASS-85 - Completed

Unit test on ordering and Verifier
Fixed bug with CassandraPersistentPropertyComparator
This commit is contained in:
David T Webb
2014-02-11 16:42:19 -05:00
parent 5be12f407d
commit c91a70b942
4 changed files with 207 additions and 50 deletions

View File

@@ -22,10 +22,10 @@ public enum CassandraPersistentPropertyComparator implements Comparator<Cassandr
public int compare(CassandraPersistentProperty left, CassandraPersistentProperty right) {
if (left != null && right == null) {
return -1;
return 1;
}
if (left == null && right != null) {
return 1;
return -1;
}
if (left == null && right == null) {
return 0;
@@ -57,11 +57,11 @@ public enum CassandraPersistentPropertyComparator implements Comparator<Cassandr
boolean rightIsKey = rightIsCompositePrimaryKey || rightIsPrimaryKey;
if (leftIsKey && !rightIsKey) {
return 1;
return -1;
}
if (!leftIsKey && rightIsKey) {
return -1;
return 1;
}
// else, neither property is a composite primary key nor a primary key; compare @Column annotations

View File

@@ -109,6 +109,7 @@ public class DefaultCassandraPersistentEntityMetadataVerifier implements Cassand
for (CassandraPersistentProperty p : primaryKeyColumns) {
if (p.getField().getAnnotation(PrimaryKeyColumn.class).type() == PrimaryKeyType.PARTITIONED) {
partitionKeyExists = true;
break;
}
}
if (!partitionKeyExists) {
@@ -121,7 +122,7 @@ public class DefaultCassandraPersistentEntityMetadataVerifier implements Cassand
*/
if (idProperties.size() > 0) {
exceptions.add(new MappingException(
"Annotations @Id and @PrimaryKey are invalid for type annoated as @PrimaryKeyClass"));
"Annotations @Id and @PrimaryKey are invalid for type annotated with @PrimaryKeyClass"));
}
/*
@@ -136,14 +137,7 @@ public class DefaultCassandraPersistentEntityMetadataVerifier implements Cassand
/*
* Ensure PrimaryKeyClass is Serializable
*/
Class<?>[] interfaces = thisType.getInterfaces();
boolean isTypeSerializable = false;
for (Class<?> c : interfaces) {
if (c.equals(Serializable.class)) {
isTypeSerializable = true;
}
}
if (!isTypeSerializable) {
if (!Serializable.class.isAssignableFrom(thisType)) {
exceptions.add(new MappingException("@PrimaryKeyClass must be Serializable"));
}
@@ -163,7 +157,8 @@ public class DefaultCassandraPersistentEntityMetadataVerifier implements Cassand
throw new NoSuchMethodException();
}
} catch (NoSuchMethodException e) {
exceptions.add(new MappingException("@PrimaryKeyClass must override 'boolean equals(Object)' method"));
exceptions.add(new MappingException(
"@PrimaryKeyClass must override 'boolean equals(Object)' method and use all @PrimaryKeyColumn fields", e));
}
/*
@@ -175,8 +170,10 @@ public class DefaultCassandraPersistentEntityMetadataVerifier implements Cassand
throw new NoSuchMethodException();
}
} catch (NoSuchMethodException e) {
exceptions.add(new MappingException("@PrimaryKeyClass must override 'int hashCode()' method"));
exceptions.add(new MappingException(
"@PrimaryKeyClass must override 'int hashCode()' method and use all @PrimaryKeyColumn fields", e));
}
}
/*
@@ -185,35 +182,29 @@ public class DefaultCassandraPersistentEntityMetadataVerifier implements Cassand
if (isTable) {
/*
* Ensure at least 1 PK
* Ensure only one PK
*/
if (idProperties.size() == 0 && compositePrimaryKeys.size() == 0) {
exceptions.add(new MappingException("@Table/@Persistent types must have at least 1 @PrimaryKey attribute"));
}
/*
* Ensure no more than 1 PK
*/
if (idProperties.size() + compositePrimaryKeys.size() > 1) {
exceptions.add(new MappingException("@Table/@Persistent must have only 1 @PrimaryKey attribute"));
int idPropertyCount = idProperties.size();
if (idPropertyCount != 1) {
exceptions.add(new MappingException(String.format(
"@Table/@Persistent types must have only one @PrimaryKey attribute. Found %s.", idPropertyCount)));
}
/*
* Ensure that Id is a supported Type. At the point there is only 1.
*/
if (idProperties.size() == 1) {
Class<?> typeClass = idProperties.get(0).getType();
if (!typeClass.isAnnotationPresent(PrimaryKeyClass.class)
&& CassandraSimpleTypeHolder.getDataTypeFor(typeClass) == null) {
exceptions.add(new MappingException("Fields annotated with @PrimaryKey must be simple CassandraTypes"));
}
Class<?> typeClass = idProperties.get(0).getType();
if (!typeClass.isAnnotationPresent(PrimaryKeyClass.class)
&& CassandraSimpleTypeHolder.getDataTypeFor(typeClass) == null) {
exceptions.add(new MappingException(
"Fields annotated with @PrimaryKey must be simple CassandraTypes or @PrimaryKeyClass type"));
}
}
/*
* Determine whether or not to throw Exception based on errors found
*/
if (exceptions.getErrorCount() > 0) {
if (exceptions.getCount() > 0) {
throw exceptions;
}
}

View File

@@ -29,8 +29,7 @@ import org.springframework.data.mapping.model.MappingException;
*/
public class VerifierMappingExceptions extends MappingException {
Collection<String> messages = new LinkedList<String>();
Collection<MappingException> errors = new LinkedList<MappingException>();
Collection<MappingException> exceptions = new LinkedList<MappingException>();
/**
* @param s
@@ -43,16 +42,7 @@ public class VerifierMappingExceptions extends MappingException {
* @param s
*/
public void add(MappingException e) {
messages.add(e.getMessage());
errors.add(e);
}
/**
* @param s
*/
public void add(String s, MappingException e) {
messages.add(s);
errors.add(e);
exceptions.add(e);
}
/**
@@ -61,7 +51,7 @@ public class VerifierMappingExceptions extends MappingException {
* @return The Collection of MappingException
*/
public Collection<MappingException> getMappingExceptions() {
return errors;
return exceptions;
}
/**
@@ -69,7 +59,11 @@ public class VerifierMappingExceptions extends MappingException {
*
* @return The Collection of Messages
*/
public Collection<String> getMappingExceptionMessages() {
public Collection<String> getMessages() {
Collection<String> messages = new LinkedList<String>();
for (MappingException e : exceptions) {
messages.add(e.getMessage());
}
return messages;
}
@@ -78,15 +72,15 @@ public class VerifierMappingExceptions extends MappingException {
*
* @return Number of Errors present
*/
public int getErrorCount() {
return errors.size();
public int getCount() {
return exceptions.size();
}
@Override
public String getMessage() {
StringBuilder builder = new StringBuilder();
for (String s : messages) {
builder.append(s).append("\n");
for (MappingException e : exceptions) {
builder.append(e.getMessage()).append("\n");
}
return builder.toString();
}

View File

@@ -0,0 +1,172 @@
/*
* Copyright 2011-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.cassandra.test.unit;
import static org.junit.Assert.assertEquals;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.data.annotation.Id;
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
import org.springframework.data.cassandra.mapping.DefaultCassandraMappingContext;
import org.springframework.data.cassandra.mapping.PrimaryKey;
import org.springframework.data.cassandra.mapping.PrimaryKeyClass;
import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
import org.springframework.data.cassandra.mapping.Table;
import org.springframework.data.mapping.PropertyHandler;
/**
* @author David Webb
*
*/
public class BasicCassandraPersistentEntityOrderPropertiesTest {
private List<CassandraPersistentProperty> expected;
private DefaultCassandraMappingContext mappingContext = new DefaultCassandraMappingContext();
@Before
public void init() {
}
@Test
public void testCompositeKeyPropertyOrder() {
CassandraPersistentEntity<?> entity = mappingContext.getPersistentEntity(CompositePK.class);
expected = new LinkedList<CassandraPersistentProperty>();
expected.add(entity.getPersistentProperty("key0"));
expected.add(entity.getPersistentProperty("key1"));
expected.add(entity.getPersistentProperty("key2"));
final List<CassandraPersistentProperty> actual = new LinkedList<CassandraPersistentProperty>();
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
@Override
public void doWithPersistentProperty(CassandraPersistentProperty persistentProperty) {
actual.add(persistentProperty);
}
});
assertEquals(expected, actual);
}
@Test
public void testTablePropertyOrder() {
CassandraPersistentEntity<?> entity = mappingContext.getPersistentEntity(CompositeKeyEntity.class);
expected = new LinkedList<CassandraPersistentProperty>();
expected.add(entity.getPersistentProperty("key"));
expected.add(entity.getPersistentProperty("attribute"));
expected.add(entity.getPersistentProperty("text"));
final List<CassandraPersistentProperty> actual = new LinkedList<CassandraPersistentProperty>();
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
@Override
public void doWithPersistentProperty(CassandraPersistentProperty persistentProperty) {
actual.add(persistentProperty);
}
});
assertEquals(expected, actual);
}
@Table
static class CompositeKeyEntity {
@PrimaryKey
private CompositePK key;
private String attribute;
private String text;
}
/**
* This is intentionally using dumb ordinals
*/
@PrimaryKeyClass
static class CompositePK implements Serializable {
@PrimaryKeyColumn(ordinal = 2, type = PrimaryKeyType.PARTITIONED)
private String key0;
@PrimaryKeyColumn(ordinal = 0)
private String key1;
@PrimaryKeyColumn(ordinal = 1)
private String key2;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((key0 == null) ? 0 : key0.hashCode());
result = prime * result + ((key1 == null) ? 0 : key1.hashCode());
result = prime * result + ((key2 == null) ? 0 : key2.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CompositePK other = (CompositePK) obj;
if (key0 == null) {
if (other.key0 != null)
return false;
} else if (!key0.equals(other.key0))
return false;
if (key1 == null) {
if (other.key1 != null)
return false;
} else if (!key1.equals(other.key1))
return false;
if (key2 == null) {
if (other.key2 != null)
return false;
} else if (!key2.equals(other.key2))
return false;
return true;
}
}
@Table
static class SimpleKeyEntity {
@Id
private String id;
}
}