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	CreateProductSet            []gax.CallOption
42	ListProductSets             []gax.CallOption
43	GetProductSet               []gax.CallOption
44	UpdateProductSet            []gax.CallOption
45	DeleteProductSet            []gax.CallOption
46	CreateProduct               []gax.CallOption
47	ListProducts                []gax.CallOption
48	GetProduct                  []gax.CallOption
49	UpdateProduct               []gax.CallOption
50	DeleteProduct               []gax.CallOption
51	CreateReferenceImage        []gax.CallOption
52	DeleteReferenceImage        []gax.CallOption
53	ListReferenceImages         []gax.CallOption
54	GetReferenceImage           []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		CreateProductSet:            retry[[2]string{"default", "non_idempotent"}],
85		ListProductSets:             retry[[2]string{"default", "idempotent"}],
86		GetProductSet:               retry[[2]string{"default", "idempotent"}],
87		UpdateProductSet:            retry[[2]string{"default", "idempotent"}],
88		DeleteProductSet:            retry[[2]string{"default", "idempotent"}],
89		CreateProduct:               retry[[2]string{"default", "non_idempotent"}],
90		ListProducts:                retry[[2]string{"default", "idempotent"}],
91		GetProduct:                  retry[[2]string{"default", "idempotent"}],
92		UpdateProduct:               retry[[2]string{"default", "idempotent"}],
93		DeleteProduct:               retry[[2]string{"default", "idempotent"}],
94		CreateReferenceImage:        retry[[2]string{"default", "non_idempotent"}],
95		DeleteReferenceImage:        retry[[2]string{"default", "idempotent"}],
96		ListReferenceImages:         retry[[2]string{"default", "idempotent"}],
97		GetReferenceImage:           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// CreateProductSet creates and returns a new ProductSet resource.
192//
193// Possible errors:
194//
195//   Returns INVALID_ARGUMENT if display_name is missing, or is longer than
196//   4096 characters.
197func (c *ProductSearchClient) CreateProductSet(ctx context.Context, req *visionpb.CreateProductSetRequest, opts ...gax.CallOption) (*visionpb.ProductSet, error) {
198	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
199	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
200	opts = append(c.CallOptions.CreateProductSet[0:len(c.CallOptions.CreateProductSet):len(c.CallOptions.CreateProductSet)], opts...)
201	var resp *visionpb.ProductSet
202	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
203		var err error
204		resp, err = c.productSearchClient.CreateProductSet(ctx, req, settings.GRPC...)
205		return err
206	}, opts...)
207	if err != nil {
208		return nil, err
209	}
210	return resp, nil
211}
212
213// ListProductSets lists ProductSets in an unspecified order.
214//
215// Possible errors:
216//
217//   Returns INVALID_ARGUMENT if page_size is greater than 100, or less
218//   than 1.
219func (c *ProductSearchClient) ListProductSets(ctx context.Context, req *visionpb.ListProductSetsRequest, opts ...gax.CallOption) *ProductSetIterator {
220	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
221	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
222	opts = append(c.CallOptions.ListProductSets[0:len(c.CallOptions.ListProductSets):len(c.CallOptions.ListProductSets)], opts...)
223	it := &ProductSetIterator{}
224	req = proto.Clone(req).(*visionpb.ListProductSetsRequest)
225	it.InternalFetch = func(pageSize int, pageToken string) ([]*visionpb.ProductSet, string, error) {
226		var resp *visionpb.ListProductSetsResponse
227		req.PageToken = pageToken
228		if pageSize > math.MaxInt32 {
229			req.PageSize = math.MaxInt32
230		} else {
231			req.PageSize = int32(pageSize)
232		}
233		err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
234			var err error
235			resp, err = c.productSearchClient.ListProductSets(ctx, req, settings.GRPC...)
236			return err
237		}, opts...)
238		if err != nil {
239			return nil, "", err
240		}
241		return resp.ProductSets, resp.NextPageToken, nil
242	}
243	fetch := func(pageSize int, pageToken string) (string, error) {
244		items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
245		if err != nil {
246			return "", err
247		}
248		it.items = append(it.items, items...)
249		return nextPageToken, nil
250	}
251	it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
252	it.pageInfo.MaxSize = int(req.PageSize)
253	it.pageInfo.Token = req.PageToken
254	return it
255}
256
257// GetProductSet gets information associated with a ProductSet.
258//
259// Possible errors:
260//
261//   Returns NOT_FOUND if the ProductSet does not exist.
262func (c *ProductSearchClient) GetProductSet(ctx context.Context, req *visionpb.GetProductSetRequest, opts ...gax.CallOption) (*visionpb.ProductSet, error) {
263	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
264	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
265	opts = append(c.CallOptions.GetProductSet[0:len(c.CallOptions.GetProductSet):len(c.CallOptions.GetProductSet)], opts...)
266	var resp *visionpb.ProductSet
267	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
268		var err error
269		resp, err = c.productSearchClient.GetProductSet(ctx, req, settings.GRPC...)
270		return err
271	}, opts...)
272	if err != nil {
273		return nil, err
274	}
275	return resp, nil
276}
277
278// UpdateProductSet makes changes to a ProductSet resource.
279// Only display_name can be updated currently.
280//
281// Possible errors:
282//
283//   Returns NOT_FOUND if the ProductSet does not exist.
284//
285//   Returns INVALID_ARGUMENT if display_name is present in update_mask but
286//   missing from the request or longer than 4096 characters.
287func (c *ProductSearchClient) UpdateProductSet(ctx context.Context, req *visionpb.UpdateProductSetRequest, opts ...gax.CallOption) (*visionpb.ProductSet, error) {
288	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "product_set.name", req.GetProductSet().GetName()))
289	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
290	opts = append(c.CallOptions.UpdateProductSet[0:len(c.CallOptions.UpdateProductSet):len(c.CallOptions.UpdateProductSet)], opts...)
291	var resp *visionpb.ProductSet
292	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
293		var err error
294		resp, err = c.productSearchClient.UpdateProductSet(ctx, req, settings.GRPC...)
295		return err
296	}, opts...)
297	if err != nil {
298		return nil, err
299	}
300	return resp, nil
301}
302
303// DeleteProductSet permanently deletes a ProductSet. Products and ReferenceImages in the
304// ProductSet are not deleted.
305//
306// The actual image files are not deleted from Google Cloud Storage.
307func (c *ProductSearchClient) DeleteProductSet(ctx context.Context, req *visionpb.DeleteProductSetRequest, opts ...gax.CallOption) error {
308	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
309	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
310	opts = append(c.CallOptions.DeleteProductSet[0:len(c.CallOptions.DeleteProductSet):len(c.CallOptions.DeleteProductSet)], opts...)
311	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
312		var err error
313		_, err = c.productSearchClient.DeleteProductSet(ctx, req, settings.GRPC...)
314		return err
315	}, opts...)
316	return err
317}
318
319// CreateProduct creates and returns a new product resource.
320//
321// Possible errors:
322//
323//   Returns INVALID_ARGUMENT if display_name is missing or longer than 4096
324//   characters.
325//
326//   Returns INVALID_ARGUMENT if description is longer than 4096 characters.
327//
328//   Returns INVALID_ARGUMENT if product_category is missing or invalid.
329func (c *ProductSearchClient) CreateProduct(ctx context.Context, req *visionpb.CreateProductRequest, opts ...gax.CallOption) (*visionpb.Product, error) {
330	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
331	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
332	opts = append(c.CallOptions.CreateProduct[0:len(c.CallOptions.CreateProduct):len(c.CallOptions.CreateProduct)], opts...)
333	var resp *visionpb.Product
334	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
335		var err error
336		resp, err = c.productSearchClient.CreateProduct(ctx, req, settings.GRPC...)
337		return err
338	}, opts...)
339	if err != nil {
340		return nil, err
341	}
342	return resp, nil
343}
344
345// ListProducts lists products in an unspecified order.
346//
347// Possible errors:
348//
349//   Returns INVALID_ARGUMENT if page_size is greater than 100 or less than 1.
350func (c *ProductSearchClient) ListProducts(ctx context.Context, req *visionpb.ListProductsRequest, opts ...gax.CallOption) *ProductIterator {
351	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
352	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
353	opts = append(c.CallOptions.ListProducts[0:len(c.CallOptions.ListProducts):len(c.CallOptions.ListProducts)], opts...)
354	it := &ProductIterator{}
355	req = proto.Clone(req).(*visionpb.ListProductsRequest)
356	it.InternalFetch = func(pageSize int, pageToken string) ([]*visionpb.Product, string, error) {
357		var resp *visionpb.ListProductsResponse
358		req.PageToken = pageToken
359		if pageSize > math.MaxInt32 {
360			req.PageSize = math.MaxInt32
361		} else {
362			req.PageSize = int32(pageSize)
363		}
364		err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
365			var err error
366			resp, err = c.productSearchClient.ListProducts(ctx, req, settings.GRPC...)
367			return err
368		}, opts...)
369		if err != nil {
370			return nil, "", err
371		}
372		return resp.Products, resp.NextPageToken, nil
373	}
374	fetch := func(pageSize int, pageToken string) (string, error) {
375		items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
376		if err != nil {
377			return "", err
378		}
379		it.items = append(it.items, items...)
380		return nextPageToken, nil
381	}
382	it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
383	it.pageInfo.MaxSize = int(req.PageSize)
384	it.pageInfo.Token = req.PageToken
385	return it
386}
387
388// GetProduct gets information associated with a Product.
389//
390// Possible errors:
391//
392//   Returns NOT_FOUND if the Product does not exist.
393func (c *ProductSearchClient) GetProduct(ctx context.Context, req *visionpb.GetProductRequest, opts ...gax.CallOption) (*visionpb.Product, error) {
394	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
395	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
396	opts = append(c.CallOptions.GetProduct[0:len(c.CallOptions.GetProduct):len(c.CallOptions.GetProduct)], opts...)
397	var resp *visionpb.Product
398	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
399		var err error
400		resp, err = c.productSearchClient.GetProduct(ctx, req, settings.GRPC...)
401		return err
402	}, opts...)
403	if err != nil {
404		return nil, err
405	}
406	return resp, nil
407}
408
409// UpdateProduct makes changes to a Product resource.
410// Only the display_name, description, and labels fields can be updated
411// right now.
412//
413// If labels are updated, the change will not be reflected in queries until
414// the next index time.
415//
416// Possible errors:
417//
418//   Returns NOT_FOUND if the Product does not exist.
419//
420//   Returns INVALID_ARGUMENT if display_name is present in update_mask but is
421//   missing from the request or longer than 4096 characters.
422//
423//   Returns INVALID_ARGUMENT if description is present in update_mask but is
424//   longer than 4096 characters.
425//
426//   Returns INVALID_ARGUMENT if product_category is present in update_mask.
427func (c *ProductSearchClient) UpdateProduct(ctx context.Context, req *visionpb.UpdateProductRequest, opts ...gax.CallOption) (*visionpb.Product, error) {
428	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "product.name", req.GetProduct().GetName()))
429	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
430	opts = append(c.CallOptions.UpdateProduct[0:len(c.CallOptions.UpdateProduct):len(c.CallOptions.UpdateProduct)], opts...)
431	var resp *visionpb.Product
432	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
433		var err error
434		resp, err = c.productSearchClient.UpdateProduct(ctx, req, settings.GRPC...)
435		return err
436	}, opts...)
437	if err != nil {
438		return nil, err
439	}
440	return resp, nil
441}
442
443// DeleteProduct permanently deletes a product and its reference images.
444//
445// Metadata of the product and all its images will be deleted right away, but
446// search queries against ProductSets containing the product may still work
447// until all related caches are refreshed.
448func (c *ProductSearchClient) DeleteProduct(ctx context.Context, req *visionpb.DeleteProductRequest, opts ...gax.CallOption) error {
449	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
450	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
451	opts = append(c.CallOptions.DeleteProduct[0:len(c.CallOptions.DeleteProduct):len(c.CallOptions.DeleteProduct)], opts...)
452	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
453		var err error
454		_, err = c.productSearchClient.DeleteProduct(ctx, req, settings.GRPC...)
455		return err
456	}, opts...)
457	return err
458}
459
460// CreateReferenceImage creates and returns a new ReferenceImage resource.
461//
462// The bounding_poly field is optional. If bounding_poly is not specified,
463// the system will try to detect regions of interest in the image that are
464// compatible with the product_category on the parent product. If it is
465// specified, detection is ALWAYS skipped. The system converts polygons into
466// non-rotated rectangles.
467//
468// Note that the pipeline will resize the image if the image resolution is too
469// large to process (above 50MP).
470//
471// Possible errors:
472//
473//   Returns INVALID_ARGUMENT if the image_uri is missing or longer than 4096
474//   characters.
475//
476//   Returns INVALID_ARGUMENT if the product does not exist.
477//
478//   Returns INVALID_ARGUMENT if bounding_poly is not provided, and nothing
479//   compatible with the parent product's product_category is detected.
480//
481//   Returns INVALID_ARGUMENT if bounding_poly contains more than 10 polygons.
482func (c *ProductSearchClient) CreateReferenceImage(ctx context.Context, req *visionpb.CreateReferenceImageRequest, opts ...gax.CallOption) (*visionpb.ReferenceImage, error) {
483	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
484	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
485	opts = append(c.CallOptions.CreateReferenceImage[0:len(c.CallOptions.CreateReferenceImage):len(c.CallOptions.CreateReferenceImage)], opts...)
486	var resp *visionpb.ReferenceImage
487	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
488		var err error
489		resp, err = c.productSearchClient.CreateReferenceImage(ctx, req, settings.GRPC...)
490		return err
491	}, opts...)
492	if err != nil {
493		return nil, err
494	}
495	return resp, nil
496}
497
498// DeleteReferenceImage permanently deletes a reference image.
499//
500// The image metadata will be deleted right away, but search queries
501// against ProductSets containing the image may still work until all related
502// caches are refreshed.
503//
504// The actual image files are not deleted from Google Cloud Storage.
505func (c *ProductSearchClient) DeleteReferenceImage(ctx context.Context, req *visionpb.DeleteReferenceImageRequest, opts ...gax.CallOption) error {
506	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
507	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
508	opts = append(c.CallOptions.DeleteReferenceImage[0:len(c.CallOptions.DeleteReferenceImage):len(c.CallOptions.DeleteReferenceImage)], opts...)
509	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
510		var err error
511		_, err = c.productSearchClient.DeleteReferenceImage(ctx, req, settings.GRPC...)
512		return err
513	}, opts...)
514	return err
515}
516
517// ListReferenceImages lists reference images.
518//
519// Possible errors:
520//
521//   Returns NOT_FOUND if the parent product does not exist.
522//
523//   Returns INVALID_ARGUMENT if the page_size is greater than 100, or less
524//   than 1.
525func (c *ProductSearchClient) ListReferenceImages(ctx context.Context, req *visionpb.ListReferenceImagesRequest, opts ...gax.CallOption) *ReferenceImageIterator {
526	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
527	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
528	opts = append(c.CallOptions.ListReferenceImages[0:len(c.CallOptions.ListReferenceImages):len(c.CallOptions.ListReferenceImages)], opts...)
529	it := &ReferenceImageIterator{}
530	req = proto.Clone(req).(*visionpb.ListReferenceImagesRequest)
531	it.InternalFetch = func(pageSize int, pageToken string) ([]*visionpb.ReferenceImage, string, error) {
532		var resp *visionpb.ListReferenceImagesResponse
533		req.PageToken = pageToken
534		if pageSize > math.MaxInt32 {
535			req.PageSize = math.MaxInt32
536		} else {
537			req.PageSize = int32(pageSize)
538		}
539		err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
540			var err error
541			resp, err = c.productSearchClient.ListReferenceImages(ctx, req, settings.GRPC...)
542			return err
543		}, opts...)
544		if err != nil {
545			return nil, "", err
546		}
547		return resp.ReferenceImages, resp.NextPageToken, nil
548	}
549	fetch := func(pageSize int, pageToken string) (string, error) {
550		items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
551		if err != nil {
552			return "", err
553		}
554		it.items = append(it.items, items...)
555		return nextPageToken, nil
556	}
557	it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
558	it.pageInfo.MaxSize = int(req.PageSize)
559	it.pageInfo.Token = req.PageToken
560	return it
561}
562
563// GetReferenceImage gets information associated with a ReferenceImage.
564//
565// Possible errors:
566//
567//   Returns NOT_FOUND if the specified image does not exist.
568func (c *ProductSearchClient) GetReferenceImage(ctx context.Context, req *visionpb.GetReferenceImageRequest, opts ...gax.CallOption) (*visionpb.ReferenceImage, error) {
569	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
570	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
571	opts = append(c.CallOptions.GetReferenceImage[0:len(c.CallOptions.GetReferenceImage):len(c.CallOptions.GetReferenceImage)], opts...)
572	var resp *visionpb.ReferenceImage
573	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
574		var err error
575		resp, err = c.productSearchClient.GetReferenceImage(ctx, req, settings.GRPC...)
576		return err
577	}, opts...)
578	if err != nil {
579		return nil, err
580	}
581	return resp, nil
582}
583
584// AddProductToProductSet adds a Product to the specified ProductSet. If the Product is already
585// present, no change is made.
586//
587// One Product can be added to at most 100 ProductSets.
588//
589// Possible errors:
590//
591//   Returns NOT_FOUND if the Product or the ProductSet doesn't exist.
592func (c *ProductSearchClient) AddProductToProductSet(ctx context.Context, req *visionpb.AddProductToProductSetRequest, opts ...gax.CallOption) error {
593	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
594	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
595	opts = append(c.CallOptions.AddProductToProductSet[0:len(c.CallOptions.AddProductToProductSet):len(c.CallOptions.AddProductToProductSet)], opts...)
596	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
597		var err error
598		_, err = c.productSearchClient.AddProductToProductSet(ctx, req, settings.GRPC...)
599		return err
600	}, opts...)
601	return err
602}
603
604// RemoveProductFromProductSet removes a Product from the specified ProductSet.
605func (c *ProductSearchClient) RemoveProductFromProductSet(ctx context.Context, req *visionpb.RemoveProductFromProductSetRequest, opts ...gax.CallOption) error {
606	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
607	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
608	opts = append(c.CallOptions.RemoveProductFromProductSet[0:len(c.CallOptions.RemoveProductFromProductSet):len(c.CallOptions.RemoveProductFromProductSet)], opts...)
609	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
610		var err error
611		_, err = c.productSearchClient.RemoveProductFromProductSet(ctx, req, settings.GRPC...)
612		return err
613	}, opts...)
614	return err
615}
616
617// ListProductsInProductSet lists the Products in a ProductSet, in an unspecified order. If the
618// ProductSet does not exist, the products field of the response will be
619// empty.
620//
621// Possible errors:
622//
623//   Returns INVALID_ARGUMENT if page_size is greater than 100 or less than 1.
624func (c *ProductSearchClient) ListProductsInProductSet(ctx context.Context, req *visionpb.ListProductsInProductSetRequest, opts ...gax.CallOption) *ProductIterator {
625	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
626	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
627	opts = append(c.CallOptions.ListProductsInProductSet[0:len(c.CallOptions.ListProductsInProductSet):len(c.CallOptions.ListProductsInProductSet)], opts...)
628	it := &ProductIterator{}
629	req = proto.Clone(req).(*visionpb.ListProductsInProductSetRequest)
630	it.InternalFetch = func(pageSize int, pageToken string) ([]*visionpb.Product, string, error) {
631		var resp *visionpb.ListProductsInProductSetResponse
632		req.PageToken = pageToken
633		if pageSize > math.MaxInt32 {
634			req.PageSize = math.MaxInt32
635		} else {
636			req.PageSize = int32(pageSize)
637		}
638		err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
639			var err error
640			resp, err = c.productSearchClient.ListProductsInProductSet(ctx, req, settings.GRPC...)
641			return err
642		}, opts...)
643		if err != nil {
644			return nil, "", err
645		}
646		return resp.Products, resp.NextPageToken, nil
647	}
648	fetch := func(pageSize int, pageToken string) (string, error) {
649		items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
650		if err != nil {
651			return "", err
652		}
653		it.items = append(it.items, items...)
654		return nextPageToken, nil
655	}
656	it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
657	it.pageInfo.MaxSize = int(req.PageSize)
658	it.pageInfo.Token = req.PageToken
659	return it
660}
661
662// ImportProductSets asynchronous API that imports a list of reference images to specified
663// product sets based on a list of image information.
664//
665// The [google.longrunning.Operation][google.longrunning.Operation] API can be
666// used to keep track of the progress and results of the request.
667// Operation.metadata contains BatchOperationMetadata. (progress)
668// Operation.response contains ImportProductSetsResponse. (results)
669//
670// The input source of this method is a csv file on Google Cloud Storage.
671// For the format of the csv file please see
672// [ImportProductSetsGcsSource.csv_file_uri][google.cloud.vision.v1.ImportProductSetsGcsSource.csv_file_uri].
673func (c *ProductSearchClient) ImportProductSets(ctx context.Context, req *visionpb.ImportProductSetsRequest, opts ...gax.CallOption) (*ImportProductSetsOperation, error) {
674	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
675	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
676	opts = append(c.CallOptions.ImportProductSets[0:len(c.CallOptions.ImportProductSets):len(c.CallOptions.ImportProductSets)], opts...)
677	var resp *longrunningpb.Operation
678	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
679		var err error
680		resp, err = c.productSearchClient.ImportProductSets(ctx, req, settings.GRPC...)
681		return err
682	}, opts...)
683	if err != nil {
684		return nil, err
685	}
686	return &ImportProductSetsOperation{
687		lro: longrunning.InternalNewOperation(c.LROClient, resp),
688	}, nil
689}
690
691// ProductIterator manages a stream of *visionpb.Product.
692type ProductIterator struct {
693	items    []*visionpb.Product
694	pageInfo *iterator.PageInfo
695	nextFunc func() error
696
697	// InternalFetch is for use by the Google Cloud Libraries only.
698	// It is not part of the stable interface of this package.
699	//
700	// InternalFetch returns results from a single call to the underlying RPC.
701	// The number of results is no greater than pageSize.
702	// If there are no more results, nextPageToken is empty and err is nil.
703	InternalFetch func(pageSize int, pageToken string) (results []*visionpb.Product, nextPageToken string, err error)
704}
705
706// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
707func (it *ProductIterator) PageInfo() *iterator.PageInfo {
708	return it.pageInfo
709}
710
711// Next returns the next result. Its second return value is iterator.Done if there are no more
712// results. Once Next returns Done, all subsequent calls will return Done.
713func (it *ProductIterator) Next() (*visionpb.Product, error) {
714	var item *visionpb.Product
715	if err := it.nextFunc(); err != nil {
716		return item, err
717	}
718	item = it.items[0]
719	it.items = it.items[1:]
720	return item, nil
721}
722
723func (it *ProductIterator) bufLen() int {
724	return len(it.items)
725}
726
727func (it *ProductIterator) takeBuf() interface{} {
728	b := it.items
729	it.items = nil
730	return b
731}
732
733// ProductSetIterator manages a stream of *visionpb.ProductSet.
734type ProductSetIterator struct {
735	items    []*visionpb.ProductSet
736	pageInfo *iterator.PageInfo
737	nextFunc func() error
738
739	// InternalFetch is for use by the Google Cloud Libraries only.
740	// It is not part of the stable interface of this package.
741	//
742	// InternalFetch returns results from a single call to the underlying RPC.
743	// The number of results is no greater than pageSize.
744	// If there are no more results, nextPageToken is empty and err is nil.
745	InternalFetch func(pageSize int, pageToken string) (results []*visionpb.ProductSet, nextPageToken string, err error)
746}
747
748// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
749func (it *ProductSetIterator) PageInfo() *iterator.PageInfo {
750	return it.pageInfo
751}
752
753// Next returns the next result. Its second return value is iterator.Done if there are no more
754// results. Once Next returns Done, all subsequent calls will return Done.
755func (it *ProductSetIterator) Next() (*visionpb.ProductSet, error) {
756	var item *visionpb.ProductSet
757	if err := it.nextFunc(); err != nil {
758		return item, err
759	}
760	item = it.items[0]
761	it.items = it.items[1:]
762	return item, nil
763}
764
765func (it *ProductSetIterator) bufLen() int {
766	return len(it.items)
767}
768
769func (it *ProductSetIterator) takeBuf() interface{} {
770	b := it.items
771	it.items = nil
772	return b
773}
774
775// ReferenceImageIterator manages a stream of *visionpb.ReferenceImage.
776type ReferenceImageIterator struct {
777	items    []*visionpb.ReferenceImage
778	pageInfo *iterator.PageInfo
779	nextFunc func() error
780
781	// InternalFetch is for use by the Google Cloud Libraries only.
782	// It is not part of the stable interface of this package.
783	//
784	// InternalFetch returns results from a single call to the underlying RPC.
785	// The number of results is no greater than pageSize.
786	// If there are no more results, nextPageToken is empty and err is nil.
787	InternalFetch func(pageSize int, pageToken string) (results []*visionpb.ReferenceImage, nextPageToken string, err error)
788}
789
790// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
791func (it *ReferenceImageIterator) PageInfo() *iterator.PageInfo {
792	return it.pageInfo
793}
794
795// Next returns the next result. Its second return value is iterator.Done if there are no more
796// results. Once Next returns Done, all subsequent calls will return Done.
797func (it *ReferenceImageIterator) Next() (*visionpb.ReferenceImage, error) {
798	var item *visionpb.ReferenceImage
799	if err := it.nextFunc(); err != nil {
800		return item, err
801	}
802	item = it.items[0]
803	it.items = it.items[1:]
804	return item, nil
805}
806
807func (it *ReferenceImageIterator) bufLen() int {
808	return len(it.items)
809}
810
811func (it *ReferenceImageIterator) takeBuf() interface{} {
812	b := it.items
813	it.items = nil
814	return b
815}
816
817// ImportProductSetsOperation manages a long-running operation from ImportProductSets.
818type ImportProductSetsOperation struct {
819	lro *longrunning.Operation
820}
821
822// ImportProductSetsOperation returns a new ImportProductSetsOperation from a given name.
823// The name must be that of a previously created ImportProductSetsOperation, possibly from a different process.
824func (c *ProductSearchClient) ImportProductSetsOperation(name string) *ImportProductSetsOperation {
825	return &ImportProductSetsOperation{
826		lro: longrunning.InternalNewOperation(c.LROClient, &longrunningpb.Operation{Name: name}),
827	}
828}
829
830// Wait blocks until the long-running operation is completed, returning the response and any errors encountered.
831//
832// See documentation of Poll for error-handling information.
833func (op *ImportProductSetsOperation) Wait(ctx context.Context, opts ...gax.CallOption) (*visionpb.ImportProductSetsResponse, error) {
834	var resp visionpb.ImportProductSetsResponse
835	if err := op.lro.WaitWithInterval(ctx, &resp, 45000*time.Millisecond, opts...); err != nil {
836		return nil, err
837	}
838	return &resp, nil
839}
840
841// Poll fetches the latest state of the long-running operation.
842//
843// Poll also fetches the latest metadata, which can be retrieved by Metadata.
844//
845// If Poll fails, the error is returned and op is unmodified. If Poll succeeds and
846// the operation has completed with failure, the error is returned and op.Done will return true.
847// If Poll succeeds and the operation has completed successfully,
848// op.Done will return true, and the response of the operation is returned.
849// If Poll succeeds and the operation has not completed, the returned response and error are both nil.
850func (op *ImportProductSetsOperation) Poll(ctx context.Context, opts ...gax.CallOption) (*visionpb.ImportProductSetsResponse, error) {
851	var resp visionpb.ImportProductSetsResponse
852	if err := op.lro.Poll(ctx, &resp, opts...); err != nil {
853		return nil, err
854	}
855	if !op.Done() {
856		return nil, nil
857	}
858	return &resp, nil
859}
860
861// Metadata returns metadata associated with the long-running operation.
862// Metadata itself does not contact the server, but Poll does.
863// To get the latest metadata, call this method after a successful call to Poll.
864// If the metadata is not available, the returned metadata and error are both nil.
865func (op *ImportProductSetsOperation) Metadata() (*visionpb.BatchOperationMetadata, error) {
866	var meta visionpb.BatchOperationMetadata
867	if err := op.lro.Metadata(&meta); err == longrunning.ErrNoMetadata {
868		return nil, nil
869	} else if err != nil {
870		return nil, err
871	}
872	return &meta, nil
873}
874
875// Done reports whether the long-running operation has completed.
876func (op *ImportProductSetsOperation) Done() bool {
877	return op.lro.Done()
878}
879
880// Name returns the name of the long-running operation.
881// The name is assigned by the server and is unique within the service from which the operation is created.
882func (op *ImportProductSetsOperation) Name() string {
883	return op.lro.Name()
884}
885