com.buschmais.xo.neo4j.spi.AbstractNeo4jDatastore Maven / Gradle / Ivy
package com.buschmais.xo.neo4j.spi;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Supplier;
import com.buschmais.xo.api.XOException;
import com.buschmais.xo.api.metadata.method.IndexedPropertyMethodMetadata;
import com.buschmais.xo.api.metadata.method.PrimitivePropertyMethodMetadata;
import com.buschmais.xo.api.metadata.type.EntityTypeMetadata;
import com.buschmais.xo.api.metadata.type.TypeMetadata;
import com.buschmais.xo.neo4j.api.model.Neo4jLabel;
import com.buschmais.xo.neo4j.api.model.Neo4jRelationshipType;
import com.buschmais.xo.neo4j.spi.Neo4jDatastoreSession.Index;
import com.buschmais.xo.neo4j.spi.metadata.IndexedPropertyMetadata;
import com.buschmais.xo.neo4j.spi.metadata.NodeMetadata;
import com.buschmais.xo.neo4j.spi.metadata.PropertyMetadata;
import com.buschmais.xo.spi.datastore.DatastoreTransaction;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public abstract class AbstractNeo4jDatastore
implements Neo4jDatastore {
@Override
public void init(Map, TypeMetadata> registeredMetadata) {
Set indexes = new HashSet<>();
for (TypeMetadata typeMetadata : registeredMetadata.values()) {
if (typeMetadata instanceof EntityTypeMetadata) {
EntityTypeMetadata> entityTypeMetadata = (EntityTypeMetadata>) typeMetadata;
// check for indexed property declared in type
Optional labelIndex = getRequiredIndex(entityTypeMetadata, entityTypeMetadata.getIndexedProperty());
labelIndex.ifPresent(index -> indexes.add(index));
// check for inherited indexed property
getRequiredIndex(entityTypeMetadata, entityTypeMetadata.getDatastoreMetadata()
.getUsingIndexedPropertyOf()).ifPresent(index -> indexes.add(index));
}
}
try (DS session = createSession()) {
Set existingIndexes = inTransaction(session, () -> session.getIndexes());
indexes.removeAll(existingIndexes);
inTransaction(session, () -> session.createIndexes(indexes));
log.debug("Detected Neo4j {}.", session.getNeo4jVersion());
}
}
private void inTransaction(DS session, Runnable runnable) {
inTransaction(session, () -> {
runnable.run();
return null;
});
}
private T inTransaction(DS session, Supplier supplier) {
DatastoreTransaction transaction = session.getDatastoreTransaction();
transaction.begin();
try {
T t = supplier.get();
transaction.commit();
return t;
} catch (XOException e) {
transaction.rollback();
throw e;
}
}
/**
* Determines if there's a required index defined for an entity.
*
* @param entityTypeMetadata
* The entity.
* @param indexedProperty
* The index metadata.
*/
private Optional getRequiredIndex(EntityTypeMetadata> entityTypeMetadata,
IndexedPropertyMethodMetadata indexedProperty) {
if (indexedProperty != null) {
L label = entityTypeMetadata.getDatastoreMetadata()
.getDiscriminator();
PrimitivePropertyMethodMetadata propertyMethodMetadata = indexedProperty.getPropertyMethodMetadata();
if (label != null && propertyMethodMetadata != null) {
return Optional.of(Index.builder()
.label(label.getName())
.property(propertyMethodMetadata.getDatastoreMetadata()
.getName())
.build());
}
}
return Optional.empty();
}
}