Search in sources :

Example 1 with DirectedRelationshipForType

use of org.neo4j.ogm.context.DirectedRelationshipForType in project neo4j-ogm by neo4j.

the class EntityAccessManager method getIterableField.

/**
 * Returns an FieldWriter for an iterable of a non-primitive scalar type defined by a ClassInfo
 *
 * @param classInfo             the ClassInfo (or a superclass thereof) declaring the iterable relationship
 * @param relationshipType      the name of the relationship as it is in the graph
 * @param relationshipDirection the direction of the relationship as it is in the graph
 * @param parameterType         the type that will be iterated over
 * @return a valid FieldWriter or null if none is found
 */
public static FieldInfo getIterableField(ClassInfo classInfo, Class<?> parameterType, String relationshipType, Direction relationshipDirection) {
    final ClassInfo lookupClassInfo = classInfo;
    final DirectedRelationshipForType directedRelationshipForType = new DirectedRelationshipForType(relationshipType, relationshipDirection, parameterType);
    final Map<DirectedRelationshipForType, FieldInfo> typeFieldInfoMap = iterableWriterCache.computeIfAbsent(lookupClassInfo, key -> new ConcurrentHashMap<>());
    if (typeFieldInfoMap.containsKey(directedRelationshipForType)) {
        return typeFieldInfoMap.get(directedRelationshipForType);
    }
    while (classInfo != null) {
        // 1st find a field annotated with type and direction
        FieldInfo fieldInfo = getIterableFieldInfo(classInfo, parameterType, relationshipType, relationshipDirection, STRICT_MODE);
        if (fieldInfo != null) {
            cacheIterableFieldWriter(lookupClassInfo, parameterType, relationshipType, relationshipDirection, directedRelationshipForType, fieldInfo, fieldInfo);
            return fieldInfo;
        }
        if (relationshipDirection != Direction.INCOMING) {
            // 3rd, find a field with implied type and direction
            fieldInfo = getIterableFieldInfo(classInfo, parameterType, relationshipType, relationshipDirection, INFERRED_MODE);
            if (fieldInfo != null) {
                cacheIterableFieldWriter(lookupClassInfo, parameterType, relationshipType, relationshipDirection, directedRelationshipForType, fieldInfo, fieldInfo);
                return fieldInfo;
            }
        }
        classInfo = classInfo.directSuperclass();
    }
    return null;
}
Also used : DirectedRelationshipForType(org.neo4j.ogm.context.DirectedRelationshipForType) FieldInfo(org.neo4j.ogm.metadata.FieldInfo) ClassInfo(org.neo4j.ogm.metadata.ClassInfo)

Example 2 with DirectedRelationshipForType

use of org.neo4j.ogm.context.DirectedRelationshipForType in project neo4j-ogm by neo4j.

the class EntityAccessManager method getRelationalWriter.

/**
 * Returns a FieldWriter for a scalar type on a ClassInfo that is not a primitive graph property
 *
 * @param classInfo             the ClassInfo (or a superclass thereof) declaring the relationship
 * @param relationshipType      the name of the relationship as it is in the graph
 * @param relationshipDirection the direction of the relationship as it is in the graph
 * @param objectType            the class the relationship is defined for
 * @return a valid FieldWriter or null if none is found
 */
public static FieldInfo getRelationalWriter(ClassInfo classInfo, String relationshipType, Direction relationshipDirection, Class<?> objectType) {
    final DirectedRelationshipForType directedRelationship = new DirectedRelationshipForType(relationshipType, relationshipDirection, objectType);
    final Map<DirectedRelationshipForType, FieldInfo> typeFieldInfoMap = relationalWriterCache.computeIfAbsent(classInfo, key -> new ConcurrentHashMap<>());
    if (typeFieldInfoMap.containsKey(directedRelationship)) {
        return typeFieldInfoMap.get(directedRelationship);
    }
    while (classInfo != null) {
        // 1st, try to find a scalar or vector field explicitly annotated as the neo4j relationship type and direction
        for (FieldInfo fieldInfo : classInfo.candidateRelationshipFields(relationshipType, relationshipDirection, STRICT_MODE)) {
            if (fieldInfo != null && !fieldInfo.getAnnotations().isEmpty()) {
                if (fieldInfo.isTypeOf(objectType) || fieldInfo.isParameterisedTypeOf(objectType) || fieldInfo.isArrayOf(objectType)) {
                    typeFieldInfoMap.put(directedRelationship, fieldInfo);
                    return fieldInfo;
                }
            }
        }
        // If it's outgoing, then proceed to find other matches
        if (relationshipDirection != Direction.INCOMING) {
            // 2nd, try to find a scalar or vector field annotated as the neo4j relationship type and direction, allowing for implied relationships
            final Set<FieldInfo> candidateRelationshipFields = classInfo.candidateRelationshipFields(relationshipType, relationshipDirection, INFERRED_MODE);
            for (FieldInfo fieldInfo : candidateRelationshipFields) {
                if (fieldInfo != null && !fieldInfo.getAnnotations().isEmpty()) {
                    if (fieldInfo.isTypeOf(objectType) || fieldInfo.isParameterisedTypeOf(objectType) || fieldInfo.isArrayOf(objectType)) {
                        typeFieldInfoMap.put(directedRelationship, fieldInfo);
                        return fieldInfo;
                    }
                }
            }
            // 3rd, try to find a "XYZ" field name where XYZ is derived from the relationship type
            for (FieldInfo fieldInfo : candidateRelationshipFields) {
                if (fieldInfo != null) {
                    if (fieldInfo.isTypeOf(objectType) || fieldInfo.isParameterisedTypeOf(objectType) || fieldInfo.isArrayOf(objectType)) {
                        typeFieldInfoMap.put(directedRelationship, fieldInfo);
                        return fieldInfo;
                    }
                }
            }
            // 4th, try to find a unique field that has the same type as the parameter
            List<FieldInfo> fieldInfos = classInfo.findFields(objectType);
            if (fieldInfos.size() == 1) {
                FieldInfo candidateField = fieldInfos.iterator().next();
                if (candidateField.relationshipDirectionOrDefault(Direction.UNDIRECTED) != Direction.INCOMING) {
                    if (candidateField.relationshipTypeAnnotation() == null) {
                        typeFieldInfoMap.put(directedRelationship, candidateField);
                        return candidateField;
                    }
                }
            }
        }
        // walk up the object hierarchy
        classInfo = classInfo.directSuperclass();
    }
    return null;
}
Also used : DirectedRelationshipForType(org.neo4j.ogm.context.DirectedRelationshipForType) FieldInfo(org.neo4j.ogm.metadata.FieldInfo)

Aggregations

DirectedRelationshipForType (org.neo4j.ogm.context.DirectedRelationshipForType)2 FieldInfo (org.neo4j.ogm.metadata.FieldInfo)2 ClassInfo (org.neo4j.ogm.metadata.ClassInfo)1