Search in sources :

Example 11 with Type

use of com.yahoo.elide.core.type.Type in project elide by yahoo.

the class GraphQLConversionUtils method attributeToQueryObject.

/**
 * Helper function which converts an attribute of an entity to a GraphQL Query Type.
 * @param parentClass The parent entity class (Can either be an elide entity or not).
 * @param attributeClass The attribute class.
 * @param attribute The name of the attribute.
 * @param fetcher The data fetcher to associated with the newly created GraphQL Query Type
 *
 * @return A GraphQL Query Type (either newly created or singleton instance for class) or
 *         null if the underlying type cannot be converted.
 */
protected GraphQLOutputType attributeToQueryObject(Type<?> parentClass, Type<?> attributeClass, String attribute, DataFetcher fetcher, EntityDictionary dictionary) {
    /* Determine if we've already processed this item. */
    if (outputConversions.containsKey(attributeClass)) {
        return outputConversions.get(attributeClass);
    }
    if (enumConversions.containsKey(attributeClass)) {
        return enumConversions.get(attributeClass);
    }
    /* We don't support Class */
    if (ClassType.CLASS_TYPE.isAssignableFrom(attributeClass)) {
        return null;
    }
    /* If the attribute is a map */
    if (ClassType.MAP_TYPE.isAssignableFrom(attributeClass)) {
        /* Extract the key and value types */
        Type<?> keyType = dictionary.getParameterizedType(parentClass, attribute, 0);
        Type<?> valueType = dictionary.getParameterizedType(parentClass, attribute, 1);
        return classToQueryMap(keyType, valueType, fetcher);
    /* If the attribute is a collection */
    } else if (ClassType.COLLECTION_TYPE.isAssignableFrom(attributeClass)) {
        /* Extract the collection type */
        Type<?> listType = dictionary.getParameterizedType(parentClass, attribute, 0);
        // If this is a collection of a boxed type scalar, we want to unwrap it properly
        return new GraphQLList(fetchScalarOrObjectOutput(listType, fetcher));
    }
    return fetchScalarOrObjectOutput(attributeClass, fetcher);
}
Also used : GraphQLList(graphql.schema.GraphQLList) GraphQLInputObjectType(graphql.schema.GraphQLInputObjectType) GraphQLScalarType(graphql.schema.GraphQLScalarType) ClassType(com.yahoo.elide.core.type.ClassType) GraphQLObjectType(graphql.schema.GraphQLObjectType) GraphQLInputType(graphql.schema.GraphQLInputType) GraphQLOutputType(graphql.schema.GraphQLOutputType) Type(com.yahoo.elide.core.type.Type) GraphQLEnumType(graphql.schema.GraphQLEnumType)

Example 12 with Type

use of com.yahoo.elide.core.type.Type in project elide by yahoo.

the class MultiplexManager method populateEntityDictionary.

@Override
public void populateEntityDictionary(EntityDictionary dictionary) {
    this.dictionary = dictionary;
    for (DataStore dataStore : dataStores) {
        EntityDictionary subordinateDictionary = new EntityDictionary(dictionary.getCheckMappings(), dictionary.getRoleChecks(), dictionary.getInjector(), dictionary.getSerdeLookup(), dictionary.getEntitiesToExclude(), dictionary.getScanner());
        dataStore.populateEntityDictionary(subordinateDictionary);
        for (EntityBinding binding : subordinateDictionary.getBindings(false)) {
            // route class to this database manager
            this.dataStoreMap.put(binding.entityClass, dataStore);
            // bind to multiplex dictionary
            dictionary.bindEntity(binding);
        }
        for (Map.Entry<Type<?>, Function<RequestScope, PermissionExecutor>> entry : subordinateDictionary.getEntityPermissionExecutor().entrySet()) {
            dictionary.bindPermissionExecutor(entry.getKey(), entry.getValue());
        }
    }
}
Also used : Function(java.util.function.Function) Type(com.yahoo.elide.core.type.Type) DataStore(com.yahoo.elide.core.datastore.DataStore) EntityBinding(com.yahoo.elide.core.dictionary.EntityBinding) EntityDictionary(com.yahoo.elide.core.dictionary.EntityDictionary) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Map(java.util.Map)

Example 13 with Type

use of com.yahoo.elide.core.type.Type in project elide by yahoo.

the class ModelBuilder method build.

/**
 * Builds a GraphQL schema.
 * @return The built schema.
 */
public GraphQLSchema build() {
    Set<Type<?>> allClasses = entityDictionary.getBoundClassesByVersion(apiVersion);
    if (allClasses.isEmpty()) {
        throw new IllegalArgumentException("None of the provided classes are exported by Elide");
    }
    Set<Type<?>> rootClasses = allClasses.stream().filter(entityDictionary::isRoot).collect(Collectors.toSet());
    /*
         * Walk the object graph (avoiding cycles) and construct the GraphQL input object types.
         */
    entityDictionary.walkEntityGraph(rootClasses, this::buildInputObjectStub);
    /* Construct root object */
    GraphQLObjectType.Builder root = newObject().name(OBJECT_QUERY);
    for (Type<?> clazz : rootClasses) {
        String entityName = entityDictionary.getJsonAliasFor(clazz);
        root.field(newFieldDefinition().name(entityName).description(EntityDictionary.getEntityDescription(clazz)).argument(relationshipOpArg).argument(idArgument).argument(filterArgument).argument(sortArgument).argument(pageFirstArgument).argument(pageOffsetArgument).argument(buildInputObjectArgument(clazz, true)).arguments(generator.entityArgumentToQueryObject(clazz, entityDictionary)).type(buildConnectionObject(clazz)));
    }
    GraphQLObjectType queryRoot = root.build();
    GraphQLObjectType mutationRoot = root.name(OBJECT_MUTATION).build();
    objectTypes.add(queryRoot);
    objectTypes.add(mutationRoot);
    /*
         * Walk the object graph (avoiding cycles) and construct the GraphQL output object types.
         */
    entityDictionary.walkEntityGraph(rootClasses, this::buildConnectionObject);
    GraphQLCodeRegistry.Builder codeRegistry = GraphQLCodeRegistry.newCodeRegistry();
    objectTypes.addAll(generator.getObjectTypes());
    for (GraphQLObjectType objectType : objectTypes) {
        String objectName = objectType.getName();
        for (GraphQLFieldDefinition fieldDefinition : objectType.getFieldDefinitions()) {
            codeRegistry.dataFetcher(FieldCoordinates.coordinates(objectName, fieldDefinition.getName()), dataFetcher);
        }
    }
    /* Construct the schema */
    GraphQLSchema schema = GraphQLSchema.newSchema().query(queryRoot).mutation(mutationRoot).codeRegistry(codeRegistry.build()).additionalTypes(new HashSet<>(CollectionUtils.union(connectionObjectRegistry.values(), inputObjectRegistry.values()))).build();
    return schema;
}
Also used : GraphQLInputObjectType(graphql.schema.GraphQLInputObjectType) GraphQLType(graphql.schema.GraphQLType) ClassType(com.yahoo.elide.core.type.ClassType) GraphQLObjectType(graphql.schema.GraphQLObjectType) GraphQLInputType(graphql.schema.GraphQLInputType) GraphQLOutputType(graphql.schema.GraphQLOutputType) Type(com.yahoo.elide.core.type.Type) RelationshipType(com.yahoo.elide.core.dictionary.RelationshipType) GraphQLObjectType(graphql.schema.GraphQLObjectType) GraphQLCodeRegistry(graphql.schema.GraphQLCodeRegistry) GraphQLFieldDefinition(graphql.schema.GraphQLFieldDefinition) GraphQLSchema(graphql.schema.GraphQLSchema) HashSet(java.util.HashSet)

Example 14 with Type

use of com.yahoo.elide.core.type.Type in project elide by yahoo.

the class PersistentResourceFetcher method fetchRelationship.

/**
 * Fetches a relationship for a top-level entity.
 *
 * @param parentResource Parent object
 * @param relationship constructed relationship object with entityProjection
 * @param ids List of ids
 * @return persistence resource object(s)
 */
public static ConnectionContainer fetchRelationship(PersistentResource<?> parentResource, @NotNull Relationship relationship, Optional<List<String>> ids) {
    EntityDictionary dictionary = parentResource.getRequestScope().getDictionary();
    Type relationshipClass = dictionary.getParameterizedType(parentResource.getObject(), relationship.getName());
    String relationshipType = dictionary.getJsonAliasFor(relationshipClass);
    Set<PersistentResource> relationResources;
    if (ids.isPresent()) {
        relationResources = parentResource.getRelation(ids.get(), relationship).toList(LinkedHashSet::new).blockingGet();
    } else {
        relationResources = parentResource.getRelationCheckedFiltered(relationship).toList(LinkedHashSet::new).blockingGet();
    }
    return new ConnectionContainer(relationResources, Optional.ofNullable(relationship.getProjection().getPagination()), relationshipType);
}
Also used : LinkedHashSet(java.util.LinkedHashSet) PersistentResource(com.yahoo.elide.core.PersistentResource) ClassType(com.yahoo.elide.core.type.ClassType) Type(com.yahoo.elide.core.type.Type) ConnectionContainer(com.yahoo.elide.graphql.containers.ConnectionContainer) EntityDictionary(com.yahoo.elide.core.dictionary.EntityDictionary)

Example 15 with Type

use of com.yahoo.elide.core.type.Type in project elide by yahoo.

the class PersistentResource method loadRecords.

/**
 * Load a collection from the datastore.
 *
 * @param projection   the projection to load
 * @param requestScope the request scope
 * @param ids          a list of object identifiers to optionally load.  Can be empty.
 * @return a filtered collection of resources loaded from the datastore.
 */
public static Observable<PersistentResource> loadRecords(EntityProjection projection, List<String> ids, RequestScope requestScope) {
    Type<?> loadClass = projection.getType();
    Pagination pagination = projection.getPagination();
    Sorting sorting = projection.getSorting();
    FilterExpression filterExpression = projection.getFilterExpression();
    EntityDictionary dictionary = requestScope.getDictionary();
    DataStoreTransaction tx = requestScope.getTransaction();
    if (shouldSkipCollection(loadClass, ReadPermission.class, requestScope, projection.getRequestedFields())) {
        if (ids.isEmpty()) {
            return Observable.empty();
        }
        throw new InvalidObjectIdentifierException(ids.toString(), dictionary.getJsonAliasFor(loadClass));
    }
    Set<String> requestedFields = projection.getRequestedFields();
    if (pagination != null && !pagination.isDefaultInstance() && !CanPaginateVisitor.canPaginate(loadClass, dictionary, requestScope, requestedFields)) {
        throw new BadRequestException(String.format("Cannot paginate %s", dictionary.getJsonAliasFor(loadClass)));
    }
    Set<PersistentResource> newResources = new LinkedHashSet<>();
    if (!ids.isEmpty()) {
        String typeAlias = dictionary.getJsonAliasFor(loadClass);
        newResources = requestScope.getNewPersistentResources().stream().filter(resource -> typeAlias.equals(resource.getTypeName()) && ids.contains(resource.getUUID().orElse(""))).collect(Collectors.toSet());
        FilterExpression idExpression = buildIdFilterExpression(ids, loadClass, dictionary, requestScope);
        // Combine filters if necessary
        filterExpression = Optional.ofNullable(filterExpression).map(fe -> (FilterExpression) new AndFilterExpression(idExpression, fe)).orElse(idExpression);
    }
    Optional<FilterExpression> permissionFilter = getPermissionFilterExpression(loadClass, requestScope, requestedFields);
    if (permissionFilter.isPresent()) {
        if (filterExpression != null) {
            filterExpression = new AndFilterExpression(filterExpression, permissionFilter.get());
        } else {
            filterExpression = permissionFilter.get();
        }
    }
    EntityProjection modifiedProjection = projection.copyOf().filterExpression(filterExpression).sorting(sorting).pagination(pagination).build();
    Observable<PersistentResource> existingResources = filter(ReadPermission.class, Optional.ofNullable(modifiedProjection.getFilterExpression()), projection.getRequestedFields(), Observable.fromIterable(new PersistentResourceSet(tx.loadObjects(modifiedProjection, requestScope), requestScope)));
    // TODO: Sort again in memory now that two sets are glommed together?
    Observable<PersistentResource> allResources = Observable.fromIterable(newResources).mergeWith(existingResources);
    Set<String> foundIds = new HashSet<>();
    allResources = allResources.doOnNext((resource) -> {
        String id = (String) resource.getUUID().orElseGet(resource::getId);
        if (ids.contains(id)) {
            foundIds.add(id);
        }
    });
    allResources = allResources.doOnComplete(() -> {
        Set<String> missedIds = Sets.difference(new HashSet<>(ids), foundIds);
        if (!missedIds.isEmpty()) {
            throw new InvalidObjectIdentifierException(missedIds.toString(), dictionary.getJsonAliasFor(loadClass));
        }
    });
    return allResources;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Resource(com.yahoo.elide.jsonapi.models.Resource) Data(com.yahoo.elide.jsonapi.models.Data) StringUtils(org.apache.commons.lang3.StringUtils) UpdatePermission(com.yahoo.elide.annotation.UpdatePermission) ClassType(com.yahoo.elide.core.type.ClassType) DeletePermission(com.yahoo.elide.annotation.DeletePermission) Argument(com.yahoo.elide.core.request.Argument) InvalidSyntaxException(com.yahoo.elide.core.audit.InvalidSyntaxException) Map(java.util.Map) DataStoreIterable(com.yahoo.elide.core.datastore.DataStoreIterable) LifeCycleHookBinding(com.yahoo.elide.annotation.LifeCycleHookBinding) EntityBinding(com.yahoo.elide.core.dictionary.EntityBinding) NonNull(lombok.NonNull) Collection(java.util.Collection) Set(java.util.Set) CoerceUtil(com.yahoo.elide.core.utils.coerce.CoerceUtil) Collectors(java.util.stream.Collectors) EntityDictionary(com.yahoo.elide.core.dictionary.EntityDictionary) Sets(com.google.common.collect.Sets) Serializable(java.io.Serializable) Objects(java.util.Objects) ExpressionResult(com.yahoo.elide.core.security.permissions.ExpressionResult) List(java.util.List) Annotation(java.lang.annotation.Annotation) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression) Optional(java.util.Optional) RelationshipType(com.yahoo.elide.core.dictionary.RelationshipType) Attribute(com.yahoo.elide.core.request.Attribute) InvalidAttributeException(com.yahoo.elide.core.exceptions.InvalidAttributeException) Function(java.util.function.Function) Supplier(java.util.function.Supplier) CollectionUtils(org.apache.commons.collections4.CollectionUtils) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) IterableUtils(org.apache.commons.collections4.IterableUtils) LogMessageImpl(com.yahoo.elide.core.audit.LogMessageImpl) DELETE(com.yahoo.elide.annotation.LifeCycleHookBinding.Operation.DELETE) EntityDictionary.getType(com.yahoo.elide.core.dictionary.EntityDictionary.getType) JsonIgnore(com.fasterxml.jackson.annotation.JsonIgnore) Predicates(com.google.common.base.Predicates) InternalServerErrorException(com.yahoo.elide.core.exceptions.InternalServerErrorException) CanPaginateVisitor(com.yahoo.elide.core.security.visitors.CanPaginateVisitor) Observable(io.reactivex.Observable) LogMessage(com.yahoo.elide.core.audit.LogMessage) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) LinkedHashSet(java.util.LinkedHashSet) UPDATE(com.yahoo.elide.annotation.LifeCycleHookBinding.Operation.UPDATE) DataStoreTransaction(com.yahoo.elide.core.datastore.DataStoreTransaction) VerifyFieldAccessFilterExpressionVisitor(com.yahoo.elide.core.filter.visitors.VerifyFieldAccessFilterExpressionVisitor) ChangeSpec(com.yahoo.elide.core.security.ChangeSpec) COLLECTION_TYPE(com.yahoo.elide.core.type.ClassType.COLLECTION_TYPE) Sorting(com.yahoo.elide.core.request.Sorting) InvalidEntityBodyException(com.yahoo.elide.core.exceptions.InvalidEntityBodyException) InvalidObjectIdentifierException(com.yahoo.elide.core.exceptions.InvalidObjectIdentifierException) InPredicate(com.yahoo.elide.core.filter.predicates.InPredicate) EntityProjection(com.yahoo.elide.core.request.EntityProjection) Relationship(com.yahoo.elide.jsonapi.models.Relationship) ForbiddenAccessException(com.yahoo.elide.core.exceptions.ForbiddenAccessException) ReadPermission(com.yahoo.elide.annotation.ReadPermission) BadRequestException(com.yahoo.elide.core.exceptions.BadRequestException) Pagination(com.yahoo.elide.core.request.Pagination) ResourceIdentifier(com.yahoo.elide.jsonapi.models.ResourceIdentifier) TreeMap(java.util.TreeMap) CreatePermission(com.yahoo.elide.annotation.CreatePermission) CREATE(com.yahoo.elide.annotation.LifeCycleHookBinding.Operation.CREATE) Type(com.yahoo.elide.core.type.Type) Preconditions(com.google.common.base.Preconditions) Comparator(java.util.Comparator) Collections(java.util.Collections) EMPTY_BINDING(com.yahoo.elide.core.dictionary.EntityBinding.EMPTY_BINDING) Audit(com.yahoo.elide.annotation.Audit) NonTransferable(com.yahoo.elide.annotation.NonTransferable) EntityProjection(com.yahoo.elide.core.request.EntityProjection) Set(java.util.Set) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) Sorting(com.yahoo.elide.core.request.Sorting) Pagination(com.yahoo.elide.core.request.Pagination) DataStoreTransaction(com.yahoo.elide.core.datastore.DataStoreTransaction) BadRequestException(com.yahoo.elide.core.exceptions.BadRequestException) InvalidObjectIdentifierException(com.yahoo.elide.core.exceptions.InvalidObjectIdentifierException) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) EntityDictionary(com.yahoo.elide.core.dictionary.EntityDictionary) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Aggregations

Type (com.yahoo.elide.core.type.Type)35 EntityDictionary (com.yahoo.elide.core.dictionary.EntityDictionary)22 Set (java.util.Set)17 List (java.util.List)16 Map (java.util.Map)16 ClassType (com.yahoo.elide.core.type.ClassType)15 Function (java.util.function.Function)14 FilterExpression (com.yahoo.elide.core.filter.expression.FilterExpression)13 Annotation (java.lang.annotation.Annotation)12 Collectors (java.util.stream.Collectors)12 Collection (java.util.Collection)11 ReadPermission (com.yahoo.elide.annotation.ReadPermission)10 ArrayList (java.util.ArrayList)10 HashSet (java.util.HashSet)10 DataStoreTransaction (com.yahoo.elide.core.datastore.DataStoreTransaction)9 Optional (java.util.Optional)9 RequestScope (com.yahoo.elide.core.RequestScope)8 Objects (java.util.Objects)8 Path (com.yahoo.elide.core.Path)7 RelationshipType (com.yahoo.elide.core.dictionary.RelationshipType)7