All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jnosql.mapping.graph.EntityConverterByField Maven / Gradle / Ivy

There is a newer version: 1.1.3
Show newest version
/*
 *  Copyright (c) 2023 Contributors to the Eclipse Foundation
 *   All rights reserved. This program and the accompanying materials
 *   are made available under the terms of the Eclipse Public License v1.0
 *   and Apache License v2.0 which accompanies this distribution.
 *   The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
 *   and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php.
 *
 *   You may elect to redistribute this code under either of these licenses.
 *
 *   Contributors:
 *
 *   Otavio Santana
 */
package org.eclipse.jnosql.mapping.graph;

import org.apache.tinkerpop.gremlin.structure.Property;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.eclipse.jnosql.communication.Value;
import org.eclipse.jnosql.mapping.AttributeConverter;
import org.eclipse.jnosql.mapping.core.Converters;
import org.eclipse.jnosql.mapping.metadata.ConstructorMetadata;
import org.eclipse.jnosql.mapping.metadata.EntitiesMetadata;
import org.eclipse.jnosql.mapping.metadata.EntityMetadata;
import org.eclipse.jnosql.mapping.metadata.FieldMetadata;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;

import static org.eclipse.jnosql.mapping.metadata.MappingType.EMBEDDED;

final class EntityConverterByField implements Supplier {
    private final List> elements;
    private final EntityMetadata mapping;
    private final T instance;
    private final Vertex vertex;

    private final Converters converters;

    private final EntitiesMetadata entities;


    private EntityConverterByField(List> elements, EntityMetadata mapping,
                                   T instance, Vertex vertex, Converters converters,
                                   EntitiesMetadata entities) {
        this.elements = elements;
        this.mapping = mapping;
        this.instance = instance;
        this.vertex = vertex;
        this.converters = converters;
        this.entities = entities;
    }

    @Override
    public T get() {
        Map fieldsGroupByName = mapping.fieldsGroupByName();
        List names = elements.stream()
                .map(Property::key)
                .sorted()
                .toList();
        Predicate existField = k -> Collections.binarySearch(names, k) >= 0;

        fieldsGroupByName.keySet().stream()
                .filter(existField.or(k -> EMBEDDED.equals(fieldsGroupByName.get(k).mappingType())))
                .forEach(feedObject(instance, elements, fieldsGroupByName, vertex));

        feedId(vertex, instance);
        return instance;
    }

    private Consumer feedObject(T instance, List> elements,
                                            Map fieldsGroupByName,
                                            Vertex vertex) {
        return k -> {
            Optional> element = elements
                    .stream()
                    .filter(c -> c.key().equals(k))
                    .findFirst();

            FieldMetadata field = fieldsGroupByName.get(k);
            if (EMBEDDED.equals(field.mappingType())) {
                embeddedField(instance, elements, field, vertex);
            } else {
                element.ifPresent(e -> singleField(instance, e, field));
            }
        };
    }

    private void embeddedField(T instance, List> elements,
                               FieldMetadata field, Vertex vertex) {
        Class type = (Class) field.type();
        field.write(instance, convert(type, elements, vertex));
    }

    private  void singleField(T instance, Property element, FieldMetadata field) {
        Object value = element.value();
        Optional>> converter = field.converter();
        if (converter.isPresent()) {
            AttributeConverter attributeConverter = converters().get(field);
            Object attributeConverted = attributeConverter.convertToEntityAttribute((Y) value);
            field.write(instance, field.value(Value.of(attributeConverted)));
        } else {
            field.write(instance, field.value(Value.of(value)));
        }
    }

    private T convert(Class type, List> properties, Vertex vertex) {
        EntityMetadata mapping = entities().get(type);
        ConstructorMetadata constructor = mapping.constructor();
        if (constructor.isDefault()) {
            T instance = mapping.newInstance();
            T entity = convertEntity(properties, mapping, instance, vertex);
            feedId(vertex, entity);
            return entity;
        } else {
            EntityConverterByContructor supplier = EntityConverterByContructor.of(mapping, vertex,
                    converters());
            return supplier.get();
        }
    }

    private void feedId(Vertex vertex, T entity) {
        EntityMetadata mapping = entities.get(entity.getClass());
        Optional id = mapping.id();


        Object vertexId = vertex.id();
        if (Objects.nonNull(vertexId) && id.isPresent()) {
            FieldMetadata fieldMetadata = id.get();
            fieldMetadata.converter().ifPresentOrElse(c -> {
                AttributeConverter attributeConverter = converters.get(fieldMetadata);
                Object attributeConverted = attributeConverter.convertToEntityAttribute(vertexId);
                fieldMetadata.write(entity, fieldMetadata.value(Value.of(attributeConverted)));
            }, () -> fieldMetadata.write(entity, fieldMetadata.value(Value.of(vertexId))));
        }
    }

    private T convertEntity(List> elements, EntityMetadata mapping, T instance, Vertex vertex) {

        Map fieldsGroupByName = mapping.fieldsGroupByName();
        List names = elements.stream()
                .map(Property::key)
                .sorted()
                .toList();
        Predicate existField = k -> Collections.binarySearch(names, k) >= 0;

        fieldsGroupByName.keySet().stream()
                .filter(existField.or(k -> EMBEDDED.equals(fieldsGroupByName.get(k).mappingType())))
                .forEach(feedObject(instance, elements, fieldsGroupByName, vertex));

        return instance;
    }

    private Converters converters() {
        return converters;
    }

    private EntitiesMetadata entities() {
        return entities;
    }

    static  EntityConverterByField of(List> elements, EntityMetadata mapping,
                                            T instance, Vertex vertex, Converters converters,
                                            EntitiesMetadata entities){
        return new EntityConverterByField<>(elements, mapping, instance, vertex, converters, entities);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy