Search in sources :

Example 1 with ResourceLevel

use of com.linkedin.restli.server.ResourceLevel in project rest.li by linkedin.

the class RestLiRouter method processResourceTree.

private RoutingResult processResourceTree(final ResourceModel resource, final ServerResourceContext context, final Queue<String> remainingPath) {
    ResourceModel currentResource = resource;
    // iterate through all path segments, simultaneously descending the resource hierarchy
    // and parsing path keys where applicable;
    // the goal of this loop is to locate the leaf resource, which will be set in
    // currentResource, and to parse the necessary information into the context
    ResourceLevel currentLevel = currentResource.getResourceLevel();
    while (remainingPath.peek() != null) {
        String currentPathSegment = remainingPath.poll();
        if (currentLevel.equals(ResourceLevel.ENTITY)) {
            currentResource = currentResource.getSubResource(parseSubresourceName(currentPathSegment));
            currentLevel = currentResource == null ? ResourceLevel.ANY : currentResource.getResourceLevel();
        } else {
            ResourceModel currentCollectionResource = currentResource;
            if (currentResource.getKeys().isEmpty()) {
                throw new RoutingException(String.format("Path key not supported on resource '%s' for URI '%s'", currentResource.getName(), context.getRequestURI()), HttpStatus.S_400_BAD_REQUEST.getCode());
            } else if (context.getParameters().containsKey(RestConstants.ALT_KEY_PARAM)) {
                parseAlternativeKey(currentResource, context, currentPathSegment);
                currentLevel = ResourceLevel.ENTITY;
            } else if (currentResource.getKeyClass() == ComplexResourceKey.class) {
                parseComplexKey(currentResource, context, currentPathSegment);
                currentLevel = ResourceLevel.ENTITY;
            } else if (currentResource.getKeyClass() == CompoundKey.class) {
                CompoundKey compoundKey;
                try {
                    compoundKey = parseCompoundKey(currentCollectionResource, context, currentPathSegment);
                } catch (IllegalArgumentException e) {
                    throw new RoutingException(String.format("Malformed Compound Key: '%s'", currentPathSegment), HttpStatus.S_400_BAD_REQUEST.getCode(), e);
                }
                if (compoundKey != null && compoundKey.getPartKeys().containsAll(currentResource.getKeyNames())) {
                    // full match on key parts means that we are targeting a unique entity
                    currentLevel = ResourceLevel.ENTITY;
                }
            } else // Must be a simple key then
            {
                parseSimpleKey(currentResource, context, currentPathSegment);
                currentLevel = ResourceLevel.ENTITY;
            }
        }
        if (currentResource == null) {
            throw new RoutingException(HttpStatus.S_404_NOT_FOUND.getCode());
        }
    }
    //now we know the key type, look for batch parameter
    parseBatchKeysParameter(currentResource, context);
    return findMethodDescriptor(currentResource, currentLevel, context);
}
Also used : RoutingException(com.linkedin.restli.server.RoutingException) CompoundKey(com.linkedin.restli.common.CompoundKey) ResourceLevel(com.linkedin.restli.server.ResourceLevel) ResourceModel(com.linkedin.restli.internal.server.model.ResourceModel)

Example 2 with ResourceLevel

use of com.linkedin.restli.server.ResourceLevel in project rest.li by linkedin.

the class RestLiHTMLDocumentationRenderer method renderResource.

@Override
public void renderResource(String resourceName, OutputStream out) {
    final ResourceSchema resourceSchema = _resourceSchemas.getResource(resourceName);
    final List<ResourceSchema> parentResources = _resourceSchemas.getParentResources(resourceSchema);
    ExampleRequestResponseGenerator generator = new ExampleRequestResponseGenerator(parentResources, resourceSchema, _schemaResolver);
    if (resourceSchema == null) {
        throw new RoutingException(String.format("Resource \"%s\" does not exist", resourceName), HttpStatus.S_404_NOT_FOUND.getCode());
    }
    final Map<String, Object> pageModel = createPageModel();
    pageModel.put("resource", resourceSchema);
    pageModel.put("resourceName", resourceName);
    pageModel.put("resourceFullName", ResourceSchemaUtil.getFullName(resourceSchema));
    pageModel.put("resourceType", getResourceType(resourceSchema));
    pageModel.put("subResources", _resourceSchemas.getSubResources(resourceSchema));
    final List<ResourceMethodDocView> restMethods = new ArrayList<ResourceMethodDocView>();
    final List<ResourceMethodDocView> finders = new ArrayList<ResourceMethodDocView>();
    final List<ResourceMethodDocView> actions = new ArrayList<ResourceMethodDocView>();
    final MethodGatheringResourceSchemaVisitor visitor = new MethodGatheringResourceSchemaVisitor(resourceName);
    ResourceSchemaCollection.visitResources(_resourceSchemas.getResources().values(), visitor);
    for (RecordTemplate methodSchema : visitor.getAllMethods()) {
        final ExampleRequestResponse capture;
        if (methodSchema instanceof RestMethodSchema) {
            RestMethodSchema restMethodSchema = (RestMethodSchema) methodSchema;
            capture = generator.method(ResourceMethod.valueOf(restMethodSchema.getMethod().toUpperCase()));
        } else if (methodSchema instanceof FinderSchema) {
            FinderSchema finderMethodSchema = (FinderSchema) methodSchema;
            capture = generator.finder(finderMethodSchema.getName());
        } else if (methodSchema instanceof ActionSchema) {
            ActionSchema actionMethodSchema = (ActionSchema) methodSchema;
            final ResourceLevel resourceLevel = (visitor.getCollectionActions().contains(methodSchema) ? ResourceLevel.COLLECTION : ResourceLevel.ENTITY);
            capture = generator.action(actionMethodSchema.getName(), resourceLevel);
        } else {
            capture = null;
        }
        String requestEntity = null;
        String responseEntity = null;
        if (capture != null) {
            try {
                DataMap entityMap;
                if (capture.getRequest().getEntity().length() > 0) {
                    entityMap = DataMapUtils.readMap(capture.getRequest());
                    requestEntity = new String(_codec.mapToBytes(entityMap));
                }
                if (capture.getResponse() != null && capture.getResponse().getEntity() != null && capture.getResponse().getEntity().length() > 0) {
                    entityMap = DataMapUtils.readMap(capture.getResponse());
                    responseEntity = new String(_codec.mapToBytes(entityMap));
                }
            } catch (IOException e) {
                throw new RestLiInternalException(e);
            }
        }
        final ResourceMethodDocView docView = new ResourceMethodDocView(methodSchema, capture, getDoc(methodSchema, resourceSchema.hasSimple()), requestEntity, responseEntity);
        if (methodSchema instanceof RestMethodSchema) {
            restMethods.add(docView);
        } else if (methodSchema instanceof FinderSchema) {
            finders.add(docView);
        } else if (methodSchema instanceof ActionSchema) {
            actions.add(docView);
        }
    }
    pageModel.put("restMethods", restMethods);
    pageModel.put("finders", finders);
    pageModel.put("actions", actions);
    addRelated(resourceSchema, pageModel);
    _templatingEngine.render("resource.vm", pageModel, out);
}
Also used : RoutingException(com.linkedin.restli.server.RoutingException) ResourceSchema(com.linkedin.restli.restspec.ResourceSchema) ExampleRequestResponse(com.linkedin.restli.docgen.examplegen.ExampleRequestResponse) ResourceLevel(com.linkedin.restli.server.ResourceLevel) ArrayList(java.util.ArrayList) RestMethodSchema(com.linkedin.restli.restspec.RestMethodSchema) FinderSchema(com.linkedin.restli.restspec.FinderSchema) IOException(java.io.IOException) ActionSchema(com.linkedin.restli.restspec.ActionSchema) DataMap(com.linkedin.data.DataMap) ExampleRequestResponseGenerator(com.linkedin.restli.docgen.examplegen.ExampleRequestResponseGenerator) RecordTemplate(com.linkedin.data.template.RecordTemplate) RestLiInternalException(com.linkedin.restli.internal.server.RestLiInternalException)

Example 3 with ResourceLevel

use of com.linkedin.restli.server.ResourceLevel 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) {
            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) {
            for (AssocKeySchema key : associationSchema.getAssocKeys()) {
                final NamedDataSchema keyTypeSchema = extractSchema(key.getType());
                if (keyTypeSchema != null) {
                    connectSchemaToResource(visitContext, keyTypeSchema);
                }
            }
        }

        @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 visitFinder(VisitContext visitContext, RecordTemplate parentResource, FinderSchema finderSchema) {
            final MetadataSchema metadata = finderSchema.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) {
            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);
            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, new DataSchemaTraverse.Callback() {

                @Override
                public void callback(List<String> path, DataSchema 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);
        }
    };
    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) FinderSchema(com.linkedin.restli.restspec.FinderSchema) StringArray(com.linkedin.data.template.StringArray) IdentifierSchema(com.linkedin.restli.restspec.IdentifierSchema) RecordTemplate(com.linkedin.data.template.RecordTemplate) AssociationSchema(com.linkedin.restli.restspec.AssociationSchema) CollectionSchema(com.linkedin.restli.restspec.CollectionSchema) MetadataSchema(com.linkedin.restli.restspec.MetadataSchema) 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

ResourceLevel (com.linkedin.restli.server.ResourceLevel)3 RecordTemplate (com.linkedin.data.template.RecordTemplate)2 ActionSchema (com.linkedin.restli.restspec.ActionSchema)2 FinderSchema (com.linkedin.restli.restspec.FinderSchema)2 ResourceSchema (com.linkedin.restli.restspec.ResourceSchema)2 RoutingException (com.linkedin.restli.server.RoutingException)2 DataMap (com.linkedin.data.DataMap)1 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 StringArray (com.linkedin.data.template.StringArray)1 CompoundKey (com.linkedin.restli.common.CompoundKey)1 ExampleRequestResponse (com.linkedin.restli.docgen.examplegen.ExampleRequestResponse)1 ExampleRequestResponseGenerator (com.linkedin.restli.docgen.examplegen.ExampleRequestResponseGenerator)1 RestLiInternalException (com.linkedin.restli.internal.server.RestLiInternalException)1 ResourceModel (com.linkedin.restli.internal.server.model.ResourceModel)1 AssocKeySchema (com.linkedin.restli.restspec.AssocKeySchema)1