/** * Delivers the primary REST method associated with the given RPC method. Returns null * if the method has no HTTP attribute. */ @Nullable public static RestMethod getPrimaryRestMethod(Method method) { HttpAttribute attrib = method.getAttribute(HttpAttribute.KEY); if (attrib == null) { return null; } return attrib.getRestMethod(); }
/** Return the names of required parameters of a method. */ public List<String> getRequiredFields(Method method) { MessageType inputMessage = method.getInputMessage(); return inputMessage .getFields() .stream() .filter(this::isFieldRequired) .map(Field::getSimpleName) .collect(Collectors.toList()); }
/** * Get the input type of the underlying method. */ public TypeRef getInputType() { return method.getInputType(); }
private static GrpcStreamingType getGrpcStreamingType( DiagCollector diagCollector, Method method) { GrpcStreamingType type = null; if (method.getRequestStreaming() && method.getResponseStreaming()) { type = GrpcStreamingType.BidiStreaming; } else if (method.getResponseStreaming()) { type = GrpcStreamingType.ServerStreaming; } else if (method.getRequestStreaming()) { type = GrpcStreamingType.ClientStreaming; } else { diagCollector.addDiag( Diag.error( SimpleLocation.TOPLEVEL, "The given grpc method does not support streaming: %s", method.getFullName())); } return type; }
public ProtoMethodModel(Method method) { Preconditions.checkNotNull(method); this.method = method; this.inputType = ProtoTypeRef.create(method.getInputType()); this.outputType = ProtoTypeRef.create(method.getOutputType()); }
@VisitsBefore void visit(Method method) { // Resolve input and output type of this method. TypeRef inputType = resolveType(method.getLocation(), FieldDescriptorProto.Type.TYPE_MESSAGE, method.getDescriptor().getInputTypeName()); if (inputType != null) { method.setInputType(inputType); } TypeRef outputType = resolveType(method.getLocation(), FieldDescriptorProto.Type.TYPE_MESSAGE, method.getDescriptor().getOutputTypeName()); if (outputType != null) { method.setOutputType(outputType); } findOptionTypes(method.getOptionFields()); }
@VisitsBefore void normalize(Interface iface) { Api.Builder coreApiBuilder = Api.newBuilder().setName(iface.getFullName()); coreApiBuilder.setSourceContext( SourceContext.newBuilder().setFileName(iface.getFile().getLocation().getDisplayString())); coreApiBuilder.setSyntax(iface.getSyntax()); for (Method method : iface.getReachableMethods()) { com.google.protobuf.Method.Builder coreMethodBuilder = com.google.protobuf.Method.newBuilder() .setName(method.getSimpleName()) .setRequestTypeUrl(generateTypeUrl(method.getInputType())) .setResponseTypeUrl(generateTypeUrl(method.getOutputType())); coreMethodBuilder.setRequestStreaming(method.getRequestStreaming()); coreMethodBuilder.setResponseStreaming(method.getResponseStreaming()); coreMethodBuilder.addAllOptions( DescriptorNormalization.getMethodOptions( method.getOptionFields(), false, includeDefaults)); coreApiBuilder.addMethods(coreMethodBuilder); } coreApiBuilder.addAllOptions( DescriptorNormalization.getOptions(iface.getProto(), includeDefaults)); coreApiBuilder.setVersion(iface.getAttribute(VersionAttribute.KEY).majorVersion()); apis.add(coreApiBuilder.build()); }
private void startMergeMethod(Interface including, Method method) { // Check conditions implied by mixin configuration. Method redeclared = including.lookupMethod(method.getSimpleName()); if (redeclared == null) { error( including.getLocation(), "The API '%s' does not redeclare method '%s' as required by the mixin configuration.", including.getFullName(), method); return; } if (!method.getInputType().equals(redeclared.getInputType())) { error( redeclared.getLocation(), "The method '%s' must have request type '%s' as required by the mixin configuration.", redeclared, method.getInputMessage()); return; } if (!method.getOutputType().equals(redeclared.getOutputType())) { error( redeclared.getLocation(), "The method '%s' must have response type '%s' as required by the mixin configuration.", redeclared, method.getOutputType()); return; } // Add attribute. redeclared.addAttribute(ImplementsAttribute.KEY, ImplementsAttribute.create(method)); }
@Visits void reach(Method method) { mustBeInScope(method, method.getInputMessage()); mustBeInScope(method, method.getOutputMessage()); markAsReachable(method); // Check whether any HTTP bounded fields are visible. HttpAttribute http = method.getAttribute(HttpAttribute.KEY); if (http != null) { for (HttpAttribute binding : http.getAllBindings()) { Iterable<FieldSelector> selectors = binding.getPathSelectors(); if (!binding.bodyCapturesUnboundFields()) { // Only add body fields if '*' is not used, otherwise they aren't required. selectors = Iterables.concat(selectors, binding.getBodySelectors()); } for (FieldSelector selector : selectors) { for (Field field : selector.getFields()) { if (!isReachable(field)) { errorSince( 2, field, "Field '%s' required by HTTP binding of method '%s' cannot be hidden. %s.", field.getFullName(), method.getFullName(), reasonForUnreachable(field)); } } } } } }
Mockito.when(createShelvesMethod.getSimpleName()).thenReturn(CREATE_SHELF_METHOD_NAME); Mockito.when(createShelvesMethod.getInputType()).thenReturn(TypeRef.of(createShelvesRequest)); Mockito.when(createShelvesMethod.getOutputType()).thenReturn(TypeRef.of(createShelvesResponse)); Mockito.doReturn(shelfMessage).when(createShelvesMethod).getInputMessage(); Mockito.doReturn(bookMessage).when(insertBook).getInputMessage(); Mockito.doReturn(protoFile).when(bookMessage).getParent();
asDiagCollector(), method.getLocation(), path, method.getModel().getConfigVersion()) .parse(); if (parsedPath == null) { rule, kind, method.getInputType().getMessageType(), parsedPath, rule.getBody().isEmpty() ? null : rule.getBody(),
/** * Get the output type of the underlying method. */ public TypeRef getOutputType() { return method.getOutputType(); }
private static Set<String> calculateRestVersions(Method method) { Set<String> restVersions = Sets.newHashSet(); if (!method.hasAttribute(HttpAttribute.KEY)) { // Return an empty set if the proto method doesn't have http binding. return restVersions; } // Exclude rest version introduced by System APIs. for (String prefix : ConfigRuleSet.SYSTEM_PROTO_PREFIXES) { if (method.getFullName().startsWith(prefix)) { return Collections.emptySet(); } } for (HttpAttribute binding : method.getAttribute(HttpAttribute.KEY).getAllBindings()) { restVersions.add(binding.getRestMethod().getVersionWithDefault()); } return restVersions; } }
private void merge(Method method) { // TODO(user): Cleanup the use of apiVersion restVersions (VersionAttribute vs // RestVersionsAttribute) in the tools framework. Some references are using the attributes // incorrectly due to the confusion caused by the names. String apiVersion = deriveApiVersion(method); Set<String> restVersions = calculateRestVersions(method); method.putAttribute(VersionAttribute.KEY, VersionAttribute.create(apiVersion)); // UM uses the logical version with a suffix appended, if defined. String versionSuffix = method.getModel().getApiV1VersionSuffix(); method.putAttribute(VersionAttribute.USAGE_MANAGER_KEY, VersionAttribute.create(ApiVersionUtil.appendVersionSuffix(apiVersion, versionSuffix))); // Add the rest versions into RestVersionsAttribute only if parent of the method is included in // the model roots. if (roots.contains(method.getParent())) { if (getModel().hasAttribute(RestVersionsAttribute.KEY)) { getModel().getAttribute(RestVersionsAttribute.KEY).getVersions().addAll(restVersions); } else { getModel().putAttribute(RestVersionsAttribute.KEY, new RestVersionsAttribute(restVersions)); } } }
static RestMethod createCustomMethod( Method method, HttpAttribute httpConfig, String customNamePrefix) { ImmutableList<PathSegment> path = httpConfig.getFlatPath(); PathSegment lastSegment = path.get(path.size() - 1); // Determine base name. String customName = ""; if (lastSegment instanceof LiteralSegment) { customName = ((LiteralSegment) lastSegment).getLiteral(); path = path.subList(0, path.size() - 1); } else { if (method.getModel().getConfigVersion() > 1) { // From version 2 on, we generate a meaningful name here. customName = method.getSimpleName(); } else if (customNamePrefix.isEmpty()){ // Older versions use the prefix or derive from the http method. customName = httpConfig.getMethodKind().toString().toLowerCase(); } } // Prepend prefix. if (!customNamePrefix.isEmpty() && !customName.toLowerCase().startsWith(customNamePrefix.toLowerCase())) { customName = customNamePrefix + ensureUpperCase(customName); } // Ensure effective start is lower case. customName = ensureLowerCase(customName); String restMethodName = ""; CollectionName collectionName = RestAnalyzer.buildCollectionName(path, method.getModel()); return RestMethod.create( method, RestKind.CUSTOM, collectionName, customName, restMethodName); }
@Override public Model getModel() { return method.getModel(); }
/** Resolves a field path into a field selector. */ FieldSelector resolveFieldPath(Method method, String fieldPath) { FieldSelector result = null; try { result = FieldSelector.resolve(method.getInputType().getMessageType(), fieldPath); if (result == null) { error( method.getLocation(), "undefined field '%s' on message '%s'.", fieldPath, getInputMessageName(method)); } } catch (RuntimeException exception) { error(method.getLocation(), "%s", exception.getMessage()); } return result; }
@Override public String getSimpleName() { return method.getSimpleName(); }
@Override public String getFullName() { return method.getFullName(); }
private void checkResponseObject(Method method, MethodKind kind) { if (kind != MethodKind.NONE) { WellKnownType wkt = TypeRef.of(method.getOutputMessage()).getWellKnownType(); if (!wkt.allowedAsHttpRequestResponse()) { error( ResolvedLocation.create(method.getLocation()), "type '%s' is not allowed as a response because it does not render as " + "a JSON object.", method.getOutputMessage().getFullName()); } } }