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

io.devbench.uibuilder.data.common.parse.annotation.IdAnnotationParser Maven / Gradle / Ivy

/*
 *
 * Copyright © 2018 Webvalto Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.devbench.uibuilder.data.common.parse.annotation;

import io.devbench.uibuilder.core.controllerbean.uiproperty.PropertyConverters;
import io.devbench.uibuilder.core.utils.reflection.ClassMetadata;
import io.devbench.uibuilder.core.utils.reflection.PropertyMetadata;

import javax.persistence.Id;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class IdAnnotationParser {

    private static final Map, Set> CACHE = new ConcurrentHashMap<>();

    public static Set getIdPropertyPathsFromClass(Class clazz) {
        CACHE.putIfAbsent(clazz, collectIdPaths(clazz));
        return CACHE.get(clazz);
    }

    private static Set collectIdPaths(Class clazz) {
        Set idSet = getIdFieldsPropertyMetadataStream(clazz)
            .flatMap(field -> getIdPropertyPathsRecursively(field, new ArrayList<>()))
            .collect(Collectors.toSet());

        if (idSet.isEmpty()) {
            throw new EntityIdNotFoundException("The class [" + clazz + "] does not contain any field annotated with the @Id annotation.");
        }

        return idSet;
    }

    private static Stream> getIdFieldsPropertyMetadataStream(Class clazz) {
        return ClassMetadata
            .ofClass(clazz)
            .getProperties()
            .stream()
            .filter(property -> property.isAnnotationPresent(Id.class));
    }

    private static Stream getIdPropertyPathsRecursively(PropertyMetadata field, List> alreadyVisitedProperties) {
        if (PropertyConverters.IMPLICIT_CONVERTERS.containsKey(field.getType())) {
            return Stream.of(calculatePropertyPath(copyListWith(alreadyVisitedProperties, field)));
        } else {
            if (alreadyVisitedProperties.contains(field)) {
                throw new IllegalIdPropertyPathRecursionException(alreadyVisitedProperties);
            }

            List> visitedPropertiesWithCurrentOne = copyListWith(alreadyVisitedProperties, field);

            return
                getIdFieldsPropertyMetadataStream(field.getType())
                    .flatMap(it -> getIdPropertyPathsRecursively(it, visitedPropertiesWithCurrentOne));
        }
    }

    private static List> copyListWith(List> alreadyVisitedProperties, PropertyMetadata field) {
        List> copiedList = new ArrayList<>(alreadyVisitedProperties);
        copiedList.add(field);
        return copiedList;
    }

    private static String calculatePropertyPath(List> visitedProperties) {
        return visitedProperties
            .stream()
            .map(PropertyMetadata::getName)
            .collect(Collectors.joining("."));
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy