Search in sources :

Example 1 with ServiceErrorSchema

use of com.linkedin.restli.restspec.ServiceErrorSchema in project rest.li by linkedin.

the class ServiceErrorGatheringVisitor method checkServiceErrors.

/**
 * Given a record which includes {@link ServiceErrorsSchema}, collects all the defined service errors and returns
 * true if any service errors are encountered.
 *
 * @param record record which includes {@link ServiceErrorsSchema}
 * @param isResourceLevel true if checking from the context of a resource
 * @return true if any service error is encountered
 */
private boolean checkServiceErrors(RecordTemplate record, boolean isResourceLevel) {
    final ServiceErrorsSchema serviceErrorsSchema = new ServiceErrorsSchema(record.data());
    if (serviceErrorsSchema.hasServiceErrors()) {
        final Map<String, ServiceErrorSchema> serviceErrorMap = serviceErrorsSchema.getServiceErrors().stream().collect(Collectors.toMap(ServiceErrorSchema::getCode, Function.identity()));
        _serviceErrors.putAll(serviceErrorMap);
        if (isResourceLevel) {
            _resourceLevelServiceErrors.putAll(serviceErrorMap);
        }
        return true;
    }
    return false;
}
Also used : ServiceErrorsSchema(com.linkedin.restli.restspec.ServiceErrorsSchema) ServiceErrorSchema(com.linkedin.restli.restspec.ServiceErrorSchema)

Example 2 with ServiceErrorSchema

use of com.linkedin.restli.restspec.ServiceErrorSchema in project rest.li by linkedin.

the class ResourceModelEncoder method buildServiceErrors.

/**
 * Given a list of service errors, returns a service error schema array record.
 *
 * @param serviceErrors list of service errors to build, assumed to be non-null and non-empty
 * @return service error schema array
 */
private ServiceErrorSchemaArray buildServiceErrors(final List<ServiceError> serviceErrors) {
    final ServiceErrorSchemaArray serviceErrorSchemaArray = new ServiceErrorSchemaArray();
    // For each service error, build a service error schema and append it to the service error schema array
    for (ServiceError serviceError : serviceErrors) {
        ServiceErrorSchema serviceErrorSchema = new ServiceErrorSchema().setStatus(serviceError.httpStatus().getCode()).setCode(serviceError.code());
        final String message = serviceError.message();
        if (message != null) {
            serviceErrorSchema.setMessage(message);
        }
        final Class<?> errorDetailType = serviceError.errorDetailType();
        if (errorDetailType != null) {
            serviceErrorSchema.setErrorDetailType(errorDetailType.getCanonicalName());
        }
        if (serviceError instanceof ParametersServiceError) {
            final String[] parameterNames = ((ParametersServiceError) serviceError).parameterNames();
            if (parameterNames != null && parameterNames.length != 0) {
                serviceErrorSchema.setParameters(new StringArray(Arrays.asList(parameterNames)));
            }
        }
        serviceErrorSchemaArray.add(serviceErrorSchema);
    }
    return serviceErrorSchemaArray;
}
Also used : ParametersServiceError(com.linkedin.restli.server.errors.ParametersServiceError) ServiceError(com.linkedin.restli.server.errors.ServiceError) ParametersServiceError(com.linkedin.restli.server.errors.ParametersServiceError) StringArray(com.linkedin.data.template.StringArray) ServiceErrorSchema(com.linkedin.restli.restspec.ServiceErrorSchema) ServiceErrorSchemaArray(com.linkedin.restli.restspec.ServiceErrorSchemaArray)

Example 3 with ServiceErrorSchema

use of com.linkedin.restli.restspec.ServiceErrorSchema in project rest.li by linkedin.

the class SnapshotGenerator method findErrorDetailTypeModels.

/**
 * For a given record that includes the {@link ServiceErrorsSchema} record, keep track of all referenced
 * error detail type models.
 *
 * @param schema record that includes the {@link ServiceErrorsSchema}
 * @param foundTypes running mapping of found data schemas
 * @param typeOrder running, ordered list of found data schemas
 */
private void findErrorDetailTypeModels(RecordTemplate schema, Map<String, NamedDataSchema> foundTypes, List<NamedDataSchema> typeOrder) {
    // Wrap the underlying data map in the shared schema interface
    final ServiceErrorsSchema serviceErrorsSchema = new ServiceErrorsSchema(schema.data());
    // For each service error, inspect its error detail type field and keep track of all referenced types
    final ServiceErrorSchemaArray serviceErrorSchemaArray = serviceErrorsSchema.getServiceErrors();
    if (serviceErrorSchemaArray != null) {
        for (ServiceErrorSchema serviceErrorSchema : serviceErrorSchemaArray) {
            if (serviceErrorSchema.hasErrorDetailType()) {
                recordType(serviceErrorSchema.getErrorDetailType(), foundTypes, typeOrder);
            }
        }
    }
}
Also used : ServiceErrorsSchema(com.linkedin.restli.restspec.ServiceErrorsSchema) ServiceErrorSchema(com.linkedin.restli.restspec.ServiceErrorSchema) ServiceErrorSchemaArray(com.linkedin.restli.restspec.ServiceErrorSchemaArray)

Example 4 with ServiceErrorSchema

use of com.linkedin.restli.restspec.ServiceErrorSchema in project rest.li by linkedin.

the class ResourceCompatibilityChecker method checkMethodServiceErrors.

/**
 * Checks the compatibility of method-level service errors. All service error compatibility logic is checked
 * semantically at the method level, so this method takes the union of the resource-level errors (from the context)
 * and the method-level errors to compute the compatibility.
 *
 * @param prevMethodServiceErrors previous method-level service errors
 * @param currMethodServiceErrors current method-level service errors
 */
private void checkMethodServiceErrors(RecordDataSchema.Field field, ServiceErrorSchemaArray prevMethodServiceErrors, ServiceErrorSchemaArray currMethodServiceErrors) {
    assert field != null;
    _infoPath.push(field.getName());
    // Compute the union of resource and method service errors separately for previous and current
    TreeResourceContext state = _resourceContexts.peek();
    Map<String, ServiceErrorSchema> prevServiceErrorUnion = getServiceErrorUnion(state._prevResourceLevelErrors, prevMethodServiceErrors);
    Map<String, ServiceErrorSchema> currServiceErrorUnion = getServiceErrorUnion(state._currResourceLevelErrors, currMethodServiceErrors);
    // Compute the union of resource and method service errors for both previous and current together
    Set<String> serviceErrorCodeUnion = new HashSet<>();
    serviceErrorCodeUnion.addAll(prevServiceErrorUnion.keySet());
    serviceErrorCodeUnion.addAll(currServiceErrorUnion.keySet());
    // Compute the intersection and both complementary subsets of previous and current service error codes
    Set<String> serviceErrorCodeIntersection = new HashSet<>();
    Set<String> removedServiceErrorCodes = new HashSet<>();
    Set<String> newServiceErrorCodes = new HashSet<>();
    for (String code : serviceErrorCodeUnion) {
        if (prevServiceErrorUnion.containsKey(code) && currServiceErrorUnion.containsKey(code)) {
            serviceErrorCodeIntersection.add(code);
        } else if (prevServiceErrorUnion.containsKey(code)) {
            removedServiceErrorCodes.add(code);
        } else {
            newServiceErrorCodes.add(code);
        }
    }
    // Check to ensure that retained service errors are compatible
    for (String code : serviceErrorCodeIntersection) {
        ServiceErrorSchema prevServiceErrorSchema = prevServiceErrorUnion.get(code);
        ServiceErrorSchema currServiceErrorSchema = currServiceErrorUnion.get(code);
        _infoPath.push(code);
        checkServiceErrorSchema(prevServiceErrorSchema, currServiceErrorSchema);
        _infoPath.pop();
    }
    // Add info about removed service errors
    for (String code : removedServiceErrorCodes) {
        _infoMap.addRestSpecInfo(CompatibilityInfo.Type.SERVICE_ERROR_REMOVED, _infoPath, code);
    }
    // Add info about new service errors
    for (String code : newServiceErrorCodes) {
        _infoMap.addRestSpecInfo(CompatibilityInfo.Type.SERVICE_ERROR_ADDED, _infoPath, code);
    }
    _infoPath.pop();
}
Also used : ServiceErrorSchema(com.linkedin.restli.restspec.ServiceErrorSchema) HashSet(java.util.HashSet)

Example 5 with ServiceErrorSchema

use of com.linkedin.restli.restspec.ServiceErrorSchema in project rest.li by linkedin.

the class RestLiResourceRelationship method findDataModels.

private void findDataModels() {
    final ResourceSchemaVisitior visitor = new BaseResourceSchemaVisitor() {

        @Override
        public void visitResourceSchema(VisitContext visitContext, ResourceSchema resourceSchema) {
            final String schema = resourceSchema.getSchema();
            // ActionSet resources do not have a schema
            if (schema != null) {
                final NamedDataSchema schemaSchema = extractSchema(schema);
                if (schemaSchema != null) {
                    connectSchemaToResource(visitContext, schemaSchema);
                }
            }
        }

        @Override
        public void visitCollectionResource(VisitContext visitContext, CollectionSchema collectionSchema) {
            connectErrorDetailTypeToResource(visitContext, collectionSchema);
            final IdentifierSchema id = collectionSchema.getIdentifier();
            final NamedDataSchema typeSchema = extractSchema(id.getType());
            if (typeSchema != null) {
                connectSchemaToResource(visitContext, typeSchema);
            }
            final String params = id.getParams();
            if (params != null) {
                final NamedDataSchema paramsSchema = extractSchema(params);
                if (paramsSchema != null) {
                    connectSchemaToResource(visitContext, paramsSchema);
                }
            }
        }

        @Override
        public void visitAssociationResource(VisitContext visitContext, AssociationSchema associationSchema) {
            connectErrorDetailTypeToResource(visitContext, associationSchema);
            for (AssocKeySchema key : associationSchema.getAssocKeys()) {
                final NamedDataSchema keyTypeSchema = extractSchema(key.getType());
                if (keyTypeSchema != null) {
                    connectSchemaToResource(visitContext, keyTypeSchema);
                }
            }
        }

        @Override
        public void visitSimpleResource(VisitContext visitContext, SimpleSchema simpleSchema) {
            connectErrorDetailTypeToResource(visitContext, simpleSchema);
        }

        @Override
        public void visitActionSetResource(VisitContext visitContext, ActionsSetSchema actionSetSchema) {
            connectErrorDetailTypeToResource(visitContext, actionSetSchema);
        }

        @Override
        public void visitParameter(VisitContext visitContext, RecordTemplate parentResource, Object parentMethodSchema, ParameterSchema parameterSchema) {
            String parameterTypeString = parameterSchema.getType();
            if (// the parameter type field contains a inline schema, so we traverse into it
            isInlineSchema(parameterTypeString)) {
                visitInlineSchema(visitContext, parameterTypeString);
            } else {
                final NamedDataSchema schema;
                // grab the schema name from it
                if (parameterSchema.hasItems()) {
                    schema = extractSchema(parameterSchema.getItems());
                } else // the only remaining possibility is that the type field contains the name of a data schema
                {
                    schema = extractSchema(parameterTypeString);
                }
                if (schema != null) {
                    connectSchemaToResource(visitContext, schema);
                }
            }
        }

        @Override
        public void visitRestMethod(VisitContext visitContext, RecordTemplate parentResource, RestMethodSchema restMethodSchema) {
            connectErrorDetailTypeToResource(visitContext, restMethodSchema);
        }

        @Override
        public void visitFinder(VisitContext visitContext, RecordTemplate parentResource, FinderSchema finderSchema) {
            connectErrorDetailTypeToResource(visitContext, finderSchema);
            final MetadataSchema metadata = finderSchema.getMetadata();
            if (metadata != null) {
                final NamedDataSchema metadataTypeSchema = extractSchema(metadata.getType());
                if (metadataTypeSchema != null) {
                    connectSchemaToResource(visitContext, metadataTypeSchema);
                }
            }
        }

        @Override
        public void visitBatchFinder(VisitContext visitContext, RecordTemplate parentResource, BatchFinderSchema batchFinderSchema) {
            connectErrorDetailTypeToResource(visitContext, batchFinderSchema);
            final MetadataSchema metadata = batchFinderSchema.getMetadata();
            if (metadata != null) {
                final NamedDataSchema metadataTypeSchema = extractSchema(metadata.getType());
                if (metadataTypeSchema != null) {
                    connectSchemaToResource(visitContext, metadataTypeSchema);
                }
            }
        }

        @Override
        public void visitAction(VisitContext visitContext, RecordTemplate parentResource, ResourceLevel resourceLevel, ActionSchema actionSchema) {
            connectErrorDetailTypeToResource(visitContext, actionSchema);
            final String returns = actionSchema.getReturns();
            if (returns != null) {
                if (// the parameter type field contains a inline schema, so we traverse into it
                isInlineSchema(returns)) {
                    visitInlineSchema(visitContext, returns);
                } else // otherwise the type field contains the name of a data schema
                {
                    final NamedDataSchema returnsSchema = extractSchema(returns);
                    if (returnsSchema != null) {
                        connectSchemaToResource(visitContext, returnsSchema);
                    }
                }
            }
            final StringArray throwsArray = actionSchema.getThrows();
            if (throwsArray != null) {
                for (String errorName : throwsArray) {
                    final NamedDataSchema errorSchema = extractSchema(errorName);
                    if (errorSchema != null) {
                        connectSchemaToResource(visitContext, errorSchema);
                    }
                }
            }
        }

        private boolean isInlineSchema(String schemaString) {
            return schemaString.startsWith("{");
        }

        private void visitInlineSchema(VisitContext visitContext, String schemaString) {
            DataSchema schema = DataTemplateUtil.parseSchema(schemaString, _schemaResolver, SchemaFormatType.PDSC);
            if (schema instanceof ArrayDataSchema) {
                DataSchema itemSchema = ((ArrayDataSchema) schema).getItems();
                if (itemSchema instanceof NamedDataSchema) {
                    connectSchemaToResource(visitContext, (NamedDataSchema) itemSchema);
                }
            }
            if (schema instanceof MapDataSchema) {
                DataSchema valueSchema = ((MapDataSchema) schema).getValues();
                if (valueSchema instanceof NamedDataSchema) {
                    connectSchemaToResource(visitContext, (NamedDataSchema) valueSchema);
                }
            }
        }

        private void connectSchemaToResource(VisitContext visitContext, final NamedDataSchema schema) {
            final Node<NamedDataSchema> schemaNode = _relationships.get(schema);
            _dataModels.put(schema.getFullName(), schema);
            final DataSchemaTraverse traveler = new DataSchemaTraverse();
            traveler.traverse(schema, (path, nestedSchema) -> {
                if (nestedSchema instanceof RecordDataSchema && nestedSchema != schema) {
                    final RecordDataSchema nestedRecordSchema = (RecordDataSchema) nestedSchema;
                    _dataModels.put(nestedRecordSchema.getFullName(), nestedRecordSchema);
                    final Node<RecordDataSchema> node = _relationships.get(nestedRecordSchema);
                    schemaNode.addAdjacentNode(node);
                }
            });
            final Node<ResourceSchema> resourceNode = _relationships.get(visitContext.getParentSchema());
            resourceNode.addAdjacentNode(schemaNode);
            schemaNode.addAdjacentNode(resourceNode);
        }

        /**
         * Given a record which includes {@link ServiceErrorsSchema}, scans for service errors and connects the error
         * detail type field (if any) to the resource.
         *
         * @param visitContext visit context
         * @param record record which includes {@link ServiceErrorsSchema}
         */
        private void connectErrorDetailTypeToResource(VisitContext visitContext, RecordTemplate record) {
            final ServiceErrorsSchema serviceErrorsSchema = new ServiceErrorsSchema(record.data());
            if (serviceErrorsSchema.getServiceErrors() != null) {
                for (ServiceErrorSchema serviceErrorSchema : serviceErrorsSchema.getServiceErrors()) {
                    if (serviceErrorSchema.hasErrorDetailType()) {
                        final NamedDataSchema errorDetailTypeSchema = extractSchema(serviceErrorSchema.getErrorDetailType());
                        if (errorDetailTypeSchema != null) {
                            connectSchemaToResource(visitContext, errorDetailTypeSchema);
                        }
                    }
                }
            }
        }
    };
    ResourceSchemaCollection.visitResources(_resourceSchemas.getResources().values(), visitor);
}
Also used : ResourceSchema(com.linkedin.restli.restspec.ResourceSchema) ResourceLevel(com.linkedin.restli.server.ResourceLevel) MapDataSchema(com.linkedin.data.schema.MapDataSchema) ParameterSchema(com.linkedin.restli.restspec.ParameterSchema) BatchFinderSchema(com.linkedin.restli.restspec.BatchFinderSchema) FinderSchema(com.linkedin.restli.restspec.FinderSchema) ActionsSetSchema(com.linkedin.restli.restspec.ActionsSetSchema) StringArray(com.linkedin.data.template.StringArray) IdentifierSchema(com.linkedin.restli.restspec.IdentifierSchema) ServiceErrorsSchema(com.linkedin.restli.restspec.ServiceErrorsSchema) RecordTemplate(com.linkedin.data.template.RecordTemplate) ServiceErrorSchema(com.linkedin.restli.restspec.ServiceErrorSchema) AssociationSchema(com.linkedin.restli.restspec.AssociationSchema) CollectionSchema(com.linkedin.restli.restspec.CollectionSchema) SimpleSchema(com.linkedin.restli.restspec.SimpleSchema) MetadataSchema(com.linkedin.restli.restspec.MetadataSchema) BatchFinderSchema(com.linkedin.restli.restspec.BatchFinderSchema) RestMethodSchema(com.linkedin.restli.restspec.RestMethodSchema) ActionSchema(com.linkedin.restli.restspec.ActionSchema) AssocKeySchema(com.linkedin.restli.restspec.AssocKeySchema) NamedDataSchema(com.linkedin.data.schema.NamedDataSchema) DataSchema(com.linkedin.data.schema.DataSchema) MapDataSchema(com.linkedin.data.schema.MapDataSchema) RecordDataSchema(com.linkedin.data.schema.RecordDataSchema) NamedDataSchema(com.linkedin.data.schema.NamedDataSchema) ArrayDataSchema(com.linkedin.data.schema.ArrayDataSchema) ArrayDataSchema(com.linkedin.data.schema.ArrayDataSchema) RecordDataSchema(com.linkedin.data.schema.RecordDataSchema) DataSchemaTraverse(com.linkedin.data.schema.DataSchemaTraverse)

Aggregations

ServiceErrorSchema (com.linkedin.restli.restspec.ServiceErrorSchema)5 ServiceErrorsSchema (com.linkedin.restli.restspec.ServiceErrorsSchema)3 StringArray (com.linkedin.data.template.StringArray)2 ServiceErrorSchemaArray (com.linkedin.restli.restspec.ServiceErrorSchemaArray)2 ArrayDataSchema (com.linkedin.data.schema.ArrayDataSchema)1 DataSchema (com.linkedin.data.schema.DataSchema)1 DataSchemaTraverse (com.linkedin.data.schema.DataSchemaTraverse)1 MapDataSchema (com.linkedin.data.schema.MapDataSchema)1 NamedDataSchema (com.linkedin.data.schema.NamedDataSchema)1 RecordDataSchema (com.linkedin.data.schema.RecordDataSchema)1 RecordTemplate (com.linkedin.data.template.RecordTemplate)1 ActionSchema (com.linkedin.restli.restspec.ActionSchema)1 ActionsSetSchema (com.linkedin.restli.restspec.ActionsSetSchema)1 AssocKeySchema (com.linkedin.restli.restspec.AssocKeySchema)1 AssociationSchema (com.linkedin.restli.restspec.AssociationSchema)1 BatchFinderSchema (com.linkedin.restli.restspec.BatchFinderSchema)1 CollectionSchema (com.linkedin.restli.restspec.CollectionSchema)1 FinderSchema (com.linkedin.restli.restspec.FinderSchema)1 IdentifierSchema (com.linkedin.restli.restspec.IdentifierSchema)1 MetadataSchema (com.linkedin.restli.restspec.MetadataSchema)1