1// Copyright 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// Code generated by gapic-generator. DO NOT EDIT.
16
17package vision
18
19import (
20	"context"
21	"fmt"
22	"math"
23	"time"
24
25	"cloud.google.com/go/longrunning"
26	lroauto "cloud.google.com/go/longrunning/autogen"
27	"github.com/golang/protobuf/proto"
28	gax "github.com/googleapis/gax-go/v2"
29	"google.golang.org/api/iterator"
30	"google.golang.org/api/option"
31	"google.golang.org/api/transport"
32	visionpb "google.golang.org/genproto/googleapis/cloud/vision/v1"
33	longrunningpb "google.golang.org/genproto/googleapis/longrunning"
34	"google.golang.org/grpc"
35	"google.golang.org/grpc/codes"
36	"google.golang.org/grpc/metadata"
37)
38
39// ProductSearchCallOptions contains the retry settings for each method of ProductSearchClient.
40type ProductSearchCallOptions struct {
41	CreateProduct               []gax.CallOption
42	ListProducts                []gax.CallOption
43	GetProduct                  []gax.CallOption
44	UpdateProduct               []gax.CallOption
45	DeleteProduct               []gax.CallOption
46	ListReferenceImages         []gax.CallOption
47	GetReferenceImage           []gax.CallOption
48	DeleteReferenceImage        []gax.CallOption
49	CreateReferenceImage        []gax.CallOption
50	CreateProductSet            []gax.CallOption
51	ListProductSets             []gax.CallOption
52	GetProductSet               []gax.CallOption
53	UpdateProductSet            []gax.CallOption
54	DeleteProductSet            []gax.CallOption
55	AddProductToProductSet      []gax.CallOption
56	RemoveProductFromProductSet []gax.CallOption
57	ListProductsInProductSet    []gax.CallOption
58	ImportProductSets           []gax.CallOption
59}
60
61func defaultProductSearchClientOptions() []option.ClientOption {
62	return []option.ClientOption{
63		option.WithEndpoint("vision.googleapis.com:443"),
64		option.WithScopes(DefaultAuthScopes()...),
65	}
66}
67
68func defaultProductSearchCallOptions() *ProductSearchCallOptions {
69	retry := map[[2]string][]gax.CallOption{
70		{"default", "idempotent"}: {
71			gax.WithRetry(func() gax.Retryer {
72				return gax.OnCodes([]codes.Code{
73					codes.DeadlineExceeded,
74					codes.Unavailable,
75				}, gax.Backoff{
76					Initial:    100 * time.Millisecond,
77					Max:        60000 * time.Millisecond,
78					Multiplier: 1.3,
79				})
80			}),
81		},
82	}
83	return &ProductSearchCallOptions{
84		CreateProduct:               retry[[2]string{"default", "non_idempotent"}],
85		ListProducts:                retry[[2]string{"default", "idempotent"}],
86		GetProduct:                  retry[[2]string{"default", "idempotent"}],
87		UpdateProduct:               retry[[2]string{"default", "idempotent"}],
88		DeleteProduct:               retry[[2]string{"default", "idempotent"}],
89		ListReferenceImages:         retry[[2]string{"default", "idempotent"}],
90		GetReferenceImage:           retry[[2]string{"default", "idempotent"}],
91		DeleteReferenceImage:        retry[[2]string{"default", "idempotent"}],
92		CreateReferenceImage:        retry[[2]string{"default", "non_idempotent"}],
93		CreateProductSet:            retry[[2]string{"default", "non_idempotent"}],
94		ListProductSets:             retry[[2]string{"default", "idempotent"}],
95		GetProductSet:               retry[[2]string{"default", "idempotent"}],
96		UpdateProductSet:            retry[[2]string{"default", "idempotent"}],
97		DeleteProductSet:            retry[[2]string{"default", "idempotent"}],
98		AddProductToProductSet:      retry[[2]string{"default", "idempotent"}],
99		RemoveProductFromProductSet: retry[[2]string{"default", "idempotent"}],
100		ListProductsInProductSet:    retry[[2]string{"default", "idempotent"}],
101		ImportProductSets:           retry[[2]string{"default", "non_idempotent"}],
102	}
103}
104
105// ProductSearchClient is a client for interacting with Cloud Vision API.
106//
107// Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls.
108type ProductSearchClient struct {
109	// The connection to the service.
110	conn *grpc.ClientConn
111
112	// The gRPC API client.
113	productSearchClient visionpb.ProductSearchClient
114
115	// LROClient is used internally to handle longrunning operations.
116	// It is exposed so that its CallOptions can be modified if required.
117	// Users should not Close this client.
118	LROClient *lroauto.OperationsClient
119
120	// The call options for this service.
121	CallOptions *ProductSearchCallOptions
122
123	// The x-goog-* metadata to be sent with each request.
124	xGoogMetadata metadata.MD
125}
126
127// NewProductSearchClient creates a new product search client.
128//
129// Manages Products and ProductSets of reference images for use in product
130// search. It uses the following resource model:
131//
132//   The API has a collection of [ProductSet][google.cloud.vision.v1.ProductSet]
133//   resources, named projects/*/locations/*/productSets/*, which acts as a way
134//   to put different products into groups to limit identification.
135//
136// In parallel,
137//
138//   The API has a collection of [Product][google.cloud.vision.v1.Product]
139//   resources, named
140//   projects/*/locations/*/products/*
141//
142//   Each [Product][google.cloud.vision.v1.Product] has a collection of
143//   [ReferenceImage][google.cloud.vision.v1.ReferenceImage] resources, named
144//   projects/*/locations/*/products/*/referenceImages/*
145func NewProductSearchClient(ctx context.Context, opts ...option.ClientOption) (*ProductSearchClient, error) {
146	conn, err := transport.DialGRPC(ctx, append(defaultProductSearchClientOptions(), opts...)...)
147	if err != nil {
148		return nil, err
149	}
150	c := &ProductSearchClient{
151		conn:        conn,
152		CallOptions: defaultProductSearchCallOptions(),
153
154		productSearchClient: visionpb.NewProductSearchClient(conn),
155	}
156	c.setGoogleClientInfo()
157
158	c.LROClient, err = lroauto.NewOperationsClient(ctx, option.WithGRPCConn(conn))
159	if err != nil {
160		// This error "should not happen", since we are just reusing old connection
161		// and never actually need to dial.
162		// If this does happen, we could leak conn. However, we cannot close conn:
163		// If the user invoked the function with option.WithGRPCConn,
164		// we would close a connection that's still in use.
165		// TODO(pongad): investigate error conditions.
166		return nil, err
167	}
168	return c, nil
169}
170
171// Connection returns the client's connection to the API service.
172func (c *ProductSearchClient) Connection() *grpc.ClientConn {
173	return c.conn
174}
175
176// Close closes the connection to the API service. The user should invoke this when
177// the client is no longer required.
178func (c *ProductSearchClient) Close() error {
179	return c.conn.Close()
180}
181
182// setGoogleClientInfo sets the name and version of the application in
183// the `x-goog-api-client` header passed on each request. Intended for
184// use by Google-written clients.
185func (c *ProductSearchClient) setGoogleClientInfo(keyval ...string) {
186	kv := append([]string{"gl-go", versionGo()}, keyval...)
187	kv = append(kv, "gapic", versionClient, "gax", gax.Version, "grpc", grpc.Version)
188	c.xGoogMetadata = metadata.Pairs("x-goog-api-client", gax.XGoogHeader(kv...))
189}
190
191// CreateProduct creates and returns a new product resource.
192//
193// Possible errors:
194//
195//   Returns INVALID_ARGUMENT if display_name is missing or longer than 4096
196//   characters.
197//
198//   Returns INVALID_ARGUMENT if description is longer than 4096 characters.
199//
200//   Returns INVALID_ARGUMENT if product_category is missing or invalid.
201func (c *ProductSearchClient) CreateProduct(ctx context.Context, req *visionpb.CreateProductRequest, opts ...gax.CallOption) (*visionpb.Product, error) {
202	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
203	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
204	opts = append(c.CallOptions.CreateProduct[0:len(c.CallOptions.CreateProduct):len(c.CallOptions.CreateProduct)], opts...)
205	var resp *visionpb.Product
206	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
207		var err error
208		resp, err = c.productSearchClient.CreateProduct(ctx, req, settings.GRPC...)
209		return err
210	}, opts...)
211	if err != nil {
212		return nil, err
213	}
214	return resp, nil
215}
216
217// ListProducts lists products in an unspecified order.
218//
219// Possible errors:
220//
221//   Returns INVALID_ARGUMENT if page_size is greater than 100 or less than 1.
222func (c *ProductSearchClient) ListProducts(ctx context.Context, req *visionpb.ListProductsRequest, opts ...gax.CallOption) *ProductIterator {
223	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
224	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
225	opts = append(c.CallOptions.ListProducts[0:len(c.CallOptions.ListProducts):len(c.CallOptions.ListProducts)], opts...)
226	it := &ProductIterator{}
227	req = proto.Clone(req).(*visionpb.ListProductsRequest)
228	it.InternalFetch = func(pageSize int, pageToken string) ([]*visionpb.Product, string, error) {
229		var resp *visionpb.ListProductsResponse
230		req.PageToken = pageToken
231		if pageSize > math.MaxInt32 {
232			req.PageSize = math.MaxInt32
233		} else {
234			req.PageSize = int32(pageSize)
235		}
236		err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
237			var err error
238			resp, err = c.productSearchClient.ListProducts(ctx, req, settings.GRPC...)
239			return err
240		}, opts...)
241		if err != nil {
242			return nil, "", err
243		}
244		return resp.Products, resp.NextPageToken, nil
245	}
246	fetch := func(pageSize int, pageToken string) (string, error) {
247		items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
248		if err != nil {
249			return "", err
250		}
251		it.items = append(it.items, items...)
252		return nextPageToken, nil
253	}
254	it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
255	it.pageInfo.MaxSize = int(req.PageSize)
256	return it
257}
258
259// GetProduct gets information associated with a Product.
260//
261// Possible errors:
262//
263//   Returns NOT_FOUND if the Product does not exist.
264func (c *ProductSearchClient) GetProduct(ctx context.Context, req *visionpb.GetProductRequest, opts ...gax.CallOption) (*visionpb.Product, error) {
265	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
266	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
267	opts = append(c.CallOptions.GetProduct[0:len(c.CallOptions.GetProduct):len(c.CallOptions.GetProduct)], opts...)
268	var resp *visionpb.Product
269	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
270		var err error
271		resp, err = c.productSearchClient.GetProduct(ctx, req, settings.GRPC...)
272		return err
273	}, opts...)
274	if err != nil {
275		return nil, err
276	}
277	return resp, nil
278}
279
280// UpdateProduct makes changes to a Product resource.
281// Only the display_name, description, and labels fields can be updated
282// right now.
283//
284// If labels are updated, the change will not be reflected in queries until
285// the next index time.
286//
287// Possible errors:
288//
289//   Returns NOT_FOUND if the Product does not exist.
290//
291//   Returns INVALID_ARGUMENT if display_name is present in update_mask but is
292//   missing from the request or longer than 4096 characters.
293//
294//   Returns INVALID_ARGUMENT if description is present in update_mask but is
295//   longer than 4096 characters.
296//
297//   Returns INVALID_ARGUMENT if product_category is present in update_mask.
298func (c *ProductSearchClient) UpdateProduct(ctx context.Context, req *visionpb.UpdateProductRequest, opts ...gax.CallOption) (*visionpb.Product, error) {
299	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "product.name", req.GetProduct().GetName()))
300	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
301	opts = append(c.CallOptions.UpdateProduct[0:len(c.CallOptions.UpdateProduct):len(c.CallOptions.UpdateProduct)], opts...)
302	var resp *visionpb.Product
303	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
304		var err error
305		resp, err = c.productSearchClient.UpdateProduct(ctx, req, settings.GRPC...)
306		return err
307	}, opts...)
308	if err != nil {
309		return nil, err
310	}
311	return resp, nil
312}
313
314// DeleteProduct permanently deletes a product and its reference images.
315//
316// Metadata of the product and all its images will be deleted right away, but
317// search queries against ProductSets containing the product may still work
318// until all related caches are refreshed.
319//
320// Possible errors:
321//
322//   Returns NOT_FOUND if the product does not exist.
323func (c *ProductSearchClient) DeleteProduct(ctx context.Context, req *visionpb.DeleteProductRequest, opts ...gax.CallOption) error {
324	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
325	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
326	opts = append(c.CallOptions.DeleteProduct[0:len(c.CallOptions.DeleteProduct):len(c.CallOptions.DeleteProduct)], opts...)
327	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
328		var err error
329		_, err = c.productSearchClient.DeleteProduct(ctx, req, settings.GRPC...)
330		return err
331	}, opts...)
332	return err
333}
334
335// ListReferenceImages lists reference images.
336//
337// Possible errors:
338//
339//   Returns NOT_FOUND if the parent product does not exist.
340//
341//   Returns INVALID_ARGUMENT if the page_size is greater than 100, or less
342//   than 1.
343func (c *ProductSearchClient) ListReferenceImages(ctx context.Context, req *visionpb.ListReferenceImagesRequest, opts ...gax.CallOption) *ReferenceImageIterator {
344	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
345	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
346	opts = append(c.CallOptions.ListReferenceImages[0:len(c.CallOptions.ListReferenceImages):len(c.CallOptions.ListReferenceImages)], opts...)
347	it := &ReferenceImageIterator{}
348	req = proto.Clone(req).(*visionpb.ListReferenceImagesRequest)
349	it.InternalFetch = func(pageSize int, pageToken string) ([]*visionpb.ReferenceImage, string, error) {
350		var resp *visionpb.ListReferenceImagesResponse
351		req.PageToken = pageToken
352		if pageSize > math.MaxInt32 {
353			req.PageSize = math.MaxInt32
354		} else {
355			req.PageSize = int32(pageSize)
356		}
357		err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
358			var err error
359			resp, err = c.productSearchClient.ListReferenceImages(ctx, req, settings.GRPC...)
360			return err
361		}, opts...)
362		if err != nil {
363			return nil, "", err
364		}
365		return resp.ReferenceImages, resp.NextPageToken, nil
366	}
367	fetch := func(pageSize int, pageToken string) (string, error) {
368		items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
369		if err != nil {
370			return "", err
371		}
372		it.items = append(it.items, items...)
373		return nextPageToken, nil
374	}
375	it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
376	it.pageInfo.MaxSize = int(req.PageSize)
377	return it
378}
379
380// GetReferenceImage gets information associated with a ReferenceImage.
381//
382// Possible errors:
383//
384//   Returns NOT_FOUND if the specified image does not exist.
385func (c *ProductSearchClient) GetReferenceImage(ctx context.Context, req *visionpb.GetReferenceImageRequest, opts ...gax.CallOption) (*visionpb.ReferenceImage, error) {
386	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
387	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
388	opts = append(c.CallOptions.GetReferenceImage[0:len(c.CallOptions.GetReferenceImage):len(c.CallOptions.GetReferenceImage)], opts...)
389	var resp *visionpb.ReferenceImage
390	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
391		var err error
392		resp, err = c.productSearchClient.GetReferenceImage(ctx, req, settings.GRPC...)
393		return err
394	}, opts...)
395	if err != nil {
396		return nil, err
397	}
398	return resp, nil
399}
400
401// DeleteReferenceImage permanently deletes a reference image.
402//
403// The image metadata will be deleted right away, but search queries
404// against ProductSets containing the image may still work until all related
405// caches are refreshed.
406//
407// The actual image files are not deleted from Google Cloud Storage.
408//
409// Possible errors:
410//
411//   Returns NOT_FOUND if the reference image does not exist.
412func (c *ProductSearchClient) DeleteReferenceImage(ctx context.Context, req *visionpb.DeleteReferenceImageRequest, opts ...gax.CallOption) error {
413	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
414	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
415	opts = append(c.CallOptions.DeleteReferenceImage[0:len(c.CallOptions.DeleteReferenceImage):len(c.CallOptions.DeleteReferenceImage)], opts...)
416	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
417		var err error
418		_, err = c.productSearchClient.DeleteReferenceImage(ctx, req, settings.GRPC...)
419		return err
420	}, opts...)
421	return err
422}
423
424// CreateReferenceImage creates and returns a new ReferenceImage resource.
425//
426// The bounding_poly field is optional. If bounding_poly is not specified,
427// the system will try to detect regions of interest in the image that are
428// compatible with the product_category on the parent product. If it is
429// specified, detection is ALWAYS skipped. The system converts polygons into
430// non-rotated rectangles.
431//
432// Note that the pipeline will resize the image if the image resolution is too
433// large to process (above 50MP).
434//
435// Possible errors:
436//
437//   Returns INVALID_ARGUMENT if the image_uri is missing or longer than 4096
438//   characters.
439//
440//   Returns INVALID_ARGUMENT if the product does not exist.
441//
442//   Returns INVALID_ARGUMENT if bounding_poly is not provided, and nothing
443//   compatible with the parent product's product_category is detected.
444//
445//   Returns INVALID_ARGUMENT if bounding_poly contains more than 10 polygons.
446func (c *ProductSearchClient) CreateReferenceImage(ctx context.Context, req *visionpb.CreateReferenceImageRequest, opts ...gax.CallOption) (*visionpb.ReferenceImage, error) {
447	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
448	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
449	opts = append(c.CallOptions.CreateReferenceImage[0:len(c.CallOptions.CreateReferenceImage):len(c.CallOptions.CreateReferenceImage)], opts...)
450	var resp *visionpb.ReferenceImage
451	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
452		var err error
453		resp, err = c.productSearchClient.CreateReferenceImage(ctx, req, settings.GRPC...)
454		return err
455	}, opts...)
456	if err != nil {
457		return nil, err
458	}
459	return resp, nil
460}
461
462// CreateProductSet creates and returns a new ProductSet resource.
463//
464// Possible errors:
465//
466//   Returns INVALID_ARGUMENT if display_name is missing, or is longer than
467//   4096 characters.
468func (c *ProductSearchClient) CreateProductSet(ctx context.Context, req *visionpb.CreateProductSetRequest, opts ...gax.CallOption) (*visionpb.ProductSet, error) {
469	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
470	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
471	opts = append(c.CallOptions.CreateProductSet[0:len(c.CallOptions.CreateProductSet):len(c.CallOptions.CreateProductSet)], opts...)
472	var resp *visionpb.ProductSet
473	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
474		var err error
475		resp, err = c.productSearchClient.CreateProductSet(ctx, req, settings.GRPC...)
476		return err
477	}, opts...)
478	if err != nil {
479		return nil, err
480	}
481	return resp, nil
482}
483
484// ListProductSets lists ProductSets in an unspecified order.
485//
486// Possible errors:
487//
488//   Returns INVALID_ARGUMENT if page_size is greater than 100, or less
489//   than 1.
490func (c *ProductSearchClient) ListProductSets(ctx context.Context, req *visionpb.ListProductSetsRequest, opts ...gax.CallOption) *ProductSetIterator {
491	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
492	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
493	opts = append(c.CallOptions.ListProductSets[0:len(c.CallOptions.ListProductSets):len(c.CallOptions.ListProductSets)], opts...)
494	it := &ProductSetIterator{}
495	req = proto.Clone(req).(*visionpb.ListProductSetsRequest)
496	it.InternalFetch = func(pageSize int, pageToken string) ([]*visionpb.ProductSet, string, error) {
497		var resp *visionpb.ListProductSetsResponse
498		req.PageToken = pageToken
499		if pageSize > math.MaxInt32 {
500			req.PageSize = math.MaxInt32
501		} else {
502			req.PageSize = int32(pageSize)
503		}
504		err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
505			var err error
506			resp, err = c.productSearchClient.ListProductSets(ctx, req, settings.GRPC...)
507			return err
508		}, opts...)
509		if err != nil {
510			return nil, "", err
511		}
512		return resp.ProductSets, resp.NextPageToken, nil
513	}
514	fetch := func(pageSize int, pageToken string) (string, error) {
515		items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
516		if err != nil {
517			return "", err
518		}
519		it.items = append(it.items, items...)
520		return nextPageToken, nil
521	}
522	it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
523	it.pageInfo.MaxSize = int(req.PageSize)
524	return it
525}
526
527// GetProductSet gets information associated with a ProductSet.
528//
529// Possible errors:
530//
531//   Returns NOT_FOUND if the ProductSet does not exist.
532func (c *ProductSearchClient) GetProductSet(ctx context.Context, req *visionpb.GetProductSetRequest, opts ...gax.CallOption) (*visionpb.ProductSet, error) {
533	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
534	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
535	opts = append(c.CallOptions.GetProductSet[0:len(c.CallOptions.GetProductSet):len(c.CallOptions.GetProductSet)], opts...)
536	var resp *visionpb.ProductSet
537	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
538		var err error
539		resp, err = c.productSearchClient.GetProductSet(ctx, req, settings.GRPC...)
540		return err
541	}, opts...)
542	if err != nil {
543		return nil, err
544	}
545	return resp, nil
546}
547
548// UpdateProductSet makes changes to a ProductSet resource.
549// Only display_name can be updated currently.
550//
551// Possible errors:
552//
553//   Returns NOT_FOUND if the ProductSet does not exist.
554//
555//   Returns INVALID_ARGUMENT if display_name is present in update_mask but
556//   missing from the request or longer than 4096 characters.
557func (c *ProductSearchClient) UpdateProductSet(ctx context.Context, req *visionpb.UpdateProductSetRequest, opts ...gax.CallOption) (*visionpb.ProductSet, error) {
558	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "product_set.name", req.GetProductSet().GetName()))
559	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
560	opts = append(c.CallOptions.UpdateProductSet[0:len(c.CallOptions.UpdateProductSet):len(c.CallOptions.UpdateProductSet)], opts...)
561	var resp *visionpb.ProductSet
562	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
563		var err error
564		resp, err = c.productSearchClient.UpdateProductSet(ctx, req, settings.GRPC...)
565		return err
566	}, opts...)
567	if err != nil {
568		return nil, err
569	}
570	return resp, nil
571}
572
573// DeleteProductSet permanently deletes a ProductSet. Products and ReferenceImages in the
574// ProductSet are not deleted.
575//
576// The actual image files are not deleted from Google Cloud Storage.
577//
578// Possible errors:
579//
580//   Returns NOT_FOUND if the ProductSet does not exist.
581func (c *ProductSearchClient) DeleteProductSet(ctx context.Context, req *visionpb.DeleteProductSetRequest, opts ...gax.CallOption) error {
582	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
583	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
584	opts = append(c.CallOptions.DeleteProductSet[0:len(c.CallOptions.DeleteProductSet):len(c.CallOptions.DeleteProductSet)], opts...)
585	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
586		var err error
587		_, err = c.productSearchClient.DeleteProductSet(ctx, req, settings.GRPC...)
588		return err
589	}, opts...)
590	return err
591}
592
593// AddProductToProductSet adds a Product to the specified ProductSet. If the Product is already
594// present, no change is made.
595//
596// One Product can be added to at most 100 ProductSets.
597//
598// Possible errors:
599//
600//   Returns NOT_FOUND if the Product or the ProductSet doesn't exist.
601func (c *ProductSearchClient) AddProductToProductSet(ctx context.Context, req *visionpb.AddProductToProductSetRequest, opts ...gax.CallOption) error {
602	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
603	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
604	opts = append(c.CallOptions.AddProductToProductSet[0:len(c.CallOptions.AddProductToProductSet):len(c.CallOptions.AddProductToProductSet)], opts...)
605	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
606		var err error
607		_, err = c.productSearchClient.AddProductToProductSet(ctx, req, settings.GRPC...)
608		return err
609	}, opts...)
610	return err
611}
612
613// RemoveProductFromProductSet removes a Product from the specified ProductSet.
614//
615// Possible errors:
616//
617//   Returns NOT_FOUND If the Product is not found under the ProductSet.
618func (c *ProductSearchClient) RemoveProductFromProductSet(ctx context.Context, req *visionpb.RemoveProductFromProductSetRequest, opts ...gax.CallOption) error {
619	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
620	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
621	opts = append(c.CallOptions.RemoveProductFromProductSet[0:len(c.CallOptions.RemoveProductFromProductSet):len(c.CallOptions.RemoveProductFromProductSet)], opts...)
622	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
623		var err error
624		_, err = c.productSearchClient.RemoveProductFromProductSet(ctx, req, settings.GRPC...)
625		return err
626	}, opts...)
627	return err
628}
629
630// ListProductsInProductSet lists the Products in a ProductSet, in an unspecified order. If the
631// ProductSet does not exist, the products field of the response will be
632// empty.
633//
634// Possible errors:
635//
636//   Returns INVALID_ARGUMENT if page_size is greater than 100 or less than 1.
637func (c *ProductSearchClient) ListProductsInProductSet(ctx context.Context, req *visionpb.ListProductsInProductSetRequest, opts ...gax.CallOption) *ProductIterator {
638	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
639	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
640	opts = append(c.CallOptions.ListProductsInProductSet[0:len(c.CallOptions.ListProductsInProductSet):len(c.CallOptions.ListProductsInProductSet)], opts...)
641	it := &ProductIterator{}
642	req = proto.Clone(req).(*visionpb.ListProductsInProductSetRequest)
643	it.InternalFetch = func(pageSize int, pageToken string) ([]*visionpb.Product, string, error) {
644		var resp *visionpb.ListProductsInProductSetResponse
645		req.PageToken = pageToken
646		if pageSize > math.MaxInt32 {
647			req.PageSize = math.MaxInt32
648		} else {
649			req.PageSize = int32(pageSize)
650		}
651		err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
652			var err error
653			resp, err = c.productSearchClient.ListProductsInProductSet(ctx, req, settings.GRPC...)
654			return err
655		}, opts...)
656		if err != nil {
657			return nil, "", err
658		}
659		return resp.Products, resp.NextPageToken, nil
660	}
661	fetch := func(pageSize int, pageToken string) (string, error) {
662		items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
663		if err != nil {
664			return "", err
665		}
666		it.items = append(it.items, items...)
667		return nextPageToken, nil
668	}
669	it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
670	it.pageInfo.MaxSize = int(req.PageSize)
671	return it
672}
673
674// ImportProductSets asynchronous API that imports a list of reference images to specified
675// product sets based on a list of image information.
676//
677// The [google.longrunning.Operation][google.longrunning.Operation] API can be
678// used to keep track of the progress and results of the request.
679// Operation.metadata contains BatchOperationMetadata. (progress)
680// Operation.response contains ImportProductSetsResponse. (results)
681//
682// The input source of this method is a csv file on Google Cloud Storage.
683// For the format of the csv file please see
684// [ImportProductSetsGcsSource.csv_file_uri][google.cloud.vision.v1.ImportProductSetsGcsSource.csv_file_uri].
685func (c *ProductSearchClient) ImportProductSets(ctx context.Context, req *visionpb.ImportProductSetsRequest, opts ...gax.CallOption) (*ImportProductSetsOperation, error) {
686	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
687	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
688	opts = append(c.CallOptions.ImportProductSets[0:len(c.CallOptions.ImportProductSets):len(c.CallOptions.ImportProductSets)], opts...)
689	var resp *longrunningpb.Operation
690	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
691		var err error
692		resp, err = c.productSearchClient.ImportProductSets(ctx, req, settings.GRPC...)
693		return err
694	}, opts...)
695	if err != nil {
696		return nil, err
697	}
698	return &ImportProductSetsOperation{
699		lro: longrunning.InternalNewOperation(c.LROClient, resp),
700	}, nil
701}
702
703// ProductIterator manages a stream of *visionpb.Product.
704type ProductIterator struct {
705	items    []*visionpb.Product
706	pageInfo *iterator.PageInfo
707	nextFunc func() error
708
709	// InternalFetch is for use by the Google Cloud Libraries only.
710	// It is not part of the stable interface of this package.
711	//
712	// InternalFetch returns results from a single call to the underlying RPC.
713	// The number of results is no greater than pageSize.
714	// If there are no more results, nextPageToken is empty and err is nil.
715	InternalFetch func(pageSize int, pageToken string) (results []*visionpb.Product, nextPageToken string, err error)
716}
717
718// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
719func (it *ProductIterator) PageInfo() *iterator.PageInfo {
720	return it.pageInfo
721}
722
723// Next returns the next result. Its second return value is iterator.Done if there are no more
724// results. Once Next returns Done, all subsequent calls will return Done.
725func (it *ProductIterator) Next() (*visionpb.Product, error) {
726	var item *visionpb.Product
727	if err := it.nextFunc(); err != nil {
728		return item, err
729	}
730	item = it.items[0]
731	it.items = it.items[1:]
732	return item, nil
733}
734
735func (it *ProductIterator) bufLen() int {
736	return len(it.items)
737}
738
739func (it *ProductIterator) takeBuf() interface{} {
740	b := it.items
741	it.items = nil
742	return b
743}
744
745// ProductSetIterator manages a stream of *visionpb.ProductSet.
746type ProductSetIterator struct {
747	items    []*visionpb.ProductSet
748	pageInfo *iterator.PageInfo
749	nextFunc func() error
750
751	// InternalFetch is for use by the Google Cloud Libraries only.
752	// It is not part of the stable interface of this package.
753	//
754	// InternalFetch returns results from a single call to the underlying RPC.
755	// The number of results is no greater than pageSize.
756	// If there are no more results, nextPageToken is empty and err is nil.
757	InternalFetch func(pageSize int, pageToken string) (results []*visionpb.ProductSet, nextPageToken string, err error)
758}
759
760// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
761func (it *ProductSetIterator) PageInfo() *iterator.PageInfo {
762	return it.pageInfo
763}
764
765// Next returns the next result. Its second return value is iterator.Done if there are no more
766// results. Once Next returns Done, all subsequent calls will return Done.
767func (it *ProductSetIterator) Next() (*visionpb.ProductSet, error) {
768	var item *visionpb.ProductSet
769	if err := it.nextFunc(); err != nil {
770		return item, err
771	}
772	item = it.items[0]
773	it.items = it.items[1:]
774	return item, nil
775}
776
777func (it *ProductSetIterator) bufLen() int {
778	return len(it.items)
779}
780
781func (it *ProductSetIterator) takeBuf() interface{} {
782	b := it.items
783	it.items = nil
784	return b
785}
786
787// ReferenceImageIterator manages a stream of *visionpb.ReferenceImage.
788type ReferenceImageIterator struct {
789	items    []*visionpb.ReferenceImage
790	pageInfo *iterator.PageInfo
791	nextFunc func() error
792
793	// InternalFetch is for use by the Google Cloud Libraries only.
794	// It is not part of the stable interface of this package.
795	//
796	// InternalFetch returns results from a single call to the underlying RPC.
797	// The number of results is no greater than pageSize.
798	// If there are no more results, nextPageToken is empty and err is nil.
799	InternalFetch func(pageSize int, pageToken string) (results []*visionpb.ReferenceImage, nextPageToken string, err error)
800}
801
802// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
803func (it *ReferenceImageIterator) PageInfo() *iterator.PageInfo {
804	return it.pageInfo
805}
806
807// Next returns the next result. Its second return value is iterator.Done if there are no more
808// results. Once Next returns Done, all subsequent calls will return Done.
809func (it *ReferenceImageIterator) Next() (*visionpb.ReferenceImage, error) {
810	var item *visionpb.ReferenceImage
811	if err := it.nextFunc(); err != nil {
812		return item, err
813	}
814	item = it.items[0]
815	it.items = it.items[1:]
816	return item, nil
817}
818
819func (it *ReferenceImageIterator) bufLen() int {
820	return len(it.items)
821}
822
823func (it *ReferenceImageIterator) takeBuf() interface{} {
824	b := it.items
825	it.items = nil
826	return b
827}
828
829// ImportProductSetsOperation manages a long-running operation from ImportProductSets.
830type ImportProductSetsOperation struct {
831	lro *longrunning.Operation
832}
833
834// ImportProductSetsOperation returns a new ImportProductSetsOperation from a given name.
835// The name must be that of a previously created ImportProductSetsOperation, possibly from a different process.
836func (c *ProductSearchClient) ImportProductSetsOperation(name string) *ImportProductSetsOperation {
837	return &ImportProductSetsOperation{
838		lro: longrunning.InternalNewOperation(c.LROClient, &longrunningpb.Operation{Name: name}),
839	}
840}
841
842// Wait blocks until the long-running operation is completed, returning the response and any errors encountered.
843//
844// See documentation of Poll for error-handling information.
845func (op *ImportProductSetsOperation) Wait(ctx context.Context, opts ...gax.CallOption) (*visionpb.ImportProductSetsResponse, error) {
846	var resp visionpb.ImportProductSetsResponse
847	if err := op.lro.WaitWithInterval(ctx, &resp, 45000*time.Millisecond, opts...); err != nil {
848		return nil, err
849	}
850	return &resp, nil
851}
852
853// Poll fetches the latest state of the long-running operation.
854//
855// Poll also fetches the latest metadata, which can be retrieved by Metadata.
856//
857// If Poll fails, the error is returned and op is unmodified. If Poll succeeds and
858// the operation has completed with failure, the error is returned and op.Done will return true.
859// If Poll succeeds and the operation has completed successfully,
860// op.Done will return true, and the response of the operation is returned.
861// If Poll succeeds and the operation has not completed, the returned response and error are both nil.
862func (op *ImportProductSetsOperation) Poll(ctx context.Context, opts ...gax.CallOption) (*visionpb.ImportProductSetsResponse, error) {
863	var resp visionpb.ImportProductSetsResponse
864	if err := op.lro.Poll(ctx, &resp, opts...); err != nil {
865		return nil, err
866	}
867	if !op.Done() {
868		return nil, nil
869	}
870	return &resp, nil
871}
872
873// Metadata returns metadata associated with the long-running operation.
874// Metadata itself does not contact the server, but Poll does.
875// To get the latest metadata, call this method after a successful call to Poll.
876// If the metadata is not available, the returned metadata and error are both nil.
877func (op *ImportProductSetsOperation) Metadata() (*visionpb.BatchOperationMetadata, error) {
878	var meta visionpb.BatchOperationMetadata
879	if err := op.lro.Metadata(&meta); err == longrunning.ErrNoMetadata {
880		return nil, nil
881	} else if err != nil {
882		return nil, err
883	}
884	return &meta, nil
885}
886
887// Done reports whether the long-running operation has completed.
888func (op *ImportProductSetsOperation) Done() bool {
889	return op.lro.Done()
890}
891
892// Name returns the name of the long-running operation.
893// The name is assigned by the server and is unique within the service from which the operation is created.
894func (op *ImportProductSetsOperation) Name() string {
895	return op.lro.Name()
896}
897