DATACASS-687 - Polishing.
Adapt unit tests.
This commit is contained in:
@@ -16,8 +16,6 @@
|
||||
package org.springframework.data.cassandra.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -148,7 +146,7 @@ public class CassandraPersistentEntitySchemaCreator {
|
||||
*/
|
||||
protected List<CreateUserTypeSpecification> createUserTypeSpecifications(boolean ifNotExists) {
|
||||
|
||||
Collection<? extends CassandraPersistentEntity<?>> entities = new ArrayList<>(
|
||||
List<? extends CassandraPersistentEntity<?>> entities = new ArrayList<>(
|
||||
this.mappingContext.getUserDefinedTypeEntities());
|
||||
|
||||
Map<CqlIdentifier, CassandraPersistentEntity<?>> byTableName = entities.stream()
|
||||
@@ -158,11 +156,12 @@ public class CassandraPersistentEntitySchemaCreator {
|
||||
UserDefinedTypeSet udts = new UserDefinedTypeSet();
|
||||
|
||||
entities.forEach(entity -> {
|
||||
|
||||
udts.add(entity.getTableName());
|
||||
visitUserTypes(entity, udts);
|
||||
});
|
||||
|
||||
System.out.println(udts.stream().collect(Collectors.toList()));
|
||||
|
||||
specifications
|
||||
.addAll(udts
|
||||
.stream().map(identifier -> this.mappingContext
|
||||
@@ -185,9 +184,8 @@ public class CassandraPersistentEntitySchemaCreator {
|
||||
if (propertyType.isUserDefinedType()) {
|
||||
if (udts.add(propertyType.getTableName())) {
|
||||
visitUserTypes(propertyType, udts);
|
||||
} else {
|
||||
udts.updateDependency(entity.getTableName(), propertyType.getTableName());
|
||||
}
|
||||
udts.addDependency(entity.getTableName(), propertyType.getTableName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -198,12 +196,12 @@ public class CassandraPersistentEntitySchemaCreator {
|
||||
static class UserDefinedTypeSet implements Streamable<CqlIdentifier> {
|
||||
|
||||
private final Set<CqlIdentifier> seen = new HashSet<>();
|
||||
private final List<CqlIdentifier> creationOrder = new ArrayList<>();
|
||||
private final List<DependencyNode> creationOrder = new ArrayList<>();
|
||||
|
||||
public boolean add(CqlIdentifier cqlIdentifier) {
|
||||
|
||||
if (seen.add(cqlIdentifier)) {
|
||||
creationOrder.add(cqlIdentifier);
|
||||
creationOrder.add(new DependencyNode(cqlIdentifier));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -214,30 +212,63 @@ public class CassandraPersistentEntitySchemaCreator {
|
||||
@Override
|
||||
public Iterator<CqlIdentifier> iterator() {
|
||||
|
||||
List<CqlIdentifier> reverseCreationOrder = new ArrayList<>(creationOrder);
|
||||
Collections.reverse(reverseCreationOrder);
|
||||
// Return items in creation order considering dependencies
|
||||
return creationOrder.stream() //
|
||||
.sorted((left, right) -> {
|
||||
|
||||
return reverseCreationOrder.iterator();
|
||||
if (left.dependsOn(right.getIdentifier())) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (right.dependsOn(left.getIdentifier())) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}) //
|
||||
.map(DependencyNode::getIdentifier) //
|
||||
.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the dependency order. {@code referent} depends on {@code reference} and we need to make sure that
|
||||
* {@code referent} gets created after {@code reference}.
|
||||
* <p>
|
||||
* This method therefore updates the dependency order.
|
||||
* Updates the dependency order.
|
||||
*
|
||||
* @param referent the client of {@code reference}.
|
||||
* @param reference the dependency required by {@code referent}.
|
||||
* @param typeToCreate the client of {@code dependsOn}.
|
||||
* @param dependsOn the dependency required by {@code typeToCreate}.
|
||||
*/
|
||||
void updateDependency(CqlIdentifier referent, CqlIdentifier reference) {
|
||||
void addDependency(CqlIdentifier typeToCreate, CqlIdentifier dependsOn) {
|
||||
|
||||
int referentIndex = creationOrder.indexOf(referent);
|
||||
int referenceIndex = creationOrder.indexOf(reference);
|
||||
for (DependencyNode toCreate : creationOrder) {
|
||||
if (toCreate.matches(typeToCreate)) {
|
||||
toCreate.addDependency(dependsOn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (referentIndex > referenceIndex) {
|
||||
static class DependencyNode {
|
||||
|
||||
creationOrder.remove(referent);
|
||||
creationOrder.add(referenceIndex, referent);
|
||||
private final CqlIdentifier identifier;
|
||||
private final List<CqlIdentifier> dependsOn = new ArrayList<>();
|
||||
|
||||
DependencyNode(CqlIdentifier identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public CqlIdentifier getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
boolean matches(CqlIdentifier typeToCreate) {
|
||||
return identifier.equals(typeToCreate);
|
||||
}
|
||||
|
||||
void addDependency(CqlIdentifier dependsOn) {
|
||||
this.dependsOn.add(dependsOn);
|
||||
|
||||
}
|
||||
|
||||
boolean dependsOn(CqlIdentifier identifier) {
|
||||
return this.dependsOn.contains(identifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,15 +22,15 @@ import static org.mockito.Mockito.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.springframework.data.cassandra.core.cql.CqlIdentifier;
|
||||
@@ -113,7 +113,20 @@ public class CassandraPersistentEntitySchemaCreatorUnitTests extends CassandraPe
|
||||
@Test // DATACASS-406
|
||||
public void createsCorrectTypeForSets() {
|
||||
|
||||
context.getPersistentEntity(PlanetType.class);
|
||||
List<Class<?>> ordered = new ArrayList<>(Arrays.asList(UniverseType.class, PlanetType.class, MoonType.class));
|
||||
|
||||
Collections.shuffle(ordered); // catch ordering issues
|
||||
context = new CassandraMappingContext() {
|
||||
@Override
|
||||
public Collection<CassandraPersistentEntity<?>> getUserDefinedTypeEntities() {
|
||||
return ordered.stream().map(this::getRequiredPersistentEntity).collect(Collectors.toList());
|
||||
}
|
||||
};
|
||||
context.setUserTypeResolver(typeName -> {
|
||||
// make sure that calls to this method pop up. Calling UserTypeResolver while resolving
|
||||
// to be created user types isn't a good idea because they do not exist at resolution time.
|
||||
throw new IllegalArgumentException(String.format("Type %s not found", typeName));
|
||||
});
|
||||
|
||||
CassandraPersistentEntitySchemaCreator schemaCreator = new CassandraPersistentEntitySchemaCreator(context,
|
||||
adminOperations);
|
||||
@@ -168,10 +181,15 @@ public class CassandraPersistentEntitySchemaCreatorUnitTests extends CassandraPe
|
||||
|
||||
private void verifyTypesGetCreatedInOrderFor(String... typenames) {
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(operations);
|
||||
ArgumentCaptor<String> cql = ArgumentCaptor.forClass(String.class);
|
||||
|
||||
for (String typename : typenames) {
|
||||
inOrder.verify(operations).execute(Mockito.contains("CREATE TYPE " + typename));
|
||||
verify(operations, atLeast(typenames.length)).execute(cql.capture());
|
||||
|
||||
List<String> allValues = cql.getAllValues();
|
||||
|
||||
for (int i = 0; i < typenames.length; i++) {
|
||||
assertThat(allValues.get(i)).describedAs("Actual: " + allValues + ", expected: " + Arrays.toString(typenames))
|
||||
.contains("CREATE TYPE " + typenames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user