Package com.buschmais.cdo.impl.metadata

Source Code of com.buschmais.cdo.impl.metadata.EntityTypeMetadataResolver

package com.buschmais.cdo.impl.metadata;

import com.buschmais.cdo.spi.datastore.DatastoreEntityMetadata;
import com.buschmais.cdo.spi.datastore.TypeMetadataSet;
import com.buschmais.cdo.spi.metadata.type.EntityTypeMetadata;
import com.buschmais.cdo.spi.metadata.type.TypeMetadata;
import com.buschmais.cdo.spi.reflection.AnnotatedType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
* Allows resolving types from entity discriminators as provided by the datastores.
*
* @param <Discriminator> The discriminator type of the datastore (e.g. Neo4j labels or strings for JSON stores).
*/
public class EntityTypeMetadataResolver<EntityMetadata extends DatastoreEntityMetadata<Discriminator>, Discriminator> {

    private static final Logger LOGGER = LoggerFactory.getLogger(EntityTypeMetadataResolver.class);

    private final Map<EntityTypeMetadata<EntityMetadata>, Set<Discriminator>> aggregatedDiscriminators = new HashMap<>();
    private final Map<Discriminator, Set<EntityTypeMetadata<EntityMetadata>>> typeMetadataByDiscriminator = new HashMap<>();

    /**
     * Constructor.
     *
     * @param metadataByType A map of all types with their metadata.
     */
    public EntityTypeMetadataResolver(Map<Class<?>, TypeMetadata> metadataByType) {
        LOGGER.debug("Type metadata = '{}'", metadataByType);
        for (TypeMetadata typeMetadata : metadataByType.values()) {
            if (typeMetadata instanceof EntityTypeMetadata) {
                Set<Discriminator> discriminators = getAggregatedDiscriminators((EntityTypeMetadata<EntityMetadata>) typeMetadata);
                LOGGER.debug("Aggregated discriminators of '{}' = '{}'", typeMetadata, discriminators);
            }
        }
        for (TypeMetadata typeMetadata : metadataByType.values()) {
            if (typeMetadata instanceof EntityTypeMetadata) {
                Set<Discriminator> discriminators = aggregatedDiscriminators.get(typeMetadata);
                for (Discriminator discriminator : discriminators) {
                    Set<EntityTypeMetadata<EntityMetadata>> entityTypeMetadataOfDiscriminator = typeMetadataByDiscriminator.get(discriminator);
                    if (entityTypeMetadataOfDiscriminator == null) {
                        entityTypeMetadataOfDiscriminator = new HashSet<>();
                        typeMetadataByDiscriminator.put(discriminator, entityTypeMetadataOfDiscriminator);
                    }
                    entityTypeMetadataOfDiscriminator.add((EntityTypeMetadata<EntityMetadata>) typeMetadata);
                }
            }
        }
        LOGGER.debug("Type metadata by discriminators: '{}'", typeMetadataByDiscriminator);
    }

    /**
     * Determine the set of discriminators for one type, i.e. the discriminator of the type itself and of all it's super types.
     *
     * @param typeMetadata The type.
     * @return The set of discriminators.
     */
    private Set<Discriminator> getAggregatedDiscriminators(EntityTypeMetadata<EntityMetadata> typeMetadata) {
        Set<Discriminator> discriminators = aggregatedDiscriminators.get(typeMetadata);
        if (discriminators == null) {
            discriminators = new HashSet<>();
            Discriminator discriminator = typeMetadata.getDatastoreMetadata().getDiscriminator();
            if (discriminator != null) {
                discriminators.add(discriminator);
            }
            for (TypeMetadata superTypeMetadata : typeMetadata.getSuperTypes()) {
                if (superTypeMetadata instanceof EntityTypeMetadata) {
                    discriminators.addAll(getAggregatedDiscriminators((EntityTypeMetadata<EntityMetadata>) superTypeMetadata));
                }
            }
            aggregatedDiscriminators.put(typeMetadata, discriminators);
        }
        return discriminators;
    }

    /**
     * Return a {@link com.buschmais.cdo.spi.datastore.TypeMetadataSet} containing all types matching to the given entity discriminators.
     *
     * @param discriminators The discriminators.
     * @return The {@link com.buschmais.cdo.spi.datastore.TypeMetadataSet}.
     */
    public TypeMetadataSet<EntityTypeMetadata<EntityMetadata>> getTypes(Set<Discriminator> discriminators) {
        // Get all types matching the discriminators
        Set<EntityTypeMetadata<EntityMetadata>> allEntityTypeMetadatas = new HashSet<>();
        for (Discriminator discriminator : discriminators) {
            Set<EntityTypeMetadata<EntityMetadata>> entityTypeMetadataOfDiscriminator = typeMetadataByDiscriminator.get(discriminator);
            if (entityTypeMetadataOfDiscriminator != null) {
                for (EntityTypeMetadata<EntityMetadata> entityTypeMetadata : entityTypeMetadataOfDiscriminator) {
                    if (discriminators.containsAll(aggregatedDiscriminators.get(entityTypeMetadata))) {
                        allEntityTypeMetadatas.add(entityTypeMetadata);
                    }
                }
            }
        }
        // remove all super types if their sub types are already contained in the type set
        TypeMetadataSet<EntityTypeMetadata<EntityMetadata>> uniqueTypes = new TypeMetadataSet();
        for (EntityTypeMetadata<EntityMetadata> entityTypeMetadata : allEntityTypeMetadatas) {
            AnnotatedType annotatedType = entityTypeMetadata.getAnnotatedType();
            boolean subtype = false;
            for (Iterator<EntityTypeMetadata<EntityMetadata>> subTypeIterator = allEntityTypeMetadatas.iterator(); subTypeIterator.hasNext() && !subtype; ) {
                AnnotatedType otherAnnotatedType = subTypeIterator.next().getAnnotatedType();
                if (!annotatedType.equals(otherAnnotatedType) && annotatedType.getAnnotatedElement().isAssignableFrom(otherAnnotatedType.getAnnotatedElement())) {
                    subtype = true;
                }
            }
            if (!subtype) {
                uniqueTypes.add(entityTypeMetadata);
            }
        }
        return uniqueTypes;
    }

    public Set<Discriminator> getDiscriminators(EntityTypeMetadata<EntityMetadata> entityTypeMetadata) {
        Set<Discriminator> discriminators = aggregatedDiscriminators.get(entityTypeMetadata);
        return discriminators != null ? discriminators : Collections.<Discriminator>emptySet();
    }

}
TOP

Related Classes of com.buschmais.cdo.impl.metadata.EntityTypeMetadataResolver

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.