use of org.neo4j.ogm.metadata.ClassInfo in project neo4j-ogm by neo4j.
the class EntityGraphMapper method updateNode.
/**
* Creates a new node or updates an existing one in the graph, if it has changed.
*
* @param entity the domain object to be persisted
* @param context the current {@link CompileContext}
* @param nodeBuilder a {@link NodeBuilder} that knows how to compile node create/update cypher phrases
*/
private void updateNode(Object entity, CompileContext context, NodeBuilder nodeBuilder) {
// fire pre-save event here
if (mappingContext.isDirty(entity)) {
LOGGER.debug("{} has changed", entity);
context.register(entity);
ClassInfo classInfo = metaData.classInfo(entity);
updateFieldsOnBuilder(entity, nodeBuilder, classInfo);
} else {
context.deregister(nodeBuilder);
LOGGER.debug("{}, has not changed", entity);
}
}
use of org.neo4j.ogm.metadata.ClassInfo in project neo4j-ogm by neo4j.
the class GraphEntityMapper method createRelationshipEntity.
private Object createRelationshipEntity(Edge edge, Object startEntity, Object endEntity) {
ClassInfo relationClassInfo = getRelationshipEntity(edge);
if (relationClassInfo == null) {
throw new MappingException("Could not find a class to map for relation " + edge);
}
Map<String, Object> allProps = new HashMap<>(toMap(edge.getPropertyList()));
getCompositeProperties(edge.getPropertyList(), relationClassInfo).forEach((k, v) -> {
allProps.put(k.getName(), v);
});
// also add start and end node as valid constructor values
allProps.put(relationClassInfo.getStartNodeReader().getName(), startEntity);
allProps.put(relationClassInfo.getEndNodeReader().getName(), endEntity);
// create and hydrate the new RE
Object relationshipEntity = entityFactory.newObject(relationClassInfo.getUnderlyingClass(), allProps);
EntityUtils.setIdentity(relationshipEntity, edge.getId(), metadata);
// REs also have properties
setProperties(edge.getPropertyList(), relationshipEntity);
// register it in the mapping context
mappingContext.addRelationshipEntity(relationshipEntity, edge.getId());
// set the start and end entities
ClassInfo relEntityInfo = metadata.classInfo(relationshipEntity);
FieldInfo startNodeWriter = relEntityInfo.getStartNodeReader();
if (startNodeWriter != null) {
startNodeWriter.write(relationshipEntity, startEntity);
} else {
throw new RuntimeException("Cannot find a writer for the StartNode of relational entity " + relEntityInfo.name());
}
FieldInfo endNodeWriter = relEntityInfo.getEndNodeReader();
if (endNodeWriter != null) {
endNodeWriter.write(relationshipEntity, endEntity);
} else {
throw new RuntimeException("Cannot find a writer for the EndNode of relational entity " + relEntityInfo.name());
}
return relationshipEntity;
}
use of org.neo4j.ogm.metadata.ClassInfo in project neo4j-ogm by neo4j.
the class GraphEntityMapper method mapOneToMany.
/**
* Map many values to an instance based on the relationship type.
* See DATAGRAPH-637
*
* @param instance the instance to map values onto
* @param valueType the type of each value
* @param values the values to map
* @param relationshipType the relationship type associated with these values
*/
private void mapOneToMany(Object instance, Class<?> valueType, Object values, String relationshipType, Direction relationshipDirection) {
ClassInfo classInfo = metadata.classInfo(instance);
FieldInfo writer = EntityAccessManager.getIterableField(classInfo, valueType, relationshipType, relationshipDirection);
if (writer != null) {
if (writer.type().isArray() || Iterable.class.isAssignableFrom(writer.type())) {
FieldInfo reader = EntityAccessManager.getIterableField(classInfo, valueType, relationshipType, relationshipDirection);
Object currentValues;
if (reader != null) {
currentValues = reader.read(instance);
if (writer.type().isArray()) {
values = EntityAccessManager.merge(writer.type(), values, (Object[]) currentValues, valueType);
} else {
values = EntityAccessManager.merge(writer.type(), values, (Collection) currentValues, valueType);
}
}
}
writer.write(instance, values);
return;
}
// this is not necessarily an error. but we can't tell.
logger.debug("Unable to map iterable of type: {} onto property of {}", valueType, classInfo.name());
}
use of org.neo4j.ogm.metadata.ClassInfo in project neo4j-ogm by neo4j.
the class GraphEntityMapper method getRelationshipEntity.
// Find the correct RE associated with the edge. The edge type may be polymorphic, so we need to do a bit of work
// to identify the correct RE to bind to. We must not cache the value when found, because the correct determination
// depends on the runtime values of the edge in the mapping context, which may vary for the same edge pattern.
private ClassInfo getRelationshipEntity(Edge edge) {
Object source = mappingContext.getNodeEntity(edge.getStartNode());
Object target = mappingContext.getNodeEntity(edge.getEndNode());
Set<ClassInfo> classInfos = metadata.classInfoByLabelOrType(edge.getType());
for (ClassInfo classInfo : classInfos) {
// both source and target must be declared as START and END nodes respectively
if (!nodeTypeMatches(classInfo, source, StartNode.class)) {
continue;
}
if (!nodeTypeMatches(classInfo, target, EndNode.class)) {
continue;
}
// if the source OR the target (or one of their superclasses) declares the relationship
// back to the relationshipEntityClass, we've found a match
Class relationshipEntityClass = classInfo.getUnderlyingClass();
if (declaresRelationshipTo(relationshipEntityClass, source.getClass(), edge.getType(), Direction.OUTGOING)) {
return classInfo;
}
if (declaresRelationshipTo(relationshipEntityClass, target.getClass(), edge.getType(), Direction.INCOMING)) {
return classInfo;
}
}
// the right one, otherwise ... give up
if (classInfos.size() == 1) {
ClassInfo classInfo = classInfos.iterator().next();
if (nodeTypeMatches(classInfo, source, StartNode.class) && nodeTypeMatches(classInfo, target, EndNode.class)) {
return classInfo;
}
} else {
if (classInfos.size() == 0) {
// not necessarily a problem, we mey be fetching edges we don't want to hydrate
if (logger.isDebugEnabled()) {
logger.debug("Unable to find a matching @RelationshipEntity for {}", edge.toString());
}
} else {
// almost definitely a user bug
logger.error("Found more than one matching @RelationshipEntity for {} but cannot tell which one to use", edge.toString());
}
}
return null;
}
use of org.neo4j.ogm.metadata.ClassInfo in project neo4j-ogm by neo4j.
the class GraphEntityMapper method setLabels.
private void setLabels(Node nodeModel, Object instance) {
ClassInfo classInfo = metadata.classInfo(instance);
FieldInfo labelFieldInfo = classInfo.labelFieldOrNull();
if (labelFieldInfo != null) {
Collection<String> staticLabels = classInfo.staticLabels();
Set<String> dynamicLabels = new HashSet<>();
for (String label : nodeModel.getLabels()) {
if (!staticLabels.contains(label)) {
dynamicLabels.add(label);
}
}
writeProperty(classInfo, instance, PropertyModel.with(labelFieldInfo.getName(), dynamicLabels));
}
}
Aggregations